diff options
Diffstat (limited to 'include/clang')
251 files changed, 15225 insertions, 7200 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 703f588c5663..a5d080035df0 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1,4 +1,4 @@ -//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- C++ -*-===// +//===- ASTContext.h - Context to hold long-lived AST nodes ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::ASTContext interface. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_ASTCONTEXT_H @@ -19,8 +19,8 @@ #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" @@ -30,32 +30,32 @@ #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Linkage.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/Module.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SanitizerBlacklist.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/XRayLists.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" @@ -65,7 +65,6 @@ #include <cstdint> #include <iterator> #include <memory> -#include <new> #include <string> #include <type_traits> #include <utility> @@ -75,50 +74,72 @@ namespace llvm { struct fltSemantics; -} // end namespace llvm +} // namespace llvm namespace clang { +class APValue; class ASTMutationListener; class ASTRecordLayout; class AtomicExpr; class BlockExpr; +class BuiltinTemplateDecl; class CharUnits; class CXXABI; +class CXXConstructorDecl; +class CXXMethodDecl; +class CXXRecordDecl; class DiagnosticsEngine; class Expr; +class MangleContext; class MangleNumberingContext; class MaterializeTemporaryExpr; -class TargetInfo; -// Decls -class MangleContext; +class MemberSpecializationInfo; +class Module; +class ObjCCategoryDecl; +class ObjCCategoryImplDecl; +class ObjCContainerDecl; +class ObjCImplDecl; +class ObjCImplementationDecl; +class ObjCInterfaceDecl; class ObjCIvarDecl; +class ObjCMethodDecl; class ObjCPropertyDecl; +class ObjCPropertyImplDecl; +class ObjCProtocolDecl; +class ObjCTypeParamDecl; +class Preprocessor; +class Stmt; +class StoredDeclsMap; +class TemplateDecl; +class TemplateParameterList; +class TemplateTemplateParmDecl; +class TemplateTypeParmDecl; class UnresolvedSetIterator; -class UsingDecl; class UsingShadowDecl; +class VarTemplateDecl; class VTableContextBase; namespace Builtin { - class Context; +class Context; -} // end namespace Builtin +} // namespace Builtin enum BuiltinTemplateKind : int; namespace comments { - class FullComment; +class FullComment; -} // end namespace comments +} // namespace comments struct TypeInfo { - uint64_t Width; - unsigned Align; + uint64_t Width = 0; + unsigned Align = 0; bool AlignIsRequired : 1; - TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {} + TypeInfo() : AlignIsRequired(false) {} TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired) : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {} }; @@ -126,7 +147,7 @@ struct TypeInfo { /// \brief Holds long-lived AST nodes (such as types and decls) that can be /// referred to throughout the semantic analysis of a file. class ASTContext : public RefCountedBase<ASTContext> { - ASTContext &this_() { return *this; } + friend class NestedNameSpecifier; mutable SmallVector<Type *, 0> Types; mutable llvm::FoldingSet<ExtQuals> ExtQualNodes; @@ -143,6 +164,8 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; mutable llvm::FoldingSet<DependentSizedExtVectorType> DependentSizedExtVectorTypes; + mutable llvm::FoldingSet<DependentAddressSpaceType> + DependentAddressSpaceTypes; mutable llvm::FoldingSet<VectorType> VectorTypes; mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&> @@ -187,8 +210,7 @@ class ASTContext : public RefCountedBase<ASTContext> { /// /// This set is managed by the NestedNameSpecifier class. mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers; - mutable NestedNameSpecifier *GlobalNestedNameSpecifier; - friend class NestedNameSpecifier; + mutable NestedNameSpecifier *GlobalNestedNameSpecifier = nullptr; /// \brief A cache mapping from RecordDecls to ASTRecordLayouts. /// @@ -199,7 +221,7 @@ class ASTContext : public RefCountedBase<ASTContext> { ObjCLayouts; /// \brief A cache from types to size and alignment information. - typedef llvm::DenseMap<const Type *, struct TypeInfo> TypeInfoMap; + using TypeInfoMap = llvm::DenseMap<const Type *, struct TypeInfo>; mutable TypeInfoMap MemoizedTypeInfo; /// \brief A cache mapping from CXXRecordDecls to key functions. @@ -233,7 +255,7 @@ class ASTContext : public RefCountedBase<ASTContext> { public: CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm) - : Parm(Parm) { } + : Parm(Parm) {} TemplateTemplateParmDecl *getParam() const { return Parm; } @@ -249,32 +271,32 @@ class ASTContext : public RefCountedBase<ASTContext> { getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const; /// \brief The typedef for the __int128_t type. - mutable TypedefDecl *Int128Decl; + mutable TypedefDecl *Int128Decl = nullptr; /// \brief The typedef for the __uint128_t type. - mutable TypedefDecl *UInt128Decl; + mutable TypedefDecl *UInt128Decl = nullptr; /// \brief The typedef for the target specific predefined /// __builtin_va_list type. - mutable TypedefDecl *BuiltinVaListDecl; + mutable TypedefDecl *BuiltinVaListDecl = nullptr; /// The typedef for the predefined \c __builtin_ms_va_list type. - mutable TypedefDecl *BuiltinMSVaListDecl; + mutable TypedefDecl *BuiltinMSVaListDecl = nullptr; /// \brief The typedef for the predefined \c id type. - mutable TypedefDecl *ObjCIdDecl; + mutable TypedefDecl *ObjCIdDecl = nullptr; /// \brief The typedef for the predefined \c SEL type. - mutable TypedefDecl *ObjCSelDecl; + mutable TypedefDecl *ObjCSelDecl = nullptr; /// \brief The typedef for the predefined \c Class type. - mutable TypedefDecl *ObjCClassDecl; + mutable TypedefDecl *ObjCClassDecl = nullptr; /// \brief The typedef for the predefined \c Protocol class in Objective-C. - mutable ObjCInterfaceDecl *ObjCProtocolClassDecl; + mutable ObjCInterfaceDecl *ObjCProtocolClassDecl = nullptr; /// \brief The typedef for the predefined 'BOOL' type. - mutable TypedefDecl *BOOLDecl; + mutable TypedefDecl *BOOLDecl = nullptr; // Typedefs which may be provided defining the structure of Objective-C // pseudo-builtins @@ -298,42 +320,42 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable IdentifierInfo *TypePackElementName = nullptr; QualType ObjCConstantStringType; - mutable RecordDecl *CFConstantStringTagDecl; - mutable TypedefDecl *CFConstantStringTypeDecl; + mutable RecordDecl *CFConstantStringTagDecl = nullptr; + mutable TypedefDecl *CFConstantStringTypeDecl = nullptr; mutable QualType ObjCSuperType; QualType ObjCNSStringType; /// \brief The typedef declaration for the Objective-C "instancetype" type. - TypedefDecl *ObjCInstanceTypeDecl; + TypedefDecl *ObjCInstanceTypeDecl = nullptr; /// \brief The type for the C FILE type. - TypeDecl *FILEDecl; + TypeDecl *FILEDecl = nullptr; /// \brief The type for the C jmp_buf type. - TypeDecl *jmp_bufDecl; + TypeDecl *jmp_bufDecl = nullptr; /// \brief The type for the C sigjmp_buf type. - TypeDecl *sigjmp_bufDecl; + TypeDecl *sigjmp_bufDecl = nullptr; /// \brief The type for the C ucontext_t type. - TypeDecl *ucontext_tDecl; + TypeDecl *ucontext_tDecl = nullptr; /// \brief 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; + mutable RecordDecl *BlockDescriptorType = nullptr; /// \brief 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; + mutable RecordDecl *BlockDescriptorExtendedType = nullptr; /// \brief Declaration for the CUDA cudaConfigureCall function. - FunctionDecl *cudaConfigureCallDecl; + FunctionDecl *cudaConfigureCallDecl = nullptr; /// \brief Keeps track of all declaration attributes. /// @@ -363,12 +385,19 @@ class ASTContext : public RefCountedBase<ASTContext> { }; llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers; + ASTContext &this_() { return *this; } + public: /// \brief A type synonym for the TemplateOrInstantiation mapping. - typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *> - TemplateOrSpecializationInfo; + using TemplateOrSpecializationInfo = + llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>; private: + friend class ASTDeclReader; + friend class ASTReader; + friend class ASTWriter; + friend class CXXRecordDecl; + /// \brief A mapping to contain the template or declaration that /// a variable declaration describes or was instantiated from, /// respectively. @@ -438,7 +467,7 @@ private: /// Since most C++ member functions aren't virtual and therefore /// don't override anything, we store the overridden functions in /// this map on the side rather than within the CXXMethodDecl structure. - typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector; + using CXXMethodVector = llvm::TinyPtrVector<const CXXMethodDecl *>; llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; /// \brief Mapping from each declaration context to its corresponding @@ -454,18 +483,18 @@ private: /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. - typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable; + using ParameterIndexTable = llvm::DenseMap<const VarDecl *, unsigned>; ParameterIndexTable ParamIndices; - ImportDecl *FirstLocalImport; - ImportDecl *LastLocalImport; + ImportDecl *FirstLocalImport = nullptr; + ImportDecl *LastLocalImport = nullptr; TranslationUnitDecl *TUDecl; - mutable ExternCContextDecl *ExternCContext; - mutable BuiltinTemplateDecl *MakeIntegerSeqDecl; - mutable BuiltinTemplateDecl *TypePackElementDecl; + mutable ExternCContextDecl *ExternCContext = nullptr; + mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr; + mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr; - /// \brief The associated SourceManager object.a + /// \brief The associated SourceManager object. SourceManager &SourceMgr; /// \brief The language options used to create the AST associated with @@ -494,19 +523,14 @@ private: CXXABI *createCXXABI(const TargetInfo &T); /// \brief The logical -> physical address space map. - const LangAS::Map *AddrSpaceMap; + const LangASMap *AddrSpaceMap = nullptr; /// \brief Address space map mangling must be used with language specific /// address spaces (e.g. OpenCL/CUDA) bool AddrSpaceMapMangling; - friend class ASTDeclReader; - friend class ASTReader; - friend class ASTWriter; - friend class CXXRecordDecl; - - const TargetInfo *Target; - const TargetInfo *AuxTarget; + const TargetInfo *Target = nullptr; + const TargetInfo *AuxTarget = nullptr; clang::PrintingPolicy PrintingPolicy; public: @@ -515,31 +539,33 @@ public: Builtin::Context &BuiltinInfo; mutable DeclarationNameTable DeclarationNames; IntrusiveRefCntPtr<ExternalASTSource> ExternalSource; - ASTMutationListener *Listener; + ASTMutationListener *Listener = nullptr; /// \brief Contains parents of a node. - typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector; + using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>; /// \brief 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. - typedef llvm::DenseMap<const void *, - llvm::PointerUnion4<const Decl *, const Stmt *, - ast_type_traits::DynTypedNode *, - ParentVector *>> ParentMapPointers; + using ParentMapPointers = + llvm::DenseMap<const void *, + llvm::PointerUnion4<const Decl *, const Stmt *, + ast_type_traits::DynTypedNode *, + ParentVector *>>; /// Parent map for nodes without pointer identity. We store a full /// DynTypedNode for all keys. - typedef llvm::DenseMap< - ast_type_traits::DynTypedNode, - llvm::PointerUnion4<const Decl *, const Stmt *, - ast_type_traits::DynTypedNode *, ParentVector *>> - ParentMapOtherNodes; + using ParentMapOtherNodes = + llvm::DenseMap<ast_type_traits::DynTypedNode, + llvm::PointerUnion4<const Decl *, const Stmt *, + ast_type_traits::DynTypedNode *, + ParentVector *>>; /// Container for either a single DynTypedNode or for an ArrayRef to /// DynTypedNode. For use with ParentMap. class DynTypedNodeList { - typedef ast_type_traits::DynTypedNode DynTypedNode; + using DynTypedNode = ast_type_traits::DynTypedNode; + llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode, ArrayRef<DynTypedNode>> Storage; bool IsSingleNode; @@ -548,6 +574,7 @@ public: DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { new (Storage.buffer) DynTypedNode(N); } + DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) { new (Storage.buffer) ArrayRef<DynTypedNode>(A); } @@ -626,13 +653,14 @@ public: template <typename T> T *Allocate(size_t Num = 1) const { return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T))); } - void Deallocate(void *Ptr) const { } + void Deallocate(void *Ptr) const {} /// Return the total amount of physical memory allocated for representing /// AST nodes and type information. size_t getASTAllocatedMemory() const { return BumpAlloc.getTotalMemory(); } + /// Return the total memory used for various side tables. size_t getSideTableAllocatedMemory() const; @@ -649,6 +677,7 @@ public: /// Returns empty type if there is no appropriate target types. QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const; + /// getRealTypeForBitwidth - /// sets floating point QualTy according to specified bitwidth. /// Returns empty type if there is no appropriate target types. @@ -676,7 +705,7 @@ public: RawCommentList Comments; /// \brief True if comments are already loaded from ExternalASTSource. - mutable bool CommentsLoaded; + mutable bool CommentsLoaded = false; class RawCommentAndCacheFlags { public: @@ -759,24 +788,24 @@ public: } /// \brief Return the documentation comment attached to a given declaration. - /// Returns NULL if no comment is attached. + /// Returns nullptr if no comment is attached. /// - /// \param OriginalDecl if not NULL, is set to declaration AST node that had - /// the comment, if the comment we found comes from a redeclaration. + /// \param OriginalDecl if not nullptr, is set to declaration AST node that + /// had the comment, if the comment we found comes from a redeclaration. const RawComment * getRawCommentForAnyRedecl(const Decl *D, const Decl **OriginalDecl = nullptr) const; /// Return parsed documentation comment attached to a given declaration. - /// Returns NULL if no comment is attached. + /// Returns nullptr if no comment is attached. /// - /// \param PP the Preprocessor used with this TU. Could be NULL if + /// \param PP the Preprocessor used with this TU. Could be nullptr if /// preprocessor is not available. comments::FullComment *getCommentForDecl(const Decl *D, const Preprocessor *PP) const; /// Return parsed documentation comment attached to a given declaration. - /// Returns NULL if no comment is attached. Does not look at any + /// Returns nullptr if no comment is attached. Does not look at any /// redeclarations of the declaration. comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const; @@ -788,16 +817,16 @@ private: /// \brief Iterator that visits import declarations. class import_iterator { - ImportDecl *Import; + ImportDecl *Import = nullptr; public: - typedef ImportDecl *value_type; - typedef ImportDecl *reference; - typedef ImportDecl *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; + using value_type = ImportDecl *; + using reference = ImportDecl *; + using pointer = ImportDecl *; + using difference_type = int; + using iterator_category = std::forward_iterator_tag; - import_iterator() : Import() {} + import_iterator() = default; explicit import_iterator(ImportDecl *Import) : Import(Import) {} reference operator*() const { return Import; } @@ -876,7 +905,7 @@ public: void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); // Access to the set of methods overridden by the given C++ method. - typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator; + using overridden_cxx_method_iterator = CXXMethodVector::const_iterator; overridden_cxx_method_iterator overridden_methods_begin(const CXXMethodDecl *Method) const; @@ -884,8 +913,10 @@ public: overridden_methods_end(const CXXMethodDecl *Method) const; unsigned overridden_methods_size(const CXXMethodDecl *Method) const; - typedef llvm::iterator_range<overridden_cxx_method_iterator> - overridden_method_range; + + using overridden_method_range = + llvm::iterator_range<overridden_cxx_method_iterator>; + overridden_method_range overridden_methods(const CXXMethodDecl *Method) const; /// \brief Note that the given C++ \p Method overrides the given \p @@ -912,7 +943,8 @@ public: return Import->NextLocalImport; } - typedef llvm::iterator_range<import_iterator> import_range; + using import_range = llvm::iterator_range<import_iterator>; + import_range local_imports() const { return import_range(import_iterator(FirstLocalImport), import_iterator()); } @@ -929,6 +961,7 @@ public: /// 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 /// added duplicates into the list. void deduplicateMergedDefinitonsFor(NamedDecl *ND); @@ -973,6 +1006,7 @@ public: CanQualType UnsignedLongLongTy, UnsignedInt128Ty; CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON + CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType Float128ComplexTy; CanQualType VoidPtrTy, NullPtrTy; @@ -1067,7 +1101,14 @@ public: /// The resulting type has a union of the qualifiers from T and the address /// space. If T already has an address space specifier, it is silently /// replaced. - QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const; + QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const; + + /// \brief 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. /// \param allowOnPointerType specifies if we can apply protocol @@ -1175,6 +1216,7 @@ public: /// \brief 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. QualType getWritePipeType(QualType T) const; @@ -1182,9 +1224,16 @@ public: /// pointer to blocks. QualType getBlockDescriptorExtendedType() const; + /// Map an AST Type to an OpenCLTypeKind enum value. + TargetInfo::OpenCLTypeKind getOpenCLTypeKind(const Type *T) const; + + /// Get address space for OpenCL type. + LangAS getOpenCLTypeAddrSpace(const Type *T) const; + void setcudaConfigureCallDecl(FunctionDecl *FD) { cudaConfigureCallDecl = FD; } + FunctionDecl *getcudaConfigureCallDecl() { return cudaConfigureCallDecl; } @@ -1192,7 +1241,6 @@ 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. @@ -1269,6 +1317,10 @@ public: Expr *SizeExpr, SourceLocation AttrLoc) const; + QualType getDependentAddressSpaceType(QualType PointeeType, + Expr *AddrSpaceExpr, + SourceLocation AttrLoc) const; + /// \brief Return a K&R style C function type like 'int()'. QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const; @@ -1396,6 +1448,7 @@ public: QualType Canonical = QualType()) const; bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); + /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in /// QT's qualified-id protocol list adopt all protocols in IDecl's list /// of protocols. @@ -1426,7 +1479,7 @@ public: /// \brief C++11 deduction pattern for 'auto &&' type. QualType getAutoRRefDeductType() const; - /// \brief C++1z deduced class template specialization type. + /// \brief C++17 deduced class template specialization type. QualType getDeducedTemplateSpecializationType(TemplateName Template, QualType DeducedType, bool IsDependent) const; @@ -1488,6 +1541,11 @@ public: /// <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; + /// \brief 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 /// <sys/types.h>. We need this to compute the correct type for vfork(). QualType getProcessIDType() const; @@ -1581,6 +1639,24 @@ public: return NSCopyingName; } + CanQualType getNSUIntegerType() const { + assert(Target && "Expected target to be initialized"); + const llvm::Triple &T = Target->getTriple(); + // Windows is LLP64 rather than LP64 + if (T.isOSWindows() && T.isArch64Bit()) + return UnsignedLongLongTy; + return UnsignedLongTy; + } + + CanQualType getNSIntegerType() const { + assert(Target && "Expected target to be initialized"); + const llvm::Triple &T = Target->getTriple(); + // Windows is LLP64 rather than LP64 + if (T.isOSWindows() && T.isArch64Bit()) + return LongLongTy; + return LongTy; + } + /// Retrieve the identifier 'bool'. IdentifierInfo *getBoolName() const { if (!BoolName) @@ -1865,10 +1941,17 @@ public: const TemplateArgument &ArgPack) const; enum GetBuiltinTypeError { - GE_None, ///< No error - GE_Missing_stdio, ///< Missing a type from <stdio.h> - GE_Missing_setjmp, ///< Missing a type from <setjmp.h> - GE_Missing_ucontext ///< Missing a type from <ucontext.h> + /// No error + GE_None, + + /// Missing a type from <stdio.h> + GE_Missing_stdio, + + /// Missing a type from <setjmp.h> + GE_Missing_setjmp, + + /// Missing a type from <ucontext.h> + GE_Missing_ucontext }; /// \brief Return the type for the specified builtin. @@ -2019,7 +2102,7 @@ public: getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const; /// \brief Get our current best idea for the key function of the - /// given record decl, or NULL if there isn't one. + /// given record decl, or nullptr if there isn't one. /// /// The key function is, according to the Itanium C++ ABI section 5.2.3: /// ...the first non-pure virtual function that is not inline at the @@ -2072,6 +2155,10 @@ public: void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); + /// \brief Return true if the specified type has unique object representations + /// according to (C++17 [meta.unary.prop]p9) + bool hasUniqueObjectRepresentations(QualType Ty) const; + //===--------------------------------------------------------------------===// // Type Operators //===--------------------------------------------------------------------===// @@ -2103,7 +2190,6 @@ public: bool hasSameType(QualType T1, QualType T2) const { return getCanonicalType(T1) == getCanonicalType(T2); } - bool hasSameType(const Type *T1, const Type *T2) const { return getCanonicalType(T1) == getCanonicalType(T2); } @@ -2192,7 +2278,7 @@ public: getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const; /// \brief Retrieves the default calling convention for the current target. - CallingConv getDefaultCallingConvention(bool isVariadic, + CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod) const; /// \brief Retrieves the "canonical" template name that refers to a @@ -2326,14 +2412,14 @@ public: return getTargetAddressSpace(Q.getAddressSpace()); } - unsigned getTargetAddressSpace(unsigned AS) const; + unsigned getTargetAddressSpace(LangAS AS) const; /// Get target-dependent integer value for null pointer which is used for /// constant folding. uint64_t getTargetNullPointerValue(QualType QT) const; - bool addressSpaceMapManglingFor(unsigned AS) const { - return AddrSpaceMapMangling || AS >= LangAS::FirstTargetAddressSpace; + bool addressSpaceMapManglingFor(LangAS AS) const { + return AddrSpaceMapMangling || isTargetAddressSpace(AS); } private: @@ -2355,12 +2441,15 @@ public: bool isObjCIdType(QualType T) const { return T == getObjCIdType(); } + bool isObjCClassType(QualType T) const { return T == getObjCClassType(); } + bool isObjCSelType(QualType T) const { return T == getObjCSelType(); } + bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, bool ForCompare); @@ -2394,9 +2483,30 @@ public: QualType mergeObjCGCQualifiers(QualType, QualType); - bool doFunctionTypesMatchOnExtParameterInfos( - const FunctionProtoType *FromFunctionType, - const FunctionProtoType *ToFunctionType); + /// This function merges the ExtParameterInfo lists of two functions. It + /// returns true if the lists are compatible. The merged list is returned in + /// NewParamInfos. + /// + /// \param FirstFnType The type of the first function. + /// + /// \param SecondFnType The type of the second function. + /// + /// \param CanUseFirst This flag is set to true if the first function's + /// ExtParameterInfo list can be used as the composite list of + /// ExtParameterInfo. + /// + /// \param CanUseSecond This flag is set to true if the second function's + /// ExtParameterInfo list can be used as the composite list of + /// ExtParameterInfo. + /// + /// \param NewParamInfos The composite list of ExtParameterInfo. The list is + /// empty if none of the flags are set. + /// + bool mergeExtParameterInfo( + const FunctionProtoType *FirstFnType, + const FunctionProtoType *SecondFnType, + bool &CanUseFirst, bool &CanUseSecond, + SmallVectorImpl<FunctionProtoType::ExtParameterInfo> &NewParamInfos); void ResetObjCLayout(const ObjCContainerDecl *CD); @@ -2432,12 +2542,13 @@ public: bool isSentinelNullExpr(const Expr *E); - /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or NULL if + /// \brief 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 NULL if + + /// \brief Get the implementation of the ObjCCategoryDecl \p D, or nullptr if /// none exists. - ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); + ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); /// \brief Return true if there is at least one \@implementation in the TU. bool AnyObjCImplementation() { @@ -2447,6 +2558,7 @@ public: /// \brief Set the implementation of ObjCInterfaceDecl. void setObjCImplementation(ObjCInterfaceDecl *IFaceD, ObjCImplementationDecl *ImplD); + /// \brief Set the implementation of ObjCCategoryDecl. void setObjCImplementation(ObjCCategoryDecl *CatD, ObjCCategoryImplDecl *ImplD); @@ -2466,8 +2578,9 @@ public: /// \brief 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 - /// NULL if none exists. + /// nullptr if none exists. Expr *getBlockVarCopyInits(const VarDecl* VD); /// \brief Allocate an uninitialized TypeSourceInfo. @@ -2636,6 +2749,7 @@ private: const FieldDecl *Field, bool includeVBases = true, QualType *NotEncodedT=nullptr) const; + public: // Adds the encoding of a method parameter or return type. void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, @@ -2647,11 +2761,19 @@ public: bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const; enum class InlineVariableDefinitionKind { - None, ///< Not an inline variable. - Weak, ///< Weak definition of inline variable. - WeakUnknown, ///< Weak for now, might become strong later in this TU. - Strong ///< Strong definition. + /// Not an inline variable. + None, + + /// Weak definition of inline variable. + Weak, + + /// Weak for now, might become strong later in this TU. + WeakUnknown, + + /// Strong definition. + Strong }; + /// \brief Determine whether a definition of this inline variable should /// be treated as a weak or strong definition. For compatibility with /// C++14 and before, for a constexpr static data member, if there is an @@ -2661,6 +2783,9 @@ public: getInlineVariableDefinitionKind(const VarDecl *VD) const; private: + friend class DeclarationNameTable; + friend class DeclContext; + const ASTRecordLayout & getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const; @@ -2673,26 +2798,23 @@ private: // into the datastructures which avoids this mess during deallocation but is // wasteful of memory, and here we require a lot of error prone book keeping // in order to track and run destructors while we're tearing things down. - typedef llvm::SmallVector<std::pair<void (*)(void *), void *>, 16> - DeallocationFunctionsAndArguments; + using DeallocationFunctionsAndArguments = + llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>; DeallocationFunctionsAndArguments Deallocations; // FIXME: This currently contains the set of StoredDeclMaps used // by DeclContext objects. This probably should not be in ASTContext, // but we include it here so that ASTContext can quickly deallocate them. - llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; - - friend class DeclContext; - friend class DeclarationNameTable; - - void ReleaseDeclContextMaps(); - void ReleaseParentMapEntries(); + llvm::PointerIntPair<StoredDeclsMap *, 1> LastSDM; std::unique_ptr<ParentMapPointers> PointerParents; std::unique_ptr<ParentMapOtherNodes> OtherParents; std::unique_ptr<VTableContextBase> VTContext; + void ReleaseDeclContextMaps(); + void ReleaseParentMapEntries(); + public: enum PragmaSectionFlag : unsigned { PSF_None = 0, @@ -2712,27 +2834,26 @@ public: SectionInfo(DeclaratorDecl *Decl, SourceLocation PragmaSectionLocation, int SectionFlags) - : Decl(Decl), - PragmaSectionLocation(PragmaSectionLocation), - SectionFlags(SectionFlags) {} + : Decl(Decl), PragmaSectionLocation(PragmaSectionLocation), + SectionFlags(SectionFlags) {} }; llvm::StringMap<SectionInfo> SectionInfos; }; /// \brief Utility function for constructing a nullary selector. -static inline Selector GetNullarySelector(StringRef name, ASTContext& Ctx) { +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. -static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { +inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(1, &II); } -} // end namespace clang +} // namespace clang // operator new and delete aren't allowed inside namespaces. @@ -2763,11 +2884,12 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { /// @param C The ASTContext that provides the allocator. /// @param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// @return The allocated memory. Could be nullptr. inline void *operator new(size_t Bytes, const clang::ASTContext &C, size_t Alignment) { return C.Allocate(Bytes, Alignment); } + /// @brief Placement delete companion to the new above. /// /// This operator is just a companion to the new above. There is no way of @@ -2800,7 +2922,7 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) { /// @param C The ASTContext that provides the allocator. /// @param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// @return The allocated memory. Could be nullptr. inline void *operator new[](size_t Bytes, const clang::ASTContext& C, size_t Alignment = 8) { return C.Allocate(Bytes, Alignment); diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index a8eff1a2fcbb..9395d36d87e5 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -22,6 +22,7 @@ namespace clang { class CXXRecordDecl; class Decl; class DeclContext; + class Expr; class FieldDecl; class FunctionDecl; class FunctionTemplateDecl; @@ -35,6 +36,7 @@ namespace clang { class QualType; class RecordDecl; class TagDecl; + class ValueDecl; class VarDecl; class VarTemplateDecl; class VarTemplateSpecializationDecl; @@ -80,13 +82,19 @@ public: /// \brief A virtual destructor's operator delete has been resolved. virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) {} + const FunctionDecl *Delete, + Expr *ThisArg) {} /// \brief An implicit member got a definition. virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} - /// \brief A static data member was implicitly instantiated. - virtual void StaticDataMemberInstantiated(const VarDecl *D) {} + /// \brief 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. + virtual void VariableDefinitionInstantiated(const VarDecl *D) {} /// \brief A function template's definition was instantiated. virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {} diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h index 9078a0e80299..3693aeccfe14 100644 --- a/include/clang/AST/ASTUnresolvedSet.h +++ b/include/clang/AST/ASTUnresolvedSet.h @@ -1,4 +1,4 @@ -//===-- ASTUnresolvedSet.h - Unresolved sets of declarations ---*- C++ -*-===// +//===- ASTUnresolvedSet.h - Unresolved sets of declarations -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,14 +16,22 @@ #define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H #include "clang/AST/ASTVector.h" +#include "clang/AST/DeclAccessPair.h" #include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/Specifiers.h" +#include <cassert> +#include <cstdint> namespace clang { +class NamedDecl; + /// \brief An UnresolvedSet-like class which uses the ASTContext's allocator. class ASTUnresolvedSet { + friend class LazyASTUnresolvedSet; + struct DeclsTy : ASTVector<DeclAccessPair> { - DeclsTy() {} + DeclsTy() = default; DeclsTy(ASTContext &C, unsigned N) : ASTVector<DeclAccessPair>(C, N) {} bool isLazy() const { return getTag(); } @@ -32,14 +40,12 @@ class ASTUnresolvedSet { DeclsTy Decls; - friend class LazyASTUnresolvedSet; - public: - ASTUnresolvedSet() {} + ASTUnresolvedSet() = default; ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {} - typedef UnresolvedSetIterator iterator; - typedef UnresolvedSetIterator const_iterator; + using iterator = UnresolvedSetIterator; + using const_iterator = UnresolvedSetIterator; iterator begin() { return iterator(Decls.begin()); } iterator end() { return iterator(Decls.end()); } @@ -98,13 +104,14 @@ public: } void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); } + void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) { assert(Impl.empty() || Impl.Decls.isLazy()); Impl.Decls.setLazy(true); - Impl.addDecl(C, reinterpret_cast<NamedDecl*>(ID << 2), AS); + Impl.addDecl(C, reinterpret_cast<NamedDecl *>(ID << 2), AS); } }; } // namespace clang -#endif +#endif // LLVM_CLANG_AST_ASTUNRESOLVEDSET_H diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 717a9e9dff34..80cd6b7007a6 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -1,4 +1,4 @@ -//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=// +//===- ASTVector.h - Vector that uses ASTContext for allocation ---*- C++ -*-=// // // The LLVM Compiler Infrastructure // @@ -18,22 +18,26 @@ #ifndef LLVM_CLANG_AST_ASTVECTOR_H #define LLVM_CLANG_AST_ASTVECTOR_H -#include "clang/AST/AttrIterator.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/type_traits.h" #include <algorithm> +#include <cassert> #include <cstddef> #include <cstring> +#include <iterator> #include <memory> +#include <type_traits> +#include <utility> namespace clang { - class ASTContext; + +class ASTContext; template<typename T> class ASTVector { private: - T *Begin, *End; - llvm::PointerIntPair<T*, 1, bool> Capacity; + T *Begin = nullptr; + T *End = nullptr; + llvm::PointerIntPair<T *, 1, bool> Capacity; void setEnd(T *P) { this->End = P; } @@ -45,7 +49,7 @@ protected: public: // Default ctor - Initialize to empty. - ASTVector() : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {} + ASTVector() : Capacity(nullptr, false) {} ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) { O.Begin = O.End = nullptr; @@ -53,14 +57,15 @@ public: O.Capacity.setInt(false); } - ASTVector(const ASTContext &C, unsigned N) - : Begin(nullptr), End(nullptr), Capacity(nullptr, false) { + ASTVector(const ASTContext &C, unsigned N) : Capacity(nullptr, false) { reserve(C, N); } ASTVector &operator=(ASTVector &&RHS) { ASTVector O(std::move(RHS)); + using std::swap; + swap(Begin, O.Begin); swap(End, O.End); swap(Capacity, O.Capacity); @@ -74,19 +79,19 @@ public: } } - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T* iterator; - typedef const T* const_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + using value_type = T; + using iterator = T *; + using const_iterator = const T *; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using reverse_iterator = std::reverse_iterator<iterator>; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; + using reference = T &; + using const_reference = const T &; + using pointer = T *; + using const_pointer = const T *; // forward iterator creation methods. iterator begin() { return Begin; } @@ -175,7 +180,6 @@ public: size_t capacity() const { return this->capacity_ptr() - Begin; } /// append - Add the specified range to the end of the SmallVector. - /// template<typename in_iter> void append(const ASTContext &C, in_iter in_start, in_iter in_end) { size_type NumInputs = std::distance(in_start, in_end); @@ -195,7 +199,6 @@ public: } /// append - Add the specified range to the end of the SmallVector. - /// void append(const ASTContext &C, size_type NumInputs, const T &Elt) { // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) @@ -368,6 +371,7 @@ protected: const_iterator capacity_ptr() const { return (iterator) Capacity.getPointer(); } + iterator capacity_ptr() { return (iterator)Capacity.getPointer(); } }; @@ -401,5 +405,6 @@ void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) { Capacity.setPointer(Begin+NewCapacity); } -} // end: clang namespace -#endif +} // namespace clang + +#endif // LLVM_CLANG_AST_ASTVECTOR_H diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h index fb9b049e5d6b..56807b4590d3 100644 --- a/include/clang/AST/AttrIterator.h +++ b/include/clang/AST/AttrIterator.h @@ -1,4 +1,4 @@ -//===--- AttrIterator.h - Classes for attribute iteration -------*- C++ -*-===// +//===- AttrIterator.h - Classes for attribute iteration ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,16 +15,23 @@ #define LLVM_CLANG_AST_ATTRITERATOR_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstddef> #include <iterator> namespace clang { - class ASTContext; - class Attr; -} + +class ASTContext; +class Attr; + +} // namespace clang // Defined in ASTContext.h void *operator new(size_t Bytes, const clang::ASTContext &C, size_t Alignment = 8); + // FIXME: Being forced to not have a default argument here due to redeclaration // rules on default arguments sucks void *operator new[](size_t Bytes, const clang::ASTContext &C, @@ -39,13 +46,13 @@ void operator delete[](void *Ptr, const clang::ASTContext &C, size_t); namespace clang { /// AttrVec - A vector of Attr, which is how they are stored on the AST. -typedef SmallVector<Attr *, 4> AttrVec; +using AttrVec = SmallVector<Attr *, 4>; /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only /// providing attributes that are of a specific type. template <typename SpecificAttr, typename Container = AttrVec> class specific_attr_iterator { - typedef typename Container::const_iterator Iterator; + using Iterator = typename Container::const_iterator; /// Current - The current, underlying iterator. /// In order to ensure we don't dereference an invalid iterator unless @@ -67,14 +74,14 @@ class specific_attr_iterator { } public: - typedef SpecificAttr* value_type; - typedef SpecificAttr* reference; - typedef SpecificAttr* pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + using value_type = SpecificAttr *; + using reference = SpecificAttr *; + using pointer = SpecificAttr *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; - specific_attr_iterator() : Current() { } - explicit specific_attr_iterator(Iterator i) : Current(i) { } + specific_attr_iterator() = default; + explicit specific_attr_iterator(Iterator i) : Current(i) {} reference operator*() const { AdvanceToNext(); @@ -136,6 +143,6 @@ inline SpecificAttr *getSpecificAttr(const Container& container) { return nullptr; } -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_ATTRITERATOR_H diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h index 66af023c828e..fdb7e718fe9e 100644 --- a/include/clang/AST/BaseSubobject.h +++ b/include/clang/AST/BaseSubobject.h @@ -1,4 +1,4 @@ -//===--- BaseSubobject.h - BaseSubobject class ----------------------------===// +//===- BaseSubobject.h - BaseSubobject class --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,12 +15,15 @@ #define LLVM_CLANG_AST_BASESUBOBJECT_H #include "clang/AST/CharUnits.h" -#include "clang/AST/DeclCXX.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/type_traits.h" +#include <cstdint> +#include <utility> namespace clang { + +class CXXRecordDecl; + // BaseSubobject - Uniquely identifies a direct or indirect base class. // Stores both the base class decl and the offset from the most derived class to // the base class. Used for vtable and VTT generation. @@ -32,9 +35,9 @@ class BaseSubobject { CharUnits BaseOffset; public: - BaseSubobject() { } + BaseSubobject() = default; BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset) - : Base(Base), BaseOffset(BaseOffset) { } + : Base(Base), BaseOffset(BaseOffset) {} /// getBase - Returns the base class declaration. const CXXRecordDecl *getBase() const { return Base; } @@ -47,7 +50,7 @@ public: } }; -} // end namespace clang +} // namespace clang namespace llvm { @@ -65,7 +68,8 @@ template<> struct DenseMapInfo<clang::BaseSubobject> { } static unsigned getHashValue(const clang::BaseSubobject &Base) { - typedef std::pair<const clang::CXXRecordDecl *, clang::CharUnits> PairTy; + using PairTy = std::pair<const clang::CXXRecordDecl *, clang::CharUnits>; + return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(), Base.getBaseOffset())); } @@ -81,6 +85,6 @@ template <> struct isPodLike<clang::BaseSubobject> { static const bool value = true; }; -} +} // namespace llvm -#endif +#endif // LLVM_CLANG_AST_BASESUBOBJECT_H diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index 181131aba07f..e4f5f7db2f73 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -133,6 +133,9 @@ FLOATING_TYPE(Double, DoubleTy) // 'long double' FLOATING_TYPE(LongDouble, LongDoubleTy) +// '_Float16' +FLOATING_TYPE(Float16, HalfTy) + // '__float128' FLOATING_TYPE(Float128, Float128Ty) diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index 260734f2200a..942d08d585fe 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -50,3 +50,6 @@ clang_tablegen(CommentCommandList.inc -gen-clang-comment-command-list SOURCE CommentCommands.td TARGET ClangCommentCommandList) +clang_tablegen(StmtDataCollectors.inc -gen-clang-data-collectors + SOURCE StmtDataCollectors.td + TARGET StmtDataCollectors) diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 980608570fd6..11fb229f0c09 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -1,4 +1,4 @@ -//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===// +//===- CXXInheritance.h - C++ Inheritance -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,19 +16,23 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" -#include <cassert> +#include "llvm/ADT/iterator_range.h" #include <list> +#include <memory> +#include <utility> namespace clang { - -class CXXBaseSpecifier; -class CXXMethodDecl; -class CXXRecordDecl; + +class ASTContext; class NamedDecl; /// \brief Represents an element in a path from a derived class to a @@ -66,12 +70,12 @@ struct CXXBasePathElement { /// subobject is being used. class CXXBasePath : public SmallVector<CXXBasePathElement, 4> { public: - CXXBasePath() : Access(AS_public) {} - /// \brief 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; + AccessSpecifier Access = AS_public; + + CXXBasePath() = default; /// \brief The set of declarations found inside this base class /// subobject. @@ -113,8 +117,10 @@ public: /// refer to the same base class subobject of type A (the virtual /// one), there is no ambiguity. class CXXBasePaths { + friend class CXXRecordDecl; + /// \brief The type from which this search originated. - CXXRecordDecl *Origin; + CXXRecordDecl *Origin = nullptr; /// Paths - The actual set of paths that can be taken from the /// derived class to the same base class. @@ -152,15 +158,13 @@ class CXXBasePaths { CXXBasePath ScratchPath; /// DetectedVirtual - The base class that is virtual. - const RecordType *DetectedVirtual; + 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; - - friend class CXXRecordDecl; + unsigned NumDeclsFound = 0; void ComputeDeclsFound(); @@ -169,17 +173,16 @@ class CXXBasePaths { bool LookupInDependent = false); public: - typedef std::list<CXXBasePath>::iterator paths_iterator; - typedef std::list<CXXBasePath>::const_iterator const_paths_iterator; - typedef NamedDecl **decl_iterator; + using paths_iterator = std::list<CXXBasePath>::iterator; + using const_paths_iterator = std::list<CXXBasePath>::const_iterator; + using decl_iterator = NamedDecl **; /// BasePaths - Construct a new BasePaths structure to record the /// paths for a derived-to-base search. explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true, bool DetectVirtual = true) - : Origin(), FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), - DetectVirtual(DetectVirtual), DetectedVirtual(nullptr), - NumDeclsFound(0) {} + : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), + DetectVirtual(DetectVirtual) {} paths_iterator begin() { return Paths.begin(); } paths_iterator end() { return Paths.end(); } @@ -189,7 +192,8 @@ public: CXXBasePath& front() { return Paths.front(); } const CXXBasePath& front() const { return Paths.front(); } - typedef llvm::iterator_range<decl_iterator> decl_range; + using decl_range = llvm::iterator_range<decl_iterator>; + decl_range found_decls(); /// \brief Determine whether the path from the most-derived type to the @@ -231,25 +235,24 @@ public: /// \brief Uniquely identifies a virtual method within a class /// hierarchy by the method itself and a class subobject number. struct UniqueVirtualMethod { - UniqueVirtualMethod() - : Method(nullptr), Subobject(0), InVirtualSubobject(nullptr) { } - - UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject, - const CXXRecordDecl *InVirtualSubobject) - : Method(Method), Subobject(Subobject), - InVirtualSubobject(InVirtualSubobject) { } - /// \brief The overriding virtual method. - CXXMethodDecl *Method; + CXXMethodDecl *Method = nullptr; /// \brief The subobject in which the overriding virtual method /// resides. - unsigned Subobject; + unsigned Subobject = 0; /// \brief 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; + const CXXRecordDecl *InVirtualSubobject = nullptr; + + UniqueVirtualMethod() = default; + + UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject, + const CXXRecordDecl *InVirtualSubobject) + : Method(Method), Subobject(Subobject), + InVirtualSubobject(InVirtualSubobject) {} friend bool operator==(const UniqueVirtualMethod &X, const UniqueVirtualMethod &Y) { @@ -271,14 +274,16 @@ struct UniqueVirtualMethod { /// pair is the virtual method that overrides it (including the /// subobject in which that virtual function occurs). class OverridingMethods { - typedef SmallVector<UniqueVirtualMethod, 4> ValuesT; - typedef llvm::MapVector<unsigned, ValuesT> MapType; + using ValuesT = SmallVector<UniqueVirtualMethod, 4>; + using MapType = llvm::MapVector<unsigned, ValuesT>; + MapType Overrides; public: // Iterate over the set of subobjects that have overriding methods. - typedef MapType::iterator iterator; - typedef MapType::const_iterator const_iterator; + using iterator = MapType::iterator; + using const_iterator = MapType::const_iterator; + iterator begin() { return Overrides.begin(); } const_iterator begin() const { return Overrides.begin(); } iterator end() { return Overrides.end(); } @@ -287,10 +292,10 @@ public: // Iterate over the set of overriding virtual methods in a given // subobject. - typedef SmallVectorImpl<UniqueVirtualMethod>::iterator - overriding_iterator; - typedef SmallVectorImpl<UniqueVirtualMethod>::const_iterator - overriding_const_iterator; + using overriding_iterator = + SmallVectorImpl<UniqueVirtualMethod>::iterator; + using overriding_const_iterator = + SmallVectorImpl<UniqueVirtualMethod>::const_iterator; // Add a new overriding method for a particular subobject. void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding); @@ -357,12 +362,12 @@ public: /// subobject numbers greater than 0 refer to non-virtual base class /// subobjects of that type. class CXXFinalOverriderMap - : public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> { }; + : public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> {}; /// \brief A set of all the primary bases for a class. class CXXIndirectPrimaryBaseSet - : public llvm::SmallSet<const CXXRecordDecl*, 32> { }; + : public llvm::SmallSet<const CXXRecordDecl*, 32> {}; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_CXXINHERITANCE_H diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 25f6172be9b1..6487613200de 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -1,4 +1,4 @@ -//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===// +//===- CanonicalType.h - C Language Family Type Representation --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,13 +16,29 @@ #define LLVM_CLANG_AST_CANONICALTYPE_H #include "clang/AST/Type.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/iterator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> +#include <iterator> +#include <type_traits> namespace clang { template<typename T> class CanProxy; template<typename T> struct CanProxyAdaptor; +class CXXRecordDecl; +class EnumDecl; +class Expr; +class IdentifierInfo; +class ObjCInterfaceDecl; +class RecordDecl; +class TagDecl; +class TemplateTypeParmDecl; //----------------------------------------------------------------------------// // Canonical, qualified type template @@ -46,8 +62,6 @@ template<typename T> struct CanProxyAdaptor; /// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can /// be implicitly converted to a QualType, but the reverse operation requires /// a call to ASTContext::getCanonicalType(). -/// -/// template<typename T = Type> class CanQual { /// \brief The actual, canonical type. @@ -55,7 +69,7 @@ class CanQual { public: /// \brief Constructs a NULL canonical type. - CanQual() : Stored() { } + CanQual() = default; /// \brief Converting constructor that permits implicit upcasting of /// canonical type pointers. @@ -66,12 +80,11 @@ public: /// \brief Retrieve the underlying type pointer, which refers to a /// canonical type. /// - /// The underlying pointer must not be NULL. + /// 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 - /// canonical type, or NULL. - /// + /// canonical type, or nullptr. const T *getTypePtrOrNull() const { return cast_or_null<T>(Stored.getTypePtrOrNull()); } @@ -125,9 +138,11 @@ public: bool isConstQualified() const { return Stored.isLocalConstQualified(); } + bool isVolatileQualified() const { return Stored.isLocalVolatileQualified(); } + bool isRestrictQualified() const { return Stored.isLocalRestrictQualified(); } @@ -195,7 +210,7 @@ inline bool operator!=(CanQual<T> x, CanQual<U> y) { } /// \brief Represents a canonical, potentially-qualified type. -typedef CanQual<Type> CanQualType; +using CanQualType = CanQual<Type>; inline CanQualType Type::getCanonicalTypeUnqualified() const { return CanQualType::CreateUnsafe(getCanonicalTypeInternal()); @@ -320,7 +335,7 @@ public: /// than the more typical @c QualType, to propagate the notion of "canonical" /// through the system. template<typename T> -struct CanProxyAdaptor : CanProxyBase<T> { }; +struct CanProxyAdaptor : CanProxyBase<T> {}; /// \brief Canonical proxy type returned when retrieving the members of a /// canonical type or as the result of the @c CanQual<T>::getAs member @@ -333,7 +348,7 @@ template<typename T> class CanProxy : public CanProxyAdaptor<T> { public: /// \brief Build a NULL proxy. - CanProxy() { } + CanProxy() = default; /// \brief Build a proxy to the given canonical type. CanProxy(CanQual<T> Stored) { this->Stored = Stored; } @@ -342,7 +357,7 @@ public: operator CanQual<T>() const { return this->Stored; } }; -} // end namespace clang +} // namespace clang namespace llvm { @@ -350,8 +365,9 @@ namespace llvm { /// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. /// to return smart pointer (proxies?). template<typename T> -struct simplify_type< ::clang::CanQual<T> > { - typedef const T *SimpleType; +struct simplify_type< ::clang::CanQual<T>> { + using SimpleType = const T *; + static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { return Val.getTypePtr(); } @@ -359,19 +375,20 @@ struct simplify_type< ::clang::CanQual<T> > { // Teach SmallPtrSet that CanQual<T> is "basically a pointer". template<typename T> -class PointerLikeTypeTraits<clang::CanQual<T> > { -public: - static inline void *getAsVoidPointer(clang::CanQual<T> P) { +struct PointerLikeTypeTraits<clang::CanQual<T>> { + static void *getAsVoidPointer(clang::CanQual<T> P) { return P.getAsOpaquePtr(); } - static inline clang::CanQual<T> getFromVoidPointer(void *P) { + + static clang::CanQual<T> getFromVoidPointer(void *P) { return clang::CanQual<T>::getFromOpaquePtr(P); } + // qualifier information is encoded in the low bits. enum { NumLowBitsAvailable = 0 }; }; -} // end namespace llvm +} // namespace llvm namespace clang { @@ -389,7 +406,7 @@ struct CanTypeIterator CanQualType, typename std::iterator_traits<InputIterator>::difference_type, CanProxy<Type>, CanQualType> { - CanTypeIterator() {} + CanTypeIterator() = default; explicit CanTypeIterator(InputIterator Iter) : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {} @@ -487,6 +504,7 @@ struct CanProxyAdaptor<FunctionProtoType> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR( ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos) + CanQualType getParamType(unsigned i) const { return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i)); } @@ -494,8 +512,8 @@ struct CanProxyAdaptor<FunctionProtoType> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals) - typedef CanTypeIterator<FunctionProtoType::param_type_iterator> - param_type_iterator; + using param_type_iterator = + CanTypeIterator<FunctionProtoType::param_type_iterator>; param_type_iterator param_type_begin() const { return param_type_iterator(this->getTypePtr()->param_type_begin()); @@ -567,7 +585,8 @@ struct CanProxyAdaptor<ObjCObjectType> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) - typedef ObjCObjectPointerType::qual_iterator qual_iterator; + using qual_iterator = ObjCObjectPointerType::qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) @@ -585,7 +604,8 @@ struct CanProxyAdaptor<ObjCObjectPointerType> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) - typedef ObjCObjectPointerType::qual_iterator qual_iterator; + using qual_iterator = ObjCObjectPointerType::qual_iterator; + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) @@ -662,7 +682,6 @@ CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const { return CanProxy<Type>(*this); } -} - +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_CANONICALTYPE_H diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 564c8ec9b9ea..ddead6046a14 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -40,14 +40,14 @@ namespace clang { typedef int64_t QuantityType; private: - QuantityType Quantity; + QuantityType Quantity = 0; explicit CharUnits(QuantityType C) : Quantity(C) {} public: /// CharUnits - A default constructor. - CharUnits() : Quantity(0) {} + CharUnits() = default; /// Zero - Construct a CharUnits quantity of zero. static CharUnits Zero() { diff --git a/include/clang/AST/CommentVisitor.h b/include/clang/AST/CommentVisitor.h index 21641bfeb89f..d1cc2d0a4e5e 100644 --- a/include/clang/AST/CommentVisitor.h +++ b/include/clang/AST/CommentVisitor.h @@ -1,4 +1,4 @@ -//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- C++ -*-===// +//===- CommentVisitor.h - Visitor for Comment subclasses --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,8 +16,8 @@ namespace clang { namespace comments { -template <typename T> struct make_ptr { typedef T *type; }; -template <typename T> struct make_const_ptr { typedef const T *type; }; +template <typename T> struct make_ptr { using type = T *; }; +template <typename T> struct make_const_ptr { using type = const T *; }; template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> class CommentVisitorBase { @@ -64,7 +64,7 @@ template<typename ImplClass, typename RetTy=void> class ConstCommentVisitor : public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {}; -} // end namespace comments -} // end namespace clang +} // namespace comments +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_COMMENTVISITOR_H diff --git a/include/clang/AST/DataCollection.h b/include/clang/AST/DataCollection.h new file mode 100644 index 000000000000..229ac2bd0f22 --- /dev/null +++ b/include/clang/AST/DataCollection.h @@ -0,0 +1,65 @@ +//===--- DatatCollection.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// \brief This file 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: +/// +/// - There must be a method addData(const T &Data) that accepts strings, +/// integral types as well as QualType. All data is forwarded using +/// to this method. +/// - The ASTContext of the Stmt must be accessible by the name Context. +/// +/// It is also possible to override individual visit methods. Have a look at +/// the DataCollector in lib/Analysis/CloneDetection.cpp for a usage example. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DATACOLLECTION_H +#define LLVM_CLANG_AST_DATACOLLECTION_H + +#include "clang/AST/ASTContext.h" + +namespace clang { +namespace data_collection { + +/// Returns a string that represents all macro expansions that expanded into the +/// given SourceLocation. +/// +/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations +/// A and B are expanded from the same macros in the same order. +std::string getMacroStack(SourceLocation Loc, ASTContext &Context); + +/// Utility functions for implementing addData() for a consumer that has a +/// method update(StringRef) +template <class T> +void addDataToConsumer(T &DataConsumer, llvm::StringRef Str) { + DataConsumer.update(Str); +} + +template <class T> void addDataToConsumer(T &DataConsumer, const QualType &QT) { + addDataToConsumer(DataConsumer, QT.getAsString()); +} + +template <class T, class Type> +typename std::enable_if< + std::is_integral<Type>::value || std::is_enum<Type>::value || + std::is_convertible<Type, size_t>::value // for llvm::hash_code + >::type +addDataToConsumer(T &DataConsumer, Type Data) { + DataConsumer.update(StringRef(reinterpret_cast<char *>(&Data), sizeof(Data))); +} + +} // end namespace data_collection +} // end namespace clang + +#endif // LLVM_CLANG_AST_DATACOLLECTION_H diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 54e6ebcd8af2..4db0b1ef949b 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1,4 +1,4 @@ -//===--- Decl.h - Classes for representing declarations ---------*- C++ -*-===// +//===- Decl.h - Classes for representing declarations -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,33 +18,58 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/Type.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Linkage.h" -#include "clang/Basic/Module.h" #include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/PragmaKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/Visibility.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <string> +#include <utility> namespace clang { + +class ASTContext; struct ASTTemplateArgumentListInfo; -class CXXTemporary; +class Attr; class CompoundStmt; class DependentFunctionTemplateSpecializationInfo; +class EnumDecl; class Expr; class FunctionTemplateDecl; class FunctionTemplateSpecializationInfo; class LabelStmt; class MemberSpecializationInfo; -class NestedNameSpecifier; +class Module; +class NamespaceDecl; class ParmVarDecl; +class RecordDecl; class Stmt; class StringLiteral; +class TagDecl; class TemplateArgumentList; +class TemplateArgumentListInfo; class TemplateParameterList; class TypeAliasTemplateDecl; class TypeLoc; @@ -58,13 +83,15 @@ class VarTemplateDecl; /// TypeLoc TL = TypeSourceInfo->getTypeLoc(); /// TL.getStartLoc().print(OS, SrcMgr); /// @endcode -/// class TypeSourceInfo { - QualType Ty; // Contains a memory block after the class, used for type source information, // allocated by ASTContext. friend class ASTContext; - TypeSourceInfo(QualType ty) : Ty(ty) { } + + QualType Ty; + + TypeSourceInfo(QualType ty) : Ty(ty) {} + public: /// \brief Return the type wrapped by this type source info. QualType getType() const { return Ty; } @@ -78,14 +105,16 @@ public: /// TranslationUnitDecl - The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { - virtual void anchor(); ASTContext &Ctx; /// The (most recently entered) anonymous namespace for this /// translation unit, if one has been created. - NamespaceDecl *AnonymousNamespace; + NamespaceDecl *AnonymousNamespace = nullptr; explicit TranslationUnitDecl(ASTContext &ctx); + + virtual void anchor(); + public: ASTContext &getASTContext() const { return Ctx; } @@ -93,6 +122,7 @@ public: void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; } static TranslationUnitDecl *Create(ASTContext &C); + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TranslationUnit; } @@ -109,18 +139,18 @@ public: class PragmaCommentDecl final : public Decl, private llvm::TrailingObjects<PragmaCommentDecl, char> { - virtual void anchor(); - - PragmaMSCommentKind CommentKind; - - friend TrailingObjects; friend class ASTDeclReader; friend class ASTDeclWriter; + friend TrailingObjects; + + PragmaMSCommentKind CommentKind; PragmaCommentDecl(TranslationUnitDecl *TU, SourceLocation CommentLoc, PragmaMSCommentKind CommentKind) : Decl(PragmaComment, TU, CommentLoc), CommentKind(CommentKind) {} + virtual void anchor(); + public: static PragmaCommentDecl *Create(const ASTContext &C, TranslationUnitDecl *DC, SourceLocation CommentLoc, @@ -143,18 +173,18 @@ public: class PragmaDetectMismatchDecl final : public Decl, private llvm::TrailingObjects<PragmaDetectMismatchDecl, char> { - virtual void anchor(); - - size_t ValueStart; - - friend TrailingObjects; friend class ASTDeclReader; friend class ASTDeclWriter; + friend TrailingObjects; + + size_t ValueStart; PragmaDetectMismatchDecl(TranslationUnitDecl *TU, SourceLocation Loc, size_t ValueStart) : Decl(PragmaDetectMismatch, TU, Loc), ValueStart(ValueStart) {} + virtual void anchor(); + public: static PragmaDetectMismatchDecl *Create(const ASTContext &C, TranslationUnitDecl *DC, @@ -189,14 +219,16 @@ public: /// The declaration at #3 finds it is a redeclaration of \c N::f through /// lookup in the extern "C" context. class ExternCContextDecl : public Decl, public DeclContext { - virtual void anchor(); - explicit ExternCContextDecl(TranslationUnitDecl *TU) : Decl(ExternCContext, TU, SourceLocation()), DeclContext(ExternCContext) {} + + virtual void anchor(); + public: static ExternCContextDecl *Create(const ASTContext &C, TranslationUnitDecl *TU); + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ExternCContext; } @@ -211,18 +243,19 @@ public: /// NamedDecl - This represents a decl with a name. Many decls have names such /// as ObjCMethodDecl, but not \@class, etc. class NamedDecl : public Decl { - virtual void anchor(); /// Name - 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; + virtual void anchor(); + private: NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY; protected: NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) - : Decl(DK, DC, L), Name(N) { } + : Decl(DK, DC, L), Name(N) {} public: /// getIdentifier - Get the identifier that names this declaration, @@ -272,8 +305,7 @@ public: // FIXME: Remove string version. std::string getQualifiedNameAsString() const; - /// getNameForDiagnostic - Appends a human-readable name for this - /// declaration into the given stream. + /// Appends a human-readable name for this declaration into the given stream. /// /// This is the method invoked by Sema when displaying a NamedDecl /// in a diagnostic. It does not necessarily produce the same @@ -339,6 +371,12 @@ public: return clang::isExternallyVisible(getLinkageInternal()); } + /// Determine whether this declaration can be redeclared in a + /// different translation unit. + bool isExternallyDeclarable() const { + return isExternallyVisible() && !getOwningModuleForLinkage(); + } + /// \brief Determines the visibility of this entity. Visibility getVisibility() const { return getLinkageAndVisibility().getVisibility(); @@ -349,7 +387,14 @@ public: /// Kinds of explicit visibility. enum ExplicitVisibilityKind { + /// Do an LV computation for, ultimately, a type. + /// Visibility may be restricted by type visibility settings and + /// the visibility of template arguments. VisibilityForType, + + /// Do an LV computation for, ultimately, a non-type declaration. + /// Visibility may be restricted by value visibility settings and + /// the visibility of template arguments. VisibilityForValue }; @@ -412,10 +457,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { /// location of the statement. For GNU local labels (__label__), the decl /// location is where the __label__ is. class LabelDecl : public NamedDecl { - void anchor() override; LabelStmt *TheStmt; StringRef MSAsmName; - bool MSAsmNameResolved; + bool MSAsmNameResolved = false; + /// LocStart - For normal labels, this is the same as the main declaration /// label, i.e., the location of the identifier; for GNU local labels, /// this is the location of the __label__ keyword. @@ -423,10 +468,9 @@ class LabelDecl : public NamedDecl { LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, LabelStmt *S, SourceLocation StartL) - : NamedDecl(Label, DC, IdentL, II), - TheStmt(S), - MSAsmNameResolved(false), - LocStart(StartL) {} + : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {} + + void anchor() override; public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, @@ -446,7 +490,7 @@ public: return SourceRange(LocStart, getLocation()); } - bool isMSAsmLabel() const { return MSAsmName.size() != 0; } + bool isMSAsmLabel() const { return !MSAsmName.empty(); } bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; } void setMSAsmLabel(StringRef Name); StringRef getMSAsmLabel() const { return MSAsmName; } @@ -464,6 +508,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext, /// LocStart - 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. SourceLocation RBraceLoc; @@ -477,12 +522,16 @@ class NamespaceDecl : public NamedDecl, public DeclContext, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, NamespaceDecl *PrevDecl); - typedef Redeclarable<NamespaceDecl> redeclarable_base; + using redeclarable_base = Redeclarable<NamespaceDecl>; + NamespaceDecl *getNextRedeclarationImpl() override; NamespaceDecl *getPreviousDeclImpl() override; NamespaceDecl *getMostRecentDeclImpl() override; public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -490,8 +539,9 @@ public: static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -569,22 +619,21 @@ public: static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// ValueDecl - 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 { - void anchor() override; QualType DeclType; + void anchor() override; + protected: ValueDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T) : NamedDecl(DK, DC, L, N), DeclType(T) {} + public: QualType getType() const { return DeclType; } void setType(QualType newType) { DeclType = newType; } @@ -607,28 +656,23 @@ struct QualifierInfo { /// 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; + unsigned NumTemplParamLists = 0; /// TemplParamLists - 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 /// case of an explicit specialization) a final "template <>". - TemplateParameterList** TemplParamLists; + TemplateParameterList** TemplParamLists = nullptr; - /// Default constructor. - QualifierInfo() - : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(nullptr) {} + QualifierInfo() = default; + QualifierInfo(const QualifierInfo &) = delete; + QualifierInfo& operator=(const QualifierInfo &) = delete; /// setTemplateParameterListsInfo - Sets info about "outer" template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists); - -private: - // Copy constructor and copy assignment are disabled. - QualifierInfo(const QualifierInfo&) = delete; - QualifierInfo& operator=(const QualifierInfo&) = delete; }; /// \brief Represents a ValueDecl that came out of a declarator. @@ -640,7 +684,7 @@ class DeclaratorDecl : public ValueDecl { TypeSourceInfo *TInfo; }; - llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; + llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo; /// InnerLocStart - The start of the source range for this declaration, /// ignoring outer template declarations. @@ -654,15 +698,18 @@ protected: DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, SourceLocation StartL) - : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) { - } + : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) {} public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + TypeSourceInfo *getTypeSourceInfo() const { return hasExtInfo() ? getExtInfo()->TInfo : DeclInfo.get<TypeSourceInfo*>(); } + void setTypeSourceInfo(TypeSourceInfo *TI) { if (hasExtInfo()) getExtInfo()->TInfo = TI; @@ -680,6 +727,7 @@ public: SourceLocation getOuterLocStart() const; SourceRange getSourceRange() const override LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY { return getOuterLocStart(); } @@ -704,10 +752,12 @@ public: unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; } + TemplateParameterList *getTemplateParameterList(unsigned index) const { assert(index < getNumTemplateParameterLists()); return getExtInfo()->TemplParamLists[index]; } + void setTemplateParameterListsInfo(ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists); @@ -718,18 +768,12 @@ public: static bool classofKind(Kind K) { return K >= firstDeclarator && K <= lastDeclarator; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief 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 { - EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), - CheckingICE(false), IsICE(false) { } - /// \brief Whether this statement was already evaluated. bool WasEvaluated : 1; @@ -751,32 +795,46 @@ struct EvaluatedStmt { Stmt *Value; APValue Evaluated; + + EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), + CheckingICE(false), IsICE(false) {} + }; /// VarDecl - An instance of this class is created to represent a variable /// declaration or definition. class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { public: - /// getStorageClassSpecifierString - 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); - /// \brief Initialization styles. enum InitializationStyle { - CInit, ///< C-style initialization with assignment - CallInit, ///< Call-style initialization (C++98) - ListInit ///< Direct list-initialization (C++11) + /// C-style initialization with assignment + CInit, + + /// Call-style initialization (C++98) + CallInit, + + /// Direct list-initialization (C++11) + ListInit }; /// \brief Kinds of thread-local storage. enum TLSKind { - TLS_None, ///< Not a TLS variable. - TLS_Static, ///< TLS with a known-constant initializer. - TLS_Dynamic ///< TLS with a dynamic initializer. + /// Not a TLS variable. + TLS_None, + + /// TLS with a known-constant initializer. + TLS_Static, + + /// TLS with a dynamic initializer. + TLS_Dynamic }; + /// getStorageClassSpecifierString - 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); + protected: // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we // have allocated the auxiliary struct of information there. @@ -785,16 +843,20 @@ protected: // this as *many* VarDecls are ParmVarDecls that don't have default // arguments. We could save some space by moving this pointer union to be // allocated in trailing space when necessary. - typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType; + using InitType = llvm::PointerUnion<Stmt *, EvaluatedStmt *>; /// \brief The initializer for this variable or, for a ParmVarDecl, the /// C++ default argument. mutable InitType Init; private: + friend class ASTDeclReader; + friend class ASTNodeImporter; + friend class StmtIteratorBase; + class VarDeclBitfields { - friend class VarDecl; friend class ASTDeclReader; + friend class VarDecl; unsigned SClass : 3; unsigned TSCSpec : 2; @@ -802,10 +864,6 @@ private: }; enum { NumVarDeclBits = 7 }; - friend class ASTDeclReader; - friend class StmtIteratorBase; - friend class ASTNodeImporter; - protected: enum { NumParameterIndexBits = 8 }; @@ -817,8 +875,8 @@ protected: }; class ParmVarDeclBitfields { - friend class ParmVarDecl; friend class ASTDeclReader; + friend class ParmVarDecl; unsigned : NumVarDeclBits; @@ -850,9 +908,9 @@ protected: }; class NonParmVarDeclBitfields { - friend class VarDecl; - friend class ImplicitParamDecl; friend class ASTDeclReader; + friend class ImplicitParamDecl; + friend class VarDecl; unsigned : NumVarDeclBits; @@ -912,20 +970,24 @@ protected: SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC); - typedef Redeclarable<VarDecl> redeclarable_base; + using redeclarable_base = Redeclarable<VarDecl>; + VarDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + VarDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + VarDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -1030,7 +1092,6 @@ public: /// inside of functions. It also includes variables inside blocks. /// /// void foo() { int x; static int y; extern int z; } - /// bool isLocalVarDecl() const { if (getKind() != Decl::Var && getKind() != Decl::Decomposition) return false; @@ -1073,9 +1134,14 @@ public: } enum DefinitionKind { - DeclarationOnly, ///< This declaration is only a declaration. - TentativeDefinition, ///< This declaration is a tentative definition. - Definition ///< This declaration is definitely a definition. + /// This declaration is only a declaration. + DeclarationOnly, + + /// This declaration is a tentative definition. + TentativeDefinition, + + /// This declaration is definitely a definition. + Definition }; /// \brief Check whether this declaration is a definition. If this could be @@ -1205,6 +1271,7 @@ public: InitializationStyle getInitStyle() const { return static_cast<InitializationStyle>(VarDeclBits.InitStyle); } + /// \brief Whether the initializer is a direct-initializer (list or call). bool isDirectInit() const { return getInitStyle() != CInit; @@ -1222,8 +1289,8 @@ public: /// definitions one of which needs to be demoted to a declaration to keep /// the AST invariants. void demoteThisDefinitionToDeclaration() { - assert (isThisDeclarationADefinition() && "Not a definition!"); - assert (!isa<ParmVarDecl>(this) && "Cannot demote ParmVarDecls!"); + assert(isThisDeclarationADefinition() && "Not a definition!"); + assert(!isa<ParmVarDecl>(this) && "Cannot demote ParmVarDecls!"); NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = 1; } @@ -1387,12 +1454,23 @@ public: /// with pointer to 'this', 'self', '_cmd', virtual table pointers, captured /// context or something else. enum ImplicitParamKind : unsigned { - ObjCSelf, /// Parameter for Objective-C 'self' argument - ObjCCmd, /// Parameter for Objective-C '_cmd' argument - CXXThis, /// Parameter for C++ 'this' argument - CXXVTT, /// Parameter for C++ virtual table pointers - CapturedContext, /// Parameter for captured context - Other, /// Other implicit parameter + /// Parameter for Objective-C 'self' argument + ObjCSelf, + + /// Parameter for Objective-C '_cmd' argument + ObjCCmd, + + /// Parameter for C++ 'this' argument + CXXThis, + + /// Parameter for C++ virtual table pointers + CXXVTT, + + /// Parameter for captured context + CapturedContext, + + /// Other implicit parameter + Other, }; /// Create implicit parameter. @@ -1425,6 +1503,7 @@ public: ImplicitParamKind getParameterKind() const { return static_cast<ImplicitParamKind>(NonParmVarDeclBits.ImplicitParamKind); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ImplicitParam; } @@ -1604,8 +1683,8 @@ private: unsigned getParameterIndexLarge() const; }; -/// FunctionDecl - An instance of this class is created to represent a -/// function declaration or definition. +/// An instance of this class is created to represent 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 @@ -1631,7 +1710,7 @@ private: /// ParamInfo - 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; + ParmVarDecl **ParamInfo = nullptr; LazyDeclStmtPtr Body; @@ -1640,10 +1719,12 @@ private: unsigned SClass : 3; unsigned IsInline : 1; unsigned IsInlineSpecified : 1; + protected: // This is shared by CXXConstructorDecl, CXXConversionDecl, and // CXXDeductionGuideDecl. unsigned IsExplicitSpecified : 1; + private: unsigned IsVirtualAsWritten : 1; unsigned IsPure : 1; @@ -1656,7 +1737,7 @@ private: unsigned HasImplicitReturnZero : 1; unsigned IsLateTemplateParsed : 1; unsigned IsConstexpr : 1; - unsigned InstantiationIsPending:1; + unsigned InstantiationIsPending : 1; /// \brief Indicates if the function uses __try. unsigned UsesSEHTry : 1; @@ -1669,6 +1750,15 @@ private: /// parsing it. unsigned WillHaveBody : 1; +protected: + /// [C++17] Only used by CXXDeductionGuideDecl. Declared here to avoid + /// increasing the size of CXXDeductionGuideDecl by the size of an unsigned + /// int as opposed to adding a single bit to FunctionDecl. + /// Indicates that the Deduction Guide is the implicitly generated 'copy + /// deduction candidate' (is used during overload resolution). + unsigned IsCopyDeductionCandidate : 1; + +private: /// \brief End part of this FunctionDecl's source range. /// /// We could compute the full range in getSourceRange(). However, when we're @@ -1696,8 +1786,8 @@ private: DependentFunctionTemplateSpecializationInfo *> TemplateOrSpecialization; - /// DNLoc - Provides source/type location info for the - /// declaration name embedded in the DeclaratorDecl base class. + /// Provides source/type location info for the declaration name embedded in + /// the DeclaratorDecl base class. DeclarationNameLoc DNLoc; /// \brief Specify that this function declaration is actually a function @@ -1743,33 +1833,38 @@ protected: bool isConstexprSpecified) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, StartLoc), - DeclContext(DK), redeclarable_base(C), ParamInfo(nullptr), Body(), - SClass(S), IsInline(isInlineSpecified), - IsInlineSpecified(isInlineSpecified), IsExplicitSpecified(false), - IsVirtualAsWritten(false), IsPure(false), + DeclContext(DK), redeclarable_base(C), SClass(S), + IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), + IsExplicitSpecified(false), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsDefaulted(false), IsExplicitlyDefaulted(false), HasImplicitReturnZero(false), IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified), - InstantiationIsPending(false), - UsesSEHTry(false), HasSkippedBody(false), WillHaveBody(false), - EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), - DNLoc(NameInfo.getInfo()) {} + InstantiationIsPending(false), UsesSEHTry(false), HasSkippedBody(false), + WillHaveBody(false), IsCopyDeductionCandidate(false), + EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {} + + using redeclarable_base = Redeclarable<FunctionDecl>; - typedef Redeclarable<FunctionDecl> redeclarable_base; FunctionDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + FunctionDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + FunctionDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + friend class ASTDeclReader; + friend class ASTDeclWriter; + + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -1826,13 +1921,13 @@ public: return hasBody(Definition); } - /// hasTrivialBody - Returns whether the function has a trivial body that does - /// not require any specific codegen. + /// Returns whether the function has a trivial body that does not require any + /// specific codegen. bool hasTrivialBody() const; - /// isDefined - 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 is defined at all, including a deleted + /// definition. Except for the behavior when the function is deleted, behaves + /// like hasBody. bool isDefined(const FunctionDecl *&Definition) const; virtual bool isDefined() const { @@ -1851,11 +1946,10 @@ public: return const_cast<FunctionDecl *>(this)->getDefinition(); } - /// getBody - Retrieve the body (definition) of the function. The - /// function body might be in any of the (re-)declarations of this - /// function. The variant that accepts a FunctionDecl pointer will - /// set that function declaration to the actual declaration - /// containing the body (if there is one). + /// Retrieve the body (definition) of the function. The function body might be + /// in any of the (re-)declarations of this function. The variant that accepts + /// a FunctionDecl pointer will set that function declaration to the actual + /// declaration containing the body (if there is one). /// NOTE: For checking if there is a body, use hasBody() instead, to avoid /// unnecessary AST de-serialization of the body. Stmt *getBody(const FunctionDecl *&Definition) const; @@ -1870,15 +1964,13 @@ public: /// /// This does not determine whether the function has been defined (e.g., in a /// previous definition); for that information, use isDefined. - /// bool isThisDeclarationADefinition() const { - return IsDeleted || IsDefaulted || Body || IsLateTemplateParsed || - WillHaveBody || hasDefiningAttr(); + return IsDeleted || IsDefaulted || Body || HasSkippedBody || + IsLateTemplateParsed || WillHaveBody || hasDefiningAttr(); } - /// doesThisDeclarationHaveABody - 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 - + /// that is, if it is a non-deleted definition. bool doesThisDeclarationHaveABody() const { return Body || IsLateTemplateParsed; } @@ -2023,6 +2115,9 @@ public: /// true through IsAligned. bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const; + /// \brief Determine whether this is a destroying operator delete. + bool isDestroyingOperatorDelete() const; + /// Compute the language linkage. LanguageLinkage getLanguageLinkage() const; @@ -2071,8 +2166,9 @@ public: } // Iterator access to formal parameters. - typedef MutableArrayRef<ParmVarDecl *>::iterator param_iterator; - typedef ArrayRef<ParmVarDecl *>::const_iterator param_const_iterator; + using param_iterator = MutableArrayRef<ParmVarDecl *>::iterator; + using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator; + bool param_empty() const { return parameters().empty(); } param_iterator param_begin() { return parameters().begin(); } param_iterator param_end() { return parameters().end(); } @@ -2080,9 +2176,9 @@ public: param_const_iterator param_end() const { return parameters().end(); } size_t param_size() const { return parameters().size(); } - /// getNumParams - Return the number of parameters this function must have - /// based on its FunctionType. This is the length of the ParamInfo array - /// after it has been created. + /// Return the number of parameters this function must have based on its + /// FunctionType. This is the length of the ParamInfo array after it has been + /// created. unsigned getNumParams() const; const ParmVarDecl *getParamDecl(unsigned i) const { @@ -2097,10 +2193,9 @@ public: setParams(getASTContext(), NewParamInfo); } - /// getMinRequiredArguments - Returns the minimum number of arguments - /// needed to call this function. This may be fewer than the number of - /// function parameters, if some of the parameters have default - /// arguments (in C++). + /// Returns the minimum number of arguments needed to call this function. This + /// may be fewer than the number of function parameters, if some of the + /// parameters have default arguments (in C++). unsigned getMinRequiredArguments() const; QualType getReturnType() const { @@ -2355,18 +2450,14 @@ public: static FunctionDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; - /// FieldDecl - An instance of this class is created by Sema::ActOnField to /// represent a member of a struct/union/class. class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { - // FIXME: This can be packed into the bitfields in Decl. + unsigned BitField : 1; unsigned Mutable : 1; - mutable unsigned CachedFieldIndex : 31; + mutable unsigned CachedFieldIndex : 30; /// The kinds of value we can store in InitializerOrBitWidth. /// @@ -2376,7 +2467,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { /// If the pointer is null, there's nothing special. Otherwise, /// this is a bitfield and the pointer is the Expr* storing the /// bit-width. - ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit, + ISK_NoInit = (unsigned) ICIS_NoInit, /// The pointer is an (optional due to delayed parsing) Expr* /// holding the copy-initializer. @@ -2391,30 +2482,40 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { ISK_CapturedVLAType, }; - /// \brief Storage for either the bit-width, the in-class - /// initializer, or the captured variable length array bound. - /// - /// We can safely combine these because in-class initializers are - /// not permitted for bit-fields, and both are exclusive with VLA - /// captures. + /// If this is a bitfield with a default member initializer, this + /// structure is used to represent the two expressions. + struct InitAndBitWidth { + Expr *Init; + Expr *BitWidth; + }; + + /// \brief 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 /// ISK_InClassListInit, but the initializer is null, then this - /// field has an in-class initializer which has not yet been parsed + /// field has an in-class initializer that has not yet been parsed /// and attached. + // FIXME: Tail-allocate this to reduce the size of FieldDecl in the + // overwhelmingly common case that we have none of these things. llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage; + protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), - Mutable(Mutable), CachedFieldIndex(0), - InitStorage(BW, (InitStorageKind) InitStyle) { - assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield"); + BitField(false), Mutable(Mutable), CachedFieldIndex(0), + InitStorage(nullptr, (InitStorageKind) InitStyle) { + if (BW) + setBitWidth(BW); } public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static FieldDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, @@ -2431,10 +2532,7 @@ public: bool isMutable() const { return Mutable; } /// \brief Determines whether this field is a bitfield. - bool isBitField() const { - return InitStorage.getInt() == ISK_BitWidthOrNothing && - InitStorage.getPointer() != nullptr; - } + bool isBitField() const { return BitField; } /// @brief Determines whether this is an unnamed bitfield. bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); } @@ -2446,66 +2544,77 @@ public: bool isAnonymousStructOrUnion() const; Expr *getBitWidth() const { - return isBitField() - ? static_cast<Expr *>(InitStorage.getPointer()) - : nullptr; + if (!BitField) + return nullptr; + void *Ptr = InitStorage.getPointer(); + if (getInClassInitStyle()) + return static_cast<InitAndBitWidth*>(Ptr)->BitWidth; + return static_cast<Expr*>(Ptr); } + unsigned getBitWidthValue(const ASTContext &Ctx) const; /// setBitWidth - Set the bit-field width for this member. // Note: used by some clients (i.e., do not remove it). void setBitWidth(Expr *Width) { - assert(InitStorage.getInt() == ISK_BitWidthOrNothing && - InitStorage.getPointer() == nullptr && - "bit width, initializer or captured type already set"); - InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing); + assert(!hasCapturedVLAType() && !BitField && + "bit width or captured type already set"); + assert(Width && "no bit width specified"); + InitStorage.setPointer( + InitStorage.getInt() + ? new (getASTContext()) + InitAndBitWidth{getInClassInitializer(), Width} + : static_cast<void*>(Width)); + BitField = true; } /// removeBitWidth - Remove the bit-field width from this member. // Note: used by some clients (i.e., do not remove it). void removeBitWidth() { assert(isBitField() && "no bitfield width to remove"); - InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); + InitStorage.setPointer(getInClassInitializer()); + BitField = false; } - /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which - /// this field has. + /// Get the kind of (C++11) default member initializer that this field has. InClassInitStyle getInClassInitStyle() const { InitStorageKind storageKind = InitStorage.getInt(); return (storageKind == ISK_CapturedVLAType ? ICIS_NoInit : (InClassInitStyle) storageKind); } - /// hasInClassInitializer - Determine whether this member has a C++11 in-class - /// initializer. + /// Determine whether this member has a C++11 default member initializer. bool hasInClassInitializer() const { return getInClassInitStyle() != ICIS_NoInit; } - /// getInClassInitializer - Get the C++11 in-class initializer for this - /// member, or null if one has not been set. If a valid declaration has an - /// in-class initializer, but this returns null, then we have not parsed and - /// attached it yet. + /// Get the C++11 default member initializer for this member, or null if one + /// has not been set. If a valid declaration has a default member initializer, + /// but this returns null, then we have not parsed and attached it yet. Expr *getInClassInitializer() const { - return hasInClassInitializer() - ? static_cast<Expr *>(InitStorage.getPointer()) - : nullptr; + if (!hasInClassInitializer()) + return nullptr; + void *Ptr = InitStorage.getPointer(); + if (BitField) + return static_cast<InitAndBitWidth*>(Ptr)->Init; + return static_cast<Expr*>(Ptr); } /// setInClassInitializer - Set the C++11 in-class initializer for this /// member. void setInClassInitializer(Expr *Init) { - assert(hasInClassInitializer() && - InitStorage.getPointer() == nullptr && - "bit width, initializer or captured type already set"); - InitStorage.setPointer(Init); + assert(hasInClassInitializer() && !getInClassInitializer()); + if (BitField) + static_cast<InitAndBitWidth*>(InitStorage.getPointer())->Init = Init; + else + InitStorage.setPointer(Init); } /// removeInClassInitializer - Remove the C++11 in-class initializer from this /// member. void removeInClassInitializer() { assert(hasInClassInitializer() && "no initializer to remove"); - InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); + InitStorage.setPointerAndInt(getBitWidth(), ISK_NoInit); } /// \brief Determine whether this member captures the variable length array @@ -2520,6 +2629,7 @@ public: InitStorage.getPointer()) : nullptr; } + /// \brief Set the captured variable length array type for this field. void setCapturedVLAType(const VariableArrayType *VLAType); @@ -2542,9 +2652,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// EnumConstantDecl - An instance of this object exists for each enum constant @@ -2554,6 +2661,7 @@ public: class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> { Stmt *Init; // an integer constant expression llvm::APSInt Val; // The value. + protected: EnumConstantDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, @@ -2561,6 +2669,7 @@ protected: : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} public: + friend class StmtIteratorBase; static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, SourceLocation L, IdentifierInfo *Id, @@ -2584,8 +2693,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == EnumConstant; } - - friend class StmtIteratorBase; }; /// IndirectFieldDecl - An instance of this class is created to represent a @@ -2593,7 +2700,6 @@ public: /// IndirectFieldDecl are always implicit. class IndirectFieldDecl : public ValueDecl, public Mergeable<IndirectFieldDecl> { - void anchor() override; NamedDecl **Chaining; unsigned ChainingSize; @@ -2601,14 +2707,18 @@ class IndirectFieldDecl : public ValueDecl, DeclarationName N, QualType T, MutableArrayRef<NamedDecl *> CH); + void anchor() override; + public: + friend class ASTDeclReader; + static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, llvm::MutableArrayRef<NamedDecl *> CH); static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); - typedef ArrayRef<NamedDecl *>::const_iterator chain_iterator; + using chain_iterator = ArrayRef<NamedDecl *>::const_iterator; ArrayRef<NamedDecl *> chain() const { return llvm::makeArrayRef(Chaining, ChainingSize); @@ -2634,26 +2744,27 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == IndirectField; } - friend class ASTDeclReader; }; /// TypeDecl - Represents a declaration of a type. -/// class TypeDecl : public NamedDecl { - void anchor() override; + friend class ASTContext; + /// TypeForDecl - 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; + mutable const Type *TypeForDecl = nullptr; + /// LocStart - The start of the source range for this declaration. SourceLocation LocStart; - friend class ASTContext; + + void anchor() override; protected: TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation StartL = SourceLocation()) - : NamedDecl(DK, DC, L, Id), TypeForDecl(nullptr), LocStart(StartL) {} + : NamedDecl(DK, DC, L, Id), LocStart(StartL) {} public: // Low-level accessor. If you just want the type defined by this node, @@ -2677,18 +2788,18 @@ public: static bool classofKind(Kind K) { return K >= firstType && K <= lastType; } }; - /// Base class for declarations which introduce a typedef-name. class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { - void anchor() override; - typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo; - llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo; + using ModedTInfo = std::pair<TypeSourceInfo *, QualType>; + llvm::PointerUnion<TypeSourceInfo *, ModedTInfo *> MaybeModedTInfo; // 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; + void anchor() override; + protected: TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -2696,20 +2807,24 @@ protected: : TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C), MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {} - typedef Redeclarable<TypedefNameDecl> redeclarable_base; + using redeclarable_base = Redeclarable<TypedefNameDecl>; + TypedefNameDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + TypedefNameDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + TypedefNameDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -2724,14 +2839,17 @@ public: ? MaybeModedTInfo.get<ModedTInfo*>()->first : MaybeModedTInfo.get<TypeSourceInfo*>(); } + QualType getUnderlyingType() const { return isModed() ? MaybeModedTInfo.get<ModedTInfo*>()->second : MaybeModedTInfo.get<TypeSourceInfo*>()->getType(); } + void setTypeSourceInfo(TypeSourceInfo *newType) { MaybeModedTInfo = newType; } + void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) { MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy); } @@ -2817,7 +2935,7 @@ class TagDecl : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> { public: // This is really ugly. - typedef TagTypeKind TagKind; + using TagKind = TagTypeKind; private: // FIXME: This can be packed into the bitfields in Decl. @@ -2850,6 +2968,7 @@ protected: /// IsScoped - 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, /// 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 @@ -2869,12 +2988,13 @@ protected: /// Has the full definition of this type been required by a use somewhere in /// the TU. unsigned IsCompleteDefinitionRequired : 1; + private: SourceRange BraceRange; // A struct representing syntactic qualifier info, // to be used for the (uncommon) case of out-of-line declarations. - typedef QualifierInfo ExtInfo; + using ExtInfo = QualifierInfo; /// \brief If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); @@ -2906,13 +3026,16 @@ protected: setPreviousDecl(PrevDecl); } - typedef Redeclarable<TagDecl> redeclarable_base; + using redeclarable_base = Redeclarable<TagDecl>; + TagDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + TagDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + TagDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -2923,8 +3046,12 @@ protected: void completeDefinition(); public: - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + friend class ASTDeclReader; + friend class ASTDeclWriter; + + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -3074,10 +3201,12 @@ public: unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; } + TemplateParameterList *getTemplateParameterList(unsigned i) const { assert(i < getNumTemplateParameterLists()); return getExtInfo()->TemplParamLists[i]; } + void setTemplateParameterListsInfo(ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists); @@ -3088,19 +3217,16 @@ public: static DeclContext *castToDeclContext(const TagDecl *D) { return static_cast<DeclContext *>(const_cast<TagDecl*>(D)); } + static TagDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// EnumDecl - 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 { - void anchor() override; /// IntegerType - 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. @@ -3115,8 +3241,7 @@ class EnumDecl : public TagDecl { /// The underlying type of an enumeration never has any qualifiers, so /// we can get away with just storing a raw Type*, and thus save an /// extra pointer when TypeSourceInfo is needed. - - llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType; + llvm::PointerUnion<const Type *, TypeSourceInfo *> IntegerType; /// PromotionType - The integer type that values of this type should /// promote to. In C, enumerators are generally of an integer type @@ -3127,13 +3252,12 @@ class EnumDecl : public TagDecl { /// \brief If this enumeration is an instantiation of a member enumeration /// of a class template specialization, this is the member specialization /// information. - MemberSpecializationInfo *SpecializationInfo; + MemberSpecializationInfo *SpecializationInfo = nullptr; EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) - : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc), - SpecializationInfo(nullptr) { + : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) { assert(Scoped || !ScopedUsingClassTag); IntegerType = (const Type *)nullptr; NumNegativeBits = 0; @@ -3143,9 +3267,13 @@ class EnumDecl : public TagDecl { IsFixed = Fixed; } + void anchor() override; + void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, TemplateSpecializationKind TSK); public: + friend class ASTDeclReader; + EnumDecl *getCanonicalDecl() override { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); } @@ -3191,9 +3319,9 @@ public: // enumerator_iterator - Iterates through the enumerators of this // enumeration. - typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; - typedef llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>> - enumerator_range; + using enumerator_iterator = specific_decl_iterator<EnumConstantDecl>; + using enumerator_range = + llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>>; enumerator_range enumerators() const { return enumerator_range(enumerator_begin(), enumerator_end()); @@ -3341,17 +3469,15 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Enum; } - - friend class ASTDeclReader; }; - /// RecordDecl - 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 { + friend class DeclContext; + // FIXME: This can be packed into the bitfields in Decl. /// HasFlexibleArrayMember - 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. @@ -3375,7 +3501,6 @@ class RecordDecl : public TagDecl { /// methods/nested types we allow deserialization of just the fields /// when needed. mutable bool LoadedFieldsFromExternalStorage : 1; - friend class DeclContext; protected: RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, @@ -3458,6 +3583,7 @@ public: /// \brief Determine whether this record is a record for captured variables in /// CapturedStmt construct. bool isCapturedRecord() const; + /// \brief Mark the record as a record for captured variables in CapturedStmt /// construct. void setCapturedRecord(); @@ -3477,8 +3603,8 @@ public: // Iterator access to field members. The field iterator only visits // the non-static data members of this class, ignoring any static // data members, functions, constructors, destructors, etc. - typedef specific_decl_iterator<FieldDecl> field_iterator; - typedef llvm::iterator_range<specific_decl_iterator<FieldDecl>> field_range; + using field_iterator = specific_decl_iterator<FieldDecl>; + using field_range = llvm::iterator_range<specific_decl_iterator<FieldDecl>>; field_range fields() const { return field_range(field_begin(), field_end()); } field_iterator field_begin() const; @@ -3502,7 +3628,7 @@ public: return K >= firstRecord && K <= lastRecord; } - /// isMsStrust - Get whether or not this is an ms_struct which can + /// \brief 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; @@ -3522,12 +3648,15 @@ private: }; class FileScopeAsmDecl : public Decl { - virtual void anchor(); StringLiteral *AsmString; SourceLocation RParenLoc; + FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring, SourceLocation StartL, SourceLocation EndL) : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {} + + virtual void anchor(); + public: static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, StringLiteral *Str, SourceLocation AsmLoc, @@ -3553,7 +3682,6 @@ public: /// BlockDecl - This represents 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 { public: /// A class which contains all the information about a particular @@ -3600,29 +3728,27 @@ private: bool CapturesCXXThis : 1; bool BlockMissingReturnType : 1; bool IsConversionFromLambda : 1; + /// ParamInfo - 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; - unsigned NumParams; + ParmVarDecl **ParamInfo = nullptr; + unsigned NumParams = 0; - Stmt *Body; - TypeSourceInfo *SignatureAsWritten; + Stmt *Body = nullptr; + TypeSourceInfo *SignatureAsWritten = nullptr; - const Capture *Captures; - unsigned NumCaptures; + const Capture *Captures = nullptr; + unsigned NumCaptures = 0; - unsigned ManglingNumber; - Decl *ManglingContextDecl; + unsigned ManglingNumber = 0; + Decl *ManglingContextDecl = nullptr; protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) - : Decl(Block, DC, CaretLoc), DeclContext(Block), - IsVariadic(false), CapturesCXXThis(false), - BlockMissingReturnType(true), IsConversionFromLambda(false), - ParamInfo(nullptr), NumParams(0), Body(nullptr), - SignatureAsWritten(nullptr), Captures(nullptr), NumCaptures(0), - ManglingNumber(0), ManglingContextDecl(nullptr) {} + : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false), + CapturesCXXThis(false), BlockMissingReturnType(true), + IsConversionFromLambda(false) {} public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); @@ -3649,8 +3775,9 @@ public: } // Iterator access to formal parameters. - typedef MutableArrayRef<ParmVarDecl *>::iterator param_iterator; - typedef ArrayRef<ParmVarDecl *>::const_iterator param_const_iterator; + using param_iterator = MutableArrayRef<ParmVarDecl *>::iterator; + using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator; + bool param_empty() const { return parameters().empty(); } param_iterator param_begin() { return parameters().begin(); } param_iterator param_end() { return parameters().end(); } @@ -3659,6 +3786,7 @@ public: size_t param_size() const { return parameters().size(); } unsigned getNumParams() const { return NumParams; } + const ParmVarDecl *getParamDecl(unsigned i) const { assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; @@ -3667,6 +3795,7 @@ public: assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } + void setParams(ArrayRef<ParmVarDecl *> NewParamInfo); /// hasCaptures - True if this block (or its nested blocks) captures @@ -3677,7 +3806,7 @@ public: /// Does not include an entry for 'this'. unsigned getNumCaptures() const { return NumCaptures; } - typedef ArrayRef<Capture>::const_iterator capture_const_iterator; + using capture_const_iterator = ArrayRef<Capture>::const_iterator; ArrayRef<Capture> captures() const { return {Captures, NumCaptures}; } @@ -3699,6 +3828,7 @@ public: unsigned getBlockManglingNumber() const { return ManglingNumber; } + Decl *getBlockManglingContextDecl() const { return ManglingContextDecl; } @@ -3735,8 +3865,10 @@ protected: private: /// \brief The number of parameters to the outlined function. unsigned NumParams; + /// \brief The position of context parameter in list of parameters. unsigned ContextParam; + /// \brief The body of the outlined function. llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow; @@ -3751,6 +3883,10 @@ private: } public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend TrailingObjects; + static CapturedDecl *Create(ASTContext &C, DeclContext *DC, unsigned NumParams); static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID, @@ -3793,8 +3929,8 @@ public: } unsigned getContextParamPosition() const { return ContextParam; } - typedef ImplicitParamDecl *const *param_iterator; - typedef llvm::iterator_range<param_iterator> param_range; + using param_iterator = ImplicitParamDecl *const *; + using param_range = llvm::iterator_range<param_iterator>; /// \brief Retrieve an iterator pointing to the first parameter decl. param_iterator param_begin() const { return getParams(); } @@ -3810,10 +3946,6 @@ public: static CapturedDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<CapturedDecl *>(const_cast<DeclContext *>(DC)); } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend TrailingObjects; }; /// \brief Describes a module import declaration, which makes the contents @@ -3828,6 +3960,11 @@ public: /// \#include/\#import directives. class ImportDecl final : public Decl, llvm::TrailingObjects<ImportDecl, SourceLocation> { + friend class ASTContext; + friend class ASTDeclReader; + friend class ASTReader; + friend TrailingObjects; + /// \brief The imported module, along with a bit that indicates whether /// we have source-location information for each identifier in the module /// name. @@ -3838,20 +3975,15 @@ class ImportDecl final : public Decl, /// \brief The next import in the list of imports local to the translation /// unit being parsed (not loaded from an AST file). - ImportDecl *NextLocalImport; + ImportDecl *NextLocalImport = nullptr; - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTContext; - friend TrailingObjects; - ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs); ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, SourceLocation EndLoc); - ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { } + ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {} public: /// \brief Create a new module import declaration. @@ -3893,15 +4025,16 @@ public: /// \endcode class ExportDecl final : public Decl, public DeclContext { virtual void anchor(); + private: + friend class ASTDeclReader; + /// \brief The source location for the right brace (if valid). SourceLocation RBraceLoc; ExportDecl(DeclContext *DC, SourceLocation ExportLoc) - : Decl(Export, DC, ExportLoc), DeclContext(Export), - RBraceLoc(SourceLocation()) { } - - friend class ASTDeclReader; + : Decl(Export, DC, ExportLoc), DeclContext(Export), + RBraceLoc(SourceLocation()) {} public: static ExportDecl *Create(ASTContext &C, DeclContext *DC, @@ -3936,9 +4069,9 @@ public: /// \brief Represents an empty-declaration. class EmptyDecl : public Decl { + EmptyDecl(DeclContext *DC, SourceLocation L) : Decl(Empty, DC, L) {} + virtual void anchor(); - EmptyDecl(DeclContext *DC, SourceLocation L) - : Decl(Empty, DC, L) { } public: static EmptyDecl *Create(ASTContext &C, DeclContext *DC, @@ -4015,6 +4148,6 @@ inline bool IsEnumDeclScoped(EnumDecl *ED) { return ED->isScoped(); } -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_DECL_H diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 041f0fd484d4..f93c9f0b9aaa 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -1,4 +1,4 @@ -//===-- DeclBase.h - Base Classes for representing declarations -*- C++ -*-===// +//===- DeclBase.h - Base Classes for representing declarations --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,33 +16,40 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" +#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" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <iterator> +#include <string> +#include <type_traits> +#include <utility> namespace clang { + +class ASTContext; class ASTMutationListener; -class BlockDecl; -class CXXRecordDecl; -class CompoundStmt; +class Attr; class DeclContext; -class DeclarationName; -class DependentDiagnostic; -class EnumDecl; -class ExportDecl; class ExternalSourceSymbolAttr; class FunctionDecl; class FunctionType; +class IdentifierInfo; enum Linkage : unsigned char; -class LinkageComputer; class LinkageSpecDecl; class Module; class NamedDecl; -class NamespaceDecl; class ObjCCategoryDecl; class ObjCCategoryImplDecl; class ObjCContainerDecl; @@ -53,23 +60,21 @@ class ObjCMethodDecl; class ObjCProtocolDecl; struct PrintingPolicy; class RecordDecl; +class SourceManager; class Stmt; class StoredDeclsMap; class TemplateDecl; class TranslationUnitDecl; class UsingDirectiveDecl; -} - -namespace clang { - /// \brief Captures the result of checking the availability of a - /// declaration. - enum AvailabilityResult { - AR_Available = 0, - AR_NotYetIntroduced, - AR_Deprecated, - AR_Unavailable - }; +/// \brief Captures the result of checking the availability of a +/// declaration. +enum AvailabilityResult { + AR_Available = 0, + AR_NotYetIntroduced, + AR_Deprecated, + AR_Unavailable +}; /// Decl - This represents one declaration (or definition), e.g. a variable, /// typedef, function, struct, etc. @@ -94,7 +99,7 @@ public: /// \brief 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 { }; + struct EmptyShell {}; /// IdentifierNamespace - The different namespaces in which /// declarations may appear. According to C99 6.2.3, there are @@ -208,15 +213,18 @@ public: enum class ModuleOwnershipKind : unsigned { /// This declaration is not owned by a module. Unowned, + /// This declaration has an owning module, but is globally visible /// (typically because its owning module is visible and we know that /// modules cannot later become hidden in this compilation). /// After serialization and deserialization, this will be converted /// to VisibleWhenImported. Visible, + /// This declaration has an owning module, and is visible when that /// module is imported. VisibleWhenImported, + /// This declaration has an owning module, but is only visible to /// lookups that occur within that module. ModulePrivate @@ -238,7 +246,6 @@ private: DeclContext *LexicalDC; }; - /// DeclCtx - Holds either a DeclContext* or a MultipleDC*. /// For declarations that don't contain C++ scope specifiers, it contains /// the DeclContext where the Decl was declared. @@ -254,12 +261,14 @@ private: /// // LexicalDC == global namespace llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx; - inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); } - inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); } - inline MultipleDC *getMultipleDC() const { + bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); } + bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); } + + MultipleDC *getMultipleDC() const { return DeclCtx.get<MultipleDC*>(); } - inline DeclContext *getSemanticDC() const { + + DeclContext *getSemanticDC() const { return DeclCtx.get<DeclContext*>(); } @@ -298,10 +307,16 @@ private: static bool StatisticsEnabled; protected: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend class ASTReader; + friend class CXXClassMemberWrapper; + friend class LinkageComputer; + template<typename decl_type> friend class Redeclarable; + /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum unsigned Access : 2; - friend class CXXClassMemberWrapper; /// \brief Whether this declaration was loaded from an AST file. unsigned FromASTFile : 1; @@ -313,13 +328,6 @@ protected: /// Otherwise, it is the linkage + 1. mutable unsigned CacheValidAndLinkage : 3; - friend class ASTDeclWriter; - friend class ASTDeclReader; - friend class ASTReader; - friend class LinkageComputer; - - template<typename decl_type> friend class Redeclarable; - /// \brief Allocate memory for a deserialized declaration. /// /// This routine must be used to allocate memory for any declaration that is @@ -357,7 +365,7 @@ private: protected: Decl(Kind DK, DeclContext *DC, SourceLocation L) : NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)), - DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), + DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false), Used(false), Referenced(false), TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), @@ -366,9 +374,9 @@ protected: } Decl(Kind DK, EmptyShell Empty) - : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false), - Implicit(false), Used(false), Referenced(false), - TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), + : DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false), + Used(false), Referenced(false), TopLevelDeclInObjCContainer(false), + Access(AS_none), FromASTFile(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); @@ -392,14 +400,15 @@ protected: } public: - /// \brief Source range that this declaration covers. virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocation(), getLocation()); } + SourceLocation getLocStart() const LLVM_READONLY { return getSourceRange().getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getSourceRange().getEnd(); } @@ -460,12 +469,15 @@ public: } bool hasAttrs() const { return HasAttrs; } + void setAttrs(const AttrVec& Attrs) { return setAttrsImpl(Attrs, getASTContext()); } + AttrVec &getAttrs() { return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); } + const AttrVec &getAttrs() const; void dropAttrs(); @@ -476,8 +488,8 @@ public: setAttrs(AttrVec(1, A)); } - typedef AttrVec::const_iterator attr_iterator; - typedef llvm::iterator_range<attr_iterator> attr_range; + using attr_iterator = AttrVec::const_iterator; + using attr_range = llvm::iterator_range<attr_iterator>; attr_range attrs() const { return attr_range(attr_begin(), attr_end()); @@ -510,6 +522,7 @@ public: specific_attr_iterator<T> specific_attr_begin() const { return specific_attr_iterator<T>(attr_begin()); } + template <typename T> specific_attr_iterator<T> specific_attr_end() const { return specific_attr_iterator<T>(attr_end()); @@ -518,6 +531,7 @@ public: template<typename T> T *getAttr() const { return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : nullptr; } + template<typename T> bool hasAttr() const { return hasAttrs() && hasSpecificAttr<T>(getAttrs()); } @@ -616,7 +630,6 @@ protected: } public: - /// \brief Determine the availability of the given declaration. /// /// This routine will determine the most restrictive availability of @@ -698,6 +711,7 @@ public: private: Module *getOwningModuleSlow() const; + protected: bool hasLocalOwningModuleStorage() const; @@ -733,11 +747,18 @@ public: return getModuleOwnershipKind() != ModuleOwnershipKind::Unowned; } - /// Get the module that owns this declaration. + /// Get the module that owns this declaration (for visibility purposes). Module *getOwningModule() const { return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule(); } + /// Get the module that owns this declaration for linkage purposes. + /// There only ever is such a module under the C++ Modules TS. + /// + /// \param IgnoreLinkage Ignore the linkage of the entity; assume that + /// 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 /// lookup. Note that the declaration might be visible even if this returns /// \c false, if the owning module is visible within the query context. @@ -770,14 +791,17 @@ public: unsigned getIdentifierNamespace() const { return IdentifierNamespace; } + bool isInIdentifierNamespace(unsigned NS) const { return getIdentifierNamespace() & NS; } + static unsigned getIdentifierNamespaceForKind(Kind DK); bool hasTagIdentifierNamespace() const { return isTagIdentifierNamespace(getIdentifierNamespace()); } + static bool isTagIdentifierNamespace(unsigned NS) { // TagDecls have Tag and Type set and may also have TagFriend. return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type); @@ -865,18 +889,18 @@ public: /// \brief Iterates through all the redeclarations of the same decl. class redecl_iterator { /// Current - The current declaration. - Decl *Current; + Decl *Current = nullptr; Decl *Starter; public: - typedef Decl *value_type; - typedef const value_type &reference; - typedef const value_type *pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + using value_type = Decl *; + using reference = const value_type &; + using pointer = const value_type *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; - redecl_iterator() : Current(nullptr) { } - explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { } + redecl_iterator() = default; + explicit redecl_iterator(Decl *C) : Current(C), Starter(C) {} reference operator*() const { return Current; } value_type operator->() const { return Current; } @@ -899,12 +923,13 @@ public: friend bool operator==(redecl_iterator x, redecl_iterator y) { return x.Current == y.Current; } + friend bool operator!=(redecl_iterator x, redecl_iterator y) { return x.Current != y.Current; } }; - typedef llvm::iterator_range<redecl_iterator> redecl_range; + using redecl_range = llvm::iterator_range<redecl_iterator>; /// \brief 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). @@ -915,6 +940,7 @@ public: redecl_iterator redecls_begin() const { return redecl_iterator(const_cast<Decl *>(this)); } + redecl_iterator redecls_end() const { return redecl_iterator(); } /// \brief Retrieve the previous declaration that declares the same entity @@ -1002,13 +1028,15 @@ public: /// declaration, but in the semantic context of the enclosing namespace /// scope. void setLocalExternDecl() { - assert((IdentifierNamespace == IDNS_Ordinary || - IdentifierNamespace == IDNS_OrdinaryFriend) && - "namespace is not ordinary"); - Decl *Prev = getPreviousDecl(); IdentifierNamespace &= ~IDNS_Ordinary; + // It's OK for the declaration to still have the "invisible friend" flag or + // the "conflicts with tag declarations in this scope" flag for the outer + // scope. + assert((IdentifierNamespace & ~(IDNS_OrdinaryFriend | IDNS_Tag)) == 0 && + "namespace is not ordinary"); + IdentifierNamespace |= IDNS_LocalExtern; if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary) IdentifierNamespace |= IDNS_Ordinary; @@ -1094,10 +1122,13 @@ public: static void printGroup(Decl** Begin, unsigned NumDecls, raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); + // Debuggers don't usually respect default arguments. void dump() const; + // Same as dump(), but forces color printing. void dumpColor() const; + void dump(raw_ostream &Out, bool Deserialize = false) const; /// \brief Looks through the Decl's underlying type to extract a FunctionType @@ -1132,10 +1163,11 @@ class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { SourceLocation Loc; SourceManager &SM; const char *Message; + public: PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L, SourceManager &sm, const char *Msg) - : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {} + : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {} void print(raw_ostream &OS) const override; }; @@ -1144,30 +1176,35 @@ public: /// single result (with no stable storage) or a collection of results (with /// stable storage provided by the lookup table). class DeclContextLookupResult { - typedef ArrayRef<NamedDecl *> ResultTy; + using ResultTy = ArrayRef<NamedDecl *>; + ResultTy Result; + // If there is only one lookup result, it would be invalidated by // reallocations of the name table, so store it separately. - NamedDecl *Single; + NamedDecl *Single = nullptr; static NamedDecl *const SingleElementDummyList; public: - DeclContextLookupResult() : Result(), Single() {} + DeclContextLookupResult() = default; DeclContextLookupResult(ArrayRef<NamedDecl *> Result) - : Result(Result), Single() {} + : Result(Result) {} DeclContextLookupResult(NamedDecl *Single) : Result(SingleElementDummyList), Single(Single) {} class iterator; - typedef llvm::iterator_adaptor_base<iterator, ResultTy::iterator, - std::random_access_iterator_tag, - NamedDecl *const> IteratorBase; + + using IteratorBase = + llvm::iterator_adaptor_base<iterator, ResultTy::iterator, + std::random_access_iterator_tag, + NamedDecl *const>; + class iterator : public IteratorBase { value_type SingleElement; public: - iterator() : IteratorBase(), SingleElement() {} + iterator() = default; explicit iterator(pointer Pos, value_type Single = nullptr) : IteratorBase(Pos), SingleElement(Single) {} @@ -1175,9 +1212,10 @@ public: return SingleElement ? SingleElement : IteratorBase::operator*(); } }; - typedef iterator const_iterator; - typedef iterator::pointer pointer; - typedef iterator::reference reference; + + using const_iterator = iterator; + using pointer = iterator::pointer; + using reference = iterator::reference; iterator begin() const { return iterator(Result.begin(), Single); } iterator end() const { return iterator(Result.end(), Single); } @@ -1211,7 +1249,6 @@ public: /// ExportDecl /// BlockDecl /// OMPDeclareReductionDecl -/// class DeclContext { /// DeclKind - This indicates which class this is. unsigned DeclKind : 8; @@ -1251,22 +1288,22 @@ class DeclContext { /// contains an entry for a DeclarationName (and we haven't lazily /// omitted anything), then it contains all relevant entries for that /// name (modulo the hasExternalDecls() flag). - mutable StoredDeclsMap *LookupPtr; + mutable StoredDeclsMap *LookupPtr = nullptr; protected: + friend class ASTDeclReader; + friend class ASTWriter; + friend class ExternalASTSource; + /// FirstDecl - The first declaration stored within this declaration /// context. - mutable Decl *FirstDecl; + mutable Decl *FirstDecl = nullptr; /// LastDecl - The last declaration stored within this declaration /// context. FIXME: We could probably cache this value somewhere /// outside of the DeclContext, to reduce the size of DeclContext by /// another pointer. - mutable Decl *LastDecl; - - friend class ExternalASTSource; - friend class ASTDeclReader; - friend class ASTWriter; + mutable Decl *LastDecl = nullptr; /// \brief Build up a chain of declarations. /// @@ -1279,8 +1316,7 @@ protected: ExternalVisibleStorage(false), NeedToReconcileExternalVisibleStorage(false), HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false), - UseQualifiedLookup(false), - LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {} + UseQualifiedLookup(false) {} public: ~DeclContext(); @@ -1288,6 +1324,7 @@ public: Decl::Kind getDeclKind() const { return static_cast<Decl::Kind>(DeclKind); } + const char *getDeclKindName() const; /// getParent - Returns the containing DeclContext. @@ -1495,19 +1532,20 @@ public: /// within this context. class decl_iterator { /// Current - The current declaration. - Decl *Current; + Decl *Current = nullptr; public: - typedef Decl *value_type; - typedef const value_type &reference; - typedef const value_type *pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + using value_type = Decl *; + using reference = const value_type &; + using pointer = const value_type *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; - decl_iterator() : Current(nullptr) { } - explicit decl_iterator(Decl *C) : Current(C) { } + decl_iterator() = default; + explicit decl_iterator(Decl *C) : Current(C) {} reference operator*() const { return Current; } + // This doesn't meet the iterator requirements, but it's convenient value_type operator->() const { return Current; } @@ -1525,12 +1563,13 @@ public: friend bool operator==(decl_iterator x, decl_iterator y) { return x.Current == y.Current; } + friend bool operator!=(decl_iterator x, decl_iterator y) { return x.Current != y.Current; } }; - typedef llvm::iterator_range<decl_iterator> decl_range; + using decl_range = llvm::iterator_range<decl_iterator>; /// decls_begin/decls_end - Iterate over the declarations stored in /// this context. @@ -1569,16 +1608,16 @@ public: } public: - typedef SpecificDecl *value_type; - // TODO: Add reference and pointer typedefs (with some appropriate proxy - // type) if we ever have a need for them. - typedef void reference; - typedef void pointer; - typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type - difference_type; - typedef std::forward_iterator_tag iterator_category; + using value_type = SpecificDecl *; + // TODO: Add reference and pointer types (with some appropriate proxy type) + // if we ever have a need for them. + using reference = void; + using pointer = void; + using difference_type = + std::iterator_traits<DeclContext::decl_iterator>::difference_type; + using iterator_category = std::forward_iterator_tag; - specific_decl_iterator() : Current() { } + specific_decl_iterator() = default; /// specific_decl_iterator - Construct a new iterator over a /// subset of the declarations the range [C, @@ -1593,6 +1632,7 @@ public: } value_type operator*() const { return cast<SpecificDecl>(*Current); } + // This doesn't meet the iterator requirements, but it's convenient value_type operator->() const { return **this; } @@ -1646,16 +1686,16 @@ public: } public: - typedef SpecificDecl *value_type; - // TODO: Add reference and pointer typedefs (with some appropriate proxy - // type) if we ever have a need for them. - typedef void reference; - typedef void pointer; - typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type - difference_type; - typedef std::forward_iterator_tag iterator_category; + using value_type = SpecificDecl *; + // TODO: Add reference and pointer types (with some appropriate proxy type) + // if we ever have a need for them. + using reference = void; + using pointer = void; + using difference_type = + std::iterator_traits<DeclContext::decl_iterator>::difference_type; + using iterator_category = std::forward_iterator_tag; - filtered_decl_iterator() : Current() { } + filtered_decl_iterator() = default; /// filtered_decl_iterator - Construct a new iterator over a /// subset of the declarations the range [C, @@ -1733,8 +1773,8 @@ public: /// @brief Checks whether a declaration is in this context. bool containsDecl(Decl *D) const; - typedef DeclContextLookupResult lookup_result; - typedef lookup_result::iterator lookup_iterator; + using lookup_result = DeclContextLookupResult; + using lookup_iterator = lookup_result::iterator; /// lookup - Find the declarations (if any) with the given Name in /// this context. Returns a range of iterators that contains all of @@ -1780,7 +1820,7 @@ public: /// of looking up every possible name. class all_lookups_iterator; - typedef llvm::iterator_range<all_lookups_iterator> lookups_range; + using lookups_range = llvm::iterator_range<all_lookups_iterator>; lookups_range lookups() const; lookups_range noload_lookups() const; @@ -1796,21 +1836,26 @@ public: all_lookups_iterator noload_lookups_end() const; struct udir_iterator; - typedef llvm::iterator_adaptor_base<udir_iterator, lookup_iterator, - std::random_access_iterator_tag, - UsingDirectiveDecl *> udir_iterator_base; + + using udir_iterator_base = + llvm::iterator_adaptor_base<udir_iterator, lookup_iterator, + std::random_access_iterator_tag, + UsingDirectiveDecl *>; + struct udir_iterator : udir_iterator_base { udir_iterator(lookup_iterator I) : udir_iterator_base(I) {} + UsingDirectiveDecl *operator*() const; }; - typedef llvm::iterator_range<udir_iterator> udir_range; + using udir_range = llvm::iterator_range<udir_iterator>; udir_range using_directives() const; // These are all defined in DependentDiagnostic.h. class ddiag_iterator; - typedef llvm::iterator_range<DeclContext::ddiag_iterator> ddiag_range; + + using ddiag_range = llvm::iterator_range<DeclContext::ddiag_iterator>; inline ddiag_range ddiags() const; @@ -1883,6 +1928,8 @@ public: bool Deserialize = false) const; private: + friend class DependentDiagnostic; + void reconcileExternalVisibleStorage() const; bool LoadLexicalDeclsFromExternalStorage() const; @@ -1894,7 +1941,6 @@ private: /// use of addDeclInternal(). void makeDeclVisibleInContextInternal(NamedDecl *D); - friend class DependentDiagnostic; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; void buildLookupImpl(DeclContext *DCtx, bool Internal); @@ -1933,8 +1979,7 @@ struct cast_convert_decl_context<ToTy, true> { } }; - -} // end clang. +} // namespace clang namespace llvm { @@ -1954,12 +1999,14 @@ struct cast_convert_val<ToTy, return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); } }; + template<class ToTy> struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> { static ToTy &doit(::clang::DeclContext &Val) { return *::clang::cast_convert_decl_context<ToTy>::doit(&Val); } }; + template<class ToTy> struct cast_convert_val<ToTy, const ::clang::DeclContext*, const ::clang::DeclContext*> { @@ -1967,6 +2014,7 @@ struct cast_convert_val<ToTy, return ::clang::cast_convert_decl_context<ToTy>::doit(Val); } }; + template<class ToTy> struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> { static ToTy *doit(::clang::DeclContext *Val) { @@ -2003,6 +2051,6 @@ struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> { } }; -} // end namespace llvm +} // namespace llvm -#endif +#endif // LLVM_CLANG_AST_DECLBASE_H diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 2f735c5506c4..88dc9a655917 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1,4 +1,4 @@ -//===-- DeclCXX.h - Classes for representing C++ declarations -*- C++ -*-=====// +//===- DeclCXX.h - Classes for representing C++ declarations --*- C++ -*-=====// // // The LLVM Compiler Infrastructure // @@ -6,11 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the C++ Decl subclasses, other than those for templates /// (found in DeclTemplate.h) and friends (in DeclFriend.h). -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_DECLCXX_H @@ -20,29 +20,56 @@ #include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExternalASTSource.h" #include "clang/AST/LambdaCapture.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Redeclarable.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <memory> +#include <vector> namespace clang { class ClassTemplateDecl; -class ClassTemplateSpecializationDecl; class ConstructorUsingShadowDecl; class CXXBasePath; class CXXBasePaths; class CXXConstructorDecl; -class CXXConversionDecl; class CXXDestructorDecl; -class CXXMethodDecl; -class CXXRecordDecl; -class CXXMemberLookupCriteria; class CXXFinalOverriderMap; class CXXIndirectPrimaryBaseSet; +class CXXMethodDecl; +class DiagnosticBuilder; class FriendDecl; -class LambdaExpr; +class FunctionTemplateDecl; +class IdentifierInfo; +class MemberSpecializationInfo; +class TemplateDecl; +class TemplateParameterList; class UsingDecl; /// \brief Represents any kind of function declaration, whether it is a @@ -50,10 +77,10 @@ class UsingDecl; class AnyFunctionDecl { NamedDecl *Function; - AnyFunctionDecl(NamedDecl *ND) : Function(ND) { } + AnyFunctionDecl(NamedDecl *ND) : Function(ND) {} public: - AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { } + AnyFunctionDecl(FunctionDecl *FD) : Function(FD) {} AnyFunctionDecl(FunctionTemplateDecl *FTD); /// \brief Implicily converts any function or function template into a @@ -68,17 +95,18 @@ public: } }; -} // end namespace clang +} // namespace clang namespace llvm { + // Provide PointerLikeTypeTraits for non-cvr pointers. template<> - class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { - public: - static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) { + struct PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { + static void *getAsVoidPointer(::clang::AnyFunctionDecl F) { return F.get(); } - static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) { + + static ::clang::AnyFunctionDecl getFromVoidPointer(void *P) { return ::clang::AnyFunctionDecl::getFromNamedDecl( static_cast< ::clang::NamedDecl*>(P)); } @@ -86,7 +114,7 @@ namespace llvm { enum { NumLowBitsAvailable = 2 }; }; -} // end namespace llvm +} // namespace llvm namespace clang { @@ -101,7 +129,6 @@ 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 { - virtual void anchor(); /// \brief The location of the ':'. SourceLocation ColonLoc; @@ -110,16 +137,21 @@ class AccessSpecDecl : public Decl { : Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) { setAccess(AS); } - AccessSpecDecl(EmptyShell Empty) - : Decl(AccessSpec, Empty) { } + + AccessSpecDecl(EmptyShell Empty) : Decl(AccessSpec, Empty) {} + + virtual void anchor(); + public: /// \brief The location of the access specifier. SourceLocation getAccessSpecifierLoc() const { return getLocation(); } + /// \brief Sets the location of the access specifier. void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); } /// \brief The location of the colon following the access specifier. SourceLocation getColonLoc() const { return ColonLoc; } + /// \brief Sets the location of the colon. void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; } @@ -132,6 +164,7 @@ public: SourceLocation ColonLoc) { return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); } + static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); // Implement isa/cast/dyncast/etc. @@ -191,12 +224,11 @@ class CXXBaseSpecifier { TypeSourceInfo *BaseTypeInfo; public: - CXXBaseSpecifier() { } - + CXXBaseSpecifier() = default; CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, TypeSourceInfo *TInfo, SourceLocation EllipsisLoc) : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC), - Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { } + Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) {} /// \brief Retrieves the source range that contains the entire base specifier. SourceRange getSourceRange() const LLVM_READONLY { return Range; } @@ -265,7 +297,16 @@ public: /// \brief Represents a C++ struct/union/class. class CXXRecordDecl : public RecordDecl { + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend class ASTNodeImporter; + friend class ASTReader; + friend class ASTRecordWriter; + friend class ASTWriter; + friend class DeclContext; + friend class LambdaExpr; + friend void FunctionDecl::setPure(bool); friend void TagDecl::startDefinition(); /// Values used in DefinitionData fields to represent special members. @@ -280,8 +321,6 @@ class CXXRecordDecl : public RecordDecl { }; struct DefinitionData { - DefinitionData(CXXRecordDecl *D); - /// \brief True if this class has any user-declared constructors. unsigned UserDeclaredConstructor : 1; @@ -475,13 +514,13 @@ class CXXRecordDecl : public RecordDecl { unsigned HasODRHash : 1; /// \brief A hash of parts of the class to help in ODR checking. - unsigned ODRHash; + unsigned ODRHash = 0; /// \brief The number of base class specifiers in Bases. - unsigned NumBases; + unsigned NumBases = 0; /// \brief The number of virtual base class specifiers in VBases. - unsigned NumVBases; + unsigned NumVBases = 0; /// \brief Base classes of this class. /// @@ -513,6 +552,8 @@ class CXXRecordDecl : public RecordDecl { /// This is actually currently stored in reverse order. LazyDeclPtr FirstFriend; + DefinitionData(CXXRecordDecl *D); + /// \brief Retrieve the set of direct base classes. CXXBaseSpecifier *getBases() const { if (!Bases.isOffset()) @@ -530,6 +571,7 @@ class CXXRecordDecl : public RecordDecl { ArrayRef<CXXBaseSpecifier> bases() const { return llvm::makeArrayRef(getBases(), NumBases); } + ArrayRef<CXXBaseSpecifier> vbases() const { return llvm::makeArrayRef(getVBases(), NumVBases); } @@ -543,22 +585,7 @@ class CXXRecordDecl : public RecordDecl { /// \brief Describes a C++ closure type (generated by a lambda expression). struct LambdaDefinitionData : public DefinitionData { - typedef LambdaCapture Capture; - - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, - bool Dependent, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) - : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), - CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), - ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr), - MethodTyInfo(Info) { - IsLambda = true; - - // C++1z [expr.prim.lambda]p4: - // This class type is not an aggregate type. - Aggregate = false; - PlainOldData = false; - } + using Capture = LambdaCapture; /// \brief Whether this lambda is known to be dependent, even if its /// context isn't dependent. @@ -584,7 +611,7 @@ class CXXRecordDecl : public RecordDecl { /// \brief The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. - unsigned ManglingNumber; + unsigned ManglingNumber = 0; /// \brief The declaration that provides context for this lambda, if the /// actual DeclContext does not suffice. This is used for lambdas that @@ -594,11 +621,24 @@ class CXXRecordDecl : public RecordDecl { /// \brief The list of captures, both explicit and implicit, for this /// lambda. - Capture *Captures; + Capture *Captures = nullptr; /// \brief The type of the call method. TypeSourceInfo *MethodTyInfo; - + + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, + bool Dependent, bool IsGeneric, + LambdaCaptureDefault CaptureDefault) + : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), + CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), + MethodTyInfo(Info) { + IsLambda = true; + + // C++1z [expr.prim.lambda]p4: + // This class type is not an aggregate type. + Aggregate = false; + PlainOldData = false; + } }; struct DefinitionData *dataPtr() const { @@ -630,11 +670,8 @@ class CXXRecordDecl : public RecordDecl { /// classes of class template specializations, this will be the /// MemberSpecializationInfo referring to the member class that was /// instantiated or specialized. - llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*> - TemplateOrInstantiation; - - friend class DeclContext; - friend class LambdaExpr; + llvm::PointerUnion<ClassTemplateDecl *, MemberSpecializationInfo *> + TemplateOrInstantiation; /// \brief 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. @@ -648,9 +685,6 @@ class CXXRecordDecl : public RecordDecl { void addedMember(Decl *D); void markedVirtualFunctionPure(); - friend void FunctionDecl::setPure(bool); - - friend class ASTNodeImporter; /// \brief Get the head of our list of friend declarations, possibly /// deserializing the friends from an external AST source. @@ -663,14 +697,15 @@ protected: public: /// \brief Iterator that traverses the base classes of a class. - typedef CXXBaseSpecifier* base_class_iterator; + using base_class_iterator = CXXBaseSpecifier *; /// \brief Iterator that traverses the base classes of a class. - typedef const CXXBaseSpecifier* base_class_const_iterator; + using base_class_const_iterator = const CXXBaseSpecifier *; CXXRecordDecl *getCanonicalDecl() override { return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); } + const CXXRecordDecl *getCanonicalDecl() const { return const_cast<CXXRecordDecl*>(this)->getCanonicalDecl(); } @@ -679,6 +714,7 @@ public: return cast_or_null<CXXRecordDecl>( static_cast<RecordDecl *>(this)->getPreviousDecl()); } + const CXXRecordDecl *getPreviousDecl() const { return const_cast<CXXRecordDecl*>(this)->getPreviousDecl(); } @@ -730,9 +766,9 @@ public: /// \brief Retrieves the number of base classes of this class. unsigned getNumBases() const { return data().NumBases; } - typedef llvm::iterator_range<base_class_iterator> base_class_range; - typedef llvm::iterator_range<base_class_const_iterator> - base_class_const_range; + using base_class_range = llvm::iterator_range<base_class_iterator>; + using base_class_const_range = + llvm::iterator_range<base_class_const_iterator>; base_class_range bases() { return base_class_range(bases_begin(), bases_end()); @@ -772,9 +808,9 @@ public: /// Iterator access to method members. The method iterator visits /// all method members of the class, including non-instance methods, /// special methods, etc. - typedef specific_decl_iterator<CXXMethodDecl> method_iterator; - typedef llvm::iterator_range<specific_decl_iterator<CXXMethodDecl>> - method_range; + using method_iterator = specific_decl_iterator<CXXMethodDecl>; + using method_range = + llvm::iterator_range<specific_decl_iterator<CXXMethodDecl>>; method_range methods() const { return method_range(method_begin(), method_end()); @@ -785,21 +821,23 @@ public: method_iterator method_begin() const { return method_iterator(decls_begin()); } + /// \brief Method past-the-end iterator. method_iterator method_end() const { return method_iterator(decls_end()); } /// Iterator access to constructor members. - typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator; - typedef llvm::iterator_range<specific_decl_iterator<CXXConstructorDecl>> - ctor_range; + using ctor_iterator = specific_decl_iterator<CXXConstructorDecl>; + using ctor_range = + llvm::iterator_range<specific_decl_iterator<CXXConstructorDecl>>; ctor_range ctors() const { return ctor_range(ctor_begin(), ctor_end()); } ctor_iterator ctor_begin() const { return ctor_iterator(decls_begin()); } + ctor_iterator ctor_end() const { return ctor_iterator(decls_end()); } @@ -807,7 +845,7 @@ public: /// An iterator over friend declarations. All of these are defined /// in DeclFriend.h. class friend_iterator; - typedef llvm::iterator_range<friend_iterator> friend_range; + using friend_range = llvm::iterator_range<friend_iterator>; friend_range friends() const; friend_iterator friend_begin() const; @@ -839,7 +877,10 @@ public: /// \brief \c true if a defaulted destructor for this class would be deleted. bool defaultedDestructorIsDeleted() const { - return !data().DefaultedDestructorIsDeleted; + assert((!needsOverloadResolutionForDestructor() || + (data().DeclaredSpecialMembers & SMF_Destructor)) && + "this property has not yet been computed by Sema"); + return data().DefaultedDestructorIsDeleted; } /// \brief \c true if we know for sure that this class has a single, @@ -986,6 +1027,15 @@ public: data().DefaultedMoveConstructorIsDeleted = true; } + /// \brief Set that we attempted to declare an implicit destructor, + /// but overload resolution failed so we deleted it. + void setImplicitDestructorIsDeleted() { + assert((data().DefaultedDestructorIsDeleted || + needsOverloadResolutionForDestructor()) && + "destructor should not be deleted"); + data().DefaultedDestructorIsDeleted = true; + } + /// \brief Determine whether this class should get an implicit move /// constructor or if any existing special member function inhibits this. bool needsImplicitMoveConstructor() const { @@ -1144,24 +1194,28 @@ public: void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, FieldDecl *&ThisCapture) const; - typedef const LambdaCapture *capture_const_iterator; - typedef llvm::iterator_range<capture_const_iterator> capture_const_range; + using capture_const_iterator = const LambdaCapture *; + using capture_const_range = llvm::iterator_range<capture_const_iterator>; capture_const_range captures() const { return capture_const_range(captures_begin(), captures_end()); } + capture_const_iterator captures_begin() const { return isLambda() ? getLambdaData().Captures : nullptr; } + capture_const_iterator captures_end() const { return isLambda() ? captures_begin() + getLambdaData().NumCaptures : nullptr; } - typedef UnresolvedSetIterator conversion_iterator; + using conversion_iterator = UnresolvedSetIterator; + conversion_iterator conversion_begin() const { return data().Conversions.get(getASTContext()).begin(); } + conversion_iterator conversion_end() const { return data().Conversions.get(getASTContext()).end(); } @@ -1433,10 +1487,10 @@ public: /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by /// treating types with trivial default constructors as literal types. /// - /// Only in C++1z and beyond, are lambdas literal types. + /// Only in C++17 and beyond, are lambdas literal types. bool isLiteral() const { return hasTrivialDestructor() && - (!isLambda() || getASTContext().getLangOpts().CPlusPlus1z) && + (!isLambda() || getASTContext().getLangOpts().CPlusPlus17) && !hasNonLiteralTypeFieldsOrBases() && (isAggregate() || isLambda() || hasConstexprNonCopyMoveConstructor() || @@ -1585,8 +1639,8 @@ public: /// \param BaseDefinition the definition of the base class /// /// \returns true if this base matched the search criteria - typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)> - ForallBasesCallback; + using ForallBasesCallback = + llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>; /// \brief Determines if the given callback holds for all the direct /// or indirect base classes of this type. @@ -1614,8 +1668,9 @@ public: /// base named by the \p Specifier. /// /// \returns true if this base matched the search criteria, false otherwise. - typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path)> BaseMatchesCallback; + using BaseMatchesCallback = + llvm::function_ref<bool(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path)>; /// \brief Look for entities within the base classes of this C++ class, /// transitively searching all base class subobjects. @@ -1794,6 +1849,7 @@ public: /// \brief Returns the inheritance model used for this record. MSInheritanceAttr::Spelling getMSInheritanceModel() const; + /// \brief Calculate what the inheritance model would be for this class. MSInheritanceAttr::Spelling calculateInheritanceModel() const; @@ -1832,16 +1888,14 @@ public: return getLambdaData().MethodTyInfo; } + // \brief Determine whether this type is an Interface Like type for + // __interface inheritence purposes. + bool isInterfaceLike() const; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend class ASTRecordWriter; - friend class ASTReader; - friend class ASTWriter; }; /// \brief Represents a C++ deduction guide declaration. @@ -1856,6 +1910,7 @@ public: /// the constructors of \c A. class CXXDeductionGuideDecl : public FunctionDecl { void anchor() override; + private: CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit, const DeclarationNameInfo &NameInfo, @@ -1869,6 +1924,9 @@ private: } public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static CXXDeductionGuideDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit, const DeclarationNameInfo &NameInfo, @@ -1888,12 +1946,15 @@ public: return getDeclName().getCXXDeductionGuideTemplate(); } + void setIsCopyDeductionCandidate() { + IsCopyDeductionCandidate = true; + } + + bool isCopyDeductionCandidate() const { return IsCopyDeductionCandidate; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == CXXDeductionGuide; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Represents a static or instance method of a struct/union/class. @@ -1902,6 +1963,7 @@ public: /// non-static) member functions, whether virtual or not. class CXXMethodDecl : public FunctionDecl { void anchor() override; + protected: CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -1953,7 +2015,7 @@ public: if (CD->isVirtualAsWritten() || CD->isPure()) return true; - return (CD->begin_overridden_methods() != CD->end_overridden_methods()); + return CD->size_overridden_methods() != 0; } /// If it's possible to devirtualize a call to this method, return the called @@ -1999,18 +2061,23 @@ public: /// True if this method is user-declared and was not /// deleted or defaulted on its first declaration. bool isUserProvided() const { - return !(isDeleted() || getCanonicalDecl()->isDefaulted()); + auto *DeclAsWritten = this; + if (auto *Pattern = getTemplateInstantiationPattern()) + DeclAsWritten = cast<CXXMethodDecl>(Pattern); + return !(DeclAsWritten->isDeleted() || + DeclAsWritten->getCanonicalDecl()->isDefaulted()); } - /// void addOverriddenMethod(const CXXMethodDecl *MD); - typedef const CXXMethodDecl *const* method_iterator; + using method_iterator = const CXXMethodDecl *const *; method_iterator begin_overridden_methods() const; method_iterator end_overridden_methods() const; unsigned size_overridden_methods() const; - typedef ASTContext::overridden_method_range overridden_method_range; + + using overridden_method_range= ASTContext::overridden_method_range; + overridden_method_range overridden_methods() const; /// Returns the parent of this method declaration, which @@ -2240,6 +2307,7 @@ public: return Initializee.get<FieldDecl*>(); return nullptr; } + FieldDecl *getAnyMember() const { if (isMemberInitializer()) return Initializee.get<FieldDecl*>(); @@ -2301,11 +2369,11 @@ public: /// Description of a constructor that was inherited from a base class. class InheritedConstructor { - ConstructorUsingShadowDecl *Shadow; - CXXConstructorDecl *BaseCtor; + ConstructorUsingShadowDecl *Shadow = nullptr; + CXXConstructorDecl *BaseCtor = nullptr; public: - InheritedConstructor() : Shadow(), BaseCtor() {} + InheritedConstructor() = default; InheritedConstructor(ConstructorUsingShadowDecl *Shadow, CXXConstructorDecl *BaseCtor) : Shadow(Shadow), BaseCtor(BaseCtor) {} @@ -2329,8 +2397,6 @@ public: class CXXConstructorDecl final : public CXXMethodDecl, private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> { - void anchor() override; - /// \name Support for base and member initializers. /// \{ /// \brief The arguments used to initialize the base or member. @@ -2350,15 +2416,20 @@ class CXXConstructorDecl final InheritedConstructor Inherited) : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), - CtorInitializers(nullptr), NumCtorInitializers(0), - IsInheritingConstructor((bool)Inherited) { + NumCtorInitializers(0), IsInheritingConstructor((bool)Inherited) { setImplicit(isImplicitlyDeclared); if (Inherited) *getTrailingObjects<InheritedConstructor>() = Inherited; IsExplicitSpecified = isExplicitSpecified; } + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend TrailingObjects; + static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID, bool InheritsConstructor); static CXXConstructorDecl * @@ -2369,13 +2440,13 @@ public: InheritedConstructor Inherited = InheritedConstructor()); /// \brief Iterates through the member/base initializer list. - typedef CXXCtorInitializer **init_iterator; + using init_iterator = CXXCtorInitializer **; /// \brief Iterates through the member/base initializer list. - typedef CXXCtorInitializer *const *init_const_iterator; + using init_const_iterator = CXXCtorInitializer *const *; - typedef llvm::iterator_range<init_iterator> init_range; - typedef llvm::iterator_range<init_const_iterator> init_const_range; + using init_range = llvm::iterator_range<init_iterator>; + using init_const_range = llvm::iterator_range<init_const_iterator>; init_range inits() { return init_range(init_begin(), init_end()); } init_const_range inits() const { @@ -2387,6 +2458,7 @@ public: const auto *ConstThis = this; return const_cast<init_iterator>(ConstThis->init_begin()); } + /// \brief Retrieve an iterator to the first initializer. init_const_iterator init_begin() const; @@ -2394,14 +2466,15 @@ public: init_iterator init_end() { return init_begin() + NumCtorInitializers; } + /// \brief Retrieve an iterator past the last initializer. init_const_iterator init_end() const { return init_begin() + NumCtorInitializers; } - typedef std::reverse_iterator<init_iterator> init_reverse_iterator; - typedef std::reverse_iterator<init_const_iterator> - init_const_reverse_iterator; + using init_reverse_iterator = std::reverse_iterator<init_iterator>; + using init_const_reverse_iterator = + std::reverse_iterator<init_const_iterator>; init_reverse_iterator init_rbegin() { return init_reverse_iterator(init_end()); @@ -2532,10 +2605,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == CXXConstructor; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend TrailingObjects; }; /// \brief Represents a C++ destructor within a class. @@ -2549,20 +2618,26 @@ public: /// }; /// \endcode class CXXDestructorDecl : public CXXMethodDecl { - void anchor() override; + friend class ASTDeclReader; + friend class ASTDeclWriter; - FunctionDecl *OperatorDelete; + // FIXME: Don't allocate storage for these except in the first declaration + // of a virtual destructor. + FunctionDecl *OperatorDelete = nullptr; + Expr *OperatorDeleteThisArg = nullptr; CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), - OperatorDelete(nullptr) { + SC_None, isInline, /*isConstexpr=*/false, SourceLocation()) + { setImplicit(isImplicitlyDeclared); } + void anchor() override; + public: static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, @@ -2572,11 +2647,16 @@ public: bool isImplicitlyDeclared); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); - void setOperatorDelete(FunctionDecl *OD); + void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); + const FunctionDecl *getOperatorDelete() const { return getCanonicalDecl()->OperatorDelete; } + Expr *getOperatorDeleteThisArg() const { + return getCanonicalDecl()->OperatorDeleteThisArg; + } + CXXDestructorDecl *getCanonicalDecl() override { return cast<CXXDestructorDecl>(FunctionDecl::getCanonicalDecl()); } @@ -2587,9 +2667,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == CXXDestructor; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Represents a C++ conversion function within a class. @@ -2603,8 +2680,6 @@ public: /// }; /// \endcode class CXXConversionDecl : public CXXMethodDecl { - void anchor() override; - CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, @@ -2615,7 +2690,12 @@ class CXXConversionDecl : public CXXMethodDecl { IsExplicitSpecified = isExplicitSpecified; } + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -2652,9 +2732,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == CXXConversion; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Represents a linkage specification. @@ -2665,6 +2742,7 @@ public: /// \endcode class LinkageSpecDecl : public Decl, public DeclContext { virtual void anchor(); + public: /// \brief Represents the language in a linkage specification. /// @@ -2676,25 +2754,29 @@ public: lang_c = /* DW_LANG_C */ 0x0002, lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 }; + private: /// \brief The language for this linkage specification. unsigned Language : 3; + /// \brief True if this linkage spec has braces. /// /// This is needed so that hasBraces() returns the correct result while the /// linkage spec body is being parsed. Once RBraceLoc has been set this is /// not used, so it doesn't need to be serialized. unsigned HasBraces : 1; + /// \brief The source location for the extern keyword. SourceLocation ExternLoc; + /// \brief The source location for the right brace (if valid). SourceLocation RBraceLoc; LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, SourceLocation LangLoc, LanguageIDs lang, bool HasBraces) - : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), - Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc), - RBraceLoc(SourceLocation()) { } + : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), + Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc), + RBraceLoc(SourceLocation()) {} public: static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, @@ -2705,6 +2787,7 @@ public: /// \brief Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return LanguageIDs(Language); } + /// \brief Set the language specified by this linkage specification. void setLanguage(LanguageIDs L) { Language = L; } @@ -2737,9 +2820,11 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == LinkageSpec; } + static DeclContext *castToDeclContext(const LinkageSpecDecl *D) { return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D)); } + static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC)); } @@ -2756,7 +2841,6 @@ public: /// artificial names for all using-directives in order to store /// them in DeclContext effectively. class UsingDirectiveDecl : public NamedDecl { - void anchor() override; /// \brief The location of the \c using keyword. SourceLocation UsingLoc; @@ -2773,6 +2857,16 @@ class UsingDirectiveDecl : public NamedDecl { /// namespace. DeclContext *CommonAncestor; + UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc, + SourceLocation NamespcLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation IdentLoc, + NamedDecl *Nominated, + DeclContext *CommonAncestor) + : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc), + NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc), + NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) {} + /// \brief Returns special DeclarationName used by using-directives. /// /// This is only used by DeclContext for storing UsingDirectiveDecls in @@ -2781,17 +2875,14 @@ class UsingDirectiveDecl : public NamedDecl { return DeclarationName::getUsingDirectiveName(); } - UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc, - SourceLocation NamespcLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Nominated, - DeclContext *CommonAncestor) - : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc), - NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc), - NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { } + void anchor() override; public: + friend class ASTDeclReader; + + // Friend for getUsingDirectiveName. + friend class DeclContext; + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } @@ -2844,11 +2935,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UsingDirective; } - - // Friend for getUsingDirectiveName. - friend class DeclContext; - - friend class ASTDeclReader; }; /// \brief Represents a C++ namespace alias. @@ -2860,7 +2946,7 @@ public: /// \endcode class NamespaceAliasDecl : public NamedDecl, public Redeclarable<NamespaceAliasDecl> { - void anchor() override; + friend class ASTDeclReader; /// \brief The location of the \c namespace keyword. SourceLocation NamespaceLoc; @@ -2885,13 +2971,14 @@ class NamespaceAliasDecl : public NamedDecl, NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), QualifierLoc(QualifierLoc), Namespace(Namespace) {} - typedef Redeclarable<NamespaceAliasDecl> redeclarable_base; + void anchor() override; + + using redeclarable_base = Redeclarable<NamespaceAliasDecl>; + NamespaceAliasDecl *getNextRedeclarationImpl() override; NamespaceAliasDecl *getPreviousDeclImpl() override; NamespaceAliasDecl *getMostRecentDeclImpl() override; - friend class ASTDeclReader; - public: static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation NamespaceLoc, @@ -2903,8 +2990,9 @@ public: static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -2976,23 +3064,27 @@ public: /// } /// \endcode class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { - void anchor() override; + friend class UsingDecl; /// The referenced declaration. - NamedDecl *Underlying; + NamedDecl *Underlying = nullptr; /// \brief The using declaration which introduced this decl or the next using /// shadow declaration contained in the aforementioned using declaration. - NamedDecl *UsingOrNextShadow; - friend class UsingDecl; + NamedDecl *UsingOrNextShadow = nullptr; + + void anchor() override; + + using redeclarable_base = Redeclarable<UsingShadowDecl>; - typedef Redeclarable<UsingShadowDecl> redeclarable_base; UsingShadowDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + UsingShadowDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + UsingShadowDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -3003,6 +3095,9 @@ protected: UsingShadowDecl(Kind K, ASTContext &C, EmptyShell); public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, NamedDecl *Target) { @@ -3011,8 +3106,9 @@ public: static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -3052,9 +3148,6 @@ public: static bool classofKind(Kind K) { return K == Decl::UsingShadow || K == Decl::ConstructorUsingShadow; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Represents a shadow constructor declaration introduced into a @@ -3068,18 +3161,16 @@ public: /// }; /// \endcode class ConstructorUsingShadowDecl final : public UsingShadowDecl { - void anchor() override; - /// \brief If this constructor using declaration inherted the constructor /// from an indirect base class, this is the ConstructorUsingShadowDecl /// in the named direct base class from which the declaration was inherited. - ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl; + ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl = nullptr; /// \brief If this constructor using declaration inherted the constructor /// from an indirect base class, this is the ConstructorUsingShadowDecl /// that will be used to construct the unique direct or virtual base class /// that receives the constructor arguments. - ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl; + ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl = nullptr; /// \brief \c true if the constructor ultimately named by this using shadow /// declaration is within a virtual base class subobject of the class that @@ -3105,12 +3196,16 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl { IsVirtual = true; } } + ConstructorUsingShadowDecl(ASTContext &C, EmptyShell Empty) - : UsingShadowDecl(ConstructorUsingShadow, C, Empty), - NominatedBaseClassShadowDecl(), ConstructedBaseClassShadowDecl(), - IsVirtual(false) {} + : UsingShadowDecl(ConstructorUsingShadow, C, Empty), IsVirtual(false) {} + + void anchor() override; public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static ConstructorUsingShadowDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, NamedDecl *Target, @@ -3169,9 +3264,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ConstructorUsingShadow; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Represents a C++ using-declaration. @@ -3181,8 +3273,6 @@ public: /// using someNameSpace::someIdentifier; /// \endcode class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { - void anchor() override; - /// \brief The source location of the 'using' keyword itself. SourceLocation UsingLocation; @@ -3208,7 +3298,12 @@ class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) { } + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// \brief Return the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } @@ -3241,17 +3336,17 @@ public: /// this using declaration. class shadow_iterator { /// \brief The current using shadow declaration. - UsingShadowDecl *Current; + UsingShadowDecl *Current = nullptr; public: - typedef UsingShadowDecl* value_type; - typedef UsingShadowDecl* reference; - typedef UsingShadowDecl* pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + using value_type = UsingShadowDecl *; + using reference = UsingShadowDecl *; + using pointer = UsingShadowDecl *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; - shadow_iterator() : Current(nullptr) { } - explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { } + shadow_iterator() = default; + explicit shadow_iterator(UsingShadowDecl *C) : Current(C) {} reference operator*() const { return Current; } pointer operator->() const { return Current; } @@ -3275,14 +3370,16 @@ public: } }; - typedef llvm::iterator_range<shadow_iterator> shadow_range; + using shadow_range = llvm::iterator_range<shadow_iterator>; shadow_range shadows() const { return shadow_range(shadow_begin(), shadow_end()); } + shadow_iterator shadow_begin() const { return shadow_iterator(FirstUsingShadow.getPointer()); } + shadow_iterator shadow_end() const { return shadow_iterator(); } /// \brief Return the number of shadowed declarations associated with this @@ -3310,9 +3407,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Using; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// Represents a pack of using declarations that a single @@ -3331,8 +3425,6 @@ public: class UsingPackDecl final : public NamedDecl, public Mergeable<UsingPackDecl>, private llvm::TrailingObjects<UsingPackDecl, NamedDecl *> { - void anchor() override; - /// The UnresolvedUsingValueDecl or UnresolvedUsingTypenameDecl from /// which this waas instantiated. NamedDecl *InstantiatedFrom; @@ -3352,7 +3444,13 @@ class UsingPackDecl final getTrailingObjects<NamedDecl *>()); } + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend TrailingObjects; + /// Get the using declaration from which this was instantiated. This will /// always be an UnresolvedUsingValueDecl or an UnresolvedUsingTypenameDecl /// that is a pack expansion. @@ -3380,10 +3478,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UsingPack; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend TrailingObjects; }; /// \brief Represents a dependent using declaration which was not marked with @@ -3399,8 +3493,6 @@ public: /// \endcode class UnresolvedUsingValueDecl : public ValueDecl, public Mergeable<UnresolvedUsingValueDecl> { - void anchor() override; - /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; @@ -3419,13 +3511,17 @@ class UnresolvedUsingValueDecl : public ValueDecl, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc) - : ValueDecl(UnresolvedUsingValue, DC, - NameInfo.getLoc(), NameInfo.getName(), Ty), - UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc), - QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo()) - { } + : ValueDecl(UnresolvedUsingValue, DC, + NameInfo.getLoc(), NameInfo.getName(), Ty), + UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc), + QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo()) {} + + void anchor() override; public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } @@ -3478,9 +3574,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Represents a dependent using declaration which was marked with @@ -3497,7 +3590,7 @@ public: class UnresolvedUsingTypenameDecl : public TypeDecl, public Mergeable<UnresolvedUsingTypenameDecl> { - void anchor() override; + friend class ASTDeclReader; /// \brief The source location of the 'typename' keyword SourceLocation TypenameLocation; @@ -3517,9 +3610,9 @@ class UnresolvedUsingTypenameDecl : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName, UsingLoc), TypenameLocation(TypenameLoc), EllipsisLoc(EllipsisLoc), - QualifierLoc(QualifierLoc) { } + QualifierLoc(QualifierLoc) {} - friend class ASTDeclReader; + void anchor() override; public: /// \brief Returns the source location of the 'using' keyword. @@ -3574,7 +3667,6 @@ public: /// \brief Represents a C++11 static_assert declaration. class StaticAssertDecl : public Decl { - virtual void anchor(); llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed; StringLiteral *Message; SourceLocation RParenLoc; @@ -3582,11 +3674,15 @@ class StaticAssertDecl : public Decl { StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, Expr *AssertExpr, StringLiteral *Message, SourceLocation RParenLoc, bool Failed) - : Decl(StaticAssert, DC, StaticAssertLoc), - AssertExprAndFailed(AssertExpr, Failed), Message(Message), - RParenLoc(RParenLoc) { } + : Decl(StaticAssert, DC, StaticAssertLoc), + AssertExprAndFailed(AssertExpr, Failed), Message(Message), + RParenLoc(RParenLoc) {} + + virtual void anchor(); public: + friend class ASTDeclReader; + static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, Expr *AssertExpr, StringLiteral *Message, @@ -3609,8 +3705,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == StaticAssert; } - - friend class ASTDeclReader; }; /// A binding in a decomposition declaration. For instance, given: @@ -3622,18 +3716,20 @@ public: /// x[0], x[1], and x[2] respectively, where x is the implicit /// DecompositionDecl of type 'int (&)[3]'. class BindingDecl : public ValueDecl { - void anchor() override; - /// The binding represented by this declaration. References to this /// declaration are effectively equivalent to this expression (except /// that it is only evaluated once at the point of declaration of the /// binding). - Expr *Binding; + Expr *Binding = nullptr; BindingDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id) - : ValueDecl(Decl::Binding, DC, IdLoc, Id, QualType()), Binding(nullptr) {} + : ValueDecl(Decl::Binding, DC, IdLoc, Id, QualType()) {} + + void anchor() override; public: + friend class ASTDeclReader; + static BindingDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id); static BindingDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -3657,8 +3753,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::Binding; } - - friend class ASTDeclReader; }; /// A decomposition declaration. For instance, given: @@ -3672,8 +3766,6 @@ public: class DecompositionDecl final : public VarDecl, private llvm::TrailingObjects<DecompositionDecl, BindingDecl *> { - void anchor() override; - /// The number of BindingDecl*s following this object. unsigned NumBindings; @@ -3688,7 +3780,12 @@ class DecompositionDecl final getTrailingObjects<BindingDecl *>()); } + void anchor() override; + public: + friend class ASTDeclReader; + friend TrailingObjects; + static DecompositionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation LSquareLoc, @@ -3706,9 +3803,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decomposition; } - - friend TrailingObjects; - friend class ASTDeclReader; }; /// An instance of this class represents the declaration of a property @@ -3748,6 +3842,8 @@ class MSPropertyDecl : public DeclaratorDecl { GetterId(Getter), SetterId(Setter) {} public: + friend class ASTDeclReader; + static MSPropertyDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, SourceLocation StartL, @@ -3760,8 +3856,6 @@ public: IdentifierInfo* getGetterId() const { return GetterId; } bool hasSetter() const { return SetterId != nullptr; } IdentifierInfo* getSetterId() const { return SetterId; } - - friend class ASTDeclReader; }; /// Insertion operator for diagnostics. This allows sending an AccessSpecifier @@ -3772,6 +3866,6 @@ const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const PartialDiagnostic &operator<<(const PartialDiagnostic &DB, AccessSpecifier AS); -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_DECLCXX_H diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index eb86526e8eca..6545f70f70b5 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -1,4 +1,4 @@ -//===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===// +//===- DeclContextInternals.h - DeclContext Representation ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,10 +11,12 @@ // of DeclContext. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclarationName.h" #include "llvm/ADT/DenseMap.h" @@ -22,6 +24,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include <algorithm> +#include <cassert> namespace clang { @@ -30,21 +33,20 @@ class DependentDiagnostic; /// \brief 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. - typedef SmallVector<NamedDecl *, 4> DeclsTy; + using DeclsTy = SmallVector<NamedDecl *, 4>; /// \brief A collection of declarations, with a flag to indicate if we have /// further external declarations. - typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy; + using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>; /// \brief 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; + llvm::PointerUnion<NamedDecl *, DeclsAndHasExternalTy> Data; public: - StoredDeclsList() {} + StoredDeclsList() = default; StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) { RHS.Data = (NamedDecl *)nullptr; @@ -186,7 +188,6 @@ public: /// AddSubsequentDecl - This is called on the second and later decl when it is /// not a redeclaration to merge it into the appropriate place in our list. - /// void AddSubsequentDecl(NamedDecl *D) { assert(!isNull() && "don't AddSubsequentDecl when we have no decls"); @@ -237,28 +238,28 @@ public: }; class StoredDeclsMap - : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { - + : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { public: static void DestroyAll(StoredDeclsMap *Map, bool Dependent); private: friend class ASTContext; // walks the chain deleting these friend class DeclContext; + llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; }; class DependentStoredDeclsMap : public StoredDeclsMap { public: - DependentStoredDeclsMap() : FirstDiagnostic(nullptr) {} + DependentStoredDeclsMap() = default; private: - friend class DependentDiagnostic; friend class DeclContext; // iterates over diagnostics + friend class DependentDiagnostic; - DependentDiagnostic *FirstDiagnostic; + DependentDiagnostic *FirstDiagnostic = nullptr; }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 172c46a44ac1..5d1c6b86fe11 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -1,4 +1,4 @@ -//===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===// +//===- DeclFriend.h - Classes for C++ friend declarations -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,16 +15,30 @@ #ifndef LLVM_CLANG_AST_DECLFRIEND_H #define LLVM_CLANG_AST_DECLFRIEND_H +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExternalASTSource.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <iterator> namespace clang { +class ASTContext; + /// FriendDecl - Represents the declaration of a friend entity, /// which can be a function, a type, or a templated function or type. -// For example: +/// For example: /// /// @code /// template <typename T> class A { @@ -41,10 +55,14 @@ class FriendDecl final : public Decl, private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> { virtual void anchor(); + public: - typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; + using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>; private: + friend class CXXRecordDecl; + friend class CXXRecordDecl::friend_iterator; + // The declaration that's a friend of this class. FriendUnion Friend; @@ -64,35 +82,33 @@ private: // template <class T> friend class A<T>::B; unsigned NumTPLists : 31; - friend class CXXRecordDecl::friend_iterator; - friend class CXXRecordDecl; - FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, SourceLocation FriendL, - ArrayRef<TemplateParameterList*> FriendTypeTPLists) - : Decl(Decl::Friend, DC, L), - Friend(Friend), - NextFriend(), - FriendLoc(FriendL), - UnsupportedFriend(false), - NumTPLists(FriendTypeTPLists.size()) { + ArrayRef<TemplateParameterList *> FriendTypeTPLists) + : Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL), + UnsupportedFriend(false), NumTPLists(FriendTypeTPLists.size()) { for (unsigned i = 0; i < NumTPLists; ++i) getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i]; } FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists) - : Decl(Decl::Friend, Empty), NextFriend(), - UnsupportedFriend(false), - NumTPLists(NumFriendTypeTPLists) { } + : Decl(Decl::Friend, Empty), UnsupportedFriend(false), + NumTPLists(NumFriendTypeTPLists) {} FriendDecl *getNextFriend() { if (!NextFriend.isOffset()) return cast_or_null<FriendDecl>(NextFriend.get(nullptr)); return getNextFriendSlowCase(); } + FriendDecl *getNextFriendSlowCase(); public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend class ASTNodeImporter; + friend TrailingObjects; + static FriendDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, SourceLocation FriendL, @@ -108,9 +124,11 @@ public: TypeSourceInfo *getFriendType() const { return Friend.dyn_cast<TypeSourceInfo*>(); } + unsigned getFriendTypeNumTemplateParameterLists() const { return NumTPLists; } + TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const { assert(N < NumTPLists); return getTrailingObjects<TemplateParameterList *>()[N]; @@ -119,7 +137,7 @@ public: /// If this friend declaration doesn't name a type, return the inner /// declaration. NamedDecl *getFriendDecl() const { - return Friend.dyn_cast<NamedDecl*>(); + return Friend.dyn_cast<NamedDecl *>(); } /// Retrieves the location of the 'friend' keyword. @@ -164,27 +182,24 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::Friend; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend class ASTNodeImporter; - friend TrailingObjects; }; /// An iterator over the friend declarations of a class. class CXXRecordDecl::friend_iterator { + friend class CXXRecordDecl; + FriendDecl *Ptr; - friend class CXXRecordDecl; explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {} + public: - friend_iterator() {} + friend_iterator() = default; - typedef FriendDecl *value_type; - typedef FriendDecl *reference; - typedef FriendDecl *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; + using value_type = FriendDecl *; + using reference = FriendDecl *; + using pointer = FriendDecl *; + using difference_type = int; + using iterator_category = std::forward_iterator_tag; reference operator*() const { return Ptr; } @@ -240,6 +255,6 @@ inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) { data().FirstFriend = FD; } -} +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_DECLFRIEND_H diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index 6353b26f7bf5..6d5aaadf529c 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -1,4 +1,4 @@ -//===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===// +//===- DeclGroup.h - Classes for representing groups of Decls ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,26 +14,26 @@ #ifndef LLVM_CLANG_AST_DECLGROUP_H #define LLVM_CLANG_AST_DECLGROUP_H -#include "llvm/Support/DataTypes.h" #include "llvm/Support/TrailingObjects.h" #include <cassert> +#include <cstdint> namespace clang { class ASTContext; class Decl; -class DeclGroup; -class DeclGroupIterator; class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> { // FIXME: Include a TypeSpecifier object. - unsigned NumDecls; + unsigned NumDecls = 0; private: - DeclGroup() : NumDecls(0) {} + DeclGroup() = default; DeclGroup(unsigned numdecls, Decl** decls); public: + friend TrailingObjects; + static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); unsigned size() const { return NumDecls; } @@ -47,23 +47,21 @@ public: assert (i < NumDecls && "Out-of-bounds access."); return getTrailingObjects<Decl *>()[i]; } - - friend TrailingObjects; }; class DeclGroupRef { // Note this is not a PointerIntPair because we need the address of the // non-group case to be valid as a Decl** for iteration. enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; - Decl* D; + + Decl* D = nullptr; Kind getKind() const { return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); } public: - DeclGroupRef() : D(nullptr) {} - + DeclGroupRef() = default; explicit DeclGroupRef(Decl* d) : D(d) {} explicit DeclGroupRef(DeclGroup* dg) : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} @@ -76,8 +74,8 @@ public: return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); } - typedef Decl** iterator; - typedef Decl* const * const_iterator; + using iterator = Decl **; + using const_iterator = Decl * const *; bool isNull() const { return D == nullptr; } bool isSingleDecl() const { return getKind() == SingleDeclKind; } @@ -133,22 +131,26 @@ public: } }; -} // end clang namespace +} // namespace clang namespace llvm { + // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. template <typename T> - class PointerLikeTypeTraits; + struct PointerLikeTypeTraits; template <> - class PointerLikeTypeTraits<clang::DeclGroupRef> { - public: + struct PointerLikeTypeTraits<clang::DeclGroupRef> { static inline void *getAsVoidPointer(clang::DeclGroupRef P) { return P.getAsOpaquePtr(); } + static inline clang::DeclGroupRef getFromVoidPointer(void *P) { return clang::DeclGroupRef::getFromOpaquePtr(P); } + enum { NumLowBitsAvailable = 0 }; }; -} -#endif + +} // namespace llvm + +#endif // LLVM_CLANG_AST_DECLGROUP_H diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h index eba2266724fd..2fff05582563 100644 --- a/include/clang/AST/DeclLookups.h +++ b/include/clang/AST/DeclLookups.h @@ -1,4 +1,4 @@ -//===-- DeclLookups.h - Low-level interface to all names in a DC-*- C++ -*-===// +//===- DeclLookups.h - Low-level interface to all names in a DC -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,6 +18,9 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/ExternalASTSource.h" +#include <cstddef> +#include <iterator> namespace clang { @@ -25,14 +28,15 @@ namespace clang { /// of looking up every possible name. class DeclContext::all_lookups_iterator { StoredDeclsMap::iterator It, End; + public: - typedef lookup_result value_type; - typedef lookup_result reference; - typedef lookup_result pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + using value_type = lookup_result; + using reference = lookup_result; + using pointer = lookup_result; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; - all_lookups_iterator() {} + all_lookups_iterator() = default; all_lookups_iterator(StoredDeclsMap::iterator It, StoredDeclsMap::iterator End) : It(It), End(End) {} @@ -63,6 +67,7 @@ public: friend bool operator==(all_lookups_iterator x, all_lookups_iterator y) { return x.It == y.It; } + friend bool operator!=(all_lookups_iterator x, all_lookups_iterator y) { return x.It != y.It; } @@ -110,6 +115,6 @@ DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const { return noload_lookups().end(); } -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_DECLLOOKUPS_H diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 1cd6e004f751..cef7d935370a 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1,4 +1,4 @@ -//===--- DeclObjC.h - Classes for representing declarations -----*- C++ -*-===// +//===- DeclObjC.h - Classes for representing declarations -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,33 +15,59 @@ #define LLVM_CLANG_AST_DECLOBJC_H #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/Redeclarable.h" #include "clang/AST/SelectorLocationsKind.h" +#include "clang/AST/Type.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <string> +#include <utility> namespace clang { + +class ASTContext; +class CompoundStmt; +class CXXCtorInitializer; class Expr; -class Stmt; -class FunctionDecl; -class RecordDecl; -class ObjCIvarDecl; -class ObjCMethodDecl; -class ObjCProtocolDecl; class ObjCCategoryDecl; +class ObjCCategoryImplDecl; +class ObjCImplementationDecl; +class ObjCInterfaceDecl; +class ObjCIvarDecl; class ObjCPropertyDecl; class ObjCPropertyImplDecl; -class CXXCtorInitializer; +class ObjCProtocolDecl; +class Stmt; class ObjCListBase { - ObjCListBase(const ObjCListBase &) = delete; - void operator=(const ObjCListBase &) = delete; protected: /// List is an array of pointers to objects that are not owned by this object. - void **List; - unsigned NumElts; + void **List = nullptr; + unsigned NumElts = 0; public: - ObjCListBase() : List(nullptr), NumElts(0) {} + ObjCListBase() = default; + ObjCListBase(const ObjCListBase &) = delete; + ObjCListBase &operator=(const ObjCListBase &) = delete; + unsigned size() const { return NumElts; } bool empty() const { return NumElts == 0; } @@ -49,7 +75,6 @@ protected: void set(void *const* InList, unsigned Elts, ASTContext &Ctx); }; - /// ObjCList - This is a simple template class used to hold various lists of /// decls etc, which is heavily used by the ObjC front-end. This only use case /// this supports is setting the list all at once and then reading elements out @@ -61,7 +86,8 @@ public: ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx); } - typedef T* const * iterator; + using iterator = T* const *; + iterator begin() const { return (iterator)List; } iterator end() const { return (iterator)List+NumElts; } @@ -74,14 +100,15 @@ public: /// \brief A list of Objective-C protocols, along with the source /// locations at which they were referenced. class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> { - SourceLocation *Locations; + SourceLocation *Locations = nullptr; using ObjCList<ObjCProtocolDecl>::set; public: - ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(nullptr) { } + ObjCProtocolList() = default; + + using loc_iterator = const SourceLocation *; - typedef const SourceLocation *loc_iterator; loc_iterator loc_begin() const { return Locations; } loc_iterator loc_end() const { return Locations + size(); } @@ -89,7 +116,6 @@ public: const SourceLocation *Locs, ASTContext &Ctx); }; - /// ObjCMethodDecl - Represents an instance or class method declaration. /// ObjC methods can be declared within 4 contexts: class interfaces, /// categories, protocols, and class implementations. While C++ member @@ -113,6 +139,7 @@ public: class ObjCMethodDecl : public NamedDecl, public DeclContext { public: enum ImplementationControl { None, Required, Optional }; + private: // The conventional meaning of this method; an ObjCMethodFamily. // This is not serialized; instead, it is computed on demand and @@ -170,8 +197,8 @@ private: /// \brief Array of ParmVarDecls for the formal parameters of this method /// and optionally followed by selector locations. - void *ParamsAndSelLocs; - unsigned NumParams; + void *ParamsAndSelLocs = nullptr; + unsigned NumParams = 0; /// List of attributes for this method declaration. SourceLocation DeclEndLoc; // the location of the ';' or '{'. @@ -181,14 +208,35 @@ private: /// SelfDecl - Decl for the implicit self parameter. This is lazily /// constructed by createImplicitParams. - ImplicitParamDecl *SelfDecl; + ImplicitParamDecl *SelfDecl = nullptr; + /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily /// constructed by createImplicitParams. - ImplicitParamDecl *CmdDecl; + ImplicitParamDecl *CmdDecl = nullptr; + + ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, + Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, + DeclContext *contextDecl, bool isInstance = true, + bool isVariadic = false, bool isPropertyAccessor = false, + bool isImplicitlyDeclared = false, bool isDefined = false, + ImplementationControl impControl = None, + bool HasRelatedResultType = false) + : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), + DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), + IsInstance(isInstance), IsVariadic(isVariadic), + IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined), + IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl), + objcDeclQualifier(OBJC_TQ_None), + RelatedResultType(HasRelatedResultType), + SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0), + MethodDeclType(T), ReturnTInfo(ReturnTInfo), DeclEndLoc(endLoc) { + setImplicit(isImplicitlyDeclared); + } SelectorLocationsKind getSelLocsKind() const { return (SelectorLocationsKind)SelLocsKind; } + bool hasStandardSelLocs() const { return getSelLocsKind() != SelLoc_NonStandard; } @@ -223,33 +271,15 @@ private: ArrayRef<ParmVarDecl*> Params, ArrayRef<SourceLocation> SelLocs); - ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, - Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, - DeclContext *contextDecl, bool isInstance = true, - bool isVariadic = false, bool isPropertyAccessor = false, - bool isImplicitlyDeclared = false, bool isDefined = false, - ImplementationControl impControl = None, - bool HasRelatedResultType = false) - : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), - DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), - IsInstance(isInstance), IsVariadic(isVariadic), - IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined), - IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl), - objcDeclQualifier(OBJC_TQ_None), - RelatedResultType(HasRelatedResultType), - SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0), - MethodDeclType(T), ReturnTInfo(ReturnTInfo), ParamsAndSelLocs(nullptr), - NumParams(0), DeclEndLoc(endLoc), Body(), SelfDecl(nullptr), - CmdDecl(nullptr) { - setImplicit(isImplicitlyDeclared); - } - /// \brief A definition will return its interface declaration. /// An interface declaration will return its definition. /// Otherwise it will return itself. ObjCMethodDecl *getNextRedeclarationImpl() override; public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static ObjCMethodDecl * Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, @@ -299,6 +329,7 @@ public: return getLocStart(); return getSelectorLoc(0); } + SourceLocation getSelectorLoc(unsigned Index) const { assert(Index < getNumSelectorLocs() && "Index out of range!"); if (hasStandardSelLocs()) @@ -346,17 +377,20 @@ public: // Iterator access to formal parameters. unsigned param_size() const { return NumParams; } - typedef const ParmVarDecl *const *param_const_iterator; - typedef ParmVarDecl *const *param_iterator; - typedef llvm::iterator_range<param_iterator> param_range; - typedef llvm::iterator_range<param_const_iterator> param_const_range; + + using param_const_iterator = const ParmVarDecl *const *; + using param_iterator = ParmVarDecl *const *; + using param_range = llvm::iterator_range<param_iterator>; + using param_const_range = llvm::iterator_range<param_const_iterator>; param_const_iterator param_begin() const { return param_const_iterator(getParams()); } + param_const_iterator param_end() const { return param_const_iterator(getParams() + NumParams); } + param_iterator param_begin() { return param_iterator(getParams()); } param_iterator param_end() { return param_iterator(getParams() + NumParams); } @@ -384,12 +418,14 @@ public: struct GetTypeFn { QualType operator()(const ParmVarDecl *PD) const { return PD->getType(); } }; - typedef llvm::mapped_iterator<param_const_iterator, GetTypeFn> - param_type_iterator; + + using param_type_iterator = + llvm::mapped_iterator<param_const_iterator, GetTypeFn>; param_type_iterator param_type_begin() const { return llvm::map_iterator(param_begin(), GetTypeFn()); } + param_type_iterator param_type_end() const { return llvm::map_iterator(param_end(), GetTypeFn()); } @@ -462,9 +498,11 @@ public: void setDeclImplementation(ImplementationControl ic) { DeclImplementation = ic; } + ImplementationControl getImplementationControl() const { return ImplementationControl(DeclImplementation); } + bool isOptional() const { return getImplementationControl() == Optional; } @@ -499,24 +537,25 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCMethod; } + static DeclContext *castToDeclContext(const ObjCMethodDecl *D) { return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D)); } + static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC)); } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// Describes the variance of a given generic parameter. enum class ObjCTypeParamVariance : uint8_t { /// The parameter is invariant: must match exactly. Invariant, + /// The parameter is covariant, e.g., X<T> is a subtype of X<U> when /// the type parameter is covariant and T is a subtype of U. Covariant, + /// The parameter is contravariant, e.g., X<T> is a subtype of X<U> /// when the type parameter is covariant and U is a subtype of T. Contravariant, @@ -535,8 +574,6 @@ enum class ObjCTypeParamVariance : uint8_t { /// /// Objective-C type parameters are typedef-names in the grammar, class ObjCTypeParamDecl : public TypedefNameDecl { - void anchor() override; - /// Index of this type parameter in the type parameter list. unsigned Index : 14; @@ -555,12 +592,17 @@ class ObjCTypeParamDecl : public TypedefNameDecl { unsigned index, SourceLocation nameLoc, IdentifierInfo *name, SourceLocation colonLoc, TypeSourceInfo *boundInfo) - : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name, - boundInfo), - Index(index), Variance(static_cast<unsigned>(variance)), - VarianceLoc(varianceLoc), ColonLoc(colonLoc) { } + : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name, + boundInfo), + Index(index), Variance(static_cast<unsigned>(variance)), + VarianceLoc(varianceLoc), ColonLoc(colonLoc) {} + + void anchor() override; public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc, ObjCTypeParamVariance variance, SourceLocation varianceLoc, @@ -600,9 +642,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCTypeParam; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// Stores a list of Objective-C type parameters for a parameterized class @@ -636,6 +675,8 @@ class ObjCTypeParamList final SourceLocation rAngleLoc); public: + friend TrailingObjects; + /// Create a new Objective-C type parameter list. static ObjCTypeParamList *create(ASTContext &ctx, SourceLocation lAngleLoc, @@ -643,7 +684,7 @@ public: SourceLocation rAngleLoc); /// Iterate through the type parameters in the list. - typedef ObjCTypeParamDecl **iterator; + using iterator = ObjCTypeParamDecl **; iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); } @@ -653,7 +694,7 @@ public: unsigned size() const { return NumParams; } // Iterate through the type parameters in the list. - typedef ObjCTypeParamDecl * const *const_iterator; + using const_iterator = ObjCTypeParamDecl * const *; const_iterator begin() const { return getTrailingObjects<ObjCTypeParamDecl *>(); @@ -676,9 +717,11 @@ public: SourceLocation getLAngleLoc() const { return SourceLocation::getFromRawEncoding(Brackets.Begin); } + SourceLocation getRAngleLoc() const { return SourceLocation::getFromRawEncoding(Brackets.End); } + SourceRange getSourceRange() const { return SourceRange(getLAngleLoc(), getRAngleLoc()); } @@ -686,7 +729,6 @@ public: /// Gather the default set of type arguments to be substituted for /// these type parameters when dealing with an unspecialized type. void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const; - friend TrailingObjects; }; enum class ObjCPropertyQueryKind : uint8_t { @@ -703,6 +745,7 @@ enum class ObjCPropertyQueryKind : uint8_t { /// \endcode class ObjCPropertyDecl : public NamedDecl { void anchor() override; + public: enum PropertyAttributeKind { OBJC_PR_noattr = 0x00, @@ -733,24 +776,42 @@ public: enum SetterKind { Assign, Retain, Copy, Weak }; enum PropertyControl { None, Required, Optional }; + private: - SourceLocation AtLoc; // location of \@property - SourceLocation LParenLoc; // location of '(' starting attribute list or null. + // location of \@property + SourceLocation AtLoc; + + // location of '(' starting attribute list or null. + SourceLocation LParenLoc; + QualType DeclType; TypeSourceInfo *DeclTypeSourceInfo; unsigned PropertyAttributes : NumPropertyAttrsBits; unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; + // \@required/\@optional unsigned PropertyImplementation : 2; - Selector GetterName; // getter name of NULL if no getter - Selector SetterName; // setter name of NULL if no setter - SourceLocation GetterNameLoc; // location of the getter attribute's value - SourceLocation SetterNameLoc; // location of the setter attribute's value + // getter name of NULL if no getter + Selector GetterName; + + // setter name of NULL if no setter + Selector SetterName; + + // location of the getter attribute's value + SourceLocation GetterNameLoc; + + // location of the setter attribute's value + SourceLocation SetterNameLoc; + + // Declaration of getter instance method + ObjCMethodDecl *GetterMethodDecl = nullptr; + + // Declaration of setter instance method + ObjCMethodDecl *SetterMethodDecl = nullptr; - ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method - ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method - ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property + // Synthesize ivar for this property + ObjCIvarDecl *PropertyIvarDecl = nullptr; ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation AtLocation, SourceLocation LParenLocation, @@ -760,11 +821,8 @@ private: LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), PropertyAttributes(OBJC_PR_noattr), PropertyAttributesAsWritten(OBJC_PR_noattr), - PropertyImplementation(propControl), - GetterName(Selector()), - SetterName(Selector()), - GetterMethodDecl(nullptr), SetterMethodDecl(nullptr), - PropertyIvarDecl(nullptr) {} + PropertyImplementation(propControl), GetterName(Selector()), + SetterName(Selector()) {} public: static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, @@ -799,9 +857,11 @@ public: PropertyAttributeKind getPropertyAttributes() const { return PropertyAttributeKind(PropertyAttributes); } + void setPropertyAttributes(PropertyAttributeKind PRVal) { PropertyAttributes |= PRVal; } + void overwritePropertyAttributes(unsigned PRVal) { PropertyAttributes = PRVal; } @@ -834,10 +894,12 @@ public: bool isInstanceProperty() const { return !isClassProperty(); } bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; } + ObjCPropertyQueryKind getQueryKind() const { return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class : ObjCPropertyQueryKind::OBJC_PR_query_instance; } + static ObjCPropertyQueryKind getQueryKind(bool isClassProperty) { return isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class : ObjCPropertyQueryKind::OBJC_PR_query_instance; @@ -860,6 +922,7 @@ public: Selector getGetterName() const { return GetterName; } SourceLocation getGetterNameLoc() const { return GetterNameLoc; } + void setGetterName(Selector Sel, SourceLocation Loc = SourceLocation()) { GetterName = Sel; GetterNameLoc = Loc; @@ -867,6 +930,7 @@ public: Selector getSetterName() const { return SetterName; } SourceLocation getSetterNameLoc() const { return SetterNameLoc; } + void setSetterName(Selector Sel, SourceLocation Loc = SourceLocation()) { SetterName = Sel; SetterNameLoc = Loc; @@ -882,9 +946,11 @@ public: void setPropertyImplementation(PropertyControl pc) { PropertyImplementation = pc; } + PropertyControl getPropertyImplementation() const { return PropertyControl(PropertyImplementation); } + bool isOptional() const { return getPropertyImplementation() == PropertyControl::Optional; } @@ -892,6 +958,7 @@ public: void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } + ObjCIvarDecl *getPropertyIvarDecl() const { return PropertyIvarDecl; } @@ -917,104 +984,116 @@ public: /// ObjCProtocolDecl, and ObjCImplDecl. /// class ObjCContainerDecl : public NamedDecl, public DeclContext { - void anchor() override; - SourceLocation AtStart; // These two locations in the range mark the end of the method container. // The first points to the '@' token, and the second to the 'end' token. SourceRange AtEnd; -public: + void anchor() override; + +public: ObjCContainerDecl(Kind DK, DeclContext *DC, IdentifierInfo *Id, SourceLocation nameLoc, SourceLocation atStartLoc) - : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {} + : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {} // Iterator access to instance/class properties. - typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>> - prop_range; + using prop_iterator = specific_decl_iterator<ObjCPropertyDecl>; + using prop_range = + llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>; prop_range properties() const { return prop_range(prop_begin(), prop_end()); } + prop_iterator prop_begin() const { return prop_iterator(decls_begin()); } + prop_iterator prop_end() const { return prop_iterator(decls_end()); } - typedef filtered_decl_iterator<ObjCPropertyDecl, - &ObjCPropertyDecl::isInstanceProperty> - instprop_iterator; - typedef llvm::iterator_range<instprop_iterator> instprop_range; + using instprop_iterator = + filtered_decl_iterator<ObjCPropertyDecl, + &ObjCPropertyDecl::isInstanceProperty>; + using instprop_range = llvm::iterator_range<instprop_iterator>; instprop_range instance_properties() const { return instprop_range(instprop_begin(), instprop_end()); } + instprop_iterator instprop_begin() const { return instprop_iterator(decls_begin()); } + instprop_iterator instprop_end() const { return instprop_iterator(decls_end()); } - typedef filtered_decl_iterator<ObjCPropertyDecl, - &ObjCPropertyDecl::isClassProperty> - classprop_iterator; - typedef llvm::iterator_range<classprop_iterator> classprop_range; + using classprop_iterator = + filtered_decl_iterator<ObjCPropertyDecl, + &ObjCPropertyDecl::isClassProperty>; + using classprop_range = llvm::iterator_range<classprop_iterator>; classprop_range class_properties() const { return classprop_range(classprop_begin(), classprop_end()); } + classprop_iterator classprop_begin() const { return classprop_iterator(decls_begin()); } + classprop_iterator classprop_end() const { return classprop_iterator(decls_end()); } // Iterator access to instance/class methods. - typedef specific_decl_iterator<ObjCMethodDecl> method_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>> - method_range; + using method_iterator = specific_decl_iterator<ObjCMethodDecl>; + using method_range = + llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>>; method_range methods() const { return method_range(meth_begin(), meth_end()); } + method_iterator meth_begin() const { return method_iterator(decls_begin()); } + method_iterator meth_end() const { return method_iterator(decls_end()); } - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isInstanceMethod> - instmeth_iterator; - typedef llvm::iterator_range<instmeth_iterator> instmeth_range; + using instmeth_iterator = + filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isInstanceMethod>; + using instmeth_range = llvm::iterator_range<instmeth_iterator>; instmeth_range instance_methods() const { return instmeth_range(instmeth_begin(), instmeth_end()); } + instmeth_iterator instmeth_begin() const { return instmeth_iterator(decls_begin()); } + instmeth_iterator instmeth_end() const { return instmeth_iterator(decls_end()); } - typedef filtered_decl_iterator<ObjCMethodDecl, - &ObjCMethodDecl::isClassMethod> - classmeth_iterator; - typedef llvm::iterator_range<classmeth_iterator> classmeth_range; + using classmeth_iterator = + filtered_decl_iterator<ObjCMethodDecl, + &ObjCMethodDecl::isClassMethod>; + using classmeth_range = llvm::iterator_range<classmeth_iterator>; classmeth_range class_methods() const { return classmeth_range(classmeth_begin(), classmeth_end()); } + classmeth_iterator classmeth_begin() const { return classmeth_iterator(decls_begin()); } + classmeth_iterator classmeth_end() const { return classmeth_iterator(decls_end()); } @@ -1022,13 +1101,16 @@ public: // Get the local instance/class method declared in this interface. ObjCMethodDecl *getMethod(Selector Sel, bool isInstance, bool AllowHidden = false) const; + ObjCMethodDecl *getInstanceMethod(Selector Sel, bool AllowHidden = false) const { return getMethod(Sel, true/*isInstance*/, AllowHidden); } + ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const { return getMethod(Sel, false/*isInstance*/, AllowHidden); } + bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const; ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; @@ -1036,13 +1118,11 @@ public: FindPropertyDeclaration(const IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const; - typedef llvm::DenseMap<std::pair<IdentifierInfo*, - unsigned/*isClassProperty*/>, - ObjCPropertyDecl*> PropertyMap; - - typedef llvm::SmallDenseSet<const ObjCProtocolDecl *, 8> ProtocolPropertySet; - - typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder; + using PropertyMap = + llvm::DenseMap<std::pair<IdentifierInfo *, unsigned/*isClassProperty*/>, + ObjCPropertyDecl *>; + using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>; + using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 8>; /// This routine collects list of properties to be implemented in the class. /// This includes, class's and its conforming protocols' properties. @@ -1057,6 +1137,7 @@ public: SourceRange getAtEndRange() const { return AtEnd; } + void setAtEndRange(SourceRange atEnd) { AtEnd = atEnd; } @@ -1067,6 +1148,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K >= firstObjCContainer && K <= lastObjCContainer; @@ -1075,6 +1157,7 @@ public: static DeclContext *castToDeclContext(const ObjCContainerDecl *D) { return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D)); } + static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC)); } @@ -1107,20 +1190,19 @@ public: /// class ObjCInterfaceDecl : public ObjCContainerDecl , public Redeclarable<ObjCInterfaceDecl> { - void anchor() override; + friend class ASTContext; /// TypeForDecl - This indicates the Type object that represents this /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType - mutable const Type *TypeForDecl; - friend class ASTContext; + mutable const Type *TypeForDecl = nullptr; struct DefinitionData { /// \brief The definition of this class, for quick access from any /// declaration. - ObjCInterfaceDecl *Definition; + ObjCInterfaceDecl *Definition = nullptr; /// When non-null, this is always an ObjCObjectType. - TypeSourceInfo *SuperClassTInfo; + TypeSourceInfo *SuperClassTInfo = nullptr; /// Protocols referenced in the \@interface declaration ObjCProtocolList ReferencedProtocols; @@ -1133,11 +1215,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// Categories are stored as a linked list in the AST, since the categories /// and class extensions come long after the initial interface declaration, /// and we avoid dynamically-resized arrays in the AST wherever possible. - ObjCCategoryDecl *CategoryList; + ObjCCategoryDecl *CategoryList = nullptr; /// IvarList - List of all ivars defined by this class; including class /// extensions and implementation. This list is built lazily. - ObjCIvarDecl *IvarList; + ObjCIvarDecl *IvarList = nullptr; /// \brief Indicates that the contents of this Objective-C class will be /// completed by the external AST source when required. @@ -1155,11 +1237,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// We didn't calculate whether the designated initializers should be /// inherited or not. IDI_Unknown = 0, + /// Designated initializers are inherited for the super class. IDI_Inherited = 1, + /// The class does not inherit designated initializers. IDI_NotInherited = 2 }; + /// One of the \c InheritedDesignatedInitializersState enumeratos. mutable unsigned InheritedDesignatedInitializers : 2; @@ -1168,22 +1253,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// identifier, SourceLocation EndLoc; - DefinitionData() : Definition(), SuperClassTInfo(), CategoryList(), IvarList(), - ExternallyCompleted(), - IvarListMissingImplementation(true), - HasDesignatedInitializers(), - InheritedDesignatedInitializers(IDI_Unknown) { } + DefinitionData() + : ExternallyCompleted(false), IvarListMissingImplementation(true), + HasDesignatedInitializers(false), + InheritedDesignatedInitializers(IDI_Unknown) {} }; - ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc, - IdentifierInfo *Id, ObjCTypeParamList *typeParamList, - SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, - bool IsInternal); - - void LoadExternalDefinition() const; - /// The type parameters associated with this class, if any. - ObjCTypeParamList *TypeParamList; + ObjCTypeParamList *TypeParamList = nullptr; /// \brief Contains a pointer to the data associated with this class, /// which will be NULL if this class has not yet been defined. @@ -1192,6 +1269,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// declarations. It will be set unless modules are enabled. llvm::PointerIntPair<DefinitionData *, 1, bool> Data; + ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc, + IdentifierInfo *Id, ObjCTypeParamList *typeParamList, + SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, + bool IsInternal); + + void anchor() override; + + void LoadExternalDefinition() const; + DefinitionData &data() const { assert(Data.getPointer() && "Declaration has no definition!"); return *Data.getPointer(); @@ -1200,13 +1286,16 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// \brief Allocate the definition data for this class. void allocateDefinitionData(); - typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base; + using redeclarable_base = Redeclarable<ObjCInterfaceDecl>; + ObjCInterfaceDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + ObjCInterfaceDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + ObjCInterfaceDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } @@ -1284,17 +1373,19 @@ public: // Get the local instance/class method declared in a category. ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const; ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const; + ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const { return isInstance ? getCategoryInstanceMethod(Sel) : getCategoryClassMethod(Sel); } - typedef ObjCProtocolList::iterator protocol_iterator; - typedef llvm::iterator_range<protocol_iterator> protocol_range; + using protocol_iterator = ObjCProtocolList::iterator; + using protocol_range = llvm::iterator_range<protocol_iterator>; protocol_range protocols() const { return protocol_range(protocol_begin(), protocol_end()); } + protocol_iterator protocol_begin() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -1305,6 +1396,7 @@ public: return data().ReferencedProtocols.begin(); } + protocol_iterator protocol_end() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -1316,12 +1408,13 @@ public: return data().ReferencedProtocols.end(); } - typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; + using protocol_loc_iterator = ObjCProtocolList::loc_iterator; + using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>; protocol_loc_range protocol_locs() const { return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); } + protocol_loc_iterator protocol_loc_begin() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -1344,13 +1437,14 @@ public: return data().ReferencedProtocols.loc_end(); } - typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; - typedef llvm::iterator_range<all_protocol_iterator> all_protocol_range; + using all_protocol_iterator = ObjCList<ObjCProtocolDecl>::iterator; + using all_protocol_range = llvm::iterator_range<all_protocol_iterator>; all_protocol_range all_referenced_protocols() const { return all_protocol_range(all_referenced_protocol_begin(), all_referenced_protocol_end()); } + all_protocol_iterator all_referenced_protocol_begin() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -1363,6 +1457,7 @@ public: ? protocol_begin() : data().AllReferencedProtocols.begin(); } + all_protocol_iterator all_referenced_protocol_end() const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) @@ -1376,10 +1471,11 @@ public: : data().AllReferencedProtocols.end(); } - typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; + using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>; + using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>; ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } + ivar_iterator ivar_begin() const { if (const ObjCInterfaceDecl *Def = getDefinition()) return ivar_iterator(Def->decls_begin()); @@ -1387,6 +1483,7 @@ public: // FIXME: Should make sure no callers ever do this. return ivar_iterator(); } + ivar_iterator ivar_end() const { if (const ObjCInterfaceDecl *Def = getDefinition()) return ivar_iterator(Def->decls_end()); @@ -1518,21 +1615,20 @@ public: /// and extension iterators. template<bool (*Filter)(ObjCCategoryDecl *)> class filtered_category_iterator { - ObjCCategoryDecl *Current; + ObjCCategoryDecl *Current = nullptr; void findAcceptableCategory(); public: - typedef ObjCCategoryDecl * value_type; - typedef value_type reference; - typedef value_type pointer; - typedef std::ptrdiff_t difference_type; - typedef std::input_iterator_tag iterator_category; + using value_type = ObjCCategoryDecl *; + using reference = value_type; + using pointer = value_type; + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; - filtered_category_iterator() : Current(nullptr) { } + filtered_category_iterator() = default; explicit filtered_category_iterator(ObjCCategoryDecl *Current) - : Current(Current) - { + : Current(Current) { findAcceptableCategory(); } @@ -1567,11 +1663,11 @@ private: public: /// \brief Iterator that walks over the list of categories and extensions /// that are visible, i.e., not hidden in a non-imported submodule. - typedef filtered_category_iterator<isVisibleCategory> - visible_categories_iterator; + using visible_categories_iterator = + filtered_category_iterator<isVisibleCategory>; - typedef llvm::iterator_range<visible_categories_iterator> - visible_categories_range; + using visible_categories_range = + llvm::iterator_range<visible_categories_iterator>; visible_categories_range visible_categories() const { return visible_categories_range(visible_categories_begin(), @@ -1603,9 +1699,9 @@ private: public: /// \brief Iterator that walks over all of the known categories and /// extensions, including those that are hidden. - typedef filtered_category_iterator<isKnownCategory> known_categories_iterator; - typedef llvm::iterator_range<known_categories_iterator> - known_categories_range; + using known_categories_iterator = filtered_category_iterator<isKnownCategory>; + using known_categories_range = + llvm::iterator_range<known_categories_iterator>; known_categories_range known_categories() const { return known_categories_range(known_categories_begin(), @@ -1637,11 +1733,11 @@ private: public: /// \brief Iterator that walks over all of the visible extensions, skipping /// any that are known but hidden. - typedef filtered_category_iterator<isVisibleExtension> - visible_extensions_iterator; + using visible_extensions_iterator = + filtered_category_iterator<isVisibleExtension>; - typedef llvm::iterator_range<visible_extensions_iterator> - visible_extensions_range; + using visible_extensions_range = + llvm::iterator_range<visible_extensions_iterator>; visible_extensions_range visible_extensions() const { return visible_extensions_range(visible_extensions_begin(), @@ -1671,11 +1767,15 @@ private: static bool isKnownExtension(ObjCCategoryDecl *Cat); public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend class ASTReader; + /// \brief Iterator that walks over all of the known extensions. - typedef filtered_category_iterator<isKnownExtension> - known_extensions_iterator; - typedef llvm::iterator_range<known_extensions_iterator> - known_extensions_range; + using known_extensions_iterator = + filtered_category_iterator<isKnownExtension>; + using known_extensions_range = + llvm::iterator_range<known_extensions_iterator>; known_extensions_range known_extensions() const { return known_extensions_range(known_extensions_begin(), @@ -1771,6 +1871,7 @@ public: ObjCMethodDecl *lookupClassMethod(Selector Sel) const { return lookupMethod(Sel, false/*isInstance*/); } + ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); /// \brief Lookup a method in the classes implementation hierarchy. @@ -1819,8 +1920,9 @@ public: bool lookupCategory, bool RHSIsQualifiedID = false); - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -1839,10 +1941,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCInterface; } - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTDeclWriter; - private: const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const; bool inheritsDesignatedInitializers() const; @@ -1876,9 +1974,9 @@ private: SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) - : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, - /*Mutable=*/false, /*HasInit=*/ICIS_NoInit), - NextIvar(nullptr), DeclAccess(ac), Synthesized(synthesized) {} + : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, + /*Mutable=*/false, /*HasInit=*/ICIS_NoInit), + DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, @@ -1918,26 +2016,27 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCIvar; } + private: /// NextIvar - Next Ivar in the list of ivars declared in class; class's /// extensions and class's implementation - ObjCIvarDecl *NextIvar; + ObjCIvarDecl *NextIvar = nullptr; // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; unsigned Synthesized : 1; }; - /// \brief Represents a field declaration created by an \@defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { - void anchor() override; ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) - : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, - /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ? - BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {} + : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, + /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ? + BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {} + + void anchor() override; public: static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, @@ -1981,11 +2080,8 @@ public: /// protocols are referenced using angle brackets as follows: /// /// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; -/// class ObjCProtocolDecl : public ObjCContainerDecl, public Redeclarable<ObjCProtocolDecl> { - void anchor() override; - struct DefinitionData { // \brief The declaration that defines this protocol. ObjCProtocolDecl *Definition; @@ -2001,29 +2097,38 @@ class ObjCProtocolDecl : public ObjCContainerDecl, /// declarations. It will be set unless modules are enabled. llvm::PointerIntPair<DefinitionData *, 1, bool> Data; + ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, + SourceLocation nameLoc, SourceLocation atStartLoc, + ObjCProtocolDecl *PrevDecl); + + void anchor() override; + DefinitionData &data() const { assert(Data.getPointer() && "Objective-C protocol has no definition!"); return *Data.getPointer(); } - ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, - SourceLocation nameLoc, SourceLocation atStartLoc, - ObjCProtocolDecl *PrevDecl); - void allocateDefinitionData(); - typedef Redeclarable<ObjCProtocolDecl> redeclarable_base; + using redeclarable_base = Redeclarable<ObjCProtocolDecl>; + ObjCProtocolDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + ObjCProtocolDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + ObjCProtocolDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend class ASTReader; + static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, SourceLocation nameLoc, @@ -2036,42 +2141,49 @@ public: assert(hasDefinition() && "No definition available!"); return data().ReferencedProtocols; } - typedef ObjCProtocolList::iterator protocol_iterator; - typedef llvm::iterator_range<protocol_iterator> protocol_range; + + using protocol_iterator = ObjCProtocolList::iterator; + using protocol_range = llvm::iterator_range<protocol_iterator>; protocol_range protocols() const { return protocol_range(protocol_begin(), protocol_end()); } + protocol_iterator protocol_begin() const { if (!hasDefinition()) return protocol_iterator(); return data().ReferencedProtocols.begin(); } + protocol_iterator protocol_end() const { if (!hasDefinition()) return protocol_iterator(); return data().ReferencedProtocols.end(); } - typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; + + using protocol_loc_iterator = ObjCProtocolList::loc_iterator; + using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>; protocol_loc_range protocol_locs() const { return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); } + protocol_loc_iterator protocol_loc_begin() const { if (!hasDefinition()) return protocol_loc_iterator(); return data().ReferencedProtocols.loc_begin(); } + protocol_loc_iterator protocol_loc_end() const { if (!hasDefinition()) return protocol_loc_iterator(); return data().ReferencedProtocols.loc_end(); } + unsigned protocol_size() const { if (!hasDefinition()) return 0; @@ -2092,9 +2204,11 @@ public: // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const; + ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const { return lookupMethod(Sel, true/*isInstance*/); } + ObjCMethodDecl *lookupClassMethod(Selector Sel) const { return lookupMethod(Sel, false/*isInstance*/); } @@ -2141,8 +2255,9 @@ public: return SourceRange(getAtStartLoc(), getLocation()); } - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -2163,10 +2278,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProtocol; } - - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// ObjCCategoryDecl - Represents a category declaration. A category allows @@ -2185,22 +2296,19 @@ public: /// Categories were originally inspired by dynamic languages such as Common /// Lisp and Smalltalk. More traditional class-based languages (C++, Java) /// don't support this level of dynamism, which is both powerful and dangerous. -/// class ObjCCategoryDecl : public ObjCContainerDecl { - void anchor() override; - /// Interface belonging to this category ObjCInterfaceDecl *ClassInterface; /// The type parameters associated with this category, if any. - ObjCTypeParamList *TypeParamList; + ObjCTypeParamList *TypeParamList = nullptr; /// referenced protocols in this category. ObjCProtocolList ReferencedProtocols; /// Next category belonging to this class. /// FIXME: this should not be a singly-linked list. Move storage elsewhere. - ObjCCategoryDecl *NextClassCategory; + ObjCCategoryDecl *NextClassCategory = nullptr; /// \brief The location of the category name in this declaration. SourceLocation CategoryNameLoc; @@ -2213,10 +2321,14 @@ class ObjCCategoryDecl : public ObjCContainerDecl { SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id, ObjCInterfaceDecl *IDecl, ObjCTypeParamList *typeParamList, - SourceLocation IvarLBraceLoc=SourceLocation(), - SourceLocation IvarRBraceLoc=SourceLocation()); + SourceLocation IvarLBraceLoc = SourceLocation(), + SourceLocation IvarRBraceLoc = SourceLocation()); + + void anchor() override; public: + friend class ASTDeclReader; + friend class ASTDeclWriter; static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation AtLoc, @@ -2257,26 +2369,31 @@ public: return ReferencedProtocols; } - typedef ObjCProtocolList::iterator protocol_iterator; - typedef llvm::iterator_range<protocol_iterator> protocol_range; + using protocol_iterator = ObjCProtocolList::iterator; + using protocol_range = llvm::iterator_range<protocol_iterator>; protocol_range protocols() const { return protocol_range(protocol_begin(), protocol_end()); } + protocol_iterator protocol_begin() const { return ReferencedProtocols.begin(); } + protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } unsigned protocol_size() const { return ReferencedProtocols.size(); } - typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; - typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range; + + using protocol_loc_iterator = ObjCProtocolList::loc_iterator; + using protocol_loc_range = llvm::iterator_range<protocol_loc_iterator>; protocol_loc_range protocol_locs() const { return protocol_loc_range(protocol_loc_begin(), protocol_loc_end()); } + protocol_loc_iterator protocol_loc_begin() const { return ReferencedProtocols.loc_begin(); } + protocol_loc_iterator protocol_loc_end() const { return ReferencedProtocols.loc_end(); } @@ -2291,19 +2408,23 @@ public: bool IsClassExtension() const { return getIdentifier() == nullptr; } - typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; + using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>; + using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>; ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } + ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } + ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } + unsigned ivar_size() const { return std::distance(ivar_begin(), ivar_end()); } + bool ivar_empty() const { return ivar_begin() == ivar_end(); } @@ -2318,24 +2439,21 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCCategory; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; class ObjCImplDecl : public ObjCContainerDecl { - void anchor() override; - /// Class interface for this class/category implementation ObjCInterfaceDecl *ClassInterface; + void anchor() override; + protected: ObjCImplDecl(Kind DK, DeclContext *DC, ObjCInterfaceDecl *classInterface, IdentifierInfo *Id, SourceLocation nameLoc, SourceLocation atStartLoc) - : ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc), - ClassInterface(classInterface) {} + : ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc), + ClassInterface(classInterface) {} public: const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } @@ -2347,6 +2465,7 @@ public: method->setLexicalDeclContext(this); addDecl(method); } + void addClassMethod(ObjCMethodDecl *method) { // FIXME: Context should be set correctly before we get here. method->setLexicalDeclContext(this); @@ -2360,21 +2479,24 @@ public: ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const; // Iterator access to properties. - typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>> - propimpl_range; + using propimpl_iterator = specific_decl_iterator<ObjCPropertyImplDecl>; + using propimpl_range = + llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>>; propimpl_range property_impls() const { return propimpl_range(propimpl_begin(), propimpl_end()); } + propimpl_iterator propimpl_begin() const { return propimpl_iterator(decls_begin()); } + propimpl_iterator propimpl_end() const { return propimpl_iterator(decls_end()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K >= firstObjCImpl && K <= lastObjCImpl; } @@ -2394,8 +2516,6 @@ public: /// /// ObjCCategoryImplDecl class ObjCCategoryImplDecl : public ObjCImplDecl { - void anchor() override; - // Category name location SourceLocation CategoryNameLoc; @@ -2403,10 +2523,16 @@ class ObjCCategoryImplDecl : public ObjCImplDecl { ObjCInterfaceDecl *classInterface, SourceLocation nameLoc, SourceLocation atStartLoc, SourceLocation CategoryNameLoc) - : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id, - nameLoc, atStartLoc), - CategoryNameLoc(CategoryNameLoc) {} + : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id, + nameLoc, atStartLoc), + CategoryNameLoc(CategoryNameLoc) {} + + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, ObjCInterfaceDecl *classInterface, @@ -2421,9 +2547,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID); @@ -2446,7 +2569,6 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID); /// we allow instance variables to be specified in the implementation. When /// specified, they need to be \em identical to the interface. class ObjCImplementationDecl : public ObjCImplDecl { - void anchor() override; /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; SourceLocation SuperLoc; @@ -2458,7 +2580,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { /// Support for ivar initialization. /// \brief The arguments used to initialize the ivars LazyCXXCtorInitializersPtr IvarInitializers; - unsigned NumIvarInitializers; + unsigned NumIvarInitializers = 0; /// Do the ivars of this class require initialization other than /// zero-initialization? @@ -2474,15 +2596,20 @@ class ObjCImplementationDecl : public ObjCImplDecl { SourceLocation superLoc = SourceLocation(), SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarRBraceLoc=SourceLocation()) - : ObjCImplDecl(ObjCImplementation, DC, classInterface, - classInterface ? classInterface->getIdentifier() - : nullptr, - nameLoc, atStartLoc), - SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc), - IvarRBraceLoc(IvarRBraceLoc), - IvarInitializers(nullptr), NumIvarInitializers(0), - HasNonZeroConstructors(false), HasDestructors(false) {} + : ObjCImplDecl(ObjCImplementation, DC, classInterface, + classInterface ? classInterface->getIdentifier() + : nullptr, + nameLoc, atStartLoc), + SuperClass(superDecl), SuperLoc(superLoc), + IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc), + HasNonZeroConstructors(false), HasDestructors(false) {} + + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl, @@ -2495,15 +2622,16 @@ public: static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// init_iterator - Iterates through the ivar initializer list. - typedef CXXCtorInitializer **init_iterator; + using init_iterator = CXXCtorInitializer **; /// init_const_iterator - Iterates through the ivar initializer list. - typedef CXXCtorInitializer * const * init_const_iterator; + using init_const_iterator = CXXCtorInitializer * const *; - typedef llvm::iterator_range<init_iterator> init_range; - typedef llvm::iterator_range<init_const_iterator> init_const_range; + using init_range = llvm::iterator_range<init_iterator>; + using init_const_range = llvm::iterator_range<init_const_iterator>; init_range inits() { return init_range(init_begin(), init_end()); } + init_const_range inits() const { return init_const_range(init_begin(), init_end()); } @@ -2513,6 +2641,7 @@ public: const auto *ConstThis = this; return const_cast<init_iterator>(ConstThis->init_begin()); } + /// begin() - Retrieve an iterator to the first initializer. init_const_iterator init_begin() const; @@ -2520,10 +2649,12 @@ public: init_iterator init_end() { return init_begin() + NumIvarInitializers; } + /// end() - Retrieve an iterator past the last initializer. init_const_iterator init_end() const { return init_begin() + NumIvarInitializers; } + /// getNumArgs - Number of ivars which must be initialized. unsigned getNumIvarInitializers() const { return NumIvarInitializers; @@ -2585,28 +2716,29 @@ public: void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; } SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; } - typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range; + using ivar_iterator = specific_decl_iterator<ObjCIvarDecl>; + using ivar_range = llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>>; ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); } + ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } + ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } + unsigned ivar_size() const { return std::distance(ivar_begin(), ivar_end()); } + bool ivar_empty() const { return ivar_begin() == ivar_end(); } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCImplementation; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID); @@ -2614,13 +2746,15 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID); /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is /// declared as \@compatibility_alias alias class. class ObjCCompatibleAliasDecl : public NamedDecl { - void anchor() override; /// Class that this is an alias of. ObjCInterfaceDecl *AliasedClass; ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, ObjCInterfaceDecl* aliasedClass) - : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {} + : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {} + + void anchor() override; + public: static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -2635,7 +2769,6 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; } - }; /// ObjCPropertyImplDecl - Represents implementation declaration of a property @@ -2648,6 +2781,7 @@ public: Synthesize, Dynamic }; + private: SourceLocation AtLoc; // location of \@synthesize or \@dynamic @@ -2667,24 +2801,25 @@ private: /// Null for \@dynamic. Non-null if property must be copy-constructed in /// getter. - Expr *GetterCXXConstructor; + Expr *GetterCXXConstructor = nullptr; /// Null for \@dynamic. Non-null if property has assignment operator to call /// in Setter synthesis. - Expr *SetterCXXAssignment; + Expr *SetterCXXAssignment = nullptr; ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, ObjCIvarDecl *ivarDecl, SourceLocation ivarLoc) - : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), - IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl), - GetterCXXConstructor(nullptr), SetterCXXAssignment(nullptr) { - assert (PK == Dynamic || PropertyIvarDecl); + : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), + IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl) { + assert(PK == Dynamic || PropertyIvarDecl); } public: + friend class ASTDeclReader; + static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, @@ -2733,6 +2868,7 @@ public: Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; } + void setGetterCXXConstructor(Expr *getterCXXConstructor) { GetterCXXConstructor = getterCXXConstructor; } @@ -2740,14 +2876,13 @@ public: Expr *getSetterCXXAssignment() const { return SetterCXXAssignment; } + void setSetterCXXAssignment(Expr *setterCXXAssignment) { SetterCXXAssignment = setterCXXAssignment; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; } - - friend class ASTDeclReader; }; template<bool (*Filter)(ObjCCategoryDecl *)> @@ -2778,5 +2913,6 @@ inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) { return Cat->IsClassExtension(); } -} // end namespace clang -#endif +} // namespace clang + +#endif // LLVM_CLANG_AST_DECLOBJC_H diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h index 30ca79e9d005..2a329c3732cb 100644 --- a/include/clang/AST/DeclOpenMP.h +++ b/include/clang/AST/DeclOpenMP.h @@ -100,12 +100,22 @@ public: /// /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer. class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { +public: + enum InitKind { + CallInit, // Initialized by function call. + DirectInit, // omp_priv(<expr>) + CopyInit // omp_priv = <expr> + }; + private: friend class ASTDeclReader; /// \brief Combiner for declare reduction construct. Expr *Combiner; /// \brief 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 /// scope with the same name. Required for proper templates instantiation if /// the declare reduction construct is declared inside compound statement. @@ -117,7 +127,8 @@ private: DeclarationName Name, QualType Ty, OMPDeclareReductionDecl *PrevDeclInScope) : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr), - Initializer(nullptr), PrevDeclInScope(PrevDeclInScope) {} + Initializer(nullptr), InitializerKind(CallInit), + PrevDeclInScope(PrevDeclInScope) {} void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) { PrevDeclInScope = Prev; @@ -142,8 +153,13 @@ public: /// 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. - void setInitializer(Expr *E) { Initializer = E; } + void setInitializer(Expr *E, InitKind IK) { + Initializer = E; + InitializerKind = IK; + } /// \brief Get reference to previous declare reduction construct in the same /// scope with the same name. diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 2879452f2404..7842d7097174 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -1,4 +1,4 @@ -//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===// +//===- DeclTemplate.h - Classes for representing C++ templates --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,42 +6,60 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the C++ template declaration subclasses. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_DECLTEMPLATE_H #define LLVM_CLANG_AST_DECLTEMPLATE_H +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> #include <utility> namespace clang { enum BuiltinTemplateKind : int; -class TemplateParameterList; -class TemplateDecl; -class RedeclarableTemplateDecl; -class FunctionTemplateDecl; class ClassTemplateDecl; class ClassTemplatePartialSpecializationDecl; -class TemplateTypeParmDecl; +class Expr; +class FunctionTemplateDecl; +class IdentifierInfo; class NonTypeTemplateParmDecl; +class TemplateDecl; class TemplateTemplateParmDecl; -class TypeAliasTemplateDecl; +class TemplateTypeParmDecl; +class UnresolvedSetImpl; class VarTemplateDecl; class VarTemplatePartialSpecializationDecl; /// \brief Stores a template parameter of any kind. -typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*, - TemplateTemplateParmDecl*> TemplateParameter; +using TemplateParameter = + llvm::PointerUnion3<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *, + TemplateTemplateParmDecl *>; NamedDecl *getAsNamedDecl(TemplateParameter P); @@ -50,7 +68,6 @@ NamedDecl *getAsNamedDecl(TemplateParameter P); class TemplateParameterList final : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *, Expr *> { - /// The location of the 'template' keyword. SourceLocation TemplateLoc; @@ -69,6 +86,10 @@ class TemplateParameterList final unsigned HasRequiresClause : 1; protected: + TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc, + Expr *RequiresClause); + size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { return NumParams; } @@ -77,11 +98,11 @@ protected: return HasRequiresClause; } - TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc, - Expr *RequiresClause); - public: + template <size_t N, bool HasRequiresClause> + friend class FixedSizeTemplateParameterListStorage; + friend TrailingObjects; + static TemplateParameterList *Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, @@ -90,10 +111,10 @@ public: Expr *RequiresClause); /// \brief Iterates through the template parameters in this list. - typedef NamedDecl** iterator; + using iterator = NamedDecl **; /// \brief Iterates through the template parameters in this list. - typedef NamedDecl* const* const_iterator; + using const_iterator = NamedDecl * const *; iterator begin() { return getTrailingObjects<NamedDecl *>(); } const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); } @@ -113,7 +134,6 @@ public: assert(Idx < size() && "Template parameter index out-of-range"); return begin()[Idx]; } - const NamedDecl* getParam(unsigned Idx) const { assert(Idx < size() && "Template parameter index out-of-range"); return begin()[Idx]; @@ -157,11 +177,6 @@ public: return SourceRange(TemplateLoc, RAngleLoc); } - friend TrailingObjects; - - template <size_t N, bool HasRequiresClause> - friend class FixedSizeTemplateParameterListStorage; - public: // FIXME: workaround for MSVC 2013; remove when no longer needed using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner; @@ -201,14 +216,16 @@ class TemplateArgumentList final /// argument list. unsigned NumArguments; - TemplateArgumentList(const TemplateArgumentList &Other) = delete; - void operator=(const TemplateArgumentList &Other) = delete; - // Constructs an instance with an internal Argument list, containing // a copy of the Args array. (Called by CreateCopy) TemplateArgumentList(ArrayRef<TemplateArgument> Args); public: + friend TrailingObjects; + + TemplateArgumentList(const TemplateArgumentList &) = delete; + TemplateArgumentList &operator=(const TemplateArgumentList &) = delete; + /// \brief Type used to indicate that the template argument list itself is a /// stack object. It does not own its template arguments. enum OnStackType { OnStack }; @@ -254,8 +271,6 @@ public: /// \brief Retrieve a pointer to the template argument list. const TemplateArgument *data() const { return Arguments; } - - friend TrailingObjects; }; void *allocateDefaultArgStorageChain(const ASTContext &C); @@ -297,9 +312,11 @@ public: /// Determine whether there is a default argument for this parameter. bool isSet() const { return !ValueOrInherited.isNull(); } + /// Determine whether the default argument for this parameter was inherited /// from a previous declaration of the same entity. bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); } + /// Get the default argument's value. This does not consider whether the /// default argument is visible. ArgType get() const { @@ -310,6 +327,7 @@ public: return C->Value; return Storage->ValueOrInherited.template get<ArgType>(); } + /// 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 { @@ -319,11 +337,13 @@ public: return C->PrevDeclWithDefaultArg; return nullptr; } + /// Set the default argument. void set(ArgType Arg) { assert(!isSet() && "default argument already set"); ValueOrInherited = Arg; } + /// Set that the default argument was inherited from another parameter. void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) { assert(!isInherited() && "default argument already inherited"); @@ -334,6 +354,7 @@ public: ValueOrInherited = new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()}; } + /// Remove the default argument, even if it was inherited. void clear() { ValueOrInherited = ArgType(); @@ -350,7 +371,7 @@ class ConstrainedTemplateDeclInfo { friend TemplateDecl; public: - ConstrainedTemplateDeclInfo() : TemplateParams(), AssociatedConstraints() {} + ConstrainedTemplateDeclInfo() = default; TemplateParameterList *getTemplateParameters() const { return TemplateParams; @@ -365,8 +386,8 @@ protected: void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; } - TemplateParameterList *TemplateParams; - Expr *AssociatedConstraints; + TemplateParameterList *TemplateParams = nullptr; + Expr *AssociatedConstraints = nullptr; }; @@ -377,13 +398,14 @@ protected: /// reference to the templated scoped declaration: the underlying AST node. class TemplateDecl : public NamedDecl { void anchor() override; + protected: // Construct a template decl with the given name and parameters. // Used when there is no templated element (e.g., for tt-params). TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false), + : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), TemplateParams(CTDI) { this->setTemplateParameters(Params); } @@ -396,7 +418,7 @@ protected: TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false), + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(CTDI) { this->setTemplateParameters(Params); } @@ -428,31 +450,22 @@ public: } /// Get the underlying, templated declaration. - NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); } + NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K >= firstTemplate && K <= lastTemplate; } SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getTemplateParameters()->getTemplateLoc(), - TemplatedDecl.getPointer()->getSourceRange().getEnd()); + TemplatedDecl->getSourceRange().getEnd()); } - /// Whether this is a (C++ Concepts TS) function or variable concept. - bool isConcept() const { return TemplatedDecl.getInt(); } - void setConcept() { TemplatedDecl.setInt(true); } - protected: - /// \brief The named declaration from which this template was instantiated. - /// (or null). - /// - /// The boolean value will be true to indicate that this template - /// (function or variable) is a concept. - llvm::PointerIntPair<NamedDecl *, 1, bool> TemplatedDecl; - + NamedDecl *TemplatedDecl; /// \brief The template parameter list and optional requires-clause /// associated with this declaration; alternatively, a /// \c ConstrainedTemplateDeclInfo if the associated constraints of the @@ -481,9 +494,9 @@ public: /// \brief Initialize the underlying templated declaration and /// template parameters. void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { - assert(!TemplatedDecl.getPointer() && "TemplatedDecl already set!"); + assert(!TemplatedDecl && "TemplatedDecl already set!"); assert(!TemplateParams && "TemplateParams already set!"); - TemplatedDecl.setPointer(templatedDecl); + TemplatedDecl = templatedDecl; TemplateParams = templateParams; } }; @@ -498,11 +511,10 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { const TemplateArgumentList *TemplateArgs, const ASTTemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI) - : Function(FD), - Template(Template, TSK - 1), - TemplateArguments(TemplateArgs), - TemplateArgumentsAsWritten(TemplateArgsAsWritten), - PointOfInstantiation(POI) { } + : Function(FD), Template(Template, TSK - 1), + TemplateArguments(TemplateArgs), + TemplateArgumentsAsWritten(TemplateArgsAsWritten), + PointOfInstantiation(POI) {} public: static FunctionTemplateSpecializationInfo * @@ -604,7 +616,7 @@ public: explicit MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK, SourceLocation POI = SourceLocation()) - : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) { + : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) { assert(TSK != TSK_Undeclared && "Cannot encode undeclared template specializations for members"); } @@ -681,6 +693,8 @@ class DependentFunctionTemplateSpecializationInfo final const TemplateArgumentListInfo &TemplateArgs); public: + friend TrailingObjects; + static DependentFunctionTemplateSpecializationInfo * Create(ASTContext &Context, const UnresolvedSetImpl &Templates, const TemplateArgumentListInfo &TemplateArgs); @@ -716,32 +730,34 @@ public: SourceLocation getRAngleLoc() const { return AngleLocs.getEnd(); } - - friend TrailingObjects; }; /// Declaration of a redeclarable template. class RedeclarableTemplateDecl : public TemplateDecl, public Redeclarable<RedeclarableTemplateDecl> { - typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base; + using redeclarable_base = Redeclarable<RedeclarableTemplateDecl>; + RedeclarableTemplateDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } + RedeclarableTemplateDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } + RedeclarableTemplateDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } protected: template <typename EntryType> struct SpecEntryTraits { - typedef EntryType DeclType; + using DeclType = EntryType; static DeclType *getDecl(EntryType *D) { return D; } + static ArrayRef<TemplateArgument> getTemplateArgs(EntryType *D) { return D->getTemplateArgs().asArray(); } @@ -756,7 +772,7 @@ protected: typename std::iterator_traits<typename llvm::FoldingSetVector< EntryType>::iterator>::iterator_category, DeclType *, ptrdiff_t, DeclType *, DeclType *> { - SpecIterator() {} + SpecIterator() = default; explicit SpecIterator( typename llvm::FoldingSetVector<EntryType>::iterator SetIter) : SpecIterator::iterator_adaptor_base(std::move(SetIter)) {} @@ -764,6 +780,7 @@ protected: DeclType *operator*() const { return SETraits::getDecl(&*this->I)->getMostRecentDecl(); } + DeclType *operator->() const { return **this; } }; @@ -773,6 +790,8 @@ protected: return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin()); } + void loadLazySpecializationsImpl() const; + template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType* findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args, void *&InsertPos); @@ -782,7 +801,7 @@ protected: EntryType *Entry, void *InsertPos); struct CommonBase { - CommonBase() : InstantiatedFromMember(nullptr, false) { } + CommonBase() : InstantiatedFromMember(nullptr, false) {} /// \brief The template from which this was most /// directly instantiated (or null). @@ -791,11 +810,18 @@ protected: /// was explicitly specialized. llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool> InstantiatedFromMember; + + /// \brief 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 + /// specializations that follow. + uint32_t *LazySpecializations = nullptr; }; /// \brief Pointer to the common data shared by all declarations of this /// template. - mutable CommonBase *Common; + mutable CommonBase *Common = nullptr; /// \brief Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory @@ -809,8 +835,8 @@ protected: ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C), - Common() {} + : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C) + {} RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -818,6 +844,9 @@ protected: : RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {} public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend class ASTReader; template <class decl_type> friend class RedeclarableTemplate; /// \brief Retrieves the canonical declaration of this template. @@ -858,7 +887,7 @@ public: } /// \brief Retrieve the member template from which this template was - /// instantiated, or NULL if this template was not instantiated from a + /// instantiated, or nullptr if this template was not instantiated from a /// member template. /// /// A template is instantiated from a member template when the member @@ -902,8 +931,9 @@ public: getCommonPtr()->InstantiatedFromMember.setPointer(TD); } - typedef redeclarable_base::redecl_range redecl_range; - typedef redeclarable_base::redecl_iterator redecl_iterator; + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; @@ -913,22 +943,20 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; } - - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTDeclWriter; }; template <> struct RedeclarableTemplateDecl:: SpecEntryTraits<FunctionTemplateSpecializationInfo> { - typedef FunctionDecl DeclType; + using DeclType = FunctionDecl; static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) { return I->Function; } + static ArrayRef<TemplateArgument> getTemplateArgs(FunctionTemplateSpecializationInfo *I) { return I->TemplateArguments->asArray(); @@ -938,11 +966,11 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> { /// Declaration of a template function. class FunctionTemplateDecl : public RedeclarableTemplateDecl { protected: + friend class FunctionDecl; + /// \brief Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { - Common() : InjectedArgs(), LazySpecializations() { } - /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations; @@ -954,14 +982,9 @@ protected: /// many template arguments as template parameaters) for the function /// template, and is allocated lazily, since most function templates do not /// require the use of this information. - TemplateArgument *InjectedArgs; + TemplateArgument *InjectedArgs = nullptr; - /// \brief If non-null, points to an array of specializations known only - /// by their external declaration IDs. - /// - /// The first value in the array is the number of of specializations - /// that follow. - uint32_t *LazySpecializations; + Common() = default; }; FunctionTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -976,8 +999,6 @@ protected: return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); } - friend class FunctionDecl; - /// \brief Retrieve the set of function template specializations of this /// function template. llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> & @@ -991,12 +1012,15 @@ protected: void *InsertPos); public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// \brief Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; /// Get the underlying function declaration of the template. FunctionDecl *getTemplatedDecl() const { - return static_cast<FunctionDecl *>(TemplatedDecl.getPointer()); + return static_cast<FunctionDecl *>(TemplatedDecl); } /// Returns whether this template declaration defines the primary @@ -1020,14 +1044,11 @@ public: } /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. + /// nullptr if no such declaration exists. FunctionTemplateDecl *getPreviousDecl() { return cast_or_null<FunctionTemplateDecl>( static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. const FunctionTemplateDecl *getPreviousDecl() const { return cast_or_null<FunctionTemplateDecl>( static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl()); @@ -1047,12 +1068,13 @@ public: RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } - typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator; - typedef llvm::iterator_range<spec_iterator> spec_range; + using spec_iterator = SpecIterator<FunctionTemplateSpecializationInfo>; + using spec_range = llvm::iterator_range<spec_iterator>; spec_range specializations() const { return spec_range(spec_begin(), spec_end()); } + spec_iterator spec_begin() const { return makeSpecIterator(getSpecializations(), false); } @@ -1083,9 +1105,6 @@ public: // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == FunctionTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; //===----------------------------------------------------------------------===// @@ -1102,19 +1121,17 @@ public: /// This class is inheritedly privately by different kinds of template /// parameters and is not part of the Decl hierarchy. Just a facility. class TemplateParmPosition { - TemplateParmPosition() = delete; - protected: - TemplateParmPosition(unsigned D, unsigned P) - : Depth(D), Position(P) - { } - // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for // position? Maybe? unsigned Depth; unsigned Position; + TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {} + public: + TemplateParmPosition() = delete; + /// Get the nesting depth of the template parameter. unsigned getDepth() const { return Depth; } void setDepth(unsigned D) { Depth = D; } @@ -1134,6 +1151,9 @@ public: /// template<typename T> class vector; /// \endcode 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 /// the 'typename' keyword. /// @@ -1141,18 +1161,14 @@ class TemplateTypeParmDecl : public TypeDecl { bool Typename : 1; /// \brief The default template argument, if any. - typedef DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *> - DefArgStorage; + using DefArgStorage = + DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>; DefArgStorage DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, SourceLocation IdLoc, IdentifierInfo *Id, bool Typename) - : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), - DefaultArgument() { } - - /// Sema creates these on the stack during auto type deduction. - friend class Sema; + : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename) {} public: static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, @@ -1199,6 +1215,7 @@ public: void setDefaultArgument(TypeSourceInfo *DefArg) { DefaultArgument.set(DefArg); } + /// \brief Set that this default argument was inherited from another /// parameter. void setInheritedDefaultArgument(const ASTContext &C, @@ -1241,9 +1258,12 @@ class NonTypeTemplateParmDecl final protected TemplateParmPosition, private llvm::TrailingObjects<NonTypeTemplateParmDecl, std::pair<QualType, TypeSourceInfo *>> { + friend class ASTDeclReader; + friend TrailingObjects; + /// \brief The default template argument, if any, and whether or not /// it was inherited. - typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage; + using DefArgStorage = DefaultArgStorage<NonTypeTemplateParmDecl, Expr *>; DefArgStorage DefaultArgument; // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index @@ -1255,10 +1275,10 @@ class NonTypeTemplateParmDecl final /// \brief 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; + bool ExpandedParameterPack = false; /// \brief The number of types in an expanded parameter pack. - unsigned NumExpandedTypes; + unsigned NumExpandedTypes = 0; size_t numTrailingObjects( OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const { @@ -1269,10 +1289,8 @@ class NonTypeTemplateParmDecl final SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) - : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), ParameterPack(ParameterPack), - ExpandedParameterPack(false), NumExpandedTypes(0) - { } + : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), + TemplateParmPosition(D, P), ParameterPack(ParameterPack) {} NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, @@ -1281,9 +1299,6 @@ class NonTypeTemplateParmDecl final ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos); - friend class ASTDeclReader; - friend TrailingObjects; - public: static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, @@ -1428,11 +1443,9 @@ class TemplateTemplateParmDecl final protected TemplateParmPosition, private llvm::TrailingObjects<TemplateTemplateParmDecl, TemplateParameterList *> { - void anchor() override; - /// \brief The default template argument, if any. - typedef DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *> - DefArgStorage; + using DefArgStorage = + DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>; DefArgStorage DefaultArgument; /// \brief Whether this parameter is a parameter pack. @@ -1441,25 +1454,29 @@ class TemplateTemplateParmDecl final /// \brief 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; + bool ExpandedParameterPack = false; /// \brief The number of parameters in an expanded parameter pack. - unsigned NumExpandedParams; + unsigned NumExpandedParams = 0; TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) - : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), ParameterPack(ParameterPack), - ExpandedParameterPack(false), NumExpandedParams(0) - { } + : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), + TemplateParmPosition(D, P), ParameterPack(ParameterPack) {} TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params, ArrayRef<TemplateParameterList *> Expansions); + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend TrailingObjects; + static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, @@ -1579,22 +1596,18 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TemplateTemplateParm; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; - friend TrailingObjects; }; /// \brief 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 { - void anchor() override; + BuiltinTemplateKind BTK; BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, DeclarationName Name, BuiltinTemplateKind BTK); - BuiltinTemplateKind BTK; + void anchor() override; public: // Implement isa/cast/dyncast support @@ -1629,7 +1642,6 @@ public: /// \endcode class ClassTemplateSpecializationDecl : public CXXRecordDecl, public llvm::FoldingSetNode { - /// \brief Structure that stores information about a class template /// specialization that was instantiated from a class template partial /// specialization. @@ -1650,19 +1662,20 @@ class ClassTemplateSpecializationDecl /// \brief Further info for explicit template specialization/instantiation. struct ExplicitSpecializationInfo { /// \brief The type-as-written. - TypeSourceInfo *TypeAsWritten; + TypeSourceInfo *TypeAsWritten = nullptr; + /// \brief The location of the extern keyword. SourceLocation ExternLoc; + /// \brief The location of the template keyword. SourceLocation TemplateKeywordLoc; - ExplicitSpecializationInfo() - : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {} + ExplicitSpecializationInfo() = default; }; /// \brief Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - ExplicitSpecializationInfo *ExplicitInfo; + ExplicitSpecializationInfo *ExplicitInfo = nullptr; /// \brief The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; @@ -1685,6 +1698,9 @@ protected: explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK); public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static ClassTemplateSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -1828,6 +1844,7 @@ public: ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TypeAsWritten = T; } + /// \brief Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { @@ -1838,6 +1855,7 @@ public: SourceLocation getExternLoc() const { return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); } + /// \brief Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc) { if (!ExplicitInfo) @@ -1851,6 +1869,7 @@ public: ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TemplateKeywordLoc = Loc; } + /// \brief Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); @@ -1871,25 +1890,21 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K >= firstClassTemplateSpecialization && K <= lastClassTemplateSpecialization; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; class ClassTemplatePartialSpecializationDecl : public ClassTemplateSpecializationDecl { - void anchor() override; - /// \brief The list of template parameters - TemplateParameterList* TemplateParams; + TemplateParameterList* TemplateParams = nullptr; /// \brief The source info for the template arguments as written. /// FIXME: redundant with TypeAsWritten? - const ASTTemplateArgumentListInfo *ArgsAsWritten; + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; /// \brief The class template partial specialization from which this /// class template partial specialization was instantiated. @@ -1911,10 +1926,14 @@ class ClassTemplatePartialSpecializationDecl ClassTemplatePartialSpecializationDecl(ASTContext &C) : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization), - TemplateParams(nullptr), ArgsAsWritten(nullptr), InstantiatedFromMember(nullptr, false) {} + void anchor() override; + public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -2024,12 +2043,10 @@ public: // FIXME: Add Profile support! static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == ClassTemplatePartialSpecialization; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// Declaration of a class template. @@ -2038,8 +2055,6 @@ protected: /// \brief Data that is common to all of the declarations of a given /// class template. struct Common : CommonBase { - Common() : LazySpecializations() { } - /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations; @@ -2052,12 +2067,7 @@ protected: /// \brief The injected-class-name type for this class template. QualType InjectedClassNameType; - /// \brief 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 of specializations/ - /// partial specializations that follow. - uint32_t *LazySpecializations; + Common() = default; }; /// \brief Retrieve the set of specializations of this class template. @@ -2087,12 +2097,15 @@ protected: } public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// \brief Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; /// \brief Get the underlying class declarations of the template. CXXRecordDecl *getTemplatedDecl() const { - return static_cast<CXXRecordDecl *>(TemplatedDecl.getPointer()); + return static_cast<CXXRecordDecl *>(TemplatedDecl); } /// \brief Returns whether this template declaration defines the primary @@ -2132,14 +2145,11 @@ public: } /// \brief Retrieve the previous declaration of this class template, or - /// NULL if no such declaration exists. + /// nullptr if no such declaration exists. ClassTemplateDecl *getPreviousDecl() { return cast_or_null<ClassTemplateDecl>( static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); } - - /// \brief Retrieve the previous declaration of this class template, or - /// NULL if no such declaration exists. const ClassTemplateDecl *getPreviousDecl() const { return cast_or_null<ClassTemplateDecl>( static_cast<const RedeclarableTemplateDecl *>( @@ -2180,7 +2190,7 @@ public: /// template. /// /// \returns the class template partial specialization that exactly matches - /// the type \p T, or NULL if no such partial specialization exists. + /// 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 @@ -2189,8 +2199,8 @@ public: /// \param D a member class template partial specialization. /// /// \returns the class template partial specialization which was instantiated - /// from the given member partial specialization, or NULL if no such partial - /// specialization exists. + /// from the given member partial specialization, or nullptr if no such + /// partial specialization exists. ClassTemplatePartialSpecializationDecl * findPartialSpecInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *D); @@ -2211,8 +2221,8 @@ public: /// \endcode QualType getInjectedClassNameSpecialization(); - typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator; - typedef llvm::iterator_range<spec_iterator> spec_range; + using spec_iterator = SpecIterator<ClassTemplateSpecializationDecl>; + using spec_range = llvm::iterator_range<spec_iterator>; spec_range specializations() const { return spec_range(spec_begin(), spec_end()); @@ -2229,9 +2239,6 @@ public: // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ClassTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Declaration of a friend template. @@ -2249,15 +2256,16 @@ public: /// will yield a FriendDecl, not a FriendTemplateDecl. class FriendTemplateDecl : public Decl { virtual void anchor(); + public: - typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; + using FriendUnion = llvm::PointerUnion<NamedDecl *,TypeSourceInfo *>; private: // The number of template parameters; always non-zero. - unsigned NumParams; + unsigned NumParams = 0; // The parameter list. - TemplateParameterList **Params; + TemplateParameterList **Params = nullptr; // The declaration that's a friend of this class. FriendUnion Friend; @@ -2271,13 +2279,11 @@ private: : Decl(Decl::FriendTemplate, DC, Loc), NumParams(Params.size()), Params(Params.data()), Friend(Friend), FriendLoc(FriendLoc) {} - FriendTemplateDecl(EmptyShell Empty) - : Decl(Decl::FriendTemplate, Empty), - NumParams(0), - Params(nullptr) - {} + FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty) {} public: + friend class ASTDeclReader; + static FriendTemplateDecl * Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc, MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend, @@ -2316,8 +2322,6 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } - - friend class ASTDeclReader; }; /// \brief Declaration of an alias template. @@ -2328,7 +2332,7 @@ public: /// \endcode class TypeAliasTemplateDecl : public RedeclarableTemplateDecl { protected: - typedef CommonBase Common; + using Common = CommonBase; TypeAliasTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, @@ -2343,9 +2347,12 @@ protected: } public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// Get the underlying function declaration of the template. TypeAliasDecl *getTemplatedDecl() const { - return static_cast<TypeAliasDecl *>(TemplatedDecl.getPointer()); + return static_cast<TypeAliasDecl *>(TemplatedDecl); } @@ -2359,14 +2366,11 @@ public: } /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. + /// nullptr if no such declaration exists. TypeAliasTemplateDecl *getPreviousDecl() { return cast_or_null<TypeAliasTemplateDecl>( static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. const TypeAliasTemplateDecl *getPreviousDecl() const { return cast_or_null<TypeAliasTemplateDecl>( static_cast<const RedeclarableTemplateDecl *>( @@ -2378,7 +2382,6 @@ public: RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } - /// \brief Create a function template node. static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -2392,9 +2395,6 @@ public: // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TypeAliasTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Declaration of a function specialization at template class scope. @@ -2414,7 +2414,9 @@ public: /// CXXMethodDecl. Then during an instantiation of class A, it will be /// transformed into an actual function specialization. class ClassScopeFunctionSpecializationDecl : public Decl { - virtual void anchor(); + CXXMethodDecl *Specialization; + bool HasExplicitTemplateArgs; + TemplateArgumentListInfo TemplateArgs; ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD, bool Args, @@ -2424,13 +2426,14 @@ class ClassScopeFunctionSpecializationDecl : public Decl { TemplateArgs(std::move(TemplArgs)) {} ClassScopeFunctionSpecializationDecl(EmptyShell Empty) - : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} + : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} - CXXMethodDecl *Specialization; - bool HasExplicitTemplateArgs; - TemplateArgumentListInfo TemplateArgs; + virtual void anchor(); public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + CXXMethodDecl *getSpecialization() const { return Specialization; } bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; } @@ -2450,17 +2453,15 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::ClassScopeFunctionSpecialization; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// Implementation of inline functions that require the template declarations inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) - : Function(FTD) { } + : Function(FTD) {} /// \brief Represents a variable template specialization, which refers to /// a variable template with a given set of template arguments. @@ -2498,19 +2499,20 @@ class VarTemplateSpecializationDecl : public VarDecl, /// \brief Further info for explicit template specialization/instantiation. struct ExplicitSpecializationInfo { /// \brief The type-as-written. - TypeSourceInfo *TypeAsWritten; + TypeSourceInfo *TypeAsWritten = nullptr; + /// \brief The location of the extern keyword. SourceLocation ExternLoc; + /// \brief The location of the template keyword. SourceLocation TemplateKeywordLoc; - ExplicitSpecializationInfo() - : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {} + ExplicitSpecializationInfo() = default; }; /// \brief Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - ExplicitSpecializationInfo *ExplicitInfo; + ExplicitSpecializationInfo *ExplicitInfo = nullptr; /// \brief The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; @@ -2523,6 +2525,12 @@ class VarTemplateSpecializationDecl : public VarDecl, /// Really a value of type TemplateSpecializationKind. unsigned SpecializationKind : 3; + /// \brief 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. + unsigned IsCompleteDefinition : 1; + protected: VarTemplateSpecializationDecl(Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -2534,6 +2542,10 @@ protected: explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context); public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend class VarDecl; + static VarTemplateSpecializationDecl * Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, @@ -2596,6 +2608,8 @@ public: PointOfInstantiation = Loc; } + void setCompleteDefinition() { IsCompleteDefinition = true; } + /// \brief If this variable template specialization is an instantiation of /// a template (rather than an explicit specialization), return the /// variable template or variable template partial specialization from which @@ -2668,6 +2682,7 @@ public: ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TypeAsWritten = T; } + /// \brief Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { @@ -2678,6 +2693,7 @@ public: SourceLocation getExternLoc() const { return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); } + /// \brief Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc) { if (!ExplicitInfo) @@ -2691,6 +2707,7 @@ public: ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TemplateKeywordLoc = Loc; } + /// \brief Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); @@ -2709,25 +2726,21 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K >= firstVarTemplateSpecialization && K <= lastVarTemplateSpecialization; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; class VarTemplatePartialSpecializationDecl : public VarTemplateSpecializationDecl { - void anchor() override; - /// \brief The list of template parameters - TemplateParameterList *TemplateParams; + TemplateParameterList *TemplateParams = nullptr; /// \brief The source info for the template arguments as written. /// FIXME: redundant with TypeAsWritten? - const ASTTemplateArgumentListInfo *ArgsAsWritten; + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; /// \brief The variable template partial specialization from which this /// variable template partial specialization was instantiated. @@ -2745,11 +2758,16 @@ class VarTemplatePartialSpecializationDecl const ASTTemplateArgumentListInfo *ArgInfos); VarTemplatePartialSpecializationDecl(ASTContext &Context) - : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context), - TemplateParams(nullptr), ArgsAsWritten(nullptr), - InstantiatedFromMember(nullptr, false) {} + : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, + Context), + InstantiatedFromMember(nullptr, false) {} + + void anchor() override; public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + static VarTemplatePartialSpecializationDecl * Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, @@ -2841,12 +2859,10 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == VarTemplatePartialSpecialization; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// Declaration of a variable template. @@ -2855,8 +2871,6 @@ protected: /// \brief Data that is common to all of the declarations of a given /// variable template. struct Common : CommonBase { - Common() : LazySpecializations() {} - /// \brief The variable template specializations for this variable /// template, including explicit specializations and instantiations. llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations; @@ -2866,12 +2880,7 @@ protected: llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> PartialSpecializations; - /// \brief If non-null, points to an array of specializations (including - /// partial specializations) known ownly by their external declaration IDs. - /// - /// The first value in the array is the number of of specializations/ - /// partial specializations that follow. - uint32_t *LazySpecializations; + Common() = default; }; /// \brief Retrieve the set of specializations of this variable template. @@ -2895,12 +2904,15 @@ protected: } public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// \brief Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; /// \brief Get the underlying variable declarations of the template. VarDecl *getTemplatedDecl() const { - return static_cast<VarDecl *>(TemplatedDecl.getPointer()); + return static_cast<VarDecl *>(TemplatedDecl); } /// \brief Returns whether this template declaration defines the primary @@ -2937,14 +2949,11 @@ public: } /// \brief Retrieve the previous declaration of this variable template, or - /// NULL if no such declaration exists. + /// nullptr if no such declaration exists. VarTemplateDecl *getPreviousDecl() { return cast_or_null<VarTemplateDecl>( static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl()); } - - /// \brief Retrieve the previous declaration of this variable template, or - /// NULL if no such declaration exists. const VarTemplateDecl *getPreviousDecl() const { return cast_or_null<VarTemplateDecl>( static_cast<const RedeclarableTemplateDecl *>( @@ -2986,13 +2995,13 @@ public: /// /// \returns the variable template partial specialization which was /// instantiated - /// from the given member partial specialization, or NULL if no such partial - /// specialization exists. + /// from the given member partial specialization, or nullptr if no such + /// partial specialization exists. VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember( VarTemplatePartialSpecializationDecl *D); - typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator; - typedef llvm::iterator_range<spec_iterator> spec_range; + using spec_iterator = SpecIterator<VarTemplateSpecializationDecl>; + using spec_range = llvm::iterator_range<spec_iterator>; spec_range specializations() const { return spec_range(spec_begin(), spec_end()); @@ -3009,9 +3018,6 @@ public: // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == VarTemplate; } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; inline NamedDecl *getAsNamedDecl(TemplateParameter P) { @@ -3032,6 +3038,6 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { : nullptr; } -} /* end of namespace clang */ +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_DECLTEMPLATE_H diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h index 4eaae35778b9..3ff274bd6a7a 100644 --- a/include/clang/AST/DeclVisitor.h +++ b/include/clang/AST/DeclVisitor.h @@ -1,4 +1,4 @@ -//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- C++ -*-===// +//===- DeclVisitor.h - Visitor for Decl subclasses --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,27 +10,30 @@ // This file defines the DeclVisitor interface. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_AST_DECLVISITOR_H #define LLVM_CLANG_AST_DECLVISITOR_H #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" +#include "llvm/Support/ErrorHandling.h" namespace clang { + namespace declvisitor { -template <typename T> struct make_ptr { typedef T *type; }; -template <typename T> struct make_const_ptr { typedef const T *type; }; +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. template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> class Base { public: - #define PTR(CLASS) typename Ptr<CLASS>::type #define DISPATCH(NAME, CLASS) \ return static_cast<ImplClass*>(this)->Visit##NAME(static_cast<PTR(CLASS)>(D)) @@ -57,23 +60,23 @@ public: #undef DISPATCH }; -} // end namespace declvisitor +} // namespace declvisitor /// \brief A simple visitor class that helps create declaration visitors. /// /// This class does not preserve constness of Decl pointers (see also /// ConstDeclVisitor). -template<typename ImplClass, typename RetTy=void> +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. /// /// This class preserves constness of Decl pointers (see also DeclVisitor). -template<typename ImplClass, typename RetTy=void> +template<typename ImplClass, typename RetTy = void> class ConstDeclVisitor : public declvisitor::Base<declvisitor::make_const_ptr, ImplClass, RetTy> {}; -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_AST_DECLVISITOR_H diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 5e773c968384..467b02c52b0c 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -1,4 +1,4 @@ -//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===// +//===- DeclarationName.h - Representation of declaration names --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,36 +10,42 @@ // This file declares the DeclarationName and DeclarationNameTable classes. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_AST_DECLARATIONNAME_H #define LLVM_CLANG_AST_DECLARATIONNAME_H +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/Compiler.h" - -namespace llvm { - template <typename T> struct DenseMapInfo; -} +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstdint> +#include <cstring> +#include <string> namespace clang { - class ASTContext; - class CXXDeductionGuideNameExtra; - class CXXLiteralOperatorIdName; - class CXXOperatorIdName; - class CXXSpecialName; - class DeclarationNameExtra; - class IdentifierInfo; - class MultiKeywordSelector; - enum OverloadedOperatorKind : int; - struct PrintingPolicy; - class QualType; - class TemplateDecl; - class Type; - class TypeSourceInfo; - class UsingDirectiveDecl; - - template <typename> class CanQual; - typedef CanQual<Type> CanQualType; + +class ASTContext; +template <typename> class CanQual; +class CXXDeductionGuideNameExtra; +class CXXLiteralOperatorIdName; +class CXXOperatorIdName; +class CXXSpecialName; +class DeclarationNameExtra; +class IdentifierInfo; +class MultiKeywordSelector; +enum OverloadedOperatorKind : int; +struct PrintingPolicy; +class QualType; +class TemplateDecl; +class Type; +class TypeSourceInfo; +class UsingDirectiveDecl; + +using CanQualType = CanQual<Type>; /// DeclarationName - The name of a declaration. In the common case, /// this just stores an IdentifierInfo pointer to a normal @@ -63,9 +69,13 @@ public: CXXLiteralOperatorName, CXXUsingDirective }; + static const unsigned NumNameKinds = CXXUsingDirective + 1; private: + friend class DeclarationNameTable; + friend class NamedDecl; + /// StoredNameKind - The kind of name that is actually stored in the /// upper bits of the Ptr field. This is only used internally. /// @@ -99,7 +109,18 @@ private: /// DeclarationNameExtra structure, whose first value will tell us /// whether this is an Objective-C selector, C++ operator-id name, /// or special C++ name. - uintptr_t Ptr; + uintptr_t Ptr = 0; + + // Construct a declaration name from the name of a C++ constructor, + // destructor, or conversion function. + DeclarationName(DeclarationNameExtra *Name) + : Ptr(reinterpret_cast<uintptr_t>(Name)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra"); + Ptr |= StoredDeclarationNameExtra; + } + + /// Construct a declaration name from a raw pointer. + DeclarationName(uintptr_t Ptr) : Ptr(Ptr) {} /// getStoredNameKind - Return the kind of object that is stored in /// Ptr. @@ -146,36 +167,22 @@ private: return nullptr; } - // Construct a declaration name from the name of a C++ constructor, - // destructor, or conversion function. - DeclarationName(DeclarationNameExtra *Name) - : Ptr(reinterpret_cast<uintptr_t>(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra"); - Ptr |= StoredDeclarationNameExtra; - } - - /// Construct a declaration name from a raw pointer. - DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { } - - friend class DeclarationNameTable; - friend class NamedDecl; - /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer /// for this name as a void pointer if it's not an identifier. void *getFETokenInfoAsVoidSlow() const; public: /// DeclarationName - Used to create an empty selector. - DeclarationName() : Ptr(0) { } + DeclarationName() = default; // Construct a declaration name from an IdentifierInfo *. DeclarationName(const IdentifierInfo *II) - : Ptr(reinterpret_cast<uintptr_t>(II)) { + : Ptr(reinterpret_cast<uintptr_t>(II)) { assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); } // Construct a declaration name from an Objective-C selector. - DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) { } + DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) {} /// getUsingDirectiveName - Return name for all using-directives. static DeclarationName getUsingDirectiveName(); @@ -344,16 +351,24 @@ inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { /// getCXXConstructorName). class DeclarationNameTable { const ASTContext &Ctx; - void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> * - CXXOperatorIdName *CXXOperatorNames; // Operator names - void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName* - void *CXXDeductionGuideNames; // FoldingSet<CXXDeductionGuideNameExtra> * - DeclarationNameTable(const DeclarationNameTable&) = delete; - void operator=(const DeclarationNameTable&) = delete; + // Actually a FoldingSet<CXXSpecialName> * + void *CXXSpecialNamesImpl; + + // Operator names + CXXOperatorIdName *CXXOperatorNames; + + // Actually a CXXOperatorIdName* + void *CXXLiteralOperatorNames; + + // FoldingSet<CXXDeductionGuideNameExtra> * + void *CXXDeductionGuideNames; public: DeclarationNameTable(const ASTContext &C); + DeclarationNameTable(const DeclarationNameTable &) = delete; + DeclarationNameTable &operator=(const DeclarationNameTable &) = delete; + ~DeclarationNameTable(); /// getIdentifier - Create a declaration name that is a simple @@ -428,10 +443,10 @@ struct DeclarationNameLoc { }; DeclarationNameLoc(DeclarationName Name); + // FIXME: this should go away once all DNLocs are properly initialized. DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); } -}; // struct DeclarationNameLoc - +}; /// DeclarationNameInfo - A collector data type for bundling together /// a DeclarationName and the correspnding source/type location info. @@ -439,29 +454,33 @@ struct DeclarationNameInfo { private: /// Name - The declaration name, also encoding name kind. DeclarationName Name; + /// Loc - The main source location for the declaration name. SourceLocation NameLoc; + /// Info - Further source/type location info for special kinds of names. DeclarationNameLoc LocInfo; public: // FIXME: remove it. - DeclarationNameInfo() {} + DeclarationNameInfo() = default; DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc) - : Name(Name), NameLoc(NameLoc), LocInfo(Name) {} + : Name(Name), NameLoc(NameLoc), LocInfo(Name) {} DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc, DeclarationNameLoc LocInfo) - : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {} + : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {} /// getName - Returns the embedded declaration name. DeclarationName getName() const { return Name; } + /// setName - Sets the embedded declaration name. void setName(DeclarationName N) { Name = N; } /// getLoc - Returns the main location of the declaration name. SourceLocation getLoc() const { return NameLoc; } + /// setLoc - Sets the main location of the declaration name. void setLoc(SourceLocation L) { NameLoc = L; } @@ -477,6 +496,7 @@ public: Name.getNameKind() == DeclarationName::CXXConversionFunctionName); return LocInfo.NamedType.TInfo; } + /// setNamedTypeInfo - Sets the source type info associated to /// the name. Assumes it is a constructor, destructor or conversion. void setNamedTypeInfo(TypeSourceInfo *TInfo) { @@ -495,6 +515,7 @@ public: SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc) ); } + /// setCXXOperatorNameRange - Sets the range of the operator name /// (without the operator keyword). Assumes it is a C++ operator. void setCXXOperatorNameRange(SourceRange R) { @@ -511,6 +532,7 @@ public: return SourceLocation:: getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc); } + /// setCXXLiteralOperatorNameLoc - Sets the location of the literal /// operator name (not the operator keyword). /// Assumes it is a literal operator. @@ -534,15 +556,19 @@ public: /// getBeginLoc - Retrieve the location of the first token. SourceLocation getBeginLoc() const { return NameLoc; } + /// getEndLoc - Retrieve the location of the last token. SourceLocation getEndLoc() const; + /// getSourceRange - The range of the declaration name. SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocStart(), getLocEnd()); } + SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { SourceLocation EndLoc = getEndLoc(); return EndLoc.isValid() ? EndLoc : getLocStart(); @@ -573,9 +599,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, return OS; } -} // end namespace clang +} // namespace clang namespace llvm { + /// Define DenseMapInfo so that DeclarationNames can be used as keys /// in DenseMap and DenseSets. template<> @@ -601,6 +628,6 @@ struct DenseMapInfo<clang::DeclarationName> { template <> struct isPodLike<clang::DeclarationName> { static const bool value = true; }; -} // end namespace llvm +} // namespace llvm -#endif +#endif // LLVM_CLANG_AST_DECLARATIONNAME_H diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h index 8e038c83c989..a514326c6cb1 100644 --- a/include/clang/AST/DependentDiagnostic.h +++ b/include/clang/AST/DependentDiagnostic.h @@ -1,4 +1,4 @@ -//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=// +//==- DependentDiagnostic.h - Dependently-generated diagnostics --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -23,6 +23,9 @@ #include "clang/AST/Type.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include <cassert> +#include <iterator> namespace clang { @@ -94,6 +97,9 @@ public: } private: + friend class DeclContext::ddiag_iterator; + friend class DependentStoredDeclsMap; + DependentDiagnostic(const PartialDiagnostic &PDiag, PartialDiagnostic::Storage *Storage) : Diag(PDiag, Storage) {} @@ -102,8 +108,6 @@ private: DeclContext *Parent, const PartialDiagnostic &PDiag); - friend class DependentStoredDeclsMap; - friend class DeclContext::ddiag_iterator; DependentDiagnostic *NextDiagnostic; PartialDiagnostic Diag; @@ -118,19 +122,17 @@ private: } AccessData; }; -/// - /// An iterator over the dependent diagnostics in a dependent context. class DeclContext::ddiag_iterator { public: - ddiag_iterator() : Ptr(nullptr) {} + ddiag_iterator() = default; explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} - typedef DependentDiagnostic *value_type; - typedef DependentDiagnostic *reference; - typedef DependentDiagnostic *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; + using value_type = DependentDiagnostic *; + using reference = DependentDiagnostic *; + using pointer = DependentDiagnostic *; + using difference_type = int; + using iterator_category = std::forward_iterator_tag; reference operator*() const { return Ptr; } @@ -168,7 +170,7 @@ public: } private: - DependentDiagnostic *Ptr; + DependentDiagnostic *Ptr = nullptr; }; inline DeclContext::ddiag_range DeclContext::ddiags() const { @@ -184,6 +186,6 @@ inline DeclContext::ddiag_range DeclContext::ddiags() const { return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator()); } -} +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 0cdbd2a97ee4..f2770940372f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -24,6 +24,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/SyncScope.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" @@ -274,6 +275,7 @@ public: MLV_LValueCast, // Specialized form of MLV_InvalidExpression. MLV_IncompleteType, MLV_ConstQualified, + MLV_ConstQualifiedField, MLV_ConstAddrSpace, MLV_ArrayType, MLV_NoSetterProperty, @@ -323,6 +325,7 @@ public: CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext CM_NoSetterProperty,// Implicit assignment to ObjC property without setter CM_ConstQualified, + CM_ConstQualifiedField, CM_ConstAddrSpace, CM_ArrayType, CM_IncompleteType @@ -2345,6 +2348,12 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; + bool isCallToStdMove() const { + const FunctionDecl* FD = getDirectCallee(); + return getNumArgs() == 1 && FD && FD->isInStdNamespace() && + FD->getIdentifier() && FD->getIdentifier()->isStr("move"); + } + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCallExprConstant && T->getStmtClass() <= lastCallExprConstant; @@ -2733,7 +2742,6 @@ protected: ty->containsUnexpandedParameterPack()) || (op && op->containsUnexpandedParameterPack()))), Op(op) { - assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; setBasePathSize(BasePathSize); assert(CastConsistency()); @@ -2771,6 +2779,16 @@ public: path_const_iterator path_begin() const { return path_buffer(); } path_const_iterator path_end() const { return path_buffer() + path_size(); } + const FieldDecl *getTargetUnionField() const { + assert(getCastKind() == CK_ToUnion); + return getTargetFieldForToUnionCast(getType(), getSubExpr()->getType()); + } + + static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType, + QualType opType); + static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD, + QualType opType); + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCastExprConstant && T->getStmtClass() <= lastCastExprConstant; @@ -3054,7 +3072,7 @@ public: static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; } bool isEqualityOp() const { return isEqualityOp(getOpcode()); } - static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; } + static bool isComparisonOp(Opcode Opc) { return Opc >= BO_Cmp && Opc<=BO_NE; } bool isComparisonOp() const { return isComparisonOp(getOpcode()); } static Opcode negateComparisonOp(Opcode Opc) { @@ -3113,6 +3131,12 @@ public: return isShiftAssignOp(getOpcode()); } + // Return true if a binary operator using the specified opcode and operands + // would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized + // integer to a pointer. + static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, + Expr *LHS, Expr *RHS); + static bool classof(const Stmt *S) { return S->getStmtClass() >= firstBinaryOperatorConstant && S->getStmtClass() <= lastBinaryOperatorConstant; @@ -3986,6 +4010,10 @@ public: /// initializer)? bool isTransparent() const; + /// Is this the zero initializer {0} in a language which considers it + /// idiomatic? + bool isIdiomaticZeroInitializer(const LangOptions &LangOpts) const; + SourceLocation getLBraceLoc() const { return LBraceLoc; } void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; } SourceLocation getRBraceLoc() const { return RBraceLoc; } @@ -3995,6 +4023,9 @@ public: InitListExpr *getSemanticForm() const { return isSemanticForm() ? nullptr : AltForm.getPointer(); } + bool isSyntacticForm() const { + return !AltForm.getInt() || !AltForm.getPointer(); + } InitListExpr *getSyntacticForm() const { return isSemanticForm() ? AltForm.getPointer() : nullptr; } @@ -5064,9 +5095,11 @@ public: /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the -/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>. -/// All of these instructions take one primary pointer and at least one memory -/// order. +/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>, +/// and corresponding __opencl_atomic_* for OpenCL 2.0. +/// All of these instructions take one primary pointer, at least one memory +/// order. The instructions for which getScopeModel returns non-null value +/// take one synch scope. class AtomicExpr : public Expr { public: enum AtomicOp { @@ -5078,14 +5111,16 @@ public: }; private: + /// \brief 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 }; - Stmt* SubExprs[END_EXPR]; + Stmt *SubExprs[END_EXPR + 1]; unsigned NumSubExprs; SourceLocation BuiltinLoc, RParenLoc; AtomicOp Op; friend class ASTStmtReader; - public: AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t, AtomicOp op, SourceLocation RP); @@ -5103,8 +5138,12 @@ public: Expr *getOrder() const { return cast<Expr>(SubExprs[ORDER]); } + Expr *getScope() const { + assert(getScopeModel() && "No scope"); + return cast<Expr>(SubExprs[NumSubExprs - 1]); + } Expr *getVal1() const { - if (Op == AO__c11_atomic_init) + if (Op == AO__c11_atomic_init || Op == AO__opencl_atomic_init) return cast<Expr>(SubExprs[ORDER]); assert(NumSubExprs > VAL1); return cast<Expr>(SubExprs[VAL1]); @@ -5123,6 +5162,7 @@ public: assert(NumSubExprs > WEAK); return cast<Expr>(SubExprs[WEAK]); } + QualType getValueType() const; AtomicOp getOp() const { return Op; } unsigned getNumSubExprs() const { return NumSubExprs; } @@ -5139,10 +5179,17 @@ public: bool isCmpXChg() const { return getOp() == AO__c11_atomic_compare_exchange_strong || getOp() == AO__c11_atomic_compare_exchange_weak || + getOp() == AO__opencl_atomic_compare_exchange_strong || + getOp() == AO__opencl_atomic_compare_exchange_weak || getOp() == AO__atomic_compare_exchange || getOp() == AO__atomic_compare_exchange_n; } + bool isOpenCL() const { + return getOp() >= AO__opencl_atomic_init && + getOp() <= AO__opencl_atomic_fetch_max; + } + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -5160,6 +5207,24 @@ public: const_child_range children() const { return const_child_range(SubExprs, SubExprs + NumSubExprs); } + + /// \brief 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) { + auto Kind = + (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max) + ? AtomicScopeModelKind::OpenCL + : AtomicScopeModelKind::None; + return AtomicScopeModel::create(Kind); + } + + /// \brief Get atomic scope model. + /// \return empty atomic scope model if this atomic expression does not have + /// scope operand. + std::unique_ptr<AtomicScopeModel> getScopeModel() const { + return getScopeModel(getOp()); + } }; /// TypoExpr - Internal placeholder for expressions where typo correction diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 79d2c58099c4..58054dda31aa 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1,4 +1,4 @@ -//===--- ExprCXX.h - Classes for representing expressions -------*- C++ -*-===// +//===- ExprCXX.h - Classes for representing expressions ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,31 +6,57 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::Expr interface and subclasses for C++ expressions. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXPRCXX_H #define LLVM_CLANG_AST_EXPRCXX_H #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" -#include "clang/AST/LambdaCapture.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" #include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/ExpressionTraits.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Lambda.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "clang/Basic/TypeTraits.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <memory> namespace clang { -class CXXTemporary; -class MSPropertyDecl; -class TemplateArgumentListInfo; -class UuidAttr; +class ASTContext; +class DeclAccessPair; +class IdentifierInfo; +class LambdaCapture; +class NonTypeTemplateParmDecl; +class TemplateParameterList; //===--------------------------------------------------------------------===// // C++ Expressions. @@ -52,23 +78,28 @@ class UuidAttr; class CXXOperatorCallExpr : public CallExpr { /// \brief The overloaded operator. OverloadedOperatorKind Operator; + SourceRange Range; // Only meaningful for floating point types. FPOptions FPFeatures; SourceRange getSourceRangeImpl() const LLVM_READONLY; + public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, ArrayRef<Expr*> args, QualType t, ExprValueKind VK, SourceLocation operatorloc, FPOptions FPFeatures) - : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc), - Operator(Op), FPFeatures(FPFeatures) { + : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc), + Operator(Op), FPFeatures(FPFeatures) { Range = getSourceRangeImpl(); } - explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : - CallExpr(C, CXXOperatorCallExprClass, Empty) { } + explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) + : CallExpr(C, CXXOperatorCallExprClass, Empty) {} /// \brief Returns the kind of overloaded operator that this /// expression refers to. @@ -120,9 +151,6 @@ public: bool isFPContractableWithinStatement() const { return FPFeatures.allowFPContractWithinStatement(); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// Represents a call to a member function that @@ -137,10 +165,10 @@ class CXXMemberCallExpr : public CallExpr { public: CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr*> args, QualType t, ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {} + : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {} CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) - : CallExpr(C, CXXMemberCallExprClass, Empty) { } + : CallExpr(C, CXXMemberCallExprClass, Empty) {} /// \brief Retrieves the implicit object argument for the member call. /// @@ -183,7 +211,7 @@ public: : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP) {} CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty) - : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { } + : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) {} const CallExpr *getConfig() const { return cast_or_null<CallExpr>(getPreArg(CONFIG)); @@ -217,23 +245,28 @@ public: /// reinterpret_cast, and CXXConstCastExpr for \c const_cast. class CXXNamedCastExpr : public ExplicitCastExpr { private: - SourceLocation Loc; // the location of the casting op - SourceLocation RParenLoc; // the location of the right parenthesis - SourceRange AngleBrackets; // range for '<' '>' + // the location of the casting op + SourceLocation Loc; + + // the location of the right parenthesis + SourceLocation RParenLoc; + + // range for '<' '>' + SourceRange AngleBrackets; protected: + friend class ASTStmtReader; + CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) - : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l), - RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} + : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l), + RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) - : ExplicitCastExpr(SC, Shell, PathSize) { } - - friend class ASTStmtReader; + : ExplicitCastExpr(SC, Shell, PathSize) {} public: const char *getCastName() const; @@ -273,13 +306,16 @@ class CXXStaticCastExpr final unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, - writtenTy, l, RParenLoc, AngleBrackets) {} + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, + writtenTy, l, RParenLoc, AngleBrackets) {} explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) - : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } + : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {} public: + friend class CastExpr; + friend TrailingObjects; + static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *Path, @@ -292,9 +328,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXStaticCastExprClass; } - - friend TrailingObjects; - friend class CastExpr; }; /// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). @@ -309,13 +342,16 @@ class CXXDynamicCastExpr final Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, - writtenTy, l, RParenLoc, AngleBrackets) {} + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, + writtenTy, l, RParenLoc, AngleBrackets) {} explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) - : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } + : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {} public: + friend class CastExpr; + friend TrailingObjects; + static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, @@ -331,9 +367,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; } - - friend TrailingObjects; - friend class CastExpr; }; /// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). @@ -353,13 +386,16 @@ class CXXReinterpretCastExpr final TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, - pathSize, writtenTy, l, RParenLoc, AngleBrackets) {} + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, + pathSize, writtenTy, l, RParenLoc, AngleBrackets) {} CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } + : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {} public: + friend class CastExpr; + friend TrailingObjects; + static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, @@ -372,9 +408,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXReinterpretCastExprClass; } - - friend TrailingObjects; - friend class CastExpr; }; /// \brief A C++ \c const_cast expression (C++ [expr.const.cast]). @@ -390,13 +423,16 @@ class CXXConstCastExpr final CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, - 0, writtenTy, l, RParenLoc, AngleBrackets) {} + : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, + 0, writtenTy, l, RParenLoc, AngleBrackets) {} explicit CXXConstCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } + : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {} public: + friend class CastExpr; + friend TrailingObjects; + static CXXConstCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, @@ -407,9 +443,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstCastExprClass; } - - friend TrailingObjects; - friend class CastExpr; }; /// \brief A call to a literal operator (C++11 [over.literal]) @@ -426,22 +459,37 @@ class UserDefinedLiteral : public CallExpr { SourceLocation UDSuffixLoc; public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args, QualType T, ExprValueKind VK, SourceLocation LitEndLoc, SourceLocation SuffixLoc) - : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc), - UDSuffixLoc(SuffixLoc) {} + : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc), + UDSuffixLoc(SuffixLoc) {} + explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty) - : CallExpr(C, UserDefinedLiteralClass, Empty) {} + : CallExpr(C, UserDefinedLiteralClass, Empty) {} /// The kind of literal operator which is invoked. enum LiteralOperatorKind { - LOK_Raw, ///< Raw form: operator "" X (const char *) - LOK_Template, ///< Raw form: operator "" X<cs...> () - LOK_Integer, ///< operator "" X (unsigned long long) - LOK_Floating, ///< operator "" X (long double) - LOK_String, ///< operator "" X (const CharT *, size_t) - LOK_Character ///< operator "" X (CharT) + /// Raw form: operator "" X (const char *) + LOK_Raw, + + /// Raw form: operator "" X<cs...> () + LOK_Template, + + /// operator "" X (unsigned long long) + LOK_Integer, + + /// operator "" X (long double) + LOK_Floating, + + /// operator "" X (const CharT *, size_t) + LOK_String, + + /// operator "" X (CharT) + LOK_Character }; /// \brief Returns the kind of literal operator invocation @@ -461,8 +509,8 @@ public: return getRParenLoc(); return getArg(0)->getLocStart(); } - SourceLocation getLocEnd() const { return getRParenLoc(); } + SourceLocation getLocEnd() const { return getRParenLoc(); } /// \brief Returns the location of a ud-suffix in the expression. /// @@ -476,24 +524,21 @@ public: static bool classof(const Stmt *S) { return S->getStmtClass() == UserDefinedLiteralClass; } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// \brief A boolean literal, per ([C++ lex.bool] Boolean literals). -/// class CXXBoolLiteralExpr : public Expr { bool Value; SourceLocation Loc; + public: - CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : - Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Value(val), Loc(l) {} + CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) + : Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + false, false), + Value(val), Loc(l) {} explicit CXXBoolLiteralExpr(EmptyShell Empty) - : Expr(CXXBoolLiteralExprClass, Empty) { } + : Expr(CXXBoolLiteralExprClass, Empty) {} bool getValue() const { return Value; } void setValue(bool V) { Value = V; } @@ -519,14 +564,15 @@ public: /// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr. class CXXNullPtrLiteralExpr : public Expr { SourceLocation Loc; + public: - CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : - Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Loc(l) {} + CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) + : Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, + false, false, false), + Loc(l) {} explicit CXXNullPtrLiteralExpr(EmptyShell Empty) - : Expr(CXXNullPtrLiteralExprClass, Empty) { } + : Expr(CXXNullPtrLiteralExprClass, Empty) {} SourceLocation getLocStart() const LLVM_READONLY { return Loc; } SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } @@ -546,18 +592,21 @@ public: /// \brief 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; + Stmt *SubExpr = nullptr; CXXStdInitializerListExpr(EmptyShell Empty) - : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {} + : Expr(CXXStdInitializerListExprClass, Empty) {} public: + friend class ASTReader; + friend class ASTStmtReader; + CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) - : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary, - Ty->isDependentType(), SubExpr->isValueDependent(), - SubExpr->isInstantiationDependent(), - SubExpr->containsUnexpandedParameterPack()), - SubExpr(SubExpr) {} + : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary, + Ty->isDependentType(), SubExpr->isValueDependent(), + SubExpr->isInstantiationDependent(), + SubExpr->containsUnexpandedParameterPack()), + SubExpr(SubExpr) {} Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); } const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); } @@ -565,9 +614,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return SubExpr->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return SubExpr->getSourceRange(); } @@ -577,9 +628,6 @@ public: } child_range children() { return child_range(&SubExpr, &SubExpr + 1); } - - friend class ASTReader; - friend class ASTStmtReader; }; /// A C++ \c typeid expression (C++ [expr.typeid]), which gets @@ -594,27 +642,29 @@ private: public: CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) - : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, - // typeid is never type-dependent (C++ [temp.dep.expr]p4) - false, - // typeid is value-dependent if the type or expression are dependent - Operand->getType()->isDependentType(), - Operand->getType()->isInstantiationDependentType(), - Operand->getType()->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, + // typeid is never type-dependent (C++ [temp.dep.expr]p4) + false, + // typeid is value-dependent if the type or expression are + // dependent + Operand->getType()->isDependentType(), + Operand->getType()->isInstantiationDependentType(), + Operand->getType()->containsUnexpandedParameterPack()), + Operand(Operand), Range(R) {} CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) - : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, - // typeid is never type-dependent (C++ [temp.dep.expr]p4) - false, - // typeid is value-dependent if the type or expression are dependent - Operand->isTypeDependent() || Operand->isValueDependent(), - Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, + // typeid is never type-dependent (C++ [temp.dep.expr]p4) + false, + // typeid is value-dependent if the type or expression are + // dependent + Operand->isTypeDependent() || Operand->isValueDependent(), + Operand->isInstantiationDependent(), + Operand->containsUnexpandedParameterPack()), + Operand(Operand), Range(R) {} CXXTypeidExpr(EmptyShell Empty, bool isExpr) - : Expr(CXXTypeidExprClass, Empty) { + : Expr(CXXTypeidExprClass, Empty) { if (isExpr) Operand = (Expr*)nullptr; else @@ -683,26 +733,30 @@ class MSPropertyRefExpr : public Expr { NestedNameSpecifierLoc QualifierLoc; public: + friend class ASTStmtReader; + MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow, QualType ty, ExprValueKind VK, NestedNameSpecifierLoc qualifierLoc, SourceLocation nameLoc) - : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary, - /*type-dependent*/ false, baseExpr->isValueDependent(), - baseExpr->isInstantiationDependent(), - baseExpr->containsUnexpandedParameterPack()), - BaseExpr(baseExpr), TheDecl(decl), - MemberLoc(nameLoc), IsArrow(isArrow), - QualifierLoc(qualifierLoc) {} + : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary, + /*type-dependent*/ false, baseExpr->isValueDependent(), + baseExpr->isInstantiationDependent(), + baseExpr->containsUnexpandedParameterPack()), + BaseExpr(baseExpr), TheDecl(decl), + MemberLoc(nameLoc), IsArrow(isArrow), + QualifierLoc(qualifierLoc) {} MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocStart(), getLocEnd()); } + bool isImplicitAccess() const { return getBaseExpr() && getBaseExpr()->isImplicitCXXThis(); } + SourceLocation getLocStart() const { if (!isImplicitAccess()) return BaseExpr->getLocStart(); @@ -711,11 +765,13 @@ public: else return MemberLoc; } + SourceLocation getLocEnd() const { return getMemberLoc(); } child_range children() { return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1); } + static bool classof(const Stmt *T) { return T->getStmtClass() == MSPropertyRefExprClass; } @@ -725,8 +781,6 @@ public: bool isArrow() const { return IsArrow; } SourceLocation getMemberLoc() const { return MemberLoc; } NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - friend class ASTStmtReader; }; /// MS property subscript expression. @@ -742,7 +796,9 @@ public: /// This is a syntactic pseudo-object expression. class MSPropertySubscriptExpr : public Expr { friend class ASTStmtReader; + enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 }; + Stmt *SubExprs[NUM_SUBEXPRS]; SourceLocation RBracketLoc; @@ -773,6 +829,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return getBase()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } SourceLocation getRBracketLoc() const { return RBracketLoc; } @@ -891,13 +948,13 @@ class CXXThisExpr : public Expr { public: CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit) - : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary, - // 'this' is type-dependent if the class type of the enclosing - // member function is dependent (C++ [temp.dep.expr]p2) - Type->isDependentType(), Type->isDependentType(), - Type->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(L), Implicit(isImplicit) { } + : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary, + // 'this' is type-dependent if the class type of the enclosing + // member function is dependent (C++ [temp.dep.expr]p2) + Type->isDependentType(), Type->isDependentType(), + Type->isInstantiationDependentType(), + /*ContainsUnexpandedParameterPack=*/false), + Loc(L), Implicit(isImplicit) {} CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} @@ -926,23 +983,25 @@ public: /// 'throw' assignment-expression. When assignment-expression isn't /// present, Op will be null. class CXXThrowExpr : public Expr { + friend class ASTStmtReader; + Stmt *Op; SourceLocation ThrowLoc; + /// \brief Whether the thrown variable (if any) is in scope. unsigned IsThrownVariableInScope : 1; - friend class ASTStmtReader; - public: // \p Ty is the void type which is used as the result type of the // expression. The \p l is the location of the throw keyword. \p expr // can by null, if the optional expression to throw isn't present. CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l, - bool IsThrownVariableInScope) : - Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - expr && expr->isInstantiationDependent(), - expr && expr->containsUnexpandedParameterPack()), - Op(expr), ThrowLoc(l), IsThrownVariableInScope(IsThrownVariableInScope) {} + bool IsThrownVariableInScope) + : Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + expr && expr->isInstantiationDependent(), + expr && expr->containsUnexpandedParameterPack()), + Op(expr), ThrowLoc(l), + IsThrownVariableInScope(IsThrownVariableInScope) {} CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } @@ -958,6 +1017,7 @@ public: bool isThrownVariableInScope() const { return IsThrownVariableInScope; } SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { if (!getSubExpr()) return ThrowLoc; @@ -987,15 +1047,19 @@ class CXXDefaultArgExpr final : public Expr { SourceLocation Loc; CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) - : Expr(SC, - param->hasUnparsedDefaultArg() - ? param->getType().getNonReferenceType() - : param->getDefaultArg()->getType(), - param->getDefaultArg()->getValueKind(), - param->getDefaultArg()->getObjectKind(), false, false, false, false), - Param(param), Loc(Loc) { } + : Expr(SC, + param->hasUnparsedDefaultArg() + ? param->getType().getNonReferenceType() + : param->getDefaultArg()->getType(), + param->getDefaultArg()->getValueKind(), + param->getDefaultArg()->getObjectKind(), false, false, false, + false), + Param(param), Loc(Loc) {} public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} // \p Param is the parameter whose default argument is used by this @@ -1036,9 +1100,6 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// \brief A use of a default initializer in a constructor or in aggregate @@ -1062,6 +1123,9 @@ class CXXDefaultInitExpr : public Expr { CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} public: + friend class ASTReader; + friend class ASTStmtReader; + /// \p Field is the non-static data member whose default initializer is used /// by this expression. static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc, @@ -1094,9 +1158,6 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend class ASTReader; - friend class ASTStmtReader; }; /// \brief Represents a C++ temporary. @@ -1105,13 +1166,14 @@ class CXXTemporary { const CXXDestructorDecl *Destructor; explicit CXXTemporary(const CXXDestructorDecl *destructor) - : Destructor(destructor) { } + : Destructor(destructor) {} public: static CXXTemporary *Create(const ASTContext &C, const CXXDestructorDecl *Destructor); const CXXDestructorDecl *getDestructor() const { return Destructor; } + void setDestructor(const CXXDestructorDecl *Dtor) { Destructor = Dtor; } @@ -1132,21 +1194,20 @@ public: /// } /// \endcode class CXXBindTemporaryExpr : public Expr { - CXXTemporary *Temp; - - Stmt *SubExpr; + CXXTemporary *Temp = nullptr; + Stmt *SubExpr = nullptr; CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr) - : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), - VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), - SubExpr->isValueDependent(), - SubExpr->isInstantiationDependent(), - SubExpr->containsUnexpandedParameterPack()), - Temp(temp), SubExpr(SubExpr) { } + : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), + VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), + SubExpr->isValueDependent(), + SubExpr->isInstantiationDependent(), + SubExpr->containsUnexpandedParameterPack()), + Temp(temp), SubExpr(SubExpr) {} public: CXXBindTemporaryExpr(EmptyShell Empty) - : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {} + : Expr(CXXBindTemporaryExprClass, Empty) {} static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); @@ -1162,6 +1223,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return SubExpr->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} // Implement isa/cast/dyncast/etc. @@ -1184,8 +1246,7 @@ public: }; private: - CXXConstructorDecl *Constructor; - + CXXConstructorDecl *Constructor = nullptr; SourceLocation Loc; SourceRange ParenOrBraceRange; unsigned NumArgs : 16; @@ -1195,7 +1256,7 @@ private: unsigned StdInitListInitialization : 1; unsigned ZeroInitialization : 1; unsigned ConstructKind : 2; - Stmt **Args; + Stmt **Args = nullptr; void setConstructor(CXXConstructorDecl *C) { Constructor = C; } @@ -1214,15 +1275,16 @@ protected: /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false), - HadMultipleCandidates(false), ListInitialization(false), - ZeroInitialization(false), ConstructKind(0), Args(nullptr) - { } + : Expr(SC, Empty), NumArgs(0), Elidable(false), + HadMultipleCandidates(false), ListInitialization(false), + ZeroInitialization(false), ConstructKind(0) {} public: + friend class ASTStmtReader; + /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) - : CXXConstructExpr(CXXConstructExprClass, Empty) {} + : CXXConstructExpr(CXXConstructExprClass, Empty) {} static CXXConstructExpr *Create(const ASTContext &C, QualType T, SourceLocation Loc, @@ -1278,10 +1340,10 @@ public: ConstructKind = CK; } - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; - typedef llvm::iterator_range<arg_iterator> arg_range; - typedef llvm::iterator_range<const_arg_iterator> arg_const_range; + using arg_iterator = ExprIterator; + using const_arg_iterator = ConstExprIterator; + using arg_range = llvm::iterator_range<arg_iterator>; + using arg_const_range = llvm::iterator_range<const_arg_iterator>; arg_range arguments() { return arg_range(arg_begin(), arg_end()); } arg_const_range arguments() const { @@ -1329,8 +1391,6 @@ public: child_range children() { return child_range(&Args[0], &Args[0]+NumArgs); } - - friend class ASTStmtReader; }; /// \brief Represents a call to an inherited base class constructor from an @@ -1339,7 +1399,7 @@ public: /// base class constructor. class CXXInheritedCtorInitExpr : public Expr { private: - CXXConstructorDecl *Constructor; + CXXConstructorDecl *Constructor = nullptr; /// The location of the using declaration. SourceLocation Loc; @@ -1352,6 +1412,8 @@ private: unsigned InheritedFromVirtualBase : 1; public: + friend class ASTStmtReader; + /// \brief Construct a C++ inheriting construction expression. CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T, CXXConstructorDecl *Ctor, bool ConstructsVirtualBase, @@ -1366,7 +1428,7 @@ public: /// \brief Construct an empty C++ inheriting construction expression. explicit CXXInheritedCtorInitExpr(EmptyShell Empty) - : Expr(CXXInheritedCtorInitExprClass, Empty), Constructor(nullptr), + : Expr(CXXInheritedCtorInitExprClass, Empty), ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {} /// \brief Get the constructor that this expression will call. @@ -1393,11 +1455,10 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXInheritedCtorInitExprClass; } + child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend class ASTStmtReader; }; /// \brief Represents an explicit C++ type conversion that uses "functional" @@ -1417,14 +1478,17 @@ class CXXFunctionalCastExpr final TypeSourceInfo *writtenTy, CastKind kind, Expr *castExpr, unsigned pathSize, SourceLocation lParenLoc, SourceLocation rParenLoc) - : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, - castExpr, pathSize, writtenTy), - LParenLoc(lParenLoc), RParenLoc(rParenLoc) {} + : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, + castExpr, pathSize, writtenTy), + LParenLoc(lParenLoc), RParenLoc(rParenLoc) {} explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) - : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } + : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {} public: + friend class CastExpr; + friend TrailingObjects; + static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, TypeSourceInfo *Written, @@ -1446,9 +1510,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFunctionalCastExprClass; } - - friend TrailingObjects; - friend class CastExpr; }; /// @brief Represents a C++ functional cast expression that builds a @@ -1467,9 +1528,11 @@ public: /// }; /// \endcode class CXXTemporaryObjectExpr : public CXXConstructExpr { - TypeSourceInfo *Type; + TypeSourceInfo *Type = nullptr; public: + friend class ASTStmtReader; + CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, QualType Type, @@ -1481,7 +1544,7 @@ public: bool StdInitListInitialization, bool ZeroInitialization); explicit CXXTemporaryObjectExpr(EmptyShell Empty) - : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } + : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) {} TypeSourceInfo *getTypeSourceInfo() const { return Type; } @@ -1491,8 +1554,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTemporaryObjectExprClass; } - - friend class ASTStmtReader; }; /// \brief A C++ lambda expression, which produces a function object @@ -1558,9 +1619,9 @@ class LambdaExpr final : public Expr, /// \brief Construct an empty lambda expression. LambdaExpr(EmptyShell Empty, unsigned NumCaptures) - : Expr(LambdaExprClass, Empty), - NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), - ExplicitResultType(false) { + : Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures), + CaptureDefault(LCD_None), ExplicitParams(false), + ExplicitResultType(false) { getStoredStmts()[NumCaptures] = nullptr; } @@ -1569,6 +1630,10 @@ class LambdaExpr final : public Expr, Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// \brief Construct a new lambda expression. static LambdaExpr * Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, @@ -1597,10 +1662,10 @@ public: /// \brief An iterator that walks over the captures of the lambda, /// both implicit and explicit. - typedef const LambdaCapture *capture_iterator; + using capture_iterator = const LambdaCapture *; /// \brief An iterator over a range of lambda captures. - typedef llvm::iterator_range<capture_iterator> capture_range; + using capture_range = llvm::iterator_range<capture_iterator>; /// \brief Retrieve this lambda's captures. capture_range captures() const; @@ -1639,11 +1704,11 @@ public: /// \brief Iterator that walks over the capture initialization /// arguments. - typedef Expr **capture_init_iterator; + using capture_init_iterator = Expr **; /// \brief Const iterator that walks over the capture initialization /// arguments. - typedef Expr *const *const_capture_init_iterator; + using const_capture_init_iterator = Expr *const *; /// \brief Retrieve the initialization expressions for this lambda's captures. llvm::iterator_range<capture_init_iterator> capture_inits() { @@ -1723,26 +1788,23 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return IntroducerRange.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; } child_range children() { // Includes initialization exprs plus body stmt return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1); } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// An expression "T()" which creates a value-initialized rvalue of type /// T, which is a non-class type. See (C++98 [5.2.3p2]). class CXXScalarValueInitExpr : public Expr { + friend class ASTStmtReader; + SourceLocation RParenLoc; TypeSourceInfo *TypeInfo; - friend class ASTStmtReader; - public: /// \brief Create an explicitly-written scalar-value initialization /// expression. @@ -1754,7 +1816,7 @@ public: RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} explicit CXXScalarValueInitExpr(EmptyShell Shell) - : Expr(CXXScalarValueInitExprClass, Shell) { } + : Expr(CXXScalarValueInitExprClass, Shell) {} TypeSourceInfo *getTypeSourceInfo() const { return TypeInfo; @@ -1778,11 +1840,16 @@ public: /// \brief Represents a new-expression for memory allocation and constructor /// calls, e.g: "new CXXNewExpr(foo)". class CXXNewExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + /// Contains an optional array size expression, an optional initialization /// expression, and any number of optional placement arguments, in that order. - Stmt **SubExprs; + Stmt **SubExprs = nullptr; + /// \brief Points to the allocation function used. FunctionDecl *OperatorNew; + /// \brief Points to the deallocation function used in case of error. May be /// null. FunctionDecl *OperatorDelete; @@ -1802,27 +1869,35 @@ class CXXNewExpr : public Expr { /// Was the usage ::new, i.e. is the global new to be used? unsigned GlobalNew : 1; + /// Do we allocate an array? If so, the first SubExpr is the size expression. unsigned Array : 1; + /// Should the alignment be passed to the allocation function? unsigned PassAlignment : 1; + /// If this is an array allocation, does the usual deallocation /// function for the allocated type want to know the allocated size? unsigned UsualArrayDeleteWantsSize : 1; + /// The number of placement new arguments. unsigned NumPlacementArgs : 26; + /// What kind of initializer do we have? Could be none, parens, or braces. /// In storage, we distinguish between "none, and no initializer expr", and /// "none, but an implicit initializer expr". unsigned StoredInitializationStyle : 2; - friend class ASTStmtReader; - friend class ASTStmtWriter; public: enum InitializationStyle { - NoInit, ///< New-expression has no initializer as written. - CallInit, ///< New-expression has a C++98 paren-delimited initializer. - ListInit ///< New-expression has a C++11 list-initializer. + /// New-expression has no initializer as written. + NoInit, + + /// New-expression has a C++98 paren-delimited initializer. + CallInit, + + /// New-expression has a C++11 list-initializer. + ListInit }; CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, @@ -1833,7 +1908,7 @@ public: QualType ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange directInitRange); explicit CXXNewExpr(EmptyShell Shell) - : Expr(CXXNewExprClass, Shell), SubExprs(nullptr) { } + : Expr(CXXNewExprClass, Shell) {} void AllocateArgsArray(const ASTContext &C, bool isArray, unsigned numPlaceArgs, bool hasInitializer); @@ -1870,6 +1945,7 @@ public: void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } bool isArray() const { return Array; } + Expr *getArraySize() { return Array ? cast<Expr>(SubExprs[0]) : nullptr; } @@ -1878,6 +1954,7 @@ public: } unsigned getNumPlacementArgs() const { return NumPlacementArgs; } + Expr **getPlacementArgs() { return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer()); } @@ -1932,8 +2009,8 @@ public: return UsualArrayDeleteWantsSize; } - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; + using arg_iterator = ExprIterator; + using const_arg_iterator = ConstExprIterator; llvm::iterator_range<arg_iterator> placement_arguments() { return llvm::make_range(placement_arg_begin(), placement_arg_end()); @@ -1956,7 +2033,8 @@ public: return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } - typedef Stmt **raw_arg_iterator; + using raw_arg_iterator = Stmt **; + raw_arg_iterator raw_arg_begin() { return SubExprs; } raw_arg_iterator raw_arg_end() { return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); @@ -1974,6 +2052,7 @@ public: SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return getStartLoc(); } SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } @@ -1991,36 +2070,43 @@ public: /// destructor calls, e.g. "delete[] pArray". class CXXDeleteExpr : public Expr { /// Points to the operator delete overload that is used. Could be a member. - FunctionDecl *OperatorDelete; + FunctionDecl *OperatorDelete = nullptr; + /// The pointer expression to be deleted. - Stmt *Argument; + Stmt *Argument = nullptr; + /// Location of the expression. SourceLocation Loc; + /// Is this a forced global delete, i.e. "::delete"? bool GlobalDelete : 1; + /// Is this the array form of delete, i.e. "delete[]"? bool ArrayForm : 1; + /// ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied /// to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm /// will be true). bool ArrayFormAsWritten : 1; + /// Does the usual deallocation function for the element type require /// a size_t argument? bool UsualArrayDeleteWantsSize : 1; + public: + friend class ASTStmtReader; + CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, bool arrayFormAsWritten, bool usualArrayDeleteWantsSize, FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) - : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, - arg->isInstantiationDependent(), - arg->containsUnexpandedParameterPack()), - OperatorDelete(operatorDelete), Argument(arg), Loc(loc), - GlobalDelete(globalDelete), - ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { } - explicit CXXDeleteExpr(EmptyShell Shell) - : Expr(CXXDeleteExprClass, Shell), OperatorDelete(nullptr), - Argument(nullptr) {} + : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, + arg->isInstantiationDependent(), + arg->containsUnexpandedParameterPack()), + OperatorDelete(operatorDelete), Argument(arg), Loc(loc), + GlobalDelete(globalDelete), + ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), + UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {} + explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {} bool isGlobalDelete() const { return GlobalDelete; } bool isArrayForm() const { return ArrayForm; } @@ -2054,8 +2140,6 @@ public: // Iterators child_range children() { return child_range(&Argument, &Argument+1); } - - friend class ASTStmtReader; }; /// \brief Stores the type being destroyed by a pseudo-destructor expression. @@ -2068,10 +2152,10 @@ class PseudoDestructorTypeStorage { SourceLocation Location; public: - PseudoDestructorTypeStorage() { } + PseudoDestructorTypeStorage() = default; PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc) - : Type(II), Location(Loc) { } + : Type(II), Location(Loc) {} PseudoDestructorTypeStorage(TypeSourceInfo *Info); @@ -2111,8 +2195,10 @@ public: /// for scalar types. A pseudo-destructor expression has no run-time semantics /// beyond evaluating the base expression. class CXXPseudoDestructorExpr : public Expr { + friend class ASTStmtReader; + /// \brief The base expression (that is being destroyed). - Stmt *Base; + Stmt *Base = nullptr; /// \brief Whether the operator was an arrow ('->'); otherwise, it was a /// period ('.'). @@ -2126,7 +2212,7 @@ class CXXPseudoDestructorExpr : public Expr { /// \brief The type that precedes the '::' in a qualified pseudo-destructor /// expression. - TypeSourceInfo *ScopeType; + TypeSourceInfo *ScopeType = nullptr; /// \brief The location of the '::' in a qualified pseudo-destructor /// expression. @@ -2139,8 +2225,6 @@ class CXXPseudoDestructorExpr : public Expr { /// resolve the name. PseudoDestructorTypeStorage DestroyedType; - friend class ASTStmtReader; - public: CXXPseudoDestructorExpr(const ASTContext &Context, Expr *Base, bool isArrow, SourceLocation OperatorLoc, @@ -2151,8 +2235,7 @@ public: PseudoDestructorTypeStorage DestroyedType); explicit CXXPseudoDestructorExpr(EmptyShell Shell) - : Expr(CXXPseudoDestructorExprClass, Shell), - Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { } + : Expr(CXXPseudoDestructorExprClass, Shell), IsArrow(false) {} Expr *getBase() const { return cast<Expr>(Base); } @@ -2270,13 +2353,17 @@ class TypeTraitExpr final SourceLocation RParenLoc, bool Value); - TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { } + TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) {} size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const { return getNumArgs(); } public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// \brief Create a new type trait expression. static TypeTraitExpr *Create(const ASTContext &C, QualType T, SourceLocation Loc, TypeTrait Kind, @@ -2323,10 +2410,6 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// \brief An Embarcadero array type trait, as used in the implementation of @@ -2338,13 +2421,11 @@ public: /// __array_extent(int, 1) == 20 /// \endcode class ArrayTypeTraitExpr : public Expr { - virtual void anchor(); - /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned. unsigned ATT : 2; /// \brief The value of the type trait. Unspecified if dependent. - uint64_t Value; + uint64_t Value = 0; /// \brief The array dimension being queried, or -1 if not used. Expr *Dimension; @@ -2356,26 +2437,28 @@ class ArrayTypeTraitExpr : public Expr { SourceLocation RParen; /// \brief The type being queried. - TypeSourceInfo *QueriedType; + TypeSourceInfo *QueriedType = nullptr; + + virtual void anchor(); public: + friend class ASTStmtReader; + ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, TypeSourceInfo *queried, uint64_t value, Expr *dimension, SourceLocation rparen, QualType ty) - : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, - false, queried->getType()->isDependentType(), - (queried->getType()->isInstantiationDependentType() || - (dimension && dimension->isInstantiationDependent())), - queried->getType()->containsUnexpandedParameterPack()), - ATT(att), Value(value), Dimension(dimension), - Loc(loc), RParen(rparen), QueriedType(queried) { } - + : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, + false, queried->getType()->isDependentType(), + (queried->getType()->isInstantiationDependentType() || + (dimension && dimension->isInstantiationDependent())), + queried->getType()->containsUnexpandedParameterPack()), + ATT(att), Value(value), Dimension(dimension), + Loc(loc), RParen(rparen), QueriedType(queried) {} explicit ArrayTypeTraitExpr(EmptyShell Empty) - : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false), - QueriedType() { } + : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {} - virtual ~ArrayTypeTraitExpr() { } + virtual ~ArrayTypeTraitExpr() = default; SourceLocation getLocStart() const LLVM_READONLY { return Loc; } SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } @@ -2398,8 +2481,6 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend class ASTStmtReader; }; /// \brief An expression trait intrinsic. @@ -2412,6 +2493,7 @@ public: class ExpressionTraitExpr : public Expr { /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned. unsigned ET : 31; + /// \brief The value of the type trait. Unspecified if dependent. unsigned Value : 1; @@ -2422,23 +2504,25 @@ class ExpressionTraitExpr : public Expr { SourceLocation RParen; /// \brief The expression being queried. - Expr* QueriedExpression; + Expr* QueriedExpression = nullptr; + public: + friend class ASTStmtReader; + ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried, bool value, SourceLocation rparen, QualType resultType) - : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, - false, // Not type-dependent - // Value-dependent if the argument is type-dependent. - queried->isTypeDependent(), - queried->isInstantiationDependent(), - queried->containsUnexpandedParameterPack()), - ET(et), Value(value), Loc(loc), RParen(rparen), - QueriedExpression(queried) { } + : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, + false, // Not type-dependent + // Value-dependent if the argument is type-dependent. + queried->isTypeDependent(), + queried->isInstantiationDependent(), + queried->containsUnexpandedParameterPack()), + ET(et), Value(value), Loc(loc), RParen(rparen), + QueriedExpression(queried) {} explicit ExpressionTraitExpr(EmptyShell Empty) - : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), - QueriedExpression() { } + : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {} SourceLocation getLocStart() const LLVM_READONLY { return Loc; } SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } @@ -2457,11 +2541,8 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend class ASTStmtReader; }; - /// \brief A reference to an overloaded function set, either an /// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. class OverloadExpr : public Expr { @@ -2475,13 +2556,26 @@ class OverloadExpr : public Expr { /// include UsingShadowDecls. Access is relative to the naming /// class. // FIXME: Allocate this data after the OverloadExpr subclass. - DeclAccessPair *Results; - unsigned NumResults; + DeclAccessPair *Results = nullptr; + + unsigned NumResults = 0; protected: /// \brief Whether the name includes info for explicit template /// keyword and arguments. - bool HasTemplateKWAndArgsInfo; + bool HasTemplateKWAndArgsInfo = false; + + OverloadExpr(StmtClass K, const ASTContext &C, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent, + bool KnownInstantiationDependent, + bool KnownContainsUnexpandedParameterPack); + + OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty) {} /// \brief Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo * @@ -2496,25 +2590,14 @@ protected: /// Return the optional template arguments. TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below - OverloadExpr(StmtClass K, const ASTContext &C, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent, - bool KnownInstantiationDependent, - bool KnownContainsUnexpandedParameterPack); - - OverloadExpr(StmtClass K, EmptyShell Empty) - : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0), - HasTemplateKWAndArgsInfo(false) { } - void initializeResults(const ASTContext &C, UnresolvedSetIterator Begin, UnresolvedSetIterator End); public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + struct FindResult { OverloadExpr *Expression; bool IsAddressOfOperand; @@ -2552,7 +2635,8 @@ public: /// \brief Gets the naming class of this lookup, if any. CXXRecordDecl *getNamingClass() const; - typedef UnresolvedSetImpl::iterator decls_iterator; + using decls_iterator = UnresolvedSetImpl::iterator; + decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } decls_iterator decls_end() const { return UnresolvedSetIterator(Results + NumResults); @@ -2636,9 +2720,6 @@ public: return T->getStmtClass() == UnresolvedLookupExprClass || T->getStmtClass() == UnresolvedMemberExprClass; } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// \brief A reference to a name which we were able to look up during @@ -2656,25 +2737,25 @@ class UnresolvedLookupExpr final : public OverloadExpr, private llvm::TrailingObjects< UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class OverloadExpr; + friend TrailingObjects; + /// True if these lookup results should be extended by /// argument-dependent lookup if this is the operand of a function /// call. - bool RequiresADL; + bool RequiresADL = false; /// True if these lookup results are overloaded. This is pretty /// trivially rederivable if we urgently need to kill this field. - bool Overloaded; + bool Overloaded = false; /// The naming class (C++ [class.access.base]p5) of the lookup, if /// any. This can generally be recalculated from the context chain, /// but that can be fairly expensive for unqualified lookups. If we /// want to improve memory use here, this could go in a union /// against the qualified-lookup bits. - CXXRecordDecl *NamingClass; - - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } + CXXRecordDecl *NamingClass = nullptr; UnresolvedLookupExpr(const ASTContext &C, CXXRecordDecl *NamingClass, @@ -2684,20 +2765,17 @@ class UnresolvedLookupExpr final bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc, - NameInfo, TemplateArgs, Begin, End, false, false, false), - RequiresADL(RequiresADL), - Overloaded(Overloaded), NamingClass(NamingClass) - {} + : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc, + NameInfo, TemplateArgs, Begin, End, false, false, false), + RequiresADL(RequiresADL), + Overloaded(Overloaded), NamingClass(NamingClass) {} UnresolvedLookupExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), Overloaded(false), NamingClass(nullptr) - {} + : OverloadExpr(UnresolvedLookupExprClass, Empty) {} - friend TrailingObjects; - friend class OverloadExpr; - friend class ASTStmtReader; + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; + } public: static UnresolvedLookupExpr *Create(const ASTContext &C, @@ -2743,6 +2821,7 @@ public: return l.getBeginLoc(); return getNameInfo().getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); @@ -2788,17 +2867,21 @@ class DependentScopeDeclRefExpr final /// keyword and arguments. bool HasTemplateKWAndArgsInfo; - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } - DependentScopeDeclRefExpr(QualType T, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args); + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; + } + public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + static DependentScopeDeclRefExpr *Create(const ASTContext &C, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -2888,6 +2971,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return QualifierLoc.getBeginLoc(); } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); @@ -2901,10 +2985,6 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// Represents an expression -- generally a full-expression -- that @@ -2925,18 +3005,18 @@ public: /// It's useful to remember the set of blocks; we could also /// remember the set of temporaries, but there's currently /// no need. - typedef BlockDecl *CleanupObject; + using CleanupObject = BlockDecl *; private: + friend class ASTStmtReader; + friend TrailingObjects; + Stmt *SubExpr; ExprWithCleanups(EmptyShell, unsigned NumObjects); ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> Objects); - friend TrailingObjects; - friend class ASTStmtReader; - public: static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty, unsigned numObjects); @@ -2959,6 +3039,7 @@ public: Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + bool cleanupsHaveSideEffects() const { return ExprWithCleanupsBits.CleanupsHaveSideEffects; } @@ -2970,6 +3051,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return SubExpr->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} // Implement isa/cast/dyncast/etc. @@ -3005,8 +3087,11 @@ public: class CXXUnresolvedConstructExpr final : public Expr, private llvm::TrailingObjects<CXXUnresolvedConstructExpr, Expr *> { + friend class ASTStmtReader; + friend TrailingObjects; + /// \brief The type being constructed. - TypeSourceInfo *Type; + TypeSourceInfo *Type = nullptr; /// \brief The location of the left parentheses ('('). SourceLocation LParenLoc; @@ -3023,10 +3108,7 @@ class CXXUnresolvedConstructExpr final SourceLocation RParenLoc); CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { } - - friend TrailingObjects; - friend class ASTStmtReader; + : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) {} public: static CXXUnresolvedConstructExpr *Create(const ASTContext &C, @@ -3056,14 +3138,21 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } + /// Determine whether this expression models list-initialization. + /// If so, there will be exactly one subexpression, which will be + /// an InitListExpr. + bool isListInitialization() const { return LParenLoc.isInvalid(); } + /// \brief Retrieve the number of arguments. unsigned arg_size() const { return NumArgs; } - typedef Expr** arg_iterator; + using arg_iterator = Expr **; + arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); } arg_iterator arg_end() { return arg_begin() + NumArgs; } - typedef const Expr* const * const_arg_iterator; + using const_arg_iterator = const Expr* const *; + const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); } const_arg_iterator arg_end() const { return arg_begin() + NumArgs; @@ -3085,6 +3174,7 @@ public: } SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY { if (!RParenLoc.isValid() && NumArgs > 0) return getArg(NumArgs - 1)->getLocEnd(); @@ -3165,6 +3255,10 @@ class CXXDependentScopeMemberExpr final const TemplateArgumentListInfo *TemplateArgs); public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -3214,7 +3308,6 @@ public: /// name, with source location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief 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. @@ -3326,10 +3419,6 @@ public: return child_range(child_iterator(), child_iterator()); return child_range(&Base, &Base + 1); } - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// \brief Represents a C++ member access expression for which lookup @@ -3351,6 +3440,10 @@ class UnresolvedMemberExpr final : public OverloadExpr, private llvm::TrailingObjects< UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class OverloadExpr; + friend TrailingObjects; + /// \brief Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; @@ -3363,7 +3456,7 @@ class UnresolvedMemberExpr final /// e.g., the \c x in x.f. /// /// This can be null if this is an 'unbased' member expression. - Stmt *Base; + Stmt *Base = nullptr; /// \brief The type of the base expression; never null. QualType BaseType; @@ -3371,10 +3464,6 @@ class UnresolvedMemberExpr final /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; - } - UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -3385,12 +3474,12 @@ class UnresolvedMemberExpr final UnresolvedSetIterator Begin, UnresolvedSetIterator End); UnresolvedMemberExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), - HasUnresolvedUsing(false), Base(nullptr) { } + : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), + HasUnresolvedUsing(false) {} - friend TrailingObjects; - friend class OverloadExpr; - friend class ASTStmtReader; + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; + } public: static UnresolvedMemberExpr * @@ -3463,6 +3552,7 @@ public: return l.getBeginLoc(); return getMemberNameInfo().getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); @@ -3508,26 +3598,23 @@ inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { /// The noexcept expression tests whether a given expression might throw. Its /// result is a boolean constant. class CXXNoexceptExpr : public Expr { + friend class ASTStmtReader; + bool Value : 1; Stmt *Operand; SourceRange Range; - friend class ASTStmtReader; - public: CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val, SourceLocation Keyword, SourceLocation RParen) - : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary, - /*TypeDependent*/false, - /*ValueDependent*/Val == CT_Dependent, - Val == CT_Dependent || Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) - { } - - CXXNoexceptExpr(EmptyShell Empty) - : Expr(CXXNoexceptExprClass, Empty) - { } + : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary, + /*TypeDependent*/false, + /*ValueDependent*/Val == CT_Dependent, + Val == CT_Dependent || Operand->isInstantiationDependent(), + Operand->containsUnexpandedParameterPack()), + Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) {} + + CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {} Expr *getOperand() const { return static_cast<Expr*>(Operand); } @@ -3563,6 +3650,9 @@ public: /// template is instantiated, the pack expansion will instantiate to zero or /// or more function arguments to the function object \c f. class PackExpansionExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + SourceLocation EllipsisLoc; /// \brief The number of expansions that will be produced by this pack @@ -3574,21 +3664,18 @@ class PackExpansionExpr : public Expr { Stmt *Pattern; - friend class ASTStmtReader; - friend class ASTStmtWriter; - public: PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc, Optional<unsigned> NumExpansions) - : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), - Pattern->getObjectKind(), /*TypeDependent=*/true, - /*ValueDependent=*/true, /*InstantiationDependent=*/true, - /*ContainsUnexpandedParameterPack=*/false), - EllipsisLoc(EllipsisLoc), - NumExpansions(NumExpansions? *NumExpansions + 1 : 0), - Pattern(Pattern) { } + : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), + Pattern->getObjectKind(), /*TypeDependent=*/true, + /*ValueDependent=*/true, /*InstantiationDependent=*/true, + /*ContainsUnexpandedParameterPack=*/false), + EllipsisLoc(EllipsisLoc), + NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), + Pattern(Pattern) {} - PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) { } + PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {} /// \brief Retrieve the pattern of the pack expansion. Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); } @@ -3612,6 +3699,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return Pattern->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; } static bool classof(const Stmt *T) { @@ -3624,7 +3712,6 @@ public: } }; - /// \brief Represents an expression that computes the length of a parameter /// pack. /// @@ -3637,6 +3724,10 @@ public: class SizeOfPackExpr final : public Expr, private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// \brief The location of the \c sizeof keyword. SourceLocation OperatorLoc; @@ -3659,11 +3750,7 @@ class SizeOfPackExpr final unsigned Length; /// \brief The parameter pack. - NamedDecl *Pack; - - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; + NamedDecl *Pack = nullptr; /// \brief Create an expression that computes the length of /// the given parameter pack. @@ -3684,7 +3771,7 @@ class SizeOfPackExpr final /// \brief Create an empty expression. SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs) - : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs), Pack() {} + : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {} public: static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc, @@ -3749,6 +3836,9 @@ public: /// \brief 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. NonTypeTemplateParmDecl *Param; @@ -3758,10 +3848,8 @@ class SubstNonTypeTemplateParmExpr : public Expr { /// \brief The location of the non-type template parameter reference. SourceLocation NameLoc; - friend class ASTReader; - friend class ASTStmtReader; explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) - : Expr(SubstNonTypeTemplateParmExprClass, Empty) { } + : Expr(SubstNonTypeTemplateParmExprClass, Empty) {} public: SubstNonTypeTemplateParmExpr(QualType type, @@ -3769,11 +3857,11 @@ public: SourceLocation loc, NonTypeTemplateParmDecl *param, Expr *replacement) - : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary, - replacement->isTypeDependent(), replacement->isValueDependent(), - replacement->isInstantiationDependent(), - replacement->containsUnexpandedParameterPack()), - Param(param), Replacement(replacement), NameLoc(loc) {} + : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary, + replacement->isTypeDependent(), replacement->isValueDependent(), + replacement->isInstantiationDependent(), + replacement->containsUnexpandedParameterPack()), + Param(param), Replacement(replacement), NameLoc(loc) {} SourceLocation getNameLoc() const { return NameLoc; } SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } @@ -3804,6 +3892,9 @@ public: /// arguments), this type will be replaced with the appropriate underlying /// expression at the current pack substitution index. class SubstNonTypeTemplateParmPackExpr : public Expr { + friend class ASTReader; + friend class ASTStmtReader; + /// \brief The non-type template parameter pack itself. NonTypeTemplateParmDecl *Param; @@ -3817,10 +3908,8 @@ class SubstNonTypeTemplateParmPackExpr : public Expr { /// \brief The location of the non-type template parameter pack reference. SourceLocation NameLoc; - friend class ASTReader; - friend class ASTStmtReader; explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) - : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { } + : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {} public: SubstNonTypeTemplateParmPackExpr(QualType T, @@ -3868,6 +3957,10 @@ public: class FunctionParmPackExpr final : public Expr, private llvm::TrailingObjects<FunctionParmPackExpr, ParmVarDecl *> { + friend class ASTReader; + friend class ASTStmtReader; + friend TrailingObjects; + /// \brief The function parameter pack which was referenced. ParmVarDecl *ParamPack; @@ -3881,10 +3974,6 @@ class FunctionParmPackExpr final SourceLocation NameLoc, unsigned NumParams, ParmVarDecl *const *Params); - friend TrailingObjects; - friend class ASTReader; - friend class ASTStmtReader; - public: static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T, ParmVarDecl *ParamPack, @@ -3901,7 +3990,7 @@ public: /// \brief Iterators over the parameters which the parameter pack expanded /// into. - typedef ParmVarDecl * const *iterator; + using iterator = ParmVarDecl * const *; iterator begin() const { return getTrailingObjects<ParmVarDecl *>(); } iterator end() const { return begin() + NumParameters; } @@ -3945,6 +4034,9 @@ public: /// declaration which is responsible for the lifetime extension. class MaterializeTemporaryExpr : public Expr { private: + friend class ASTStmtReader; + friend class ASTStmtWriter; + struct ExtraState { /// \brief The temporary-generating expression whose value will be /// materialized. @@ -3958,24 +4050,21 @@ private: }; llvm::PointerUnion<Stmt *, ExtraState *> State; - friend class ASTStmtReader; - friend class ASTStmtWriter; - void initializeExtraState(const ValueDecl *ExtendedBy, unsigned ManglingNumber); public: MaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference) - : Expr(MaterializeTemporaryExprClass, T, - BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, - Temporary->isTypeDependent(), Temporary->isValueDependent(), - Temporary->isInstantiationDependent(), - Temporary->containsUnexpandedParameterPack()), + : Expr(MaterializeTemporaryExprClass, T, + BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, + Temporary->isTypeDependent(), Temporary->isValueDependent(), + Temporary->isInstantiationDependent(), + Temporary->containsUnexpandedParameterPack()), State(Temporary) {} MaterializeTemporaryExpr(EmptyShell Empty) - : Expr(MaterializeTemporaryExprClass, Empty) { } + : Expr(MaterializeTemporaryExprClass, Empty) {} Stmt *getTemporary() const { return State.is<Stmt *>() ? State.get<Stmt *>() @@ -4026,6 +4115,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return getTemporary()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getTemporary()->getLocEnd(); } @@ -4053,14 +4143,15 @@ public: /// ( ... op expr ) /// ( expr op ... op expr ) class CXXFoldExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + SourceLocation LParenLoc; SourceLocation EllipsisLoc; SourceLocation RParenLoc; Stmt *SubExprs[2]; BinaryOperatorKind Opcode; - friend class ASTStmtReader; - friend class ASTStmtWriter; public: CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, @@ -4073,6 +4164,7 @@ public: SubExprs[0] = LHS; SubExprs[1] = RHS; } + CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); } @@ -4082,10 +4174,13 @@ public: bool isRightFold() const { return getLHS() && getLHS()->containsUnexpandedParameterPack(); } + /// Does this produce a left-associated sequence of operators? bool isLeftFold() const { return !isRightFold(); } + /// Get the pattern, that is, the operand that contains an unexpanded pack. Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); } + /// Get the operand that doesn't contain a pack, for a binary fold. Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); } @@ -4095,6 +4190,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } @@ -4121,13 +4217,15 @@ public: /// expression is evaluated, and its result is the result of the overall /// expression. class CoroutineSuspendExpr : public Expr { + friend class ASTStmtReader; + SourceLocation KeywordLoc; enum SubExpr { Common, Ready, Suspend, Resume, Count }; + Stmt *SubExprs[SubExpr::Count]; OpaqueValueExpr *OpaqueValue = nullptr; - friend class ASTStmtReader; public: CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume, @@ -4142,6 +4240,7 @@ public: SubExprs[SubExpr::Suspend] = Suspend; SubExprs[SubExpr::Resume] = Resume; } + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty, Expr *Common) : Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true, @@ -4154,6 +4253,7 @@ public: SubExprs[SubExpr::Suspend] = nullptr; SubExprs[SubExpr::Resume] = nullptr; } + CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { SubExprs[SubExpr::Common] = nullptr; SubExprs[SubExpr::Ready] = nullptr; @@ -4162,18 +4262,22 @@ public: } SourceLocation getKeywordLoc() const { return KeywordLoc; } + Expr *getCommonExpr() const { return static_cast<Expr*>(SubExprs[SubExpr::Common]); } + /// \brief getOpaqueValue - Return the opaque value placeholder. OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } Expr *getReadyExpr() const { return static_cast<Expr*>(SubExprs[SubExpr::Ready]); } + Expr *getSuspendExpr() const { return static_cast<Expr*>(SubExprs[SubExpr::Suspend]); } + Expr *getResumeExpr() const { return static_cast<Expr*>(SubExprs[SubExpr::Resume]); } @@ -4181,6 +4285,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return getCommonExpr()->getLocEnd(); } @@ -4198,6 +4303,7 @@ public: /// \brief Represents a 'co_await' expression. class CoawaitExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; + public: CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready, Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue, @@ -4206,11 +4312,13 @@ public: Suspend, Resume, OpaqueValue) { CoawaitBits.IsImplicit = IsImplicit; } + CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand, bool IsImplicit = false) : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) { CoawaitBits.IsImplicit = IsImplicit; } + CoawaitExpr(EmptyShell Empty) : CoroutineSuspendExpr(CoawaitExprClass, Empty) {} @@ -4230,11 +4338,11 @@ public: /// \brief Represents a 'co_await' expression while the type of the promise /// is dependent. class DependentCoawaitExpr : public Expr { + friend class ASTStmtReader; + SourceLocation KeywordLoc; Stmt *SubExprs[2]; - friend class ASTStmtReader; - public: DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op, UnresolvedLookupExpr *OpCoawait) @@ -4255,12 +4363,15 @@ public: : Expr(DependentCoawaitExprClass, Empty) {} Expr *getOperand() const { return cast<Expr>(SubExprs[0]); } + UnresolvedLookupExpr *getOperatorCoawaitLookup() const { return cast<UnresolvedLookupExpr>(SubExprs[1]); } + SourceLocation getKeywordLoc() const { return KeywordLoc; } SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return getOperand()->getLocEnd(); } @@ -4275,6 +4386,7 @@ public: /// \brief Represents a 'co_yield' expression. class CoyieldExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; + public: CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready, Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue) @@ -4295,6 +4407,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_EXPRCXX_H diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index cd9381758618..ab2df8a34819 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -1,4 +1,4 @@ -//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===// +//===- ExprObjC.h - Classes for representing ObjC expressions ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,28 +14,51 @@ #ifndef LLVM_CLANG_AST_EXPROBJC_H #define LLVM_CLANG_AST_EXPROBJC_H +#include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/SelectorLocationsKind.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/Specifiers.h" +#include "clang/Basic/VersionTuple.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstddef> +#include <cstdint> namespace clang { - class IdentifierInfo; - class ASTContext; + +class ASTContext; +class CXXBaseSpecifier; /// ObjCStringLiteral, used for Objective-C string literals /// i.e. @"foo". class ObjCStringLiteral : public Expr { Stmt *String; SourceLocation AtLoc; + public: ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) - : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - String(SL), AtLoc(L) {} + : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + String(SL), AtLoc(L) {} explicit ObjCStringLiteral(EmptyShell Empty) - : Expr(ObjCStringLiteralClass, Empty) {} + : Expr(ObjCStringLiteralClass, Empty) {} StringLiteral *getString() { return cast<StringLiteral>(String); } const StringLiteral *getString() const { return cast<StringLiteral>(String); } @@ -47,26 +70,26 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); } + // Iterators + child_range children() { return child_range(&String, &String+1); } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCStringLiteralClass; } - - // Iterators - child_range children() { return child_range(&String, &String+1); } }; /// ObjCBoolLiteralExpr - Objective-C Boolean Literal. -/// class ObjCBoolLiteralExpr : public Expr { bool Value; SourceLocation Loc; + public: - ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : - Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), Value(val), Loc(l) {} - + ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) + : Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + false, false), + Value(val), Loc(l) {} explicit ObjCBoolLiteralExpr(EmptyShell Empty) - : Expr(ObjCBoolLiteralExprClass, Empty) { } + : Expr(ObjCBoolLiteralExprClass, Empty) {} bool getValue() const { return Value; } void setValue(bool V) { Value = V; } @@ -77,14 +100,14 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCBoolLiteralExprClass; - } - // Iterators child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCBoolLiteralExprClass; + } }; /// ObjCBoxedExpr - used for generalized expression boxing. @@ -95,15 +118,19 @@ class ObjCBoxedExpr : public Expr { Stmt *SubExpr; ObjCMethodDecl *BoxingMethod; SourceRange Range; + public: + friend class ASTStmtReader; + ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, SourceRange R) - : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary, - E->isTypeDependent(), E->isValueDependent(), - E->isInstantiationDependent(), E->containsUnexpandedParameterPack()), - SubExpr(E), BoxingMethod(method), Range(R) {} + : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary, + E->isTypeDependent(), E->isValueDependent(), + E->isInstantiationDependent(), + E->containsUnexpandedParameterPack()), + SubExpr(E), BoxingMethod(method), Range(R) {} explicit ObjCBoxedExpr(EmptyShell Empty) - : Expr(ObjCBoxedExprClass, Empty) {} + : Expr(ObjCBoxedExprClass, Empty) {} Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } @@ -116,27 +143,27 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCBoxedExprClass; - } - // Iterators child_range children() { return child_range(&SubExpr, &SubExpr+1); } - typedef ConstExprIterator const_arg_iterator; + using const_arg_iterator = ConstExprIterator; const_arg_iterator arg_begin() const { return reinterpret_cast<Stmt const * const*>(&SubExpr); } + const_arg_iterator arg_end() const { return reinterpret_cast<Stmt const * const*>(&SubExpr + 1); } - - friend class ASTStmtReader; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCBoxedExprClass; + } }; /// ObjCArrayLiteral - used for objective-c array containers; as in: @@ -153,9 +180,12 @@ class ObjCArrayLiteral final SourceRange SR); explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements) - : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {} + : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {} public: + friend class ASTStmtReader; + friend TrailingObjects; + static ObjCArrayLiteral *Create(const ASTContext &C, ArrayRef<Expr *> Elements, QualType T, ObjCMethodDecl * Method, @@ -168,10 +198,6 @@ public: SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCArrayLiteralClass; - } - /// \brief Retrieve elements of array of literals. Expr **getElements() { return getTrailingObjects<Expr *>(); } @@ -183,7 +209,7 @@ public: /// getNumElements - Return number of elements of objective-c array literal. unsigned getNumElements() const { return NumElements; } - /// getExpr - Return the Expr at the specified index. + /// 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]); @@ -203,8 +229,9 @@ public: reinterpret_cast<Stmt **>(getElements()) + NumElements); } - friend TrailingObjects; - friend class ASTStmtReader; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCArrayLiteralClass; + } }; /// \brief An element in an Objective-C dictionary literal. @@ -226,13 +253,17 @@ struct ObjCDictionaryElement { /// \brief Determines whether this dictionary element is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } }; -} // end namespace clang + +} // namespace clang namespace llvm { + template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {}; -} + +} // namespace llvm namespace clang { + /// \brief Internal struct for storing Key/value pair. struct ObjCDictionaryLiteral_KeyValuePair { Expr *Key; @@ -274,12 +305,8 @@ class ObjCDictionaryLiteral final SourceRange Range; ObjCMethodDecl *DictWithObjectsMethod; - typedef ObjCDictionaryLiteral_KeyValuePair KeyValuePair; - typedef ObjCDictionaryLiteral_ExpansionData ExpansionData; - - size_t numTrailingObjects(OverloadToken<KeyValuePair>) const { - return NumElements; - } + using KeyValuePair = ObjCDictionaryLiteral_KeyValuePair; + using ExpansionData = ObjCDictionaryLiteral_ExpansionData; ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK, bool HasPackExpansions, @@ -288,10 +315,18 @@ class ObjCDictionaryLiteral final explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements, bool HasPackExpansions) - : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements), - HasPackExpansions(HasPackExpansions) {} + : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements), + HasPackExpansions(HasPackExpansions) {} + + size_t numTrailingObjects(OverloadToken<KeyValuePair>) const { + return NumElements; + } public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + static ObjCDictionaryLiteral *Create(const ASTContext &C, ArrayRef<ObjCDictionaryElement> VK, bool HasPackExpansions, @@ -320,17 +355,14 @@ public: return Result; } - ObjCMethodDecl *getDictWithObjectsMethod() const - { return DictWithObjectsMethod; } + ObjCMethodDecl *getDictWithObjectsMethod() const { + return DictWithObjectsMethod; + } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCDictionaryLiteralClass; - } - + // Iterators child_range children() { // Note: we're taking advantage of the layout of the KeyValuePair struct @@ -342,12 +374,11 @@ public: reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) + NumElements * 2); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; - friend TrailingObjects; -}; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCDictionaryLiteralClass; + } +}; /// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same /// type and behavior as StringLiteral except that the string initializer is @@ -355,19 +386,19 @@ public: class ObjCEncodeExpr : public Expr { TypeSourceInfo *EncodedType; SourceLocation AtLoc, RParenLoc; + public: ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at, SourceLocation rp) - : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary, - EncodedType->getType()->isDependentType(), - EncodedType->getType()->isDependentType(), - EncodedType->getType()->isInstantiationDependentType(), - EncodedType->getType()->containsUnexpandedParameterPack()), - EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} + : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary, + EncodedType->getType()->isDependentType(), + EncodedType->getType()->isDependentType(), + EncodedType->getType()->isInstantiationDependentType(), + EncodedType->getType()->containsUnexpandedParameterPack()), + EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} - SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -376,6 +407,7 @@ public: QualType getEncodedType() const { return EncodedType->getType(); } TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; } + void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) { EncodedType = EncType; } @@ -383,28 +415,29 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCEncodeExprClass; - } - // Iterators child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCEncodeExprClass; + } }; /// ObjCSelectorExpr used for \@selector in Objective-C. class ObjCSelectorExpr : public Expr { Selector SelName; SourceLocation AtLoc, RParenLoc; + public: ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, SourceLocation rp) - : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - SelName(selInfo), AtLoc(at), RParenLoc(rp){} + : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + SelName(selInfo), AtLoc(at), RParenLoc(rp) {} explicit ObjCSelectorExpr(EmptyShell Empty) - : Expr(ObjCSelectorExprClass, Empty) {} + : Expr(ObjCSelectorExprClass, Empty) {} Selector getSelector() const { return SelName; } void setSelector(Selector S) { SelName = S; } @@ -420,14 +453,14 @@ public: /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return SelName.getNumArgs(); } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCSelectorExprClass; - } - // Iterators child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCSelectorExprClass; + } }; /// ObjCProtocolExpr used for protocol expression in Objective-C. @@ -441,14 +474,18 @@ public: class ObjCProtocolExpr : public Expr { ObjCProtocolDecl *TheProtocol; SourceLocation AtLoc, ProtoLoc, RParenLoc; + public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, SourceLocation protoLoc, SourceLocation rp) - : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {} + : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {} explicit ObjCProtocolExpr(EmptyShell Empty) - : Expr(ObjCProtocolExprClass, Empty) {} + : Expr(ObjCProtocolExprClass, Empty) {} ObjCProtocolDecl *getProtocol() const { return TheProtocol; } void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } @@ -462,17 +499,14 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCProtocolExprClass; - } - // Iterators child_range children() { return child_range(child_iterator(), child_iterator()); } - friend class ASTStmtReader; - friend class ASTStmtWriter; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCProtocolExprClass; + } }; /// ObjCIvarRefExpr - A reference to an ObjC instance variable. @@ -480,27 +514,31 @@ class ObjCIvarRefExpr : public Expr { ObjCIvarDecl *D; Stmt *Base; SourceLocation Loc; + /// OpLoc - This is the location of '.' or '->' SourceLocation OpLoc; - - bool IsArrow:1; // True if this is "X->F", false if this is "X.F". - bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). + + // True if this is "X->F", false if this is "X.F". + bool IsArrow : 1; + + // True if ivar reference has no base (self assumed). + bool IsFreeIvar : 1; public: ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, SourceLocation oploc, Expr *base, - bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t, VK_LValue, - d->isBitField() ? OK_BitField : OK_Ordinary, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - D(d), Base(base), Loc(l), OpLoc(oploc), - IsArrow(arrow), IsFreeIvar(freeIvar) {} + bool arrow = false, bool freeIvar = false) + : Expr(ObjCIvarRefExprClass, t, VK_LValue, + d->isBitField() ? OK_BitField : OK_Ordinary, + /*TypeDependent=*/false, base->isValueDependent(), + base->isInstantiationDependent(), + base->containsUnexpandedParameterPack()), + D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow), + IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) - : Expr(ObjCIvarRefExprClass, Empty) {} + : Expr(ObjCIvarRefExprClass, Empty) {} ObjCIvarDecl *getDecl() { return D; } const ObjCIvarDecl *getDecl() const { return D; } @@ -526,12 +564,12 @@ public: SourceLocation getOpLoc() const { return OpLoc; } void setOpLoc(SourceLocation L) { OpLoc = L; } + // Iterators + child_range children() { return child_range(&Base, &Base+1); } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIvarRefExprClass; } - - // Iterators - child_range children() { return child_range(&Base, &Base+1); } }; /// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC @@ -542,7 +580,7 @@ private: /// pointer is an (optional) ObjCMethodDecl and Setter may be set. /// if the bool is false, this is an explicit property reference; /// the pointer is an ObjCPropertyDecl and Setter is always null. - llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter; + llvm::PointerIntPair<NamedDecl *, 1, bool> PropertyOrGetter; /// \brief Indicates whether the property reference will result in a message /// to the getter, the setter, or both. @@ -567,40 +605,39 @@ private: /// the location of the 'super' keyword. When it's an interface, /// this is that interface. SourceLocation ReceiverLoc; - llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver; + llvm::PointerUnion3<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver; public: ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, Expr *base) - : Expr(ObjCPropertyRefExprClass, t, VK, OK, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), - IdLoc(l), ReceiverLoc(), Receiver(base) { + : Expr(ObjCPropertyRefExprClass, t, VK, OK, + /*TypeDependent=*/false, base->isValueDependent(), + base->isInstantiationDependent(), + base->containsUnexpandedParameterPack()), + PropertyOrGetter(PD, false), IdLoc(l), Receiver(base) { assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, SourceLocation sl, QualType st) - : Expr(ObjCPropertyRefExprClass, t, VK, OK, - /*TypeDependent=*/false, false, st->isInstantiationDependentType(), - st->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), SetterAndMethodRefFlags(), - IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { + : Expr(ObjCPropertyRefExprClass, t, VK, OK, + /*TypeDependent=*/false, false, st->isInstantiationDependentType(), + st->containsUnexpandedParameterPack()), + PropertyOrGetter(PD, false), IdLoc(l), ReceiverLoc(sl), + Receiver(st.getTypePtr()) { assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, QualType T, ExprValueKind VK, ExprObjectKind OK, SourceLocation IdLoc, Expr *Base) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, - Base->isValueDependent(), Base->isInstantiationDependent(), - Base->containsUnexpandedParameterPack()), - PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), - IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) { + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, + Base->isValueDependent(), Base->isInstantiationDependent(), + Base->containsUnexpandedParameterPack()), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), + IdLoc(IdLoc), Receiver(Base) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } @@ -608,9 +645,9 @@ public: QualType T, ExprValueKind VK, ExprObjectKind OK, SourceLocation IdLoc, SourceLocation SuperLoc, QualType SuperTy) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), - PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), - IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), + IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } @@ -618,14 +655,14 @@ public: QualType T, ExprValueKind VK, ExprObjectKind OK, SourceLocation IdLoc, SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), - PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), - IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { + : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), + IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); } explicit ObjCPropertyRefExpr(EmptyShell Empty) - : Expr(ObjCPropertyRefExprClass, Empty) {} + : Expr(ObjCPropertyRefExprClass, Empty) {} bool isImplicitProperty() const { return PropertyOrGetter.getInt(); } bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); } @@ -689,6 +726,7 @@ public: SourceLocation getLocation() const { return IdLoc; } SourceLocation getReceiverLocation() const { return ReceiverLoc; } + QualType getSuperReceiverType() const { return QualType(Receiver.get<const Type*>(), 0); } @@ -696,6 +734,7 @@ public: ObjCInterfaceDecl *getClassReceiver() const { return Receiver.get<ObjCInterfaceDecl*>(); } + bool isObjectReceiver() const { return Receiver.is<Stmt*>(); } bool isSuperReceiver() const { return Receiver.is<const Type*>(); } bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); } @@ -706,11 +745,8 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCPropertyRefExprClass; - } + SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; } // Iterators child_range children() { @@ -721,15 +757,21 @@ public: return child_range(child_iterator(), child_iterator()); } + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCPropertyRefExprClass; + } + private: friend class ASTStmtReader; friend class ASTStmtWriter; + void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) { PropertyOrGetter.setPointer(D); PropertyOrGetter.setInt(false); SetterAndMethodRefFlags.setPointer(nullptr); SetterAndMethodRefFlags.setInt(methRefFlags); } + void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, unsigned methRefFlags) { PropertyOrGetter.setPointer(Getter); @@ -737,6 +779,7 @@ private: SetterAndMethodRefFlags.setPointer(Setter); SetterAndMethodRefFlags.setInt(methRefFlags); } + void setBase(Expr *Base) { Receiver = Base; } void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); } void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; } @@ -756,10 +799,10 @@ private: /// ObjCSubscriptRefExpr - used for array and dictionary subscripting. /// array[4] = array[3]; dictionary[key] = dictionary[alt_key]; -/// class ObjCSubscriptRefExpr : public Expr { // Location of ']' in an indexing expression. SourceLocation RBracket; + // array/dictionary base expression. // for arrays, this is a numeric expression. For dictionaries, this is // an objective-c object pointer expression. @@ -773,24 +816,24 @@ class ObjCSubscriptRefExpr : public Expr { ObjCMethodDecl *SetAtIndexMethodDecl; public: - ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T, ExprValueKind VK, ExprObjectKind OK, ObjCMethodDecl *getMethod, ObjCMethodDecl *setMethod, SourceLocation RB) - : Expr(ObjCSubscriptRefExprClass, T, VK, OK, - base->isTypeDependent() || key->isTypeDependent(), - base->isValueDependent() || key->isValueDependent(), - base->isInstantiationDependent() || key->isInstantiationDependent(), - (base->containsUnexpandedParameterPack() || - key->containsUnexpandedParameterPack())), - RBracket(RB), - GetAtIndexMethodDecl(getMethod), - SetAtIndexMethodDecl(setMethod) - {SubExprs[BASE] = base; SubExprs[KEY] = key;} + : Expr(ObjCSubscriptRefExprClass, T, VK, OK, + base->isTypeDependent() || key->isTypeDependent(), + base->isValueDependent() || key->isValueDependent(), + (base->isInstantiationDependent() || + key->isInstantiationDependent()), + (base->containsUnexpandedParameterPack() || + key->containsUnexpandedParameterPack())), + RBracket(RB), GetAtIndexMethodDecl(getMethod), + SetAtIndexMethodDecl(setMethod) { + SubExprs[BASE] = base; SubExprs[KEY] = key; + } explicit ObjCSubscriptRefExpr(EmptyShell Empty) - : Expr(ObjCSubscriptRefExprClass, Empty) {} + : Expr(ObjCSubscriptRefExprClass, Empty) {} SourceLocation getRBracket() const { return RBracket; } void setRBracket(SourceLocation RB) { RBracket = RB; } @@ -798,11 +841,8 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return SubExprs[BASE]->getLocStart(); } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCSubscriptRefExprClass; - } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; } Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); } void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; } @@ -825,10 +865,14 @@ public: child_range children() { return child_range(SubExprs, SubExprs+END_EXPR); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCSubscriptRefExprClass; + } + private: friend class ASTStmtReader; }; - /// \brief An expression that sends a message to the given Objective-C /// object or class. @@ -856,14 +900,13 @@ private: /// The "void *" trailing objects are actually ONE void * (the /// receiver pointer), and NumArgs Expr *. But due to the /// implementation of children(), these must be together contiguously. - class ObjCMessageExpr final : public Expr, private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> { /// \brief 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; + uintptr_t SelectorOrMethod = 0; enum { NumArgsBitWidth = 16 }; @@ -904,16 +947,9 @@ class ObjCMessageExpr final /// brackets ('[' and ']', respectively). SourceLocation LBracLoc, RBracLoc; - size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; } - - void setNumArgs(unsigned Num) { - assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!"); - NumArgs = Num; - } - ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0), - HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) { + : Expr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false), + IsDelegateInitCall(false), IsImplicit(false), SelLocsKind(0) { setNumArgs(NumArgs); } @@ -950,6 +986,13 @@ class ObjCMessageExpr final SourceLocation RBracLoc, bool isImplicit); + size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; } + + void setNumArgs(unsigned Num) { + assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!"); + NumArgs = Num; + } + void initArgsAndSelLocs(ArrayRef<Expr *> Args, ArrayRef<SourceLocation> SelLocs, SelectorLocationsKind SelLocsK); @@ -965,6 +1008,7 @@ class ObjCMessageExpr final SelectorLocationsKind getSelLocsKind() const { return (SelectorLocationsKind)SelLocsKind; } + bool hasStandardSelLocs() const { return getSelLocsKind() != SelLoc_NonStandard; } @@ -997,14 +1041,21 @@ class ObjCMessageExpr final unsigned NumStoredSelLocs); public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// \brief The kind of receiver this message is sending to. enum ReceiverKind { /// \brief The receiver is a class. Class = 0, + /// \brief The receiver is an object instance. Instance, + /// \brief The receiver is a superclass. SuperClass, + /// \brief The receiver is the instance of the superclass object. SuperInstance }; @@ -1029,7 +1080,7 @@ public: /// \param Sel The selector used to determine which method gets called. /// /// \param Method The Objective-C method against which this message - /// send was type-checked. May be NULL. + /// send was type-checked. May be nullptr. /// /// \param Args The message send arguments. /// @@ -1065,7 +1116,7 @@ public: /// \param Sel The selector used to determine which method gets called. /// /// \param Method The Objective-C method against which this message - /// send was type-checked. May be NULL. + /// send was type-checked. May be nullptr. /// /// \param Args The message send arguments. /// @@ -1099,7 +1150,7 @@ public: /// \param Sel The selector used to determine which method gets called. /// /// \param Method The Objective-C method against which this message - /// send was type-checked. May be NULL. + /// send was type-checked. May be nullptr. /// /// \param Args The message send arguments. /// @@ -1175,11 +1226,11 @@ public: if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) return TSInfo->getType(); - return QualType(); + return {}; } /// \brief Returns a type-source information of a class message - /// send, or NULL if the message is not a class message. + /// send, or nullptr if the message is not a class message. TypeSourceInfo *getClassReceiverTypeInfo() const { if (getReceiverKind() == Class) return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); @@ -1220,7 +1271,7 @@ public: /// whether the message is a class or an instance method, whether it /// is a send to super or not, etc. /// - /// \returns The Objective-C interface if known, otherwise NULL. + /// \returns The Objective-C interface if known, otherwise nullptr. ObjCInterfaceDecl *getReceiverInterface() const; /// \brief Retrieve the type referred to by 'super'. @@ -1295,6 +1346,7 @@ public: assert(Arg < NumArgs && "Arg access out of range!"); return getArgs()[Arg]; } + /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); @@ -1315,6 +1367,7 @@ public: return getLocStart(); return getSelectorLoc(0); } + SourceLocation getSelectorLoc(unsigned Index) const { assert(Index < getNumSelectorLocs() && "Index out of range!"); if (hasStandardSelLocs()) @@ -1341,18 +1394,15 @@ public: LBracLoc = R.getBegin(); RBracLoc = R.getEnd(); } + SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; } - static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCMessageExprClass; - } - // Iterators child_range children(); - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; + using arg_iterator = ExprIterator; + using const_arg_iterator = ConstExprIterator; llvm::iterator_range<arg_iterator> arguments() { return llvm::make_range(arg_begin(), arg_end()); @@ -1363,19 +1413,22 @@ public: } arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); } + arg_iterator arg_end() { return reinterpret_cast<Stmt **>(getArgs() + NumArgs); } + const_arg_iterator arg_begin() const { return reinterpret_cast<Stmt const * const*>(getArgs()); } + const_arg_iterator arg_end() const { return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs); } - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCMessageExprClass; + } }; /// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. @@ -1392,17 +1445,18 @@ class ObjCIsaExpr : public Expr { /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow; + public: ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc, QualType ty) - : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - /*ContainsUnexpandedParameterPack=*/false), - Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {} + : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, + /*TypeDependent=*/false, base->isValueDependent(), + base->isInstantiationDependent(), + /*ContainsUnexpandedParameterPack=*/false), + Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {} /// \brief Build an empty expression. - explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { } + explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {} void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast<Expr>(Base); } @@ -1430,15 +1484,14 @@ public: SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; } + // Iterators + child_range children() { return child_range(&Base, &Base+1); } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIsaExprClass; } - - // Iterators - child_range children() { return child_range(&Base, &Base+1); } }; - /// ObjCIndirectCopyRestoreExpr - Represents the passing of a function /// argument by indirect copy-restore in ARC. This is used to support /// passing indirect arguments with the wrong lifetime, e.g. when @@ -1462,27 +1515,27 @@ public: /// __autoreleasing; this qualifier is ignored when initializing /// the value. class ObjCIndirectCopyRestoreExpr : public Expr { + friend class ASTReader; + friend class ASTStmtReader; + Stmt *Operand; // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1; - friend class ASTReader; - friend class ASTStmtReader; + explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty) + : Expr(ObjCIndirectCopyRestoreExprClass, Empty) {} void setShouldCopy(bool shouldCopy) { ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy; } - explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty) - : Expr(ObjCIndirectCopyRestoreExprClass, Empty) { } - public: ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy) - : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary, - operand->isTypeDependent(), operand->isValueDependent(), - operand->isInstantiationDependent(), - operand->containsUnexpandedParameterPack()), - Operand(operand) { + : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary, + operand->isTypeDependent(), operand->isValueDependent(), + operand->isInstantiationDependent(), + operand->containsUnexpandedParameterPack()), + Operand(operand) { setShouldCopy(shouldCopy); } @@ -1519,26 +1572,26 @@ public: class ObjCBridgedCastExpr final : public ExplicitCastExpr, private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class CastExpr; + friend TrailingObjects; + SourceLocation LParenLoc; SourceLocation BridgeKeywordLoc; unsigned Kind : 2; - friend TrailingObjects; - friend class CastExpr; - friend class ASTStmtReader; - friend class ASTStmtWriter; - public: ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, CastKind CK, SourceLocation BridgeKeywordLoc, TypeSourceInfo *TSInfo, Expr *Operand) - : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue, - CK, Operand, 0, TSInfo), - LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { } + : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue, + CK, Operand, 0, TSInfo), + LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {} /// \brief Construct an empty Objective-C bridged cast. explicit ObjCBridgedCastExpr(EmptyShell Shell) - : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { } + : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) {} SourceLocation getLParenLoc() const { return LParenLoc; } @@ -1554,6 +1607,7 @@ public: SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return getSubExpr()->getLocEnd(); } @@ -1577,10 +1631,11 @@ public: /// expressions. /// class ObjCAvailabilityCheckExpr : public Expr { + friend class ASTStmtReader; + VersionTuple VersionToCheck; SourceLocation AtLoc, RParen; - friend class ASTStmtReader; public: ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc, SourceLocation RParen, QualType Ty) @@ -1608,6 +1663,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_EXPROBJC_H diff --git a/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h index 51d0c30ad23b..81492aec6e13 100644 --- a/include/clang/AST/ExternalASTMerger.h +++ b/include/clang/AST/ExternalASTMerger.h @@ -16,34 +16,159 @@ #include "clang/AST/ASTImporter.h" #include "clang/AST/ExternalASTSource.h" +#include "llvm/Support/raw_ostream.h" namespace clang { +/// ExternalASTSource implementation that merges information from several +/// ASTContexts. +/// +/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import +/// (potentially incomplete) Decls and DeclContexts from the source ASTContexts +/// in response to ExternalASTSource API calls. +/// +/// When lookup occurs in the resulting imported DeclContexts, the original +/// DeclContexts need to be queried. Roughly, there are three cases here: +/// +/// - The DeclContext of origin can be found by simple name lookup. In this +/// case, no additional state is required. +/// +/// - The DeclContext of origin is different from what would be found by name +/// lookup. In this case, Origins contains an entry overriding lookup and +/// specifying the correct pair of DeclContext/ASTContext. +/// +/// - The DeclContext of origin was determined by another ExterenalASTMerger. +/// (This is possible when the source ASTContext for one of the Importers has +/// its own ExternalASTMerger). The origin must be properly forwarded in this +/// case. +/// +/// ExternalASTMerger's job is to maintain the data structures necessary to +/// allow this. The data structures themselves can be extracted (read-only) and +/// copied for re-use. class ExternalASTMerger : public ExternalASTSource { public: - struct ImporterPair { - std::unique_ptr<ASTImporter> Forward; - std::unique_ptr<ASTImporter> Reverse; + /// A single origin for a DeclContext. Unlike Decls, DeclContexts do + /// not allow their containing ASTContext to be determined in all cases. + struct DCOrigin { + DeclContext *DC; + ASTContext *AST; }; + typedef std::map<const DeclContext *, DCOrigin> OriginMap; + typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector; private: - std::vector<ImporterPair> Importers; + /// One importer exists for each source. + ImporterVector Importers; + /// Overrides in case name lookup would return nothing or would return + /// the wrong thing. + OriginMap Origins; + /// The installed log stream. + llvm::raw_ostream *LogStream; public: - struct ImporterEndpoint { + /// The target for an ExternalASTMerger. + /// + /// ASTImporters require both ASTContext and FileManager to be able to + /// import SourceLocations properly. + struct ImporterTarget { ASTContext &AST; FileManager &FM; }; - ExternalASTMerger(const ImporterEndpoint &Target, - llvm::ArrayRef<ImporterEndpoint> Sources); + /// A source for an ExternalASTMerger. + /// + /// ASTImporters require both ASTContext and FileManager to be able to + /// import SourceLocations properly. Additionally, when import occurs for + /// a DeclContext whose origin has been overridden, then this + /// ExternalASTMerger must be able to determine that. + struct ImporterSource { + ASTContext &AST; + FileManager &FM; + const OriginMap &OM; + }; +private: + /// The target for this ExtenralASTMerger. + ImporterTarget Target; + +public: + ExternalASTMerger(const ImporterTarget &Target, + llvm::ArrayRef<ImporterSource> Sources); + + /// 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, + /// newly-parsed source files). + /// + /// Ensures that Importers does not gain duplicate entries as a result. + void AddSources(llvm::ArrayRef<ImporterSource> Sources); + + /// Remove a set of ASTContexts as possible origins. + /// + /// Sometimes an origin goes away (for example, if a source file gets + /// superseded by a newer version). + /// + /// The caller is responsible for ensuring that this doesn't leave + /// DeclContexts that can't be completed. + void RemoveSources(llvm::ArrayRef<ImporterSource> Sources); + + /// Implementation of the ExternalASTSource API. bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override; + /// Implementation of the ExternalASTSource API. void FindExternalLexicalDecls(const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl<Decl *> &Result) override; + + /// Implementation of the ExternalASTSource API. + void CompleteType(TagDecl *Tag) override; + + /// Implementation of the ExternalASTSource API. + void CompleteType(ObjCInterfaceDecl *Interface) override; + + /// Returns true if DC can be found in any source AST context. + bool CanComplete(DeclContext *DC); + + /// Records an origin in Origins only if name lookup would find + /// something different or nothing at all. + void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin); + + /// Regardless of any checks, override the Origin for a DeclContext. + void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin); + + /// Get a read-only view of the Origins map, for use in constructing + /// an ImporterSource for another ExternalASTMerger. + const OriginMap &GetOrigins() { return Origins; } + + /// Returns true if Importers contains an ASTImporter whose source is + /// OriginContext. + bool HasImporterForOrigin(ASTContext &OriginContext); + + /// Returns a reference to the ASTRImporter from Importers whose origin + /// is OriginContext. This allows manual import of ASTs while preserving the + /// OriginMap correctly. + ASTImporter &ImporterForOrigin(ASTContext &OriginContext); + + /// Sets the current log stream. + void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; } +private: + /// Records and origin in Origins. + void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, + ASTImporter &importer); + + /// Performs an action for every DeclContext that is identified as + /// corresponding (either by forced origin or by name lookup) to DC. + template <typename CallbackType> + void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback); + +public: + /// Log something if there is a logging callback installed. + llvm::raw_ostream &logs() { return *LogStream; } + + /// True if the log stream is not llvm::nulls(); + bool LoggingEnabled() { return LogStream != &llvm::nulls(); } }; } // end namespace clang diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index d8dd18ecb8d3..be013c5d6b6a 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -1,4 +1,4 @@ -//===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===// +//===- ExternalASTSource.h - Abstract External AST Interface ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,24 +11,44 @@ // construction of AST nodes from some external source. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H #define LLVM_CLANG_AST_EXTERNALASTSOURCE_H #include "clang/AST/CharUnits.h" #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" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> +#include <string> +#include <utility> namespace clang { class ASTConsumer; +class ASTContext; class CXXBaseSpecifier; class CXXCtorInitializer; +class CXXRecordDecl; class DeclarationName; -class ExternalSemaSource; // layering violation required for downcasting class FieldDecl; -class Module; +class IdentifierInfo; class NamedDecl; +class ObjCInterfaceDecl; class RecordDecl; class Selector; class Stmt; @@ -42,30 +62,31 @@ class TagDecl; /// actual type and declaration nodes, and read parts of declaration /// contexts. class ExternalASTSource : public RefCountedBase<ExternalASTSource> { + friend class ExternalSemaSource; + /// Generation number for this external AST source. Must be increased /// whenever we might have added new redeclarations for existing decls. - uint32_t CurrentGeneration; + uint32_t CurrentGeneration = 0; /// \brief Whether this AST source also provides information for /// semantic analysis. - bool SemaSource; - - friend class ExternalSemaSource; + bool SemaSource = false; public: - ExternalASTSource() : CurrentGeneration(0), SemaSource(false) { } - + ExternalASTSource() = default; virtual ~ExternalASTSource(); /// \brief RAII class for safely pairing a StartedDeserializing call /// with FinishedDeserializing. class Deserializing { ExternalASTSource *Source; + public: explicit Deserializing(ExternalASTSource *source) : Source(source) { assert(Source); Source->StartedDeserializing(); } + ~Deserializing() { Source->FinishedDeserializing(); } @@ -122,7 +143,7 @@ public: virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); /// \brief Update an out-of-date identifier. - virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { } + virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {} /// \brief Find all declarations with the given name in the given context, /// and add them to the context by calling SetExternalVisibleDeclsForName @@ -154,12 +175,13 @@ public: const Module *ClangModule = nullptr; public: - ASTSourceDescriptor(){}; + ASTSourceDescriptor() = default; ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile, ASTFileSignature Signature) : PCHModuleName(std::move(Name)), Path(std::move(Path)), - ASTFile(std::move(ASTFile)), Signature(Signature){}; + ASTFile(std::move(ASTFile)), Signature(Signature) {} ASTSourceDescriptor(const Module &M); + std::string getModuleName() const; StringRef getPath() const { return Path; } StringRef getASTFile() const { return ASTFile; } @@ -246,7 +268,6 @@ public: /// The default implementation of this method is a no-op. virtual void PrintStats(); - /// \brief Perform layout on the given record. /// /// This routine allows the external AST source to provide an specific @@ -289,7 +310,7 @@ public: size_t mmap_bytes; MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) - : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} + : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} }; /// Return the amount of memory used by memory buffers, breaking down @@ -329,12 +350,12 @@ struct LazyOffsetPtr { /// /// If the low bit is clear, a pointer to the AST node. If the low /// bit is set, the upper 63 bits are the offset. - mutable uint64_t Ptr; + mutable uint64_t Ptr = 0; public: - LazyOffsetPtr() : Ptr(0) { } + LazyOffsetPtr() = default; + explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {} - explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); if (Offset == 0) @@ -392,15 +413,16 @@ struct LazyGenerationalUpdatePtr { /// A cache of the value of this pointer, in the most recent generation in /// which we queried it. struct LazyData { - LazyData(ExternalASTSource *Source, T Value) - : ExternalSource(Source), LastGeneration(0), LastValue(Value) {} ExternalASTSource *ExternalSource; - uint32_t LastGeneration; + uint32_t LastGeneration = 0; T LastValue; + + LazyData(ExternalASTSource *Source, T Value) + : ExternalSource(Source), LastValue(Value) {} }; // Our value is represented as simply T if there is no external AST source. - typedef llvm::PointerUnion<T, LazyData*> ValueType; + using ValueType = llvm::PointerUnion<T, LazyData*>; ValueType Value; LazyGenerationalUpdatePtr(ValueType V) : Value(V) {} @@ -459,25 +481,31 @@ public: return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr)); } }; -} // end namespace clang + +} // namespace clang /// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be /// placed into a PointerUnion. namespace llvm { + template<typename Owner, typename T, void (clang::ExternalASTSource::*Update)(Owner)> struct PointerLikeTypeTraits< clang::LazyGenerationalUpdatePtr<Owner, T, Update>> { - typedef clang::LazyGenerationalUpdatePtr<Owner, T, Update> Ptr; + using Ptr = clang::LazyGenerationalUpdatePtr<Owner, T, Update>; + static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); } static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); } + enum { NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1 }; }; -} + +} // namespace llvm namespace clang { + /// \brief Represents a lazily-loaded vector of data. /// /// The lazily-loaded vector of data contains data that is partially loaded @@ -511,13 +539,14 @@ public: class iterator : public llvm::iterator_adaptor_base< iterator, int, std::random_access_iterator_tag, T, int, T *, T &> { + friend class LazyVector; + LazyVector *Self; iterator(LazyVector *Self, int Position) : iterator::iterator_adaptor_base(Position), Self(Self) {} bool isLoaded() const { return this->I < 0; } - friend class LazyVector; public: iterator() : iterator(nullptr, 0) {} @@ -562,23 +591,23 @@ public: }; /// \brief A lazy pointer to a statement. -typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> - LazyDeclStmtPtr; +using LazyDeclStmtPtr = + LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>; /// \brief A lazy pointer to a declaration. -typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> - LazyDeclPtr; +using LazyDeclPtr = + LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>; /// \brief A lazy pointer to a set of CXXCtorInitializers. -typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t, - &ExternalASTSource::GetExternalCXXCtorInitializers> - LazyCXXCtorInitializersPtr; +using LazyCXXCtorInitializersPtr = + LazyOffsetPtr<CXXCtorInitializer *, uint64_t, + &ExternalASTSource::GetExternalCXXCtorInitializers>; /// \brief A lazy pointer to a set of CXXBaseSpecifiers. -typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, - &ExternalASTSource::GetExternalCXXBaseSpecifiers> - LazyCXXBaseSpecifiersPtr; +using LazyCXXBaseSpecifiersPtr = + LazyOffsetPtr<CXXBaseSpecifier, uint64_t, + &ExternalASTSource::GetExternalCXXBaseSpecifiers>; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_EXTERNALASTSOURCE_H diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h index adf63a3aea69..3b3e4367d56c 100644 --- a/include/clang/AST/GlobalDecl.h +++ b/include/clang/AST/GlobalDecl.h @@ -1,4 +1,4 @@ -//===--- GlobalDecl.h - Global declaration holder ---------------*- C++ -*-===// +//===- GlobalDecl.h - Global declaration holder -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,6 +19,12 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" #include "clang/Basic/ABI.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/type_traits.h" +#include <cassert> namespace clang { @@ -27,7 +33,7 @@ namespace clang { /// a CXXDestructorDecl and the destructor type (Base, Complete) or /// a VarDecl, a FunctionDecl or a BlockDecl. class GlobalDecl { - llvm::PointerIntPair<const Decl*, 2> Value; + llvm::PointerIntPair<const Decl *, 2> Value; void Init(const Decl *D) { assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!"); @@ -37,19 +43,15 @@ class GlobalDecl { } public: - GlobalDecl() {} - + GlobalDecl() = default; GlobalDecl(const VarDecl *D) { Init(D);} GlobalDecl(const FunctionDecl *D) { Init(D); } GlobalDecl(const BlockDecl *D) { Init(D); } GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl *D) { Init(D); } GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } - - GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) - : Value(D, Type) {} - GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) - : Value(D, Type) {} + GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} + GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} GlobalDecl getCanonicalDecl() const { GlobalDecl CanonGD; @@ -90,10 +92,9 @@ public: } }; -} // end namespace clang +} // namespace clang namespace llvm { - template<class> struct DenseMapInfo; template<> struct DenseMapInfo<clang::GlobalDecl> { static inline clang::GlobalDecl getEmptyKey() { @@ -113,7 +114,6 @@ namespace llvm { clang::GlobalDecl RHS) { return LHS == RHS; } - }; // GlobalDecl isn't *technically* a POD type. However, its copy constructor, @@ -122,6 +122,7 @@ namespace llvm { struct isPodLike<clang::GlobalDecl> { static const bool value = true; }; -} // end namespace llvm -#endif +} // namespace llvm + +#endif // LLVM_CLANG_AST_GLOBALDECL_H diff --git a/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h b/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h new file mode 100644 index 000000000000..264f20f19ad5 --- /dev/null +++ b/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h @@ -0,0 +1,164 @@ +//===--- LexicallyOrderedRecursiveASTVisitor.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 the LexicallyOrderedRecursiveASTVisitor interface, which +// recursively traverses the entire AST in a lexical order. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H +#define LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H + +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/SaveAndRestore.h" + +namespace clang { + +/// A RecursiveASTVisitor subclass that guarantees that AST traversal is +/// performed in a lexical order (i.e. the order in which declarations are +/// written in the source). +/// +/// RecursiveASTVisitor doesn't guarantee lexical ordering because there are +/// some declarations, like Objective-C @implementation declarations +/// that might be represented in the AST differently to how they were written +/// in the source. +/// In particular, Objective-C @implementation declarations may contain +/// non-Objective-C declarations, like functions: +/// +/// @implementation MyClass +/// +/// - (void) method { } +/// void normalFunction() { } +/// +/// @end +/// +/// Clang's AST stores these declarations outside of the @implementation +/// declaration, so the example above would be represented using the following +/// AST: +/// |-ObjCImplementationDecl ... MyClass +/// | `-ObjCMethodDecl ... method +/// | ... +/// `-FunctionDecl ... normalFunction +/// ... +/// +/// This class ensures that these declarations are traversed before the +/// corresponding TraverseDecl for the @implementation returns. This ensures +/// that the lexical parent relationship between these declarations and the +/// @implementation is preserved while traversing the AST. Note that the +/// current implementation doesn't mix these declarations with the declarations +/// contained in the @implementation, so the traversal of all of the +/// declarations in the @implementation still doesn't follow the lexical order. +template <typename Derived> +class LexicallyOrderedRecursiveASTVisitor + : public RecursiveASTVisitor<Derived> { + using BaseType = RecursiveASTVisitor<Derived>; + +public: + LexicallyOrderedRecursiveASTVisitor(const SourceManager &SM) : SM(SM) {} + + bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) { + // Objective-C @implementation declarations should not trigger early exit + // until the additional decls are traversed as their children are not + // lexically ordered. + bool Result = BaseType::TraverseObjCImplementationDecl(D); + return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false; + } + + bool TraverseObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { + bool Result = BaseType::TraverseObjCCategoryImplDecl(D); + return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false; + } + + bool TraverseDeclContextHelper(DeclContext *DC) { + if (!DC) + return true; + + for (auto I = DC->decls_begin(), E = DC->decls_end(); I != E;) { + Decl *Child = *I; + if (BaseType::canIgnoreChildDeclWhileTraversingDeclContext(Child)) { + ++I; + continue; + } + if (!isa<ObjCImplementationDecl>(Child) && + !isa<ObjCCategoryImplDecl>(Child)) { + if (!BaseType::getDerived().TraverseDecl(Child)) + return false; + ++I; + continue; + } + // Gather declarations that follow the Objective-C implementation + // declarations but are lexically contained in the implementation. + LexicallyNestedDeclarations.clear(); + for (++I; I != E; ++I) { + Decl *Sibling = *I; + if (!SM.isBeforeInTranslationUnit(Sibling->getLocStart(), + Child->getLocEnd())) + break; + if (!BaseType::canIgnoreChildDeclWhileTraversingDeclContext(Sibling)) + LexicallyNestedDeclarations.push_back(Sibling); + } + if (!BaseType::getDerived().TraverseDecl(Child)) + return false; + } + return true; + } + + Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } + + SmallVector<Stmt *, 8> getStmtChildren(CXXOperatorCallExpr *CE) { + SmallVector<Stmt *, 8> Children(CE->children()); + bool Swap; + // Switch the operator and the first operand for all infix and postfix + // operations. + switch (CE->getOperator()) { + case OO_Arrow: + case OO_Call: + case OO_Subscript: + Swap = true; + break; + case OO_PlusPlus: + case OO_MinusMinus: + // These are postfix unless there is exactly one argument. + Swap = Children.size() != 2; + break; + default: + Swap = CE->isInfixBinaryOp(); + break; + } + if (Swap && Children.size() > 1) + std::swap(Children[0], Children[1]); + return Children; + } + +private: + bool TraverseAdditionalLexicallyNestedDeclarations() { + // FIXME: Ideally the gathered declarations and the declarations in the + // @implementation should be mixed and sorted to get a true lexical order, + // but right now we only care about getting the correct lexical parent, so + // we can traverse the gathered nested declarations after the declarations + // in the decl context. + assert(!BaseType::getDerived().shouldTraversePostOrder() && + "post-order traversal is not supported for lexically ordered " + "recursive ast visitor"); + for (Decl *D : LexicallyNestedDeclarations) { + if (!BaseType::getDerived().TraverseDecl(D)) + return false; + } + return true; + } + + const SourceManager &SM; + llvm::SmallVector<Decl *, 8> LexicallyNestedDeclarations; +}; + +} // end namespace clang + +#endif // LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index b1ff9bdff589..e2cb45c36de6 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -1,4 +1,4 @@ -//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- C++ -*-===// +//===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,38 +11,42 @@ // a C++ nested-name-specifier. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Compiler.h" +#include <cstdint> +#include <cstdlib> +#include <utility> namespace clang { class ASTContext; class CXXRecordDecl; +class IdentifierInfo; +class LangOptions; class NamespaceAliasDecl; class NamespaceDecl; -class IdentifierInfo; struct PrintingPolicy; class Type; class TypeLoc; -class LangOptions; /// \brief Represents a C++ nested name specifier, such as /// "\::std::vector<int>::". /// /// C++ nested name specifiers are the prefixes to qualified -/// namespaces. For example, "foo::" in "foo::x" is a nested name +/// names. For example, "foo::" in "foo::x" is a nested name /// specifier. Nested name specifiers are made up of a sequence of /// specifiers, each of which can be a namespace, type, identifier /// (for dependent names), decltype specifier, or the global specifier ('::'). /// The last two specifiers can only appear at the start of a /// nested-namespace-specifier. class NestedNameSpecifier : public llvm::FoldingSetNode { - /// \brief Enumeration describing enum StoredSpecifierKind { StoredIdentifier = 0, @@ -66,7 +70,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { /// specifier '::'. Otherwise, the pointer is one of /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of /// specifier as encoded within the prefix. - void* Specifier; + void* Specifier = nullptr; public: /// \brief The kind of specifier that completes this nested name @@ -74,17 +78,23 @@ public: enum SpecifierKind { /// \brief An identifier, stored as an IdentifierInfo*. Identifier, + /// \brief A namespace, stored as a NamespaceDecl*. Namespace, + /// \brief A namespace alias, stored as a NamespaceAliasDecl*. NamespaceAlias, + /// \brief A type, stored as a Type*. TypeSpec, + /// \brief A type that was preceded by the 'template' keyword, /// stored as a Type*. TypeSpecWithTemplate, + /// \brief The global specifier '::'. There is no stored value. Global, + /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of /// the class it appeared in. Super @@ -92,17 +102,11 @@ public: private: /// \brief Builds the global specifier. - NestedNameSpecifier() - : Prefix(nullptr, StoredIdentifier), Specifier(nullptr) {} + NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {} /// \brief Copy constructor used internally to clone nested name /// specifiers. - NestedNameSpecifier(const NestedNameSpecifier &Other) - : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), - Specifier(Other.Specifier) { - } - - void operator=(const NestedNameSpecifier &) = delete; + NestedNameSpecifier(const NestedNameSpecifier &Other) = default; /// \brief Either find or insert the given nested name specifier /// mockup in the given context. @@ -110,6 +114,8 @@ private: const NestedNameSpecifier &Mockup); public: + NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete; + /// \brief Builds a specifier combining a prefix and an identifier. /// /// The prefix must be dependent, since nested name specifiers @@ -224,8 +230,8 @@ public: /// \brief A C++ nested-name-specifier augmented with source location /// information. class NestedNameSpecifierLoc { - NestedNameSpecifier *Qualifier; - void *Data; + NestedNameSpecifier *Qualifier = nullptr; + void *Data = nullptr; /// \brief Determines the data length for the last component in the /// given nested-name-specifier. @@ -237,12 +243,12 @@ class NestedNameSpecifierLoc { public: /// \brief Construct an empty nested-name-specifier. - NestedNameSpecifierLoc() : Qualifier(nullptr), Data(nullptr) { } + NestedNameSpecifierLoc() = default; /// \brief Construct a nested-name-specifier with source location information /// from NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) - : Qualifier(Qualifier), Data(Data) { } + : Qualifier(Qualifier), Data(Data) {} /// \brief Evalutes true when this nested-name-specifier location is /// non-empty. @@ -339,7 +345,7 @@ public: class NestedNameSpecifierLocBuilder { /// \brief The current representation of the nested-name-specifier we're /// building. - NestedNameSpecifier *Representation; + NestedNameSpecifier *Representation = nullptr; /// \brief Buffer used to store source-location information for the /// nested-name-specifier. @@ -347,21 +353,18 @@ class NestedNameSpecifierLocBuilder { /// Note that we explicitly manage the buffer (rather than using a /// SmallVector) because \c Declarator expects it to be possible to memcpy() /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. - char *Buffer; + char *Buffer = nullptr; /// \brief The size of the buffer used to store source-location information /// for the nested-name-specifier. - unsigned BufferSize; + unsigned BufferSize = 0; /// \brief The capacity of the buffer used to store source-location /// information for the nested-name-specifier. - unsigned BufferCapacity; + unsigned BufferCapacity = 0; public: - NestedNameSpecifierLocBuilder() - : Representation(nullptr), Buffer(nullptr), BufferSize(0), - BufferCapacity(0) {} - + NestedNameSpecifierLocBuilder() = default; NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); NestedNameSpecifierLocBuilder & @@ -451,6 +454,7 @@ public: /// \param ColonColonLoc The location of the trailing '::'. void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, SourceLocation SuperLoc, SourceLocation ColonColonLoc); + /// \brief Make a new nested-name-specifier from incomplete source-location /// information. /// @@ -511,6 +515,6 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, return DB; } -} +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index a1cae8e18f84..1f732f67517a 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -6,35 +6,55 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// /// \file /// \brief 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. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_OPENMPCLAUSE_H #define LLVM_CLANG_AST_OPENMPCLAUSE_H +#include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtIterator.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <utility> namespace clang { +class ASTContext; + //===----------------------------------------------------------------------===// // AST classes for clauses. //===----------------------------------------------------------------------===// /// \brief This is a basic class for representing single OpenMP clause. -/// class OMPClause { /// \brief Starting location of the clause (the clause keyword). SourceLocation StartLoc; + /// \brief Ending location of the clause. SourceLocation EndLoc; + /// \brief Kind of the clause. OpenMPClauseKind Kind; @@ -45,11 +65,13 @@ protected: public: /// \brief Returns the starting location of the clause. SourceLocation getLocStart() const { return StartLoc; } + /// \brief Returns the ending location of the clause. SourceLocation getLocEnd() const { return EndLoc; } /// \brief Sets the starting location of the clause. void setLocStart(SourceLocation Loc) { StartLoc = Loc; } + /// \brief Sets the ending location of the clause. void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } @@ -58,16 +80,17 @@ public: bool isImplicit() const { return StartLoc.isInvalid(); } - typedef StmtIterator child_iterator; - typedef ConstStmtIterator const_child_iterator; - typedef llvm::iterator_range<child_iterator> child_range; - typedef llvm::iterator_range<const_child_iterator> const_child_range; + using child_iterator = StmtIterator; + using const_child_iterator = ConstStmtIterator; + using child_range = llvm::iterator_range<child_iterator>; + using const_child_range = llvm::iterator_range<const_child_iterator>; child_range children(); const_child_range children() const { auto Children = const_cast<OMPClause *>(this)->children(); return const_child_range(Children.begin(), Children.end()); } + static bool classof(const OMPClause *) { return true; } }; @@ -75,29 +98,34 @@ public: /// 'shedule', 'firstprivate' etc. class OMPClauseWithPreInit { friend class OMPClauseReader; + /// Pre-initialization statement for the clause. - Stmt *PreInit; + Stmt *PreInit = nullptr; + /// Region that captures the associated stmt. - OpenMPDirectiveKind CaptureRegion; + OpenMPDirectiveKind CaptureRegion = OMPD_unknown; protected: + OMPClauseWithPreInit(const OMPClause *This) { + assert(get(This) && "get is not tuned for pre-init."); + } + /// Set pre-initialization statement for the clause. void setPreInitStmt(Stmt *S, OpenMPDirectiveKind ThisRegion = OMPD_unknown) { PreInit = S; CaptureRegion = ThisRegion; } - OMPClauseWithPreInit(const OMPClause *This) - : PreInit(nullptr), CaptureRegion(OMPD_unknown) { - assert(get(This) && "get is not tuned for pre-init."); - } public: /// Get pre-initialization statement for the clause. const Stmt *getPreInitStmt() const { return PreInit; } + /// Get pre-initialization statement for the clause. Stmt *getPreInitStmt() { return PreInit; } + /// Get capture region for the stmt in the clause. OpenMPDirectiveKind getCaptureRegion() { return CaptureRegion; } + static OMPClauseWithPreInit *get(OMPClause *C); static const OMPClauseWithPreInit *get(const OMPClause *C); }; @@ -106,21 +134,25 @@ public: /// 'lastprivate', 'reduction' etc. class OMPClauseWithPostUpdate : public OMPClauseWithPreInit { friend class OMPClauseReader; + /// Post-update expression for the clause. - Expr *PostUpdate; + Expr *PostUpdate = nullptr; + protected: - /// Set pre-initialization statement for the clause. - void setPostUpdateExpr(Expr *S) { PostUpdate = S; } - OMPClauseWithPostUpdate(const OMPClause *This) - : OMPClauseWithPreInit(This), PostUpdate(nullptr) { + OMPClauseWithPostUpdate(const OMPClause *This) : OMPClauseWithPreInit(This) { assert(get(This) && "get is not tuned for post-update."); } + /// Set pre-initialization statement for the clause. + void setPostUpdateExpr(Expr *S) { PostUpdate = S; } + public: /// Get post-update expression for the clause. const Expr *getPostUpdateExpr() const { return PostUpdate; } + /// Get post-update expression for the clause. Expr *getPostUpdateExpr() { return PostUpdate; } + static OMPClauseWithPostUpdate *get(OMPClause *C); static const OMPClauseWithPostUpdate *get(const OMPClause *C); }; @@ -130,12 +162,25 @@ public: /// '#pragma omp ...' directives. template <class T> class OMPVarListClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Number of variables in the list. unsigned NumVars; protected: + /// \brief Build a clause with \a N variables + /// + /// \param K Kind of the clause. + /// \param StartLoc Starting location of the clause (the clause keyword). + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + OMPVarListClause(OpenMPClauseKind K, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) + : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {} + /// \brief Fetches list of variables associated with this clause. MutableArrayRef<Expr *> getVarRefs() { return MutableArrayRef<Expr *>( @@ -150,23 +195,11 @@ protected: static_cast<T *>(this)->template getTrailingObjects<Expr *>()); } - /// \brief Build a clause with \a N variables - /// - /// \param K Kind of the clause. - /// \param StartLoc Starting location of the clause (the clause keyword). - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. - /// - OMPVarListClause(OpenMPClauseKind K, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {} - public: - typedef MutableArrayRef<Expr *>::iterator varlist_iterator; - typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; - typedef llvm::iterator_range<varlist_iterator> varlist_range; - typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; + using varlist_iterator = MutableArrayRef<Expr *>::iterator; + using varlist_const_iterator = ArrayRef<const Expr *>::iterator; + using varlist_range = llvm::iterator_range<varlist_iterator>; + using varlist_const_range = llvm::iterator_range<varlist_const_iterator>; unsigned varlist_size() const { return NumVars; } bool varlist_empty() const { return NumVars == 0; } @@ -185,6 +218,7 @@ public: /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } @@ -203,31 +237,34 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has simple 'if' clause with /// condition 'a > 5' and directive name modifier 'parallel'. -/// class OMPIfClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Condition of the 'if' clause. - Stmt *Condition; + Stmt *Condition = nullptr; + /// \brief Location of ':' (if any). SourceLocation ColonLoc; + /// \brief Directive name modifier for the clause. - OpenMPDirectiveKind NameModifier; + OpenMPDirectiveKind NameModifier = OMPD_unknown; + /// \brief Name modifier location. SourceLocation NameModifierLoc; /// \brief Set condition. - /// void setCondition(Expr *Cond) { Condition = Cond; } + /// \brief Set directive name modifier for the clause. - /// void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; } + /// \brief Set location of directive name modifier for the clause. - /// void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; } + /// \brief Set location of ':'. - /// void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } public: @@ -243,7 +280,6 @@ public: /// \param NameModifierLoc Location of directive name modifier. /// \param ColonLoc [OpenMP 4.1] Location of ':'. /// \param EndLoc Ending location of the clause. - /// OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond, Stmt *HelperCond, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, @@ -255,14 +291,13 @@ public: } /// \brief Build an empty clause. - /// OMPIfClause() : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this), LParenLoc(), Condition(nullptr), ColonLoc(), - NameModifier(OMPD_unknown), NameModifierLoc() {} + OMPClauseWithPreInit(this) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } @@ -271,17 +306,18 @@ public: /// \brief Returns condition. Expr *getCondition() const { return cast_or_null<Expr>(Condition); } + /// \brief Return directive name modifier associated with the clause. OpenMPDirectiveKind getNameModifier() const { return NameModifier; } /// \brief Return the location of directive name modifier. SourceLocation getNameModifierLoc() const { return NameModifierLoc; } + child_range children() { return child_range(&Condition, &Condition + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_if; } - - child_range children() { return child_range(&Condition, &Condition + 1); } }; /// \brief This represents 'final' clause in the '#pragma omp ...' directive. @@ -291,16 +327,16 @@ public: /// \endcode /// In this example directive '#pragma omp task' has simple 'final' /// clause with condition 'a > 5'. -/// class OMPFinalClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Condition of the 'if' clause. - Stmt *Condition; + Stmt *Condition = nullptr; /// \brief Set condition. - /// void setCondition(Expr *Cond) { Condition = Cond; } public: @@ -310,31 +346,29 @@ public: /// \param LParenLoc Location of '('. /// \param Cond Condition of the clause. /// \param EndLoc Ending location of the clause. - /// OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc), Condition(Cond) {} /// \brief Build an empty clause. - /// OMPFinalClause() - : OMPClause(OMPC_final, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Condition(nullptr) {} + : OMPClause(OMPC_final, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief Returns condition. Expr *getCondition() const { return cast_or_null<Expr>(Condition); } + child_range children() { return child_range(&Condition, &Condition + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_final; } - - child_range children() { return child_range(&Condition, &Condition + 1); } }; /// \brief This represents 'num_threads' clause in the '#pragma omp ...' @@ -345,16 +379,16 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has simple 'num_threads' /// clause with number of threads '6'. -/// class OMPNumThreadsClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Condition of the 'num_threads' clause. - Stmt *NumThreads; + Stmt *NumThreads = nullptr; /// \brief Set condition. - /// void setNumThreads(Expr *NThreads) { NumThreads = NThreads; } public: @@ -367,7 +401,6 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPNumThreadsClause(Expr *NumThreads, Stmt *HelperNumThreads, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -379,25 +412,24 @@ public: } /// \brief Build an empty clause. - /// OMPNumThreadsClause() : OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this), LParenLoc(SourceLocation()), - NumThreads(nullptr) {} + OMPClauseWithPreInit(this) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief Returns number of threads. Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); } + child_range children() { return child_range(&NumThreads, &NumThreads + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_num_threads; } - - child_range children() { return child_range(&NumThreads, &NumThreads + 1); } }; /// \brief This represents 'safelen' clause in the '#pragma omp ...' @@ -412,13 +444,14 @@ public: /// concurrently with SIMD instructions can have a greater distance /// in the logical iteration space than its value. The parameter of /// the safelen clause must be a constant positive integer expression. -/// class OMPSafelenClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Safe iteration space distance. - Stmt *Safelen; + Stmt *Safelen = nullptr; /// \brief Set safelen. void setSafelen(Expr *Len) { Safelen = Len; } @@ -429,31 +462,29 @@ public: /// \param Len Expression associated with this clause. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc), Safelen(Len) {} /// \brief Build an empty clause. - /// explicit OMPSafelenClause() - : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Safelen(nullptr) {} + : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief Return safe iteration space distance. Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); } + child_range children() { return child_range(&Safelen, &Safelen + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_safelen; } - - child_range children() { return child_range(&Safelen, &Safelen + 1); } }; /// \brief This represents 'simdlen' clause in the '#pragma omp ...' @@ -467,13 +498,14 @@ public: /// If the 'simdlen' clause is used then it specifies the preferred number of /// iterations to be executed concurrently. The parameter of the 'simdlen' /// clause must be a constant positive integer expression. -/// class OMPSimdlenClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Safe iteration space distance. - Stmt *Simdlen; + Stmt *Simdlen = nullptr; /// \brief Set simdlen. void setSimdlen(Expr *Len) { Simdlen = Len; } @@ -484,31 +516,29 @@ public: /// \param Len Expression associated with this clause. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc), Simdlen(Len) {} /// \brief Build an empty clause. - /// explicit OMPSimdlenClause() - : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Simdlen(nullptr) {} + : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief Return safe iteration space distance. Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); } + child_range children() { return child_range(&Simdlen, &Simdlen + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_simdlen; } - - child_range children() { return child_range(&Simdlen, &Simdlen + 1); } }; /// \brief This represents 'collapse' clause in the '#pragma omp ...' @@ -522,13 +552,14 @@ public: /// The parameter must be a constant positive integer expression, it specifies /// the number of nested loops that should be collapsed into a single iteration /// space. -/// class OMPCollapseClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Number of for-loops. - Stmt *NumForLoops; + Stmt *NumForLoops = nullptr; /// \brief Set the number of associated for-loops. void setNumForLoops(Expr *Num) { NumForLoops = Num; } @@ -540,31 +571,29 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPCollapseClause(Expr *Num, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc), NumForLoops(Num) {} /// \brief Build an empty clause. - /// explicit OMPCollapseClause() - : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumForLoops(nullptr) {} + : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief 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); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_collapse; } - - child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } }; /// \brief This represents 'default' clause in the '#pragma omp ...' directive. @@ -574,26 +603,26 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has simple 'default' /// clause with kind 'shared'. -/// class OMPDefaultClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief A kind of the 'default' clause. - OpenMPDefaultClauseKind Kind; + OpenMPDefaultClauseKind Kind = OMPC_DEFAULT_unknown; + /// \brief Start location of the kind in source code. SourceLocation KindKwLoc; /// \brief Set kind of the clauses. /// /// \param K Argument of clause. - /// void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; } /// \brief Set argument location. /// /// \param KLoc Argument location. - /// void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } public: @@ -604,7 +633,6 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) @@ -612,14 +640,12 @@ public: Kind(A), KindKwLoc(ALoc) {} /// \brief Build an empty clause. - /// OMPDefaultClause() - : OMPClause(OMPC_default, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown), - KindKwLoc(SourceLocation()) {} + : OMPClause(OMPC_default, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } @@ -629,13 +655,13 @@ public: /// \brief Returns location of clause kind. SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_default; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_default; + } }; /// \brief This represents 'proc_bind' clause in the '#pragma omp ...' @@ -646,26 +672,26 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has simple 'proc_bind' /// clause with kind 'master'. -/// class OMPProcBindClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief A kind of the 'proc_bind' clause. - OpenMPProcBindClauseKind Kind; + OpenMPProcBindClauseKind Kind = OMPC_PROC_BIND_unknown; + /// \brief Start location of the kind in source code. SourceLocation KindKwLoc; /// \brief Set kind of the clause. /// /// \param K Kind of clause. - /// void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; } /// \brief Set clause kind location. /// /// \param KLoc Kind location. - /// void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } public: @@ -677,7 +703,6 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) @@ -685,14 +710,12 @@ public: Kind(A), KindKwLoc(ALoc) {} /// \brief Build an empty clause. - /// OMPProcBindClause() - : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Kind(OMPC_PROC_BIND_unknown), - KindKwLoc(SourceLocation()) {} + : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } @@ -702,13 +725,13 @@ public: /// \brief Returns location of clause kind. SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; } - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_proc_bind; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_proc_bind; + } }; /// \brief This represents 'schedule' clause in the '#pragma omp ...' directive. @@ -718,58 +741,63 @@ public: /// \endcode /// In this example directive '#pragma omp for' has 'schedule' clause with /// arguments 'static' and '3'. -/// class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief A kind of the 'schedule' clause. - OpenMPScheduleClauseKind Kind; + OpenMPScheduleClauseKind Kind = OMPC_SCHEDULE_unknown; + /// \brief Modifiers for 'schedule' clause. enum {FIRST, SECOND, NUM_MODIFIERS}; OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS]; + /// \brief Locations of modifiers. SourceLocation ModifiersLoc[NUM_MODIFIERS]; + /// \brief Start location of the schedule ind in source code. SourceLocation KindLoc; + /// \brief Location of ',' (if any). SourceLocation CommaLoc; + /// \brief Chunk size. - Expr *ChunkSize; + Expr *ChunkSize = nullptr; /// \brief Set schedule kind. /// /// \param K Schedule kind. - /// void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; } + /// \brief Set the first schedule modifier. /// /// \param M Schedule modifier. - /// void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) { Modifiers[FIRST] = M; } + /// \brief Set the second schedule modifier. /// /// \param M Schedule modifier. - /// void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) { Modifiers[SECOND] = M; } + /// \brief Set location of the first schedule modifier. - /// void setFirstScheduleModifierLoc(SourceLocation Loc) { ModifiersLoc[FIRST] = Loc; } + /// \brief Set location of the second schedule modifier. - /// void setSecondScheduleModifierLoc(SourceLocation Loc) { ModifiersLoc[SECOND] = Loc; } + /// \brief Set schedule modifier location. /// /// \param M Schedule modifier location. - /// void setScheduleModifer(OpenMPScheduleClauseModifier M) { if (Modifiers[FIRST] == OMPC_SCHEDULE_MODIFIER_unknown) Modifiers[FIRST] = M; @@ -778,25 +806,25 @@ class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit { Modifiers[SECOND] = M; } } + /// \brief Sets the location of '('. /// /// \param Loc Location of '('. - /// void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Set schedule kind start location. /// /// \param KLoc Schedule kind location. - /// void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } + /// \brief Set location of ','. /// /// \param Loc Location of ','. - /// void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; } + /// \brief Set chunk size. /// /// \param E Chunk size. - /// void setChunkSize(Expr *E) { ChunkSize = E; } public: @@ -815,7 +843,6 @@ public: /// \param M1Loc Location of the first modifier /// \param M2 The second modifier applied to 'schedule' clause. /// \param M2Loc Location of the second modifier - /// OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KLoc, SourceLocation CommaLoc, SourceLocation EndLoc, OpenMPScheduleClauseKind Kind, @@ -833,62 +860,59 @@ public: } /// \brief Build an empty clause. - /// explicit OMPScheduleClause() : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this), Kind(OMPC_SCHEDULE_unknown), - ChunkSize(nullptr) { + OMPClauseWithPreInit(this) { Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown; Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown; } /// \brief Get kind of the clause. - /// OpenMPScheduleClauseKind getScheduleKind() const { return Kind; } + /// \brief Get the first modifier of the clause. - /// OpenMPScheduleClauseModifier getFirstScheduleModifier() const { return Modifiers[FIRST]; } + /// \brief Get the second modifier of the clause. - /// OpenMPScheduleClauseModifier getSecondScheduleModifier() const { return Modifiers[SECOND]; } + /// \brief Get location of '('. - /// SourceLocation getLParenLoc() { return LParenLoc; } + /// \brief Get kind location. - /// SourceLocation getScheduleKindLoc() { return KindLoc; } + /// \brief Get the first modifier location. - /// SourceLocation getFirstScheduleModifierLoc() const { return ModifiersLoc[FIRST]; } + /// \brief Get the second modifier location. - /// SourceLocation getSecondScheduleModifierLoc() const { return ModifiersLoc[SECOND]; } + /// \brief Get location of ','. - /// SourceLocation getCommaLoc() { return CommaLoc; } + /// \brief Get chunk size. - /// Expr *getChunkSize() { return ChunkSize; } + /// \brief Get chunk size. - /// const Expr *getChunkSize() const { return ChunkSize; } - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_schedule; - } - child_range children() { return child_range(reinterpret_cast<Stmt **>(&ChunkSize), reinterpret_cast<Stmt **>(&ChunkSize) + 1); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_schedule; + } }; /// \brief This represents 'ordered' clause in the '#pragma omp ...' directive. @@ -898,13 +922,14 @@ public: /// \endcode /// In this example directive '#pragma omp for' has 'ordered' clause with /// parameter 2. -/// class OMPOrderedClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Number of for-loops. - Stmt *NumForLoops; + Stmt *NumForLoops = nullptr; /// \brief Set the number of associated for-loops. void setNumForLoops(Expr *Num) { NumForLoops = Num; } @@ -916,31 +941,29 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPOrderedClause(Expr *Num, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), NumForLoops(Num) {} /// \brief Build an empty clause. - /// explicit OMPOrderedClause() - : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumForLoops(nullptr) {} + : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief 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); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_ordered; } - - child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } }; /// \brief This represents 'nowait' clause in the '#pragma omp ...' directive. @@ -949,29 +972,26 @@ public: /// #pragma omp for nowait /// \endcode /// In this example directive '#pragma omp for' has 'nowait' clause. -/// class OMPNowaitClause : public OMPClause { public: /// \brief 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. - /// OMPNowaitClause() : OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_nowait; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_nowait; + } }; /// \brief This represents 'untied' clause in the '#pragma omp ...' directive. @@ -980,29 +1000,26 @@ public: /// #pragma omp task untied /// \endcode /// In this example directive '#pragma omp task' has 'untied' clause. -/// class OMPUntiedClause : public OMPClause { public: /// \brief 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. - /// OMPUntiedClause() : OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_untied; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_untied; + } }; /// \brief This represents 'mergeable' clause in the '#pragma omp ...' @@ -1012,29 +1029,26 @@ public: /// #pragma omp task mergeable /// \endcode /// In this example directive '#pragma omp task' has 'mergeable' clause. -/// class OMPMergeableClause : public OMPClause { public: /// \brief 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. - /// OMPMergeableClause() : OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_mergeable; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_mergeable; + } }; /// \brief This represents 'read' clause in the '#pragma omp atomic' directive. @@ -1043,28 +1057,25 @@ public: /// #pragma omp atomic read /// \endcode /// In this example directive '#pragma omp atomic' has 'read' clause. -/// class OMPReadClause : public OMPClause { public: /// \brief Build 'read' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_read, StartLoc, EndLoc) {} /// \brief Build an empty clause. - /// OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_read; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_read; + } }; /// \brief This represents 'write' clause in the '#pragma omp atomic' directive. @@ -1073,29 +1084,26 @@ public: /// #pragma omp atomic write /// \endcode /// In this example directive '#pragma omp atomic' has 'write' clause. -/// class OMPWriteClause : public OMPClause { public: /// \brief Build 'write' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_write, StartLoc, EndLoc) {} /// \brief Build an empty clause. - /// OMPWriteClause() : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_write; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_write; + } }; /// \brief This represents 'update' clause in the '#pragma omp atomic' @@ -1105,29 +1113,26 @@ public: /// #pragma omp atomic update /// \endcode /// In this example directive '#pragma omp atomic' has 'update' clause. -/// class OMPUpdateClause : public OMPClause { public: /// \brief Build 'update' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_update, StartLoc, EndLoc) {} /// \brief Build an empty clause. - /// OMPUpdateClause() : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_update; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_update; + } }; /// \brief This represents 'capture' clause in the '#pragma omp atomic' @@ -1137,29 +1142,26 @@ public: /// #pragma omp atomic capture /// \endcode /// In this example directive '#pragma omp atomic' has 'capture' clause. -/// class OMPCaptureClause : public OMPClause { public: /// \brief Build 'capture' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_capture, StartLoc, EndLoc) {} /// \brief Build an empty clause. - /// OMPCaptureClause() : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_capture; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_capture; + } }; /// \brief This represents 'seq_cst' clause in the '#pragma omp atomic' @@ -1169,29 +1171,26 @@ public: /// #pragma omp atomic seq_cst /// \endcode /// In this example directive '#pragma omp atomic' has 'seq_cst' clause. -/// class OMPSeqCstClause : public OMPClause { public: /// \brief Build 'seq_cst' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {} /// \brief Build an empty clause. - /// OMPSeqCstClause() : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_seq_cst; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_seq_cst; + } }; /// \brief This represents clause 'private' in the '#pragma omp ...' directives. @@ -1201,20 +1200,19 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has clause 'private' /// with the variables 'a' and 'b'. -/// class OMPPrivateClause final : public OMPVarListClause<OMPPrivateClause>, private llvm::TrailingObjects<OMPPrivateClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc, @@ -1223,7 +1221,6 @@ class OMPPrivateClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPPrivateClause(unsigned N) : OMPVarListClause<OMPPrivateClause>(OMPC_private, SourceLocation(), SourceLocation(), SourceLocation(), @@ -1252,28 +1249,28 @@ public: /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. /// \param PrivateVL List of references to private copies with initializers. - /// static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL); + /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. - /// static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); - typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; - typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; - typedef llvm::iterator_range<private_copies_iterator> private_copies_range; - typedef llvm::iterator_range<private_copies_const_iterator> - private_copies_const_range; + using private_copies_iterator = MutableArrayRef<Expr *>::iterator; + using private_copies_const_iterator = ArrayRef<const Expr *>::iterator; + using private_copies_range = llvm::iterator_range<private_copies_iterator>; + using private_copies_const_range = + llvm::iterator_range<private_copies_const_iterator>; private_copies_range private_copies() { return private_copies_range(getPrivateCopies().begin(), getPrivateCopies().end()); } + private_copies_const_range private_copies() const { return private_copies_const_range(getPrivateCopies().begin(), getPrivateCopies().end()); @@ -1297,14 +1294,13 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has clause 'firstprivate' /// with the variables 'a' and 'b'. -/// class OMPFirstprivateClause final : public OMPVarListClause<OMPFirstprivateClause>, public OMPClauseWithPreInit, private llvm::TrailingObjects<OMPFirstprivateClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; /// \brief Build clause with number of variables \a N. /// @@ -1312,7 +1308,6 @@ class OMPFirstprivateClause final /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPFirstprivateClause>(OMPC_firstprivate, StartLoc, @@ -1322,12 +1317,12 @@ class OMPFirstprivateClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPFirstprivateClause(unsigned N) : OMPVarListClause<OMPFirstprivateClause>( OMPC_firstprivate, SourceLocation(), SourceLocation(), SourceLocation(), N), OMPClauseWithPreInit(this) {} + /// \brief Sets the list of references to private copies with initializers for /// new private variables. /// \param VL List of references. @@ -1370,23 +1365,22 @@ public: /// of array type. /// \param PreInit Statement that must be executed before entering the OpenMP /// region with this clause. - /// static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, ArrayRef<Expr *> InitVL, Stmt *PreInit); + /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. - /// static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N); - typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; - typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; - typedef llvm::iterator_range<private_copies_iterator> private_copies_range; - typedef llvm::iterator_range<private_copies_const_iterator> - private_copies_const_range; + using private_copies_iterator = MutableArrayRef<Expr *>::iterator; + using private_copies_const_iterator = ArrayRef<const Expr *>::iterator; + using private_copies_range = llvm::iterator_range<private_copies_iterator>; + using private_copies_const_range = + llvm::iterator_range<private_copies_const_iterator>; private_copies_range private_copies() { return private_copies_range(getPrivateCopies().begin(), @@ -1397,10 +1391,10 @@ public: getPrivateCopies().end()); } - typedef MutableArrayRef<Expr *>::iterator inits_iterator; - typedef ArrayRef<const Expr *>::iterator inits_const_iterator; - typedef llvm::iterator_range<inits_iterator> inits_range; - typedef llvm::iterator_range<inits_const_iterator> inits_const_range; + using inits_iterator = MutableArrayRef<Expr *>::iterator; + using inits_const_iterator = ArrayRef<const Expr *>::iterator; + using inits_range = llvm::iterator_range<inits_iterator>; + using inits_const_range = llvm::iterator_range<inits_const_iterator>; inits_range inits() { return inits_range(getInits().begin(), getInits().end()); @@ -1447,10 +1441,9 @@ class OMPLastprivateClause final // \endcode // Required for proper codegen of final assignment performed by the // lastprivate clause. - // - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; /// \brief Build clause with number of variables \a N. /// @@ -1458,7 +1451,6 @@ class OMPLastprivateClause final /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPLastprivateClause>(OMPC_lastprivate, StartLoc, @@ -1468,7 +1460,6 @@ class OMPLastprivateClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPLastprivateClause(unsigned N) : OMPVarListClause<OMPLastprivateClause>( OMPC_lastprivate, SourceLocation(), SourceLocation(), @@ -1550,24 +1541,23 @@ public: /// region with this clause. /// \param PostUpdate Expression that must be executed after exit from the /// OpenMP region with this clause. - /// static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps, Stmt *PreInit, Expr *PostUpdate); + /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. - /// static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N); - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; + using helper_expr_iterator = MutableArrayRef<Expr *>::iterator; + using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator; + using helper_expr_range = llvm::iterator_range<helper_expr_iterator>; + using helper_expr_const_range = + llvm::iterator_range<helper_expr_const_iterator>; /// \brief Set list of helper expressions, required for generation of private /// copies of original lastprivate variables. @@ -1577,29 +1567,36 @@ public: return helper_expr_const_range(getPrivateCopies().begin(), getPrivateCopies().end()); } + helper_expr_range private_copies() { return helper_expr_range(getPrivateCopies().begin(), getPrivateCopies().end()); } + helper_expr_const_range source_exprs() const { return helper_expr_const_range(getSourceExprs().begin(), getSourceExprs().end()); } + helper_expr_range source_exprs() { return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end()); } + helper_expr_const_range destination_exprs() const { return helper_expr_const_range(getDestinationExprs().begin(), getDestinationExprs().end()); } + helper_expr_range destination_exprs() { return helper_expr_range(getDestinationExprs().begin(), getDestinationExprs().end()); } + helper_expr_const_range assignment_ops() const { return helper_expr_const_range(getAssignmentOps().begin(), getAssignmentOps().end()); } + helper_expr_range assignment_ops() { return helper_expr_range(getAssignmentOps().begin(), getAssignmentOps().end()); @@ -1622,19 +1619,18 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has clause 'shared' /// with the variables 'a' and 'b'. -/// class OMPSharedClause final : public OMPVarListClause<OMPSharedClause>, private llvm::TrailingObjects<OMPSharedClause, Expr *> { - friend TrailingObjects; friend OMPVarListClause; + friend TrailingObjects; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc, @@ -1643,7 +1639,6 @@ class OMPSharedClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPSharedClause(unsigned N) : OMPVarListClause<OMPSharedClause>(OMPC_shared, SourceLocation(), SourceLocation(), SourceLocation(), @@ -1657,15 +1652,14 @@ public: /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. - /// static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. - /// static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N); child_range children() { @@ -1686,18 +1680,20 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has clause 'reduction' /// with operator '+' and the variables 'a' and 'b'. -/// class OMPReductionClause final : public OMPVarListClause<OMPReductionClause>, public OMPClauseWithPostUpdate, private llvm::TrailingObjects<OMPReductionClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// \brief Location of ':'. SourceLocation ColonLoc; + /// \brief Nested name specifier for C++. NestedNameSpecifierLoc QualifierLoc; + /// \brief Name of custom operator. DeclarationNameInfo NameInfo; @@ -1710,7 +1706,6 @@ class OMPReductionClause final /// \param N Number of the variables in the clause. /// \param QualifierLoc The nested-name qualifier with location information /// \param NameInfo The full name info for reduction identifier. - /// OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N, NestedNameSpecifierLoc QualifierLoc, @@ -1723,17 +1718,18 @@ class OMPReductionClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPReductionClause(unsigned N) : OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(), SourceLocation(), SourceLocation(), N), - OMPClauseWithPostUpdate(this), ColonLoc(), QualifierLoc(), NameInfo() {} + OMPClauseWithPostUpdate(this) {} /// \brief Sets location of ':' symbol in clause. void setColonLoc(SourceLocation CL) { ColonLoc = CL; } + /// \brief Sets the name info for specified reduction identifier. void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; } + /// \brief Sets the nested name specifier. void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; } @@ -1825,7 +1821,6 @@ public: /// region with this clause. /// \param PostUpdate Expression that must be executed after exit from the /// OpenMP region with this clause. - /// static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, @@ -1833,48 +1828,57 @@ public: const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates, 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. /// /// \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. SourceLocation getColonLoc() const { return ColonLoc; } + /// \brief Gets the name info for specified reduction identifier. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + /// \brief Gets the nested name specifier. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; + using helper_expr_iterator = MutableArrayRef<Expr *>::iterator; + using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator; + using helper_expr_range = llvm::iterator_range<helper_expr_iterator>; + using helper_expr_const_range = + llvm::iterator_range<helper_expr_const_iterator>; helper_expr_const_range privates() const { return helper_expr_const_range(getPrivates().begin(), getPrivates().end()); } + helper_expr_range privates() { return helper_expr_range(getPrivates().begin(), getPrivates().end()); } + helper_expr_const_range lhs_exprs() const { return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end()); } + helper_expr_range lhs_exprs() { return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end()); } + helper_expr_const_range rhs_exprs() const { return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end()); } + helper_expr_range rhs_exprs() { return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end()); } + helper_expr_const_range reduction_ops() const { return helper_expr_const_range(getReductionOps().begin(), getReductionOps().end()); } + helper_expr_range reduction_ops() { return helper_expr_range(getReductionOps().begin(), getReductionOps().end()); @@ -1898,18 +1902,20 @@ public: /// \endcode /// In this example directive '#pragma omp taskgroup' has clause /// 'task_reduction' with operator '+' and the variables 'a' and 'b'. -/// class OMPTaskReductionClause final : public OMPVarListClause<OMPTaskReductionClause>, public OMPClauseWithPostUpdate, private llvm::TrailingObjects<OMPTaskReductionClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// Location of ':'. SourceLocation ColonLoc; + /// Nested name specifier for C++. NestedNameSpecifierLoc QualifierLoc; + /// Name of custom operator. DeclarationNameInfo NameInfo; @@ -1922,7 +1928,6 @@ class OMPTaskReductionClause final /// \param N Number of the variables in the clause. /// \param QualifierLoc The nested-name qualifier with location information /// \param NameInfo The full name info for reduction identifier. - /// OMPTaskReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N, NestedNameSpecifierLoc QualifierLoc, @@ -1935,17 +1940,18 @@ class OMPTaskReductionClause final /// Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPTaskReductionClause(unsigned N) : OMPVarListClause<OMPTaskReductionClause>( OMPC_task_reduction, SourceLocation(), SourceLocation(), SourceLocation(), N), - OMPClauseWithPostUpdate(this), ColonLoc(), QualifierLoc(), NameInfo() {} + OMPClauseWithPostUpdate(this) {} /// Sets location of ':' symbol in clause. void setColonLoc(SourceLocation CL) { ColonLoc = CL; } + /// Sets the name info for specified reduction identifier. void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; } + /// Sets the nested name specifier. void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; } @@ -2035,7 +2041,6 @@ public: /// region with this clause. /// \param PostUpdate Expression that must be executed after exit from the /// OpenMP region with this clause. - /// static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, @@ -2048,44 +2053,52 @@ public: /// /// \param C AST context. /// \param N The number of variables. - /// static OMPTaskReductionClause *CreateEmpty(const ASTContext &C, unsigned N); /// Gets location of ':' symbol in clause. SourceLocation getColonLoc() const { return ColonLoc; } + /// Gets the name info for specified reduction identifier. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + /// Gets the nested name specifier. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; + using helper_expr_iterator = MutableArrayRef<Expr *>::iterator; + using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator; + using helper_expr_range = llvm::iterator_range<helper_expr_iterator>; + using helper_expr_const_range = + llvm::iterator_range<helper_expr_const_iterator>; helper_expr_const_range privates() const { return helper_expr_const_range(getPrivates().begin(), getPrivates().end()); } + helper_expr_range privates() { return helper_expr_range(getPrivates().begin(), getPrivates().end()); } + helper_expr_const_range lhs_exprs() const { return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end()); } + helper_expr_range lhs_exprs() { return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end()); } + helper_expr_const_range rhs_exprs() const { return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end()); } + helper_expr_range rhs_exprs() { return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end()); } + helper_expr_const_range reduction_ops() const { return helper_expr_const_range(getReductionOps().begin(), getReductionOps().end()); } + helper_expr_range reduction_ops() { return helper_expr_range(getReductionOps().begin(), getReductionOps().end()); @@ -2101,6 +2114,249 @@ public: } }; +/// This represents clause 'in_reduction' in the '#pragma omp task' directives. +/// +/// \code +/// #pragma omp task in_reduction(+:a,b) +/// \endcode +/// In this example directive '#pragma omp task' has clause 'in_reduction' with +/// operator '+' and the variables 'a' and 'b'. +class OMPInReductionClause final + : public OMPVarListClause<OMPInReductionClause>, + public OMPClauseWithPostUpdate, + private llvm::TrailingObjects<OMPInReductionClause, Expr *> { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// Location of ':'. + SourceLocation ColonLoc; + + /// Nested name specifier for C++. + NestedNameSpecifierLoc QualifierLoc; + + /// Name of custom operator. + DeclarationNameInfo NameInfo; + + /// Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param ColonLoc Location of ':'. + /// \param N Number of the variables in the clause. + /// \param QualifierLoc The nested-name qualifier with location information + /// \param NameInfo The full name info for reduction identifier. + OMPInReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, + unsigned N, NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo) + : OMPVarListClause<OMPInReductionClause>(OMPC_in_reduction, StartLoc, + LParenLoc, EndLoc, N), + OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc), + QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} + + /// Build an empty clause. + /// + /// \param N Number of variables. + explicit OMPInReductionClause(unsigned N) + : OMPVarListClause<OMPInReductionClause>( + OMPC_in_reduction, SourceLocation(), SourceLocation(), + SourceLocation(), N), + OMPClauseWithPostUpdate(this) {} + + /// Sets location of ':' symbol in clause. + void setColonLoc(SourceLocation CL) { ColonLoc = CL; } + + /// Sets the name info for specified reduction identifier. + void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; } + + /// Sets the nested name specifier. + void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; } + + /// 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); + + /// Get the list of helper privates. + MutableArrayRef<Expr *> getPrivates() { + return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); + } + ArrayRef<const Expr *> getPrivates() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + + /// 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); + + /// Get the list of helper LHS expressions. + MutableArrayRef<Expr *> getLHSExprs() { + return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); + } + ArrayRef<const Expr *> getLHSExprs() const { + return llvm::makeArrayRef(getPrivates().end(), varlist_size()); + } + + /// 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); + + /// Get the list of helper destination expressions. + MutableArrayRef<Expr *> getRHSExprs() { + return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size()); + } + ArrayRef<const Expr *> getRHSExprs() const { + return llvm::makeArrayRef(getLHSExprs().end(), varlist_size()); + } + + /// 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); + + /// Get the list of helper reduction expressions. + MutableArrayRef<Expr *> getReductionOps() { + return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size()); + } + ArrayRef<const Expr *> getReductionOps() const { + return llvm::makeArrayRef(getRHSExprs().end(), varlist_size()); + } + + /// Set list of helper reduction taskgroup descriptors. + void setTaskgroupDescriptors(ArrayRef<Expr *> ReductionOps); + + /// Get the list of helper reduction taskgroup descriptors. + MutableArrayRef<Expr *> getTaskgroupDescriptors() { + return MutableArrayRef<Expr *>(getReductionOps().end(), varlist_size()); + } + ArrayRef<const Expr *> getTaskgroupDescriptors() const { + return llvm::makeArrayRef(getReductionOps().end(), varlist_size()); + } + +public: + /// Creates clause with a list of variables \a VL. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param VL The variables in the clause. + /// \param QualifierLoc The nested-name qualifier with location information + /// \param NameInfo The full name info for reduction identifier. + /// \param Privates List of helper expressions for proper generation of + /// private copies. + /// \param LHSExprs List of helper expressions for proper generation of + /// assignment operation required for copyprivate clause. This list represents + /// LHSs of the reduction expressions. + /// \param RHSExprs List of helper expressions for proper generation of + /// assignment operation required for copyprivate clause. This list represents + /// RHSs of the reduction expressions. + /// Also, variables in these expressions are used for proper initialization of + /// reduction copies. + /// \param ReductionOps List of helper expressions that represents reduction + /// expressions: + /// \code + /// LHSExprs binop RHSExprs; + /// operator binop(LHSExpr, RHSExpr); + /// <CutomReduction>(LHSExpr, RHSExpr); + /// \endcode + /// Required for proper codegen of final reduction operation performed by the + /// reduction clause. + /// \param TaskgroupDescriptors List of helper taskgroup descriptors for + /// corresponding items in parent taskgroup task_reduction clause. + /// \param PreInit Statement that must be executed before entering the OpenMP + /// region with this clause. + /// \param PostUpdate Expression that must be executed after exit from the + /// OpenMP region with this clause. + static OMPInReductionClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates, + ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, + ArrayRef<Expr *> ReductionOps, ArrayRef<Expr *> TaskgroupDescriptors, + Stmt *PreInit, Expr *PostUpdate); + + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + static OMPInReductionClause *CreateEmpty(const ASTContext &C, unsigned N); + + /// Gets location of ':' symbol in clause. + SourceLocation getColonLoc() const { return ColonLoc; } + + /// Gets the name info for specified reduction identifier. + const DeclarationNameInfo &getNameInfo() const { return NameInfo; } + + /// Gets the nested name specifier. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + using helper_expr_iterator = MutableArrayRef<Expr *>::iterator; + using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator; + using helper_expr_range = llvm::iterator_range<helper_expr_iterator>; + using helper_expr_const_range = + llvm::iterator_range<helper_expr_const_iterator>; + + helper_expr_const_range privates() const { + return helper_expr_const_range(getPrivates().begin(), getPrivates().end()); + } + + helper_expr_range privates() { + return helper_expr_range(getPrivates().begin(), getPrivates().end()); + } + + helper_expr_const_range lhs_exprs() const { + return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end()); + } + + helper_expr_range lhs_exprs() { + return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end()); + } + + helper_expr_const_range rhs_exprs() const { + return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end()); + } + + helper_expr_range rhs_exprs() { + return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end()); + } + + helper_expr_const_range reduction_ops() const { + return helper_expr_const_range(getReductionOps().begin(), + getReductionOps().end()); + } + + helper_expr_range reduction_ops() { + return helper_expr_range(getReductionOps().begin(), + getReductionOps().end()); + } + + helper_expr_const_range taskgroup_descriptors() const { + return helper_expr_const_range(getTaskgroupDescriptors().begin(), + getTaskgroupDescriptors().end()); + } + + helper_expr_range taskgroup_descriptors() { + return helper_expr_range(getTaskgroupDescriptors().begin(), + getTaskgroupDescriptors().end()); + } + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_in_reduction; + } +}; + /// \brief This represents clause 'linear' in the '#pragma omp ...' /// directives. /// @@ -2109,18 +2365,20 @@ public: /// \endcode /// In this example directive '#pragma omp simd' has clause 'linear' /// with variables 'a', 'b' and linear step '2'. -/// class OMPLinearClause final : public OMPVarListClause<OMPLinearClause>, public OMPClauseWithPostUpdate, private llvm::TrailingObjects<OMPLinearClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// \brief Modifier of 'linear' clause. - OpenMPLinearClauseKind Modifier; + OpenMPLinearClauseKind Modifier = OMPC_LINEAR_val; + /// \brief Location of linear modifier if any. SourceLocation ModifierLoc; + /// \brief Location of ':'. SourceLocation ColonLoc; @@ -2137,7 +2395,6 @@ class OMPLinearClause final /// \param ColonLoc Location of ':'. /// \param EndLoc Ending location of the clause. /// \param NumVars Number of variables. - /// OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, @@ -2150,13 +2407,11 @@ class OMPLinearClause final /// \brief Build an empty clause. /// /// \param NumVars Number of variables. - /// explicit OMPLinearClause(unsigned NumVars) : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(), SourceLocation(), SourceLocation(), NumVars), - OMPClauseWithPostUpdate(this), Modifier(OMPC_LINEAR_val), ModifierLoc(), - ColonLoc() {} + OMPClauseWithPostUpdate(this) {} /// \brief Gets the list of initial values for linear variables. /// @@ -2170,7 +2425,6 @@ class OMPLinearClause final /// /// { Vars[] /* in OMPVarListClause */; Privates[]; Inits[]; Updates[]; /// Finals[]; Step; CalcStep; } - /// MutableArrayRef<Expr *> getPrivates() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } @@ -2240,30 +2494,35 @@ public: /// /// \param C AST context. /// \param NumVars Number of variables. - /// static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars); /// \brief Set modifier. void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; } + /// \brief Return modifier. OpenMPLinearClauseKind getModifier() const { return Modifier; } /// \brief Set modifier location. void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } + /// \brief Return modifier location. SourceLocation getModifierLoc() const { return ModifierLoc; } /// \brief Sets the location of ':'. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// \brief Returns the location of ':'. SourceLocation getColonLoc() const { return ColonLoc; } /// \brief Returns linear step. Expr *getStep() { return *(getFinals().end()); } + /// \brief Returns linear step. const Expr *getStep() const { return *(getFinals().end()); } + /// \brief Returns expression to calculate linear step. Expr *getCalcStep() { return *(getFinals().end() + 1); } + /// \brief Returns expression to calculate linear step. const Expr *getCalcStep() const { return *(getFinals().end() + 1); } @@ -2275,50 +2534,54 @@ public: /// \param FL List of expressions. void setFinals(ArrayRef<Expr *> FL); - typedef MutableArrayRef<Expr *>::iterator privates_iterator; - typedef ArrayRef<const Expr *>::iterator privates_const_iterator; - typedef llvm::iterator_range<privates_iterator> privates_range; - typedef llvm::iterator_range<privates_const_iterator> privates_const_range; + using privates_iterator = MutableArrayRef<Expr *>::iterator; + using privates_const_iterator = ArrayRef<const Expr *>::iterator; + using privates_range = llvm::iterator_range<privates_iterator>; + using privates_const_range = llvm::iterator_range<privates_const_iterator>; privates_range privates() { return privates_range(getPrivates().begin(), getPrivates().end()); } + privates_const_range privates() const { return privates_const_range(getPrivates().begin(), getPrivates().end()); } - typedef MutableArrayRef<Expr *>::iterator inits_iterator; - typedef ArrayRef<const Expr *>::iterator inits_const_iterator; - typedef llvm::iterator_range<inits_iterator> inits_range; - typedef llvm::iterator_range<inits_const_iterator> inits_const_range; + using inits_iterator = MutableArrayRef<Expr *>::iterator; + using inits_const_iterator = ArrayRef<const Expr *>::iterator; + using inits_range = llvm::iterator_range<inits_iterator>; + using inits_const_range = llvm::iterator_range<inits_const_iterator>; inits_range inits() { return inits_range(getInits().begin(), getInits().end()); } + inits_const_range inits() const { return inits_const_range(getInits().begin(), getInits().end()); } - typedef MutableArrayRef<Expr *>::iterator updates_iterator; - typedef ArrayRef<const Expr *>::iterator updates_const_iterator; - typedef llvm::iterator_range<updates_iterator> updates_range; - typedef llvm::iterator_range<updates_const_iterator> updates_const_range; + using updates_iterator = MutableArrayRef<Expr *>::iterator; + using updates_const_iterator = ArrayRef<const Expr *>::iterator; + using updates_range = llvm::iterator_range<updates_iterator>; + using updates_const_range = llvm::iterator_range<updates_const_iterator>; updates_range updates() { return updates_range(getUpdates().begin(), getUpdates().end()); } + updates_const_range updates() const { return updates_const_range(getUpdates().begin(), getUpdates().end()); } - typedef MutableArrayRef<Expr *>::iterator finals_iterator; - typedef ArrayRef<const Expr *>::iterator finals_const_iterator; - typedef llvm::iterator_range<finals_iterator> finals_range; - typedef llvm::iterator_range<finals_const_iterator> finals_const_range; + using finals_iterator = MutableArrayRef<Expr *>::iterator; + using finals_const_iterator = ArrayRef<const Expr *>::iterator; + using finals_range = llvm::iterator_range<finals_iterator>; + using finals_const_range = llvm::iterator_range<finals_const_iterator>; finals_range finals() { return finals_range(getFinals().begin(), getFinals().end()); } + finals_const_range finals() const { return finals_const_range(getFinals().begin(), getFinals().end()); } @@ -2341,13 +2604,13 @@ public: /// \endcode /// In this example directive '#pragma omp simd' has clause 'aligned' /// with variables 'a', 'b' and alignment '8'. -/// class OMPAlignedClause final : public OMPVarListClause<OMPAlignedClause>, private llvm::TrailingObjects<OMPAlignedClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// \brief Location of ':'. SourceLocation ColonLoc; @@ -2361,7 +2624,6 @@ class OMPAlignedClause final /// \param ColonLoc Location of ':'. /// \param EndLoc Ending location of the clause. /// \param NumVars Number of variables. - /// OMPAlignedClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned NumVars) @@ -2372,12 +2634,10 @@ class OMPAlignedClause final /// \brief Build an empty clause. /// /// \param NumVars Number of variables. - /// explicit OMPAlignedClause(unsigned NumVars) : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, SourceLocation(), SourceLocation(), SourceLocation(), - NumVars), - ColonLoc(SourceLocation()) {} + NumVars) {} public: /// \brief Creates clause with a list of variables \a VL and alignment \a A. @@ -2399,16 +2659,17 @@ public: /// /// \param C AST context. /// \param NumVars Number of variables. - /// static OMPAlignedClause *CreateEmpty(const ASTContext &C, unsigned NumVars); /// \brief Sets the location of ':'. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// \brief Returns the location of ':'. SourceLocation getColonLoc() const { return ColonLoc; } /// \brief Returns alignment. Expr *getAlignment() { return *varlist_end(); } + /// \brief Returns alignment. const Expr *getAlignment() const { return *varlist_end(); } @@ -2429,7 +2690,6 @@ public: /// \endcode /// In this example directive '#pragma omp parallel' has clause 'copyin' /// with the variables 'a' and 'b'. -/// class OMPCopyinClause final : public OMPVarListClause<OMPCopyinClause>, private llvm::TrailingObjects<OMPCopyinClause, Expr *> { @@ -2446,16 +2706,16 @@ class OMPCopyinClause final // threadprivate variables to local instances of that variables in other // implicit threads. - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc, @@ -2464,7 +2724,6 @@ class OMPCopyinClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPCopyinClause(unsigned N) : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, SourceLocation(), SourceLocation(), SourceLocation(), @@ -2532,43 +2791,47 @@ public: /// Required for proper codegen of propagation of master's thread values of /// threadprivate variables to local instances of that variables in other /// implicit threads. - /// static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps); + /// \brief Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. - /// static OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N); - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; + using helper_expr_iterator = MutableArrayRef<Expr *>::iterator; + using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator; + using helper_expr_range = llvm::iterator_range<helper_expr_iterator>; + using helper_expr_const_range = + llvm::iterator_range<helper_expr_const_iterator>; helper_expr_const_range source_exprs() const { return helper_expr_const_range(getSourceExprs().begin(), getSourceExprs().end()); } + helper_expr_range source_exprs() { return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end()); } + helper_expr_const_range destination_exprs() const { return helper_expr_const_range(getDestinationExprs().begin(), getDestinationExprs().end()); } + helper_expr_range destination_exprs() { return helper_expr_range(getDestinationExprs().begin(), getDestinationExprs().end()); } + helper_expr_const_range assignment_ops() const { return helper_expr_const_range(getAssignmentOps().begin(), getAssignmentOps().end()); } + helper_expr_range assignment_ops() { return helper_expr_range(getAssignmentOps().begin(), getAssignmentOps().end()); @@ -2592,20 +2855,19 @@ public: /// \endcode /// In this example directive '#pragma omp single' has clause 'copyprivate' /// with the variables 'a' and 'b'. -/// class OMPCopyprivateClause final : public OMPVarListClause<OMPCopyprivateClause>, private llvm::TrailingObjects<OMPCopyprivateClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc, @@ -2614,7 +2876,6 @@ class OMPCopyprivateClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPCopyprivateClause(unsigned N) : OMPVarListClause<OMPCopyprivateClause>( OMPC_copyprivate, SourceLocation(), SourceLocation(), @@ -2681,43 +2942,47 @@ public: /// \endcode /// Required for proper codegen of final assignment performed by the /// copyprivate clause. - /// static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps); + /// \brief Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. - /// static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N); - typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator; - typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator; - typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range; - typedef llvm::iterator_range<helper_expr_const_iterator> - helper_expr_const_range; + using helper_expr_iterator = MutableArrayRef<Expr *>::iterator; + using helper_expr_const_iterator = ArrayRef<const Expr *>::iterator; + using helper_expr_range = llvm::iterator_range<helper_expr_iterator>; + using helper_expr_const_range = + llvm::iterator_range<helper_expr_const_iterator>; helper_expr_const_range source_exprs() const { return helper_expr_const_range(getSourceExprs().begin(), getSourceExprs().end()); } + helper_expr_range source_exprs() { return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end()); } + helper_expr_const_range destination_exprs() const { return helper_expr_const_range(getDestinationExprs().begin(), getDestinationExprs().end()); } + helper_expr_range destination_exprs() { return helper_expr_range(getDestinationExprs().begin(), getDestinationExprs().end()); } + helper_expr_const_range assignment_ops() const { return helper_expr_const_range(getAssignmentOps().begin(), getAssignmentOps().end()); } + helper_expr_range assignment_ops() { return helper_expr_range(getAssignmentOps().begin(), getAssignmentOps().end()); @@ -2745,19 +3010,18 @@ public: /// \endcode /// In this example directive '#pragma omp flush' has implicit clause 'flush' /// with the variables 'a' and 'b'. -/// class OMPFlushClause final : public OMPVarListClause<OMPFlushClause>, private llvm::TrailingObjects<OMPFlushClause, Expr *> { - friend TrailingObjects; friend OMPVarListClause; + friend TrailingObjects; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPFlushClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc, @@ -2766,7 +3030,6 @@ class OMPFlushClause final /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPFlushClause(unsigned N) : OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(), SourceLocation(), SourceLocation(), @@ -2780,15 +3043,14 @@ public: /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. - /// static OMPFlushClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. - /// static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N); child_range children() { @@ -2809,41 +3071,41 @@ public: /// \endcode /// In this example directive '#pragma omp task' with clause 'depend' with the /// variables 'a' and 'b' with dependency 'in'. -/// class OMPDependClause final : public OMPVarListClause<OMPDependClause>, private llvm::TrailingObjects<OMPDependClause, Expr *> { - friend TrailingObjects; - friend OMPVarListClause; friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + /// \brief Dependency type (one of in, out, inout). - OpenMPDependClauseKind DepKind; + OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; + /// \brief Dependency type location. SourceLocation DepLoc; + /// \brief Colon location. SourceLocation ColonLoc; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. - /// OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc, - EndLoc, N), - DepKind(OMPC_DEPEND_unknown) {} + EndLoc, N) {} /// \brief Build an empty clause. /// /// \param N Number of variables. - /// explicit OMPDependClause(unsigned N) : OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(), SourceLocation(), SourceLocation(), - N), - DepKind(OMPC_DEPEND_unknown) {} + N) {} + /// \brief Set dependency kind. void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; } @@ -2868,25 +3130,29 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL); + /// \brief 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. OpenMPDependClauseKind getDependencyKind() const { return DepKind; } + /// \brief Get dependency type location. SourceLocation getDependencyLoc() const { return DepLoc; } + /// \brief Get colon location. SourceLocation getColonLoc() const { return ColonLoc; } /// Set the loop counter value for the depend clauses with 'sink|source' kind /// of dependency. Required for codegen. void setCounterValue(Expr *V); + /// Get the loop counter value. Expr *getCounterValue(); + /// Get the loop counter value. const Expr *getCounterValue() const; @@ -2908,17 +3174,18 @@ public: /// \endcode /// In this example directive '#pragma omp target' has clause 'device' /// with single expression 'a'. -/// -class OMPDeviceClause : public OMPClause { +class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Device number. - Stmt *Device; + Stmt *Device = nullptr; + /// \brief Set the device number. /// /// \param E Device number. - /// void setDevice(Expr *E) { Device = E; } public: @@ -2928,31 +3195,35 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// - OMPDeviceClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_device, StartLoc, EndLoc), LParenLoc(LParenLoc), - Device(E) {} + OMPDeviceClause(Expr *E, Stmt *HelperE, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this), + LParenLoc(LParenLoc), Device(E) { + setPreInitStmt(HelperE); + } /// \brief Build an empty clause. - /// OMPDeviceClause() - : OMPClause(OMPC_device, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Device(nullptr) {} + : OMPClause(OMPC_device, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this) {} + /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } + /// \brief Return device number. Expr *getDevice() { return cast<Expr>(Device); } + /// \brief Return device number. Expr *getDevice() const { return cast<Expr>(Device); } + child_range children() { return child_range(&Device, &Device + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_device; } - - child_range children() { return child_range(&Device, &Device + 1); } }; /// \brief This represents 'threads' clause in the '#pragma omp ...' directive. @@ -2961,29 +3232,26 @@ public: /// #pragma omp ordered threads /// \endcode /// In this example directive '#pragma omp ordered' has simple 'threads' clause. -/// class OMPThreadsClause : public OMPClause { public: /// \brief 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. - /// OMPThreadsClause() : OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_threads; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_threads; + } }; /// \brief This represents 'simd' clause in the '#pragma omp ...' directive. @@ -2992,28 +3260,25 @@ public: /// #pragma omp ordered simd /// \endcode /// In this example directive '#pragma omp ordered' has simple 'simd' clause. -/// class OMPSIMDClause : public OMPClause { public: /// \brief 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. - /// OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_simd; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_simd; + } }; /// \brief Struct that defines common infrastructure to handle mappable @@ -3029,13 +3294,14 @@ public: class MappableComponent { // \brief Expression associated with the component. Expr *AssociatedExpression = nullptr; + // \brief Declaration associated with the declaration. If the component does // not have a declaration (e.g. array subscripts or section), this is set to // nullptr. ValueDecl *AssociatedDeclaration = nullptr; public: - explicit MappableComponent() {} + explicit MappableComponent() = default; explicit MappableComponent(Expr *AssociatedExpression, ValueDecl *AssociatedDeclaration) : AssociatedExpression(AssociatedExpression), @@ -3045,6 +3311,7 @@ public: : nullptr) {} Expr *getAssociatedExpression() const { return AssociatedExpression; } + ValueDecl *getAssociatedDeclaration() const { return AssociatedDeclaration; } @@ -3052,14 +3319,14 @@ public: // \brief List of components of an expression. This first one is the whole // expression and the last one is the base expression. - typedef SmallVector<MappableComponent, 8> MappableExprComponentList; - typedef ArrayRef<MappableComponent> MappableExprComponentListRef; + using MappableExprComponentList = SmallVector<MappableComponent, 8>; + using MappableExprComponentListRef = ArrayRef<MappableComponent>; // \brief List of all component lists associated to the same base declaration. // E.g. if both 'S.a' and 'S.b' are a mappable expressions, each will have // their component list but the same base declaration 'S'. - typedef SmallVector<MappableExprComponentList, 8> MappableExprComponentLists; - typedef ArrayRef<MappableExprComponentList> MappableExprComponentListsRef; + using MappableExprComponentLists = SmallVector<MappableExprComponentList, 8>; + using MappableExprComponentListsRef = ArrayRef<MappableExprComponentList>; protected: // \brief Return the total number of elements in a list of component lists. @@ -3091,6 +3358,28 @@ class OMPMappableExprListClause : public OMPVarListClause<T>, unsigned NumComponents; protected: + /// \brief Build a clause for \a NumUniqueDeclarations declarations, \a + /// NumComponentLists total component lists, and \a NumComponents total + /// components. + /// + /// \param K Kind of the clause. + /// \param StartLoc Starting location of the clause (the clause keyword). + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param NumVars Number of expressions listed in the clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause - one + /// list for each expression in the clause. + /// \param NumComponents Total number of expression components in the clause. + OMPMappableExprListClause(OpenMPClauseKind K, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPVarListClause<T>(K, StartLoc, LParenLoc, EndLoc, NumVars), + NumUniqueDeclarations(NumUniqueDeclarations), + NumComponentLists(NumComponentLists), NumComponents(NumComponents) {} + /// \brief Get the unique declarations that are in the trailing objects of the /// class. MutableArrayRef<ValueDecl *> getUniqueDeclsRef() { @@ -3270,34 +3559,13 @@ protected: } } - /// \brief Build a clause for \a NumUniqueDeclarations declarations, \a - /// NumComponentLists total component lists, and \a NumComponents total - /// components. - /// - /// \param K Kind of the clause. - /// \param StartLoc Starting location of the clause (the clause keyword). - /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. - /// \param NumVars Number of expressions listed in the clause. - /// \param NumUniqueDeclarations Number of unique base declarations in this - /// clause. - /// \param NumComponentLists Number of component lists in this clause - one - /// list for each expression in the clause. - /// \param NumComponents Total number of expression components in the clause. - /// - OMPMappableExprListClause(OpenMPClauseKind K, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - unsigned NumVars, unsigned NumUniqueDeclarations, - unsigned NumComponentLists, unsigned NumComponents) - : OMPVarListClause<T>(K, StartLoc, LParenLoc, EndLoc, NumVars), - NumUniqueDeclarations(NumUniqueDeclarations), - NumComponentLists(NumComponentLists), NumComponents(NumComponents) {} - public: /// \brief Return the number of unique base declarations in this clause. unsigned getUniqueDeclarationsNum() const { return NumUniqueDeclarations; } + /// \brief Return the number of lists derived from the clause expressions. unsigned getTotalComponentListNum() const { return NumComponentLists; } + /// \brief Return the total number of components in all lists derived from the /// clause. unsigned getTotalComponentsNum() const { return NumComponents; } @@ -3317,11 +3585,11 @@ public: ArrayRef<unsigned>::iterator NumListsCur; // Remaining lists for the current declaration. - unsigned RemainingLists; + unsigned RemainingLists = 0; // The cumulative size of the previous list, or zero if there is no previous // list. - unsigned PrevListSize; + unsigned PrevListSize = 0; // The cumulative sizes of the current list - it will delimit the remaining // range of interest. @@ -3340,7 +3608,6 @@ public: : const_component_lists_iterator::iterator_adaptor_base( Components.begin()), DeclCur(UniqueDecls.begin()), NumListsCur(DeclsListNum.begin()), - RemainingLists(0u), PrevListSize(0u), ListSizeCur(CumulativeListSizes.begin()), ListSizeEnd(CumulativeListSizes.end()), End(Components.end()) { assert(UniqueDecls.size() == DeclsListNum.size() && @@ -3357,7 +3624,6 @@ public: MappableExprComponentListRef Components) : const_component_lists_iterator(UniqueDecls, DeclsListNum, CumulativeListSizes, Components) { - // Look for the desired declaration. While we are looking for it, we // update the state so that we know the component where a given list // starts. @@ -3437,8 +3703,8 @@ public: } }; - typedef llvm::iterator_range<const_component_lists_iterator> - const_component_lists_range; + using const_component_lists_range = + llvm::iterator_range<const_component_lists_iterator>; /// \brief Iterators for all component lists. const_component_lists_iterator component_lists_begin() const { @@ -3473,32 +3739,36 @@ public: /// Iterators to access all the declarations, number of lists, list sizes, and /// components. - typedef ArrayRef<ValueDecl *>::iterator const_all_decls_iterator; - typedef llvm::iterator_range<const_all_decls_iterator> const_all_decls_range; + using const_all_decls_iterator = ArrayRef<ValueDecl *>::iterator; + using const_all_decls_range = llvm::iterator_range<const_all_decls_iterator>; + const_all_decls_range all_decls() const { auto A = getUniqueDeclsRef(); return const_all_decls_range(A.begin(), A.end()); } - typedef ArrayRef<unsigned>::iterator const_all_num_lists_iterator; - typedef llvm::iterator_range<const_all_num_lists_iterator> - const_all_num_lists_range; + using const_all_num_lists_iterator = ArrayRef<unsigned>::iterator; + using const_all_num_lists_range = + llvm::iterator_range<const_all_num_lists_iterator>; + const_all_num_lists_range all_num_lists() const { auto A = getDeclNumListsRef(); return const_all_num_lists_range(A.begin(), A.end()); } - typedef ArrayRef<unsigned>::iterator const_all_lists_sizes_iterator; - typedef llvm::iterator_range<const_all_lists_sizes_iterator> - const_all_lists_sizes_range; + using const_all_lists_sizes_iterator = ArrayRef<unsigned>::iterator; + using const_all_lists_sizes_range = + llvm::iterator_range<const_all_lists_sizes_iterator>; + const_all_lists_sizes_range all_lists_sizes() const { auto A = getComponentListSizesRef(); return const_all_lists_sizes_range(A.begin(), A.end()); } - typedef ArrayRef<MappableComponent>::iterator const_all_components_iterator; - typedef llvm::iterator_range<const_all_components_iterator> - const_all_components_range; + using const_all_components_iterator = ArrayRef<MappableComponent>::iterator; + using const_all_components_range = + llvm::iterator_range<const_all_components_iterator>; + const_all_components_range all_components() const { auto A = getComponentsRef(); return const_all_components_range(A.begin(), A.end()); @@ -3513,15 +3783,14 @@ public: /// \endcode /// In this example directive '#pragma omp target' has clause 'map' /// with the variables 'a' and 'b'. -/// class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, private llvm::TrailingObjects< OMPMapClause, Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent> { - friend TrailingObjects; - friend OMPVarListClause; - friend OMPMappableExprListClause; friend class OMPClauseReader; + friend OMPMappableExprListClause; + friend OMPVarListClause; + friend TrailingObjects; /// Define the sizes of each trailing object array except the last one. This /// is required for TrailingObjects to work properly. @@ -3536,37 +3805,20 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, } /// \brief Map type modifier for the 'map' clause. - OpenMPMapClauseKind MapTypeModifier; + OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; + /// \brief Map type for the 'map' clause. - OpenMPMapClauseKind MapType; + OpenMPMapClauseKind MapType = OMPC_MAP_unknown; + /// \brief Is this an implicit map type or not. - bool MapTypeIsImplicit; + bool MapTypeIsImplicit = false; + /// \brief Location of the map type. SourceLocation MapLoc; + /// \brief Colon location. SourceLocation ColonLoc; - /// \brief 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. - /// - /// \param T Type for the clause. - /// - void setMapType(OpenMPMapClauseKind T) { MapType = T; } - - /// \brief Set type location. - /// - /// \param TLoc Type location. - /// - void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; } - - /// \brief Set colon location. - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - /// \brief Build a clause for \a NumVars listed expressions, \a /// NumUniqueDeclarations declarations, \a NumComponentLists total component /// lists, and \a NumComponents total expression components. @@ -3582,7 +3834,6 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, bool MapTypeIsImplicit, SourceLocation MapLoc, SourceLocation StartLoc, @@ -3602,14 +3853,29 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPMapClause(unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, unsigned NumComponents) : OMPMappableExprListClause( OMPC_map, SourceLocation(), SourceLocation(), SourceLocation(), - NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents), - MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), - MapTypeIsImplicit(false), MapLoc() {} + NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} + + /// \brief 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. + /// + /// \param T Type for the clause. + void setMapType(OpenMPMapClauseKind T) { MapType = T; } + + /// \brief Set type location. + /// + /// \param TLoc Type location. + void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; } + + /// \brief Set colon location. + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } public: /// \brief Creates clause with a list of variables \a VL. @@ -3624,7 +3890,6 @@ public: /// \param Type Map type. /// \param TypeIsImplicit Map type is inferred implicitly. /// \param TypeLoc Location of the map type. - /// static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> Vars, @@ -3633,6 +3898,7 @@ public: OpenMPMapClauseKind TypeModifier, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc); + /// \brief Creates an empty clause with the place for for \a NumVars original /// expressions, \a NumUniqueDeclarations declarations, \NumComponentLists /// lists, and \a NumComponents expression components. @@ -3644,7 +3910,6 @@ public: /// \param NumComponentLists Number of unique base declarations in this /// clause. /// \param NumComponents Total number of expression components in the clause. - /// static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, @@ -3671,15 +3936,15 @@ public: /// \brief Get colon location. SourceLocation getColonLoc() const { return ColonLoc; } - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_map; - } - child_range children() { return child_range( reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_map; + } }; /// \brief This represents 'num_teams' clause in the '#pragma omp ...' @@ -3690,17 +3955,18 @@ public: /// \endcode /// In this example directive '#pragma omp teams' has clause 'num_teams' /// with single expression 'n'. -/// class OMPNumTeamsClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief NumTeams number. - Stmt *NumTeams; + Stmt *NumTeams = nullptr; + /// \brief Set the NumTeams number. /// /// \param E NumTeams number. - /// void setNumTeams(Expr *E) { NumTeams = E; } public: @@ -3713,7 +3979,6 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPNumTeamsClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) @@ -3723,25 +3988,27 @@ public: } /// \brief Build an empty clause. - /// OMPNumTeamsClause() : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this), LParenLoc(SourceLocation()), - NumTeams(nullptr) {} + OMPClauseWithPreInit(this) {} + /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } + /// \brief Return NumTeams number. Expr *getNumTeams() { return cast<Expr>(NumTeams); } + /// \brief Return NumTeams number. Expr *getNumTeams() const { return cast<Expr>(NumTeams); } + child_range children() { return child_range(&NumTeams, &NumTeams + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_num_teams; } - - child_range children() { return child_range(&NumTeams, &NumTeams + 1); } }; /// \brief This represents 'thread_limit' clause in the '#pragma omp ...' @@ -3752,17 +4019,18 @@ public: /// \endcode /// In this example directive '#pragma omp teams' has clause 'thread_limit' /// with single expression 'n'. -/// class OMPThreadLimitClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief ThreadLimit number. - Stmt *ThreadLimit; + Stmt *ThreadLimit = nullptr; + /// \brief Set the ThreadLimit number. /// /// \param E ThreadLimit number. - /// void setThreadLimit(Expr *E) { ThreadLimit = E; } public: @@ -3775,7 +4043,6 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPThreadLimitClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -3786,25 +4053,27 @@ public: } /// \brief Build an empty clause. - /// OMPThreadLimitClause() : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this), LParenLoc(SourceLocation()), - ThreadLimit(nullptr) {} + OMPClauseWithPreInit(this) {} + /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } + /// \brief Return ThreadLimit number. Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); } + /// \brief Return ThreadLimit number. Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); } + child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_thread_limit; } - - child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); } }; /// \brief This represents 'priority' clause in the '#pragma omp ...' @@ -3815,17 +4084,18 @@ public: /// \endcode /// In this example directive '#pragma omp teams' has clause 'priority' with /// single expression 'n'. -/// class OMPPriorityClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Priority number. - Stmt *Priority; + Stmt *Priority = nullptr; + /// \brief Set the Priority number. /// /// \param E Priority number. - /// void setPriority(Expr *E) { Priority = E; } public: @@ -3835,31 +4105,32 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc), Priority(E) {} /// \brief Build an empty clause. - /// OMPPriorityClause() - : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Priority(nullptr) {} + : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()) {} + /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } + /// \brief Return Priority number. Expr *getPriority() { return cast<Expr>(Priority); } + /// \brief Return Priority number. Expr *getPriority() const { return cast<Expr>(Priority); } + child_range children() { return child_range(&Priority, &Priority + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_priority; } - - child_range children() { return child_range(&Priority, &Priority + 1); } }; /// \brief This represents 'grainsize' clause in the '#pragma omp ...' @@ -3870,13 +4141,14 @@ public: /// \endcode /// In this example directive '#pragma omp taskloop' has clause 'grainsize' /// with single expression '4'. -/// class OMPGrainsizeClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Safe iteration space distance. - Stmt *Grainsize; + Stmt *Grainsize = nullptr; /// \brief Set safelen. void setGrainsize(Expr *Size) { Grainsize = Size; } @@ -3887,31 +4159,29 @@ public: /// \param Size Expression associated with this clause. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc), Grainsize(Size) {} /// \brief Build an empty clause. - /// explicit OMPGrainsizeClause() - : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Grainsize(nullptr) {} + : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief Return safe iteration space distance. Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); } + child_range children() { return child_range(&Grainsize, &Grainsize + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_grainsize; } - - child_range children() { return child_range(&Grainsize, &Grainsize + 1); } }; /// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive. @@ -3920,29 +4190,26 @@ public: /// #pragma omp taskloop nogroup /// \endcode /// In this example directive '#pragma omp taskloop' has 'nogroup' clause. -/// class OMPNogroupClause : public OMPClause { public: /// \brief 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. - /// OMPNogroupClause() : OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {} - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_nogroup; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_nogroup; + } }; /// \brief This represents 'num_tasks' clause in the '#pragma omp ...' @@ -3953,13 +4220,14 @@ public: /// \endcode /// In this example directive '#pragma omp taskloop' has clause 'num_tasks' /// with single expression '4'. -/// class OMPNumTasksClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Safe iteration space distance. - Stmt *NumTasks; + Stmt *NumTasks = nullptr; /// \brief Set safelen. void setNumTasks(Expr *Size) { NumTasks = Size; } @@ -3970,31 +4238,29 @@ public: /// \param Size Expression associated with this clause. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// OMPNumTasksClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc), NumTasks(Size) {} /// \brief Build an empty clause. - /// explicit OMPNumTasksClause() - : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), NumTasks(nullptr) {} + : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief Return safe iteration space distance. Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); } + child_range children() { return child_range(&NumTasks, &NumTasks + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_num_tasks; } - - child_range children() { return child_range(&NumTasks, &NumTasks + 1); } }; /// \brief This represents 'hint' clause in the '#pragma omp ...' directive. @@ -4004,16 +4270,16 @@ public: /// \endcode /// In this example directive '#pragma omp critical' has name 'name' and clause /// 'hint' with argument '6'. -/// class OMPHintClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Hint expression of the 'hint' clause. - Stmt *Hint; + Stmt *Hint = nullptr; /// \brief Set hint expression. - /// void setHint(Expr *H) { Hint = H; } public: @@ -4023,31 +4289,28 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc), Hint(Hint) {} /// \brief Build an empty clause. - /// - OMPHintClause() - : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Hint(nullptr) {} + OMPHintClause() : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()) {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } /// \brief Returns number of threads. Expr *getHint() const { return cast_or_null<Expr>(Hint); } + child_range children() { return child_range(&Hint, &Hint + 1); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_hint; } - - child_range children() { return child_range(&Hint, &Hint + 1); } }; /// \brief This represents 'dist_schedule' clause in the '#pragma omp ...' @@ -4058,44 +4321,47 @@ public: /// \endcode /// In this example directive '#pragma omp distribute' has 'dist_schedule' /// clause with arguments 'static' and '3'. -/// class OMPDistScheduleClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief A kind of the 'schedule' clause. - OpenMPDistScheduleClauseKind Kind; + OpenMPDistScheduleClauseKind Kind = OMPC_DIST_SCHEDULE_unknown; + /// \brief Start location of the schedule kind in source code. SourceLocation KindLoc; + /// \brief Location of ',' (if any). SourceLocation CommaLoc; + /// \brief Chunk size. - Expr *ChunkSize; + Expr *ChunkSize = nullptr; /// \brief Set schedule kind. /// /// \param K Schedule kind. - /// void setDistScheduleKind(OpenMPDistScheduleClauseKind K) { Kind = K; } + /// \brief Sets the location of '('. /// /// \param Loc Location of '('. - /// void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Set schedule kind start location. /// /// \param KLoc Schedule kind location. - /// void setDistScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } + /// \brief Set location of ','. /// /// \param Loc Location of ','. - /// void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; } + /// \brief Set chunk size. /// /// \param E Chunk size. - /// void setChunkSize(Expr *E) { ChunkSize = E; } public: @@ -4110,7 +4376,6 @@ public: /// \param Kind DistSchedule kind. /// \param ChunkSize Chunk size. /// \param HelperChunkSize Helper chunk size for combined directives. - /// OMPDistScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KLoc, SourceLocation CommaLoc, SourceLocation EndLoc, @@ -4123,39 +4388,36 @@ public: } /// \brief Build an empty clause. - /// explicit OMPDistScheduleClause() : OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()), - OMPClauseWithPreInit(this), Kind(OMPC_DIST_SCHEDULE_unknown), - ChunkSize(nullptr) {} + OMPClauseWithPreInit(this) {} /// \brief Get kind of the clause. - /// OpenMPDistScheduleClauseKind getDistScheduleKind() const { return Kind; } + /// \brief Get location of '('. - /// SourceLocation getLParenLoc() { return LParenLoc; } + /// \brief Get kind location. - /// SourceLocation getDistScheduleKindLoc() { return KindLoc; } + /// \brief Get location of ','. - /// SourceLocation getCommaLoc() { return CommaLoc; } + /// \brief Get chunk size. - /// Expr *getChunkSize() { return ChunkSize; } + /// \brief Get chunk size. - /// const Expr *getChunkSize() const { return ChunkSize; } - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_dist_schedule; - } - child_range children() { return child_range(reinterpret_cast<Stmt **>(&ChunkSize), reinterpret_cast<Stmt **>(&ChunkSize) + 1); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_dist_schedule; + } }; /// \brief This represents 'defaultmap' clause in the '#pragma omp ...' directive. @@ -4165,46 +4427,49 @@ public: /// \endcode /// In this example directive '#pragma omp target' has 'defaultmap' clause of kind /// 'scalar' with modifier 'tofrom'. -/// class OMPDefaultmapClause : public OMPClause { friend class OMPClauseReader; + /// \brief Location of '('. SourceLocation LParenLoc; + /// \brief Modifiers for 'defaultmap' clause. - OpenMPDefaultmapClauseModifier Modifier; + OpenMPDefaultmapClauseModifier Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; + /// \brief Locations of modifiers. SourceLocation ModifierLoc; + /// \brief A kind of the 'defaultmap' clause. - OpenMPDefaultmapClauseKind Kind; + OpenMPDefaultmapClauseKind Kind = OMPC_DEFAULTMAP_unknown; + /// \brief Start location of the defaultmap kind in source code. SourceLocation KindLoc; /// \brief Set defaultmap kind. /// /// \param K Defaultmap kind. - /// void setDefaultmapKind(OpenMPDefaultmapClauseKind K) { Kind = K; } + /// \brief Set the defaultmap modifier. /// /// \param M Defaultmap modifier. - /// void setDefaultmapModifier(OpenMPDefaultmapClauseModifier M) { Modifier = M; } + /// \brief Set location of the defaultmap modifier. - /// void setDefaultmapModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } + /// \brief Sets the location of '('. /// /// \param Loc Location of '('. - /// void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Set defaultmap kind start location. /// /// \param KLoc Defaultmap kind location. - /// void setDefaultmapKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } public: @@ -4217,7 +4482,6 @@ public: /// \param Kind Defaultmap kind. /// \param M The modifier applied to 'defaultmap' clause. /// \param MLoc Location of the modifier - /// OMPDefaultmapClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KLoc, SourceLocation EndLoc, OpenMPDefaultmapClauseKind Kind, @@ -4226,39 +4490,35 @@ public: Modifier(M), ModifierLoc(MLoc), Kind(Kind), KindLoc(KLoc) {} /// \brief Build an empty clause. - /// explicit OMPDefaultmapClause() - : OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()), - Modifier(OMPC_DEFAULTMAP_MODIFIER_unknown), - Kind(OMPC_DEFAULTMAP_unknown) {} + : OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()) {} /// \brief Get kind of the clause. - /// OpenMPDefaultmapClauseKind getDefaultmapKind() const { return Kind; } + /// \brief Get the modifier of the clause. - /// OpenMPDefaultmapClauseModifier getDefaultmapModifier() const { return Modifier; } + /// \brief Get location of '('. - /// SourceLocation getLParenLoc() { return LParenLoc; } + /// \brief Get kind location. - /// SourceLocation getDefaultmapKindLoc() { return KindLoc; } + /// \brief Get the modifier location. - /// SourceLocation getDefaultmapModifierLoc() const { return ModifierLoc; } - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_defaultmap; - } - child_range children() { return child_range(child_iterator(), child_iterator()); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_defaultmap; + } }; /// \brief This represents clause 'to' in the '#pragma omp ...' @@ -4269,27 +4529,14 @@ public: /// \endcode /// In this example directive '#pragma omp target update' has clause 'to' /// with the variables 'a' and 'b'. -/// class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, private llvm::TrailingObjects< OMPToClause, Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent> { - friend TrailingObjects; - friend OMPVarListClause; - friend OMPMappableExprListClause; friend class OMPClauseReader; - - /// Define the sizes of each trailing object array except the last one. This - /// is required for TrailingObjects to work properly. - size_t numTrailingObjects(OverloadToken<Expr *>) const { - return varlist_size(); - } - size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { - return getUniqueDeclarationsNum(); - } - size_t numTrailingObjects(OverloadToken<unsigned>) const { - return getUniqueDeclarationsNum() + getTotalComponentListNum(); - } + friend OMPMappableExprListClause; + friend OMPVarListClause; + friend TrailingObjects; /// \brief Build clause with number of variables \a NumVars. /// @@ -4300,7 +4547,6 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPToClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned NumVars, unsigned NumUniqueDeclarations, @@ -4316,13 +4562,24 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPToClause(unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, unsigned NumComponents) : OMPMappableExprListClause( OMPC_to, SourceLocation(), SourceLocation(), SourceLocation(), NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken<unsigned>) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + public: /// \brief Creates clause with a list of variables \a Vars. /// @@ -4332,7 +4589,6 @@ public: /// \param Vars The original expression used in the clause. /// \param Declarations Declarations used in the clause. /// \param ComponentLists Component lists used in the clause. - /// static OMPToClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> Vars, @@ -4348,20 +4604,19 @@ public: /// \param NumComponentLists Number of unique base declarations in this /// clause. /// \param NumComponents Total number of expression components in the clause. - /// static OMPToClause *CreateEmpty(const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, unsigned NumComponents); - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_to; - } - child_range children() { return child_range(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_to; + } }; /// \brief This represents clause 'from' in the '#pragma omp ...' @@ -4372,28 +4627,15 @@ public: /// \endcode /// In this example directive '#pragma omp target update' has clause 'from' /// with the variables 'a' and 'b'. -/// class OMPFromClause final : public OMPMappableExprListClause<OMPFromClause>, private llvm::TrailingObjects< OMPFromClause, Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent> { - friend TrailingObjects; - friend OMPVarListClause; - friend OMPMappableExprListClause; friend class OMPClauseReader; - - /// Define the sizes of each trailing object array except the last one. This - /// is required for TrailingObjects to work properly. - size_t numTrailingObjects(OverloadToken<Expr *>) const { - return varlist_size(); - } - size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { - return getUniqueDeclarationsNum(); - } - size_t numTrailingObjects(OverloadToken<unsigned>) const { - return getUniqueDeclarationsNum() + getTotalComponentListNum(); - } + friend OMPMappableExprListClause; + friend OMPVarListClause; + friend TrailingObjects; /// \brief Build clause with number of variables \a NumVars. /// @@ -4404,7 +4646,6 @@ class OMPFromClause final /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPFromClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned NumVars, unsigned NumUniqueDeclarations, @@ -4420,13 +4661,24 @@ class OMPFromClause final /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPFromClause(unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, unsigned NumComponents) : OMPMappableExprListClause( OMPC_from, SourceLocation(), SourceLocation(), SourceLocation(), NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken<unsigned>) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + public: /// \brief Creates clause with a list of variables \a Vars. /// @@ -4436,7 +4688,6 @@ public: /// \param Vars The original expression used in the clause. /// \param Declarations Declarations used in the clause. /// \param ComponentLists Component lists used in the clause. - /// static OMPFromClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> Vars, @@ -4452,20 +4703,19 @@ public: /// \param NumComponentLists Number of unique base declarations in this /// clause. /// \param NumComponents Total number of expression components in the clause. - /// static OMPFromClause *CreateEmpty(const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, unsigned NumComponents); - static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_from; - } - child_range children() { return child_range(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_from; + } }; /// This represents clause 'use_device_ptr' in the '#pragma omp ...' @@ -4476,28 +4726,15 @@ public: /// \endcode /// In this example directive '#pragma omp target data' has clause /// 'use_device_ptr' with the variables 'a' and 'b'. -/// class OMPUseDevicePtrClause final : public OMPMappableExprListClause<OMPUseDevicePtrClause>, private llvm::TrailingObjects< OMPUseDevicePtrClause, Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent> { - friend TrailingObjects; - friend OMPVarListClause; - friend OMPMappableExprListClause; friend class OMPClauseReader; - - /// Define the sizes of each trailing object array except the last one. This - /// is required for TrailingObjects to work properly. - size_t numTrailingObjects(OverloadToken<Expr *>) const { - return 3 * varlist_size(); - } - size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { - return getUniqueDeclarationsNum(); - } - size_t numTrailingObjects(OverloadToken<unsigned>) const { - return getUniqueDeclarationsNum() + getTotalComponentListNum(); - } + friend OMPMappableExprListClause; + friend OMPVarListClause; + friend TrailingObjects; /// Build clause with number of variables \a NumVars. /// @@ -4508,7 +4745,6 @@ class OMPUseDevicePtrClause final /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPUseDevicePtrClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned NumVars, @@ -4526,7 +4762,6 @@ class OMPUseDevicePtrClause final /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPUseDevicePtrClause(unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, @@ -4536,6 +4771,18 @@ class OMPUseDevicePtrClause final NumUniqueDeclarations, NumComponentLists, NumComponents) {} + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return 3 * varlist_size(); + } + size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken<unsigned>) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + /// Sets the list of references to private copies with initializers for new /// private variables. /// \param VL List of references. @@ -4575,7 +4822,6 @@ public: /// \param Inits Expressions referring to private copy initializers. /// \param Declarations Declarations used in the clause. /// \param ComponentLists Component lists used in the clause. - /// static OMPUseDevicePtrClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> Vars, @@ -4592,36 +4838,37 @@ public: /// \param NumComponentLists Number of unique base declarations in this /// clause. /// \param NumComponents Total number of expression components in the clause. - /// static OMPUseDevicePtrClause *CreateEmpty(const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, unsigned NumComponents); - typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; - typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; - typedef llvm::iterator_range<private_copies_iterator> private_copies_range; - typedef llvm::iterator_range<private_copies_const_iterator> - private_copies_const_range; + using private_copies_iterator = MutableArrayRef<Expr *>::iterator; + using private_copies_const_iterator = ArrayRef<const Expr *>::iterator; + using private_copies_range = llvm::iterator_range<private_copies_iterator>; + using private_copies_const_range = + llvm::iterator_range<private_copies_const_iterator>; private_copies_range private_copies() { return private_copies_range(getPrivateCopies().begin(), getPrivateCopies().end()); } + private_copies_const_range private_copies() const { return private_copies_const_range(getPrivateCopies().begin(), getPrivateCopies().end()); } - typedef MutableArrayRef<Expr *>::iterator inits_iterator; - typedef ArrayRef<const Expr *>::iterator inits_const_iterator; - typedef llvm::iterator_range<inits_iterator> inits_range; - typedef llvm::iterator_range<inits_const_iterator> inits_const_range; + using inits_iterator = MutableArrayRef<Expr *>::iterator; + using inits_const_iterator = ArrayRef<const Expr *>::iterator; + using inits_range = llvm::iterator_range<inits_iterator>; + using inits_const_range = llvm::iterator_range<inits_const_iterator>; inits_range inits() { return inits_range(getInits().begin(), getInits().end()); } + inits_const_range inits() const { return inits_const_range(getInits().begin(), getInits().end()); } @@ -4644,28 +4891,16 @@ public: /// \endcode /// In this example directive '#pragma omp target' has clause /// 'is_device_ptr' with the variables 'a' and 'b'. -/// class OMPIsDevicePtrClause final : public OMPMappableExprListClause<OMPIsDevicePtrClause>, private llvm::TrailingObjects< OMPIsDevicePtrClause, Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent> { - friend TrailingObjects; - friend OMPVarListClause; - friend OMPMappableExprListClause; friend class OMPClauseReader; + friend OMPMappableExprListClause; + friend OMPVarListClause; + friend TrailingObjects; - /// Define the sizes of each trailing object array except the last one. This - /// is required for TrailingObjects to work properly. - size_t numTrailingObjects(OverloadToken<Expr *>) const { - return varlist_size(); - } - size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { - return getUniqueDeclarationsNum(); - } - size_t numTrailingObjects(OverloadToken<unsigned>) const { - return getUniqueDeclarationsNum() + getTotalComponentListNum(); - } /// Build clause with number of variables \a NumVars. /// /// \param StartLoc Starting location of the clause. @@ -4675,7 +4910,6 @@ class OMPIsDevicePtrClause final /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPIsDevicePtrClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned NumVars, @@ -4693,7 +4927,6 @@ class OMPIsDevicePtrClause final /// clause. /// \param NumComponentLists Number of component lists in this clause. /// \param NumComponents Total number of expression components in the clause. - /// explicit OMPIsDevicePtrClause(unsigned NumVars, unsigned NumUniqueDeclarations, unsigned NumComponentLists, @@ -4703,6 +4936,18 @@ class OMPIsDevicePtrClause final NumUniqueDeclarations, NumComponentLists, NumComponents) {} + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken<unsigned>) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + public: /// Creates clause with a list of variables \a Vars. /// @@ -4712,7 +4957,6 @@ public: /// \param Vars The original expression used in the clause. /// \param Declarations Declarations used in the clause. /// \param ComponentLists Component lists used in the clause. - /// static OMPIsDevicePtrClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> Vars, @@ -4728,7 +4972,6 @@ public: /// \param NumComponentLists Number of unique base declarations in this /// clause. /// \param NumComponents Total number of expression components in the clause. - /// static OMPIsDevicePtrClause *CreateEmpty(const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, @@ -4744,6 +4987,7 @@ public: return T->getClauseKind() == OMPC_is_device_ptr; } }; -} // end namespace clang + +} // namespace clang #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def index 2d48a7df47b7..b13cf3b63276 100644 --- a/include/clang/AST/OperationKinds.def +++ b/include/clang/AST/OperationKinds.def @@ -327,12 +327,13 @@ CAST_OPERATION(ZeroToOCLQueue) // Convert a pointer to a different address space. CAST_OPERATION(AddressSpaceConversion) -// Convert an integer initializer to an OpenCL sampler.
+// Convert an integer initializer to an OpenCL sampler. CAST_OPERATION(IntToOCLSampler) //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. -// Note that additions to this should also update the StmtVisitor class. +// Note that additions to this should also update the StmtVisitor class and +// BinaryOperator::getOverloadedOperator. // [C++ 5.5] Pointer-to-member operators. BINARY_OPERATION(PtrMemD, ".*") @@ -347,6 +348,8 @@ BINARY_OPERATION(Sub, "-") // [C99 6.5.7] Bitwise shift operators. BINARY_OPERATION(Shl, "<<") BINARY_OPERATION(Shr, ">>") +// C++20 [expr.spaceship] Three-way comparison operator. +BINARY_OPERATION(Cmp, "<=>") // [C99 6.5.8] Relational operators. BINARY_OPERATION(LT, "<") BINARY_OPERATION(GT, ">") @@ -382,7 +385,8 @@ BINARY_OPERATION(Comma, ",") //===- Unary Operations ---------------------------------------------------===// -// Note that additions to this should also update the StmtVisitor class. +// Note that additions to this should also update the StmtVisitor class and +// UnaryOperator::getOverloadedOperator. // [C99 6.5.2.4] Postfix increment and decrement UNARY_OPERATION(PostInc, "++") diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 00f060fe9e3d..e3832689d64b 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -23,8 +23,6 @@ enum CastKind { #include "clang/AST/OperationKinds.def" }; -static const CastKind CK_Invalid = static_cast<CastKind>(-1); - enum BinaryOperatorKind { #define BINARY_OPERATION(Name, Spelling) BO_##Name, #include "clang/AST/OperationKinds.def" diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 274df220e160..e831b903cbae 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -30,8 +30,8 @@ public: virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0; }; -/// \brief Describes how types, statements, expressions, and -/// declarations should be printed. +/// Describes how types, statements, expressions, and declarations should be +/// printed. /// /// This type is intended to be small and suitable for passing by value. /// It is very frequently copied. @@ -50,22 +50,24 @@ struct PrintingPolicy { UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), - IncludeNewlines(true), MSVCFormatting(false) { } - - /// \brief Adjust this printing policy for cases where it's known that - /// we're printing C++ code (for instance, if AST dumping reaches a - /// C++-only construct). This should not be used if a real LangOptions - /// object is available. + IncludeNewlines(true), MSVCFormatting(false), + ConstantsAsWritten(false), SuppressImplicitBase(false), + FullyQualifiedName(false) { } + + /// Adjust this printing policy for cases where it's known that we're + /// printing C++ code (for instance, if AST dumping reaches a C++-only + /// construct). This should not be used if a real LangOptions object is + /// available. void adjustForCPlusPlus() { SuppressTagKeyword = true; Bool = true; UseVoidForZeroParams = false; } - /// \brief The number of spaces to use to indent each line. + /// The number of spaces to use to indent each line. unsigned Indentation : 8; - /// \brief Whether we should suppress printing of the actual specifiers for + /// Whether we should suppress printing of the actual specifiers for /// the given type or declaration. /// /// This flag is only used when we are printing declarators beyond @@ -81,7 +83,7 @@ struct PrintingPolicy { /// "const int" type specifier and instead only print the "*y". bool SuppressSpecifiers : 1; - /// \brief Whether type printing should skip printing the tag keyword. + /// Whether type printing should skip printing the tag keyword. /// /// This is used when printing the inner type of elaborated types, /// (as the tag keyword is part of the elaborated type): @@ -91,7 +93,7 @@ struct PrintingPolicy { /// \endcode bool SuppressTagKeyword : 1; - /// \brief When true, include the body of a tag definition. + /// When true, include the body of a tag definition. /// /// This is used to place the definition of a struct /// in the middle of another declaration as with: @@ -101,14 +103,14 @@ struct PrintingPolicy { /// \endcode bool IncludeTagDefinition : 1; - /// \brief Suppresses printing of scope specifiers. + /// Suppresses printing of scope specifiers. bool SuppressScope : 1; - /// \brief Suppress printing parts of scope specifiers that don't need + /// Suppress printing parts of scope specifiers that don't need /// to be written, e.g., for inline or anonymous namespaces. bool SuppressUnwrittenScope : 1; - /// \brief Suppress printing of variable initializers. + /// Suppress printing of variable initializers. /// /// This flag is used when printing the loop variable in a for-range /// statement. For example, given: @@ -121,8 +123,8 @@ struct PrintingPolicy { /// internal initializer constructed for x will not be printed. bool SuppressInitializers : 1; - /// \brief Whether we should print the sizes of constant array expressions - /// as written in the sources. + /// Whether we should print the sizes of constant array expressions as written + /// in the sources. /// /// This flag determines whether array types declared as /// @@ -139,67 +141,90 @@ struct PrintingPolicy { /// \endcode bool ConstantArraySizeAsWritten : 1; - /// \brief When printing an anonymous tag name, also print the location of - /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just - /// prints "(anonymous)" for the name. + /// When printing an anonymous tag name, also print the location of that + /// entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just prints + /// "(anonymous)" for the name. bool AnonymousTagLocations : 1; - /// \brief When true, suppress printing of the __strong lifetime qualifier in - /// ARC. + /// When true, suppress printing of the __strong lifetime qualifier in ARC. unsigned SuppressStrongLifetime : 1; - /// \brief When true, suppress printing of lifetime qualifier in - /// ARC. + /// When true, suppress printing of lifetime qualifier in ARC. unsigned SuppressLifetimeQualifiers : 1; /// When true, suppresses printing template arguments in names of C++ /// constructors. unsigned SuppressTemplateArgsInCXXConstructors : 1; - /// \brief Whether we can use 'bool' rather than '_Bool' (even if the language + /// Whether we can use 'bool' rather than '_Bool' (even if the language /// doesn't actually have 'bool', because, e.g., it is defined as a macro). unsigned Bool : 1; - /// \brief Whether we can use 'restrict' rather than '__restrict'. + /// Whether we can use 'restrict' rather than '__restrict'. unsigned Restrict : 1; - /// \brief Whether we can use 'alignof' rather than '__alignof'. + /// Whether we can use 'alignof' rather than '__alignof'. unsigned Alignof : 1; - /// \brief Whether we can use '_Alignof' rather than '__alignof'. + /// Whether we can use '_Alignof' rather than '__alignof'. unsigned UnderscoreAlignof : 1; - /// \brief Whether we should use '(void)' rather than '()' for a function - /// prototype with zero parameters. + /// Whether we should use '(void)' rather than '()' for a function prototype + /// with zero parameters. unsigned UseVoidForZeroParams : 1; - /// \brief Provide a 'terse' output. + /// Provide a 'terse' output. /// /// For example, in this mode we don't print function bodies, class members, /// declarations inside namespaces etc. Effectively, this should print /// only the requested declaration. unsigned TerseOutput : 1; - /// \brief When true, do certain refinement needed for producing proper - /// declaration tag; such as, do not print attributes attached to the declaration. + /// When true, do certain refinement needed for producing proper declaration + /// tag; such as, do not print attributes attached to the declaration. /// unsigned PolishForDeclaration : 1; - /// \brief When true, print the half-precision floating-point type as 'half' + /// When true, print the half-precision floating-point type as 'half' /// instead of '__fp16' unsigned Half : 1; - /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in + /// When true, print the built-in wchar_t type as __wchar_t. For use in /// Microsoft mode when wchar_t is not available. unsigned MSWChar : 1; - /// \brief When true, include newlines after statements like "break", etc. + /// When true, include newlines after statements like "break", etc. unsigned IncludeNewlines : 1; - /// \brief Use whitespace and punctuation like MSVC does. In particular, this - /// prints anonymous namespaces as `anonymous namespace' and does not insert - /// spaces after template arguments. + /// Use whitespace and punctuation like MSVC does. In particular, this prints + /// anonymous namespaces as `anonymous namespace' and does not insert spaces + /// after template arguments. bool MSVCFormatting : 1; + + /// Whether we should print the constant expressions as written in the + /// sources. + /// + /// This flag determines whether constants expressions like + /// + /// \code + /// 0x10 + /// 2.5e3 + /// \endcode + /// + /// will be printed as written or as follows: + /// + /// \code + /// 0x10 + /// 2.5e3 + /// \endcode + bool ConstantsAsWritten : 1; + + /// When true, don't print the implicit 'self' or 'this' expressions. + bool SuppressImplicitBase : 1; + + /// When true, print the fully qualified name of function declarations. + /// This is the opposite of SuppressScope and thus overrules it. + bool FullyQualifiedName : 1; }; } // end namespace clang diff --git a/include/clang/Tooling/Core/QualTypeNames.h b/include/clang/AST/QualTypeNames.h index 7248356e748e..86d805feeed7 100644 --- a/include/clang/Tooling/Core/QualTypeNames.h +++ b/include/clang/AST/QualTypeNames.h @@ -56,8 +56,8 @@ // // ===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H -#define LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H +#ifndef LLVM_CLANG_AST_QUALTYPENAMES_H +#define LLVM_CLANG_AST_QUALTYPENAMES_H #include "clang/AST/ASTContext.h" @@ -71,9 +71,20 @@ namespace TypeName { /// \param[in] Ctx - the ASTContext to be used. /// \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, +std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix = false); -} // end namespace TypeName -} // end namespace clang -#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H + +/// \brief 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. +/// +/// \param[in] QT - the type for which the fully qualified type will be +/// returned. +/// \param[in] Ctx - the ASTContext to be used. +/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace +/// specifier "::" should be prepended or not. +QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, + bool WithGlobalNsPrefix = false); +} // end namespace TypeName +} // end namespace clang +#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 7a39c3b2539d..696d44efa0d9 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -1,4 +1,4 @@ -//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===// +//===- RecordLayout.h - Layout information for a struct/union ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,15 +14,20 @@ #ifndef LLVM_CLANG_AST_RECORDLAYOUT_H #define LLVM_CLANG_AST_RECORDLAYOUT_H +#include "clang/AST/ASTVector.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include <cassert> +#include <cstdint> namespace clang { - class ASTContext; - class FieldDecl; - class RecordDecl; - class CXXRecordDecl; + +class ASTContext; +class CXXRecordDecl; /// ASTRecordLayout - /// This class contains layout information for one RecordDecl, @@ -42,21 +47,21 @@ public: /// Whether this virtual base requires a vtordisp field in the /// Microsoft ABI. These fields are required for certain operations /// in constructors and destructors. - bool HasVtorDisp; + bool HasVtorDisp = false; public: - bool hasVtorDisp() const { return HasVtorDisp; } - - VBaseInfo() : HasVtorDisp(false) {} + VBaseInfo() = default; + VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) + : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} - VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) : - VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} + bool hasVtorDisp() const { return HasVtorDisp; } }; - typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo> - VBaseOffsetsMapTy; + using VBaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>; private: + friend class ASTContext; + /// Size - Size of record in characters. CharUnits Size; @@ -117,7 +122,7 @@ private: const CXXRecordDecl *BaseSharingVBPtr; /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) - typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy; + using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>; /// BaseOffsets - Contains a map from base classes to their offset. BaseOffsetsMapTy BaseOffsets; @@ -128,16 +133,15 @@ private: /// CXXInfo - If the record layout is for a C++ record, this will have /// C++ specific information about the record. - CXXRecordLayoutInfo *CXXInfo; - - friend class ASTContext; + CXXRecordLayoutInfo *CXXInfo = nullptr; ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, CharUnits requiredAlignment, CharUnits datasize, ArrayRef<uint64_t> fieldoffsets); + using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy; + // Constructor for C++ records. - typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, CharUnits requiredAlignment, @@ -159,9 +163,9 @@ private: void Destroy(ASTContext &Ctx); - ASTRecordLayout(const ASTRecordLayout &) = delete; - void operator=(const ASTRecordLayout &) = delete; public: + ASTRecordLayout(const ASTRecordLayout &) = delete; + ASTRecordLayout &operator=(const ASTRecordLayout &) = delete; /// getAlignment - Get the record alignment in characters. CharUnits getAlignment() const { return Alignment; } @@ -305,6 +309,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_RECORDLAYOUT_H diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index e7f271cc0812..ba76ea0a0df5 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -63,8 +63,8 @@ OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \ OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \ OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \ - OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \ - OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) + OPERATOR(NE) OPERATOR(Cmp) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \ + OPERATOR(LAnd) OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) // All compound assign operators. #define CAO_LIST() \ @@ -83,7 +83,7 @@ namespace clang { return false; \ } while (false) -/// \brief A class that does preordor or postorder +/// \brief 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: @@ -267,6 +267,12 @@ public: bool TraverseTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); + /// \brief 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 /// automatically dispatches to another visitor for the initializer /// expression, but not for the name of the initializer, so may @@ -309,6 +315,8 @@ public: // ---- Methods on Stmts ---- + Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } + private: template<typename T, typename U> struct has_same_member_pointer_type : std::false_type {}; @@ -491,6 +499,8 @@ public: bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } #include "clang/AST/DeclNodes.inc" + bool canIgnoreChildDeclWhileTraversingDeclContext(const Decl *Child); + private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); @@ -978,6 +988,11 @@ DEF_TRAVERSE_TYPE(DependentSizedArrayType, { TRY_TO(TraverseStmt(T->getSizeExpr())); }) +DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { + TRY_TO(TraverseStmt(T->getAddrSpaceExpr())); + TRY_TO(TraverseType(T->getPointeeType())); +}) + DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { if (T->getSizeExpr()) TRY_TO(TraverseStmt(T->getSizeExpr())); @@ -1188,6 +1203,11 @@ DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { return TraverseArrayTypeLocHelper(TL); }) +DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, { + TRY_TO(TraverseStmt(TL.getTypePtr()->getAddrSpaceExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getPointeeType())); +}) + // FIXME: order? why not size expr first? // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { @@ -1339,14 +1359,20 @@ DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) // than those. template <typename Derived> +bool RecursiveASTVisitor<Derived>::canIgnoreChildDeclWhileTraversingDeclContext( + const Decl *Child) { + // BlockDecls and CapturedDecls are traversed through BlockExprs and + // CapturedStmts respectively. + return isa<BlockDecl>(Child) || isa<CapturedDecl>(Child); +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { if (!DC) return true; for (auto *Child : DC->decls()) { - // BlockDecls and CapturedDecls are traversed through BlockExprs and - // CapturedStmts respectively. - if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child)) + if (!canIgnoreChildDeclWhileTraversingDeclContext(Child)) TRY_TO(TraverseDecl(Child)); } @@ -1674,8 +1700,8 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( // template declarations. #define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ - TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ + TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ \ /* By default, we do not traverse the instantiations of \ class templates since they do not appear in the user code. The \ @@ -1769,12 +1795,19 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseCXXBaseSpecifier( + const CXXBaseSpecifier &Base) { + TRY_TO(TraverseTypeLoc(Base.getTypeSourceInfo()->getTypeLoc())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) { if (!TraverseRecordHelper(D)) return false; if (D->isCompleteDefinition()) { for (const auto &I : D->bases()) { - TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc())); + TRY_TO(TraverseCXXBaseSpecifier(I)); } // We don't traverse the friends or the conversions, as they are // already in decls_begin()/decls_end(). @@ -2057,7 +2090,7 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { TRY_TO(WalkUpFrom##STMT(S)); \ { CODE; } \ if (ShouldVisitChildren) { \ - for (Stmt *SubStmt : S->children()) { \ + for (Stmt * SubStmt : getDerived().getStmtChildren(S)) { \ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \ } \ } \ @@ -3039,6 +3072,30 @@ bool RecursiveASTVisitor<Derived>::VisitOMPTaskReductionClause( } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPInReductionClause( + OMPInReductionClause *C) { + TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); + TRY_TO(VisitOMPClauseList(C)); + TRY_TO(VisitOMPClauseWithPostUpdate(C)); + for (auto *E : C->privates()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->lhs_exprs()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->rhs_exprs()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->reduction_ops()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->taskgroup_descriptors()) + TRY_TO(TraverseStmt(E)); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { TRY_TO(VisitOMPClauseList(C)); return true; @@ -3052,6 +3109,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getDevice())); return true; } diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 89a9d3c4cc21..86b0f356e7b5 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -1,4 +1,4 @@ -//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====// +//===- Redeclarable.h - Base for Decls that can be redeclared --*- C++ -*-====// // // The LLVM Compiler Infrastructure // @@ -15,11 +15,18 @@ #define LLVM_CLANG_AST_REDECLARABLE_H #include "clang/AST/ExternalASTSource.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Casting.h" +#include <cassert> +#include <cstddef> #include <iterator> namespace clang { + class ASTContext; +class Decl; // Some notes on redeclarables: // @@ -82,21 +89,21 @@ protected: class DeclLink { /// A pointer to a known latest declaration, either statically known or /// generationally updated as decls are added by an external source. - typedef LazyGenerationalUpdatePtr<const Decl*, Decl*, - &ExternalASTSource::CompleteRedeclChain> - KnownLatest; + using KnownLatest = + LazyGenerationalUpdatePtr<const Decl *, Decl *, + &ExternalASTSource::CompleteRedeclChain>; /// We store a pointer to the ASTContext in the UninitializedLatest /// pointer, but to avoid circular type dependencies when we steal the low /// bits of this pointer, we use a raw void* here. - typedef const void *UninitializedLatest; + using UninitializedLatest = const void *; - typedef Decl *Previous; + using Previous = Decl *; /// A pointer to either an uninitialized latest declaration (where either /// we've not yet set the previous decl or there isn't one), or to a known /// previous declaration. - typedef llvm::PointerUnion<Previous, UninitializedLatest> NotKnownLatest; + using NotKnownLatest = llvm::PointerUnion<Previous, UninitializedLatest>; mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next; @@ -106,8 +113,7 @@ protected: DeclLink(LatestTag, const ASTContext &Ctx) : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {} - DeclLink(PreviousTag, decl_type *D) - : Next(NotKnownLatest(Previous(D))) {} + DeclLink(PreviousTag, decl_type *D) : Next(NotKnownLatest(Previous(D))) {} bool NextIsPrevious() const { return Next.is<NotKnownLatest>() && @@ -182,6 +188,7 @@ protected: /// /// If there is only one declaration, it is <pointer to self, true> DeclLink RedeclLink; + decl_type *First; decl_type *getNextRedeclaration() const { @@ -189,8 +196,12 @@ protected: } public: - Redeclarable(const ASTContext &Ctx) - : RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {} + friend class ASTDeclReader; + friend class ASTDeclWriter; + + Redeclarable(const ASTContext &Ctx) + : RedeclLink(LatestDeclLink(Ctx)), + First(static_cast<decl_type *>(this)) {} /// \brief Return the previous declaration of this declaration or NULL if this /// is the first declaration. @@ -232,20 +243,19 @@ public: /// \brief Iterates through all the redeclarations of the same decl. class redecl_iterator { /// Current - The current declaration. - decl_type *Current; + decl_type *Current = nullptr; decl_type *Starter; - bool PassedFirst; + bool PassedFirst = false; public: - typedef decl_type* value_type; - typedef decl_type* reference; - typedef decl_type* pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + using value_type = decl_type *; + using reference = decl_type *; + using pointer = decl_type *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; - redecl_iterator() : Current(nullptr) { } - explicit redecl_iterator(decl_type *C) - : Current(C), Starter(C), PassedFirst(false) { } + redecl_iterator() = default; + explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) {} reference operator*() const { return Current; } pointer operator->() const { return Current; } @@ -282,7 +292,7 @@ public: } }; - typedef llvm::iterator_range<redecl_iterator> redecl_range; + using redecl_range = llvm::iterator_range<redecl_iterator>; /// \brief 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). @@ -294,9 +304,6 @@ public: redecl_iterator redecls_begin() const { return redecls().begin(); } redecl_iterator redecls_end() const { return redecls().end(); } - - friend class ASTDeclReader; - friend class ASTDeclWriter; }; /// \brief Get the primary declaration for a declaration from an AST file. That @@ -309,7 +316,7 @@ Decl *getPrimaryMergedDecl(Decl *D); template<typename decl_type> class Mergeable { public: - Mergeable() {} + Mergeable() = default; /// \brief Return the first declaration of this declaration or itself if this /// is the only declaration. @@ -344,7 +351,7 @@ public: /// remember to call getCanonicalDecl() everywhere. template <typename decl_type> class CanonicalDeclPtr { public: - CanonicalDeclPtr() : Ptr(nullptr) {} + CanonicalDeclPtr() = default; CanonicalDeclPtr(decl_type *Ptr) : Ptr(Ptr ? Ptr->getCanonicalDecl() : nullptr) {} CanonicalDeclPtr(const CanonicalDeclPtr &) = default; @@ -362,11 +369,13 @@ public: private: friend struct llvm::DenseMapInfo<CanonicalDeclPtr<decl_type>>; - decl_type *Ptr; + decl_type *Ptr = nullptr; }; + } // namespace clang namespace llvm { + template <typename decl_type> struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> { using CanonicalDeclPtr = clang::CanonicalDeclPtr<decl_type>; @@ -395,6 +404,7 @@ struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> { return BaseInfo::isEqual(LHS, RHS); } }; + } // namespace llvm -#endif +#endif // LLVM_CLANG_AST_REDECLARABLE_H diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index c210bd1cec2e..6bd07af1affa 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -1,4 +1,4 @@ -//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===// +//===- Stmt.h - Classes for representing statements -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -22,34 +22,40 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <iterator> #include <string> namespace llvm { - class FoldingSetNodeID; -} + +class FoldingSetNodeID; + +} // namespace llvm namespace clang { - class ASTContext; - class Attr; - class CapturedDecl; - class Decl; - class Expr; - class IdentifierInfo; - class LabelDecl; - class ODRHash; - class ParmVarDecl; - class PrinterHelper; - struct PrintingPolicy; - class QualType; - class RecordDecl; - class SourceManager; - class StringLiteral; - class SwitchStmt; - class Token; - class VarDecl; + +class ASTContext; +class Attr; +class CapturedDecl; +class Decl; +class Expr; +class LabelDecl; +class ODRHash; +class PrinterHelper; +struct PrintingPolicy; +class RecordDecl; +class SourceManager; +class StringLiteral; +class Token; +class VarDecl; //===----------------------------------------------------------------------===// // AST classes for statements. @@ -72,9 +78,13 @@ public: // Make vanilla 'new' and 'delete' illegal for Stmts. protected: + friend class ASTStmtReader; + friend class ASTStmtWriter; + void *operator new(size_t bytes) noexcept { llvm_unreachable("Stmts cannot be allocated with regular 'new'."); } + void operator delete(void *data) noexcept { llvm_unreachable("Stmts cannot be released with regular 'delete'."); } @@ -89,6 +99,7 @@ protected: class CompoundStmtBitfields { friend class CompoundStmt; + unsigned : NumStmtBits; unsigned NumStmts : 32 - NumStmtBits; @@ -96,34 +107,36 @@ protected: class IfStmtBitfields { friend class IfStmt; + unsigned : NumStmtBits; unsigned IsConstexpr : 1; }; class ExprBitfields { - friend class Expr; - friend class DeclRefExpr; // computeDependence - friend class InitListExpr; // ctor - friend class DesignatedInitExpr; // ctor - friend class BlockDeclRefExpr; // ctor friend class ASTStmtReader; // deserialization + friend class AtomicExpr; // ctor + friend class BlockDeclRefExpr; // ctor + friend class CallExpr; // ctor + friend class CXXConstructExpr; // ctor + friend class CXXDependentScopeMemberExpr; // ctor friend class CXXNewExpr; // ctor + friend class CXXUnresolvedConstructExpr; // ctor + friend class DeclRefExpr; // computeDependence friend class DependentScopeDeclRefExpr; // ctor - friend class CXXConstructExpr; // ctor - friend class CallExpr; // ctor - friend class OffsetOfExpr; // ctor - friend class ObjCMessageExpr; // ctor + friend class DesignatedInitExpr; // ctor + friend class Expr; + friend class InitListExpr; // ctor friend class ObjCArrayLiteral; // ctor friend class ObjCDictionaryLiteral; // ctor - friend class ShuffleVectorExpr; // ctor - friend class ParenListExpr; // ctor - friend class CXXUnresolvedConstructExpr; // ctor - friend class CXXDependentScopeMemberExpr; // ctor + friend class ObjCMessageExpr; // ctor + friend class OffsetOfExpr; // ctor + friend class OpaqueValueExpr; // ctor friend class OverloadExpr; // ctor + friend class ParenListExpr; // ctor friend class PseudoObjectExpr; // ctor - friend class AtomicExpr; // ctor - friend class OpaqueValueExpr; // ctor + friend class ShuffleVectorExpr; // ctor + unsigned : NumStmtBits; unsigned ValueKind : 2; @@ -137,6 +150,7 @@ protected: class CharacterLiteralBitfields { friend class CharacterLiteral; + unsigned : NumExprBits; unsigned Kind : 3; @@ -153,6 +167,7 @@ protected: class FloatingLiteralBitfields { friend class FloatingLiteral; + unsigned : NumExprBits; unsigned Semantics : 3; // Provides semantics for APFloat construction @@ -161,6 +176,7 @@ protected: class UnaryExprOrTypeTraitExprBitfields { friend class UnaryExprOrTypeTraitExpr; + unsigned : NumExprBits; unsigned Kind : 2; @@ -168,8 +184,9 @@ protected: }; class DeclRefExprBitfields { - friend class DeclRefExpr; friend class ASTStmtReader; // deserialization + friend class DeclRefExpr; + unsigned : NumExprBits; unsigned HasQualifier : 1; @@ -181,6 +198,7 @@ protected: class CastExprBitfields { friend class CastExpr; + unsigned : NumExprBits; unsigned Kind : 6; @@ -189,14 +207,15 @@ protected: class CallExprBitfields { friend class CallExpr; + unsigned : NumExprBits; unsigned NumPreArgs : 1; }; class ExprWithCleanupsBitfields { - friend class ExprWithCleanups; friend class ASTStmtReader; // deserialization + friend class ExprWithCleanups; unsigned : NumExprBits; @@ -207,8 +226,8 @@ protected: }; class PseudoObjectExprBitfields { - friend class PseudoObjectExpr; friend class ASTStmtReader; // deserialization + friend class PseudoObjectExpr; unsigned : NumExprBits; @@ -220,6 +239,7 @@ protected: class ObjCIndirectCopyRestoreExprBitfields { friend class ObjCIndirectCopyRestoreExpr; + unsigned : NumExprBits; unsigned ShouldCopy : 1; @@ -236,9 +256,9 @@ protected: }; class TypeTraitExprBitfields { - friend class TypeTraitExpr; friend class ASTStmtReader; friend class ASTStmtWriter; + friend class TypeTraitExpr; unsigned : NumExprBits; @@ -280,9 +300,6 @@ protected: CoawaitExprBitfields CoawaitBits; }; - friend class ASTStmtReader; - friend class ASTStmtWriter; - public: // Only allow allocation of Stmts using the allocator in ASTContext // or by doing a placement new. @@ -305,7 +322,7 @@ public: /// \brief 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 { }; + struct EmptyShell {}; protected: /// Iterator for iterating over Stmt * arrays that contain only Expr * @@ -361,6 +378,7 @@ public: StmtClass getStmtClass() const { return static_cast<StmtClass>(StmtBits.sClass); } + const char *getStmtClassName() const; /// SourceLocation tokens are not useful in isolation - they are low level @@ -389,8 +407,8 @@ public: /// back to its original source language syntax. void dumpPretty(const ASTContext &Context) const; void printPretty(raw_ostream &OS, PrinterHelper *Helper, - const PrintingPolicy &Policy, - unsigned Indentation = 0) const; + const PrintingPolicy &Policy, unsigned Indentation = 0, + const ASTContext *Context = nullptr) const; /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// works on systems with GraphViz (Mac OS X) or dot+gv installed. @@ -406,6 +424,9 @@ public: /// \brief Skip no-op (attributed, compound) container stmts and skip captured /// stmt at the top, if \a IgnoreCaptured is true. Stmt *IgnoreContainers(bool IgnoreCaptured = false); + const Stmt *IgnoreContainers(bool IgnoreCaptured = false) const { + return const_cast<Stmt *>(this)->IgnoreContainers(IgnoreCaptured); + } const Stmt *stripLabelLikeStatements() const; Stmt *stripLabelLikeStatements() { @@ -416,11 +437,11 @@ public: /// Child Iterators: All subclasses must implement 'children' /// to permit easy iteration over the substatements/subexpessions of an /// AST node. This permits easy iteration over all nodes in the AST. - typedef StmtIterator child_iterator; - typedef ConstStmtIterator const_child_iterator; + using child_iterator = StmtIterator; + using const_child_iterator = ConstStmtIterator; - typedef llvm::iterator_range<child_iterator> child_range; - typedef llvm::iterator_range<const_child_iterator> const_child_range; + using child_range = llvm::iterator_range<child_iterator>; + using const_child_range = llvm::iterator_range<const_child_iterator>; child_range children(); const_child_range children() const { @@ -463,18 +484,16 @@ public: /// expressions. For example, CompoundStmt mixes statements, expressions /// and declarations (variables, types). Another example is ForStmt, where /// the first statement can be an expression or a declaration. -/// class DeclStmt : public Stmt { DeclGroupRef DG; SourceLocation StartLoc, EndLoc; public: - DeclStmt(DeclGroupRef dg, SourceLocation startLoc, - SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), - StartLoc(startLoc), EndLoc(endLoc) {} + DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) + : Stmt(DeclStmtClass), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {} /// \brief Build an empty declaration statement. - explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { } + explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) {} /// isSingleDecl - This method returns true if this DeclStmt refers /// to a single Decl. @@ -507,10 +526,10 @@ public: child_iterator(DG.end(), DG.end())); } - typedef DeclGroupRef::iterator decl_iterator; - typedef DeclGroupRef::const_iterator const_decl_iterator; - typedef llvm::iterator_range<decl_iterator> decl_range; - typedef llvm::iterator_range<const_decl_iterator> decl_const_range; + using decl_iterator = DeclGroupRef::iterator; + using const_decl_iterator = DeclGroupRef::const_iterator; + using decl_range = llvm::iterator_range<decl_iterator>; + 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 { @@ -521,10 +540,12 @@ public: const_decl_iterator decl_begin() const { return DG.begin(); } const_decl_iterator decl_end() const { return DG.end(); } - typedef std::reverse_iterator<decl_iterator> reverse_decl_iterator; + using reverse_decl_iterator = std::reverse_iterator<decl_iterator>; + reverse_decl_iterator decl_rbegin() { return reverse_decl_iterator(decl_end()); } + reverse_decl_iterator decl_rend() { return reverse_decl_iterator(decl_begin()); } @@ -540,15 +561,18 @@ class NullStmt : public Stmt { /// #define CALL(x) /// CALL(0); /// @endcode - bool HasLeadingEmptyMacro; + bool HasLeadingEmptyMacro = false; + public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false) - : Stmt(NullStmtClass), SemiLoc(L), - HasLeadingEmptyMacro(hasLeadingEmptyMacro) {} + : Stmt(NullStmtClass), SemiLoc(L), + HasLeadingEmptyMacro(hasLeadingEmptyMacro) {} /// \brief Build an empty null statement. - explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty), - HasLeadingEmptyMacro(false) { } + explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {} SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } @@ -565,32 +589,27 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// CompoundStmt - This represents a group of statements like { stmt stmt }. -/// class CompoundStmt : public Stmt { - Stmt** Body; - SourceLocation LBraceLoc, RBraceLoc; - friend class ASTStmtReader; + Stmt** Body = nullptr; + SourceLocation LBraceLoc, RBraceLoc; + public: CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, SourceLocation LB, SourceLocation RB); // \brief Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) { + : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) { CompoundStmtBits.NumStmts = 0; } // \brief Build an empty compound statement. - explicit CompoundStmt(EmptyShell Empty) - : Stmt(CompoundStmtClass, Empty), Body(nullptr) { + explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) { CompoundStmtBits.NumStmts = 0; } @@ -599,8 +618,8 @@ public: bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } unsigned size() const { return CompoundStmtBits.NumStmts; } - typedef Stmt** body_iterator; - typedef llvm::iterator_range<body_iterator> body_range; + using body_iterator = Stmt **; + using body_range = llvm::iterator_range<body_iterator>; body_range body() { return body_range(body_begin(), body_end()); } body_iterator body_begin() { return Body; } @@ -613,31 +632,36 @@ public: Body[size()-1] = S; } - typedef Stmt* const * const_body_iterator; - typedef llvm::iterator_range<const_body_iterator> body_const_range; + using const_body_iterator = Stmt* const *; + using body_const_range = llvm::iterator_range<const_body_iterator>; body_const_range body() const { return body_const_range(body_begin(), body_end()); } + const_body_iterator body_begin() const { return Body; } const_body_iterator body_end() const { return Body + size(); } + const Stmt *body_front() const { return !body_empty() ? Body[0] : nullptr; } + const Stmt *body_back() const { return !body_empty() ? Body[size() - 1] : nullptr; } - typedef std::reverse_iterator<body_iterator> reverse_body_iterator; + using reverse_body_iterator = std::reverse_iterator<body_iterator>; + reverse_body_iterator body_rbegin() { return reverse_body_iterator(body_end()); } + reverse_body_iterator body_rend() { return reverse_body_iterator(body_begin()); } - typedef std::reverse_iterator<const_body_iterator> - const_reverse_body_iterator; + using const_reverse_body_iterator = + std::reverse_iterator<const_body_iterator>; const_reverse_body_iterator body_rbegin() const { return const_reverse_body_iterator(body_end()); @@ -673,16 +697,14 @@ class SwitchCase : public Stmt { protected: // A pointer to the following CaseStmt or DefaultStmt class, // used by SwitchStmt. - SwitchCase *NextSwitchCase; + SwitchCase *NextSwitchCase = nullptr; SourceLocation KeywordLoc; SourceLocation ColonLoc; SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc) - : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) { - } + : Stmt(SC), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {} - SwitchCase(StmtClass SC, EmptyShell) - : Stmt(SC), NextSwitchCase(nullptr) {} + SwitchCase(StmtClass SC, EmptyShell) : Stmt(SC) {} public: const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } @@ -715,6 +737,7 @@ class CaseStmt : public SwitchCase { enum { LHS, RHS, SUBSTMT, END_EXPR }; Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension + public: CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, SourceLocation ellipsisLoc, SourceLocation colonLoc) @@ -726,7 +749,7 @@ public: } /// \brief Build an empty switch case statement. - explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) { } + explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {} SourceLocation getCaseLoc() const { return KeywordLoc; } void setCaseLoc(SourceLocation L) { KeywordLoc = L; } @@ -742,9 +765,11 @@ public: const Expr *getLHS() const { return reinterpret_cast<const Expr*>(SubExprs[LHS]); } + const Expr *getRHS() const { return reinterpret_cast<const Expr*>(SubExprs[RHS]); } + const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; } void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; } @@ -752,6 +777,7 @@ public: void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); } SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { // Handle deeply nested case statements with iteration instead of recursion. const CaseStmt *CS = this; @@ -773,13 +799,14 @@ public: class DefaultStmt : public SwitchCase { Stmt* SubStmt; + public: DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {} /// \brief Build an empty default statement. explicit DefaultStmt(EmptyShell Empty) - : SwitchCase(DefaultStmtClass, Empty) { } + : SwitchCase(DefaultStmtClass, Empty) {} Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -809,7 +836,6 @@ inline SourceLocation SwitchCase::getLocEnd() const { /// LabelStmt - Represents a label, which has a substatement. For example: /// foo: return; -/// class LabelStmt : public Stmt { SourceLocation IdentLoc; LabelDecl *TheDecl; @@ -824,7 +850,7 @@ public: } // \brief Build an empty label statement. - explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { } + explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {} SourceLocation getIdentLoc() const { return IdentLoc; } LabelDecl *getDecl() const { return TheDecl; } @@ -845,19 +871,17 @@ public: } }; - /// \brief Represents an attribute applied to a statement. /// /// Represents an attribute applied to a statement. For example: /// [[omp::for(...)]] for (...) { ... } -/// class AttributedStmt : public Stmt { + friend class ASTStmtReader; + Stmt *SubStmt; SourceLocation AttrLoc; unsigned NumAttrs; - friend class ASTStmtReader; - AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt) : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc), NumAttrs(Attrs.size()) { @@ -879,6 +903,7 @@ class AttributedStmt : public Stmt { public: static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt); + // \brief Build an empty attributed statement. static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs); @@ -886,6 +911,7 @@ public: ArrayRef<const Attr*> getAttrs() const { return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs); } + Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -899,9 +925,7 @@ public: } }; - /// IfStmt - This represents an if/then/else. -/// class IfStmt : public Stmt { enum { INIT, VAR, COND, THEN, ELSE, END_EXPR }; Stmt* SubExprs[END_EXPR]; @@ -916,7 +940,7 @@ public: Stmt *elsev = nullptr); /// \brief Build an empty if/then/else statement - explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } + explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) {} /// \brief Retrieve the variable declared in this "if" statement, if any. /// @@ -960,6 +984,7 @@ public: bool isObjCAvailabilityCheck() const; SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { if (SubExprs[ELSE]) return SubExprs[ELSE]->getLocEnd(); @@ -979,11 +1004,11 @@ public: }; /// SwitchStmt - This represents a 'switch' stmt. -/// class SwitchStmt : public Stmt { SourceLocation SwitchLoc; enum { INIT, VAR, COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; + // This points to a linked list of case and default statements and, if the // SwitchStmt is a switch on an enum value, records whether all the enum // values were covered by CaseStmts. The coverage information value is meant @@ -994,7 +1019,7 @@ public: SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond); /// \brief Build a empty switch statement. - explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } + explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) {} /// \brief Retrieve the variable declared in this "switch" statement, if any. /// @@ -1037,6 +1062,7 @@ public: SubExprs[BODY] = S; SwitchLoc = SL; } + void addSwitchCase(SwitchCase *SC) { assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); @@ -1053,6 +1079,7 @@ public: bool isAllEnumCasesCovered() const { return FirstCase.getInt(); } SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd(); } @@ -1067,19 +1094,18 @@ public: } }; - /// WhileStmt - This represents a 'while' stmt. -/// class WhileStmt : public Stmt { SourceLocation WhileLoc; enum { VAR, COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; + public: WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL); /// \brief Build an empty while statement. - explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } + explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) {} /// \brief Retrieve the variable declared in this "while" statement, if any. /// @@ -1109,6 +1135,7 @@ public: void setWhileLoc(SourceLocation L) { WhileLoc = L; } SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExprs[BODY]->getLocEnd(); } @@ -1124,7 +1151,6 @@ public: }; /// DoStmt - This represents a 'do/while' stmt. -/// class DoStmt : public Stmt { SourceLocation DoLoc; enum { BODY, COND, END_EXPR }; @@ -1141,7 +1167,7 @@ public: } /// \brief Build an empty do-while statement. - explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { } + explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) {} Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} @@ -1171,11 +1197,9 @@ public: } }; - /// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of /// the init/cond/inc parts of the ForStmt will be null if they were not /// specified in the source. -/// class ForStmt : public Stmt { SourceLocation ForLoc; enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR }; @@ -1188,7 +1212,7 @@ public: SourceLocation RP); /// \brief Build an empty for statement. - explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } + explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) {} Stmt *getInit() { return SubExprs[INIT]; } @@ -1231,6 +1255,7 @@ public: void setRParenLoc(SourceLocation L) { RParenLoc = L; } SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExprs[BODY]->getLocEnd(); } @@ -1246,17 +1271,17 @@ public: }; /// GotoStmt - This represents a direct goto. -/// class GotoStmt : public Stmt { LabelDecl *Label; SourceLocation GotoLoc; SourceLocation LabelLoc; + public: GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL) - : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} + : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} /// \brief Build an empty goto statement. - explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { } + explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) {} LabelDecl *getLabel() const { return Label; } void setLabel(LabelDecl *D) { Label = D; } @@ -1280,11 +1305,11 @@ public: }; /// IndirectGotoStmt - This represents an indirect goto. -/// class IndirectGotoStmt : public Stmt { SourceLocation GotoLoc; SourceLocation StarLoc; Stmt *Target; + public: IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, Expr *target) @@ -1293,7 +1318,7 @@ public: /// \brief Build an empty indirect goto statement. explicit IndirectGotoStmt(EmptyShell Empty) - : Stmt(IndirectGotoStmtClass, Empty) { } + : Stmt(IndirectGotoStmtClass, Empty) {} void setGotoLoc(SourceLocation L) { GotoLoc = L; } SourceLocation getGotoLoc() const { return GotoLoc; } @@ -1322,16 +1347,15 @@ public: child_range children() { return child_range(&Target, &Target+1); } }; - /// ContinueStmt - This represents a continue. -/// class ContinueStmt : public Stmt { SourceLocation ContinueLoc; + public: ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} /// \brief Build an empty continue statement. - explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { } + explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {} SourceLocation getContinueLoc() const { return ContinueLoc; } void setContinueLoc(SourceLocation L) { ContinueLoc = L; } @@ -1350,7 +1374,6 @@ public: }; /// BreakStmt - This represents a break. -/// class BreakStmt : public Stmt { SourceLocation BreakLoc; @@ -1361,7 +1384,7 @@ public: } /// \brief Build an empty break statement. - explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { } + explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {} SourceLocation getBreakLoc() const { return BreakLoc; } void setBreakLoc(SourceLocation L) { BreakLoc = L; } @@ -1379,7 +1402,6 @@ public: } }; - /// ReturnStmt - This represents a return, optionally of an expression: /// return; /// return 4; @@ -1388,7 +1410,6 @@ public: /// return a value, and it allows returning a value in functions declared to /// return void. We explicitly model this in the AST, which means you can't /// depend on the return type of the function and the presence of an argument. -/// class ReturnStmt : public Stmt { SourceLocation RetLoc; Stmt *RetExpr; @@ -1402,7 +1423,7 @@ public: NRVOCandidate(NRVOCandidate) {} /// \brief Build an empty return expression. - explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } + explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) {} const Expr *getRetValue() const; Expr *getRetValue(); @@ -1420,6 +1441,7 @@ public: void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RetExpr ? RetExpr->getLocEnd() : RetLoc; } @@ -1436,10 +1458,12 @@ public: }; /// AsmStmt is the base class for GCCAsmStmt and MSAsmStmt. -/// class AsmStmt : public Stmt { protected: + friend class ASTStmtReader; + SourceLocation AsmLoc; + /// \brief True if the assembly statement does not have any input or output /// operands. bool IsSimple; @@ -1452,19 +1476,17 @@ protected: unsigned NumInputs; unsigned NumClobbers; - Stmt **Exprs; + Stmt **Exprs = nullptr; AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile, - unsigned numoutputs, unsigned numinputs, unsigned numclobbers) : - Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile), - NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { } - - friend class ASTStmtReader; + unsigned numoutputs, unsigned numinputs, unsigned numclobbers) + : Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile), + NumOutputs(numoutputs), NumInputs(numinputs), + NumClobbers(numclobbers) {} public: /// \brief Build an empty inline-assembly statement. - explicit AsmStmt(StmtClass SC, EmptyShell Empty) : - Stmt(SC, Empty), Exprs(nullptr) { } + explicit AsmStmt(StmtClass SC, EmptyShell Empty) : Stmt(SC, Empty) {} SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } @@ -1527,10 +1549,10 @@ public: // Input expr iterators. - typedef ExprIterator inputs_iterator; - typedef ConstExprIterator const_inputs_iterator; - typedef llvm::iterator_range<inputs_iterator> inputs_range; - typedef llvm::iterator_range<const_inputs_iterator> inputs_const_range; + using inputs_iterator = ExprIterator; + using const_inputs_iterator = ConstExprIterator; + using inputs_range = llvm::iterator_range<inputs_iterator>; + using inputs_const_range = llvm::iterator_range<const_inputs_iterator>; inputs_iterator begin_inputs() { return &Exprs[0] + NumOutputs; @@ -1556,17 +1578,19 @@ public: // Output expr iterators. - typedef ExprIterator outputs_iterator; - typedef ConstExprIterator const_outputs_iterator; - typedef llvm::iterator_range<outputs_iterator> outputs_range; - typedef llvm::iterator_range<const_outputs_iterator> outputs_const_range; + using outputs_iterator = ExprIterator; + using const_outputs_iterator = ConstExprIterator; + using outputs_range = llvm::iterator_range<outputs_iterator>; + using outputs_const_range = llvm::iterator_range<const_outputs_iterator>; outputs_iterator begin_outputs() { return &Exprs[0]; } + outputs_iterator end_outputs() { return &Exprs[0] + NumOutputs; } + outputs_range outputs() { return outputs_range(begin_outputs(), end_outputs()); } @@ -1574,9 +1598,11 @@ public: const_outputs_iterator begin_outputs() const { return &Exprs[0]; } + const_outputs_iterator end_outputs() const { return &Exprs[0] + NumOutputs; } + outputs_const_range outputs() const { return outputs_const_range(begin_outputs(), end_outputs()); } @@ -1587,17 +1613,16 @@ public: }; /// This represents a GCC inline-assembly statement extension. -/// class GCCAsmStmt : public AsmStmt { + friend class ASTStmtReader; + SourceLocation RParenLoc; StringLiteral *AsmStr; // FIXME: If we wanted to, we could allocate all of these in one big array. - StringLiteral **Constraints; - StringLiteral **Clobbers; - IdentifierInfo **Names; - - friend class ASTStmtReader; + StringLiteral **Constraints = nullptr; + StringLiteral **Clobbers = nullptr; + IdentifierInfo **Names = nullptr; public: GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, @@ -1607,8 +1632,7 @@ public: StringLiteral **clobbers, SourceLocation rparenloc); /// \brief Build an empty inline-assembly statement. - explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty), - Constraints(nullptr), Clobbers(nullptr), Names(nullptr) { } + explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {} SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -1628,6 +1652,7 @@ public: String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%". Operand // Operand reference, with optional modifier %c4. }; + private: Kind MyKind; std::string Str; @@ -1635,13 +1660,13 @@ public: // Source range for operand references. CharSourceRange Range; + public: AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin, SourceLocation End) - : MyKind(Operand), Str(S), OperandNo(OpNo), - Range(CharSourceRange::getCharRange(Begin, End)) { - } + : MyKind(Operand), Str(S), OperandNo(OpNo), + Range(CharSourceRange::getCharRange(Begin, End)) {} bool isString() const { return MyKind == String; } bool isOperand() const { return MyKind == Operand; } @@ -1742,8 +1767,8 @@ private: unsigned NumInputs, StringLiteral **Clobbers, unsigned NumClobbers); -public: +public: //===--- Other ---===// /// getNamedOperand - Given a symbolic operand reference like %[foo], @@ -1752,6 +1777,7 @@ public: int getNamedOperand(StringRef SymbolicName) const; StringRef getClobber(unsigned i) const; + StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; } const StringLiteral *getClobberStringLiteral(unsigned i) const { return Clobbers[i]; @@ -1766,18 +1792,17 @@ public: }; /// This represents a Microsoft inline-assembly statement extension. -/// class MSAsmStmt : public AsmStmt { + friend class ASTStmtReader; + SourceLocation LBraceLoc, EndLoc; StringRef AsmStr; - unsigned NumAsmToks; - - Token *AsmToks; - StringRef *Constraints; - StringRef *Clobbers; + unsigned NumAsmToks = 0; - friend class ASTStmtReader; + Token *AsmToks = nullptr; + StringRef *Constraints = nullptr; + StringRef *Clobbers = nullptr; public: MSAsmStmt(const ASTContext &C, SourceLocation asmloc, @@ -1788,8 +1813,7 @@ public: ArrayRef<StringRef> clobbers, SourceLocation endloc); /// \brief Build an empty MS-style inline-assembly statement. - explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty), - NumAsmToks(0), AsmToks(nullptr), Constraints(nullptr), Clobbers(nullptr) { } + explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty) {} SourceLocation getLBraceLoc() const { return LBraceLoc; } void setLBraceLoc(SourceLocation L) { LBraceLoc = L; } @@ -1839,9 +1863,11 @@ public: ArrayRef<StringRef> getAllConstraints() const { return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs); } + ArrayRef<StringRef> getClobbers() const { return llvm::makeArrayRef(Clobbers, NumClobbers); } + ArrayRef<Expr*> getAllExprs() const { return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs), NumInputs + NumOutputs); @@ -1853,8 +1879,8 @@ private: void initialize(const ASTContext &C, StringRef AsmString, ArrayRef<Token> AsmToks, ArrayRef<StringRef> Constraints, ArrayRef<Expr*> Exprs, ArrayRef<StringRef> Clobbers); -public: +public: SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } @@ -1868,18 +1894,16 @@ public: }; class SEHExceptStmt : public Stmt { + friend class ASTReader; + friend class ASTStmtReader; + SourceLocation Loc; - Stmt *Children[2]; + Stmt *Children[2]; enum { FILTER_EXPR, BLOCK }; - SEHExceptStmt(SourceLocation Loc, - Expr *FilterExpr, - Stmt *Block); - - friend class ASTReader; - friend class ASTStmtReader; - explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { } + SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block); + explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) {} public: static SEHExceptStmt* Create(const ASTContext &C, @@ -1908,19 +1932,17 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHExceptStmtClass; } - }; class SEHFinallyStmt : public Stmt { - SourceLocation Loc; - Stmt *Block; - - SEHFinallyStmt(SourceLocation Loc, - Stmt *Block); - friend class ASTReader; friend class ASTStmtReader; - explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { } + + SourceLocation Loc; + Stmt *Block; + + SEHFinallyStmt(SourceLocation Loc, Stmt *Block); + explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) {} public: static SEHFinallyStmt* Create(const ASTContext &C, @@ -1942,13 +1964,15 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHFinallyStmtClass; } - }; class SEHTryStmt : public Stmt { - bool IsCXXTry; + friend class ASTReader; + friend class ASTStmtReader; + + bool IsCXXTry; SourceLocation TryLoc; - Stmt *Children[2]; + Stmt *Children[2]; enum { TRY = 0, HANDLER = 1 }; @@ -1957,9 +1981,7 @@ class SEHTryStmt : public Stmt { Stmt *TryBlock, Stmt *Handler); - friend class ASTReader; - friend class ASTStmtReader; - explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } + explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) {} public: static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry, @@ -1994,15 +2016,15 @@ public: }; /// Represents a __leave statement. -/// class SEHLeaveStmt : public Stmt { SourceLocation LeaveLoc; + public: explicit SEHLeaveStmt(SourceLocation LL) : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {} /// \brief Build an empty __leave statement. - explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { } + explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) {} SourceLocation getLeaveLoc() const { return LeaveLoc; } void setLeaveLoc(SourceLocation L) { LeaveLoc = L; } @@ -2047,6 +2069,8 @@ public: SourceLocation Loc; public: + friend class ASTStmtReader; + /// \brief Create a new capture. /// /// \param Loc The source location associated with this capture. @@ -2054,7 +2078,6 @@ public: /// \param Kind The kind of capture (this, ByRef, ...). /// /// \param Var The variable being captured, or null if capturing this. - /// Capture(SourceLocation Loc, VariableCaptureKind Kind, VarDecl *Var = nullptr); @@ -2086,8 +2109,6 @@ public: /// /// This operation is only valid if this capture captures a variable. VarDecl *getCapturedVar() const; - - friend class ASTStmtReader; }; private: @@ -2099,7 +2120,7 @@ private: llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind; /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl. - RecordDecl *TheRecordDecl; + RecordDecl *TheRecordDecl = nullptr; /// \brief Construct a captured statement. CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures, @@ -2119,6 +2140,8 @@ private: void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; } public: + friend class ASTStmtReader; + static CapturedStmt *Create(const ASTContext &Context, Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures, @@ -2158,10 +2181,10 @@ public: bool capturesVariable(const VarDecl *Var) const; /// \brief An iterator that walks over the captures. - typedef Capture *capture_iterator; - typedef const Capture *const_capture_iterator; - typedef llvm::iterator_range<capture_iterator> capture_range; - typedef llvm::iterator_range<const_capture_iterator> capture_const_range; + using capture_iterator = Capture *; + using const_capture_iterator = const Capture *; + using capture_range = llvm::iterator_range<capture_iterator>; + using capture_const_range = llvm::iterator_range<const_capture_iterator>; capture_range captures() { return capture_range(capture_begin(), capture_end()); @@ -2184,14 +2207,14 @@ public: unsigned capture_size() const { return NumCaptures; } /// \brief Iterator that walks over the capture initialization arguments. - typedef Expr **capture_init_iterator; - typedef llvm::iterator_range<capture_init_iterator> capture_init_range; + using capture_init_iterator = Expr **; + using capture_init_range = llvm::iterator_range<capture_init_iterator>; /// \brief Const iterator that walks over the capture initialization /// arguments. - typedef Expr *const *const_capture_init_iterator; - typedef llvm::iterator_range<const_capture_init_iterator> - const_capture_init_range; + using const_capture_init_iterator = Expr *const *; + using const_capture_init_range = + llvm::iterator_range<const_capture_init_iterator>; capture_init_range capture_inits() { return capture_init_range(capture_init_begin(), capture_init_end()); @@ -2223,9 +2246,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return getCapturedStmt()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getCapturedStmt()->getLocEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return getCapturedStmt()->getSourceRange(); } @@ -2235,10 +2260,8 @@ public: } child_range children(); - - friend class ASTStmtReader; }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_STMT_H diff --git a/include/clang/AST/StmtDataCollectors.td b/include/clang/AST/StmtDataCollectors.td new file mode 100644 index 000000000000..bf5f8c21707f --- /dev/null +++ b/include/clang/AST/StmtDataCollectors.td @@ -0,0 +1,242 @@ +class Stmt { + code Code = [{ + addData(S->getStmtClass()); + // This ensures that non-macro-generated code isn't identical to + // macro-generated code. + addData(data_collection::getMacroStack(S->getLocStart(), Context)); + addData(data_collection::getMacroStack(S->getLocEnd(), Context)); + }]; +} + +class Expr { + code Code = [{ + addData(S->getType()); + }]; +} + +//--- Builtin functionality ----------------------------------------------// +class ArrayTypeTraitExpr { + code Code = [{ + addData(S->getTrait()); + }]; +} +class ExpressionTraitExpr { + code Code = [{ + addData(S->getTrait()); + }]; +} +class PredefinedExpr { + code Code = [{ + addData(S->getIdentType()); + }]; +} +class TypeTraitExpr { + code Code = [{ + addData(S->getTrait()); + for (unsigned i = 0; i < S->getNumArgs(); ++i) + addData(S->getArg(i)->getType()); + }]; +} + +//--- Calls --------------------------------------------------------------// +class CallExpr { + code Code = [{ + // Function pointers don't have a callee and we just skip hashing it. + if (const FunctionDecl *D = S->getDirectCallee()) { + // If the function is a template specialization, we also need to handle + // the template arguments as they are not included in the qualified name. + if (auto Args = D->getTemplateSpecializationArgs()) { + std::string ArgString; + + // Print all template arguments into ArgString + llvm::raw_string_ostream OS(ArgString); + for (unsigned i = 0; i < Args->size(); ++i) { + Args->get(i).print(Context.getLangOpts(), OS); + // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'. + OS << '\n'; + } + OS.flush(); + + addData(ArgString); + } + addData(D->getQualifiedNameAsString()); + } + }]; +} + +//--- Value references ---------------------------------------------------// +class DeclRefExpr { + code Code = [{ + addData(S->getDecl()->getQualifiedNameAsString()); + }]; +} +class MemberExpr { + code Code = [{ + addData(S->getMemberDecl()->getName()); + }]; +} + +//--- Literals -----------------------------------------------------------// +class IntegerLiteral { + code Code = [{ + addData(llvm::hash_value(S->getValue())); + }]; +} +class FloatingLiteral { + code Code = [{ + addData(llvm::hash_value(S->getValue())); + }]; +} +class StringLiteral { + code Code = [{ + addData(S->getString()); +}]; +} +class CXXBoolLiteralExpr { + code Code = [{ + addData(S->getValue()); + }]; +} +class CharacterLiteral { + code Code = [{ + addData(S->getValue()); + }]; +} + +//--- Exceptions ---------------------------------------------------------// +class CXXCatchStmt { + code Code = [{ + addData(S->getCaughtType()); + }]; +} + +//--- C++ OOP Stmts ------------------------------------------------------// +class CXXDeleteExpr { + code Code = [{ + addData(S->isArrayFormAsWritten()); addData(S->isGlobalDelete()); + }]; +} + +//--- Casts --------------------------------------------------------------// +class ObjCBridgedCastExpr { + code Code = [{ + addData(S->getBridgeKind()); + }]; +} + +//--- Miscellaneous Exprs ------------------------------------------------// +class BinaryOperator { + code Code = [{ + addData(S->getOpcode()); + }]; +} +class UnaryOperator { + code Code = [{ + addData(S->getOpcode()); + }]; +} + +//--- Control flow -------------------------------------------------------// +class GotoStmt { + code Code = [{ + addData(S->getLabel()->getName()); + }]; +} +class IndirectGotoStmt { + code Code = [{ + if (S->getConstantTarget()) + addData(S->getConstantTarget()->getName()); + }]; +} +class LabelStmt { + code Code = [{ + addData(S->getDecl()->getName()); + }]; +} +class MSDependentExistsStmt { + code Code = [{ + addData(S->isIfExists()); + }]; +} +class AddrLabelExpr { + code Code = [{ + addData(S->getLabel()->getName()); + }]; +} + +//--- Objective-C --------------------------------------------------------// +class ObjCIndirectCopyRestoreExpr { + code Code = [{ + addData(S->shouldCopy()); + }]; +} +class ObjCPropertyRefExpr { + code Code = [{ + addData(S->isSuperReceiver()); addData(S->isImplicitProperty()); + }]; +} +class ObjCAtCatchStmt { + code Code = [{ + addData(S->hasEllipsis()); + }]; +} + +//--- Miscellaneous Stmts ------------------------------------------------// +class CXXFoldExpr { + code Code = [{ + addData(S->isRightFold()); addData(S->getOperator()); + }]; +} +class GenericSelectionExpr { + code Code = [{ + for (unsigned i = 0; i < S->getNumAssocs(); ++i) { + addData(S->getAssocType(i)); + } + }]; +} +class LambdaExpr { + code Code = [{ + for (const LambdaCapture &C : S->captures()) { + addData(C.isPackExpansion()); + addData(C.getCaptureKind()); + if (C.capturesVariable()) + addData(C.getCapturedVar()->getType()); + } + addData(S->isGenericLambda()); + addData(S->isMutable()); + }]; +} +class DeclStmt { + code Code = [{ + auto numDecls = std::distance(S->decl_begin(), S->decl_end()); + addData(static_cast<unsigned>(numDecls)); + for (const Decl *D : S->decls()) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + addData(VD->getType()); + } + } + }]; +} +class AsmStmt { + code Code = [{ + addData(S->isSimple()); + addData(S->isVolatile()); + addData(S->generateAsmString(Context)); + for (unsigned i = 0; i < S->getNumInputs(); ++i) { + addData(S->getInputConstraint(i)); + } + for (unsigned i = 0; i < S->getNumOutputs(); ++i) { + addData(S->getOutputConstraint(i)); + } + for (unsigned i = 0; i < S->getNumClobbers(); ++i) { + addData(S->getClobber(i)); + } + }]; +} +class AttributedStmt { + code Code = [{ + for (const Attr *A : S->getAttrs()) { + addData(std::string(A->getSpelling())); + } + }]; +} diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h index 92eb64430f73..02c77b242c7c 100644 --- a/include/clang/AST/StmtGraphTraits.h +++ b/include/clang/AST/StmtGraphTraits.h @@ -1,4 +1,4 @@ -//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- C++ -*-===// +//===- StmtGraphTraits.h - Graph Traits for the class Stmt ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,13 +21,10 @@ namespace llvm { -//template <typename T> struct GraphTraits; - - -template <> struct GraphTraits<clang::Stmt*> { - typedef clang::Stmt * NodeRef; - typedef clang::Stmt::child_iterator ChildIteratorType; - typedef llvm::df_iterator<clang::Stmt*> nodes_iterator; +template <> struct GraphTraits<clang::Stmt *> { + using NodeRef = clang::Stmt *; + using ChildIteratorType = clang::Stmt::child_iterator; + using nodes_iterator = llvm::df_iterator<clang::Stmt *>; static NodeRef getEntryNode(clang::Stmt *S) { return S; } @@ -50,11 +47,10 @@ template <> struct GraphTraits<clang::Stmt*> { } }; - -template <> struct GraphTraits<const clang::Stmt*> { - typedef const clang::Stmt * NodeRef; - typedef clang::Stmt::const_child_iterator ChildIteratorType; - typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator; +template <> struct GraphTraits<const clang::Stmt *> { + using NodeRef = const clang::Stmt *; + using ChildIteratorType = clang::Stmt::const_child_iterator; + using nodes_iterator = llvm::df_iterator<const clang::Stmt *>; static NodeRef getEntryNode(const clang::Stmt *S) { return S; } @@ -77,7 +73,6 @@ template <> struct GraphTraits<const clang::Stmt*> { } }; +} // namespace llvm -} // end namespace llvm - -#endif +#endif // LLVM_CLANG_AST_STMTGRAPHTRAITS_H diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 5d3bce8d83ba..33aab08bbb71 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -1,4 +1,4 @@ -//===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===// +//===- StmtIterator.h - Iterators for Statements ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,31 +14,38 @@ #ifndef LLVM_CLANG_AST_STMTITERATOR_H #define LLVM_CLANG_AST_STMTITERATOR_H -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" #include <cassert> #include <cstddef> +#include <cstdint> #include <iterator> -#include <utility> namespace clang { -class Stmt; class Decl; +class Stmt; class VariableArrayType; class StmtIteratorBase { protected: - enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2, - Flags = 0x3 }; + enum { + StmtMode = 0x0, + SizeOfTypeVAMode = 0x1, + DeclGroupMode = 0x2, + Flags = 0x3 + }; union { Stmt **stmt; Decl **DGI; }; - uintptr_t RawVAPtr; + uintptr_t RawVAPtr = 0; Decl **DGE; + StmtIteratorBase(Stmt **s) : stmt(s) {} + StmtIteratorBase(const VariableArrayType *t); + StmtIteratorBase(Decl **dgi, Decl **dge); + StmtIteratorBase() : stmt(nullptr) {} + bool inDeclGroup() const { return (RawVAPtr & Flags) == DeclGroupMode; } @@ -56,7 +63,7 @@ protected: } void setVAPtr(const VariableArrayType *P) { - assert (inDeclGroup() || inSizeOfTypeVA()); + assert(inDeclGroup() || inSizeOfTypeVA()); RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags); } @@ -65,14 +72,8 @@ protected: void NextVA(); Stmt*& GetDeclExpr() const; - - StmtIteratorBase(Stmt **s) : stmt(s), RawVAPtr(0) {} - StmtIteratorBase(const VariableArrayType *t); - StmtIteratorBase(Decl **dgi, Decl **dge); - StmtIteratorBase() : stmt(nullptr), RawVAPtr(0) {} }; - template <typename DERIVED, typename REFERENCE> class StmtIteratorImpl : public StmtIteratorBase, public std::iterator<std::forward_iterator_tag, @@ -80,8 +81,9 @@ class StmtIteratorImpl : public StmtIteratorBase, REFERENCE, REFERENCE> { protected: StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {} + public: - StmtIteratorImpl() {} + StmtIteratorImpl() = default; StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {} StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {} StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {} @@ -120,16 +122,13 @@ public: struct ConstStmtIterator; -struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { - explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {} - - StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {} - +struct StmtIterator : public StmtIteratorImpl<StmtIterator, Stmt*&> { + explicit StmtIterator() = default; + StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator, Stmt*&>(S) {} StmtIterator(Decl** dgi, Decl** dge) - : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {} - + : StmtIteratorImpl<StmtIterator, Stmt*&>(dgi, dge) {} StmtIterator(const VariableArrayType *t) - : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} + : StmtIteratorImpl<StmtIterator, Stmt*&>(t) {} private: StmtIterator(const StmtIteratorBase &RHS) @@ -141,11 +140,9 @@ private: struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, const Stmt*> { - explicit ConstStmtIterator() : - StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {} - - ConstStmtIterator(const StmtIterator& RHS) : - StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} + explicit ConstStmtIterator() = default; + ConstStmtIterator(const StmtIterator& RHS) + : StmtIteratorImpl<ConstStmtIterator, const Stmt*>(RHS) {} ConstStmtIterator(Stmt * const *S) : StmtIteratorImpl<ConstStmtIterator, const Stmt *>( @@ -155,6 +152,7 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, inline StmtIterator cast_away_const(const ConstStmtIterator &RHS) { return RHS; } -} // end namespace clang -#endif +} // namespace clang + +#endif // LLVM_CLANG_AST_STMTITERATOR_H diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 09dd87fdc8bc..66fb037fc33c 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -899,7 +899,9 @@ public: } const Stmt *getBody() const { // This relies on the loop form is already checked by Sema. - Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); + const Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); + while(const auto *CS = dyn_cast<CapturedStmt>(Body)) + Body = CS->getCapturedStmt(); Body = cast<ForStmt>(Body)->getBody(); for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { Body = Body->IgnoreContainers(); @@ -955,8 +957,15 @@ public: T->getStmtClass() == OMPTargetSimdDirectiveClass || T->getStmtClass() == OMPTeamsDistributeDirectiveClass || T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass || - T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass || - T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass; + T->getStmtClass() == + OMPTeamsDistributeParallelForSimdDirectiveClass || + T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass || + T->getStmtClass() == + OMPTargetTeamsDistributeParallelForDirectiveClass || + T->getStmtClass() == + OMPTargetTeamsDistributeParallelForSimdDirectiveClass || + T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass || + T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass; } }; @@ -1912,7 +1921,7 @@ class OMPTaskgroupDirective : public OMPExecutableDirective { OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned NumClauses) : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, - StartLoc, EndLoc, NumClauses, 1) {} + StartLoc, EndLoc, NumClauses, 2) {} /// Build an empty directive. /// \param NumClauses Number of clauses. @@ -1920,7 +1929,12 @@ class OMPTaskgroupDirective : public OMPExecutableDirective { explicit OMPTaskgroupDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup, SourceLocation(), SourceLocation(), NumClauses, - 1) {} + 2) {} + + /// Sets the task_reduction return variable. + void setReductionRef(Expr *RR) { + *std::next(child_begin(), 1) = RR; + } public: /// Creates directive. @@ -1930,10 +1944,12 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param ReductionRef Reference to the task_reduction return variable. /// static OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, + Expr *ReductionRef); /// Creates an empty directive. /// @@ -1943,6 +1959,15 @@ public: static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + + /// Returns reference to the task_reduction return variable. + const Expr *getReductionRef() const { + return static_cast<const Expr *>(*std::next(child_begin(), 1)); + } + Expr *getReductionRef() { + return static_cast<Expr *>(*std::next(child_begin(), 1)); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPTaskgroupDirectiveClass; } @@ -2330,7 +2355,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective { unsigned NumClauses) : OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass, OMPD_target_enter_data, StartLoc, EndLoc, - NumClauses, /*NumChildren=*/0) {} + NumClauses, /*NumChildren=*/1) {} /// \brief Build an empty directive. /// @@ -2340,7 +2365,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass, OMPD_target_enter_data, SourceLocation(), SourceLocation(), NumClauses, - /*NumChildren=*/0) {} + /*NumChildren=*/1) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -2349,11 +2374,11 @@ public: /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. /// - static OMPTargetEnterDataDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses); + static OMPTargetEnterDataDirective * + 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. /// @@ -2389,7 +2414,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective { unsigned NumClauses) : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass, OMPD_target_exit_data, StartLoc, EndLoc, - NumClauses, /*NumChildren=*/0) {} + NumClauses, /*NumChildren=*/1) {} /// \brief Build an empty directive. /// @@ -2399,7 +2424,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass, OMPD_target_exit_data, SourceLocation(), SourceLocation(), NumClauses, - /*NumChildren=*/0) {} + /*NumChildren=*/1) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -2408,11 +2433,11 @@ public: /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. /// - static OMPTargetExitDataDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses); + static OMPTargetExitDataDirective * + 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. /// @@ -2966,7 +2991,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective { unsigned NumClauses) : OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass, OMPD_target_update, StartLoc, EndLoc, NumClauses, - 0) {} + 1) {} /// \brief Build an empty directive. /// @@ -2975,7 +3000,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective { explicit OMPTargetUpdateDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass, OMPD_target_update, SourceLocation(), - SourceLocation(), NumClauses, 0) {} + SourceLocation(), NumClauses, 1) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -2984,11 +3009,11 @@ public: /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. /// - static OMPTargetUpdateDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses); + static OMPTargetUpdateDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); /// \brief Creates an empty directive with the place for \a NumClauses /// clauses. @@ -3015,6 +3040,8 @@ public: /// class OMPDistributeParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; + /// true if the construct has inner cancel directive. + bool HasCancel = false; /// \brief Build directive with the given start and end location. /// @@ -3028,7 +3055,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective { unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass, OMPD_distribute_parallel_for, StartLoc, EndLoc, - CollapsedNum, NumClauses) {} + CollapsedNum, NumClauses), HasCancel(false) {} /// \brief Build an empty directive. /// @@ -3039,7 +3066,11 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective { unsigned NumClauses) : OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass, OMPD_distribute_parallel_for, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses) {} + SourceLocation(), CollapsedNum, NumClauses), + HasCancel(false) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// \brief Creates directive with a list of \a Clauses. @@ -3051,11 +3082,12 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -3069,6 +3101,9 @@ public: unsigned CollapsedNum, EmptyShell); + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPDistributeParallelForDirectiveClass; } @@ -3565,6 +3600,8 @@ public: /// class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective { friend class ASTStmtReader; + /// true if the construct has inner cancel directive. + bool HasCancel = false; /// Build directive with the given start and end location. /// @@ -3579,7 +3616,7 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective { unsigned NumClauses) : OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass, OMPD_teams_distribute_parallel_for, StartLoc, EndLoc, - CollapsedNum, NumClauses) {} + CollapsedNum, NumClauses), HasCancel(false) {} /// Build an empty directive. /// @@ -3590,7 +3627,11 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective { unsigned NumClauses) : OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass, OMPD_teams_distribute_parallel_for, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses) {} + SourceLocation(), CollapsedNum, NumClauses), + HasCancel(false) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// Creates directive with a list of \a Clauses. @@ -3602,11 +3643,12 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); /// Creates an empty directive with the place for \a NumClauses clauses. /// @@ -3618,6 +3660,9 @@ public: CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass; } @@ -3761,6 +3806,8 @@ public: class OMPTargetTeamsDistributeParallelForDirective final : public OMPLoopDirective { friend class ASTStmtReader; + /// true if the construct has inner cancel directive. + bool HasCancel = false; /// Build directive with the given start and end location. /// @@ -3776,7 +3823,8 @@ class OMPTargetTeamsDistributeParallelForDirective final : OMPLoopDirective(this, OMPTargetTeamsDistributeParallelForDirectiveClass, OMPD_target_teams_distribute_parallel_for, StartLoc, - EndLoc, CollapsedNum, NumClauses) {} + EndLoc, CollapsedNum, NumClauses), + HasCancel(false) {} /// Build an empty directive. /// @@ -3788,7 +3836,11 @@ class OMPTargetTeamsDistributeParallelForDirective final : OMPLoopDirective( this, OMPTargetTeamsDistributeParallelForDirectiveClass, OMPD_target_teams_distribute_parallel_for, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses) {} + SourceLocation(), CollapsedNum, NumClauses), + HasCancel(false) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// Creates directive with a list of \a Clauses. @@ -3800,11 +3852,12 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); /// Creates an empty directive with the place for \a NumClauses clauses. /// @@ -3816,6 +3869,9 @@ public: CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPTargetTeamsDistributeParallelForDirectiveClass; diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index df4a2d8bc3d7..98fa11327406 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -1,4 +1,4 @@ -//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===// +//===- StmtVisitor.h - Visitor for Stmt subclasses --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,28 +17,33 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/LLVM.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <utility> namespace clang { -template <typename T> struct make_ptr { typedef T *type; }; -template <typename T> struct make_const_ptr { typedef const T *type; }; +template <typename T> struct make_ptr { using type = T *; }; +template <typename T> struct make_const_ptr { using type = const T *; }; /// StmtVisitorBase - This class implements a simple visitor for Stmt /// subclasses. Since Expr derives from Stmt, this also includes support for /// visiting Exprs. -template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> +template<template <typename> class Ptr, typename ImplClass, typename RetTy=void, + class... ParamTys> class StmtVisitorBase { public: - #define PTR(CLASS) typename Ptr<CLASS>::type #define DISPATCH(NAME, CLASS) \ - return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<PTR(CLASS)>(S)) - - RetTy Visit(PTR(Stmt) S) { + return static_cast<ImplClass*>(this)->Visit ## NAME( \ + static_cast<PTR(CLASS)>(S), std::forward<ParamTys>(P)...) + RetTy Visit(PTR(Stmt) S, ParamTys... P) { // If we have a binary expr, dispatch to the subcode of the binop. A smart // optimizer (e.g. LLVM) will fold this comparison into the switch stmt // below. @@ -60,6 +65,7 @@ public: case BO_GE: DISPATCH(BinGE, BinaryOperator); case BO_EQ: DISPATCH(BinEQ, BinaryOperator); case BO_NE: DISPATCH(BinNE, BinaryOperator); + case BO_Cmp: DISPATCH(BinCmp, BinaryOperator); case BO_And: DISPATCH(BinAnd, BinaryOperator); case BO_Xor: DISPATCH(BinXor, BinaryOperator); @@ -111,13 +117,13 @@ public: // If the implementation chooses not to implement a certain visit method, fall // back on VisitExpr or whatever else is the superclass. #define STMT(CLASS, PARENT) \ - RetTy Visit ## CLASS(PTR(CLASS) S) { DISPATCH(PARENT, PARENT); } + RetTy Visit ## CLASS(PTR(CLASS) S, ParamTys... P) { DISPATCH(PARENT, PARENT); } #include "clang/AST/StmtNodes.inc" // If the implementation doesn't implement binary operator methods, fall back // on VisitBinaryOperator. #define BINOP_FALLBACK(NAME) \ - RetTy VisitBin ## NAME(PTR(BinaryOperator) S) { \ + RetTy VisitBin ## NAME(PTR(BinaryOperator) S, ParamTys... P) { \ DISPATCH(BinaryOperator, BinaryOperator); \ } BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) @@ -127,6 +133,8 @@ public: BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) + BINOP_FALLBACK(Cmp) + BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) @@ -137,7 +145,7 @@ public: // If the implementation doesn't implement compound assignment operator // methods, fall back on VisitCompoundAssignOperator. #define CAO_FALLBACK(NAME) \ - RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S) { \ + RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S, ParamTys... P) { \ DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \ } CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) @@ -149,7 +157,7 @@ public: // If the implementation doesn't implement unary operator methods, fall back // on VisitUnaryOperator. #define UNARYOP_FALLBACK(NAME) \ - RetTy VisitUnary ## NAME(PTR(UnaryOperator) S) { \ + RetTy VisitUnary ## NAME(PTR(UnaryOperator) S, ParamTys... P) { \ DISPATCH(UnaryOperator, UnaryOperator); \ } UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) @@ -163,7 +171,7 @@ public: #undef UNARYOP_FALLBACK // Base case, ignore it. :) - RetTy VisitStmt(PTR(Stmt) Node) { return RetTy(); } + RetTy VisitStmt(PTR(Stmt) Node, ParamTys... P) { return RetTy(); } #undef PTR #undef DISPATCH @@ -174,18 +182,18 @@ public: /// /// This class does not preserve constness of Stmt pointers (see also /// ConstStmtVisitor). -template<typename ImplClass, typename RetTy=void> +template<typename ImplClass, typename RetTy=void, typename... ParamTys> class StmtVisitor - : public StmtVisitorBase<make_ptr, ImplClass, RetTy> {}; + : public StmtVisitorBase<make_ptr, ImplClass, RetTy, ParamTys...> {}; /// ConstStmtVisitor - This class implements a simple visitor for Stmt /// subclasses. Since Expr derives from Stmt, this also includes support for /// visiting Exprs. /// /// This class preserves constness of Stmt pointers (see also StmtVisitor). -template<typename ImplClass, typename RetTy=void> +template<typename ImplClass, typename RetTy=void, typename... ParamTys> class ConstStmtVisitor - : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {}; + : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy, ParamTys...> {}; /// \brief This class implements a simple visitor for OMPClause /// subclasses. @@ -222,6 +230,6 @@ template<class ImplClass, typename RetTy = void> class ConstOMPClauseVisitor : public OMPClauseVisitorBase <ImplClass, make_const_ptr, RetTy> {}; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_STMTVISITOR_H diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 84fbcda6e087..850250b9c0a2 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -1,4 +1,4 @@ -//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===// +//===- TemplateBase.h - Core classes for C++ templates ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,21 +15,32 @@ #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H #define LLVM_CLANG_AST_TEMPLATEBASE_H +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TrailingObjects.h" +#include <cassert> +#include <cstddef> +#include <cstdint> namespace llvm { - class FoldingSetNodeID; -} + +class FoldingSetNodeID; + +} // namespace llvm namespace clang { +class ASTContext; class DiagnosticBuilder; class Expr; struct PrintingPolicy; @@ -44,29 +55,37 @@ public: /// \brief Represents an empty template argument, e.g., one that has not /// been deduced. Null = 0, + /// The template argument is a type. Type, + /// The template argument is a declaration that was provided for a pointer, /// reference, or pointer to member non-type template parameter. Declaration, + /// The template argument is a null pointer or null pointer to member that /// was provided for a non-type template parameter. NullPtr, + /// The template argument is an integral value stored in an llvm::APSInt /// that was provided for an integral non-type template parameter. Integral, + /// The template argument is a template name that was provided for a /// template template parameter. Template, + /// The template argument is a pack expansion of a template name that was /// provided for a template template parameter. TemplateExpansion, + /// The template argument is an expression, and we've not resolved it to one /// of the other forms yet, either because it's dependent or because we're /// representing a non-canonical template argument (for instance, in a /// TemplateSpecializationType). Also used to represent a non-dependent /// __uuidof expression (a Microsoft extension). Expression, + /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. Pack @@ -88,8 +107,11 @@ private: unsigned BitWidth : 31; unsigned IsUnsigned : 1; union { - uint64_t VAL; ///< Used to store the <= 64 bits integer value. - const uint64_t *pVal; ///< Used to store the >64 bits integer value. + /// Used to store the <= 64 bits integer value. + uint64_t VAL; + + /// Used to store the >64 bits integer value. + const uint64_t *pVal; }; void *Type; }; @@ -115,8 +137,6 @@ private: struct TV TypeOrValue; }; - TemplateArgument(TemplateName, bool) = delete; - public: /// \brief Construct an empty, invalid template argument. constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} @@ -202,6 +222,8 @@ public: this->Args.NumArgs = Args.size(); } + TemplateArgument(TemplateName, bool) = delete; + static TemplateArgument getEmptyPack() { return TemplateArgument(None); } /// \brief Create a new template argument pack by copying the given set of @@ -278,7 +300,9 @@ public: // FIXME: Provide a way to read the integral data without copying the value. llvm::APSInt getAsIntegral() const { assert(getKind() == Integral && "Unexpected kind"); + using namespace llvm; + if (Integer.BitWidth <= 64) return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); @@ -309,7 +333,7 @@ public: } /// \brief Iterator that traverses the elements of a template argument pack. - typedef const TemplateArgument * pack_iterator; + using pack_iterator = const TemplateArgument *; /// \brief Iterator referencing the first argument of a template argument /// pack. @@ -368,7 +392,6 @@ public: /// Location information for a TemplateArgument. struct TemplateArgumentLocInfo { private: - struct T { // FIXME: We'd like to just use the qualifier in the TemplateName, // but template arguments get canonicalized too quickly. @@ -393,8 +416,7 @@ public: TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, - SourceLocation EllipsisLoc) - { + SourceLocation EllipsisLoc) { Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); Template.QualifierLocData = QualifierLoc.getOpaqueData(); Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); @@ -434,16 +456,15 @@ public: TemplateArgumentLoc(const TemplateArgument &Argument, TemplateArgumentLocInfo Opaque) - : Argument(Argument), LocInfo(Opaque) { - } + : Argument(Argument), LocInfo(Opaque) {} TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) - : Argument(Argument), LocInfo(TInfo) { + : Argument(Argument), LocInfo(TInfo) { assert(Argument.getKind() == TemplateArgument::Type); } TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E) - : Argument(Argument), LocInfo(E) { + : Argument(Argument), LocInfo(E) { assert(Argument.getKind() == TemplateArgument::Expression); } @@ -451,7 +472,8 @@ public: NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc = SourceLocation()) - : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { + : Argument(Argument), + LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); } @@ -526,16 +548,16 @@ class TemplateArgumentListInfo { SourceLocation LAngleLoc; SourceLocation RAngleLoc; - // This can leak if used in an AST node, use ASTTemplateArgumentListInfo - // instead. - void *operator new(size_t bytes, ASTContext &C) = delete; - public: - TemplateArgumentListInfo() {} + TemplateArgumentListInfo() = default; TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc) - : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} + : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} + + // This can leak if used in an AST node, use ASTTemplateArgumentListInfo + // instead. + void *operator new(size_t bytes, ASTContext &C) = delete; SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } @@ -574,8 +596,8 @@ struct ASTTemplateArgumentListInfo final : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, TemplateArgumentLoc> { private: - friend TrailingObjects; friend class ASTNodeImporter; + friend TrailingObjects; ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); @@ -668,6 +690,6 @@ inline const TemplateArgument & return getArgs()[Idx]; } -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_TEMPLATEBASE_H diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index bf4d008ee807..fb33cf58d796 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -1,4 +1,4 @@ -//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===// +//===- TemplateName.h - C++ Template Name Representation --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,10 +14,12 @@ #ifndef LLVM_CLANG_AST_TEMPLATENAME_H #define LLVM_CLANG_AST_TEMPLATENAME_H -#include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> namespace clang { @@ -94,7 +96,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage { friend class ASTContext; OverloadedTemplateStorage(unsigned size) - : UncommonTemplateNameStorage(Overloaded, size) { } + : UncommonTemplateNameStorage(Overloaded, size) {} NamedDecl **getStorage() { return reinterpret_cast<NamedDecl **>(this + 1); @@ -104,7 +106,7 @@ class OverloadedTemplateStorage : public UncommonTemplateNameStorage { } public: - typedef NamedDecl *const *iterator; + using iterator = NamedDecl *const *; iterator begin() const { return getStorage(); } iterator end() const { return getStorage() + size(); } @@ -126,8 +128,8 @@ public: SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter, unsigned Size, const TemplateArgument *Arguments) - : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), - Parameter(Parameter), Arguments(Arguments) { } + : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), + Parameter(Parameter), Arguments(Arguments) {} /// \brief Retrieve the template template parameter pack being substituted. TemplateTemplateParmDecl *getParameterPack() const { @@ -174,10 +176,9 @@ public: /// specifier in the typedef. "apply" is a nested template, and can /// only be understood in the context of class TemplateName { - typedef llvm::PointerUnion4<TemplateDecl *, - UncommonTemplateNameStorage *, - QualifiedTemplateName *, - DependentTemplateName *> StorageType; + using StorageType = + llvm::PointerUnion4<TemplateDecl *, UncommonTemplateNameStorage *, + QualifiedTemplateName *, DependentTemplateName *>; StorageType Storage; @@ -188,24 +189,29 @@ public: enum NameKind { /// \brief A single template declaration. Template, + /// \brief A set of overloaded template declarations. OverloadedTemplate, + /// \brief 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 /// template (or set of templates). DependentTemplate, + /// \brief 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 argument pack, but has not yet been expanded into /// individual arguments. SubstTemplateTemplateParmPack }; - TemplateName() : Storage() { } + TemplateName() = default; explicit TemplateName(TemplateDecl *Template); explicit TemplateName(OverloadedTemplateStorage *Storage); explicit TemplateName(SubstTemplateTemplateParmStorage *Storage); @@ -262,6 +268,11 @@ public: TemplateName getUnderlying() const; + /// Get the template name to substitute when this template name is used as a + /// template template argument. This refers to the most recent declaration of + /// the template, including any default template arguments. + TemplateName getNameToSubstitute() const; + /// \brief Determines whether this is a dependent template name. bool isDependent() const; @@ -320,8 +331,8 @@ class SubstTemplateTemplateParmStorage SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter, TemplateName replacement) - : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), - Parameter(parameter), Replacement(replacement) {} + : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), + Parameter(parameter), Replacement(replacement) {} public: TemplateTemplateParmDecl *getParameter() const { return Parameter; } @@ -353,6 +364,8 @@ inline TemplateName TemplateName::getUnderlying() const { /// manner, it is to TemplateName what ElaboratedType is to Type, /// providing extra syntactic sugar for downstream clients. class QualifiedTemplateName : public llvm::FoldingSetNode { + friend class ASTContext; + /// \brief The nested name specifier that qualifies the template name. /// /// The bit is used to indicate whether the "template" keyword was @@ -366,12 +379,9 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// that this qualified name refers to. TemplateDecl *Template; - friend class ASTContext; - QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template) - : Qualifier(NNS, TemplateKeyword? 1 : 0), - Template(Template) { } + : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {} public: /// \brief Return the nested name specifier that qualifies this name. @@ -410,6 +420,8 @@ public: /// where "MetaFun::" is the nested name specifier and "apply" is the /// template name referenced. The "template" keyword is implied. class DependentTemplateName : public llvm::FoldingSetNode { + friend class ASTContext; + /// \brief The nested name specifier that qualifies the template /// name. /// @@ -439,29 +451,27 @@ class DependentTemplateName : public llvm::FoldingSetNode { /// canonical. TemplateName CanonicalTemplateName; - friend class ASTContext; - DependentTemplateName(NestedNameSpecifier *Qualifier, const IdentifierInfo *Identifier) - : Qualifier(Qualifier, false), Identifier(Identifier), - CanonicalTemplateName(this) { } + : Qualifier(Qualifier, false), Identifier(Identifier), + CanonicalTemplateName(this) {} DependentTemplateName(NestedNameSpecifier *Qualifier, const IdentifierInfo *Identifier, TemplateName Canon) - : Qualifier(Qualifier, false), Identifier(Identifier), - CanonicalTemplateName(Canon) { } + : Qualifier(Qualifier, false), Identifier(Identifier), + CanonicalTemplateName(Canon) {} DependentTemplateName(NestedNameSpecifier *Qualifier, OverloadedOperatorKind Operator) - : Qualifier(Qualifier, true), Operator(Operator), - CanonicalTemplateName(this) { } + : Qualifier(Qualifier, true), Operator(Operator), + CanonicalTemplateName(this) {} DependentTemplateName(NestedNameSpecifier *Qualifier, OverloadedOperatorKind Operator, TemplateName Canon) - : Qualifier(Qualifier, true), Operator(Operator), - CanonicalTemplateName(Canon) { } + : Qualifier(Qualifier, true), Operator(Operator), + CanonicalTemplateName(Canon) {} public: /// \brief Return the nested name specifier that qualifies this name. @@ -509,14 +519,13 @@ public: } }; -} // end namespace clang. +} // namespace clang. namespace llvm { /// \brief The clang::TemplateName class is effectively a pointer. template<> -class PointerLikeTypeTraits<clang::TemplateName> { -public: +struct PointerLikeTypeTraits<clang::TemplateName> { static inline void *getAsVoidPointer(clang::TemplateName TN) { return TN.getAsVoidPointer(); } @@ -529,6 +538,6 @@ public: enum { NumLowBitsAvailable = 0 }; }; -} // end namespace llvm. +} // namespace llvm. -#endif +#endif // LLVM_CLANG_AST_TEMPLATENAME_H diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 984096ffa987..7247838947a2 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1,4 +1,4 @@ -//===--- Type.h - C Language Family Type Representation ---------*- C++ -*-===// +//===- Type.h - C Language Family Type Representation -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,12 +6,13 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// /// \file /// \brief C Language Family Type Representation /// /// This file defines the clang::Type interface and subclasses, used to /// represent types for languages in the C family. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_TYPE_H @@ -25,85 +26,118 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <string> +#include <type_traits> +#include <utility> namespace clang { - enum { - TypeAlignmentInBits = 4, - TypeAlignment = 1 << TypeAlignmentInBits - }; - class Type; - class ExtQuals; - class QualType; -} + +class ExtQuals; +class QualType; +class Type; + +enum { + TypeAlignmentInBits = 4, + TypeAlignment = 1 << TypeAlignmentInBits +}; + +} // namespace clang namespace llvm { + template <typename T> - class PointerLikeTypeTraits; + struct PointerLikeTypeTraits; template<> - class PointerLikeTypeTraits< ::clang::Type*> { - public: + struct PointerLikeTypeTraits< ::clang::Type*> { static inline void *getAsVoidPointer(::clang::Type *P) { return P; } + static inline ::clang::Type *getFromVoidPointer(void *P) { return static_cast< ::clang::Type*>(P); } + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; }; + template<> - class PointerLikeTypeTraits< ::clang::ExtQuals*> { - public: + struct PointerLikeTypeTraits< ::clang::ExtQuals*> { static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; } + static inline ::clang::ExtQuals *getFromVoidPointer(void *P) { return static_cast< ::clang::ExtQuals*>(P); } + enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; }; template <> struct isPodLike<clang::QualType> { static const bool value = true; }; -} + +} // namespace llvm namespace clang { - class ASTContext; - class TypedefNameDecl; - class TemplateDecl; - class TemplateTypeParmDecl; - class NonTypeTemplateParmDecl; - class TemplateTemplateParmDecl; - class TagDecl; - class RecordDecl; - class CXXRecordDecl; - class EnumDecl; - class FieldDecl; - class FunctionDecl; - class ObjCInterfaceDecl; - class ObjCProtocolDecl; - class ObjCMethodDecl; - class ObjCTypeParamDecl; - class UnresolvedUsingTypenameDecl; - class Expr; - class Stmt; - class SourceLocation; - class StmtIteratorBase; - class TemplateArgument; - class TemplateArgumentLoc; - class TemplateArgumentListInfo; - class ElaboratedType; - class ExtQuals; - class ExtQualsTypeCommonBase; - struct PrintingPolicy; - - template <typename> class CanQual; - typedef CanQual<Type> CanQualType; + +class ArrayType; +class ASTContext; +class AttributedType; +class AutoType; +class BuiltinType; +template <typename> class CanQual; +class ComplexType; +class CXXRecordDecl; +class DeclContext; +class DeducedType; +class EnumDecl; +class Expr; +class ExtQualsTypeCommonBase; +class FunctionDecl; +class FunctionNoProtoType; +class FunctionProtoType; +class IdentifierInfo; +class InjectedClassNameType; +class NamedDecl; +class ObjCInterfaceDecl; +class ObjCObjectPointerType; +class ObjCObjectType; +class ObjCProtocolDecl; +class ObjCTypeParamDecl; +class ParenType; +struct PrintingPolicy; +class RecordDecl; +class RecordType; +class Stmt; +class TagDecl; +class TemplateArgument; +class TemplateArgumentListInfo; +class TemplateArgumentLoc; +class TemplateSpecializationType; +class TemplateTypeParmDecl; +class TypedefNameDecl; +class TypedefType; +class UnresolvedUsingTypenameDecl; + +using CanQualType = CanQual<Type>; // Provide forward declarations for all of the *Type classes #define TYPE(Class, Base) class Class##Type; @@ -164,8 +198,6 @@ public: FastMask = (1 << FastWidth) - 1 }; - Qualifiers() : Mask(0) {} - /// Returns the common set of qualifiers while removing them from /// the given sets. static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { @@ -332,9 +364,11 @@ public: } bool hasAddressSpace() const { return Mask & AddressSpaceMask; } - unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } + LangAS getAddressSpace() const { + return static_cast<LangAS>(Mask >> AddressSpaceShift); + } bool hasTargetSpecificAddressSpace() const { - return getAddressSpace() >= LangAS::FirstTargetAddressSpace; + return isTargetAddressSpace(getAddressSpace()); } /// Get the address space attribute value to be printed by diagnostics. unsigned getAddressSpaceAttributePrintValue() const { @@ -342,22 +376,22 @@ public: // This function is not supposed to be used with language specific // address spaces. If that happens, the diagnostic message should consider // printing the QualType instead of the address space value. - assert(Addr == 0 || hasTargetSpecificAddressSpace()); - if (Addr) - return Addr - LangAS::FirstTargetAddressSpace; + assert(Addr == LangAS::Default || hasTargetSpecificAddressSpace()); + if (Addr != LangAS::Default) + return toTargetAddressSpace(Addr); // TODO: The diagnostic messages where Addr may be 0 should be fixed // since it cannot differentiate the situation where 0 denotes the default // address space or user specified __attribute__((address_space(0))). return 0; } - void setAddressSpace(unsigned space) { - assert(space <= MaxAddressSpace); + void setAddressSpace(LangAS space) { + assert((unsigned)space <= MaxAddressSpace); Mask = (Mask & ~AddressSpaceMask) | (((uint32_t) space) << AddressSpaceShift); } - void removeAddressSpace() { setAddressSpace(0); } - void addAddressSpace(unsigned space) { - assert(space); + void removeAddressSpace() { setAddressSpace(LangAS::Default); } + void addAddressSpace(LangAS space) { + assert(space != LangAS::Default); setAddressSpace(space); } @@ -538,10 +572,9 @@ public: } private: - // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31| // |C R V|U|GCAttr|Lifetime|AddressSpace| - uint32_t Mask; + uint32_t Mask = 0; static const uint32_t UMask = 0x8; static const uint32_t UShift = 3; @@ -558,12 +591,12 @@ private: /// into its local qualifiers and its locally-unqualified type. struct SplitQualType { /// The locally-unqualified type. - const Type *Ty; + const Type *Ty = nullptr; /// The local qualifiers. Qualifiers Quals; - SplitQualType() : Ty(nullptr), Quals() {} + SplitQualType() = default; SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {} SplitQualType getSingleStepDesugaredType() const; // end of this file @@ -589,12 +622,16 @@ struct SplitQualType { enum class ObjCSubstitutionContext { /// An ordinary type. Ordinary, + /// The result type of a method or function. Result, + /// The parameter type of a method or function. Parameter, + /// The type of a property. Property, + /// The superclass of a type. Superclass, }; @@ -614,8 +651,10 @@ enum class ObjCSubstitutionContext { /// indicates whether there are extended qualifiers present, in which /// case the pointer points to a special structure. class QualType { + friend class QualifierCollector; + // Thankfully, these are efficiently composable. - llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>, + llvm::PointerIntPair<llvm::PointerUnion<const Type *, const ExtQuals *>, Qualifiers::FastWidth> Value; const ExtQuals *getExtQualsUnsafe() const { @@ -634,14 +673,10 @@ class QualType { return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal); } - friend class QualifierCollector; public: - QualType() {} - - QualType(const Type *Ptr, unsigned Quals) - : Value(Ptr, Quals) {} - QualType(const ExtQuals *Ptr, unsigned Quals) - : Value(Ptr, Quals) {} + QualType() = default; + QualType(const Type *Ptr, unsigned Quals) : Value(Ptr, Quals) {} + QualType(const ExtQuals *Ptr, unsigned Quals) : Value(Ptr, Quals) {} unsigned getLocalFastQualifiers() const { return Value.getInt(); } void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } @@ -662,6 +697,7 @@ public: SplitQualType split() const; void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } + static QualType getFromOpaquePtr(const void *Ptr) { QualType T; T.Value.setFromOpaqueValue(const_cast<void*>(Ptr)); @@ -939,12 +975,15 @@ public: friend bool operator!=(const QualType &LHS, const QualType &RHS) { return LHS.Value != RHS.Value; } + std::string getAsString() const { return getAsString(split()); } + static std::string getAsString(SplitQualType split) { return getAsString(split.Ty, split.Quals); } + static std::string getAsString(const Type *ty, Qualifiers qs); std::string getAsString(const PrintingPolicy &Policy) const; @@ -954,11 +993,13 @@ public: unsigned Indentation = 0) const { print(split(), OS, Policy, PlaceHolder, Indentation); } + static void print(SplitQualType split, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, unsigned Indentation = 0) { return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); } + static void print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, @@ -968,10 +1009,12 @@ public: const PrintingPolicy &Policy) const { return getAsStringInternal(split(), Str, Policy); } + static void getAsStringInternal(SplitQualType split, std::string &out, const PrintingPolicy &policy) { return getAsStringInternal(split.Ty, split.Quals, out, policy); } + static void getAsStringInternal(const Type *ty, Qualifiers qs, std::string &out, const PrintingPolicy &policy); @@ -981,11 +1024,12 @@ public: const PrintingPolicy &Policy; const Twine &PlaceHolder; unsigned Indentation; + public: StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, const Twine &PlaceHolder, unsigned Indentation) - : T(T), Policy(Policy), PlaceHolder(PlaceHolder), - Indentation(Indentation) { } + : T(T), Policy(Policy), PlaceHolder(PlaceHolder), + Indentation(Indentation) {} friend raw_ostream &operator<<(raw_ostream &OS, const StreamedQualTypeHelper &SQT) { @@ -1009,7 +1053,7 @@ public: } /// Return the address space of this type. - inline unsigned getAddressSpace() const; + inline LangAS getAddressSpace() const; /// Returns gc attribute of this type. inline Qualifiers::GC getObjCGCAttr() const; @@ -1129,13 +1173,15 @@ private: static DestructionKind isDestructedTypeImpl(QualType type); }; -} // end clang. +} // namespace clang namespace llvm { + /// Implement simplify_type for QualType, so that we can dyn_cast from QualType /// to a specific Type class. template<> struct simplify_type< ::clang::QualType> { - typedef const ::clang::Type *SimpleType; + using SimpleType = const ::clang::Type *; + static SimpleType getSimplifiedValue(::clang::QualType Val) { return Val.getTypePtr(); } @@ -1143,29 +1189,30 @@ template<> struct simplify_type< ::clang::QualType> { // Teach SmallPtrSet that QualType is "basically a pointer". template<> -class PointerLikeTypeTraits<clang::QualType> { -public: +struct PointerLikeTypeTraits<clang::QualType> { static inline void *getAsVoidPointer(clang::QualType P) { return P.getAsOpaquePtr(); } + static inline clang::QualType getFromVoidPointer(void *P) { return clang::QualType::getFromOpaquePtr(P); } + // Various qualifiers go in low bits. enum { NumLowBitsAvailable = 0 }; }; -} // end namespace llvm +} // namespace llvm namespace clang { /// \brief 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 { - ExtQualsTypeCommonBase(const Type *baseType, QualType canon) - : BaseType(baseType), CanonicalType(canon) {} + friend class ExtQuals; + friend class QualType; + friend class Type; /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or /// a self-referential pointer (for \c Type). @@ -1177,9 +1224,8 @@ class ExtQualsTypeCommonBase { /// \brief The canonical type of this type. A QualType. QualType CanonicalType; - friend class QualType; - friend class Type; - friend class ExtQuals; + ExtQualsTypeCommonBase(const Type *baseType, QualType canon) + : BaseType(baseType), CanonicalType(canon) {} }; /// We can encode up to four bits in the low bits of a @@ -1214,10 +1260,9 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { public: ExtQuals(const Type *baseType, QualType canon, Qualifiers quals) - : ExtQualsTypeCommonBase(baseType, - canon.isNull() ? QualType(this_(), 0) : canon), - Quals(quals) - { + : ExtQualsTypeCommonBase(baseType, + canon.isNull() ? QualType(this_(), 0) : canon), + Quals(quals) { assert(Quals.hasNonFastQualifiers() && "ExtQuals created with no fast qualifiers"); assert(!Quals.hasFastQualifiers() @@ -1235,7 +1280,7 @@ public: } bool hasAddressSpace() const { return Quals.hasAddressSpace(); } - unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + LangAS getAddressSpace() const { return Quals.getAddressSpace(); } const Type *getBaseType() const { return BaseType; } @@ -1243,6 +1288,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, getBaseType(), Quals); } + static void Profile(llvm::FoldingSetNodeID &ID, const Type *BaseType, Qualifiers Quals) { @@ -1258,8 +1304,10 @@ public: enum RefQualifierKind { /// \brief No ref-qualifier was provided. RQ_None = 0, + /// \brief An lvalue ref-qualifier was provided (\c &). RQ_LValue, + /// \brief An rvalue ref-qualifier was provided (\c &&). RQ_RValue }; @@ -1268,8 +1316,10 @@ enum RefQualifierKind { enum class AutoTypeKeyword { /// \brief auto Auto, + /// \brief decltype(auto) DecltypeAuto, + /// \brief __auto_type (GNU extension) GNUAutoType }; @@ -1311,9 +1361,6 @@ public: }; private: - Type(const Type &) = delete; - void operator=(const Type &) = delete; - /// Bitfields required by the Type class. class TypeBitfields { friend class Type; @@ -1352,10 +1399,12 @@ private: bool isCacheValid() const { return CacheValid; } + Linkage getLinkage() const { assert(isCacheValid() && "getting linkage from invalid cache"); return static_cast<Linkage>(CachedLinkage); } + bool hasLocalOrUnnamedType() const { assert(isCacheValid() && "getting linkage from invalid cache"); return CachedLocalOrUnnamed; @@ -1392,8 +1441,8 @@ protected: }; class FunctionTypeBitfields { - friend class FunctionType; friend class FunctionProtoType; + friend class FunctionType; unsigned : NumTypeBits; @@ -1429,6 +1478,7 @@ protected: /// Whether this is a "kindof" type. unsigned IsKindOf : 1; }; + static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned"); class ReferenceTypeBitfields { @@ -1511,21 +1561,21 @@ protected: }; private: + template <class T> friend class TypePropertyCache; + /// \brief Set whether this type comes from an AST file. void setFromAST(bool V = true) const { TypeBits.FromAST = V; } - template <class T> friend class TypePropertyCache; - protected: - // silence VC++ warning C4355: 'this' : used in base member initializer list - Type *this_() { return this; } + friend class ASTContext; + Type(TypeClass tc, QualType canon, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) - : ExtQualsTypeCommonBase(this, - canon.isNull() ? QualType(this_(), 0) : canon) { + : ExtQualsTypeCommonBase(this, + canon.isNull() ? QualType(this_(), 0) : canon) { TypeBits.TC = tc; TypeBits.Dependent = Dependent; TypeBits.InstantiationDependent = Dependent || InstantiationDependent; @@ -1536,22 +1586,32 @@ protected: TypeBits.CachedLinkage = NoLinkage; TypeBits.FromAST = false; } - friend class ASTContext; + + // silence VC++ warning C4355: 'this' : used in base member initializer list + Type *this_() { return this; } void setDependent(bool D = true) { TypeBits.Dependent = D; if (D) TypeBits.InstantiationDependent = true; } + void setInstantiationDependent(bool D = true) { TypeBits.InstantiationDependent = D; } - void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; - } + + void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; } + void setContainsUnexpandedParameterPack(bool PP = true) { TypeBits.ContainsUnexpandedParameterPack = PP; } public: + friend class ASTReader; + friend class ASTWriter; + + Type(const Type &) = delete; + Type &operator=(const Type &) = delete; + TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); } /// \brief Whether this type comes from an AST file. @@ -1658,6 +1718,7 @@ public: /// Determine whether this type is an integral or enumeration type. bool isIntegralOrEnumerationType() const; + /// Determine whether this type is an integral or unscoped enumeration type. bool isIntegralOrUnscopedEnumerationType() const; @@ -1708,6 +1769,7 @@ public: bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. + bool isDependentAddressSpaceType() const; // value-dependent address space qualifier bool isObjCObjectPointerType() const; // pointer to ObjC object bool isObjCRetainableType() const; // ObjC object or block pointer bool isObjCLifetimeType() const; // (array of)* retainable type @@ -1789,6 +1851,7 @@ public: STK_IntegralComplex, STK_FloatingComplex }; + /// Given that this is a scalar type, classify it. ScalarTypeKind getScalarTypeKind() const; @@ -1859,6 +1922,7 @@ public: const RecordType *getAsUnionType() const; const ComplexType *getAsComplexIntegerType() const; // GCC complex int type. const ObjCObjectType *getAsObjCInterfaceType() const; + // The following is a convenience method that returns an ObjCObjectPointerType // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; @@ -2045,12 +2109,10 @@ public: QualType getCanonicalTypeInternal() const { return CanonicalType; } + CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h void dump() const; void dump(llvm::raw_ostream &OS) const; - - friend class ASTReader; - friend class ASTWriter; }; /// \brief This will check for a TypedefType by removing any existing sugar @@ -2078,7 +2140,6 @@ template <> inline const Class##Type *Type::castAs() const { \ } #include "clang/AST/TypeNodes.def" - /// This class is used for builtin types like 'int'. Builtin /// types are always canonical and have a literal name field. class BuiltinType : public Type { @@ -2095,15 +2156,16 @@ public: public: BuiltinType(Kind K) - : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), - /*InstantiationDependent=*/(K == Dependent), - /*VariablyModified=*/false, - /*Unexpanded parameter pack=*/false) { + : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), + /*InstantiationDependent=*/(K == Dependent), + /*VariablyModified=*/false, + /*Unexpanded parameter pack=*/false) { BuiltinTypeBits.Kind = K; } Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); } StringRef getName(const PrintingPolicy &Policy) const; + const char *getNameAsCString(const PrintingPolicy &Policy) const { // The StringRef is null-terminated. StringRef str = getName(Policy); @@ -2160,17 +2222,17 @@ public: /// Complex values, per C99 6.2.5p11. This supports the C99 complex /// types (_Complex float etc) as well as the GCC integer complex extensions. -/// class ComplexType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType ElementType; - ComplexType(QualType Element, QualType CanonicalPtr) : - Type(Complex, CanonicalPtr, Element->isDependentType(), - Element->isInstantiationDependentType(), - Element->isVariablyModifiedType(), - Element->containsUnexpandedParameterPack()), - ElementType(Element) { - } - friend class ASTContext; // ASTContext creates these. + + ComplexType(QualType Element, QualType CanonicalPtr) + : Type(Complex, CanonicalPtr, Element->isDependentType(), + Element->isInstantiationDependentType(), + Element->isVariablyModifiedType(), + Element->containsUnexpandedParameterPack()), + ElementType(Element) {} public: QualType getElementType() const { return ElementType; } @@ -2181,6 +2243,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) { ID.AddPointer(Element.getAsOpaquePtr()); } @@ -2189,21 +2252,19 @@ public: }; /// Sugar for parentheses used when specifying types. -/// class ParenType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType Inner; - ParenType(QualType InnerType, QualType CanonType) : - Type(Paren, CanonType, InnerType->isDependentType(), - InnerType->isInstantiationDependentType(), - InnerType->isVariablyModifiedType(), - InnerType->containsUnexpandedParameterPack()), - Inner(InnerType) { - } - friend class ASTContext; // ASTContext creates these. + ParenType(QualType InnerType, QualType CanonType) + : Type(Paren, CanonType, InnerType->isDependentType(), + InnerType->isInstantiationDependentType(), + InnerType->isVariablyModifiedType(), + InnerType->containsUnexpandedParameterPack()), + Inner(InnerType) {} public: - QualType getInnerType() const { return Inner; } bool isSugared() const { return true; } @@ -2212,6 +2273,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getInnerType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) { Inner.Profile(ID); } @@ -2220,21 +2282,19 @@ public: }; /// PointerType - C99 6.7.5.1 - Pointer Declarators. -/// class PointerType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType PointeeType; - PointerType(QualType Pointee, QualType CanonicalPtr) : - Type(Pointer, CanonicalPtr, Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) { - } - friend class ASTContext; // ASTContext creates these. + PointerType(QualType Pointee, QualType CanonicalPtr) + : Type(Pointer, CanonicalPtr, Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), + PointeeType(Pointee) {} public: - QualType getPointeeType() const { return PointeeType; } /// Returns true if address spaces of pointers overlap. @@ -2259,6 +2319,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { ID.AddPointer(Pointee.getAsOpaquePtr()); } @@ -2274,6 +2335,8 @@ class AdjustedType : public Type, public llvm::FoldingSetNode { QualType AdjustedTy; protected: + friend class ASTContext; // ASTContext creates these. + AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy, QualType CanonicalPtr) : Type(TC, CanonicalPtr, OriginalTy->isDependentType(), @@ -2282,8 +2345,6 @@ protected: OriginalTy->containsUnexpandedParameterPack()), OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {} - friend class ASTContext; // ASTContext creates these. - public: QualType getOriginalType() const { return OriginalTy; } QualType getAdjustedType() const { return AdjustedTy; } @@ -2294,6 +2355,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, OriginalTy, AdjustedTy); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) { ID.AddPointer(Orig.getAsOpaquePtr()); ID.AddPointer(New.getAsOpaquePtr()); @@ -2306,12 +2368,11 @@ public: /// Represents a pointer type decayed from an array or function type. class DecayedType : public AdjustedType { + friend class ASTContext; // ASTContext creates these. inline DecayedType(QualType OriginalType, QualType Decayed, QualType Canonical); - friend class ASTContext; // ASTContext creates these. - public: QualType getDecayedType() const { return getAdjustedType(); } @@ -2323,20 +2384,20 @@ public: /// Pointer to a block type. /// This type is to represent types syntactically represented as /// "void (^)(int)", etc. Pointee is required to always be a function type. -/// class BlockPointerType : public Type, public llvm::FoldingSetNode { - QualType PointeeType; // Block is some kind of pointer type - BlockPointerType(QualType Pointee, QualType CanonicalCls) : - Type(BlockPointer, CanonicalCls, Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) { - } - friend class ASTContext; // ASTContext creates these. + friend class ASTContext; // ASTContext creates these. -public: + // Block is some kind of pointer type + QualType PointeeType; + BlockPointerType(QualType Pointee, QualType CanonicalCls) + : Type(BlockPointer, CanonicalCls, Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), + PointeeType(Pointee) {} + +public: // Get the pointee type. Pointee is required to always be a function type. QualType getPointeeType() const { return PointeeType; } @@ -2346,6 +2407,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) { ID.AddPointer(Pointee.getAsOpaquePtr()); } @@ -2356,19 +2418,17 @@ public: }; /// Base for LValueReferenceType and RValueReferenceType -/// class ReferenceType : public Type, public llvm::FoldingSetNode { QualType PointeeType; protected: ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, - bool SpelledAsLValue) : - Type(tc, CanonicalRef, Referencee->isDependentType(), - Referencee->isInstantiationDependentType(), - Referencee->isVariablyModifiedType(), - Referencee->containsUnexpandedParameterPack()), - PointeeType(Referencee) - { + bool SpelledAsLValue) + : Type(tc, CanonicalRef, Referencee->isDependentType(), + Referencee->isInstantiationDependentType(), + Referencee->isVariablyModifiedType(), + Referencee->containsUnexpandedParameterPack()), + PointeeType(Referencee) { ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue; ReferenceTypeBits.InnerRef = Referencee->isReferenceType(); } @@ -2378,6 +2438,7 @@ public: bool isInnerRef() const { return ReferenceTypeBits.InnerRef; } QualType getPointeeTypeAsWritten() const { return PointeeType; } + QualType getPointeeType() const { // FIXME: this might strip inner qualifiers; okay? const ReferenceType *T = this; @@ -2389,6 +2450,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, PointeeType, isSpelledAsLValue()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee, bool SpelledAsLValue) { @@ -2403,13 +2465,14 @@ public: }; /// An lvalue reference type, per C++11 [dcl.ref]. -/// class LValueReferenceType : public ReferenceType { - LValueReferenceType(QualType Referencee, QualType CanonicalRef, - bool SpelledAsLValue) : - ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue) - {} friend class ASTContext; // ASTContext creates these + + LValueReferenceType(QualType Referencee, QualType CanonicalRef, + bool SpelledAsLValue) + : ReferenceType(LValueReference, Referencee, CanonicalRef, + SpelledAsLValue) {} + public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2420,12 +2483,12 @@ public: }; /// An rvalue reference type, per C++11 [dcl.ref]. -/// class RValueReferenceType : public ReferenceType { - RValueReferenceType(QualType Referencee, QualType CanonicalRef) : - ReferenceType(RValueReference, Referencee, CanonicalRef, false) { - } friend class ASTContext; // ASTContext creates these + + RValueReferenceType(QualType Referencee, QualType CanonicalRef) + : ReferenceType(RValueReference, Referencee, CanonicalRef, false) {} + public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2438,24 +2501,24 @@ public: /// A pointer to member type per C++ 8.3.3 - Pointers to members. /// /// This includes both pointers to data members and pointer to member functions. -/// class MemberPointerType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType PointeeType; + /// The class of which the pointee is a member. Must ultimately be a /// RecordType, but could be a typedef or a template parameter too. const Type *Class; - MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : - Type(MemberPointer, CanonicalPtr, - Cls->isDependentType() || Pointee->isDependentType(), - (Cls->isInstantiationDependentType() || - Pointee->isInstantiationDependentType()), - Pointee->isVariablyModifiedType(), - (Cls->containsUnexpandedParameterPack() || - Pointee->containsUnexpandedParameterPack())), - PointeeType(Pointee), Class(Cls) { - } - friend class ASTContext; // ASTContext creates these. + MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) + : Type(MemberPointer, CanonicalPtr, + Cls->isDependentType() || Pointee->isDependentType(), + (Cls->isInstantiationDependentType() || + Pointee->isInstantiationDependentType()), + Pointee->isVariablyModifiedType(), + (Cls->containsUnexpandedParameterPack() || + Pointee->containsUnexpandedParameterPack())), + PointeeType(Pointee), Class(Cls) {} public: QualType getPointeeType() const { return PointeeType; } @@ -2481,6 +2544,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType(), getClass()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, const Type *Class) { ID.AddPointer(Pointee.getAsOpaquePtr()); @@ -2493,7 +2557,6 @@ public: }; /// Represents an array type, per C99 6.7.5.2 - Array Declarators. -/// class ArrayType : public Type, public llvm::FoldingSetNode { public: /// Capture whether this is a normal array (e.g. int X[4]) @@ -2503,11 +2566,14 @@ public: enum ArraySizeModifier { Normal, Static, Star }; + private: /// The element type of the array. QualType ElementType; protected: + friend class ASTContext; // ASTContext creates these. + // C++ [temp.dep.type]p1: // A type is dependent if it is... // - an array type constructed from any dependent type or whose @@ -2516,25 +2582,26 @@ protected: ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm, unsigned tq, bool ContainsUnexpandedParameterPack) - : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, - et->isInstantiationDependentType() || tc == DependentSizedArray, - (tc == VariableArray || et->isVariablyModifiedType()), - ContainsUnexpandedParameterPack), - ElementType(et) { + : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, + et->isInstantiationDependentType() || tc == DependentSizedArray, + (tc == VariableArray || et->isVariablyModifiedType()), + ContainsUnexpandedParameterPack), + ElementType(et) { ArrayTypeBits.IndexTypeQuals = tq; ArrayTypeBits.SizeModifier = sm; } - friend class ASTContext; // ASTContext creates these. - public: QualType getElementType() const { return ElementType; } + ArraySizeModifier getSizeModifier() const { return ArraySizeModifier(ArrayTypeBits.SizeModifier); } + Qualifiers getIndexTypeQualifiers() const { return Qualifiers::fromCVRMask(getIndexTypeCVRQualifiers()); } + unsigned getIndexTypeCVRQualifiers() const { return ArrayTypeBits.IndexTypeQuals; } @@ -2555,21 +2622,23 @@ class ConstantArrayType : public ArrayType { ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), - Size(size) {} + : ArrayType(ConstantArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()), + Size(size) {} + protected: + friend class ASTContext; // ASTContext creates these. + ConstantArrayType(TypeClass tc, QualType et, QualType can, const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), - Size(size) {} - friend class ASTContext; // ASTContext creates these. + : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), + Size(size) {} + public: const llvm::APInt &getSize() const { return Size; } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - /// \brief Determine the number of bits required to address a member of // an array with the given element type and number of elements. static unsigned getNumAddressingBits(const ASTContext &Context, @@ -2584,6 +2653,7 @@ public: Profile(ID, getElementType(), getSize(), getSizeModifier(), getIndexTypeCVRQualifiers()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, const llvm::APInt &ArraySize, ArraySizeModifier SizeMod, unsigned TypeQuals) { @@ -2592,6 +2662,7 @@ public: ID.AddInteger(SizeMod); ID.AddInteger(TypeQuals); } + static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray; } @@ -2601,13 +2672,16 @@ public: /// an IncompleteArrayType where the element type is 'int' and the size is /// unspecified. class IncompleteArrayType : public ArrayType { + friend class ASTContext; // ASTContext creates these. IncompleteArrayType(QualType et, QualType can, ArraySizeModifier sm, unsigned tq) - : ArrayType(IncompleteArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()) {} - friend class ASTContext; // ASTContext creates these. + : ArrayType(IncompleteArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()) {} + public: + friend class StmtIteratorBase; + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2615,8 +2689,6 @@ public: return T->getTypeClass() == IncompleteArray; } - friend class StmtIteratorBase; - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType(), getSizeModifier(), getIndexTypeCVRQualifiers()); @@ -2644,28 +2716,32 @@ public: /// ++x; /// int Z[x]; /// } -/// class VariableArrayType : public ArrayType { + friend class ASTContext; // ASTContext creates these. + /// An assignment-expression. VLA's are only permitted within /// a function block. Stmt *SizeExpr; + /// The range spanned by the left and right array brackets. SourceRange Brackets; VariableArrayType(QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(VariableArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), - SizeExpr((Stmt*) e), Brackets(brackets) {} - friend class ASTContext; // ASTContext creates these. + : ArrayType(VariableArray, et, can, sm, tq, + et->containsUnexpandedParameterPack()), + SizeExpr((Stmt*) e), Brackets(brackets) {} public: + friend class StmtIteratorBase; + Expr *getSizeExpr() const { // We use C-style casts instead of cast<> here because we do not wish // to have a dependency of Type.h on Stmt.h/Expr.h. return (Expr*) SizeExpr; } + SourceRange getBracketsRange() const { return Brackets; } SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } @@ -2677,8 +2753,6 @@ public: return T->getTypeClass() == VariableArray; } - friend class StmtIteratorBase; - void Profile(llvm::FoldingSetNodeID &ID) { llvm_unreachable("Cannot unique VariableArrayTypes."); } @@ -2698,6 +2772,8 @@ public: /// until template instantiation occurs, at which point this will /// become either a ConstantArrayType or a VariableArrayType. class DependentSizedArrayType : public ArrayType { + friend class ASTContext; // ASTContext creates these. + const ASTContext &Context; /// \brief An assignment expression that will instantiate to the @@ -2714,14 +2790,15 @@ class DependentSizedArrayType : public ArrayType { Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets); - friend class ASTContext; // ASTContext creates these. - public: + friend class StmtIteratorBase; + Expr *getSizeExpr() const { // We use C-style casts instead of cast<> here because we do not wish // to have a dependency of Type.h on Stmt.h/Expr.h. return (Expr*) SizeExpr; } + SourceRange getBracketsRange() const { return Brackets; } SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } @@ -2733,9 +2810,6 @@ public: return T->getTypeClass() == DependentSizedArray; } - friend class StmtIteratorBase; - - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getElementType(), getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr()); @@ -2746,6 +2820,49 @@ public: unsigned TypeQuals, Expr *E); }; +/// Represents an extended address space qualifier where the input address space +/// value is dependent. Non-dependent address spaces are not represented with a +/// special Type subclass; they are stored on an ExtQuals node as part of a QualType. +/// +/// For example: +/// \code +/// template<typename T, int AddrSpace> +/// class AddressSpace { +/// typedef T __attribute__((address_space(AddrSpace))) type; +/// } +/// \endcode +class DependentAddressSpaceType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + + const ASTContext &Context; + Expr *AddrSpaceExpr; + QualType PointeeType; + SourceLocation loc; + + DependentAddressSpaceType(const ASTContext &Context, QualType PointeeType, + QualType can, Expr *AddrSpaceExpr, + SourceLocation loc); + +public: + Expr *getAddrSpaceExpr() const { return AddrSpaceExpr; } + QualType getPointeeType() const { return PointeeType; } + SourceLocation getAttributeLoc() const { return loc; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentAddressSpace; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getPointeeType(), getAddrSpaceExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType PointeeType, Expr *AddrSpaceExpr); +}; + /// Represents an extended vector type where either the type or size is /// dependent. /// @@ -2757,17 +2874,19 @@ public: /// } /// \endcode class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + const ASTContext &Context; Expr *SizeExpr; + /// The element type of the array. QualType ElementType; + SourceLocation loc; DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, QualType can, Expr *SizeExpr, SourceLocation loc); - friend class ASTContext; - public: Expr *getSizeExpr() const { return SizeExpr; } QualType getElementType() const { return ElementType; } @@ -2797,14 +2916,28 @@ public: class VectorType : public Type, public llvm::FoldingSetNode { public: enum VectorKind { - GenericVector, ///< not a target-specific vector type - AltiVecVector, ///< is AltiVec vector - AltiVecPixel, ///< is AltiVec 'vector Pixel' - AltiVecBool, ///< is AltiVec 'vector bool ...' - NeonVector, ///< is ARM Neon vector - NeonPolyVector ///< is ARM Neon polynomial vector + /// not a target-specific vector type + GenericVector, + + /// is AltiVec vector + AltiVecVector, + + /// is AltiVec 'vector Pixel' + AltiVecPixel, + + /// is AltiVec 'vector bool ...' + AltiVecBool, + + /// is ARM Neon vector + NeonVector, + + /// is ARM Neon polynomial vector + NeonPolyVector }; + protected: + friend class ASTContext; // ASTContext creates these. + /// The element type of the vector. QualType ElementType; @@ -2814,12 +2947,10 @@ protected: VectorType(TypeClass tc, QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind); - friend class ASTContext; // ASTContext creates these. - public: - QualType getElementType() const { return ElementType; } unsigned getNumElements() const { return VectorTypeBits.NumElements; } + static bool isVectorSizeTooLarge(unsigned NumElements) { return NumElements > VectorTypeBitfields::MaxNumElements; } @@ -2835,6 +2966,7 @@ public: Profile(ID, getElementType(), getNumElements(), getTypeClass(), getVectorKind()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, unsigned NumElements, TypeClass TypeClass, VectorKind VecKind) { @@ -2856,9 +2988,11 @@ public: /// points (as .xyzw), colors (as .rgba), and textures (modeled after OpenGL /// Shading Language). class ExtVectorType : public VectorType { - ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : - VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {} - friend class ASTContext; // ASTContext creates these. + friend class ASTContext; // ASTContext creates these. + + ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) + : VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {} + public: static int getPointAccessorIdx(char c) { switch (c) { @@ -2869,6 +3003,7 @@ public: case 'w': case 'a': return 3; } } + static int getNumericAccessorIdx(char c) { switch (c) { default: return -1; @@ -2909,6 +3044,7 @@ public: return unsigned(idx-1) < getNumElements(); return false; } + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2919,12 +3055,11 @@ public: /// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base /// class of FunctionNoProtoType and FunctionProtoType. -/// class FunctionType : public Type { // The type returned by the function. QualType ResultType; - public: +public: /// A class which abstracts out some details necessary for /// making a call. /// @@ -2946,6 +3081,8 @@ class FunctionType : public Type { // * AST read and write // * Codegen class ExtInfo { + friend class FunctionType; + // Feel free to rearrange or add bits, but if you go over 11, // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. @@ -2964,15 +3101,13 @@ class FunctionType : public Type { RegParmOffset = 8 }; // Assumed to be the last field - uint16_t Bits; + uint16_t Bits = CC_C; ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {} - friend class FunctionType; - public: - // Constructor with no defaults. Use this when you know that you - // have all the elements (when reading an AST file for example). + // 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) { assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); @@ -2984,22 +3119,24 @@ class FunctionType : public Type { // Constructor with all defaults. Use when for example creating a // function known to use defaults. - ExtInfo() : Bits(CC_C) { } + ExtInfo() = default; // Constructor with just the calling convention, which is an important part // of the canonical type. - ExtInfo(CallingConv CC) : Bits(CC) { } + ExtInfo(CallingConv CC) : Bits(CC) {} bool getNoReturn() const { return Bits & NoReturnMask; } bool getProducesResult() const { return Bits & ProducesResultMask; } bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; } bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } + unsigned getRegParm() const { unsigned RegParm = Bits >> RegParmOffset; if (RegParm > 0) --RegParm; return RegParm; } + CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } bool operator==(ExtInfo Other) const { @@ -3054,11 +3191,12 @@ protected: bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack), - ResultType(res) { + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, + ContainsUnexpandedParameterPack), + ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; } + unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } public: @@ -3066,10 +3204,12 @@ public: bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } + /// Determine whether this function type includes the GNU noreturn /// attribute. The C++11 [[noreturn]] attribute does not affect the function /// type. bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } + CallingConv getCallConv() const { return getExtInfo().getCC(); } ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } bool isConst() const { return getTypeQuals() & Qualifiers::Const; } @@ -3093,13 +3233,13 @@ public: /// Represents a K&R-style 'int foo()' function, which has /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { - FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) - : FunctionType(FunctionNoProto, Result, Canonical, - /*Dependent=*/false, /*InstantiationDependent=*/false, - Result->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false, Info) {} + friend class ASTContext; // ASTContext creates these. - friend class ASTContext; // ASTContext creates these. + FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) + : FunctionType(FunctionNoProto, Result, Canonical, + /*Dependent=*/false, /*InstantiationDependent=*/false, + Result->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false, Info) {} public: // No additional state past what FunctionType provides. @@ -3110,6 +3250,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getReturnType(), getExtInfo()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, ExtInfo Info) { Info.Profile(ID); @@ -3152,11 +3293,12 @@ public: ABIMask = 0x0F, IsConsumed = 0x10, HasPassObjSize = 0x20, + IsNoEscape = 0x40, }; - unsigned char Data; + unsigned char Data = 0; public: - ExtParameterInfo() : Data(0) {} + ExtParameterInfo() = default; /// Return the ABI treatment of this parameter. ParameterABI getABI() const { @@ -3192,6 +3334,19 @@ public: return Copy; } + bool isNoEscape() const { + return Data & IsNoEscape; + } + + ExtParameterInfo withIsNoEscape(bool NoEscape) const { + ExtParameterInfo Copy = *this; + if (NoEscape) + Copy.Data |= IsNoEscape; + else + Copy.Data &= ~IsNoEscape; + return Copy; + } + unsigned char getOpaqueValue() const { return Data; } static ExtParameterInfo getFromOpaqueValue(unsigned char data) { ExtParameterInfo result; @@ -3208,54 +3363,54 @@ public: }; struct ExceptionSpecInfo { - ExceptionSpecInfo() - : Type(EST_None), NoexceptExpr(nullptr), - SourceDecl(nullptr), SourceTemplate(nullptr) {} - - ExceptionSpecInfo(ExceptionSpecificationType EST) - : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr), - SourceTemplate(nullptr) {} - /// The kind of exception specification this is. - ExceptionSpecificationType Type; + ExceptionSpecificationType Type = EST_None; + /// Explicitly-specified list of exception types. ArrayRef<QualType> Exceptions; + /// Noexcept expression, if this is EST_ComputedNoexcept. - Expr *NoexceptExpr; + Expr *NoexceptExpr = nullptr; + /// The function whose exception specification this is, for /// EST_Unevaluated and EST_Uninstantiated. - FunctionDecl *SourceDecl; + FunctionDecl *SourceDecl = nullptr; + /// The function template whose exception specification this is instantiated /// from, for EST_Uninstantiated. - FunctionDecl *SourceTemplate; + FunctionDecl *SourceTemplate = nullptr; + + ExceptionSpecInfo() = default; + + ExceptionSpecInfo(ExceptionSpecificationType EST) : Type(EST) {} }; /// Extra information about a function prototype. struct ExtProtoInfo { + FunctionType::ExtInfo ExtInfo; + bool Variadic : 1; + bool HasTrailingReturn : 1; + unsigned char TypeQuals = 0; + RefQualifierKind RefQualifier = RQ_None; + ExceptionSpecInfo ExceptionSpec; + const ExtParameterInfo *ExtParameterInfos = nullptr; + ExtProtoInfo() - : Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ExtParameterInfos(nullptr) {} + : Variadic(false), HasTrailingReturn(false) {} ExtProtoInfo(CallingConv CC) - : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ExtParameterInfos(nullptr) {} + : ExtInfo(CC), Variadic(false), HasTrailingReturn(false) {} ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) { ExtProtoInfo Result(*this); Result.ExceptionSpec = O; return Result; } - - FunctionType::ExtInfo ExtInfo; - bool Variadic : 1; - bool HasTrailingReturn : 1; - unsigned char TypeQuals; - RefQualifierKind RefQualifier; - ExceptionSpecInfo ExceptionSpec; - const ExtParameterInfo *ExtParameterInfos; }; private: + friend class ASTContext; // ASTContext creates these. + /// \brief Determine whether there are any argument types that /// contain an unexpanded parameter pack. static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, @@ -3307,8 +3462,6 @@ private: // for each of the parameters. This only appears if HasExtParameterInfos // is true. - friend class ASTContext; // ASTContext creates these. - const ExtParameterInfo *getExtParameterInfosBuffer() const { assert(hasExtParameterInfos()); @@ -3336,10 +3489,12 @@ private: public: unsigned getNumParams() const { return NumParams; } + QualType getParamType(unsigned i) const { assert(i < NumParams && "invalid parameter index"); return param_type_begin()[i]; } + ArrayRef<QualType> getParamTypes() const { return llvm::makeArrayRef(param_type_begin(), param_type_end()); } @@ -3371,31 +3526,47 @@ public: ExceptionSpecificationType getExceptionSpecType() const { return static_cast<ExceptionSpecificationType>(ExceptionSpecType); } + /// Return whether this function has any kind of exception spec. bool hasExceptionSpec() const { return getExceptionSpecType() != EST_None; } + /// Return whether this function has a dynamic (throw) exception spec. bool hasDynamicExceptionSpec() const { return isDynamicExceptionSpec(getExceptionSpecType()); } + /// Return whether this function has a noexcept exception spec. bool hasNoexceptExceptionSpec() const { return isNoexceptExceptionSpec(getExceptionSpecType()); } + /// Return whether this function has a dependent exception spec. bool hasDependentExceptionSpec() const; + /// Return whether this function has an instantiation-dependent exception /// spec. bool hasInstantiationDependentExceptionSpec() const; + /// Result type of getNoexceptSpec(). enum NoexceptResult { - NR_NoNoexcept, ///< There is no noexcept specifier. - NR_BadNoexcept, ///< The noexcept specifier has a bad expression. - NR_Dependent, ///< The noexcept specifier is dependent. - NR_Throw, ///< The noexcept specifier evaluates to false. - NR_Nothrow ///< The noexcept specifier evaluates to true. + /// 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; } @@ -3409,6 +3580,7 @@ public: // 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 /// been determined yet (either because it has not been evaluated or because /// it has not been instantiated), this is the function whose exception @@ -3419,6 +3591,7 @@ public: return nullptr; return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0]; } + /// \brief 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 @@ -3428,9 +3601,11 @@ public: return nullptr; return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1]; } + /// Determine whether this function type has a non-throwing exception /// specification. CanThrowResult canThrow(const ASTContext &Ctx) const; + /// Determine whether this function type has a non-throwing exception /// specification. If this depends on template arguments, returns /// \c ResultIfDependent. @@ -3453,34 +3628,37 @@ public: unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } - /// Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); } - typedef const QualType *param_type_iterator; - typedef llvm::iterator_range<param_type_iterator> param_type_range; + using param_type_iterator = const QualType *; + using param_type_range = llvm::iterator_range<param_type_iterator>; param_type_range param_types() const { return param_type_range(param_type_begin(), param_type_end()); } + param_type_iterator param_type_begin() const { return reinterpret_cast<const QualType *>(this+1); } + param_type_iterator param_type_end() const { return param_type_begin() + NumParams; } - typedef const QualType *exception_iterator; + using exception_iterator = const QualType *; ArrayRef<QualType> exceptions() const { return llvm::makeArrayRef(exception_begin(), exception_end()); } + exception_iterator exception_begin() const { // exceptions begin where arguments end return param_type_end(); } + exception_iterator exception_end() const { if (getExceptionSpecType() != EST_Dynamic) return exception_begin(); @@ -3495,6 +3673,7 @@ public: return ArrayRef<ExtParameterInfo>(getExtParameterInfosBuffer(), getNumParams()); } + /// Return a pointer to the beginning of the array of extra parameter /// information, if present, or else null if none of the parameters /// carry it. This is equivalent to getExtProtoInfo().ExtParameterInfos. @@ -3548,15 +3727,16 @@ public: /// /// Template instantiation turns these into the underlying type. class UnresolvedUsingType : public Type { + friend class ASTContext; // ASTContext creates these. + UnresolvedUsingTypenameDecl *Decl; UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true, true, false, - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} - friend class ASTContext; // ASTContext creates these. -public: + : Type(UnresolvedUsing, QualType(), true, true, false, + /*ContainsUnexpandedParameterPack=*/false), + Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} +public: UnresolvedUsingTypenameDecl *getDecl() const { return Decl; } bool isSugared() const { return false; } @@ -3569,27 +3749,29 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { return Profile(ID, Decl); } + static void Profile(llvm::FoldingSetNodeID &ID, UnresolvedUsingTypenameDecl *D) { ID.AddPointer(D); } }; - class TypedefType : public Type { TypedefNameDecl *Decl; + protected: + friend class ASTContext; // ASTContext creates these. + TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) - : Type(tc, can, can->isDependentType(), - can->isInstantiationDependentType(), - can->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<TypedefNameDecl*>(D)) { + : Type(tc, can, can->isDependentType(), + can->isInstantiationDependentType(), + can->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + Decl(const_cast<TypedefNameDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } - friend class ASTContext; // ASTContext creates these. -public: +public: TypedefNameDecl *getDecl() const { return Decl; } bool isSugared() const { return true; } @@ -3603,8 +3785,10 @@ class TypeOfExprType : public Type { Expr *TOExpr; protected: + friend class ASTContext; // ASTContext creates these. + TypeOfExprType(Expr *E, QualType can = QualType()); - friend class ASTContext; // ASTContext creates these. + public: Expr *getUnderlyingExpr() const { return TOExpr; } @@ -3629,7 +3813,7 @@ class DependentTypeOfExprType public: DependentTypeOfExprType(const ASTContext &Context, Expr *E) - : TypeOfExprType(E), Context(Context) { } + : TypeOfExprType(E), Context(Context) {} void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Context, getUnderlyingExpr()); @@ -3641,16 +3825,19 @@ public: /// Represents `typeof(type)`, a GCC extension. class TypeOfType : public Type { + friend class ASTContext; // ASTContext creates these. + QualType TOType; + TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->isDependentType(), - T->isInstantiationDependentType(), - T->isVariablyModifiedType(), - T->containsUnexpandedParameterPack()), - TOType(T) { + : Type(TypeOf, can, T->isDependentType(), + T->isInstantiationDependentType(), + T->isVariablyModifiedType(), + T->containsUnexpandedParameterPack()), + TOType(T) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } - friend class ASTContext; // ASTContext creates these. + public: QualType getUnderlyingType() const { return TOType; } @@ -3669,8 +3856,10 @@ class DecltypeType : public Type { QualType UnderlyingType; protected: + friend class ASTContext; // ASTContext creates these. + DecltypeType(Expr *E, QualType underlyingType, QualType can = QualType()); - friend class ASTContext; // ASTContext creates these. + public: Expr *getUnderlyingExpr() const { return E; } QualType getUnderlyingType() const { return UnderlyingType; } @@ -3714,14 +3903,18 @@ public: private: /// The untransformed type. QualType BaseType; + /// The transformed type if not dependent, otherwise the same as BaseType. QualType UnderlyingType; UTTKind UKind; + protected: + friend class ASTContext; + UnaryTransformType(QualType BaseTy, QualType UnderlyingTy, UTTKind UKind, QualType CanonicalTy); - friend class ASTContext; + public: bool isSugared() const { return !isDependentType(); } QualType desugar() const { return UnderlyingType; } @@ -3747,6 +3940,7 @@ class DependentUnaryTransformType : public UnaryTransformType, public: DependentUnaryTransformType(const ASTContext &C, QualType BaseType, UTTKind UKind); + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getBaseType(), getUTTKind()); } @@ -3759,11 +3953,11 @@ public: }; class TagType : public Type { + friend class ASTReader; + /// Stores the TagDecl associated with this type. The decl may point to any /// TagDecl that declares the entity. - TagDecl * decl; - - friend class ASTReader; + TagDecl *decl; protected: TagType(TypeClass TC, const TagDecl *D, QualType can); @@ -3783,21 +3977,21 @@ public: /// to detect TagType objects of structs/unions/classes. class RecordType : public TagType { protected: + friend class ASTContext; // ASTContext creates these. + explicit RecordType(const RecordDecl *D) - : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { } + : TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) {} explicit RecordType(TypeClass TC, RecordDecl *D) - : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { } - friend class ASTContext; // ASTContext creates these. -public: + : TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) {} +public: RecordDecl *getDecl() const { return reinterpret_cast<RecordDecl*>(TagType::getDecl()); } - // FIXME: This predicate is a helper to QualType/Type. It needs to - // recursively check all fields for const-ness. If any field is declared - // const, it needs to return false. - bool hasConstFields() const { return false; } + /// Recursively check all fields in the record for const-ness. If any field + /// is declared const, return true. Otherwise, return false. + bool hasConstFields() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -3808,11 +4002,12 @@ public: /// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of enums. class EnumType : public TagType { + friend class ASTContext; // ASTContext creates these. + explicit EnumType(const EnumDecl *D) - : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { } - friend class ASTContext; // ASTContext creates these. -public: + : TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) {} +public: EnumDecl *getDecl() const { return reinterpret_cast<EnumDecl*>(TagType::getDecl()); } @@ -3887,11 +4082,11 @@ public: }; private: + friend class ASTContext; // ASTContext creates these + QualType ModifiedType; QualType EquivalentType; - friend class ASTContext; // creates these - AttributedType(QualType canon, Kind attrKind, QualType modified, QualType equivalent) : Type(Attributed, canon, equivalent->isDependentType(), @@ -3980,6 +4175,8 @@ public: }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + // Helper data collector for canonical types. struct CanonicalTTPTInfo { unsigned Depth : 15; @@ -3990,31 +4187,30 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { union { // Info for the canonical type. CanonicalTTPTInfo CanTTPTInfo; + // Info for the non-canonical type. TemplateTypeParmDecl *TTPDecl; }; /// Build a non-canonical type. TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) - : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - Canon->containsUnexpandedParameterPack()), - TTPDecl(TTPDecl) { } + : Type(TemplateTypeParm, Canon, /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, + Canon->containsUnexpandedParameterPack()), + TTPDecl(TTPDecl) {} /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) - : Type(TemplateTypeParm, QualType(this, 0), - /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, PP) { + : Type(TemplateTypeParm, QualType(this, 0), + /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, PP) { CanTTPTInfo.Depth = D; CanTTPTInfo.Index = I; CanTTPTInfo.ParameterPack = PP; } - friend class ASTContext; // ASTContext creates these - const CanonicalTTPTInfo& getCanTTPTInfo() const { QualType Can = getCanonicalTypeInternal(); return Can->castAs<TemplateTypeParmType>()->CanTTPTInfo; @@ -4060,17 +4256,17 @@ public: /// type was originally written as a template type parameter; /// therefore they are never canonical. class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + // The original type parameter. const TemplateTypeParmType *Replaced; SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) - : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), - Canon->isInstantiationDependentType(), - Canon->isVariablyModifiedType(), - Canon->containsUnexpandedParameterPack()), - Replaced(Param) { } - - friend class ASTContext; + : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), + Canon->isInstantiationDependentType(), + Canon->isVariablyModifiedType(), + Canon->containsUnexpandedParameterPack()), + Replaced(Param) {} public: /// Gets the template parameter that was substituted for. @@ -4090,6 +4286,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getReplacedParameter(), getReplacementType()); } + static void Profile(llvm::FoldingSetNodeID &ID, const TemplateTypeParmType *Replaced, QualType Replacement) { @@ -4115,6 +4312,8 @@ public: /// arguments), this type will be replaced with the \c SubstTemplateTypeParmType /// at the current pack substitution index. class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + /// \brief The original type parameter. const TemplateTypeParmType *Replaced; @@ -4129,8 +4328,6 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { QualType Canon, const TemplateArgument &ArgPack); - friend class ASTContext; - public: IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } @@ -4204,6 +4401,8 @@ public: /// \brief Represents a C++11 auto or C++14 decltype(auto) type. class AutoType : public DeducedType, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, bool IsDeducedAsDependent) : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent, @@ -4211,12 +4410,11 @@ class AutoType : public DeducedType, public llvm::FoldingSetNode { AutoTypeBits.Keyword = (unsigned)Keyword; } - friend class ASTContext; // ASTContext creates these - public: bool isDecltypeAuto() const { return getKeyword() == AutoTypeKeyword::DecltypeAuto; } + AutoTypeKeyword getKeyword() const { return (AutoTypeKeyword)AutoTypeBits.Keyword; } @@ -4240,6 +4438,8 @@ public: /// \brief Represents a C++17 deduced template specialization type. class DeducedTemplateSpecializationType : public DeducedType, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + /// The name of the template whose arguments will be deduced. TemplateName Template; @@ -4252,8 +4452,6 @@ class DeducedTemplateSpecializationType : public DeducedType, Template.containsUnexpandedParameterPack()), Template(Template) {} - friend class ASTContext; // ASTContext creates these - public: /// Retrieve the name of the template that we are deducing. TemplateName getTemplateName() const { return Template;} @@ -4297,6 +4495,8 @@ public: class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + /// The name of the template being specialized. This is /// either a TemplateName::Template (in which case it is a /// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a @@ -4318,8 +4518,6 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType QualType Canon, QualType Aliased); - friend class ASTContext; // ASTContext creates these - public: /// Determine whether any of the given template arguments are dependent. static bool anyDependentTemplateArguments(ArrayRef<TemplateArgumentLoc> Args, @@ -4328,21 +4526,6 @@ public: static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &, bool &InstantiationDependent); - /// \brief Print a template argument list, including the '<' and '>' - /// enclosing the template arguments. - static void PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef<TemplateArgument> Args, - const PrintingPolicy &Policy, - bool SkipBrackets = false); - - static void PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef<TemplateArgumentLoc> Args, - const PrintingPolicy &Policy); - - static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentListInfo &, - const PrintingPolicy &Policy); - /// True if this template specialization type matches a current /// instantiation in the context in which it is found. bool isCurrentInstantiation() const { @@ -4373,7 +4556,7 @@ public: return *reinterpret_cast<const QualType*>(end()); } - typedef const TemplateArgument * iterator; + using iterator = const TemplateArgument *; iterator begin() const { return getArgs(); } iterator end() const; // defined inline in TemplateBase.h @@ -4400,6 +4583,7 @@ public: bool isSugared() const { return !isDependentType() || isCurrentInstantiation() || isTypeAlias(); } + QualType desugar() const { return getCanonicalTypeInternal(); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { @@ -4417,6 +4601,20 @@ public: } }; +/// \brief Print a template argument list, including the '<' and '>' +/// enclosing the template arguments. +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef<TemplateArgument> Args, + const PrintingPolicy &Policy); + +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef<TemplateArgumentLoc> Args, + const PrintingPolicy &Policy); + +void printTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentListInfo &Args, + const PrintingPolicy &Policy); + /// The injected class name of a C++ class template or class /// template partial specialization. Used to record that a type was /// spelled with a bare identifier rather than as a template-id; the @@ -4435,6 +4633,12 @@ public: /// will canonicalize to the injected class name (when appropriate /// according to the rules of the language). class InjectedClassNameType : public Type { + friend class ASTContext; // ASTContext creates these. + friend class ASTNodeImporter; + friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not + // currently suitable for AST reading, too much + // interdependencies. + CXXRecordDecl *Decl; /// The template specialization which this type represents. @@ -4448,18 +4652,12 @@ class InjectedClassNameType : public Type { /// and always dependent. QualType InjectedType; - friend class ASTContext; // ASTContext creates these. - friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not - // currently suitable for AST reading, too much - // interdependencies. - friend class ASTNodeImporter; - InjectedClassNameType(CXXRecordDecl *D, QualType TST) - : Type(InjectedClassName, QualType(), /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - /*ContainsUnexpandedParameterPack=*/false), - Decl(D), InjectedType(TST) { + : Type(InjectedClassName, QualType(), /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, + /*ContainsUnexpandedParameterPack=*/false), + Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); assert(!TST.hasQualifiers()); assert(TST->isDependentType()); @@ -4467,9 +4665,11 @@ class InjectedClassNameType : public Type { public: QualType getInjectedSpecializationType() const { return InjectedType; } + const TemplateSpecializationType *getInjectedTST() const { return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } + TemplateName getTemplateName() const { return getInjectedTST()->getTemplateName(); } @@ -4488,12 +4688,16 @@ public: enum TagTypeKind { /// \brief The "struct" keyword. TTK_Struct, + /// \brief The "__interface" keyword. TTK_Interface, + /// \brief The "union" keyword. TTK_Union, + /// \brief The "class" keyword. TTK_Class, + /// \brief The "enum" keyword. TTK_Enum }; @@ -4503,17 +4707,23 @@ enum TagTypeKind { enum ElaboratedTypeKeyword { /// \brief The "struct" keyword introduces the elaborated-type-specifier. ETK_Struct, + /// \brief The "__interface" keyword introduces the elaborated-type-specifier. ETK_Interface, + /// \brief The "union" keyword introduces the elaborated-type-specifier. ETK_Union, + /// \brief The "class" keyword introduces the elaborated-type-specifier. ETK_Class, + /// \brief The "enum" keyword introduces the elaborated-type-specifier. ETK_Enum, + /// \brief The "typename" keyword precedes the qualified type name, e.g., /// \c typename T::type. ETK_Typename, + /// \brief No keyword precedes the qualified type name. ETK_None }; @@ -4528,8 +4738,8 @@ protected: QualType Canonical, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack) { + : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, + ContainsUnexpandedParameterPack) { TypeWithKeywordBits.Keyword = Keyword; } @@ -4574,6 +4784,7 @@ public: /// The type itself is always "sugar", used to express what was written /// in the source code but containing no additional semantic information. class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -4594,8 +4805,6 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { "and name qualifier both null."); } - friend class ASTContext; // ASTContext creates these - public: ~ElaboratedType(); @@ -4640,6 +4849,7 @@ public: /// mode, this type is used with non-dependent names to delay name lookup until /// instantiation. class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -4649,13 +4859,11 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) - : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name) {} - - friend class ASTContext; // ASTContext creates these + : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, + /*InstantiationDependent=*/true, + /*VariablyModified=*/false, + NNS->containsUnexpandedParameterPack()), + NNS(NNS), Name(Name) {} public: /// Retrieve the qualification on this type. @@ -4695,6 +4903,7 @@ public: class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType : public TypeWithKeyword, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -4706,20 +4915,19 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType /// specialization. unsigned NumArgs; - const TemplateArgument *getArgBuffer() const { - return reinterpret_cast<const TemplateArgument*>(this+1); - } - TemplateArgument *getArgBuffer() { - return reinterpret_cast<TemplateArgument*>(this+1); - } - DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args, QualType Canon); - friend class ASTContext; // ASTContext creates these + const TemplateArgument *getArgBuffer() const { + return reinterpret_cast<const TemplateArgument*>(this+1); + } + + TemplateArgument *getArgBuffer() { + return reinterpret_cast<TemplateArgument*>(this+1); + } public: NestedNameSpecifier *getQualifier() const { return NNS; } @@ -4739,7 +4947,8 @@ public: return {getArgs(), NumArgs}; } - typedef const TemplateArgument * iterator; + using iterator = const TemplateArgument *; + iterator begin() const { return getArgs(); } iterator end() const; // inline in TemplateBase.h @@ -4785,6 +4994,8 @@ public: /// Here, the pack expansion \c Types&... is represented via a /// PackExpansionType whose pattern is Types&. class PackExpansionType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these + /// \brief The pattern of the pack expansion. QualType Pattern; @@ -4798,14 +5009,12 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { PackExpansionType(QualType Pattern, QualType Canon, Optional<unsigned> NumExpansions) - : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), - /*InstantiationDependent=*/true, - /*VariablyModified=*/Pattern->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - Pattern(Pattern), - NumExpansions(NumExpansions? *NumExpansions + 1: 0) { } - - friend class ASTContext; // ASTContext creates these + : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), + /*InstantiationDependent=*/true, + /*VariablyModified=*/Pattern->isVariablyModifiedType(), + /*ContainsUnexpandedParameterPack=*/false), + Pattern(Pattern), + NumExpansions(NumExpansions ? *NumExpansions + 1 : 0) {} public: /// \brief Retrieve the pattern of this pack expansion, which is the @@ -4847,7 +5056,8 @@ public: template <class T> class ObjCProtocolQualifiers { protected: - ObjCProtocolQualifiers() {} + ObjCProtocolQualifiers() = default; + ObjCProtocolDecl * const *getProtocolStorage() const { return const_cast<ObjCProtocolQualifiers*>(this)->getProtocolStorage(); } @@ -4855,9 +5065,11 @@ protected: ObjCProtocolDecl **getProtocolStorage() { return static_cast<T*>(this)->getProtocolStorageImpl(); } + void setNumProtocols(unsigned N) { static_cast<T*>(this)->setNumProtocolsImpl(N); } + void initialize(ArrayRef<ObjCProtocolDecl *> protocols) { setNumProtocols(protocols.size()); assert(getNumProtocols() == protocols.size() && @@ -4868,8 +5080,8 @@ protected: } public: - typedef ObjCProtocolDecl * const *qual_iterator; - typedef llvm::iterator_range<qual_iterator> qual_range; + using qual_iterator = ObjCProtocolDecl * const *; + using qual_range = llvm::iterator_range<qual_iterator>; qual_range quals() const { return qual_range(qual_begin(), qual_end()); } qual_iterator qual_begin() const { return getProtocolStorage(); } @@ -4907,21 +5119,26 @@ class ObjCTypeParamType : public Type, unsigned NumProtocols : 6; ObjCTypeParamDecl *OTPDecl; + /// The protocols are stored after the ObjCTypeParamType node. In the /// canonical type, the list of protocols are sorted alphabetically /// and uniqued. ObjCProtocolDecl **getProtocolStorageImpl(); + /// Return the number of qualifying protocols in this interface type, /// or 0 if there are none. unsigned getNumProtocolsImpl() const { return NumProtocols; } + void setNumProtocolsImpl(unsigned N) { NumProtocols = N; } + ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can, ArrayRef<ObjCProtocolDecl *> protocols); + public: bool isSugared() const { return true; } QualType desugar() const { return getCanonicalTypeInternal(); } @@ -4969,6 +5186,7 @@ public: class ObjCObjectType : public Type, public ObjCProtocolQualifiers<ObjCObjectType> { friend class ObjCProtocolQualifiers<ObjCObjectType>; + // ObjCObjectType.NumTypeArgs - the number of type arguments stored // after the ObjCObjectPointerType node. // ObjCObjectType.NumProtocols - the number of protocols stored @@ -5004,15 +5222,16 @@ class ObjCObjectType : public Type, } protected: + enum Nonce_ObjCInterface { Nonce_ObjCInterface }; + ObjCObjectType(QualType Canonical, QualType Base, ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf); - enum Nonce_ObjCInterface { Nonce_ObjCInterface }; ObjCObjectType(enum Nonce_ObjCInterface) : Type(ObjCInterface, QualType(), false, false, false, false), - BaseType(QualType(this_(), 0)) { + BaseType(QualType(this_(), 0)) { ObjCObjectTypeBits.NumProtocols = 0; ObjCObjectTypeBits.NumTypeArgs = 0; ObjCObjectTypeBits.IsKindOf = 0; @@ -5032,9 +5251,11 @@ public: bool isObjCId() const { return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCId); } + bool isObjCClass() const { return getBaseType()->isSpecificBuiltinType(BuiltinType::ObjCClass); } + bool isObjCUnqualifiedId() const { return qual_empty() && isObjCId(); } bool isObjCUnqualifiedClass() const { return qual_empty() && isObjCClass(); } bool isObjCUnqualifiedIdOrClass() const { @@ -5125,7 +5346,7 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode { ArrayRef<QualType> typeArgs, ArrayRef<ObjCProtocolDecl *> protocols, bool isKindOf) - : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {} + : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {} public: void Profile(llvm::FoldingSetNodeID &ID); @@ -5163,14 +5384,15 @@ inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() { /// - It is its own base type. That is, if T is an ObjCInterfaceType*, /// T->getBaseType() == QualType(T, 0). class ObjCInterfaceType : public ObjCObjectType { + friend class ASTContext; // ASTContext creates these. + friend class ASTReader; + friend class ObjCInterfaceDecl; + mutable ObjCInterfaceDecl *Decl; ObjCInterfaceType(const ObjCInterfaceDecl *D) - : ObjCObjectType(Nonce_ObjCInterface), - Decl(const_cast<ObjCInterfaceDecl*>(D)) {} - friend class ASTContext; // ASTContext creates these. - friend class ASTReader; - friend class ObjCInterfaceDecl; + : ObjCObjectType(Nonce_ObjCInterface), + Decl(const_cast<ObjCInterfaceDecl*>(D)) {} public: /// Get the declaration of this interface. @@ -5218,16 +5440,17 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { /// Pointers to pointers to Objective C objects are still PointerTypes; /// only the first level of pointer gets it own type implementation. class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType PointeeType; ObjCObjectPointerType(QualType Canonical, QualType Pointee) - : Type(ObjCObjectPointer, Canonical, - Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), - PointeeType(Pointee) {} - friend class ASTContext; // ASTContext creates these. + : Type(ObjCObjectPointer, Canonical, + Pointee->isDependentType(), + Pointee->isInstantiationDependentType(), + Pointee->isVariablyModifiedType(), + Pointee->containsUnexpandedParameterPack()), + PointeeType(Pointee) {} public: /// Gets the type pointed to by this ObjC pointer. @@ -5336,16 +5559,19 @@ public: /// An iterator over the qualifiers on the object type. Provided /// for convenience. This will always iterate over the full set of /// protocols on a type, not just those provided directly. - typedef ObjCObjectType::qual_iterator qual_iterator; - typedef llvm::iterator_range<qual_iterator> qual_range; + using qual_iterator = ObjCObjectType::qual_iterator; + using qual_range = llvm::iterator_range<qual_iterator>; qual_range quals() const { return qual_range(qual_begin(), qual_end()); } + qual_iterator qual_begin() const { return getObjectType()->qual_begin(); } + qual_iterator qual_end() const { return getObjectType()->qual_end(); } + bool qual_empty() const { return getObjectType()->qual_empty(); } /// Return the number of qualifying protocols on the object type. @@ -5377,26 +5603,29 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPointeeType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { ID.AddPointer(T.getAsOpaquePtr()); } + static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } }; class AtomicType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType ValueType; AtomicType(QualType ValTy, QualType Canonical) - : Type(Atomic, Canonical, ValTy->isDependentType(), - ValTy->isInstantiationDependentType(), - ValTy->isVariablyModifiedType(), - ValTy->containsUnexpandedParameterPack()), - ValueType(ValTy) {} - friend class ASTContext; // ASTContext creates these. + : Type(Atomic, Canonical, ValTy->isDependentType(), + ValTy->isInstantiationDependentType(), + ValTy->isVariablyModifiedType(), + ValTy->containsUnexpandedParameterPack()), + ValueType(ValTy) {} - public: +public: /// Gets the type contained by this atomic type, i.e. /// the type returned by performing an atomic load of this atomic type. QualType getValueType() const { return ValueType; } @@ -5407,9 +5636,11 @@ class AtomicType : public Type, public llvm::FoldingSetNode { void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getValueType()); } + static void Profile(llvm::FoldingSetNodeID &ID, QualType T) { ID.AddPointer(T.getAsOpaquePtr()); } + static bool classof(const Type *T) { return T->getTypeClass() == Atomic; } @@ -5417,16 +5648,17 @@ class AtomicType : public Type, public llvm::FoldingSetNode { /// PipeType - OpenCL20. class PipeType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + QualType ElementType; bool isRead; - PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) : - Type(Pipe, CanonicalPtr, elemType->isDependentType(), - elemType->isInstantiationDependentType(), - elemType->isVariablyModifiedType(), - elemType->containsUnexpandedParameterPack()), - ElementType(elemType), isRead(isRead) {} - friend class ASTContext; // ASTContext creates these. + PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) + : Type(Pipe, CanonicalPtr, elemType->isDependentType(), + elemType->isInstantiationDependentType(), + elemType->isVariablyModifiedType(), + elemType->containsUnexpandedParameterPack()), + ElementType(elemType), isRead(isRead) {} public: QualType getElementType() const { return ElementType; } @@ -5476,7 +5708,6 @@ public: QualType apply(const ASTContext &Context, const Type* T) const; }; - // Inline function definitions. inline SplitQualType SplitQualType::getSingleStepDesugaredType() const { @@ -5602,7 +5833,7 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { } /// Return the address space of this type. -inline unsigned QualType::getAddressSpace() const { +inline LangAS QualType::getAddressSpace() const { return getQualifiers().getAddressSpace(); } @@ -5709,88 +5940,117 @@ inline bool Type::isCompoundType() const { inline bool Type::isFunctionType() const { return isa<FunctionType>(CanonicalType); } + inline bool Type::isPointerType() const { return isa<PointerType>(CanonicalType); } + inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } + inline bool Type::isBlockPointerType() const { return isa<BlockPointerType>(CanonicalType); } + inline bool Type::isReferenceType() const { return isa<ReferenceType>(CanonicalType); } + inline bool Type::isLValueReferenceType() const { return isa<LValueReferenceType>(CanonicalType); } + inline bool Type::isRValueReferenceType() const { return isa<RValueReferenceType>(CanonicalType); } + inline bool Type::isFunctionPointerType() const { if (const PointerType *T = getAs<PointerType>()) return T->getPointeeType()->isFunctionType(); else return false; } + inline bool Type::isMemberPointerType() const { return isa<MemberPointerType>(CanonicalType); } + inline bool Type::isMemberFunctionPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) return T->isMemberFunctionPointer(); else return false; } + inline bool Type::isMemberDataPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) return T->isMemberDataPointer(); else return false; } + inline bool Type::isArrayType() const { return isa<ArrayType>(CanonicalType); } + inline bool Type::isConstantArrayType() const { return isa<ConstantArrayType>(CanonicalType); } + inline bool Type::isIncompleteArrayType() const { return isa<IncompleteArrayType>(CanonicalType); } + inline bool Type::isVariableArrayType() const { return isa<VariableArrayType>(CanonicalType); } + inline bool Type::isDependentSizedArrayType() const { return isa<DependentSizedArrayType>(CanonicalType); } + inline bool Type::isBuiltinType() const { return isa<BuiltinType>(CanonicalType); } + inline bool Type::isRecordType() const { return isa<RecordType>(CanonicalType); } + inline bool Type::isEnumeralType() const { return isa<EnumType>(CanonicalType); } + inline bool Type::isAnyComplexType() const { return isa<ComplexType>(CanonicalType); } + inline bool Type::isVectorType() const { return isa<VectorType>(CanonicalType); } + inline bool Type::isExtVectorType() const { return isa<ExtVectorType>(CanonicalType); } + +inline bool Type::isDependentAddressSpaceType() const { + return isa<DependentAddressSpaceType>(CanonicalType); +} + inline bool Type::isObjCObjectPointerType() const { return isa<ObjCObjectPointerType>(CanonicalType); } + inline bool Type::isObjCObjectType() const { return isa<ObjCObjectType>(CanonicalType); } + inline bool Type::isObjCObjectOrInterfaceType() const { return isa<ObjCInterfaceType>(CanonicalType) || isa<ObjCObjectType>(CanonicalType); } + inline bool Type::isAtomicType() const { return isa<AtomicType>(CanonicalType); } @@ -5800,26 +6060,31 @@ inline bool Type::isObjCQualifiedIdType() const { return OPT->isObjCQualifiedIdType(); return false; } + inline bool Type::isObjCQualifiedClassType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedClassType(); return false; } + inline bool Type::isObjCIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCIdType(); return false; } + inline bool Type::isObjCClassType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCClassType(); return false; } + inline bool Type::isObjCSelType() const { if (const PointerType *OPT = getAs<PointerType>()) return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel); return false; } + inline bool Type::isObjCBuiltinType() const { return isObjCIdType() || isObjCClassType() || isObjCSelType(); } @@ -5854,7 +6119,7 @@ inline bool Type::isImageType() const { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) is##Id##Type() || return #include "clang/Basic/OpenCLImageTypes.def" - 0; // end boolean or operation + false; // end boolean or operation } inline bool Type::isPipeType() const { @@ -6133,7 +6398,6 @@ QualType DecayedType::getPointeeType() const { return cast<PointerType>(Decayed)->getPointeeType(); } +} // namespace clang -} // end namespace clang - -#endif +#endif // LLVM_CLANG_AST_TYPE_H diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index ad95f6f8effa..b805160a2780 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1,4 +1,4 @@ -//===--- TypeLoc.h - Type Source Info Wrapper -------------------*- C++ -*-===// +//===- TypeLoc.h - Type Source Info Wrapper ---------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,26 +6,42 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::TypeLoc interface and its subclasses. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_TYPELOC_H #define LLVM_CLANG_AST_TYPELOC_H #include "clang/AST/Decl.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> namespace clang { - class ASTContext; - class ParmVarDecl; - class TypeSourceInfo; - class UnqualTypeLoc; + +class ASTContext; +class CXXRecordDecl; +class Expr; +class ObjCInterfaceDecl; +class ObjCProtocolDecl; +class ObjCTypeParamDecl; +class TemplateTypeParmDecl; +class UnqualTypeLoc; +class UnresolvedUsingTypenameDecl; // Predeclare all the type nodes. #define ABSTRACT_TYPELOC(Class, Base) @@ -41,10 +57,16 @@ class TypeLoc { protected: // The correctness of this relies on the property that, for Type *Ty, // QualType(Ty, 0).getAsOpaquePtr() == (void*) Ty - const void *Ty; - void *Data; + const void *Ty = nullptr; + void *Data = nullptr; public: + TypeLoc() = default; + TypeLoc(QualType ty, void *opaqueData) + : Ty(ty.getAsOpaquePtr()), Data(opaqueData) {} + TypeLoc(const Type *ty, void *opaqueData) + : Ty(ty), Data(opaqueData) {} + /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc /// is of the desired type. /// @@ -88,12 +110,6 @@ public: Qualified }; - TypeLoc() : Ty(nullptr), Data(nullptr) { } - TypeLoc(QualType ty, void *opaqueData) - : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { } - TypeLoc(const Type *ty, void *opaqueData) - : Ty(ty), Data(opaqueData) { } - TypeLocClass getTypeLocClass() const { if (getType().hasLocalQualifiers()) return Qualified; return (TypeLocClass) getType()->getTypeClass(); @@ -134,6 +150,7 @@ public: SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBeginLoc(), getEndLoc()); } + SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); } SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } @@ -228,7 +245,7 @@ inline TypeLoc TypeSourceInfo::getTypeLoc() const { /// no direct qualifiers. class UnqualTypeLoc : public TypeLoc { public: - UnqualTypeLoc() {} + UnqualTypeLoc() = default; UnqualTypeLoc(const Type *Ty, void *Data) : TypeLoc(Ty, Data) {} const Type *getTypePtr() const { @@ -241,6 +258,7 @@ public: private: friend class TypeLoc; + static bool isKind(const TypeLoc &TL) { return !TL.getType().hasLocalQualifiers(); } @@ -253,9 +271,7 @@ private: /// type qualifiers. class QualifiedTypeLoc : public TypeLoc { public: - SourceRange getLocalSourceRange() const { - return SourceRange(); - } + SourceRange getLocalSourceRange() const { return {}; } UnqualTypeLoc getUnqualifiedLoc() const { unsigned align = @@ -296,6 +312,7 @@ public: private: friend class TypeLoc; + static bool isKind(const TypeLoc &TL) { return TL.getType().hasLocalQualifiers(); } @@ -337,12 +354,12 @@ inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { /// InheritingConcreteTypeLoc instead. template <class Base, class Derived, class TypeClass, class LocalData> class ConcreteTypeLoc : public Base { + friend class TypeLoc; const Derived *asDerived() const { return static_cast<const Derived*>(this); } - friend class TypeLoc; static bool isKind(const TypeLoc &TL) { return !TL.getType().hasLocalQualifiers() && Derived::classofType(TL.getTypePtr()); @@ -357,6 +374,7 @@ public: return std::max(unsigned(alignof(LocalData)), asDerived()->getExtraLocalDataAlignment()); } + unsigned getLocalDataSize() const { unsigned size = sizeof(LocalData); unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); @@ -449,9 +467,7 @@ private: return TypeLoc::getLocalAlignmentForType(T); } - TypeLoc getNextTypeLoc(HasNoInnerType _) const { - return TypeLoc(); - } + TypeLoc getNextTypeLoc(HasNoInnerType _) const { return {}; } TypeLoc getNextTypeLoc(QualType T) const { return TypeLoc(T, getNonLocalData()); @@ -464,6 +480,7 @@ private: template <class Base, class Derived, class TypeClass> class InheritingConcreteTypeLoc : public Base { friend class TypeLoc; + static bool classofType(const Type *Ty) { return TypeClass::classof(Ty); } @@ -482,7 +499,6 @@ public: } }; - struct TypeSpecLocInfo { SourceLocation NameLoc; }; @@ -502,22 +518,25 @@ public: SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } + void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } + SourceRange getLocalSourceRange() const { return SourceRange(getNameLoc(), getNameLoc()); } + void initializeLocal(ASTContext &Context, SourceLocation Loc) { setNameLoc(Loc); } private: friend class TypeLoc; + static bool isKind(const TypeLoc &TL); }; - struct BuiltinLocInfo { SourceRange BuiltinRange; }; @@ -531,9 +550,11 @@ public: SourceLocation getBuiltinLoc() const { return getLocalData()->BuiltinRange.getBegin(); } + void setBuiltinLoc(SourceLocation Loc) { getLocalData()->BuiltinRange = Loc; } + void expandBuiltinRange(SourceRange Range) { SourceRange &BuiltinRange = getLocalData()->BuiltinRange; if (!BuiltinRange.getBegin().isValid()) { @@ -579,9 +600,11 @@ public: else return TSS_unspecified; } + bool hasWrittenSignSpec() const { return getWrittenSignSpec() != TSS_unspecified; } + void setWrittenSignSpec(TypeSpecifierSign written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().Sign = written; @@ -593,18 +616,22 @@ public: else return TSW_unspecified; } + bool hasWrittenWidthSpec() const { return getWrittenWidthSpec() != TSW_unspecified; } + void setWrittenWidthSpec(TypeSpecifierWidth written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().Width = written; } TypeSpecifierType getWrittenTypeSpec() const; + bool hasWrittenTypeSpec() const { return getWrittenTypeSpec() != TST_unspecified; } + void setWrittenTypeSpec(TypeSpecifierType written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().Type = written; @@ -616,6 +643,7 @@ public: else return false; } + void setModeAttr(bool written) { if (needsExtraLocalData()) getWrittenBuiltinSpecs().ModeAttr = written; @@ -633,7 +661,6 @@ public: } }; - /// \brief Wrapper for source info for typedefs. class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TypedefTypeLoc, @@ -742,6 +769,7 @@ public: *((SourceLocation*)this->getExtraLocalData()) : SourceLocation(); } + void setProtocolLAngleLoc(SourceLocation Loc) { *((SourceLocation*)this->getExtraLocalData()) = Loc; } @@ -751,6 +779,7 @@ public: *((SourceLocation*)this->getExtraLocalData() + 1) : SourceLocation(); } + void setProtocolRAngleLoc(SourceLocation Loc) { *((SourceLocation*)this->getExtraLocalData() + 1) = Loc; } @@ -763,6 +792,7 @@ public: assert(i < getNumProtocols() && "Index is out of bounds!"); return getProtocolLocArray()[i]; } + void setProtocolLoc(unsigned i, SourceLocation Loc) { assert(i < getNumProtocols() && "Index is out of bounds!"); getProtocolLocArray()[i] = Loc; @@ -785,9 +815,11 @@ public: // as well. return (this->getNumProtocols() + 2) * sizeof(SourceLocation) ; } + unsigned getExtraLocalDataAlignment() const { return alignof(SourceLocation); } + SourceRange getLocalSourceRange() const { SourceLocation start = getNameLoc(); SourceLocation end = getProtocolRAngleLoc(); @@ -938,7 +970,6 @@ public: } }; - struct ObjCObjectTypeLocInfo { SourceLocation TypeArgsLAngleLoc; SourceLocation TypeArgsRAngleLoc; @@ -971,6 +1002,7 @@ public: SourceLocation getTypeArgsLAngleLoc() const { return this->getLocalData()->TypeArgsLAngleLoc; } + void setTypeArgsLAngleLoc(SourceLocation Loc) { this->getLocalData()->TypeArgsLAngleLoc = Loc; } @@ -978,6 +1010,7 @@ public: SourceLocation getTypeArgsRAngleLoc() const { return this->getLocalData()->TypeArgsRAngleLoc; } + void setTypeArgsRAngleLoc(SourceLocation Loc) { this->getLocalData()->TypeArgsRAngleLoc = Loc; } @@ -999,6 +1032,7 @@ public: SourceLocation getProtocolLAngleLoc() const { return this->getLocalData()->ProtocolLAngleLoc; } + void setProtocolLAngleLoc(SourceLocation Loc) { this->getLocalData()->ProtocolLAngleLoc = Loc; } @@ -1006,6 +1040,7 @@ public: SourceLocation getProtocolRAngleLoc() const { return this->getLocalData()->ProtocolRAngleLoc; } + void setProtocolRAngleLoc(SourceLocation Loc) { this->getLocalData()->ProtocolRAngleLoc = Loc; } @@ -1018,6 +1053,7 @@ public: assert(i < getNumProtocols() && "Index is out of bounds!"); return getProtocolLocArray()[i]; } + void setProtocolLoc(unsigned i, SourceLocation Loc) { assert(i < getNumProtocols() && "Index is out of bounds!"); getProtocolLocArray()[i] = Loc; @@ -1073,7 +1109,6 @@ public: } }; - struct ObjCInterfaceLocInfo { SourceLocation NameLoc; SourceLocation NameEndLoc; @@ -1127,12 +1162,15 @@ public: SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } + SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } + void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } + void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } @@ -1161,8 +1199,7 @@ inline TypeLoc TypeLoc::IgnoreParens() const { return *this; } - -struct AdjustedLocInfo { }; // Nothing. +struct AdjustedLocInfo {}; // Nothing. class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc, AdjustedType, AdjustedLocInfo> { @@ -1181,9 +1218,7 @@ public: return getTypePtr()->getOriginalType(); } - SourceRange getLocalSourceRange() const { - return SourceRange(); - } + SourceRange getLocalSourceRange() const { return {}; } unsigned getLocalDataSize() const { // sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique @@ -1210,6 +1245,7 @@ public: SourceLocation getSigilLoc() const { return this->getLocalData()->StarLoc; } + void setSigilLoc(SourceLocation Loc) { this->getLocalData()->StarLoc = Loc; } @@ -1231,7 +1267,6 @@ public: } }; - /// \brief Wrapper for source info for pointers. class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, PointerType> { @@ -1239,12 +1274,12 @@ public: SourceLocation getStarLoc() const { return getSigilLoc(); } + void setStarLoc(SourceLocation Loc) { setSigilLoc(Loc); } }; - /// \brief Wrapper for source info for block pointers. class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, BlockPointerType> { @@ -1252,6 +1287,7 @@ public: SourceLocation getCaretLoc() const { return getSigilLoc(); } + void setCaretLoc(SourceLocation Loc) { setSigilLoc(Loc); } @@ -1269,6 +1305,7 @@ public: SourceLocation getStarLoc() const { return getSigilLoc(); } + void setStarLoc(SourceLocation Loc) { setSigilLoc(Loc); } @@ -1276,9 +1313,11 @@ public: const Type *getClass() const { return getTypePtr()->getClass(); } + TypeSourceInfo *getClassTInfo() const { return getLocalData()->ClassTInfo; } + void setClassTInfo(TypeSourceInfo* TI) { getLocalData()->ClassTInfo = TI; } @@ -1310,7 +1349,6 @@ public: } }; - class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, ReferenceType> { public: @@ -1327,6 +1365,7 @@ public: SourceLocation getAmpLoc() const { return getSigilLoc(); } + void setAmpLoc(SourceLocation Loc) { setSigilLoc(Loc); } @@ -1340,12 +1379,12 @@ public: SourceLocation getAmpAmpLoc() const { return getSigilLoc(); } + void setAmpAmpLoc(SourceLocation Loc) { setSigilLoc(Loc); } }; - struct FunctionLocInfo { SourceLocation LocalRangeBegin; SourceLocation LParenLoc; @@ -1371,10 +1410,12 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, // exception specification information. return (SourceRange *)(getParmArray() + getNumParams()); } + public: SourceLocation getLocalRangeBegin() const { return getLocalData()->LocalRangeBegin; } + void setLocalRangeBegin(SourceLocation L) { getLocalData()->LocalRangeBegin = L; } @@ -1382,6 +1423,7 @@ public: SourceLocation getLocalRangeEnd() const { return getLocalData()->LocalRangeEnd; } + void setLocalRangeEnd(SourceLocation L) { getLocalData()->LocalRangeEnd = L; } @@ -1389,6 +1431,7 @@ public: SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } + void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } @@ -1396,6 +1439,7 @@ public: SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } + void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } @@ -1407,8 +1451,9 @@ public: SourceRange getExceptionSpecRange() const { if (hasExceptionSpec()) return *getExceptionSpecRangePtr(); - return SourceRange(); + return {}; } + void setExceptionSpecRange(SourceRange R) { if (hasExceptionSpec()) *getExceptionSpecRangePtr() = R; @@ -1428,6 +1473,7 @@ public: return 0; return cast<FunctionProtoType>(getTypePtr())->getNumParams(); } + ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; } void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; } @@ -1474,7 +1520,6 @@ class FunctionNoProtoTypeLoc : FunctionNoProtoType> { }; - struct ArrayLocInfo { SourceLocation LBracketLoc, RBracketLoc; Expr *Size; @@ -1489,6 +1534,7 @@ public: SourceLocation getLBracketLoc() const { return getLocalData()->LBracketLoc; } + void setLBracketLoc(SourceLocation Loc) { getLocalData()->LBracketLoc = Loc; } @@ -1496,6 +1542,7 @@ public: SourceLocation getRBracketLoc() const { return getLocalData()->RBracketLoc; } + void setRBracketLoc(SourceLocation Loc) { getLocalData()->RBracketLoc = Loc; } @@ -1507,6 +1554,7 @@ public: Expr *getSizeExpr() const { return getLocalData()->Size; } + void setSizeExpr(Expr *Size) { getLocalData()->Size = Size; } @@ -1557,7 +1605,6 @@ class VariableArrayTypeLoc : VariableArrayType> { }; - // Location information for a TemplateName. Rudimentary for now. struct TemplateNameLocInfo { SourceLocation NameLoc; @@ -1578,6 +1625,7 @@ public: SourceLocation getTemplateKeywordLoc() const { return getLocalData()->TemplateKWLoc; } + void setTemplateKeywordLoc(SourceLocation Loc) { getLocalData()->TemplateKWLoc = Loc; } @@ -1585,6 +1633,7 @@ public: SourceLocation getLAngleLoc() const { return getLocalData()->LAngleLoc; } + void setLAngleLoc(SourceLocation Loc) { getLocalData()->LAngleLoc = Loc; } @@ -1592,6 +1641,7 @@ public: SourceLocation getRAngleLoc() const { return getLocalData()->RAngleLoc; } + void setRAngleLoc(SourceLocation Loc) { getLocalData()->RAngleLoc = Loc; } @@ -1599,9 +1649,11 @@ public: unsigned getNumArgs() const { return getTypePtr()->getNumArgs(); } + void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { getArgInfos()[i] = AI; } + TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { return getArgInfos()[i]; } @@ -1613,6 +1665,7 @@ public: SourceLocation getTemplateNameLoc() const { return getLocalData()->NameLoc; } + void setTemplateNameLoc(SourceLocation Loc) { getLocalData()->NameLoc = Loc; } @@ -1664,6 +1717,74 @@ private: } }; +struct DependentAddressSpaceLocInfo { + Expr *ExprOperand; + SourceRange OperandParens; + SourceLocation AttrLoc; +}; + +class DependentAddressSpaceTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, + DependentAddressSpaceTypeLoc, + DependentAddressSpaceType, + DependentAddressSpaceLocInfo> { +public: + /// The location of the attribute name, i.e. + /// int * __attribute__((address_space(11))) + /// ^~~~~~~~~~~~~ + SourceLocation getAttrNameLoc() const { + return getLocalData()->AttrLoc; + } + void setAttrNameLoc(SourceLocation loc) { + getLocalData()->AttrLoc = loc; + } + + /// The attribute's expression operand, if it has one. + /// int * __attribute__((address_space(11))) + /// ^~ + Expr *getAttrExprOperand() const { + return getLocalData()->ExprOperand; + } + void setAttrExprOperand(Expr *e) { + getLocalData()->ExprOperand = e; + } + + /// The location of the parentheses around the operand, if there is + /// an operand. + /// int * __attribute__((address_space(11))) + /// ^ ^ + SourceRange getAttrOperandParensRange() const { + return getLocalData()->OperandParens; + } + void setAttrOperandParensRange(SourceRange range) { + getLocalData()->OperandParens = range; + } + + SourceRange getLocalSourceRange() const { + SourceRange range(getAttrNameLoc()); + range.setEnd(getAttrOperandParensRange().getEnd()); + return range; + } + + /// Returns the type before the address space attribute application + /// area. + /// int * __attribute__((address_space(11))) * + /// ^ ^ + QualType getInnerType() const { + return this->getTypePtr()->getPointeeType(); + } + + TypeLoc getPointeeTypeLoc() const { + return this->getInnerTypeLoc(); + } + + void initializeLocal(ASTContext &Context, SourceLocation loc) { + setAttrNameLoc(loc); + setAttrOperandParensRange(SourceRange(loc)); + setAttrExprOperand(getTypePtr()->getAddrSpaceExpr()); + } +}; + //===----------------------------------------------------------------------===// // // All of these need proper implementations. @@ -1717,6 +1838,7 @@ public: SourceLocation getTypeofLoc() const { return this->getLocalData()->TypeofLoc; } + void setTypeofLoc(SourceLocation Loc) { this->getLocalData()->TypeofLoc = Loc; } @@ -1724,6 +1846,7 @@ public: SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } + void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } @@ -1731,6 +1854,7 @@ public: SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } + void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } @@ -1738,6 +1862,7 @@ public: SourceRange getParensRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } + void setParensRange(SourceRange range) { setLParenLoc(range.getBegin()); setRParenLoc(range.getEnd()); @@ -1761,6 +1886,7 @@ public: Expr* getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } + // Reimplemented to account for GNU/C++ extension // typeof unary-expression // where there are no parentheses. @@ -1773,9 +1899,11 @@ public: QualType getUnderlyingType() const { return this->getTypePtr()->getUnderlyingType(); } + TypeSourceInfo* getUnderlyingTInfo() const { return this->getLocalData()->UnderlyingTInfo; } + void setUnderlyingTInfo(TypeSourceInfo* TI) const { this->getLocalData()->UnderlyingTInfo = TI; } @@ -1815,6 +1943,7 @@ public: TypeSourceInfo* getUnderlyingTInfo() const { return getLocalData()->UnderlyingTInfo; } + void setUnderlyingTInfo(TypeSourceInfo *TInfo) { getLocalData()->UnderlyingTInfo = TInfo; } @@ -1826,16 +1955,13 @@ public: SourceRange getParensRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } + void setParensRange(SourceRange Range) { setLParenLoc(Range.getBegin()); setRParenLoc(Range.getEnd()); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKWLoc(Loc); - setRParenLoc(Loc); - setLParenLoc(Loc); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); }; class DeducedTypeLoc @@ -1854,6 +1980,7 @@ public: SourceLocation getTemplateNameLoc() const { return getNameLoc(); } + void setTemplateNameLoc(SourceLocation Loc) { setNameLoc(Loc); } @@ -1861,6 +1988,7 @@ public: struct ElaboratedLocInfo { SourceLocation ElaboratedKWLoc; + /// \brief Data associated with the nested-name-specifier location. void *QualifierData; }; @@ -1873,6 +2001,7 @@ public: SourceLocation getElaboratedKeywordLoc() const { return this->getLocalData()->ElaboratedKWLoc; } + void setElaboratedKeywordLoc(SourceLocation Loc) { this->getLocalData()->ElaboratedKWLoc = Loc; } @@ -1931,6 +2060,7 @@ public: SourceLocation getElaboratedKeywordLoc() const { return this->getLocalData()->ElaboratedKWLoc; } + void setElaboratedKeywordLoc(SourceLocation Loc) { this->getLocalData()->ElaboratedKWLoc = Loc; } @@ -1950,6 +2080,7 @@ public: SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } + void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } @@ -1986,6 +2117,7 @@ public: SourceLocation getElaboratedKeywordLoc() const { return this->getLocalData()->ElaboratedKWLoc; } + void setElaboratedKeywordLoc(SourceLocation Loc) { this->getLocalData()->ElaboratedKWLoc = Loc; } @@ -2017,6 +2149,7 @@ public: SourceLocation getTemplateKeywordLoc() const { return getLocalData()->TemplateKWLoc; } + void setTemplateKeywordLoc(SourceLocation Loc) { getLocalData()->TemplateKWLoc = Loc; } @@ -2024,6 +2157,7 @@ public: SourceLocation getTemplateNameLoc() const { return this->getLocalData()->NameLoc; } + void setTemplateNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; } @@ -2031,6 +2165,7 @@ public: SourceLocation getLAngleLoc() const { return this->getLocalData()->LAngleLoc; } + void setLAngleLoc(SourceLocation Loc) { this->getLocalData()->LAngleLoc = Loc; } @@ -2038,6 +2173,7 @@ public: SourceLocation getRAngleLoc() const { return this->getLocalData()->RAngleLoc; } + void setRAngleLoc(SourceLocation Loc) { this->getLocalData()->RAngleLoc = Loc; } @@ -2049,6 +2185,7 @@ public: void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { getArgInfos()[i] = AI; } + TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { return getArgInfos()[i]; } @@ -2090,7 +2227,6 @@ private: } }; - struct PackExpansionTypeLocInfo { SourceLocation EllipsisLoc; }; @@ -2142,6 +2278,7 @@ public: SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; } + void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; } @@ -2149,6 +2286,7 @@ public: SourceLocation getLParenLoc() const { return this->getLocalData()->LParenLoc; } + void setLParenLoc(SourceLocation Loc) { this->getLocalData()->LParenLoc = Loc; } @@ -2156,6 +2294,7 @@ public: SourceLocation getRParenLoc() const { return this->getLocalData()->RParenLoc; } + void setRParenLoc(SourceLocation Loc) { this->getLocalData()->RParenLoc = Loc; } @@ -2163,6 +2302,7 @@ public: SourceRange getParensRange() const { return SourceRange(getLParenLoc(), getRParenLoc()); } + void setParensRange(SourceRange Range) { setLParenLoc(Range.getBegin()); setRParenLoc(Range.getEnd()); @@ -2217,6 +2357,7 @@ inline T TypeLoc::getAsAdjusted() const { } return Cur.getAs<T>(); } -} -#endif +} // namespace clang + +#endif // LLVM_CLANG_AST_TYPELOC_H diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 9d1d09e2cc66..66697fa0d0fa 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -23,7 +23,7 @@ // NON_CANONICAL_TYPE(Class, Base) - A type that can show up // anywhere in the AST but will never be a part of a canonical // type. Clients that only need to deal with canonical types -// (ignoring, e.g., typedefs and other type alises used for +// (ignoring, e.g., typedefs and other type aliases used for // pretty-printing) can ignore these types. // // DEPENDENT_TYPE(Class, Base) - A type that will only show up @@ -73,6 +73,7 @@ TYPE(IncompleteArray, ArrayType) TYPE(VariableArray, ArrayType) DEPENDENT_TYPE(DependentSizedArray, ArrayType) DEPENDENT_TYPE(DependentSizedExtVector, Type) +DEPENDENT_TYPE(DependentAddressSpace, Type) TYPE(Vector, Type) TYPE(ExtVector, VectorType) ABSTRACT_TYPE(Function, Type) diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index b63c6eb21769..614ff9bf2efd 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -1,4 +1,4 @@ -//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- C++ -*-===// +//===- UnresolvedSet.h - Unresolved sets of declarations --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,20 +17,25 @@ #include "clang/AST/DeclAccessPair.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/Specifiers.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" +#include <cstddef> +#include <iterator> namespace clang { +class NamedDecl; + /// The iterator over UnresolvedSets. Serves as both the const and /// non-const iterator. class UnresolvedSetIterator : public llvm::iterator_adaptor_base< UnresolvedSetIterator, DeclAccessPair *, std::random_access_iterator_tag, NamedDecl *, std::ptrdiff_t, NamedDecl *, NamedDecl *> { - friend class UnresolvedSetImpl; friend class ASTUnresolvedSet; friend class OverloadExpr; + friend class UnresolvedSetImpl; explicit UnresolvedSetIterator(DeclAccessPair *Iter) : iterator_adaptor_base(Iter) {} @@ -54,12 +59,13 @@ public: /// \brief A set of unresolved declarations. class UnresolvedSetImpl { - typedef SmallVectorImpl<DeclAccessPair> DeclsTy; + using DeclsTy = SmallVectorImpl<DeclAccessPair>; // Don't allow direct construction, and only permit subclassing by // UnresolvedSet. private: template <unsigned N> friend class UnresolvedSet; + UnresolvedSetImpl() = default; UnresolvedSetImpl(const UnresolvedSetImpl &) = default; UnresolvedSetImpl &operator=(const UnresolvedSetImpl &) = default; @@ -71,8 +77,8 @@ private: public: // We don't currently support assignment through this iterator, so we might // as well use the same implementation twice. - typedef UnresolvedSetIterator iterator; - typedef UnresolvedSetIterator const_iterator; + using iterator = UnresolvedSetIterator; + using const_iterator = UnresolvedSetIterator; iterator begin() { return iterator(decls().begin()); } iterator end() { return iterator(decls().end()); } @@ -140,7 +146,7 @@ template <unsigned InlineCapacity> class UnresolvedSet : SmallVector<DeclAccessPair, InlineCapacity> Decls; }; - + } // namespace clang -#endif +#endif // LLVM_CLANG_AST_UNRESOLVEDSET_H diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h index b4a6fe3bdb94..178139477d00 100644 --- a/include/clang/AST/VTTBuilder.h +++ b/include/clang/AST/VTTBuilder.h @@ -1,4 +1,4 @@ -//===--- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-=// +//===- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,25 +16,31 @@ #define LLVM_CLANG_AST_VTTBUILDER_H #include "clang/AST/BaseSubobject.h" -#include "clang/AST/CXXInheritance.h" -#include "clang/AST/GlobalDecl.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/ABI.h" -#include <utility> +#include "clang/AST/CharUnits.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include <cstdint> namespace clang { +class ASTContext; +class ASTRecordLayout; +class CXXRecordDecl; + class VTTVTable { llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual; CharUnits BaseOffset; public: - VTTVTable() {} + VTTVTable() = default; VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual) - : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {} + : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {} VTTVTable(BaseSubobject Base, bool BaseIsVirtual) - : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual), - BaseOffset(Base.getBaseOffset()) {} + : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual), + BaseOffset(Base.getBaseOffset()) {} const CXXRecordDecl *getBase() const { return BaseAndIsVirtual.getPointer(); @@ -57,25 +63,24 @@ struct VTTComponent { uint64_t VTableIndex; BaseSubobject VTableBase; - VTTComponent() {} + VTTComponent() = default; VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase) - : VTableIndex(VTableIndex), VTableBase(VTableBase) {} + : VTableIndex(VTableIndex), VTableBase(VTableBase) {} }; /// \brief Class for building VTT layout information. class VTTBuilder { - ASTContext &Ctx; /// \brief The most derived class for which we're building this vtable. const CXXRecordDecl *MostDerivedClass; - typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy; + using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>; /// \brief The VTT vtables. VTTVTablesVectorTy VTTVTables; - typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy; + using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>; /// \brief The VTT components. VTTComponentsVectorTy VTTComponents; @@ -83,9 +88,9 @@ class VTTBuilder { /// \brief The AST record layout of the most derived class. const ASTRecordLayout &MostDerivedClassLayout; - typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; + using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>; - typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; + using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>; /// \brief The sub-VTT indices for the bases of the most derived class. llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies; @@ -153,9 +158,8 @@ public: getSecondaryVirtualPointerIndices() const { return SecondaryVirtualPointerIndices; } - }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_VTTBUILDER_H diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index c9b496df33f7..64e7e908d51e 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -1,4 +1,4 @@ -//===--- ASTMatchers.h - Structural query framework -------------*- C++ -*-===// +//===- ASTMatchers.h - Structural query framework ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -25,7 +25,7 @@ // // For example, when we're interested in child classes of a certain class, we // would write: -// cxxRecordDecl(hasName("MyClass"), hasChild(id("child", recordDecl()))) +// cxxRecordDecl(hasName("MyClass"), has(id("child", recordDecl()))) // When the match is found via the MatchFinder, a user provided callback will // be called with a BoundNodes instance that contains a mapping from the // strings that we provided for the id(...) calls to the nodes that were @@ -46,13 +46,48 @@ #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" #include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "clang/Basic/AttrKinds.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TypeTraits.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Regex.h" +#include <cassert> +#include <cstddef> #include <iterator> +#include <limits> +#include <string> +#include <utility> +#include <vector> namespace clang { namespace ast_matchers { @@ -78,7 +113,7 @@ public: /// \brief Type of mapping from binding identifiers to bound nodes. This type /// is an associative container with a key type of \c std::string and a value /// type of \c clang::ast_type_traits::DynTypedNode - typedef internal::BoundNodesMap::IDToNodeMap IDToNodeMap; + using IDToNodeMap = internal::BoundNodesMap::IDToNodeMap; /// \brief Retrieve mapping from binding identifiers to bound nodes. const IDToNodeMap &getMap() const { @@ -86,13 +121,13 @@ public: } private: + friend class internal::BoundNodesTreeBuilder; + /// \brief Create BoundNodes from a pre-filled map of bindings. BoundNodes(internal::BoundNodesMap &MyBoundNodes) : MyBoundNodes(MyBoundNodes) {} internal::BoundNodesMap MyBoundNodes; - - friend class internal::BoundNodesTreeBuilder; }; /// \brief If the provided matcher matches a node, binds the node to \c ID. @@ -107,13 +142,13 @@ internal::Matcher<T> id(StringRef ID, /// \brief Types of matchers for the top-level classes in the AST class /// hierarchy. /// @{ -typedef internal::Matcher<Decl> DeclarationMatcher; -typedef internal::Matcher<Stmt> StatementMatcher; -typedef internal::Matcher<QualType> TypeMatcher; -typedef internal::Matcher<TypeLoc> TypeLocMatcher; -typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher; -typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher; -typedef internal::Matcher<CXXCtorInitializer> CXXCtorInitializerMatcher; +using DeclarationMatcher = internal::Matcher<Decl>; +using StatementMatcher = internal::Matcher<Stmt>; +using TypeMatcher = internal::Matcher<QualType>; +using TypeLocMatcher = internal::Matcher<TypeLoc>; +using NestedNameSpecifierMatcher = internal::Matcher<NestedNameSpecifier>; +using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>; +using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>; /// @} /// \brief Matches any node. @@ -143,7 +178,7 @@ inline internal::TrueMatcher anything() { return internal::TrueMatcher(); } /// \endcode /// decl(hasDeclContext(translationUnitDecl())) /// matches "int X", but not "int Y". -const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> +extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> translationUnitDecl; /// \brief Matches typedef declarations. @@ -155,7 +190,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> /// \endcode /// typedefDecl() /// matches "typedef int X", but not "using Y = int" -const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> + typedefDecl; /// \brief Matches typedef name declarations. /// @@ -166,7 +202,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl; /// \endcode /// typedefNameDecl() /// matches "typedef int X" and "using Y = int" -const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> +extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> typedefNameDecl; /// \brief Matches type alias declarations. @@ -178,7 +214,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> /// \endcode /// typeAliasDecl() /// matches "using Y = int", but not "typedef int X" -const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> + typeAliasDecl; /// \brief Matches type alias template declarations. /// @@ -187,7 +224,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl; /// template <typename T> /// using Y = X<T>; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl> +extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl> typeAliasTemplateDecl; /// \brief Matches AST nodes that were expanded within the main-file. @@ -278,7 +315,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching, /// friend X; /// }; /// \endcode -const internal::VariadicAllOfMatcher<Decl> decl; +extern const internal::VariadicAllOfMatcher<Decl> decl; /// \brief Matches a declaration of a linkage specification. /// @@ -288,7 +325,7 @@ const internal::VariadicAllOfMatcher<Decl> decl; /// \endcode /// linkageSpecDecl() /// matches "extern "C" {}" -const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> +extern const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> linkageSpecDecl; /// \brief Matches a declaration of anything that could have a name. @@ -302,7 +339,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> /// } U; /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; /// \brief Matches a declaration of label. /// @@ -313,7 +350,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; /// \endcode /// labelDecl() /// matches 'FOO:' -const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl; /// \brief Matches a declaration of a namespace. /// @@ -324,7 +361,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl; /// \endcode /// namespaceDecl() /// matches "namespace {}" and "namespace test {}" -const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> + namespaceDecl; /// \brief Matches a declaration of a namespace alias. /// @@ -335,7 +373,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl; /// \endcode /// namespaceAliasDecl() /// matches "namespace alias" but not "namespace test" -const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl> +extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl> namespaceAliasDecl; /// \brief Matches class, struct, and union declarations. @@ -347,9 +385,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl> /// struct S {}; /// union U {}; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - RecordDecl> recordDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl; /// \brief Matches C++ class declarations. /// @@ -358,9 +394,8 @@ const internal::VariadicDynCastAllOfMatcher< /// class X; /// template<class T> class Z {}; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - CXXRecordDecl> cxxRecordDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> + cxxRecordDecl; /// \brief Matches C++ class template declarations. /// @@ -368,9 +403,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// template<class T> class Z {}; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ClassTemplateDecl> classTemplateDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl> + classTemplateDecl; /// \brief Matches C++ class template specializations. /// @@ -382,9 +416,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// classTemplateSpecializationDecl() /// matches the specializations \c A<int> and \c A<double> -const internal::VariadicDynCastAllOfMatcher< - Decl, - ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; +extern const internal::VariadicDynCastAllOfMatcher< + Decl, ClassTemplateSpecializationDecl> + classTemplateSpecializationDecl; /// \brief Matches declarator declarations (field, variable, function /// and non-type template parameter declarations). @@ -395,7 +429,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// declaratorDecl() /// matches \c int y. -const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> +extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> declaratorDecl; /// \brief Matches parameter variable declarations. @@ -406,7 +440,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> /// \endcode /// parmVarDecl() /// matches \c int x. -const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> + parmVarDecl; /// \brief Matches C++ access specifier declarations. /// @@ -419,9 +454,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl; /// \endcode /// accessSpecDecl() /// matches 'public:' -const internal::VariadicDynCastAllOfMatcher< - Decl, - AccessSpecDecl> accessSpecDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl> + accessSpecDecl; /// \brief Matches constructor initializers. /// @@ -432,7 +466,8 @@ const internal::VariadicDynCastAllOfMatcher< /// int i; /// }; /// \endcode -const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer; +extern const internal::VariadicAllOfMatcher<CXXCtorInitializer> + cxxCtorInitializer; /// \brief Matches template arguments. /// @@ -443,7 +478,7 @@ const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer; /// \endcode /// templateArgument() /// matches 'int' in C<int>. -const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; +extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; /// \brief Matches template name. /// @@ -454,7 +489,7 @@ const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; /// \endcode /// templateName() /// matches 'X' in X<int>. -const internal::VariadicAllOfMatcher<TemplateName> templateName; +extern const internal::VariadicAllOfMatcher<TemplateName> templateName; /// \brief Matches non-type template parameter declarations. /// @@ -464,9 +499,9 @@ const internal::VariadicAllOfMatcher<TemplateName> templateName; /// \endcode /// nonTypeTemplateParmDecl() /// matches 'N', but not 'T'. -const internal::VariadicDynCastAllOfMatcher< - Decl, - NonTypeTemplateParmDecl> nonTypeTemplateParmDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, + NonTypeTemplateParmDecl> + nonTypeTemplateParmDecl; /// \brief Matches template type parameter declarations. /// @@ -476,9 +511,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// templateTypeParmDecl() /// matches 'T', but not 'N'. -const internal::VariadicDynCastAllOfMatcher< - Decl, - TemplateTypeParmDecl> templateTypeParmDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl> + templateTypeParmDecl; /// \brief Matches public C++ declarations. /// @@ -582,6 +616,23 @@ AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>, InnerMatcher.matches(*Initializer, Finder, Builder)); } +/// \brief Matches the specialized template of a specialization declaration. +/// +/// Given +/// \code +/// tempalate<typename T> class A {}; +/// typedef A<int> B; +/// \endcode +/// classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl())) +/// matches 'B' with classTemplateDecl() matching the class template +/// declaration of 'A'. +AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate, + internal::Matcher<ClassTemplateDecl>, InnerMatcher) { + const ClassTemplateDecl* Decl = Node.getSpecializedTemplate(); + return (Decl != nullptr && + InnerMatcher.matches(*Decl, Finder, Builder)); +} + /// \brief Matches a declaration that has been implicitly added /// by the compiler (eg. implicit default/copy constructors). AST_MATCHER(Decl, isImplicit) { @@ -922,7 +973,7 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue, /// enum X { A, B, C }; /// void F(); /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; /// \brief Matches C++ constructor declarations. /// @@ -935,9 +986,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; /// int DoSomething(); /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - CXXConstructorDecl> cxxConstructorDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl> + cxxConstructorDecl; /// \brief Matches explicit C++ destructor declarations. /// @@ -948,9 +998,8 @@ const internal::VariadicDynCastAllOfMatcher< /// virtual ~Foo(); /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - CXXDestructorDecl> cxxDestructorDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> + cxxDestructorDecl; /// \brief Matches enum declarations. /// @@ -960,7 +1009,7 @@ const internal::VariadicDynCastAllOfMatcher< /// A, B, C /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; /// \brief Matches enum constants. /// @@ -970,9 +1019,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; /// A, B, C /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - EnumConstantDecl> enumConstantDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> + enumConstantDecl; /// \brief Matches method declarations. /// @@ -980,7 +1028,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// class X { void y(); }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> + cxxMethodDecl; /// \brief Matches conversion operator declarations. /// @@ -988,7 +1037,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; /// \code /// class X { operator int() const; }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> +extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> cxxConversionDecl; /// \brief Matches variable declarations. @@ -1000,7 +1049,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> /// \code /// int a; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; /// \brief Matches field declarations. /// @@ -1010,7 +1059,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; /// \endcode /// fieldDecl() /// matches 'm'. -const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; /// \brief Matches function declarations. /// @@ -1018,7 +1067,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; /// \code /// void f(); /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> + functionDecl; /// \brief Matches C++ function template declarations. /// @@ -1026,9 +1076,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl; /// \code /// template<class T> void f(T t) {} /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - FunctionTemplateDecl> functionTemplateDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl> + functionTemplateDecl; /// \brief Matches friend declarations. /// @@ -1038,7 +1087,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// friendDecl() /// matches 'friend void foo()'. -const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; /// \brief Matches statements. /// @@ -1048,7 +1097,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; /// \endcode /// stmt() /// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicAllOfMatcher<Stmt> stmt; +extern const internal::VariadicAllOfMatcher<Stmt> stmt; /// \brief Matches declaration statements. /// @@ -1058,9 +1107,7 @@ const internal::VariadicAllOfMatcher<Stmt> stmt; /// \endcode /// declStmt() /// matches 'int a'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - DeclStmt> declStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt; /// \brief Matches member expressions. /// @@ -1073,7 +1120,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// memberExpr() /// matches this->x, x, y.x, a, this->b -const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; /// \brief Matches call expressions. /// @@ -1083,7 +1130,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; /// x.y(); /// y(); /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; /// \brief Matches lambda expressions. /// @@ -1091,7 +1138,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; /// \code /// [&](){return 5;} /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; /// \brief Matches member call expressions. /// @@ -1100,9 +1147,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; /// X x; /// x.y(); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXMemberCallExpr> cxxMemberCallExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> + cxxMemberCallExpr; /// \brief Matches ObjectiveC Message invocation expressions. /// @@ -1113,9 +1159,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// [[NSString alloc] initWithString:@"Hello"] /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ObjCMessageExpr> objcMessageExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr> + objcMessageExpr; /// \brief Matches Objective-C interface declarations. /// @@ -1124,9 +1169,18 @@ const internal::VariadicDynCastAllOfMatcher< /// @interface Foo /// @end /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ObjCInterfaceDecl> objcInterfaceDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl> + objcInterfaceDecl; + +/// \brief Matches Objective-C implementation declarations. +/// +/// Example matches Foo +/// \code +/// @implementation Foo +/// @end +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl> + objcImplementationDecl; /// \brief Matches Objective-C protocol declarations. /// @@ -1135,9 +1189,8 @@ const internal::VariadicDynCastAllOfMatcher< /// @protocol FooDelegate /// @end /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ObjCProtocolDecl> objcProtocolDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl> + objcProtocolDecl; /// \brief Matches Objective-C category declarations. /// @@ -1146,9 +1199,18 @@ const internal::VariadicDynCastAllOfMatcher< /// @interface Foo (Additions) /// @end /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ObjCCategoryDecl> objcCategoryDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl> + objcCategoryDecl; + +/// \brief Matches Objective-C category definitions. +/// +/// Example matches Foo (Additions) +/// \code +/// @implementation Foo (Additions) +/// @end +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl> + objcCategoryImplDecl; /// \brief Matches Objective-C method declarations. /// @@ -1162,9 +1224,8 @@ const internal::VariadicDynCastAllOfMatcher< /// - (void)method {} /// @end /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ObjCMethodDecl> objcMethodDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl> + objcMethodDecl; /// \brief Matches Objective-C instance variable declarations. /// @@ -1175,9 +1236,8 @@ const internal::VariadicDynCastAllOfMatcher< /// } /// @end /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ObjCIvarDecl> objcIvarDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> + objcIvarDecl; /// \brief Matches Objective-C property declarations. /// @@ -1187,9 +1247,47 @@ const internal::VariadicDynCastAllOfMatcher< /// @property BOOL enabled; /// @end /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ObjCPropertyDecl> objcPropertyDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl> + objcPropertyDecl; + +/// \brief Matches Objective-C \@throw statements. +/// +/// Example matches \@throw +/// \code +/// @throw obj; +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt> + objcThrowStmt; + +/// \brief Matches Objective-C @try statements. +/// +/// Example matches @try +/// \code +/// @try {} +/// @catch (...) {} +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt> + objcTryStmt; + +/// \brief Matches Objective-C @catch statements. +/// +/// Example matches @catch +/// \code +/// @try {} +/// @catch (...) {} +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt> + objcCatchStmt; + +/// \brief Matches Objective-C @finally statements. +/// +/// Example matches @finally +/// \code +/// @try {} +/// @finally {} +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt> + objcFinallyStmt; /// \brief Matches expressions that introduce cleanups to be run at the end /// of the sub-expression's evaluation. @@ -1198,9 +1296,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// const std::string str = std::string(); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ExprWithCleanups> exprWithCleanups; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups> + exprWithCleanups; /// \brief Matches init list expressions. /// @@ -1212,7 +1309,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// initListExpr() /// matches "{ 1, 2 }" and "{ 5, 6 }" -const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> + initListExpr; /// \brief Matches the syntactic form of init list expressions /// (if expression have it). @@ -1234,8 +1332,9 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm, /// \endcode /// cxxStdInitializerListExpr() /// matches "{ 1, 2, 3 }" and "{ 4, 5 }" -const internal::VariadicDynCastAllOfMatcher<Stmt, - CXXStdInitializerListExpr> cxxStdInitializerListExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + CXXStdInitializerListExpr> + cxxStdInitializerListExpr; /// \brief Matches implicit initializers of init list expressions. /// @@ -1245,8 +1344,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, /// \endcode /// implicitValueInitExpr() /// matches "[0].y" (implicitly) -const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr> -implicitValueInitExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr> + implicitValueInitExpr; /// \brief Matches paren list expressions. /// ParenListExprs don't have a predefined type and are used for late parsing. @@ -1263,7 +1362,8 @@ implicitValueInitExpr; /// \endcode /// parenListExpr() matches "*this" but NOT matches (a, b) because (a, b) /// has a predefined type and is a ParenExpr, not a ParenListExpr. -const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> + parenListExpr; /// \brief Matches substitutions of non-type template parameters. /// @@ -1275,9 +1375,9 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr; /// \endcode /// substNonTypeTemplateParmExpr() /// matches "N" in the right-hand side of "static const int n = N;" -const internal::VariadicDynCastAllOfMatcher< - Stmt, - SubstNonTypeTemplateParmExpr> substNonTypeTemplateParmExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + SubstNonTypeTemplateParmExpr> + substNonTypeTemplateParmExpr; /// \brief Matches using declarations. /// @@ -1288,7 +1388,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// usingDecl() /// matches \code using X::x \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; /// \brief Matches using namespace declarations. /// @@ -1299,9 +1399,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; /// \endcode /// usingDirectiveDecl() /// matches \code using namespace X \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - UsingDirectiveDecl> usingDirectiveDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl> + usingDirectiveDecl; /// \brief Matches reference to a name that can be looked up during parsing /// but could not be resolved to a specific declaration. @@ -1317,9 +1416,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// unresolvedLookupExpr() /// matches \code foo<T>() \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - UnresolvedLookupExpr> unresolvedLookupExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr> + unresolvedLookupExpr; /// \brief Matches unresolved using value declarations. /// @@ -1332,9 +1430,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// unresolvedUsingValueDecl() /// matches \code using X::x \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - UnresolvedUsingValueDecl> unresolvedUsingValueDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, + UnresolvedUsingValueDecl> + unresolvedUsingValueDecl; /// \brief Matches unresolved using value declarations that involve the /// typename. @@ -1351,9 +1449,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// unresolvedUsingTypenameDecl() /// matches \code using Base<T>::Foo \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - UnresolvedUsingTypenameDecl> unresolvedUsingTypenameDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, + UnresolvedUsingTypenameDecl> + unresolvedUsingTypenameDecl; /// \brief Matches parentheses used in expressions. /// @@ -1362,9 +1460,7 @@ const internal::VariadicDynCastAllOfMatcher< /// int foo() { return 1; } /// int a = (foo() + 1); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ParenExpr> parenExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr; /// \brief Matches constructor call expressions (including implicit ones). /// @@ -1376,9 +1472,8 @@ const internal::VariadicDynCastAllOfMatcher< /// int n; /// f(string(ptr, n), ptr); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXConstructExpr> cxxConstructExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr> + cxxConstructExpr; /// \brief Matches unresolved constructor call expressions. /// @@ -1388,9 +1483,9 @@ const internal::VariadicDynCastAllOfMatcher< /// template <typename T> /// void f(const T& t) { return T(t); } /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXUnresolvedConstructExpr> cxxUnresolvedConstructExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + CXXUnresolvedConstructExpr> + cxxUnresolvedConstructExpr; /// \brief Matches implicit and explicit this expressions. /// @@ -1402,7 +1497,8 @@ const internal::VariadicDynCastAllOfMatcher< /// int f() { return i; } /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> + cxxThisExpr; /// \brief Matches nodes where temporaries are created. /// @@ -1412,9 +1508,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr; /// FunctionTakesString(GetStringByValue()); /// FunctionTakesStringByPointer(GetStringPointer()); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXBindTemporaryExpr> cxxBindTemporaryExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr> + cxxBindTemporaryExpr; /// \brief Matches nodes where temporaries are materialized. /// @@ -1434,9 +1529,9 @@ const internal::VariadicDynCastAllOfMatcher< /// f(); /// f().func(); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - MaterializeTemporaryExpr> materializeTemporaryExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + MaterializeTemporaryExpr> + materializeTemporaryExpr; /// \brief Matches new expressions. /// @@ -1446,7 +1541,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// cxxNewExpr() /// matches 'new X'. -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; /// \brief Matches delete expressions. /// @@ -1456,7 +1551,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; /// \endcode /// cxxDeleteExpr() /// matches 'delete X'. -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> + cxxDeleteExpr; /// \brief Matches array subscript expressions. /// @@ -1466,9 +1562,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr; /// \endcode /// arraySubscriptExpr() /// matches "a[1]" -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ArraySubscriptExpr> arraySubscriptExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr> + arraySubscriptExpr; /// \brief Matches the value of a default argument at the call site. /// @@ -1479,9 +1574,8 @@ const internal::VariadicDynCastAllOfMatcher< /// void f(int x, int y = 0); /// f(42); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXDefaultArgExpr> cxxDefaultArgExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr> + cxxDefaultArgExpr; /// \brief Matches overloaded operator calls. /// @@ -1497,9 +1591,8 @@ const internal::VariadicDynCastAllOfMatcher< /// ostream &o; int b = 1, c = 1; /// o << b << c; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXOperatorCallExpr> cxxOperatorCallExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr> + cxxOperatorCallExpr; /// \brief Matches expressions. /// @@ -1507,7 +1600,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// void f() { x(); } /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; /// \brief Matches expressions that refer to declarations. /// @@ -1516,7 +1609,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; /// bool x; /// if (x) {} /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> + declRefExpr; /// \brief Matches if statements. /// @@ -1524,7 +1618,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; /// \code /// if (x) {} /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; /// \brief Matches for statements. /// @@ -1533,7 +1627,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; /// for (;;) {} /// int i[] = {1, 2, 3}; for (auto a : i); /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; /// \brief Matches the increment statement of a for loop. /// @@ -1571,9 +1665,8 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, /// int i[] = {1, 2, 3}; for (auto a : i); /// for(int j = 0; j < 5; ++j); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXForRangeStmt> cxxForRangeStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> + cxxForRangeStmt; /// \brief Matches the initialization statement of a for loop. /// @@ -1611,7 +1704,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>, /// \endcode /// whileStmt() /// matches 'while (true) {}'. -const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; /// \brief Matches do statements. /// @@ -1621,7 +1714,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; /// \endcode /// doStmt() /// matches 'do {} while(true)' -const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; /// \brief Matches break statements. /// @@ -1631,7 +1724,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; /// \endcode /// breakStmt() /// matches 'break' -const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; /// \brief Matches continue statements. /// @@ -1641,7 +1734,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; /// \endcode /// continueStmt() /// matches 'continue' -const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> + continueStmt; /// \brief Matches return statements. /// @@ -1651,7 +1745,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; /// \endcode /// returnStmt() /// matches 'return 1' -const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; /// \brief Matches goto statements. /// @@ -1662,7 +1756,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; /// \endcode /// gotoStmt() /// matches 'goto FOO' -const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; /// \brief Matches label statements. /// @@ -1673,7 +1767,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; /// \endcode /// labelStmt() /// matches 'FOO:' -const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; /// \brief Matches address of label statements (GNU extension). /// @@ -1685,7 +1779,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; /// \endcode /// addrLabelExpr() /// matches '&&FOO' -const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> + addrLabelExpr; /// \brief Matches switch statements. /// @@ -1695,7 +1790,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr; /// \endcode /// switchStmt() /// matches 'switch(a)'. -const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; /// \brief Matches case and default statements inside switch statements. /// @@ -1705,7 +1800,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; /// \endcode /// switchCase() /// matches 'case 42: break;' and 'default: break;'. -const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; /// \brief Matches case statements inside switch statements. /// @@ -1715,7 +1810,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; /// \endcode /// caseStmt() /// matches 'case 42: break;'. -const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; /// \brief Matches default statements inside switch statements. /// @@ -1725,7 +1820,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; /// \endcode /// defaultStmt() /// matches 'default: break;'. -const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> + defaultStmt; /// \brief Matches compound statements. /// @@ -1733,7 +1829,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt; /// \code /// for (;;) {{}} /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> + compoundStmt; /// \brief Matches catch statements. /// @@ -1742,7 +1839,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt; /// \endcode /// cxxCatchStmt() /// matches 'catch(int i)' -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> + cxxCatchStmt; /// \brief Matches try statements. /// @@ -1751,7 +1849,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt; /// \endcode /// cxxTryStmt() /// matches 'try {}' -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; /// \brief Matches throw expressions. /// @@ -1760,7 +1858,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; /// \endcode /// cxxThrowExpr() /// matches 'throw 5' -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> + cxxThrowExpr; /// \brief Matches null statements. /// @@ -1769,7 +1868,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr; /// \endcode /// nullStmt() /// matches the second ';' -const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; /// \brief Matches asm statements. /// @@ -1779,7 +1878,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; /// \endcode /// asmStmt() /// matches '__asm("mov al, 2")' -const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; /// \brief Matches bool literals. /// @@ -1787,9 +1886,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; /// \code /// true /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXBoolLiteralExpr> cxxBoolLiteral; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr> + cxxBoolLiteral; /// \brief Matches string literals (also matches wide string literals). /// @@ -1798,9 +1896,8 @@ const internal::VariadicDynCastAllOfMatcher< /// char *s = "abcd"; /// wchar_t *ws = L"abcd"; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - StringLiteral> stringLiteral; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral> + stringLiteral; /// \brief Matches character literals (also matches wchar_t). /// @@ -1812,17 +1909,15 @@ const internal::VariadicDynCastAllOfMatcher< /// char ch = 'a'; /// wchar_t chw = L'a'; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CharacterLiteral> characterLiteral; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral> + characterLiteral; /// \brief Matches integer literals of all sizes / encodings, e.g. /// 1, 1L, 0x1 and 1U. /// /// Does not match character-encoded integers such as L'a'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - IntegerLiteral> integerLiteral; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral> + integerLiteral; /// \brief Matches float literals of all sizes / encodings, e.g. /// 1.0, 1.0f, 1.0L and 1e10. @@ -1831,16 +1926,14 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// float a = 10; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - FloatingLiteral> floatLiteral; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> + floatLiteral; /// \brief Matches user defined literal operator call. /// /// Example match: "foo"_suffix -const internal::VariadicDynCastAllOfMatcher< - Stmt, - UserDefinedLiteral> userDefinedLiteral; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral> + userDefinedLiteral; /// \brief Matches compound (i.e. non-scalar) literals /// @@ -1849,24 +1942,23 @@ const internal::VariadicDynCastAllOfMatcher< /// int array[4] = {1}; /// vector int myvec = (vector int)(1, 2); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CompoundLiteralExpr> compoundLiteralExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr> + compoundLiteralExpr; /// \brief Matches nullptr literal. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> + cxxNullPtrLiteralExpr; /// \brief Matches GNU __null expression. -const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> + gnuNullExpr; /// \brief Matches atomic builtins. /// Example matches __atomic_load_n(ptr, 1) /// \code /// void foo() { int *ptr; __atomic_load_n(ptr, 1); } /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; /// \brief Matches statement expression (GNU extension). /// @@ -1874,7 +1966,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; /// \code /// int C = ({ int X = 4; X; }); /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; /// \brief Matches binary operator expressions. /// @@ -1882,9 +1974,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; /// \code /// !(a || b) /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - BinaryOperator> binaryOperator; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator> + binaryOperator; /// \brief Matches unary operator expressions. /// @@ -1892,9 +1983,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// !a || b /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - UnaryOperator> unaryOperator; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> + unaryOperator; /// \brief Matches conditional operator expressions. /// @@ -1902,9 +1992,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// (a ? b : c) + 42 /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ConditionalOperator> conditionalOperator; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator> + conditionalOperator; /// \brief Matches binary conditional operator expressions (GNU extension). /// @@ -1912,9 +2001,9 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// (a ?: b) + 42; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - BinaryConditionalOperator> binaryConditionalOperator; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + BinaryConditionalOperator> + binaryConditionalOperator; /// \brief Matches opaque value expressions. They are used as helpers /// to reference another expressions and can be met @@ -1924,9 +2013,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// (a ?: c) + 42; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - OpaqueValueExpr> opaqueValueExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr> + opaqueValueExpr; /// \brief Matches a C++ static_assert declaration. /// @@ -1941,9 +2029,8 @@ const internal::VariadicDynCastAllOfMatcher< /// }; /// static_assert(sizeof(S) == sizeof(int)); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - StaticAssertDecl> staticAssertDecl; +extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl> + staticAssertDecl; /// \brief Matches a reinterpret_cast expression. /// @@ -1955,9 +2042,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// void* p = reinterpret_cast<char*>(&p); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXReinterpretCastExpr> cxxReinterpretCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr> + cxxReinterpretCastExpr; /// \brief Matches a C++ static_cast expression. /// @@ -1972,9 +2058,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// long eight(static_cast<long>(8)); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXStaticCastExpr> cxxStaticCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr> + cxxStaticCastExpr; /// \brief Matches a dynamic_cast expression. /// @@ -1988,9 +2073,8 @@ const internal::VariadicDynCastAllOfMatcher< /// B b; /// D* p = dynamic_cast<D*>(&b); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXDynamicCastExpr> cxxDynamicCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr> + cxxDynamicCastExpr; /// \brief Matches a const_cast expression. /// @@ -2000,9 +2084,8 @@ const internal::VariadicDynCastAllOfMatcher< /// const int &r(n); /// int* p = const_cast<int*>(&r); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXConstCastExpr> cxxConstCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr> + cxxConstCastExpr; /// \brief Matches a C-style cast expression. /// @@ -2010,9 +2093,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// int i = (int) 2.2f; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CStyleCastExpr> cStyleCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr> + cStyleCastExpr; /// \brief Matches explicit cast expressions. /// @@ -2035,17 +2117,15 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// long ell = 42; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ExplicitCastExpr> explicitCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr> + explicitCastExpr; /// \brief 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. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ImplicitCastExpr> implicitCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr> + implicitCastExpr; /// \brief Matches any cast nodes of Clang's AST. /// @@ -2060,7 +2140,7 @@ const internal::VariadicDynCastAllOfMatcher< /// int i = (0); /// int k = 0; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; /// \brief Matches functional cast expressions /// @@ -2070,9 +2150,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; /// Foo g = (Foo) bar; /// Foo h = Foo(bar); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXFunctionalCastExpr> cxxFunctionalCastExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr> + cxxFunctionalCastExpr; /// \brief Matches functional cast expressions having N != 1 arguments /// @@ -2080,9 +2159,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// Foo h = Foo(bar, bar); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXTemporaryObjectExpr> cxxTemporaryObjectExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr> + cxxTemporaryObjectExpr; /// \brief Matches predefined identifier expressions [C99 6.4.2.2]. /// @@ -2090,9 +2168,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// printf("%s", __func__); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - PredefinedExpr> predefinedExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr> + predefinedExpr; /// \brief Matches C99 designated initializer expressions [C99 6.7.8]. /// @@ -2100,9 +2177,8 @@ const internal::VariadicDynCastAllOfMatcher< /// \code /// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 }; /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - DesignatedInitExpr> designatedInitExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr> + designatedInitExpr; /// \brief Matches designated initializer expressions that contain /// a specific number of designators. @@ -2120,13 +2196,13 @@ AST_MATCHER_P(DesignatedInitExpr, designatorCountIs, unsigned, N) { } /// \brief Matches \c QualTypes in the clang AST. -const internal::VariadicAllOfMatcher<QualType> qualType; +extern const internal::VariadicAllOfMatcher<QualType> qualType; /// \brief Matches \c Types in the clang AST. -const internal::VariadicAllOfMatcher<Type> type; +extern const internal::VariadicAllOfMatcher<Type> type; /// \brief Matches \c TypeLocs in the clang AST. -const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; +extern const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; /// \brief Matches if any of the given matchers matches. /// @@ -2147,23 +2223,23 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; /// \c b. /// /// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = { - internal::DynTypedMatcher::VO_EachOf -}; +extern const internal::VariadicOperatorMatcherFunc< + 2, std::numeric_limits<unsigned>::max()> + eachOf; /// \brief Matches if any of the given matchers matches. /// /// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = { - internal::DynTypedMatcher::VO_AnyOf -}; +extern const internal::VariadicOperatorMatcherFunc< + 2, std::numeric_limits<unsigned>::max()> + anyOf; /// \brief Matches if all given matchers match. /// /// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = { - internal::DynTypedMatcher::VO_AllOf -}; +extern const internal::VariadicOperatorMatcherFunc< + 2, std::numeric_limits<unsigned>::max()> + allOf; /// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) /// @@ -2174,9 +2250,9 @@ const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = { /// \endcode /// unaryExprOrTypeTraitExpr() /// matches \c sizeof(x) and \c alignof(x) -const internal::VariadicDynCastAllOfMatcher< - Stmt, - UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr; +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + UnaryExprOrTypeTraitExpr> + unaryExprOrTypeTraitExpr; /// \brief Matches unary expressions that have a specific type of argument. /// @@ -2252,9 +2328,9 @@ inline internal::Matcher<NamedDecl> hasName(const std::string &Name) { /// \code /// anyOf(hasName(a), hasName(b), hasName(c)) /// \endcode -const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef, - internal::hasAnyNameFunc> - hasAnyName = {}; +extern const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef, + internal::hasAnyNameFunc> + hasAnyName; /// \brief Matches NamedDecl nodes whose fully qualified names contain /// a substring matched by the given RegExp. @@ -2403,8 +2479,7 @@ AST_MATCHER(CXXRecordDecl, isLambda) { /// casts and paren casts. If you are matching with expr then you should /// probably consider using ignoringParenImpCasts like: /// has(ignoringParenImpCasts(expr())). -const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> -LLVM_ATTRIBUTE_UNUSED has = {}; +extern const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has; /// \brief Matches AST nodes that have descendant AST nodes that match the /// provided matcher. @@ -2420,8 +2495,9 @@ LLVM_ATTRIBUTE_UNUSED has = {}; /// DescendantT must be an AST base type. /// /// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher> -LLVM_ATTRIBUTE_UNUSED hasDescendant = {}; +extern const internal::ArgumentAdaptingMatcherFunc< + internal::HasDescendantMatcher> + hasDescendant; /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. @@ -2440,8 +2516,8 @@ LLVM_ATTRIBUTE_UNUSED hasDescendant = {}; /// matches instead of only on the first one. /// /// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> -LLVM_ATTRIBUTE_UNUSED forEach = {}; +extern const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> + forEach; /// \brief Matches AST nodes that have descendant AST nodes that match the /// provided matcher. @@ -2469,8 +2545,9 @@ LLVM_ATTRIBUTE_UNUSED forEach = {}; /// \endcode /// /// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher> -LLVM_ATTRIBUTE_UNUSED forEachDescendant = {}; +extern const internal::ArgumentAdaptingMatcherFunc< + internal::ForEachDescendantMatcher> + forEachDescendant; /// \brief Matches if the node or any descendant matches. /// @@ -2503,11 +2580,11 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) { /// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }". /// /// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc< +extern const internal::ArgumentAdaptingMatcherFunc< internal::HasParentMatcher, internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>, internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> - LLVM_ATTRIBUTE_UNUSED hasParent = {}; + hasParent; /// \brief Matches AST nodes that have an ancestor that matches the provided /// matcher. @@ -2520,11 +2597,11 @@ const internal::ArgumentAdaptingMatcherFunc< /// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43. /// /// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc< +extern const internal::ArgumentAdaptingMatcherFunc< internal::HasAncestorMatcher, internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>, internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> - LLVM_ATTRIBUTE_UNUSED hasAncestor = {}; + hasAncestor; /// \brief Matches if the provided matcher does not match. /// @@ -2535,9 +2612,7 @@ const internal::ArgumentAdaptingMatcherFunc< /// \endcode /// /// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<1, 1> unless = { - internal::DynTypedMatcher::VO_UnaryNot -}; +extern const internal::VariadicOperatorMatcherFunc<1, 1> unless; /// \brief Matches a node if the declaration associated with that node /// matches the given matcher. @@ -2549,8 +2624,21 @@ const internal::VariadicOperatorMatcherFunc<1, 1> unless = { /// - for CXXConstructExpr, the declaration of the constructor /// - for CXXNewExpr, the declaration of the operator new /// -/// Also usable as Matcher<T> for any T supporting the getDecl() member -/// function. e.g. various subtypes of clang::Type and various expressions. +/// For type nodes, hasDeclaration will generally match the declaration of the +/// sugared type. Given +/// \code +/// class X {}; +/// typedef X Y; +/// Y y; +/// \endcode +/// in varDecl(hasType(hasDeclaration(decl()))) the decl will match the +/// typedefDecl. A common use case is to match the underlying, desugared type. +/// This can be achieved by using the hasUnqualifiedDesugaredType matcher: +/// \code +/// varDecl(hasType(hasUnqualifiedDesugaredType( +/// recordType(hasDeclaration(decl()))))) +/// \endcode +/// In this matcher, the decl will match the CXXRecordDecl of class X. /// /// Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>, /// Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>, @@ -2843,7 +2931,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>, /// class A {}; /// using B = A; /// \endcode -/// The matcher type(hasUniqualifeidDesugaredType(recordType())) matches +/// The matcher type(hasUnqualifeidDesugaredType(recordType())) matches /// both B and A. AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>, InnerMatcher) { @@ -3237,7 +3325,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, /// with forField matching foo_ AST_MATCHER_P(CXXCtorInitializer, forField, internal::Matcher<FieldDecl>, InnerMatcher) { - const FieldDecl *NodeAsDecl = Node.getMember(); + const FieldDecl *NodeAsDecl = Node.getAnyMember(); return (NodeAsDecl != nullptr && InnerMatcher.matches(*NodeAsDecl, Finder, Builder)); } @@ -3492,16 +3580,21 @@ AST_MATCHER_P(FunctionDecl, returns, return InnerMatcher.matches(Node.getReturnType(), Finder, Builder); } -/// \brief Matches extern "C" function declarations. +/// \brief Matches extern "C" function or variable declarations. /// /// Given: /// \code /// extern "C" void f() {} /// extern "C" { void g() {} } /// void h() {} +/// extern "C" int x = 1; +/// extern "C" int y = 2; +/// int z = 3; /// \endcode /// functionDecl(isExternC()) -/// matches the declaration of f and g, but not the declaration h +/// matches the declaration of f and g, but not the declaration of h. +/// varDecl(isExternC()) +/// matches the declaration of x and y, but not the declaration of z. AST_POLYMORPHIC_MATCHER(isExternC, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl)) { return Node.isExternC(); @@ -3947,7 +4040,6 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand, /// \code /// int a = b ?: 1; /// \endcode - AST_POLYMORPHIC_MATCHER_P(hasSourceExpression, AST_POLYMORPHIC_SUPPORTED_TYPES(CastExpr, OpaqueValueExpr), @@ -4067,11 +4159,19 @@ AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression, /// extern int vb; // Doesn't match, as it doesn't define the variable. /// void fa() {} /// void fb(); // Doesn't match, as it has no body. +/// @interface X +/// - (void)ma; // Doesn't match, interface is declaration. +/// @end +/// @implementation X +/// - (void)ma {} +/// @end /// \endcode /// -/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> +/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>, +/// Matcher<ObjCMethodDecl> AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES(TagDecl, VarDecl, + ObjCMethodDecl, FunctionDecl)) { return Node.isThisDeclarationADefinition(); } @@ -4638,6 +4738,9 @@ AST_MATCHER(Type, voidType) { return Node.isVoidType(); } +template <typename NodeType> +using AstTypeMatcher = internal::VariadicDynCastAllOfMatcher<Type, NodeType>; + /// \brief Matches builtin Types. /// /// Given @@ -4650,7 +4753,7 @@ AST_MATCHER(Type, voidType) { /// \endcode /// builtinType() /// matches "int b", "float c" and "bool d" -AST_TYPE_MATCHER(BuiltinType, builtinType); +extern const AstTypeMatcher<BuiltinType> builtinType; /// \brief Matches all kinds of arrays. /// @@ -4662,7 +4765,7 @@ AST_TYPE_MATCHER(BuiltinType, builtinType); /// \endcode /// arrayType() /// matches "int a[]", "int b[4]" and "int c[a[0]]"; -AST_TYPE_MATCHER(ArrayType, arrayType); +extern const AstTypeMatcher<ArrayType> arrayType; /// \brief Matches C99 complex types. /// @@ -4672,7 +4775,7 @@ AST_TYPE_MATCHER(ArrayType, arrayType); /// \endcode /// complexType() /// matches "_Complex float f" -AST_TYPE_MATCHER(ComplexType, complexType); +extern const AstTypeMatcher<ComplexType> complexType; /// \brief Matches any real floating-point type (float, double, long double). /// @@ -4700,9 +4803,9 @@ AST_MATCHER(Type, realFloatingPointType) { /// matches "int b[7]" /// /// Usable as: Matcher<ArrayType>, Matcher<ComplexType> -AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement, - AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType, - ComplexType)); +AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement, + AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType, + ComplexType)); /// \brief Matches C arrays with a specified constant size. /// @@ -4716,7 +4819,7 @@ AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement, /// \endcode /// constantArrayType() /// matches "int a[2]" -AST_TYPE_MATCHER(ConstantArrayType, constantArrayType); +extern const AstTypeMatcher<ConstantArrayType> constantArrayType; /// \brief Matches nodes that have the specified size. /// @@ -4751,7 +4854,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSize, /// \endcode /// dependentSizedArrayType /// matches "T data[Size]" -AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType); +extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType; /// \brief Matches C arrays with unspecified size. /// @@ -4763,7 +4866,7 @@ AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType); /// \endcode /// incompleteArrayType() /// matches "int a[]" and "int c[]" -AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); +extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType; /// \brief Matches C arrays with a specified size that is not an /// integer-constant-expression. @@ -4778,7 +4881,7 @@ AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); /// \endcode /// variableArrayType() /// matches "int c[a[0]]" -AST_TYPE_MATCHER(VariableArrayType, variableArrayType); +extern const AstTypeMatcher<VariableArrayType> variableArrayType; /// \brief Matches \c VariableArrayType nodes that have a specific size /// expression. @@ -4805,7 +4908,7 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr, /// \endcode /// atomicType() /// matches "_Atomic(int) i" -AST_TYPE_MATCHER(AtomicType, atomicType); +extern const AstTypeMatcher<AtomicType> atomicType; /// \brief Matches atomic types with a specific value type. /// @@ -4818,8 +4921,8 @@ AST_TYPE_MATCHER(AtomicType, atomicType); /// matches "_Atomic(int) i" /// /// Usable as: Matcher<AtomicType> -AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue, - AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType)); +AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue, + AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType)); /// \brief Matches types nodes representing C++11 auto types. /// @@ -4831,7 +4934,7 @@ AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue, /// \endcode /// autoType() /// matches "auto n" and "auto i" -AST_TYPE_MATCHER(AutoType, autoType); +extern const AstTypeMatcher<AutoType> autoType; /// \brief Matches \c AutoType nodes where the deduced type is a specific type. /// @@ -4859,7 +4962,7 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, /// \endcode /// functionType() /// matches "int (*f)(int)" and the type of "g". -AST_TYPE_MATCHER(FunctionType, functionType); +extern const AstTypeMatcher<FunctionType> functionType; /// \brief Matches \c FunctionProtoType nodes. /// @@ -4871,7 +4974,7 @@ AST_TYPE_MATCHER(FunctionType, functionType); /// functionProtoType() /// matches "int (*f)(int)" and the type of "g" in C++ mode. /// In C mode, "g" is not matched because it does not contain a prototype. -AST_TYPE_MATCHER(FunctionProtoType, functionProtoType); +extern const AstTypeMatcher<FunctionProtoType> functionProtoType; /// \brief Matches \c ParenType nodes. /// @@ -4883,7 +4986,7 @@ AST_TYPE_MATCHER(FunctionProtoType, functionProtoType); /// /// \c varDecl(hasType(pointsTo(parenType()))) matches \c ptr_to_array but not /// \c array_of_ptrs. -AST_TYPE_MATCHER(ParenType, parenType); +extern const AstTypeMatcher<ParenType> parenType; /// \brief Matches \c ParenType nodes where the inner type is a specific type. /// @@ -4904,7 +5007,7 @@ AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType, /// "void (^)(int)". /// /// The \c pointee is always required to be a \c FunctionType. -AST_TYPE_MATCHER(BlockPointerType, blockPointerType); +extern const AstTypeMatcher<BlockPointerType> blockPointerType; /// \brief Matches member pointer types. /// Given @@ -4914,7 +5017,7 @@ AST_TYPE_MATCHER(BlockPointerType, blockPointerType); /// \endcode /// memberPointerType() /// matches "A::* ptr" -AST_TYPE_MATCHER(MemberPointerType, memberPointerType); +extern const AstTypeMatcher<MemberPointerType> memberPointerType; /// \brief Matches pointer types, but does not match Objective-C object pointer /// types. @@ -4931,7 +5034,7 @@ AST_TYPE_MATCHER(MemberPointerType, memberPointerType); /// \endcode /// pointerType() /// matches "int *a", but does not match "Foo *f". -AST_TYPE_MATCHER(PointerType, pointerType); +extern const AstTypeMatcher<PointerType> pointerType; /// \brief Matches an Objective-C object pointer type, which is different from /// a pointer type, despite being syntactically similar. @@ -4946,7 +5049,7 @@ AST_TYPE_MATCHER(PointerType, pointerType); /// \endcode /// pointerType() /// matches "Foo *f", but does not match "int *a". -AST_TYPE_MATCHER(ObjCObjectPointerType, objcObjectPointerType); +extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType; /// \brief Matches both lvalue and rvalue reference types. /// @@ -4962,7 +5065,7 @@ AST_TYPE_MATCHER(ObjCObjectPointerType, objcObjectPointerType); /// \endcode /// /// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f. -AST_TYPE_MATCHER(ReferenceType, referenceType); +extern const AstTypeMatcher<ReferenceType> referenceType; /// \brief Matches lvalue reference types. /// @@ -4979,7 +5082,7 @@ AST_TYPE_MATCHER(ReferenceType, referenceType); /// /// \c lValueReferenceType() matches the types of \c b, \c d, and \c e. \c e is /// matched since the type is deduced as int& by reference collapsing rules. -AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType); +extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType; /// \brief Matches rvalue reference types. /// @@ -4996,7 +5099,7 @@ AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType); /// /// \c rValueReferenceType() matches the types of \c c and \c f. \c e is not /// matched as it is deduced to int& by reference collapsing rules. -AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType); +extern const AstTypeMatcher<RValueReferenceType> rValueReferenceType; /// \brief Narrows PointerType (and similar) matchers to those where the /// \c pointee matches a given matcher. @@ -5012,11 +5115,10 @@ AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType); /// /// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>, /// Matcher<PointerType>, Matcher<ReferenceType> -AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee, - AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, - MemberPointerType, - PointerType, - ReferenceType)); +AST_TYPELOC_TRAVERSE_MATCHER_DECL( + pointee, getPointee, + AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType, + PointerType, ReferenceType)); /// \brief Matches typedef types. /// @@ -5026,7 +5128,7 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee, /// \endcode /// typedefType() /// matches "typedef int X" -AST_TYPE_MATCHER(TypedefType, typedefType); +extern const AstTypeMatcher<TypedefType> typedefType; /// \brief Matches enum types. /// @@ -5041,7 +5143,7 @@ AST_TYPE_MATCHER(TypedefType, typedefType); // /// \c enumType() matches the type of the variable declarations of both \c c and /// \c s. -AST_TYPE_MATCHER(EnumType, enumType); +extern const AstTypeMatcher<EnumType> enumType; /// \brief Matches template specialization types. /// @@ -5056,7 +5158,8 @@ AST_TYPE_MATCHER(EnumType, enumType); /// /// \c templateSpecializationType() matches the type of the explicit /// instantiation in \c A and the type of the variable declaration in \c B. -AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType); +extern const AstTypeMatcher<TemplateSpecializationType> + templateSpecializationType; /// \brief Matches types nodes representing unary type transformations. /// @@ -5066,7 +5169,7 @@ AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType); /// \endcode /// unaryTransformType() /// matches "__underlying_type(T)" -AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType); +extern const AstTypeMatcher<UnaryTransformType> unaryTransformType; /// \brief Matches record types (e.g. structs, classes). /// @@ -5081,7 +5184,22 @@ AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType); /// /// \c recordType() matches the type of the variable declarations of both \c c /// and \c s. -AST_TYPE_MATCHER(RecordType, recordType); +extern const AstTypeMatcher<RecordType> recordType; + +/// \brief Matches tag types (record and enum types). +/// +/// Given +/// \code +/// enum E {}; +/// class C {}; +/// +/// E e; +/// C c; +/// \endcode +/// +/// \c tagType() matches the type of the variable declarations of both \c e +/// and \c c. +extern const AstTypeMatcher<TagType> tagType; /// \brief Matches types specified with an elaborated type keyword or with a /// qualified name. @@ -5101,7 +5219,7 @@ AST_TYPE_MATCHER(RecordType, recordType); /// /// \c elaboratedType() matches the type of the variable declarations of both /// \c c and \c d. -AST_TYPE_MATCHER(ElaboratedType, elaboratedType); +extern const AstTypeMatcher<ElaboratedType> elaboratedType; /// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier, /// matches \c InnerMatcher if the qualifier exists. @@ -5158,7 +5276,8 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>, /// \endcode /// /// \c substTemplateTypeParmType() matches the type of 't' but not '1' -AST_TYPE_MATCHER(SubstTemplateTypeParmType, substTemplateTypeParmType); +extern const AstTypeMatcher<SubstTemplateTypeParmType> + substTemplateTypeParmType; /// \brief Matches template type parameter substitutions that have a replacement /// type that matches the provided matcher. @@ -5183,7 +5302,7 @@ AST_TYPE_TRAVERSE_MATCHER( /// \code /// template <typename T> void f(int i); /// \endcode -AST_TYPE_MATCHER(TemplateTypeParmType, templateTypeParmType); +extern const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType; /// \brief Matches injected class name types. /// @@ -5195,7 +5314,7 @@ AST_TYPE_MATCHER(TemplateTypeParmType, templateTypeParmType); /// void g(S<T> s); /// }; /// \endcode -AST_TYPE_MATCHER(InjectedClassNameType, injectedClassNameType); +extern const AstTypeMatcher<InjectedClassNameType> injectedClassNameType; /// \brief Matches decayed type /// Example matches i[] in declaration of f. @@ -5207,7 +5326,7 @@ AST_TYPE_MATCHER(InjectedClassNameType, injectedClassNameType); /// i[1] = 0; /// } /// \endcode -AST_TYPE_MATCHER(DecayedType, decayedType); +extern const AstTypeMatcher<DecayedType> decayedType; /// \brief Matches the decayed type, whos decayed type matches \c InnerMatcher AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>, @@ -5248,11 +5367,12 @@ AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) { /// \endcode /// nestedNameSpecifier() /// matches "ns::" and both "A::" -const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; +extern const internal::VariadicAllOfMatcher<NestedNameSpecifier> + nestedNameSpecifier; /// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc. -const internal::VariadicAllOfMatcher< - NestedNameSpecifierLoc> nestedNameSpecifierLoc; +extern const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc> + nestedNameSpecifierLoc; /// \brief Matches \c NestedNameSpecifierLocs for which the given inner /// NestedNameSpecifier-matcher matches. @@ -5605,17 +5725,14 @@ AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>, return false; } - /// \brief Matches CUDA kernel call expression. /// /// Example matches, /// \code /// kernel<<<i,j>>>(); /// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CUDAKernelCallExpr> cudaKernelCallExpr; - +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr> + cudaKernelCallExpr; /// \brief Matches expressions that resolve to a null pointer constant, such as /// GNU's __null, C++11's nullptr, or C's NULL macro. @@ -5700,7 +5817,54 @@ AST_MATCHER(NamedDecl, hasExternalFormalLinkage) { return Node.hasExternalFormalLinkage(); } -} // end namespace ast_matchers -} // end namespace clang +/// \brief Matches a declaration that has default arguments. +/// +/// Example matches y (matcher = parmVarDecl(hasDefaultArgument())) +/// \code +/// void x(int val) {} +/// void y(int val = 0) {} +/// \endcode +AST_MATCHER(ParmVarDecl, hasDefaultArgument) { + return Node.hasDefaultArg(); +} + +/// \brief Matches array new expressions. +/// +/// Given: +/// \code +/// MyClass *p1 = new MyClass[10]; +/// \endcode +/// cxxNewExpr(isArray()) +/// matches the expression 'new MyClass[10]'. +AST_MATCHER(CXXNewExpr, isArray) { + return Node.isArray(); +} + +/// \brief Matches array new expressions with a given array size. +/// +/// Given: +/// \code +/// MyClass *p1 = new MyClass[10]; +/// \endcode +/// cxxNewExpr(hasArraySize(intgerLiteral(equals(10)))) +/// matches the expression 'new MyClass[10]'. +AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher<Expr>, InnerMatcher) { + return Node.isArray() && + InnerMatcher.matches(*Node.getArraySize(), Finder, Builder); +} + +/// \brief Matches a class declaration that is defined. +/// +/// Example matches x (matcher = cxxRecordDecl(hasDefinition())) +/// \code +/// class x {}; +/// class y; +/// \endcode +AST_MATCHER(CXXRecordDecl, hasDefinition) { + return Node.hasDefinition(); +} + +} // namespace ast_matchers +} // namespace clang -#endif +#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index bc75e807ced9..8bd61a76e185 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1,4 +1,4 @@ -//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===// +//===- ASTMatchersInternal.h - Structural query framework -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -38,23 +38,42 @@ #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Stmt.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/OperatorKinds.h" +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/ArrayRef.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/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ManagedStatic.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> #include <map> #include <string> +#include <tuple> +#include <type_traits> +#include <utility> #include <vector> namespace clang { + +class ASTContext; + namespace ast_matchers { class BoundNodes; @@ -158,7 +177,7 @@ public: /// Note that we're using std::map here, as for memoization: /// - we need a comparison operator /// - we need an assignment operator - typedef std::map<std::string, ast_type_traits::DynTypedNode> IDToNodeMap; + using IDToNodeMap = std::map<std::string, ast_type_traits::DynTypedNode>; const IDToNodeMap &getMap() const { return NodeMap; @@ -188,7 +207,7 @@ public: /// BoundNodesTree. class Visitor { public: - virtual ~Visitor() {} + virtual ~Visitor() = default; /// \brief Called multiple times during a single call to VisitMatches(...). /// @@ -248,7 +267,7 @@ class ASTMatchFinder; class DynMatcherInterface : public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> { public: - virtual ~DynMatcherInterface() {} + virtual ~DynMatcherInterface() = default; /// \brief Returns true if \p DynNode can be matched. /// @@ -317,26 +336,29 @@ public: /// \brief Takes ownership of the provided implementation pointer. template <typename T> DynTypedMatcher(MatcherInterface<T> *Implementation) - : AllowBind(false), - SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()), + : SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()), RestrictKind(SupportedKind), Implementation(Implementation) {} /// \brief Construct from a variadic function. enum VariadicOperator { /// \brief Matches nodes for which all provided matchers match. VO_AllOf, + /// \brief Matches nodes for which at least one of the provided matchers /// matches. VO_AnyOf, + /// \brief Matches nodes for which at least one of the provided matchers /// matches, but doesn't stop at the first match. VO_EachOf, + /// \brief Matches nodes that do not match the provided matcher. /// /// Uses the variadic matcher interface, but fails if /// InnerMatchers.size() != 1. VO_UnaryNot }; + static DynTypedMatcher constructVariadic(VariadicOperator Op, ast_type_traits::ASTNodeKind SupportedKind, @@ -382,7 +404,7 @@ public: /// include both in the ID to make it unique. /// /// \c MatcherIDType supports operator< and provides strict weak ordering. - typedef std::pair<ast_type_traits::ASTNodeKind, uint64_t> MatcherIDType; + using MatcherIDType = std::pair<ast_type_traits::ASTNodeKind, uint64_t>; MatcherIDType getID() const { /// FIXME: Document the requirements this imposes on matcher /// implementations (no new() implementation_ during a Matches()). @@ -428,13 +450,12 @@ private: DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind, ast_type_traits::ASTNodeKind RestrictKind, IntrusiveRefCntPtr<DynMatcherInterface> Implementation) - : AllowBind(false), - SupportedKind(SupportedKind), - RestrictKind(RestrictKind), + : SupportedKind(SupportedKind), RestrictKind(RestrictKind), Implementation(std::move(Implementation)) {} - bool AllowBind; + bool AllowBind = false; ast_type_traits::ASTNodeKind SupportedKind; + /// \brief A potentially stricter node kind. /// /// It allows to perform implicit and dynamic cast of matchers without @@ -545,6 +566,7 @@ public: private: // For Matcher<T> <=> Matcher<U> conversions. template <typename U> friend class Matcher; + // For DynTypedMatcher::unconditionalConvertTo<T>. friend class DynTypedMatcher; @@ -618,8 +640,8 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, // Metafunction to determine if type T has a member called getDecl. template <typename Ty> class has_getDecl { - typedef char yes[1]; - typedef char no[2]; + using yes = char[1]; + using no = char[2]; template <typename Inner> static yes& test(Inner *I, decltype(I->getDecl()) * = nullptr); @@ -728,48 +750,94 @@ public: } private: - /// \brief If getDecl exists as a member of U, returns whether the inner - /// matcher matches Node.getDecl(). - template <typename U> - bool matchesSpecialized( - const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, - typename std::enable_if<has_getDecl<U>::value, int>::type = 0) const { - return matchesDecl(Node.getDecl(), Finder, Builder); - } - - /// \brief Extracts the TagDecl of a QualType and returns whether the inner - /// matcher matches on it. + /// \brief Forwards to matching on the underlying type of the QualType. bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { if (Node.isNull()) return false; - if (auto *TD = Node->getAsTagDecl()) - return matchesDecl(TD, Finder, Builder); - else if (auto *TT = Node->getAs<TypedefType>()) - return matchesDecl(TT->getDecl(), Finder, Builder); - // Do not use getAs<TemplateTypeParmType> instead of the direct dyn_cast. - // Calling getAs will return the canonical type, but that type does not - // store a TemplateTypeParmDecl. We *need* the uncanonical type, if it is - // available, and using dyn_cast ensures that. - else if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr())) - return matchesDecl(TTP->getDecl(), Finder, Builder); - else if (auto *OCIT = Node->getAs<ObjCInterfaceType>()) - return matchesDecl(OCIT->getDecl(), Finder, Builder); - else if (auto *UUT = Node->getAs<UnresolvedUsingType>()) - return matchesDecl(UUT->getDecl(), Finder, Builder); - else if (auto *ICNT = Node->getAs<InjectedClassNameType>()) - return matchesDecl(ICNT->getDecl(), Finder, Builder); + return matchesSpecialized(*Node, Finder, Builder); + } + + /// \brief 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 { + // DeducedType does not have declarations of its own, so + // match the deduced type instead. + const Type *EffectiveType = &Node; + if (const auto *S = dyn_cast<DeducedType>(&Node)) { + EffectiveType = S->getDeducedType().getTypePtrOrNull(); + if (!EffectiveType) + return false; + } + + // First, for any types that have a declaration, extract the declaration and + // match on it. + if (const auto *S = dyn_cast<TagType>(EffectiveType)) { + return matchesDecl(S->getDecl(), Finder, Builder); + } + if (const auto *S = dyn_cast<InjectedClassNameType>(EffectiveType)) { + return matchesDecl(S->getDecl(), Finder, Builder); + } + if (const auto *S = dyn_cast<TemplateTypeParmType>(EffectiveType)) { + return matchesDecl(S->getDecl(), Finder, Builder); + } + if (const auto *S = dyn_cast<TypedefType>(EffectiveType)) { + return matchesDecl(S->getDecl(), Finder, Builder); + } + if (const auto *S = dyn_cast<UnresolvedUsingType>(EffectiveType)) { + return matchesDecl(S->getDecl(), Finder, Builder); + } + if (const auto *S = dyn_cast<ObjCObjectType>(EffectiveType)) { + return matchesDecl(S->getInterface(), Finder, Builder); + } + + // A SubstTemplateTypeParmType exists solely to mark a type substitution + // on the instantiated template. As users usually want to match the + // template parameter on the uninitialized template, we can always desugar + // one level without loss of expressivness. + // For example, given: + // template<typename T> struct X { T t; } class A {}; X<A> a; + // The following matcher will match, which otherwise would not: + // fieldDecl(hasType(pointerType())). + if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(EffectiveType)) { + return matchesSpecialized(S->getReplacementType(), Finder, Builder); + } + + // For template specialization types, we want to match the template + // declaration, as long as the type is still dependent, and otherwise the + // declaration of the instantiated tag type. + if (const auto *S = dyn_cast<TemplateSpecializationType>(EffectiveType)) { + if (!S->isTypeAlias() && S->isSugared()) { + // If the template is non-dependent, we want to match the instantiated + // tag type. + // For example, given: + // template<typename T> struct X {}; X<int> a; + // The following matcher will match, which otherwise would not: + // templateSpecializationType(hasDeclaration(cxxRecordDecl())). + return matchesSpecialized(*S->desugar(), Finder, Builder); + } + // If the template is dependent or an alias, match the template + // declaration. + return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder, + Builder); + } + + // FIXME: We desugar elaborated types. This makes the assumption that users + // do never want to match on whether a type is elaborated - there are + // arguments for both sides; for now, continue desugaring. + if (const auto *S = dyn_cast<ElaboratedType>(EffectiveType)) { + return matchesSpecialized(S->desugar(), Finder, Builder); + } return false; } - /// \brief Gets the TemplateDecl from a TemplateSpecializationType - /// and returns whether the inner matches on it. - bool matchesSpecialized(const TemplateSpecializationType &Node, - ASTMatchFinder *Finder, + /// \brief 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.getTemplateName().getAsTemplateDecl(), - Finder, Builder); + return matchesDecl(Node.getDecl(), Finder, Builder); } /// \brief Extracts the Decl of the callee of a CallExpr and returns whether @@ -811,6 +879,13 @@ private: return matchesDecl(Node.getLabel(), Finder, Builder); } + /// \brief 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 /// is \c NULL. bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder, @@ -863,6 +938,7 @@ public: enum TraversalKind { /// Will traverse any child nodes. TK_AsIs, + /// Will not traverse implicit casts and parentheses. TK_IgnoreImplicitCastsAndParentheses }; @@ -871,6 +947,7 @@ public: enum BindKind { /// Stop at the first match and only bind the first match. BK_First, + /// Create results for all combinations of bindings that match. BK_All }; @@ -879,11 +956,12 @@ public: enum AncestorMatchMode { /// All ancestors. AMM_All, + /// Direct parent only. AMM_ParentOnly }; - virtual ~ASTMatchFinder() {} + virtual ~ASTMatchFinder() = default; /// \brief Returns true if the given class is directly or indirectly derived /// from a base type matching \c base. @@ -906,7 +984,7 @@ public: std::is_base_of<TypeLoc, T>::value || std::is_base_of<QualType, T>::value, "unsupported type for recursive matching"); - return matchesChildOf(ast_type_traits::DynTypedNode::create(Node), + return matchesChildOf(ast_type_traits::DynTypedNode::create(Node), Matcher, Builder, Traverse, Bind); } @@ -969,17 +1047,17 @@ 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. - typedef T1 head; + using head = T1; /// \brief 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. - typedef TypeList<Ts...> tail; + using tail = TypeList<Ts...>; }; /// \brief The empty type list. -typedef TypeList<> EmptyTypeList; +using EmptyTypeList = TypeList<>; /// \brief Helper meta-function to determine if some type \c T is present or /// a parent type in the list. @@ -997,8 +1075,9 @@ struct TypeListContainsSuperOf<EmptyTypeList, T> { /// \brief A "type list" that contains all types. /// /// Useful for matchers like \c anything and \c unless. -typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, - QualType, Type, TypeLoc, CXXCtorInitializer> AllNodeBaseTypes; +using AllNodeBaseTypes = + TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType, + Type, TypeLoc, CXXCtorInitializer>; /// \brief Helper meta-function to extract the argument out of a function of /// type void(Arg). @@ -1006,20 +1085,22 @@ typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, /// See AST_POLYMORPHIC_SUPPORTED_TYPES for details. template <class T> struct ExtractFunctionArgMeta; template <class T> struct ExtractFunctionArgMeta<void(T)> { - typedef T type; + using type = T; }; /// \brief Default type lists for ArgumentAdaptingMatcher matchers. -typedef AllNodeBaseTypes AdaptativeDefaultFromTypes; -typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, - TypeLoc, QualType> AdaptativeDefaultToTypes; +using AdaptativeDefaultFromTypes = AllNodeBaseTypes; +using AdaptativeDefaultToTypes = + TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc, + QualType>; /// \brief All types that are supported by HasDeclarationMatcher above. -typedef TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType, - InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr, - QualType, RecordType, TagType, TemplateSpecializationType, - TemplateTypeParmType, TypedefType, UnresolvedUsingType> - HasDeclarationSupportedTypes; +using HasDeclarationSupportedTypes = + TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType, + ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr, + MemberExpr, QualType, RecordType, TagType, + TemplateSpecializationType, TemplateTypeParmType, TypedefType, + UnresolvedUsingType>; /// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by /// "adapting" a \c To into a \c T. @@ -1043,7 +1124,7 @@ struct ArgumentAdaptingMatcherFunc { explicit Adaptor(const Matcher<T> &InnerMatcher) : InnerMatcher(InnerMatcher) {} - typedef ToTypes ReturnTypes; + using ReturnTypes = ToTypes; template <typename To> operator Matcher<To>() const { return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher)); @@ -1080,7 +1161,8 @@ template <template <typename T> class MatcherT, typename ReturnTypesF = void(AllNodeBaseTypes)> class PolymorphicMatcherWithParam0 { public: - typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes; + using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; + template <typename T> operator Matcher<T>() const { static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, @@ -1097,7 +1179,7 @@ public: explicit PolymorphicMatcherWithParam1(const P1 &Param1) : Param1(Param1) {} - typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes; + using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; template <typename T> operator Matcher<T>() const { @@ -1118,7 +1200,7 @@ public: PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2) : Param1(Param1), Param2(Param2) {} - typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes; + using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; template <typename T> operator Matcher<T>() const { @@ -1137,8 +1219,8 @@ private: /// This is useful when a matcher syntactically requires a child matcher, /// but the context doesn't care. See for example: anything(). class TrueMatcher { - public: - typedef AllNodeBaseTypes ReturnTypes; +public: + using ReturnTypes = AllNodeBaseTypes; template <typename T> operator Matcher<T>() const { @@ -1184,7 +1266,6 @@ public: /// ChildT must be an AST base type. template <typename T, typename ChildT> class HasMatcher : public WrapperMatcherInterface<T> { - public: explicit HasMatcher(const Matcher<ChildT> &ChildMatcher) : HasMatcher::WrapperMatcherInterface(ChildMatcher) {} @@ -1278,7 +1359,7 @@ template<typename T> BindableMatcher<T> makeAllOfComposite( ArrayRef<const Matcher<T> *> InnerMatchers) { // For the size() == 0 case, we return a "true" matcher. - if (InnerMatchers.size() == 0) { + if (InnerMatchers.empty()) { return BindableMatcher<T>(TrueMatcher()); } // For the size() == 1 case, we simply return that one matcher. @@ -1287,7 +1368,8 @@ BindableMatcher<T> makeAllOfComposite( return BindableMatcher<T>(*InnerMatchers[0]); } - typedef llvm::pointee_iterator<const Matcher<T> *const *> PI; + using PI = llvm::pointee_iterator<const Matcher<T> *const *>; + std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()), PI(InnerMatchers.end())); return BindableMatcher<T>( @@ -1580,12 +1662,13 @@ template <typename InnerTBase, typename ReturnTypesF> class TypeTraversePolymorphicMatcher { private: - typedef TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, - ReturnTypesF> Self; + using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, + ReturnTypesF>; + static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers); public: - typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes; + using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; explicit TypeTraversePolymorphicMatcher( ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) @@ -1612,6 +1695,7 @@ private: template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher { struct Wrapper { Wrapper() : M(Func()) {} + Matcher M; }; @@ -1657,6 +1741,7 @@ struct NotEqualsBoundNodePredicate { bool operator()(const internal::BoundNodesMap &Nodes) const { return Nodes.getNode(ID) != Node; } + std::string ID; ast_type_traits::DynTypedNode Node; }; @@ -1712,9 +1797,10 @@ CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) { return Node.getSubStmt(); } +} // namespace internal + +} // namespace ast_matchers -} // end namespace internal -} // end namespace ast_matchers -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index ddc48378e714..6a48da821a53 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -367,6 +367,27 @@ // FIXME: add a matcher for TypeLoc derived classes using its custom casting // API (no longer dyn_cast) if/when we need such matching +#define AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \ + ReturnTypesF) \ + namespace internal { \ + template <typename T> struct TypeMatcher##MatcherName##Getter { \ + static QualType (T::*value())() const { return &T::FunctionName; } \ + }; \ + } \ + extern const ::clang::ast_matchers::internal:: \ + TypeTraversePolymorphicMatcher< \ + QualType, \ + ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \ + ::clang::ast_matchers::internal::TypeTraverseMatcher, \ + ReturnTypesF>::Func MatcherName + +#define AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \ + const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ + QualType, \ + ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \ + ::clang::ast_matchers::internal::TypeTraverseMatcher, \ + ReturnTypesF>::Func MatcherName + /// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines /// the matcher \c MatcherName that can be used to traverse from one \c Type /// to another. @@ -386,6 +407,30 @@ ::clang::ast_matchers::internal::TypeTraverseMatcher, \ ReturnTypesF>::Func MatcherName +#define AST_TYPELOC_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName, \ + ReturnTypesF) \ + namespace internal { \ + template <typename T> struct TypeLocMatcher##MatcherName##Getter { \ + static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \ + }; \ + } \ + extern const ::clang::ast_matchers::internal:: \ + TypeTraversePolymorphicMatcher< \ + TypeLoc, \ + ::clang::ast_matchers::internal:: \ + TypeLocMatcher##MatcherName##Getter, \ + ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \ + ReturnTypesF>::Func MatcherName##Loc; \ + AST_TYPE_TRAVERSE_MATCHER_DECL(MatcherName, FunctionName##Type, ReturnTypesF) + +#define AST_TYPELOC_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) \ + const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \ + TypeLoc, \ + ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \ + ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \ + ReturnTypesF>::Func MatcherName##Loc; \ + AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) + /// \brief 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) \ diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h index 5ec4a9abf4bf..e8fcf0a9d6cc 100644 --- a/include/clang/ASTMatchers/Dynamic/Parser.h +++ b/include/clang/ASTMatchers/Dynamic/Parser.h @@ -1,4 +1,4 @@ -//===--- Parser.h - Matcher expression parser -----*- C++ -*-===// +//===- Parser.h - Matcher expression parser ---------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Simple matcher expression parser. /// @@ -30,24 +30,28 @@ /// <Identifier> := [a-zA-Z]+ /// <ArgumentList> := <Expression> | <Expression>,<ArgumentList> /// \endcode -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H #define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H -#include "clang/ASTMatchers/Dynamic/Diagnostics.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" #include "clang/ASTMatchers/Dynamic/Registry.h" #include "clang/ASTMatchers/Dynamic/VariantValue.h" -#include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include <utility> +#include <vector> namespace clang { namespace ast_matchers { namespace dynamic { +class Diagnostics; + /// \brief Matcher expression parser. class Parser { public: @@ -124,8 +128,8 @@ public: /// \brief Sema implementation that uses the matcher registry to process the /// tokens. class RegistrySema : public Parser::Sema { - public: - ~RegistrySema() override; + public: + ~RegistrySema() override; llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) override; @@ -143,7 +147,7 @@ public: getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override; }; - typedef llvm::StringMap<VariantValue> NamedValueMap; + using NamedValueMap = llvm::StringMap<VariantValue>; /// \brief Parse a matcher expression. /// @@ -247,13 +251,14 @@ private: const NamedValueMap *const NamedValues; Diagnostics *const Error; - typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy; + using ContextStackTy = std::vector<std::pair<MatcherCtor, unsigned>>; + ContextStackTy ContextStack; std::vector<MatcherCompletion> Completions; }; -} // namespace dynamic -} // namespace ast_matchers -} // namespace clang +} // namespace dynamic +} // namespace ast_matchers +} // namespace clang -#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H +#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h index 7bba95dbffea..277491250db8 100644 --- a/include/clang/ASTMatchers/Dynamic/Registry.h +++ b/include/clang/ASTMatchers/Dynamic/Registry.h @@ -1,4 +1,4 @@ -//===--- Registry.h - Matcher registry --------------------------*- C++ -*-===// +//===- Registry.h - Matcher registry ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,12 +6,12 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Registry of all known matchers. /// /// The registry provides a generic interface to construct any matcher by name. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H @@ -34,9 +34,9 @@ namespace internal { class MatcherDescriptor; -} // end namespace internal +} // namespace internal -typedef const internal::MatcherDescriptor *MatcherCtor; +using MatcherCtor = const internal::MatcherDescriptor *; struct MatcherCompletion { MatcherCompletion() = default; @@ -129,8 +129,8 @@ public: Diagnostics *Error); }; -} // end namespace dynamic -} // end namespace ast_matchers -} // end namespace clang +} // namespace dynamic +} // namespace ast_matchers +} // namespace clang #endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h index c0fc02724f09..5ba42b475c83 100644 --- a/include/clang/Analysis/Analyses/Consumed.h +++ b/include/clang/Analysis/Analyses/Consumed.h @@ -19,7 +19,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/SourceLocation.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h index 38010e1ee1d8..6cb161ab37c8 100644 --- a/include/clang/Analysis/Analyses/Dominators.h +++ b/include/clang/Analysis/Analyses/Dominators.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H #define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/GenericDomTree.h" diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 8db4b0a58f86..6a1222386bae 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -15,7 +15,7 @@ #define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H #include "clang/AST/Decl.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "llvm/ADT/ImmutableSet.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h index a1c650427588..c0a93528373e 100644 --- a/include/clang/Analysis/Analyses/PostOrderCFGView.h +++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h @@ -21,7 +21,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/BitVector.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index 22694a7a225a..7e403b1f4090 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -19,7 +19,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/StringRef.h" diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h index 8c1d1da554bd..414645b7231b 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -25,7 +25,7 @@ #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/OperatorKinds.h" #include <memory> #include <ostream> diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index be8a7105d783..0a58d2a80250 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -92,6 +92,7 @@ enum TIL_BinaryOpcode : unsigned char { BOP_Neq, // != BOP_Lt, // < BOP_Leq, // <= + BOP_Cmp, // <=> BOP_LogicAnd, // && (no short-circuit) BOP_LogicOr // || (no short-circuit) }; @@ -909,15 +910,10 @@ class Project : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Project; } - Project(SExpr *R, StringRef SName) - : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr) - { } Project(SExpr *R, const clang::ValueDecl *Cvd) - : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd) - { } - Project(const Project &P, SExpr *R) - : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl) - { } + : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) { + assert(Cvd && "ValueDecl must not be null"); + } SExpr *record() { return Rec; } const SExpr *record() const { return Rec; } @@ -931,10 +927,14 @@ public: } StringRef slotName() const { - if (Cvdecl) + if (Cvdecl->getDeclName().isIdentifier()) return Cvdecl->getName(); - else - return SlotName; + if (!SlotName) { + SlotName = ""; + llvm::raw_string_ostream OS(*SlotName); + Cvdecl->printName(OS); + } + return *SlotName; } template <class V> @@ -953,7 +953,7 @@ public: private: SExpr* Rec; - StringRef SlotName; + mutable llvm::Optional<std::string> SlotName; const clang::ValueDecl *Cvdecl; }; diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisDeclContext.h index ec7549d4535c..03ff4a9516da 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisDeclContext.h @@ -1,4 +1,4 @@ -//=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-// +//=== AnalysisDeclContext.h - Analysis context for Path Sens analysis --*- C++ -*-// // // The LLVM Compiler Infrastructure // @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H -#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H +#define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H #include "clang/AST/Decl.h" +#include "clang/Analysis/BodyFarm.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CodeInjector.h" #include "llvm/ADT/DenseMap.h" @@ -416,23 +417,25 @@ class AnalysisDeclContextManager { /// Pointer to an interface that can provide function bodies for /// declarations from external source. std::unique_ptr<CodeInjector> Injector; - + + /// A factory for creating and caching implementations for common + /// methods during the analysis. + BodyFarm FunctionBodyFarm; + /// Flag to indicate whether or not bodies should be synthesized /// for well-known functions. bool SynthesizeBodies; public: - AnalysisDeclContextManager(bool useUnoptimizedCFG = false, + AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG = false, bool addImplicitDtors = false, bool addInitializers = false, bool addTemporaryDtors = false, - bool addLifetime = false, + bool addLifetime = false, bool addLoopExit = false, bool synthesizeBodies = false, bool addStaticInitBranches = false, bool addCXXNewAllocator = true, - CodeInjector* injector = nullptr); - - ~AnalysisDeclContextManager(); + CodeInjector *injector = nullptr); AnalysisDeclContext *getContext(const Decl *D); @@ -471,6 +474,9 @@ public: return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); } + /// Get a reference to {@code BodyFarm} instance. + BodyFarm &getBodyFarm(); + /// Discard all previously created AnalysisDeclContexts. void clear(); diff --git a/include/clang/Analysis/BodyFarm.h b/include/clang/Analysis/BodyFarm.h new file mode 100644 index 000000000000..ff0859bc662d --- /dev/null +++ b/include/clang/Analysis/BodyFarm.h @@ -0,0 +1,54 @@ +//== BodyFarm.h - Factory for conjuring up fake bodies -------------*- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// BodyFarm is a factory for creating faux implementations for functions/methods +// for analysis purposes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_ANALYSIS_BODYFARM_H +#define LLVM_CLANG_LIB_ANALYSIS_BODYFARM_H + +#include "clang/AST/DeclBase.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" + +namespace clang { + +class ASTContext; +class FunctionDecl; +class ObjCMethodDecl; +class ObjCPropertyDecl; +class Stmt; +class CodeInjector; + +class BodyFarm { +public: + BodyFarm(ASTContext &C, CodeInjector *injector) : C(C), Injector(injector) {} + + /// Factory method for creating bodies for ordinary functions. + Stmt *getBody(const FunctionDecl *D); + + /// Factory method for creating bodies for Objective-C properties. + Stmt *getBody(const ObjCMethodDecl *D); + + /// Remove copy constructor to avoid accidental copying. + BodyFarm(const BodyFarm &other) = delete; + +private: + typedef llvm::DenseMap<const Decl *, Optional<Stmt *>> BodyMap; + + ASTContext &C; + BodyMap Bodies; + CodeInjector *Injector; +}; +} // namespace clang + +#endif diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 97639bbfade2..cfedb2aa8ed5 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -1,4 +1,4 @@ -//===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===// +//===- CFG.h - Classes for representing and building CFGs -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,38 +17,38 @@ #include "clang/AST/Stmt.h" #include "clang/Analysis/Support/BumpVector.h" -#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include <bitset> #include <cassert> +#include <cstddef> #include <iterator> #include <memory> +#include <vector> namespace clang { - class CXXDestructorDecl; - class Decl; - class Stmt; - class Expr; - class FieldDecl; - class VarDecl; - class CXXCtorInitializer; - class CXXBaseSpecifier; - class CXXBindTemporaryExpr; - class CFG; - class PrinterHelper; - class LangOptions; - class ASTContext; - class CXXRecordDecl; - class CXXDeleteExpr; - class CXXNewExpr; - class BinaryOperator; + +class ASTContext; +class BinaryOperator; +class CFG; +class CXXBaseSpecifier; +class CXXBindTemporaryExpr; +class CXXCtorInitializer; +class CXXDeleteExpr; +class CXXDestructorDecl; +class CXXNewExpr; +class CXXRecordDecl; +class Decl; +class FieldDecl; +class LangOptions; +class VarDecl; /// CFGElement - Represents a top-level expression in a basic block. class CFGElement { @@ -59,6 +59,7 @@ public: Initializer, NewAllocator, LifetimeEnds, + LoopExit, // dtor kind AutomaticObjectDtor, DeleteDtor, @@ -75,14 +76,14 @@ protected: llvm::PointerIntPair<void *, 2> Data2; CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr) - : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), - Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { + : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), + Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { assert(getKind() == kind); } - CFGElement() {} -public: + CFGElement() = default; +public: /// \brief Convert to the specified CFGElement type, asserting that this /// CFGElement is of the desired type. template<typename T> @@ -124,7 +125,9 @@ public: private: friend class CFGElement; - CFGStmt() {} + + CFGStmt() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Statement; } @@ -143,7 +146,9 @@ public: private: friend class CFGElement; - CFGInitializer() {} + + CFGInitializer() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Initializer; } @@ -162,12 +167,38 @@ public: private: friend class CFGElement; - CFGNewAllocator() {} + + CFGNewAllocator() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == NewAllocator; } }; +/// Represents the point where a loop ends. +/// This element is is only produced when building the CFG for the static +/// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag. +/// +/// Note: a loop exit element can be reached even when the loop body was never +/// entered. +class CFGLoopExit : public CFGElement { +public: + explicit CFGLoopExit(const Stmt *stmt) : CFGElement(LoopExit, stmt) {} + + const Stmt *getLoopStmt() const { + return static_cast<Stmt *>(Data1.getPointer()); + } + +private: + friend class CFGElement; + + CFGLoopExit() = default; + + static bool isKind(const CFGElement &elem) { + return elem.getKind() == LoopExit; + } +}; + /// Represents the point where the lifetime of an automatic object ends class CFGLifetimeEnds : public CFGElement { public: @@ -184,7 +215,9 @@ public: private: friend class CFGElement; - CFGLifetimeEnds() {} + + CFGLifetimeEnds() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == LifetimeEnds; } @@ -194,7 +227,8 @@ private: /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: - CFGImplicitDtor() {} + CFGImplicitDtor() = default; + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr) : CFGElement(kind, data1, data2) { assert(kind >= DTOR_BEGIN && kind <= DTOR_END); @@ -206,6 +240,7 @@ public: private: friend class CFGElement; + static bool isKind(const CFGElement &E) { Kind kind = E.getKind(); return kind >= DTOR_BEGIN && kind <= DTOR_END; @@ -231,7 +266,9 @@ public: private: friend class CFGElement; - CFGAutomaticObjDtor() {} + + CFGAutomaticObjDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == AutomaticObjectDtor; } @@ -255,7 +292,9 @@ public: private: friend class CFGElement; - CFGDeleteDtor() {} + + CFGDeleteDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == DeleteDtor; } @@ -274,7 +313,9 @@ public: private: friend class CFGElement; - CFGBaseDtor() {} + + CFGBaseDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == BaseDtor; } @@ -293,7 +334,9 @@ public: private: friend class CFGElement; - CFGMemberDtor() {} + + CFGMemberDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == MemberDtor; } @@ -312,7 +355,9 @@ public: private: friend class CFGElement; - CFGTemporaryDtor() {} + + CFGTemporaryDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == TemporaryDtor; } @@ -326,8 +371,9 @@ private: /// of matching full expression. class CFGTerminator { llvm::PointerIntPair<Stmt *, 1> Data; + public: - CFGTerminator() {} + CFGTerminator() = default; CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false) : Data(S, TemporaryDtorsBranch) {} @@ -373,21 +419,23 @@ public: /// &&, || expression that uses result of && or ||, RHS /// /// But note that any of that may be NULL in case of optimized-out edges. -/// class CFGBlock { class ElementList { - typedef BumpVector<CFGElement> ImplTy; + using ImplTy = BumpVector<CFGElement>; + ImplTy Impl; + public: ElementList(BumpVectorContext &C) : Impl(C, 4) {} - typedef std::reverse_iterator<ImplTy::iterator> iterator; - typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator; - typedef ImplTy::iterator reverse_iterator; - typedef ImplTy::const_iterator const_reverse_iterator; - typedef ImplTy::const_reference const_reference; + using iterator = std::reverse_iterator<ImplTy::iterator>; + using const_iterator = std::reverse_iterator<ImplTy::const_iterator>; + using reverse_iterator = ImplTy::iterator; + using const_reverse_iterator = ImplTy::const_iterator; + using const_reference = ImplTy::const_reference; void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } + reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E, BumpVectorContext &C) { return Impl.insert(I, Cnt, E, C); @@ -405,10 +453,10 @@ class CFGBlock { const_reverse_iterator rbegin() const { return Impl.begin(); } const_reverse_iterator rend() const { return Impl.end(); } - CFGElement operator[](size_t i) const { - assert(i < Impl.size()); - return Impl[Impl.size() - 1 - i]; - } + CFGElement operator[](size_t i) const { + assert(i < Impl.size()); + return Impl[Impl.size() - 1 - i]; + } size_t size() const { return Impl.size(); } bool empty() const { return Impl.empty(); } @@ -420,7 +468,7 @@ class CFGBlock { /// Label - An (optional) label that prefixes the executable /// statements in the block. When this variable is non-NULL, it is /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt. - Stmt *Label; + Stmt *Label = nullptr; /// Terminator - The terminator for a basic block that /// indicates the type of control-flow that occurs between a block @@ -430,7 +478,7 @@ class CFGBlock { /// LoopTarget - Some blocks are used to represent the "loop edge" to /// the start of a loop from within the loop body. This Stmt* will be /// refer to the loop statement for such blocks (and be null otherwise). - const Stmt *LoopTarget; + const Stmt *LoopTarget = nullptr; /// BlockID - A numerical ID assigned to a CFGBlock during construction /// of the CFG. @@ -450,7 +498,7 @@ public: }; CFGBlock *ReachableBlock; - llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock; + llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock; public: /// Construct an AdjacentBlock with a possibly unreachable block. @@ -493,7 +541,7 @@ public: private: /// Predecessors/Successors - Keep track of the predecessor / successor /// CFG blocks. - typedef BumpVector<AdjacentBlock> AdjacentBlocks; + using AdjacentBlocks = BumpVector<AdjacentBlock>; AdjacentBlocks Preds; AdjacentBlocks Succs; @@ -513,15 +561,14 @@ private: public: explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent) - : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr), - BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false), - Parent(parent) {} + : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1), + Succs(C, 1), HasNoReturnElement(false), Parent(parent) {} // Statement iterators - typedef ElementList::iterator iterator; - typedef ElementList::const_iterator const_iterator; - typedef ElementList::reverse_iterator reverse_iterator; - typedef ElementList::const_reverse_iterator const_reverse_iterator; + using iterator = ElementList::iterator; + using const_iterator = ElementList::const_iterator; + using reverse_iterator = ElementList::reverse_iterator; + using const_reverse_iterator = ElementList::const_reverse_iterator; CFGElement front() const { return Elements.front(); } CFGElement back() const { return Elements.back(); } @@ -542,19 +589,19 @@ public: CFGElement operator[](size_t i) const { return Elements[i]; } // CFG iterators - typedef AdjacentBlocks::iterator pred_iterator; - typedef AdjacentBlocks::const_iterator const_pred_iterator; - typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator; - typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator; - typedef llvm::iterator_range<pred_iterator> pred_range; - typedef llvm::iterator_range<const_pred_iterator> pred_const_range; - - typedef AdjacentBlocks::iterator succ_iterator; - typedef AdjacentBlocks::const_iterator const_succ_iterator; - typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator; - typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator; - typedef llvm::iterator_range<succ_iterator> succ_range; - typedef llvm::iterator_range<const_succ_iterator> succ_const_range; + using pred_iterator = AdjacentBlocks::iterator; + using const_pred_iterator = AdjacentBlocks::const_iterator; + using pred_reverse_iterator = AdjacentBlocks::reverse_iterator; + using const_pred_reverse_iterator = AdjacentBlocks::const_reverse_iterator; + using pred_range = llvm::iterator_range<pred_iterator>; + using pred_const_range = llvm::iterator_range<const_pred_iterator>; + + using succ_iterator = AdjacentBlocks::iterator; + using const_succ_iterator = AdjacentBlocks::const_iterator; + using succ_reverse_iterator = AdjacentBlocks::reverse_iterator; + using const_succ_reverse_iterator = AdjacentBlocks::const_reverse_iterator; + using succ_range = llvm::iterator_range<succ_iterator>; + using succ_const_range = llvm::iterator_range<const_succ_iterator>; pred_iterator pred_begin() { return Preds.begin(); } pred_iterator pred_end() { return Preds.end(); } @@ -566,10 +613,11 @@ public: const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); } const_pred_reverse_iterator pred_rend() const { return Preds.rend(); } - pred_range preds() { + pred_range preds() { return pred_range(pred_begin(), pred_end()); } - pred_const_range preds() const { + + pred_const_range preds() const { return pred_const_range(pred_begin(), pred_end()); } @@ -583,10 +631,11 @@ public: const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); } const_succ_reverse_iterator succ_rend() const { return Succs.rend(); } - succ_range succs() { + succ_range succs() { return succ_range(succ_begin(), succ_end()); } - succ_const_range succs() const { + + succ_const_range succs() const { return succ_const_range(succ_begin(), succ_end()); } @@ -599,13 +648,11 @@ public: class FilterOptions { public: - FilterOptions() { - IgnoreNullPredecessors = 1; - IgnoreDefaultsWithCoveredEnums = 0; - } - unsigned IgnoreNullPredecessors : 1; unsigned IgnoreDefaultsWithCoveredEnums : 1; + + FilterOptions() + : IgnoreNullPredecessors(1), IgnoreDefaultsWithCoveredEnums(0) {} }; static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, @@ -617,6 +664,7 @@ public: IMPL I, E; const FilterOptions F; const CFGBlock *From; + public: explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, const CFGBlock *from, @@ -634,17 +682,18 @@ public: } const CFGBlock *operator*() const { return *I; } + private: bool Filter(const CFGBlock *To) { return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To); } }; - typedef FilteredCFGBlockIterator<const_pred_iterator, true> - filtered_pred_iterator; + using filtered_pred_iterator = + FilteredCFGBlockIterator<const_pred_iterator, true>; - typedef FilteredCFGBlockIterator<const_succ_iterator, false> - filtered_succ_iterator; + using filtered_succ_iterator = + FilteredCFGBlockIterator<const_succ_iterator, false>; filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const { return filtered_pred_iterator(pred_begin(), pred_end(), this, f); @@ -728,6 +777,10 @@ public: Elements.push_back(CFGLifetimeEnds(VD, S), C); } + void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) { + Elements.push_back(CFGLoopExit(LoopStmt), C); + } + void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) { Elements.push_back(CFGDeleteDtor(RD, DE), C); } @@ -763,11 +816,12 @@ public: /// operator error is found when building the CFG. class CFGCallback { public: - CFGCallback() {} + CFGCallback() = default; + virtual ~CFGCallback() = default; + virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {} virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) {} - virtual ~CFGCallback() {} }; /// CFG - Represents a source-level, intra-procedural CFG that represents the @@ -785,19 +839,24 @@ public: class BuildOptions { std::bitset<Stmt::lastStmtConstant> alwaysAddMask; + public: - typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; - ForcedBlkExprs **forcedBlkExprs; - CFGCallback *Observer; - bool PruneTriviallyFalseEdges; - bool AddEHEdges; - bool AddInitializers; - bool AddImplicitDtors; - bool AddLifetime; - bool AddTemporaryDtors; - bool AddStaticInitBranches; - bool AddCXXNewAllocator; - bool AddCXXDefaultInitExprInCtors; + using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>; + + ForcedBlkExprs **forcedBlkExprs = nullptr; + CFGCallback *Observer = nullptr; + bool PruneTriviallyFalseEdges = true; + bool AddEHEdges = false; + bool AddInitializers = false; + bool AddImplicitDtors = false; + bool AddLifetime = false; + bool AddLoopExit = false; + bool AddTemporaryDtors = false; + bool AddStaticInitBranches = false; + bool AddCXXNewAllocator = false; + bool AddCXXDefaultInitExprInCtors = false; + + BuildOptions() = default; bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; @@ -812,15 +871,6 @@ public: alwaysAddMask.set(); return *this; } - - BuildOptions() - : forcedBlkExprs(nullptr), Observer(nullptr), - PruneTriviallyFalseEdges(true), - AddEHEdges(false), - AddInitializers(false), AddImplicitDtors(false), - AddLifetime(false), - AddTemporaryDtors(false), AddStaticInitBranches(false), - AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {} }; /// buildCFG - Builds a CFG from an AST. @@ -844,11 +894,11 @@ public: // Block Iterators //===--------------------------------------------------------------------===// - typedef BumpVector<CFGBlock*> CFGBlockListTy; - typedef CFGBlockListTy::iterator iterator; - typedef CFGBlockListTy::const_iterator const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + using CFGBlockListTy = BumpVector<CFGBlock *>; + using iterator = CFGBlockListTy::iterator; + using const_iterator = CFGBlockListTy::const_iterator; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; CFGBlock & front() { return *Blocks.front(); } CFGBlock & back() { return *Blocks.back(); } @@ -876,10 +926,12 @@ public: CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; } const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; } - typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator; + using try_block_iterator = std::vector<const CFGBlock *>::const_iterator; + try_block_iterator try_blocks_begin() const { return TryDispatchBlocks.begin(); } + try_block_iterator try_blocks_end() const { return TryDispatchBlocks.end(); } @@ -900,9 +952,9 @@ public: SyntheticDeclStmts[Synthetic] = Source; } - typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator - synthetic_stmt_iterator; - typedef llvm::iterator_range<synthetic_stmt_iterator> synthetic_stmt_range; + using synthetic_stmt_iterator = + llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator; + using synthetic_stmt_range = llvm::iterator_range<synthetic_stmt_iterator>; /// Iterates over synthetic DeclStmts in the CFG. /// @@ -962,9 +1014,7 @@ public: // Internal: constructors and data. //===--------------------------------------------------------------------===// - CFG() - : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0), - Blocks(BlkBVC, 10) {} + CFG() : Blocks(BlkBVC, 10) {} llvm::BumpPtrAllocator& getAllocator() { return BlkBVC.getAllocator(); @@ -975,11 +1025,13 @@ public: } private: - CFGBlock *Entry; - CFGBlock *Exit; - CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch - // for indirect gotos - unsigned NumBlockIDs; + CFGBlock *Entry = nullptr; + CFGBlock *Exit = nullptr; + + // Special block to contain collective dispatch for indirect gotos + CFGBlock* IndirectGotoBlock = nullptr; + + unsigned NumBlockIDs = 0; BumpVectorContext BlkBVC; @@ -993,7 +1045,8 @@ private: /// source DeclStmt. llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts; }; -} // end namespace clang + +} // namespace clang //===----------------------------------------------------------------------===// // GraphTraits specializations for CFG basic block graphs (source-level CFGs) @@ -1004,7 +1057,8 @@ namespace llvm { /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from /// CFGTerminator to a specific Stmt class. template <> struct simplify_type< ::clang::CFGTerminator> { - typedef ::clang::Stmt *SimpleType; + using SimpleType = ::clang::Stmt *; + static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) { return Val.getStmt(); } @@ -1013,50 +1067,44 @@ template <> struct simplify_type< ::clang::CFGTerminator> { // Traits for: CFGBlock template <> struct GraphTraits< ::clang::CFGBlock *> { - typedef ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::succ_iterator ChildIteratorType; + using NodeRef = ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::succ_iterator; static NodeRef getEntryNode(::clang::CFGBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } }; template <> struct GraphTraits< const ::clang::CFGBlock *> { - typedef const ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType; + using NodeRef = const ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_succ_iterator; static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } }; -template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > { - typedef ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse< ::clang::CFGBlock *>> { + using NodeRef = ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; static NodeRef getEntryNode(Inverse<::clang::CFGBlock *> G) { return G.Graph; } static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } }; -template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { - typedef const ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse<const ::clang::CFGBlock *>> { + using NodeRef = const ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; static NodeRef getEntryNode(Inverse<const ::clang::CFGBlock *> G) { return G.Graph; } static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } }; @@ -1064,8 +1112,7 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { template <> struct GraphTraits< ::clang::CFG* > : public GraphTraits< ::clang::CFGBlock *> { - - typedef ::clang::CFG::iterator nodes_iterator; + using nodes_iterator = ::clang::CFG::iterator; static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); } static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();} @@ -1075,44 +1122,47 @@ template <> struct GraphTraits< ::clang::CFG* > template <> struct GraphTraits<const ::clang::CFG* > : public GraphTraits<const ::clang::CFGBlock *> { - - typedef ::clang::CFG::const_iterator nodes_iterator; + using nodes_iterator = ::clang::CFG::const_iterator; static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); } + static nodes_iterator nodes_begin( const ::clang::CFG* F) { return F->nodes_begin(); } + static nodes_iterator nodes_end( const ::clang::CFG* F) { return F->nodes_end(); } + static unsigned size(const ::clang::CFG* F) { return F->size(); } }; -template <> struct GraphTraits<Inverse< ::clang::CFG*> > - : public GraphTraits<Inverse< ::clang::CFGBlock*> > { - - typedef ::clang::CFG::iterator nodes_iterator; +template <> struct GraphTraits<Inverse< ::clang::CFG *>> + : public GraphTraits<Inverse< ::clang::CFGBlock *>> { + using nodes_iterator = ::clang::CFG::iterator; static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); } static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();} static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); } }; -template <> struct GraphTraits<Inverse<const ::clang::CFG*> > - : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { - - typedef ::clang::CFG::const_iterator nodes_iterator; +template <> struct GraphTraits<Inverse<const ::clang::CFG *>> + : public GraphTraits<Inverse<const ::clang::CFGBlock *>> { + using nodes_iterator = ::clang::CFG::const_iterator; static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); } + static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->nodes_begin(); } + static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->nodes_end(); } }; -} // end llvm namespace + +} // namespace llvm #endif // LLVM_CLANG_ANALYSIS_CFG_H diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index a2a27a8e47c7..bdcdfecddc3e 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -1,4 +1,4 @@ -//== CallGraph.h - AST-based Call graph ------------------------*- C++ -*--==// +//===- CallGraph.h - AST-based Call graph -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,19 +12,27 @@ // A call graph for functions whose definitions/bodies are available in the // current translation unit. The graph has a "virtual" root node that contains // edges to all externally available functions. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H -#include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include <memory> namespace clang { + class CallGraphNode; +class Decl; +class DeclContext; +class Stmt; /// \brief The AST-based call graph. /// @@ -34,8 +42,8 @@ class CallGraphNode; class CallGraph : public RecursiveASTVisitor<CallGraph> { friend class CallGraphNode; - typedef llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>> - FunctionMapTy; + using FunctionMapTy = + llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>>; /// FunctionMap owns all CallGraphNodes. FunctionMapTy FunctionMap; @@ -65,10 +73,11 @@ public: /// one into the graph. CallGraphNode *getOrInsertNode(Decl *); + using iterator = FunctionMapTy::iterator; + using const_iterator = FunctionMapTy::const_iterator; + /// Iterators through all the elements in the graph. Note, this gives /// non-deterministic order. - typedef FunctionMapTy::iterator iterator; - typedef FunctionMapTy::const_iterator const_iterator; iterator begin() { return FunctionMap.begin(); } iterator end() { return FunctionMap.end(); } const_iterator begin() const { return FunctionMap.begin(); } @@ -84,8 +93,8 @@ public: /// Iterators through all the nodes of the graph that have no parent. These /// are the unreachable nodes, which are either unused or are due to us /// failing to add a call edge due to the analysis imprecision. - typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator; - typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator; + using nodes_iterator = llvm::SetVector<CallGraphNode *>::iterator; + using const_nodes_iterator = llvm::SetVector<CallGraphNode *>::const_iterator; void print(raw_ostream &os) const; void dump() const; @@ -133,7 +142,7 @@ private: class CallGraphNode { public: - typedef CallGraphNode* CallRecord; + using CallRecord = CallGraphNode *; private: /// \brief The function/method declaration. @@ -145,17 +154,17 @@ private: public: CallGraphNode(Decl *D) : FD(D) {} - typedef SmallVectorImpl<CallRecord>::iterator iterator; - typedef SmallVectorImpl<CallRecord>::const_iterator const_iterator; + using iterator = SmallVectorImpl<CallRecord>::iterator; + using const_iterator = SmallVectorImpl<CallRecord>::const_iterator; /// Iterators through all the callees/children of the node. - inline iterator begin() { return CalledFunctions.begin(); } - inline iterator end() { return CalledFunctions.end(); } - inline const_iterator begin() const { return CalledFunctions.begin(); } - inline const_iterator end() const { return CalledFunctions.end(); } + iterator begin() { return CalledFunctions.begin(); } + iterator end() { return CalledFunctions.end(); } + const_iterator begin() const { return CalledFunctions.begin(); } + const_iterator end() const { return CalledFunctions.end(); } - inline bool empty() const {return CalledFunctions.empty(); } - inline unsigned size() const {return CalledFunctions.size(); } + bool empty() const { return CalledFunctions.empty(); } + unsigned size() const { return CalledFunctions.size(); } void addCallee(CallGraphNode *N) { CalledFunctions.push_back(N); @@ -167,35 +176,33 @@ public: void dump() const; }; -} // end clang namespace +} // namespace clang // Graph traits for iteration, viewing. namespace llvm { + template <> struct GraphTraits<clang::CallGraphNode*> { - typedef clang::CallGraphNode NodeType; - typedef clang::CallGraphNode *NodeRef; - typedef NodeType::iterator ChildIteratorType; + using NodeType = clang::CallGraphNode; + using NodeRef = clang::CallGraphNode *; + using ChildIteratorType = NodeType::iterator; static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; } - static inline ChildIteratorType child_begin(NodeType *N) { - return N->begin(); - } - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static ChildIteratorType child_begin(NodeType *N) { return N->begin(); } + static ChildIteratorType child_end(NodeType *N) { return N->end(); } }; template <> struct GraphTraits<const clang::CallGraphNode*> { - typedef const clang::CallGraphNode NodeType; - typedef const clang::CallGraphNode *NodeRef; - typedef NodeType::const_iterator ChildIteratorType; + using NodeType = const clang::CallGraphNode; + using NodeRef = const clang::CallGraphNode *; + using ChildIteratorType = NodeType::const_iterator; static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; } - static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static ChildIteratorType child_begin(NodeType *N) { return N->begin();} + static ChildIteratorType child_end(NodeType *N) { return N->end(); } }; template <> struct GraphTraits<clang::CallGraph*> : public GraphTraits<clang::CallGraphNode*> { - static NodeType *getEntryNode(clang::CallGraph *CGN) { return CGN->getRoot(); // Start at the external node! } @@ -206,19 +213,18 @@ template <> struct GraphTraits<clang::CallGraph*> } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)> - nodes_iterator; + using nodes_iterator = + mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)>; static nodes_iterator nodes_begin(clang::CallGraph *CG) { return nodes_iterator(CG->begin(), &CGGetValue); } + static nodes_iterator nodes_end (clang::CallGraph *CG) { return nodes_iterator(CG->end(), &CGGetValue); } - static unsigned size(clang::CallGraph *CG) { - return CG->size(); - } + static unsigned size(clang::CallGraph *CG) { return CG->size(); } }; template <> struct GraphTraits<const clang::CallGraph*> : @@ -233,21 +239,20 @@ template <> struct GraphTraits<const clang::CallGraph*> : } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef mapped_iterator<clang::CallGraph::const_iterator, - decltype(&CGGetValue)> - nodes_iterator; + using nodes_iterator = + mapped_iterator<clang::CallGraph::const_iterator, decltype(&CGGetValue)>; static nodes_iterator nodes_begin(const clang::CallGraph *CG) { return nodes_iterator(CG->begin(), &CGGetValue); } + static nodes_iterator nodes_end(const clang::CallGraph *CG) { return nodes_iterator(CG->end(), &CGGetValue); } - static unsigned size(const clang::CallGraph *CG) { - return CG->size(); - } + + static unsigned size(const clang::CallGraph *CG) { return CG->size(); } }; -} // end llvm namespace +} // namespace llvm -#endif +#endif // LLVM_CLANG_ANALYSIS_CALLGRAPH_H diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h index 6339deef41bd..051b9236658c 100644 --- a/include/clang/Analysis/CloneDetection.h +++ b/include/clang/Analysis/CloneDetection.h @@ -7,19 +7,15 @@ // //===----------------------------------------------------------------------===// /// -/// /file -/// This file defines classes for searching and anlyzing source code clones. +/// \file +/// This file defines classes for searching and analyzing source code clones. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_CLONEDETECTION_H #define LLVM_CLANG_AST_CLONEDETECTION_H -#include "clang/AST/DeclTemplate.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/Regex.h" #include <vector> @@ -31,192 +27,6 @@ class VarDecl; class ASTContext; class CompoundStmt; -namespace clone_detection { - -/// Returns a string that represents all macro expansions that expanded into the -/// given SourceLocation. -/// -/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations -/// A and B are expanded from the same macros in the same order. -std::string getMacroStack(SourceLocation Loc, ASTContext &Context); - -/// Collects the data of a single Stmt. -/// -/// This class defines what a code clone is: If it collects for two statements -/// the same data, then those two statements are considered to be clones of each -/// other. -/// -/// All collected data is forwarded to the given data consumer of the type T. -/// The data consumer class needs to provide a member method with the signature: -/// update(StringRef Str) -template <typename T> -class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector<T>> { - - ASTContext &Context; - /// The data sink to which all data is forwarded. - T &DataConsumer; - -public: - /// Collects data of the given Stmt. - /// \param S The given statement. - /// \param Context The ASTContext of S. - /// \param DataConsumer The data sink to which all data is forwarded. - StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer) - : Context(Context), DataConsumer(DataConsumer) { - this->Visit(S); - } - - typedef unsigned DataPiece; - - // Below are utility methods for appending different data to the vector. - - void addData(DataPiece Integer) { - DataConsumer.update( - StringRef(reinterpret_cast<char *>(&Integer), sizeof(Integer))); - } - - void addData(llvm::StringRef Str) { DataConsumer.update(Str); } - - void addData(const QualType &QT) { addData(QT.getAsString()); } - -// The functions below collect the class specific data of each Stmt subclass. - -// Utility macro for defining a visit method for a given class. This method -// calls back to the ConstStmtVisitor to visit all parent classes. -#define DEF_ADD_DATA(CLASS, CODE) \ - void Visit##CLASS(const CLASS *S) { \ - CODE; \ - ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \ - } - - DEF_ADD_DATA(Stmt, { - addData(S->getStmtClass()); - // This ensures that macro generated code isn't identical to macro-generated - // code. - addData(getMacroStack(S->getLocStart(), Context)); - addData(getMacroStack(S->getLocEnd(), Context)); - }) - DEF_ADD_DATA(Expr, { addData(S->getType()); }) - - //--- Builtin functionality ----------------------------------------------// - DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); }) - DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); }) - DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); }) - DEF_ADD_DATA(TypeTraitExpr, { - addData(S->getTrait()); - for (unsigned i = 0; i < S->getNumArgs(); ++i) - addData(S->getArg(i)->getType()); - }) - - //--- Calls --------------------------------------------------------------// - DEF_ADD_DATA(CallExpr, { - // Function pointers don't have a callee and we just skip hashing it. - if (const FunctionDecl *D = S->getDirectCallee()) { - // If the function is a template specialization, we also need to handle - // the template arguments as they are not included in the qualified name. - if (auto Args = D->getTemplateSpecializationArgs()) { - std::string ArgString; - - // Print all template arguments into ArgString - llvm::raw_string_ostream OS(ArgString); - for (unsigned i = 0; i < Args->size(); ++i) { - Args->get(i).print(Context.getLangOpts(), OS); - // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'. - OS << '\n'; - } - OS.flush(); - - addData(ArgString); - } - addData(D->getQualifiedNameAsString()); - } - }) - - //--- Exceptions ---------------------------------------------------------// - DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); }) - - //--- C++ OOP Stmts ------------------------------------------------------// - DEF_ADD_DATA(CXXDeleteExpr, { - addData(S->isArrayFormAsWritten()); - addData(S->isGlobalDelete()); - }) - - //--- Casts --------------------------------------------------------------// - DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); }) - - //--- Miscellaneous Exprs ------------------------------------------------// - DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); }) - DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); }) - - //--- Control flow -------------------------------------------------------// - DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); }) - DEF_ADD_DATA(IndirectGotoStmt, { - if (S->getConstantTarget()) - addData(S->getConstantTarget()->getName()); - }) - DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); }) - DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); }) - DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); }) - - //--- Objective-C --------------------------------------------------------// - DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); }) - DEF_ADD_DATA(ObjCPropertyRefExpr, { - addData(S->isSuperReceiver()); - addData(S->isImplicitProperty()); - }) - DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); }) - - //--- Miscellaneous Stmts ------------------------------------------------// - DEF_ADD_DATA(CXXFoldExpr, { - addData(S->isRightFold()); - addData(S->getOperator()); - }) - DEF_ADD_DATA(GenericSelectionExpr, { - for (unsigned i = 0; i < S->getNumAssocs(); ++i) { - addData(S->getAssocType(i)); - } - }) - DEF_ADD_DATA(LambdaExpr, { - for (const LambdaCapture &C : S->captures()) { - addData(C.isPackExpansion()); - addData(C.getCaptureKind()); - if (C.capturesVariable()) - addData(C.getCapturedVar()->getType()); - } - addData(S->isGenericLambda()); - addData(S->isMutable()); - }) - DEF_ADD_DATA(DeclStmt, { - auto numDecls = std::distance(S->decl_begin(), S->decl_end()); - addData(static_cast<DataPiece>(numDecls)); - for (const Decl *D : S->decls()) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - addData(VD->getType()); - } - } - }) - DEF_ADD_DATA(AsmStmt, { - addData(S->isSimple()); - addData(S->isVolatile()); - addData(S->generateAsmString(Context)); - for (unsigned i = 0; i < S->getNumInputs(); ++i) { - addData(S->getInputConstraint(i)); - } - for (unsigned i = 0; i < S->getNumOutputs(); ++i) { - addData(S->getOutputConstraint(i)); - } - for (unsigned i = 0; i < S->getNumClobbers(); ++i) { - addData(S->getClobber(i)); - } - }) - DEF_ADD_DATA(AttributedStmt, { - for (const Attr *A : S->getAttrs()) { - addData(std::string(A->getSpelling())); - } - }) -}; -} // namespace clone_detection - /// Identifies a list of statements. /// /// Can either identify a single arbitrary Stmt object, a continuous sequence of @@ -423,9 +233,9 @@ public: /// filtered. /// \param Filter The filter function that should return true for all groups /// that should be removed from the list. - static void - filterGroups(std::vector<CloneDetector::CloneGroup> &CloneGroups, - std::function<bool(const CloneDetector::CloneGroup &)> Filter) { + static void filterGroups( + std::vector<CloneDetector::CloneGroup> &CloneGroups, + llvm::function_ref<bool(const CloneDetector::CloneGroup &)> Filter) { CloneGroups.erase( std::remove_if(CloneGroups.begin(), CloneGroups.end(), Filter), CloneGroups.end()); @@ -439,25 +249,29 @@ public: /// to the same CloneGroup. static void splitCloneGroups( std::vector<CloneDetector::CloneGroup> &CloneGroups, - std::function<bool(const StmtSequence &, const StmtSequence &)> Compare); + llvm::function_ref<bool(const StmtSequence &, const StmtSequence &)> + Compare); }; -/// Searches all children of the given clones for type II clones (i.e. they are -/// identical in every aspect beside the used variable names). -class RecursiveCloneTypeIIConstraint { - - /// Generates and saves a hash code for the given Stmt. - /// \param S The given Stmt. - /// \param D The Decl containing S. - /// \param StmtsByHash Output parameter that will contain the hash codes for - /// each StmtSequence in the given Stmt. - /// \return The hash code of the given Stmt. - /// - /// If the given Stmt is a CompoundStmt, this method will also generate - /// hashes for all possible StmtSequences in the children of this Stmt. - size_t saveHash(const Stmt *S, const Decl *D, - std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash); +/// This constraint moves clones into clone groups of type II via hashing. +/// +/// Clones with different hash values are moved into separate clone groups. +/// Collisions are possible, and this constraint does nothing to address this +/// them. Add the slower RecursiveCloneTypeIIVerifyConstraint later in the +/// constraint chain, not necessarily immediately, to eliminate hash collisions +/// through a more detailed analysis. +class RecursiveCloneTypeIIHashConstraint { +public: + void constrain(std::vector<CloneDetector::CloneGroup> &Sequences); +}; +/// This constraint moves clones into clone groups of type II by comparing them. +/// +/// Clones that aren't type II clones are moved into separate clone groups. +/// In contrast to the RecursiveCloneTypeIIHashConstraint, all clones in a clone +/// group are guaranteed to be be type II clones of each other, but it is too +/// slow to efficiently handle large amounts of clones. +class RecursiveCloneTypeIIVerifyConstraint { public: void constrain(std::vector<CloneDetector::CloneGroup> &Sequences); }; @@ -474,14 +288,19 @@ public: MinComplexityConstraint(unsigned MinComplexity) : MinComplexity(MinComplexity) {} - size_t calculateStmtComplexity(const StmtSequence &Seq, + /// Calculates the complexity of the given StmtSequence. + /// \param Limit The limit of complexity we probe for. After reaching + /// this limit during calculation, this method is exiting + /// early to improve performance and returns this limit. + size_t calculateStmtComplexity(const StmtSequence &Seq, std::size_t Limit, const std::string &ParentMacroStack = ""); void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) { CloneConstraint::filterGroups( CloneGroups, [this](const CloneDetector::CloneGroup &A) { if (!A.empty()) - return calculateStmtComplexity(A.front()) < MinComplexity; + return calculateStmtComplexity(A.front(), MinComplexity) < + MinComplexity; else return false; }); diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index be5adfb29423..2d59dec48a88 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H #define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -83,6 +83,7 @@ public: PostImplicitCallKind, MinImplicitCallKind = PreImplicitCallKind, MaxImplicitCallKind = PostImplicitCallKind, + LoopExitKind, EpsilonKind}; private: @@ -654,6 +655,29 @@ private: } }; +/// Represents a point when we exit a loop. +/// When this ProgramPoint is encountered we can be sure that the symbolic +/// execution of the corresponding LoopStmt is finished on the given path. +/// Note: It is possible to encounter a LoopExit element when we haven't even +/// encountered the loop itself. At the current state not all loop exits will +/// result in a LoopExit program point. +class LoopExit : public ProgramPoint { +public: + LoopExit(const Stmt *LoopStmt, const LocationContext *LC) + : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {} + + const Stmt *getLoopStmt() const { + return static_cast<const Stmt *>(getData1()); + } + +private: + friend class ProgramPoint; + LoopExit() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == LoopExitKind; + } +}; + /// This is a meta program point, which should be skipped by all the diagnostic /// reasoning etc. class EpsilonPoint : public ProgramPoint { diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index 591d17b9bc03..5940520855ef 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -1,4 +1,4 @@ -//===-- BumpVector.h - Vector-like ADT that uses bump allocation --*- C++ -*-=// +//===- BumpVector.h - Vector-like ADT that uses bump allocation -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,16 +21,18 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/type_traits.h" -#include <algorithm> +#include <cassert> +#include <cstddef> #include <cstring> #include <iterator> #include <memory> +#include <type_traits> namespace clang { class BumpVectorContext { llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc; + public: /// Construct a new BumpVectorContext that creates a new BumpPtrAllocator /// and destroys it when the BumpVectorContext object is destroyed. @@ -56,11 +58,13 @@ public: template<typename T> class BumpVector { - T *Begin, *End, *Capacity; + T *Begin = nullptr; + T *End = nullptr; + T *Capacity = nullptr; + public: // Default ctor - Initialize to empty. - explicit BumpVector(BumpVectorContext &C, unsigned N) - : Begin(nullptr), End(nullptr), Capacity(nullptr) { + explicit BumpVector(BumpVectorContext &C, unsigned N) { reserve(C, N); } @@ -71,19 +75,19 @@ public: } } - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T* iterator; - typedef const T* const_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + using value_type = T; + using iterator = T *; + using const_iterator = const T *; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using reverse_iterator = std::reverse_iterator<iterator>; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; + using reference = T &; + using const_reference = const T &; + using pointer = T *; + using const_pointer = const T *; // forward iterator creation methods. iterator begin() { return Begin; } @@ -92,10 +96,12 @@ public: const_iterator end() const { return End; } // reverse iterator creation methods. - reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } bool empty() const { return Begin == End; } size_type size() const { return End-Begin; } @@ -166,7 +172,7 @@ public: /// iterator to position after last inserted copy. iterator insert(iterator I, size_t Cnt, const_reference E, BumpVectorContext &C) { - assert (I >= Begin && I <= End && "Iterator out of bounds."); + assert(I >= Begin && I <= End && "Iterator out of bounds."); if (End + Cnt <= Capacity) { Retry: move_range_right(I, End, Cnt); @@ -246,5 +252,6 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) { Capacity = Begin+NewCapacity; } -} // end: clang namespace -#endif +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index 95b9b9c7d0b3..6b0090813e9b 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -16,25 +16,26 @@ #ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H #define LLVM_CLANG_BASIC_ADDRESSSPACES_H -namespace clang { +#include <assert.h> -namespace LangAS { +namespace clang { /// \brief Defines the address space values used by the address space qualifier /// of QualType. /// -enum ID { +enum class LangAS : unsigned { // The default value 0 is the value used in QualType for the the situation - // where there is no address space qualifier. For most languages, this also - // corresponds to the situation where there is no address space qualifier in - // the source code, except for OpenCL, where the address space value 0 in - // QualType represents private address space in OpenCL source code. + // where there is no address space qualifier. Default = 0, // OpenCL specific address spaces. + // In OpenCL each l-value must have certain non-default address space, each + // r-value must have no address space (i.e. the default address space). The + // pointee of a pointer must have non-default address space. opencl_global, opencl_local, opencl_constant, + opencl_private, opencl_generic, // CUDA specific address spaces. @@ -50,9 +51,24 @@ enum ID { /// The type of a lookup table which maps from language-specific address spaces /// to target-specific ones. -typedef unsigned Map[FirstTargetAddressSpace]; +typedef unsigned LangASMap[(unsigned)LangAS::FirstTargetAddressSpace]; + +/// \return whether \p AS is a target-specific address space rather than a +/// clang AST address space +inline bool isTargetAddressSpace(LangAS AS) { + return (unsigned)AS >= (unsigned)LangAS::FirstTargetAddressSpace; } +inline unsigned toTargetAddressSpace(LangAS AS) { + assert(isTargetAddressSpace(AS)); + return (unsigned)AS - (unsigned)LangAS::FirstTargetAddressSpace; } +inline LangAS getLangASFromTargetAS(unsigned TargetAS) { + return static_cast<LangAS>((TargetAS) + + (unsigned)LangAS::FirstTargetAddressSpace); +} + +} // namespace clang + #endif diff --git a/include/clang/Basic/AlignedAllocation.h b/include/clang/Basic/AlignedAllocation.h new file mode 100644 index 000000000000..b3496949f39a --- /dev/null +++ b/include/clang/Basic/AlignedAllocation.h @@ -0,0 +1,44 @@ +//===--- AlignedAllocation.h - Aligned Allocation ---------------*- 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 a function that returns the minimum OS versions supporting +/// C++17's aligned allocation functions. +/// +//===----------------------------------------------------------------------===// + +#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" + +namespace clang { + +inline 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); + case llvm::Triple::IOS: + case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0. + return VersionTuple(11U); + case llvm::Triple::WatchOS: // Earliest supporting version is 4.0.0. + return VersionTuple(4U); + } + + llvm_unreachable("Unexpected OS"); +} + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h index fc861a1952a5..1c83e2d0f8a0 100644 --- a/include/clang/Basic/AllDiagnostics.h +++ b/include/clang/Basic/AllDiagnostics.h @@ -18,12 +18,14 @@ #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CommentDiagnostic.h" #include "clang/Analysis/AnalysisDiagnostic.h" +#include "clang/CrossTU/CrossTUDiagnostic.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/Serialization/SerializationDiagnostic.h" +#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h" namespace clang { template <size_t SizeOfStr, typename FieldType> diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 5c69635b9492..d926fdde4eee 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -69,44 +69,47 @@ include "clang/Basic/StmtNodes.td" // // The code fragment is a boolean expression that will confirm that the subject // meets the requirements; the subject will have the name S, and will have the -// type specified by the base. It should be a simple boolean expression. -class SubsetSubject<AttrSubject base, code check> : AttrSubject { +// type specified by the base. It should be a simple boolean expression. The +// diagnostic string should be a comma-separated list of subject names. +class SubsetSubject<AttrSubject base, code check, string diag> : AttrSubject { AttrSubject Base = base; code CheckCode = check; + string DiagSpelling = diag; } -// This is the type of a variable which C++11 allows alignas(...) to appertain -// to. -def NormalVar : SubsetSubject<Var, - [{S->getStorageClass() != VarDecl::Register && - S->getKind() != Decl::ImplicitParam && - S->getKind() != Decl::ParmVar && - S->getKind() != Decl::NonTypeTemplateParm}]>; +def LocalVar : SubsetSubject<Var, + [{S->hasLocalStorage() && !isa<ParmVarDecl>(S)}], + "local variables">; def NonParmVar : SubsetSubject<Var, - [{S->getKind() != Decl::ParmVar}]>; + [{S->getKind() != Decl::ParmVar}], + "variables">; def NonBitField : SubsetSubject<Field, - [{!S->isBitField()}]>; + [{!S->isBitField()}], + "non-bit-field non-static data members">; def ObjCInstanceMethod : SubsetSubject<ObjCMethod, - [{S->isInstanceMethod()}]>; + [{S->isInstanceMethod()}], + "Objective-C instance methods">; def ObjCInterfaceDeclInitMethod : SubsetSubject<ObjCMethod, [{S->getMethodFamily() == OMF_init && (isa<ObjCInterfaceDecl>(S->getDeclContext()) || (isa<ObjCCategoryDecl>(S->getDeclContext()) && - cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}]>; + cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}], + "init methods of interface or class extension declarations">; def Struct : SubsetSubject<Record, - [{!S->isUnion()}]>; + [{!S->isUnion()}], "structs">; def TLSVar : SubsetSubject<Var, - [{S->getTLSKind() != 0}]>; + [{S->getTLSKind() != 0}], "thread-local variables">; def SharedVar : SubsetSubject<Var, - [{S->hasGlobalStorage() && !S->getTLSKind()}]>; + [{S->hasGlobalStorage() && !S->getTLSKind()}], + "global variables">; def GlobalVar : SubsetSubject<Var, - [{S->hasGlobalStorage()}]>; + [{S->hasGlobalStorage()}], "global variables">; // 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 @@ -115,11 +118,12 @@ def GlobalVar : SubsetSubject<Var, // the case of a SubsetSubject, there's no way to express it without this hack. def DeclBase : AttrSubject; def FunctionLike : SubsetSubject<DeclBase, - [{S->getFunctionType(false) != nullptr}]>; + [{S->getFunctionType(false) != nullptr}], + "functions, function pointers">; -def OpenCLKernelFunction : SubsetSubject<Function, [{ - S->hasAttr<OpenCLKernelAttr>() -}]>; +def OpenCLKernelFunction + : SubsetSubject<Function, [{S->hasAttr<OpenCLKernelAttr>()}], + "kernel functions">; // HasFunctionProto is a more strict version of FunctionLike, so it should // never be specified in a Subjects list along with FunctionLike (due to the @@ -128,7 +132,8 @@ def HasFunctionProto : SubsetSubject<DeclBase, [{(S->getFunctionType(true) != nullptr && isa<FunctionProtoType>(S->getFunctionType())) || isa<ObjCMethodDecl>(S) || - isa<BlockDecl>(S)}]>; + isa<BlockDecl>(S)}], + "non-K&R-style functions">; // A single argument to an attribute class Argument<string name, bit optional, bit fake = 0> { @@ -210,18 +215,26 @@ class CXX11<string namespace, string name, int version = 1> string Namespace = namespace; int Version = version; } +class C2x<string namespace, string name> : Spelling<name, "C2x"> { + string Namespace = namespace; +} + class Keyword<string name> : Spelling<name, "Keyword">; class Pragma<string namespace, string name> : Spelling<name, "Pragma"> { string Namespace = namespace; } -// The GCC spelling implies GNU<name, "GNU"> and CXX11<"gnu", name> and also -// sets KnownToGCC to 1. This spelling should be used for any GCC-compatible +// The GCC spelling implies GNU<name> and CXX11<"gnu", name> and also sets +// KnownToGCC to 1. This spelling should be used for any GCC-compatible // attributes. 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">; + class Accessor<string name, list<Spelling> spellings> { string Name = name; list<Spelling> Spellings = spellings; @@ -264,14 +277,15 @@ class TargetArch<list<string> arches> { } def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>; def TargetAVR : TargetArch<["avr"]>; -def TargetMips : TargetArch<["mips", "mipsel"]>; +def TargetMips32 : TargetArch<["mips", "mipsel"]>; +def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>; def TargetMSP430 : TargetArch<["msp430"]>; def TargetX86 : TargetArch<["x86"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; -def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> { +def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> { let OSes = ["Win32"]; } -def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> { +def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> { let CXXABIs = ["Microsoft"]; } @@ -493,14 +507,13 @@ class IgnoredAttr : Attr { def AbiTag : Attr { let Spellings = [GCC<"abi_tag">]; let Args = [VariadicStringArgument<"Tags">]; - let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag, - "ExpectedStructClassVariableFunctionOrInlineNamespace">; + let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag>; let MeaningfulToClassTemplateDefinition = 1; let Documentation = [AbiTagsDocs]; } def AddressSpace : TypeAttr { - let Spellings = [GNU<"address_space">]; + let Spellings = [Clang<"address_space">]; let Args = [IntArgument<"AddressSpace">]; let Documentation = [Undocumented]; } @@ -508,15 +521,13 @@ def AddressSpace : TypeAttr { def Alias : Attr { let Spellings = [GCC<"alias">]; let Args = [StringArgument<"Aliasee">]; - let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag, - "ExpectedFunctionOrGlobalVar">; + let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag>; let Documentation = [Undocumented]; } def Aligned : InheritableAttr { let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">, Keyword<"_Alignas">]; -// let Subjects = SubjectList<[NonBitField, NormalVar, Tag]>; let Args = [AlignedArgument<"Alignment", 1>]; let Accessors = [Accessor<"isGNU", [GCC<"aligned">]>, Accessor<"isC11", [Keyword<"_Alignas">]>, @@ -534,13 +545,15 @@ def AlignValue : Attr { // the future (and a corresponding C++ attribute), but this can be done // later once we decide if we also want them to have slightly-different // semantics than Intel's align_value. + // + // Does not get a [[]] spelling because the attribute is not exposed as such + // by Intel. GNU<"align_value"> // Intel's compiler on Windows also supports: // , Declspec<"align_value"> ]; let Args = [ExprArgument<"Alignment">]; - let Subjects = SubjectList<[Var, TypedefName], WarnDiag, - "ExpectedVariableOrTypedef">; + let Subjects = SubjectList<[Var, TypedefName]>; let Documentation = [AlignValueDocs]; } @@ -558,44 +571,40 @@ def AlwaysInline : InheritableAttr { } def XRayInstrument : InheritableAttr { - let Spellings = [GNU<"xray_always_instrument">, - CXX11<"clang", "xray_always_instrument">, - GNU<"xray_never_instrument">, - CXX11<"clang", "xray_never_instrument">]; - let Subjects = SubjectList<[CXXMethod, ObjCMethod, Function], WarnDiag, - "ExpectedFunctionOrMethod">; + let Spellings = [Clang<"xray_always_instrument">, + Clang<"xray_never_instrument">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; let Accessors = [Accessor<"alwaysXRayInstrument", - [GNU<"xray_always_instrument">, - CXX11<"clang", "xray_always_instrument">]>, + [Clang<"xray_always_instrument">]>, Accessor<"neverXRayInstrument", - [GNU<"xray_never_instrument">, - CXX11<"clang", "xray_never_instrument">]>]; + [Clang<"xray_never_instrument">]>]; let Documentation = [XRayDocs]; } def XRayLogArgs : InheritableAttr { - let Spellings = [GNU<"xray_log_args">, CXX11<"clang", "xray_log_args">]; - let Subjects = SubjectList< - [CXXMethod, ObjCMethod, Function], WarnDiag, "ExpectedFunctionOrMethod" - >; + let Spellings = [Clang<"xray_log_args">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; let Args = [UnsignedArgument<"ArgumentCount">]; let Documentation = [XRayDocs]; } def TLSModel : InheritableAttr { let Spellings = [GCC<"tls_model">]; - let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">; + let Subjects = SubjectList<[TLSVar], ErrorDiag>; let Args = [StringArgument<"Model">]; let Documentation = [TLSModelDocs]; } def AnalyzerNoReturn : InheritableAttr { + // TODO: should this attribute be exposed with a [[]] spelling under the clang + // vendor namespace, or should it use a vendor namespace specific to the + // analyzer? let Spellings = [GNU<"analyzer_noreturn">]; let Documentation = [Undocumented]; } def Annotate : InheritableParamAttr { - let Spellings = [GNU<"annotate">]; + let Spellings = [Clang<"annotate">]; let Args = [StringArgument<"Annotation">]; // Ensure that the annotate attribute can be used with // '#pragma clang attribute' even though it has no subject list. @@ -606,7 +615,7 @@ def Annotate : InheritableParamAttr { def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> { // NOTE: If you add any additional spellings, MSP430Interrupt's, // MipsInterrupt's and AnyX86Interrupt's spellings must match. - let Spellings = [GNU<"interrupt">]; + let Spellings = [GCC<"interrupt">]; let Args = [EnumArgument<"Interrupt", "InterruptType", ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""], ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", "Generic"], @@ -617,14 +626,14 @@ def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> { } def AVRInterrupt : InheritableAttr, TargetSpecificAttr<TargetAVR> { - let Spellings = [GNU<"interrupt">]; + let Spellings = [GCC<"interrupt">]; let Subjects = SubjectList<[Function]>; let ParseKind = "Interrupt"; let Documentation = [AVRInterruptDocs]; } def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> { - let Spellings = [GNU<"signal">]; + let Spellings = [GCC<"signal">]; let Subjects = SubjectList<[Function]>; let Documentation = [AVRSignalDocs]; } @@ -637,6 +646,8 @@ def AsmLabel : InheritableAttr { } def Availability : InheritableAttr { + // TODO: does not have a [[]] spelling because it requires custom parsing + // support. let Spellings = [GNU<"availability">]; let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, VersionArgument<"deprecated">, VersionArgument<"obsoleted">, @@ -687,8 +698,7 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { } def ExternalSourceSymbol : InheritableAttr { - let Spellings = [GNU<"external_source_symbol">, - CXX11<"clang", "external_source_symbol">]; + let Spellings = [Clang<"external_source_symbol">]; let Args = [StringArgument<"language", 1>, StringArgument<"definedIn", 1>, BoolArgument<"generatedDeclaration", 1>]; @@ -698,12 +708,13 @@ def ExternalSourceSymbol : InheritableAttr { } def Blocks : InheritableAttr { - let Spellings = [GNU<"blocks">]; + let Spellings = [Clang<"blocks">]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; let Documentation = [Undocumented]; } def Bounded : IgnoredAttr { + // Does not have a [[]] spelling because the attribute is ignored. let Spellings = [GNU<"bounded">]; } @@ -725,7 +736,7 @@ def CDecl : InheritableAttr { // cf_returns_retained attributes. It is generally applied by // '#pragma clang arc_cf_code_audited' rather than explicitly. def CFAuditedTransfer : InheritableAttr { - let Spellings = [GNU<"cf_audited_transfer">]; + let Spellings = [Clang<"cf_audited_transfer">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; } @@ -734,25 +745,25 @@ def CFAuditedTransfer : InheritableAttr { // It indicates that the function has unknown or unautomatable // transfer semantics. def CFUnknownTransfer : InheritableAttr { - let Spellings = [GNU<"cf_unknown_transfer">]; + let Spellings = [Clang<"cf_unknown_transfer">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; } def CFReturnsRetained : InheritableAttr { - let Spellings = [GNU<"cf_returns_retained">]; + let Spellings = [Clang<"cf_returns_retained">]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def CFReturnsNotRetained : InheritableAttr { - let Spellings = [GNU<"cf_returns_not_retained">]; + let Spellings = [Clang<"cf_returns_not_retained">]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def CFConsumed : InheritableParamAttr { - let Spellings = [GNU<"cf_consumed">]; + let Spellings = [Clang<"cf_consumed">]; let Subjects = SubjectList<[ParmVar]>; let Documentation = [Undocumented]; } @@ -760,7 +771,7 @@ def CFConsumed : InheritableParamAttr { def Cleanup : InheritableAttr { let Spellings = [GCC<"cleanup">]; let Args = [FunctionArgument<"FunctionDecl">]; - let Subjects = SubjectList<[Var]>; + let Subjects = SubjectList<[LocalVar]>; let Documentation = [Undocumented]; } @@ -788,8 +799,8 @@ def Constructor : InheritableAttr { let Documentation = [Undocumented]; } -// CUDA attributes are spelled __attribute__((attr)) or __declspec(__attr__). - +// CUDA attributes are spelled __attribute__((attr)) or __declspec(__attr__), +// and they do not receive a [[]] spelling. def CUDAConstant : InheritableAttr { let Spellings = [GNU<"constant">, Declspec<"__constant__">]; let Subjects = SubjectList<[Var]>; @@ -851,8 +862,7 @@ def CUDALaunchBounds : InheritableAttr { let Spellings = [GNU<"launch_bounds">, Declspec<"__launch_bounds__">]; let Args = [ExprArgument<"MaxThreads">, ExprArgument<"MinBlocks", 1>]; let LangOpts = [CUDA]; - let Subjects = SubjectList<[ObjCMethod, FunctionLike], WarnDiag, - "ExpectedFunctionOrMethod">; + let Subjects = SubjectList<[ObjCMethod, FunctionLike]>; // An AST node is created for this attribute, but is not used by other parts // of the compiler. However, this node needs to exist in the AST because // non-LLVM backends may be relying on the attribute's presence. @@ -874,11 +884,13 @@ def C11NoReturn : InheritableAttr { } def CXX11NoReturn : InheritableAttr { - let Spellings = [CXX11<"","noreturn", 200809>]; + let Spellings = [CXX11<"", "noreturn", 200809>]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [CXX11NoReturnDocs]; } +// Similar to CUDA, OpenCL attributes do not receive a [[]] spelling because +// the specification does not expose them with one currently. def OpenCLKernel : InheritableAttr { let Spellings = [Keyword<"__kernel">, Keyword<"kernel">]; let Subjects = SubjectList<[Function], ErrorDiag>; @@ -904,8 +916,7 @@ def OpenCLAccess : Attr { let Spellings = [Keyword<"__read_only">, Keyword<"read_only">, Keyword<"__write_only">, Keyword<"write_only">, Keyword<"__read_write">, Keyword<"read_write">]; - let Subjects = SubjectList<[ParmVar, TypedefName], ErrorDiag, - "ExpectedParameterOrTypedef">; + let Subjects = SubjectList<[ParmVar, TypedefName], ErrorDiag>; let Accessors = [Accessor<"isReadOnly", [Keyword<"__read_only">, Keyword<"read_only">]>, Accessor<"isReadWrite", [Keyword<"__read_write">, @@ -957,7 +968,7 @@ def RenderScriptKernel : Attr { def Deprecated : InheritableAttr { let Spellings = [GCC<"deprecated">, Declspec<"deprecated">, - CXX11<"","deprecated", 201309>]; + CXX11<"","deprecated", 201309>, C2x<"", "deprecated">]; let Args = [StringArgument<"Message", 1>, // An optional string argument that enables us to provide a // Fix-It. @@ -988,6 +999,9 @@ def AllocSize : InheritableAttr { } def EnableIf : InheritableAttr { + // Does not have a [[]] spelling because this attribute requires the ability + // to parse function arguments but the attribute is not written in the type + // position. let Spellings = [GNU<"enable_if">]; let Subjects = SubjectList<[Function]>; let Args = [ExprArgument<"Cond">, StringArgument<"Message">]; @@ -996,6 +1010,7 @@ def EnableIf : InheritableAttr { } def ExtVectorType : Attr { + // This is an OpenCL-related attribute and does not receive a [[]] spelling. let Spellings = [GNU<"ext_vector_type">]; let Subjects = SubjectList<[TypedefName], ErrorDiag>; let Args = [ExprArgument<"NumElements">]; @@ -1004,7 +1019,7 @@ def ExtVectorType : Attr { } def FallThrough : StmtAttr { - let Spellings = [CXX11<"", "fallthrough", 201603>, + let Spellings = [CXX11<"", "fallthrough", 201603>, C2x<"", "fallthrough">, CXX11<"clang", "fallthrough">]; // let Subjects = [NullStmt]; let Documentation = [FallthroughDocs]; @@ -1030,20 +1045,19 @@ def Final : InheritableAttr { } def MinSize : InheritableAttr { - let Spellings = [GNU<"minsize">]; + let Spellings = [Clang<"minsize">]; let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>; let Documentation = [Undocumented]; } def FlagEnum : InheritableAttr { - let Spellings = [GNU<"flag_enum">]; + let Spellings = [Clang<"flag_enum">]; let Subjects = SubjectList<[Enum]>; let Documentation = [FlagEnumDocs]; } def EnumExtensibility : InheritableAttr { - let Spellings = [GNU<"enum_extensibility">, - CXX11<"clang", "enum_extensibility">]; + let Spellings = [Clang<"enum_extensibility">]; let Subjects = SubjectList<[Enum]>; let Args = [EnumArgument<"Extensibility", "Kind", ["closed", "open"], ["Closed", "Open"]>]; @@ -1060,16 +1074,14 @@ def Format : InheritableAttr { let Spellings = [GCC<"format">]; let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">, IntArgument<"FirstArg">]; - let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag, - "ExpectedFunctionWithProtoType">; + let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto]>; let Documentation = [FormatDocs]; } def FormatArg : InheritableAttr { let Spellings = [GCC<"format_arg">]; let Args = [IntArgument<"FormatIdx">]; - let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag, - "ExpectedFunctionWithProtoType">; + let Subjects = SubjectList<[ObjCMethod, HasFunctionProto]>; let Documentation = [Undocumented]; } @@ -1088,9 +1100,8 @@ def Hot : InheritableAttr { } def IBAction : InheritableAttr { - let Spellings = [GNU<"ibaction">]; - let Subjects = SubjectList<[ObjCInstanceMethod], WarnDiag, - "ExpectedObjCInstanceMethod">; + let Spellings = [Clang<"ibaction">]; + let Subjects = SubjectList<[ObjCInstanceMethod]>; // An AST node is created for this attribute, but is not used by other parts // of the compiler. However, this node needs to exist in the AST because // external tools rely on it. @@ -1098,13 +1109,13 @@ def IBAction : InheritableAttr { } def IBOutlet : InheritableAttr { - let Spellings = [GNU<"iboutlet">]; + let Spellings = [Clang<"iboutlet">]; // let Subjects = [ObjCIvar, ObjCProperty]; let Documentation = [Undocumented]; } def IBOutletCollection : InheritableAttr { - let Spellings = [GNU<"iboutletcollection">]; + let Spellings = [Clang<"iboutletcollection">]; let Args = [TypeArgument<"Interface", 1>]; // let Subjects = [ObjCIvar, ObjCProperty]; let Documentation = [Undocumented]; @@ -1153,23 +1164,23 @@ def MSABI : InheritableAttr { def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> { // NOTE: If you add any additional spellings, ARMInterrupt's, MipsInterrupt's // and AnyX86Interrupt's spellings must match. - let Spellings = [GNU<"interrupt">]; + let Spellings = [GCC<"interrupt">]; let Args = [UnsignedArgument<"Number">]; let ParseKind = "Interrupt"; let HasCustomParsing = 1; let Documentation = [Undocumented]; } -def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> { +def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> { let Spellings = [GCC<"mips16">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; } -def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> { +def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips32> { // NOTE: If you add any additional spellings, ARMInterrupt's, // MSP430Interrupt's and AnyX86Interrupt's spellings must match. - let Spellings = [GNU<"interrupt">]; + let Spellings = [GCC<"interrupt">]; let Subjects = SubjectList<[Function]>; let Args = [EnumArgument<"Interrupt", "InterruptType", ["vector=sw0", "vector=sw1", "vector=hw0", @@ -1182,16 +1193,27 @@ def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> { let Documentation = [MipsInterruptDocs]; } -def MicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> { +def MicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> { let Spellings = [GCC<"micromips">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [MicroMipsDocs]; } +def MipsLongCall : InheritableAttr, TargetSpecificAttr<TargetAnyMips> { + let Spellings = [GCC<"long_call">, GCC<"far">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [MipsLongCallStyleDocs]; +} + +def MipsShortCall : InheritableAttr, TargetSpecificAttr<TargetAnyMips> { + let Spellings = [GCC<"short_call">, GCC<"near">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [MipsShortCallStyleDocs]; +} + def Mode : Attr { let Spellings = [GCC<"mode">]; - let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag, - "ExpectedVariableEnumFieldOrTypedef">; + let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag>; let Args = [IdentifierArgument<"Mode">]; let Documentation = [Undocumented]; } @@ -1203,13 +1225,13 @@ def Naked : InheritableAttr { } def NeonPolyVectorType : TypeAttr { - let Spellings = [GNU<"neon_polyvector_type">]; + let Spellings = [Clang<"neon_polyvector_type">]; let Args = [IntArgument<"NumElements">]; let Documentation = [Undocumented]; } def NeonVectorType : TypeAttr { - let Spellings = [GNU<"neon_vector_type">]; + let Spellings = [Clang<"neon_vector_type">]; let Args = [IntArgument<"NumElements">]; let Documentation = [Undocumented]; } @@ -1221,8 +1243,7 @@ def ReturnsTwice : InheritableAttr { } def DisableTailCalls : InheritableAttr { - let Spellings = [GNU<"disable_tail_calls">, - CXX11<"clang", "disable_tail_calls">]; + let Spellings = [Clang<"disable_tail_calls">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let Documentation = [DisableTailCallsDocs]; } @@ -1241,19 +1262,18 @@ def NoCommon : InheritableAttr { def NoDebug : InheritableAttr { let Spellings = [GCC<"nodebug">]; - let Subjects = SubjectList<[FunctionLike, ObjCMethod, NonParmVar], WarnDiag, - "ExpectedVariableOrFunction">; + let Subjects = SubjectList<[FunctionLike, ObjCMethod, NonParmVar]>; let Documentation = [NoDebugDocs]; } def NoDuplicate : InheritableAttr { - let Spellings = [GNU<"noduplicate">, CXX11<"clang", "noduplicate">]; + let Spellings = [Clang<"noduplicate">]; let Subjects = SubjectList<[Function]>; let Documentation = [NoDuplicateDocs]; } def Convergent : InheritableAttr { - let Spellings = [GNU<"convergent">, CXX11<"clang", "convergent">]; + let Spellings = [Clang<"convergent">]; let Subjects = SubjectList<[Function]>; let Documentation = [ConvergentDocs]; } @@ -1264,13 +1284,13 @@ def NoInline : InheritableAttr { let Documentation = [Undocumented]; } -def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> { +def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips32> { let Spellings = [GCC<"nomips16">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; } -def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> { +def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> { let Spellings = [GCC<"nomicromips">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [MicroMipsDocs]; @@ -1294,31 +1314,31 @@ def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips> { // this should be rejected on non-kernels. def AMDGPUFlatWorkGroupSize : InheritableAttr { - let Spellings = [GNU<"amdgpu_flat_work_group_size">]; + let Spellings = [Clang<"amdgpu_flat_work_group_size">]; let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max">]; let Documentation = [AMDGPUFlatWorkGroupSizeDocs]; - let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } def AMDGPUWavesPerEU : InheritableAttr { - let Spellings = [GNU<"amdgpu_waves_per_eu">]; + let Spellings = [Clang<"amdgpu_waves_per_eu">]; let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max", 1>]; let Documentation = [AMDGPUWavesPerEUDocs]; - let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } def AMDGPUNumSGPR : InheritableAttr { - let Spellings = [GNU<"amdgpu_num_sgpr">]; + let Spellings = [Clang<"amdgpu_num_sgpr">]; let Args = [UnsignedArgument<"NumSGPR">]; let Documentation = [AMDGPUNumSGPRNumVGPRDocs]; - let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } def AMDGPUNumVGPR : InheritableAttr { - let Spellings = [GNU<"amdgpu_num_vgpr">]; + let Spellings = [Clang<"amdgpu_num_vgpr">]; let Args = [UnsignedArgument<"NumVGPR">]; let Documentation = [AMDGPUNumSGPRNumVGPRDocs]; - let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">; + let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } def NoSplitStack : InheritableAttr { @@ -1330,7 +1350,7 @@ def NoSplitStack : InheritableAttr { def NonNull : InheritableParamAttr { let Spellings = [GCC<"nonnull">]; let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag, - "ExpectedFunctionMethodOrParameter">; + "functions, methods, and parameters">; let Args = [VariadicUnsignedArgument<"Args">]; let AdditionalMembers = [{bool isNonNull(unsigned idx) const { @@ -1348,15 +1368,14 @@ def NonNull : InheritableParamAttr { def ReturnsNonNull : InheritableAttr { let Spellings = [GCC<"returns_nonnull">]; - let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag, - "ExpectedFunctionOrMethod">; + let Subjects = SubjectList<[ObjCMethod, Function]>; let Documentation = [ReturnsNonNullDocs]; } // pass_object_size(N) indicates that the parameter should have // __builtin_object_size with Type=N evaluated on the parameter at the callsite. def PassObjectSize : InheritableParamAttr { - let Spellings = [GNU<"pass_object_size">]; + let Spellings = [Clang<"pass_object_size">]; let Args = [IntArgument<"Type">]; let Subjects = SubjectList<[ParmVar]>; let Documentation = [PassObjectSizeDocs]; @@ -1383,6 +1402,12 @@ def ObjCKindOf : TypeAttr { let Documentation = [Undocumented]; } +def NoEscape : Attr { + let Spellings = [Clang<"noescape">]; + let Subjects = SubjectList<[ParmVar]>; + let Documentation = [NoEscapeDocs]; +} + def AssumeAligned : InheritableAttr { let Spellings = [GCC<"assume_aligned">]; let Subjects = SubjectList<[ObjCMethod, Function]>; @@ -1392,8 +1417,7 @@ def AssumeAligned : InheritableAttr { def AllocAlign : InheritableAttr { let Spellings = [GCC<"alloc_align">]; - let Subjects = SubjectList<[HasFunctionProto], WarnDiag, - "ExpectedFunctionWithProtoType">; + let Subjects = SubjectList<[HasFunctionProto]>; let Args = [IntArgument<"ParamIndex">]; let Documentation = [AllocAlignDocs]; } @@ -1411,39 +1435,42 @@ def NoInstrumentFunction : InheritableAttr { } def NotTailCalled : InheritableAttr { - let Spellings = [GNU<"not_tail_called">, CXX11<"clang", "not_tail_called">]; + let Spellings = [Clang<"not_tail_called">]; let Subjects = SubjectList<[Function]>; let Documentation = [NotTailCalledDocs]; } def NoThrow : InheritableAttr { let Spellings = [GCC<"nothrow">, Declspec<"nothrow">]; - let Documentation = [Undocumented]; + let Subjects = SubjectList<[Function]>; + let Documentation = [NoThrowDocs]; } def NvWeak : IgnoredAttr { // No Declspec spelling of this attribute; the CUDA headers use - // __attribute__((nv_weak)) unconditionally. + // __attribute__((nv_weak)) unconditionally. Does not receive an [[]] + // spelling because it is a CUDA attribute. let Spellings = [GNU<"nv_weak">]; let LangOpts = [CUDA]; } def ObjCBridge : InheritableAttr { - let Spellings = [GNU<"objc_bridge">]; - let Subjects = SubjectList<[Record, TypedefName], ErrorDiag, - "ExpectedStructOrUnionOrTypedef">; + let Spellings = [Clang<"objc_bridge">]; + let Subjects = SubjectList<[Record, TypedefName], ErrorDiag>; let Args = [IdentifierArgument<"BridgedType">]; let Documentation = [Undocumented]; } def ObjCBridgeMutable : InheritableAttr { - let Spellings = [GNU<"objc_bridge_mutable">]; + let Spellings = [Clang<"objc_bridge_mutable">]; let Subjects = SubjectList<[Record], ErrorDiag>; let Args = [IdentifierArgument<"BridgedType">]; let Documentation = [Undocumented]; } def ObjCBridgeRelated : InheritableAttr { + // TODO: this attribute does not have a [[]] spelling because it requires + // custom parsing support. let Spellings = [GNU<"objc_bridge_related">]; let Subjects = SubjectList<[Record], ErrorDiag>; let Args = [IdentifierArgument<"RelatedClass">, @@ -1454,43 +1481,43 @@ def ObjCBridgeRelated : InheritableAttr { } def NSReturnsRetained : InheritableAttr { - let Spellings = [GNU<"ns_returns_retained">]; + let Spellings = [Clang<"ns_returns_retained">]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def NSReturnsNotRetained : InheritableAttr { - let Spellings = [GNU<"ns_returns_not_retained">]; + let Spellings = [Clang<"ns_returns_not_retained">]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def NSReturnsAutoreleased : InheritableAttr { - let Spellings = [GNU<"ns_returns_autoreleased">]; + let Spellings = [Clang<"ns_returns_autoreleased">]; // let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>; let Documentation = [Undocumented]; } def NSConsumesSelf : InheritableAttr { - let Spellings = [GNU<"ns_consumes_self">]; + let Spellings = [Clang<"ns_consumes_self">]; let Subjects = SubjectList<[ObjCMethod]>; let Documentation = [Undocumented]; } def NSConsumed : InheritableParamAttr { - let Spellings = [GNU<"ns_consumed">]; + let Spellings = [Clang<"ns_consumed">]; let Subjects = SubjectList<[ParmVar]>; let Documentation = [Undocumented]; } def ObjCException : InheritableAttr { - let Spellings = [GNU<"objc_exception">]; + let Spellings = [Clang<"objc_exception">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCMethodFamily : InheritableAttr { - let Spellings = [GNU<"objc_method_family">]; + let Spellings = [Clang<"objc_method_family">]; let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Args = [EnumArgument<"Family", "FamilyKind", ["none", "alloc", "copy", "init", "mutableCopy", "new"], @@ -1500,85 +1527,84 @@ def ObjCMethodFamily : InheritableAttr { } def ObjCNSObject : InheritableAttr { - let Spellings = [GNU<"NSObject">]; + let Spellings = [Clang<"NSObject">]; let Documentation = [Undocumented]; } def ObjCIndependentClass : InheritableAttr { - let Spellings = [GNU<"objc_independent_class">]; + let Spellings = [Clang<"objc_independent_class">]; let Documentation = [Undocumented]; } def ObjCPreciseLifetime : InheritableAttr { - let Spellings = [GNU<"objc_precise_lifetime">]; + let Spellings = [Clang<"objc_precise_lifetime">]; let Subjects = SubjectList<[Var], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCReturnsInnerPointer : InheritableAttr { - let Spellings = [GNU<"objc_returns_inner_pointer">]; + let Spellings = [Clang<"objc_returns_inner_pointer">]; let Subjects = SubjectList<[ObjCMethod, ObjCProperty], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCRequiresSuper : InheritableAttr { - let Spellings = [GNU<"objc_requires_super">]; + let Spellings = [Clang<"objc_requires_super">]; let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Documentation = [ObjCRequiresSuperDocs]; } def ObjCRootClass : InheritableAttr { - let Spellings = [GNU<"objc_root_class">]; + let Spellings = [Clang<"objc_root_class">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCSubclassingRestricted : InheritableAttr { - let Spellings = [GNU<"objc_subclassing_restricted">]; + let Spellings = [Clang<"objc_subclassing_restricted">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [ObjCSubclassingRestrictedDocs]; } def ObjCExplicitProtocolImpl : InheritableAttr { - let Spellings = [GNU<"objc_protocol_requires_explicit_implementation">]; + let Spellings = [Clang<"objc_protocol_requires_explicit_implementation">]; let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCDesignatedInitializer : Attr { - let Spellings = [GNU<"objc_designated_initializer">]; - let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag, - "ExpectedObjCInterfaceDeclInitMethod">; + let Spellings = [Clang<"objc_designated_initializer">]; + let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCRuntimeName : Attr { - let Spellings = [GNU<"objc_runtime_name">]; + let Spellings = [Clang<"objc_runtime_name">]; let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag>; let Args = [StringArgument<"MetadataName">]; let Documentation = [ObjCRuntimeNameDocs]; } def ObjCRuntimeVisible : Attr { - let Spellings = [GNU<"objc_runtime_visible">]; + let Spellings = [Clang<"objc_runtime_visible">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [ObjCRuntimeVisibleDocs]; } def ObjCBoxable : Attr { - let Spellings = [GNU<"objc_boxable">]; - let Subjects = SubjectList<[Record], ErrorDiag, "ExpectedStructOrUnion">; + let Spellings = [Clang<"objc_boxable">]; + let Subjects = SubjectList<[Record], ErrorDiag>; let Documentation = [ObjCBoxableDocs]; } def OptimizeNone : InheritableAttr { - let Spellings = [GNU<"optnone">, CXX11<"clang", "optnone">]; + let Spellings = [Clang<"optnone">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let Documentation = [OptnoneDocs]; } def Overloadable : Attr { - let Spellings = [GNU<"overloadable">]; + let Spellings = [Clang<"overloadable">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [OverloadableDocs]; } @@ -1590,11 +1616,11 @@ def Override : InheritableAttr { } def Ownership : InheritableAttr { - let Spellings = [GNU<"ownership_holds">, GNU<"ownership_returns">, - GNU<"ownership_takes">]; - let Accessors = [Accessor<"isHolds", [GNU<"ownership_holds">]>, - Accessor<"isReturns", [GNU<"ownership_returns">]>, - Accessor<"isTakes", [GNU<"ownership_takes">]>]; + let Spellings = [Clang<"ownership_holds">, Clang<"ownership_returns">, + Clang<"ownership_takes">]; + let Accessors = [Accessor<"isHolds", [Clang<"ownership_holds">]>, + Accessor<"isReturns", [Clang<"ownership_returns">]>, + Accessor<"isTakes", [Clang<"ownership_takes">]>]; let AdditionalMembers = [{ enum OwnershipKind { Holds, Returns, Takes }; OwnershipKind getOwnKind() const { @@ -1604,8 +1630,7 @@ def Ownership : InheritableAttr { } }]; let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">]; - let Subjects = SubjectList<[HasFunctionProto], WarnDiag, - "ExpectedFunctionWithProtoType">; + let Subjects = SubjectList<[HasFunctionProto]>; let Documentation = [Undocumented]; } @@ -1616,7 +1641,7 @@ def Packed : InheritableAttr { } def IntelOclBicc : InheritableAttr { - let Spellings = [GNU<"intel_ocl_bicc">]; + let Spellings = [Clang<"intel_ocl_bicc">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; } @@ -1642,6 +1667,7 @@ def Regparm : TypeAttr { } def ReqdWorkGroupSize : InheritableAttr { + // Does not have a [[]] spelling because it is an OpenCL-related attribute. let Spellings = [GNU<"reqd_work_group_size">]; let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">, UnsignedArgument<"ZDim">]; @@ -1650,15 +1676,14 @@ def ReqdWorkGroupSize : InheritableAttr { } def RequireConstantInit : InheritableAttr { - let Spellings = [GNU<"require_constant_initialization">, - CXX11<"clang", "require_constant_initialization">]; - let Subjects = SubjectList<[GlobalVar], ErrorDiag, - "ExpectedStaticOrTLSVar">; + let Spellings = [Clang<"require_constant_initialization">]; + let Subjects = SubjectList<[GlobalVar], ErrorDiag>; let Documentation = [RequireConstantInitDocs]; let LangOpts = [CPlusPlus]; } def WorkGroupSizeHint : InheritableAttr { + // Does not have a [[]] spelling because it is an OpenCL-related attribute. let Spellings = [GNU<"work_group_size_hint">]; let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">, @@ -1668,7 +1693,7 @@ def WorkGroupSizeHint : InheritableAttr { } def InitPriority : InheritableAttr { - let Spellings = [GNU<"init_priority">]; + let Spellings = [GCC<"init_priority">]; let Args = [UnsignedArgument<"Priority">]; let Subjects = SubjectList<[Var], ErrorDiag>; let Documentation = [Undocumented]; @@ -1677,9 +1702,8 @@ def InitPriority : InheritableAttr { def Section : InheritableAttr { let Spellings = [GCC<"section">, Declspec<"allocate">]; let Args = [StringArgument<"Name">]; - let Subjects = SubjectList<[Function, GlobalVar, - ObjCMethod, ObjCProperty], ErrorDiag, - "ExpectedFunctionGlobalVarMethodOrProperty">; + let Subjects = + SubjectList<[ Function, GlobalVar, ObjCMethod, ObjCProperty ], ErrorDiag>; let Documentation = [SectionDocs]; } @@ -1687,8 +1711,7 @@ def PragmaClangBSSSection : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; let Args = [StringArgument<"Name">]; - let Subjects = SubjectList<[GlobalVar], ErrorDiag, - "ExpectedFunctionMethodOrGlobalVar">; + let Subjects = SubjectList<[GlobalVar], ErrorDiag>; let Documentation = [Undocumented]; } @@ -1696,8 +1719,7 @@ def PragmaClangDataSection : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; let Args = [StringArgument<"Name">]; - let Subjects = SubjectList<[GlobalVar], ErrorDiag, - "ExpectedFunctionMethodOrGlobalVar">; + let Subjects = SubjectList<[GlobalVar], ErrorDiag>; let Documentation = [Undocumented]; } @@ -1705,8 +1727,7 @@ def PragmaClangRodataSection : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; let Args = [StringArgument<"Name">]; - let Subjects = SubjectList<[GlobalVar], ErrorDiag, - "ExpectedFunctionMethodOrGlobalVar">; + let Subjects = SubjectList<[GlobalVar], ErrorDiag>; let Documentation = [Undocumented]; } @@ -1714,8 +1735,7 @@ def PragmaClangTextSection : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; let Args = [StringArgument<"Name">]; - let Subjects = SubjectList<[Function], ErrorDiag, - "ExpectedFunctionMethodOrGlobalVar">; + let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; } @@ -1734,23 +1754,23 @@ def StdCall : InheritableAttr { } def SwiftCall : InheritableAttr { - let Spellings = [GCC<"swiftcall">]; + let Spellings = [Clang<"swiftcall">]; // let Subjects = SubjectList<[Function]>; let Documentation = [SwiftCallDocs]; } def SwiftContext : ParameterABIAttr { - let Spellings = [GCC<"swift_context">]; + let Spellings = [Clang<"swift_context">]; let Documentation = [SwiftContextDocs]; } def SwiftErrorResult : ParameterABIAttr { - let Spellings = [GCC<"swift_error_result">]; + let Spellings = [Clang<"swift_error_result">]; let Documentation = [SwiftErrorResultDocs]; } def SwiftIndirectResult : ParameterABIAttr { - let Spellings = [GCC<"swift_indirect_result">]; + let Spellings = [Clang<"swift_indirect_result">]; let Documentation = [SwiftIndirectResultDocs]; } @@ -1774,25 +1794,25 @@ def ThisCall : InheritableAttr { } def VectorCall : InheritableAttr { - let Spellings = [GNU<"vectorcall">, Keyword<"__vectorcall">, + let Spellings = [Clang<"vectorcall">, Keyword<"__vectorcall">, Keyword<"_vectorcall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [VectorCallDocs]; } def Pascal : InheritableAttr { - let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">]; + let Spellings = [Clang<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; } def PreserveMost : InheritableAttr { - let Spellings = [GNU<"preserve_most">]; + let Spellings = [Clang<"preserve_most">]; let Documentation = [PreserveMostDocs]; } def PreserveAll : InheritableAttr { - let Spellings = [GNU<"preserve_all">]; + let Spellings = [Clang<"preserve_all">]; let Documentation = [PreserveAllDocs]; } @@ -1853,7 +1873,7 @@ def TransparentUnion : InheritableAttr { } def Unavailable : InheritableAttr { - let Spellings = [GNU<"unavailable">]; + let Spellings = [Clang<"unavailable">]; let Args = [StringArgument<"Message", 1>, EnumArgument<"ImplicitReason", "ImplicitReason", ["", "", "", ""], @@ -1867,6 +1887,9 @@ def Unavailable : InheritableAttr { } def DiagnoseIf : InheritableAttr { + // Does not have a [[]] spelling because this attribute requires the ability + // to parse function arguments but the attribute is not written in the type + // position. let Spellings = [GNU<"diagnose_if">]; let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>; let Args = [ExprArgument<"Cond">, StringArgument<"Message">, @@ -1887,35 +1910,35 @@ def DiagnoseIf : InheritableAttr { } def ArcWeakrefUnavailable : InheritableAttr { - let Spellings = [GNU<"objc_arc_weak_reference_unavailable">]; + let Spellings = [Clang<"objc_arc_weak_reference_unavailable">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } def ObjCGC : TypeAttr { - let Spellings = [GNU<"objc_gc">]; + let Spellings = [Clang<"objc_gc">]; let Args = [IdentifierArgument<"Kind">]; let Documentation = [Undocumented]; } def ObjCOwnership : InheritableAttr { - let Spellings = [GNU<"objc_ownership">]; + let Spellings = [Clang<"objc_ownership">]; let Args = [IdentifierArgument<"Kind">]; let ASTNode = 0; let Documentation = [Undocumented]; } def ObjCRequiresPropertyDefs : InheritableAttr { - let Spellings = [GNU<"objc_requires_property_definitions">]; + let Spellings = [Clang<"objc_requires_property_definitions">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; } def Unused : InheritableAttr { - let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">]; + let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">, + C2x<"", "maybe_unused">]; let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label, - Field, ObjCMethod, FunctionLike], WarnDiag, - "ExpectedForMaybeUnused">; + Field, ObjCMethod, FunctionLike]>; let Documentation = [WarnMaybeUnusedDocs]; } @@ -1927,7 +1950,7 @@ def Used : InheritableAttr { def Uuid : InheritableAttr { let Spellings = [Declspec<"uuid">, Microsoft<"uuid">]; let Args = [StringArgument<"Guid">]; - let Subjects = SubjectList<[Record, Enum], WarnDiag, "ExpectedEnumOrClass">; + let Subjects = SubjectList<[Record, Enum]>; // FIXME: Allow expressing logical AND for LangOpts. Our condition should be: // CPlusPlus && (MicrosoftExt || Borland) let LangOpts = [MicrosoftExt, Borland]; @@ -1941,6 +1964,7 @@ def VectorSize : TypeAttr { } def VecTypeHint : InheritableAttr { + // Does not have a [[]] spelling because it is an OpenCL-related attribute. let Spellings = [GNU<"vec_type_hint">]; let Args = [TypeArgument<"TypeHint">]; let Subjects = SubjectList<[Function], ErrorDiag>; @@ -1959,7 +1983,7 @@ def Visibility : InheritableAttr { def TypeVisibility : InheritableAttr { let Clone = 0; - let Spellings = [GNU<"type_visibility">, CXX11<"clang", "type_visibility">]; + let Spellings = [Clang<"type_visibility">]; let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; @@ -1968,23 +1992,22 @@ def TypeVisibility : InheritableAttr { } def VecReturn : InheritableAttr { - let Spellings = [GNU<"vecreturn">]; + let Spellings = [Clang<"vecreturn">]; let Subjects = SubjectList<[CXXRecord], ErrorDiag>; let Documentation = [Undocumented]; } def WarnUnused : InheritableAttr { - let Spellings = [GNU<"warn_unused">]; + let Spellings = [GCC<"warn_unused">]; let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; } def WarnUnusedResult : InheritableAttr { - let Spellings = [CXX11<"", "nodiscard", 201603>, + let Spellings = [CXX11<"", "nodiscard", 201603>, C2x<"", "nodiscard">, CXX11<"clang", "warn_unused_result">, GCC<"warn_unused_result">]; - let Subjects = SubjectList<[ObjCMethod, Enum, CXXRecord, FunctionLike], - WarnDiag, "ExpectedFunctionMethodEnumOrClass">; + let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike]>; let Documentation = [WarnUnusedResultsDocs]; } @@ -1995,7 +2018,7 @@ def Weak : InheritableAttr { } def WeakImport : InheritableAttr { - let Spellings = [GNU<"weak_import">]; + let Spellings = [Clang<"weak_import">]; let Documentation = [Undocumented]; } @@ -2008,7 +2031,7 @@ def WeakRef : InheritableAttr { } def LTOVisibilityPublic : InheritableAttr { - let Spellings = [CXX11<"clang", "lto_visibility_public">]; + let Spellings = [Clang<"lto_visibility_public">]; let Subjects = SubjectList<[Record]>; let Documentation = [LTOVisibilityDocs]; } @@ -2016,11 +2039,11 @@ def LTOVisibilityPublic : InheritableAttr { def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> { // NOTE: If you add any additional spellings, ARMInterrupt's, // MSP430Interrupt's and MipsInterrupt's spellings must match. - let Spellings = [GNU<"interrupt">]; + let Spellings = [GCC<"interrupt">]; let Subjects = SubjectList<[HasFunctionProto]>; let ParseKind = "Interrupt"; let HasCustomParsing = 1; - let Documentation = [AnyX86InterruptDocs]; + let Documentation = [Undocumented]; } def AnyX86NoCallerSavedRegisters : InheritableAttr, @@ -2029,19 +2052,18 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr, let Documentation = [AnyX86NoCallerSavedRegistersDocs]; } -def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> { - let Spellings = [GNU<"force_align_arg_pointer">]; +def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetAnyX86> { + let Spellings = [GCC<"force_align_arg_pointer">]; // Technically, this appertains to a FunctionDecl, but the target-specific // code silently allows anything function-like (such as typedefs or function // pointers), but does not apply the attribute to them. - let Documentation = [Undocumented]; + let Documentation = [X86ForceAlignArgPointerDocs]; } def NoSanitize : InheritableAttr { - let Spellings = [GNU<"no_sanitize">, CXX11<"clang", "no_sanitize">]; + let Spellings = [Clang<"no_sanitize">]; let Args = [VariadicStringArgument<"Sanitizers">]; - let Subjects = SubjectList<[Function, ObjCMethod, GlobalVar], ErrorDiag, - "ExpectedFunctionMethodOrGlobalVar">; + let Subjects = SubjectList<[Function, ObjCMethod, GlobalVar], ErrorDiag>; let Documentation = [NoSanitizeDocs]; let AdditionalMembers = [{ SanitizerMask getMask() const { @@ -2062,27 +2084,28 @@ def NoSanitizeSpecific : InheritableAttr { let Spellings = [GCC<"no_address_safety_analysis">, GCC<"no_sanitize_address">, GCC<"no_sanitize_thread">, - GNU<"no_sanitize_memory">]; - let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag, - "ExpectedFunctionOrGlobalVar">; + Clang<"no_sanitize_memory">]; + let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag>; let Documentation = [NoSanitizeAddressDocs, NoSanitizeThreadDocs, NoSanitizeMemoryDocs]; let ASTNode = 0; } // C/C++ Thread safety attributes (e.g. for deadlock, data race checking) - +// Not all of these attributes will be given a [[]] spelling. The attributes +// which require access to function parameter names cannot use the [[]] spelling +// because they are not written in the type position. Some attributes are given +// an updated captability-based name and the older name will only be supported +// under the GNU-style spelling. def GuardedVar : InheritableAttr { - let Spellings = [GNU<"guarded_var">]; - let Subjects = SubjectList<[Field, SharedVar], WarnDiag, - "ExpectedFieldOrGlobalVar">; + let Spellings = [Clang<"guarded_var">]; + let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } def PtGuardedVar : InheritableAttr { - let Spellings = [GNU<"pt_guarded_var">]; - let Subjects = SubjectList<[Field, SharedVar], WarnDiag, - "ExpectedFieldOrGlobalVar">; + let Spellings = [Clang<"pt_guarded_var">]; + let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2094,21 +2117,17 @@ def Lockable : InheritableAttr { } def ScopedLockable : InheritableAttr { - let Spellings = [GNU<"scoped_lockable">]; + let Spellings = [Clang<"scoped_lockable">]; let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; } def Capability : InheritableAttr { - let Spellings = [GNU<"capability">, CXX11<"clang", "capability">, - GNU<"shared_capability">, - CXX11<"clang", "shared_capability">]; - let Subjects = SubjectList<[Record, TypedefName], ErrorDiag, - "ExpectedStructOrUnionOrTypedef">; + let Spellings = [Clang<"capability">, Clang<"shared_capability">]; + let Subjects = SubjectList<[Record, TypedefName], ErrorDiag>; let Args = [StringArgument<"Name">]; let Accessors = [Accessor<"isShared", - [GNU<"shared_capability">, - CXX11<"clang","shared_capability">]>]; + [Clang<"shared_capability">]>]; let Documentation = [Undocumented]; let AdditionalMembers = [{ bool isMutex() const { return getName().equals_lower("mutex"); } @@ -2117,27 +2136,22 @@ def Capability : InheritableAttr { } def AssertCapability : InheritableAttr { - let Spellings = [GNU<"assert_capability">, - CXX11<"clang", "assert_capability">, - GNU<"assert_shared_capability">, - CXX11<"clang", "assert_shared_capability">]; + let Spellings = [Clang<"assert_capability">, + Clang<"assert_shared_capability">]; let Subjects = SubjectList<[Function]>; let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let DuplicatesAllowedWhileMerging = 1; - let Args = [ExprArgument<"Expr">]; + let Args = [VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [GNU<"assert_shared_capability">, - CXX11<"clang", "assert_shared_capability">]>]; + [Clang<"assert_shared_capability">]>]; let Documentation = [AssertCapabilityDocs]; } def AcquireCapability : InheritableAttr { - let Spellings = [GNU<"acquire_capability">, - CXX11<"clang", "acquire_capability">, - GNU<"acquire_shared_capability">, - CXX11<"clang", "acquire_shared_capability">, + let Spellings = [Clang<"acquire_capability">, + Clang<"acquire_shared_capability">, GNU<"exclusive_lock_function">, GNU<"shared_lock_function">]; let Subjects = SubjectList<[Function]>; @@ -2147,17 +2161,14 @@ def AcquireCapability : InheritableAttr { let DuplicatesAllowedWhileMerging = 1; let Args = [VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [GNU<"acquire_shared_capability">, - CXX11<"clang", "acquire_shared_capability">, + [Clang<"acquire_shared_capability">, GNU<"shared_lock_function">]>]; let Documentation = [AcquireCapabilityDocs]; } def TryAcquireCapability : InheritableAttr { - let Spellings = [GNU<"try_acquire_capability">, - CXX11<"clang", "try_acquire_capability">, - GNU<"try_acquire_shared_capability">, - CXX11<"clang", "try_acquire_shared_capability">]; + let Spellings = [Clang<"try_acquire_capability">, + Clang<"try_acquire_shared_capability">]; let Subjects = SubjectList<[Function], ErrorDiag>; let LateParsed = 1; @@ -2166,19 +2177,15 @@ def TryAcquireCapability : InheritableAttr { let DuplicatesAllowedWhileMerging = 1; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [GNU<"try_acquire_shared_capability">, - CXX11<"clang", "try_acquire_shared_capability">]>]; + [Clang<"try_acquire_shared_capability">]>]; let Documentation = [TryAcquireCapabilityDocs]; } def ReleaseCapability : InheritableAttr { - let Spellings = [GNU<"release_capability">, - CXX11<"clang", "release_capability">, - GNU<"release_shared_capability">, - CXX11<"clang", "release_shared_capability">, - GNU<"release_generic_capability">, - CXX11<"clang", "release_generic_capability">, - GNU<"unlock_function">]; + let Spellings = [Clang<"release_capability">, + Clang<"release_shared_capability">, + Clang<"release_generic_capability">, + Clang<"unlock_function">]; let Subjects = SubjectList<[Function]>; let LateParsed = 1; let TemplateDependent = 1; @@ -2186,36 +2193,31 @@ def ReleaseCapability : InheritableAttr { let DuplicatesAllowedWhileMerging = 1; let Args = [VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [GNU<"release_shared_capability">, - CXX11<"clang", "release_shared_capability">]>, + [Clang<"release_shared_capability">]>, Accessor<"isGeneric", - [GNU<"release_generic_capability">, - CXX11<"clang", "release_generic_capability">, - GNU<"unlock_function">]>]; + [Clang<"release_generic_capability">, + Clang<"unlock_function">]>]; let Documentation = [ReleaseCapabilityDocs]; } def RequiresCapability : InheritableAttr { - let Spellings = [GNU<"requires_capability">, - CXX11<"clang", "requires_capability">, - GNU<"exclusive_locks_required">, - GNU<"requires_shared_capability">, - CXX11<"clang", "requires_shared_capability">, - GNU<"shared_locks_required">]; + let Spellings = [Clang<"requires_capability">, + Clang<"exclusive_locks_required">, + Clang<"requires_shared_capability">, + Clang<"shared_locks_required">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let DuplicatesAllowedWhileMerging = 1; let Subjects = SubjectList<[Function]>; - let Accessors = [Accessor<"isShared", [GNU<"requires_shared_capability">, - GNU<"shared_locks_required">, - CXX11<"clang","requires_shared_capability">]>]; + let Accessors = [Accessor<"isShared", [Clang<"requires_shared_capability">, + Clang<"shared_locks_required">]>]; let Documentation = [Undocumented]; } def NoThreadSafetyAnalysis : InheritableAttr { - let Spellings = [GNU<"no_thread_safety_analysis">]; + let Spellings = [Clang<"no_thread_safety_analysis">]; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } @@ -2227,8 +2229,7 @@ def GuardedBy : InheritableAttr { let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let DuplicatesAllowedWhileMerging = 1; - let Subjects = SubjectList<[Field, SharedVar], WarnDiag, - "ExpectedFieldOrGlobalVar">; + let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2239,8 +2240,7 @@ def PtGuardedBy : InheritableAttr { let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let DuplicatesAllowedWhileMerging = 1; - let Subjects = SubjectList<[Field, SharedVar], WarnDiag, - "ExpectedFieldOrGlobalVar">; + let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2251,8 +2251,7 @@ def AcquiredAfter : InheritableAttr { let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let DuplicatesAllowedWhileMerging = 1; - let Subjects = SubjectList<[Field, SharedVar], WarnDiag, - "ExpectedFieldOrGlobalVar">; + let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2263,8 +2262,7 @@ def AcquiredBefore : InheritableAttr { let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; let DuplicatesAllowedWhileMerging = 1; - let Subjects = SubjectList<[Field, SharedVar], WarnDiag, - "ExpectedFieldOrGlobalVar">; + let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2340,7 +2338,7 @@ def LocksExcluded : InheritableAttr { // C/C++ consumed attributes. def Consumable : InheritableAttr { - let Spellings = [GNU<"consumable">]; + let Spellings = [Clang<"consumable">]; let Subjects = SubjectList<[CXXRecord]>; let Args = [EnumArgument<"DefaultState", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2349,19 +2347,19 @@ def Consumable : InheritableAttr { } def ConsumableAutoCast : InheritableAttr { - let Spellings = [GNU<"consumable_auto_cast_state">]; + let Spellings = [Clang<"consumable_auto_cast_state">]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [Undocumented]; } def ConsumableSetOnRead : InheritableAttr { - let Spellings = [GNU<"consumable_set_state_on_read">]; + let Spellings = [Clang<"consumable_set_state_on_read">]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [Undocumented]; } def CallableWhen : InheritableAttr { - let Spellings = [GNU<"callable_when">]; + let Spellings = [Clang<"callable_when">]; let Subjects = SubjectList<[CXXMethod]>; let Args = [VariadicEnumArgument<"CallableStates", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2370,7 +2368,7 @@ def CallableWhen : InheritableAttr { } def ParamTypestate : InheritableAttr { - let Spellings = [GNU<"param_typestate">]; + let Spellings = [Clang<"param_typestate">]; let Subjects = SubjectList<[ParmVar]>; let Args = [EnumArgument<"ParamState", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2379,7 +2377,7 @@ def ParamTypestate : InheritableAttr { } def ReturnTypestate : InheritableAttr { - let Spellings = [GNU<"return_typestate">]; + let Spellings = [Clang<"return_typestate">]; let Subjects = SubjectList<[Function, ParmVar]>; let Args = [EnumArgument<"State", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2388,7 +2386,7 @@ def ReturnTypestate : InheritableAttr { } def SetTypestate : InheritableAttr { - let Spellings = [GNU<"set_typestate">]; + let Spellings = [Clang<"set_typestate">]; let Subjects = SubjectList<[CXXMethod]>; let Args = [EnumArgument<"NewState", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2397,7 +2395,7 @@ def SetTypestate : InheritableAttr { } def TestTypestate : InheritableAttr { - let Spellings = [GNU<"test_typestate">]; + let Spellings = [Clang<"test_typestate">]; let Subjects = SubjectList<[CXXMethod]>; let Args = [EnumArgument<"TestState", "ConsumedState", ["consumed", "unconsumed"], @@ -2673,6 +2671,14 @@ def OMPCaptureNoInit : InheritableAttr { let Documentation = [Undocumented]; } +def OMPCaptureKind : Attr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let SemaHandler = 0; + let Args = [UnsignedArgument<"CaptureKind">]; + let Documentation = [Undocumented]; +} + def OMPDeclareSimdDecl : Attr { let Spellings = [Pragma<"omp", "declare simd">]; let Subjects = SubjectList<[Function]>; @@ -2759,7 +2765,7 @@ def OMPDeclareTargetDecl : Attr { } def InternalLinkage : InheritableAttr { - let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">]; + let Spellings = [Clang<"internal_linkage">]; let Subjects = SubjectList<[Var, Function, CXXRecord]>; let Documentation = [InternalLinkageDocs]; } diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 567c7a3a53b0..ecff329c4ccb 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -7,6 +7,24 @@ // //===---------------------------------------------------------------------===// +// To test that the documentation builds cleanly, you must run clang-tblgen to +// convert the .td file into a .rst file, and then run sphinx to convert the +// .rst file into an HTML file. After completing testing, you should revert the +// generated .rst file so that the modified version does not get checked in to +// version control. +// +// To run clang-tblgen to generate the .rst file: +// clang-tblgen -gen-attr-docs -I <root>/llvm/tools/clang/include +// <root>/llvm/tools/clang/include/clang/Basic/Attr.td -o +// <root>/llvm/tools/clang/docs/AttributeReference.rst +// +// To run sphinx to generate the .html files (note that sphinx-build must be +// available on the PATH): +// Windows (from within the clang\docs directory): +// make.bat html +// Non-Windows (from within the clang\docs directory): +// make -f Makefile.sphinx html + def GlobalDocumentation { code Intro =[{.. ------------------------------------------------------------------- @@ -112,6 +130,50 @@ members, and static locals. }]; } +def NoEscapeDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +``noescape`` placed on a function parameter of a pointer type is used to inform +the compiler that the pointer cannot escape: that is, no reference to the object +the pointer points to that is derived from the parameter value will survive +after the function returns. Users are responsible for making sure parameters +annotated with ``noescape`` do not actuallly escape. + +For example: + +.. code-block:: c + + int *gp; + + void nonescapingFunc(__attribute__((noescape)) int *p) { + *p += 100; // OK. + } + + void escapingFunc(__attribute__((noescape)) int *p) { + gp = p; // Not OK. + } + +Additionally, when the parameter is a `block pointer +<https://clang.llvm.org/docs/BlockLanguageSpec.html>`, the same restriction +applies to copies of the block. For example: + +.. code-block:: c + + typedef void (^BlockTy)(); + BlockTy g0, g1; + + void nonescapingFunc(__attribute__((noescape)) BlockTy block) { + block(); // OK. + } + + void escapingFunc(__attribute__((noescape)) BlockTy block) { + g0 = block; // Not OK. + g1 = Block_copy(block); // Not OK either. + } + + }]; +} + def CarriesDependencyDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -1231,6 +1293,7 @@ Here is an example: def ARMInterruptDocs : Documentation { let Category = DocCatFunction; + let Heading = "interrupt (ARM)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on ARM targets. This attribute may be attached to a function definition and @@ -1272,6 +1335,7 @@ The semantics are as follows: def MipsInterruptDocs : Documentation { let Category = DocCatFunction; + let Heading = "interrupt (MIPS)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on MIPS targets. This attribute may be attached to a function definition and instructs @@ -1323,8 +1387,52 @@ on the command line. }]; } +def MipsLongCallStyleDocs : Documentation { + let Category = DocCatFunction; + let Heading = "long_call (gnu::long_call, gnu::far)"; + let Content = [{ +Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, +and ``__attribute__((near))`` attributes on MIPS targets. These attributes may +only be added to function declarations and change the code generated +by the compiler when directly calling the function. The ``near`` attribute +allows calls to the function to be made using the ``jal`` instruction, which +requires the function to be located in the same naturally aligned 256MB +segment as the caller. The ``long_call`` and ``far`` attributes are synonyms +and require the use of a different call sequence that works regardless +of the distance between the functions. + +These attributes have no effect for position-independent code. + +These attributes take priority over command line switches such +as ``-mlong-calls`` and ``-mno-long-calls``. + }]; +} + +def MipsShortCallStyleDocs : Documentation { + let Category = DocCatFunction; + let Heading = "short_call (gnu::short_call, gnu::near)"; + let Content = [{ +Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, +``__attribute__((short__call))``, and ``__attribute__((near))`` attributes +on MIPS targets. These attributes may only be added to function declarations +and change the code generated by the compiler when directly calling +the function. The ``short_call`` and ``near`` attributes are synonyms and +allow calls to the function to be made using the ``jal`` instruction, which +requires the function to be located in the same naturally aligned 256MB segment +as the caller. The ``long_call`` and ``far`` attributes are synonyms and +require the use of a different call sequence that works regardless +of the distance between the functions. + +These attributes have no effect for position-independent code. + +These attributes take priority over command line switches such +as ``-mlong-calls`` and ``-mno-long-calls``. + }]; +} + def AVRInterruptDocs : Documentation { let Category = DocCatFunction; + let Heading = "interrupt (AVR)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt))`` attribute on AVR targets. This attribute may be attached to a function definition and instructs @@ -2625,6 +2733,18 @@ Marking virtual functions as ``not_tail_called`` is an error: }]; } +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 +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 +guaranteed to not throw an exception. + }]; +} + def InternalLinkageDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -2673,59 +2793,6 @@ Marking virtual functions as ``disable_tail_calls`` is legal. }]; } -def AnyX86InterruptDocs : Documentation { - let Category = DocCatFunction; - let Content = [{ -Clang supports the GNU style ``__attribute__((interrupt))`` attribute on -x86/x86-64 targets.The compiler generates function entry and exit sequences -suitable for use in an interrupt handler when this attribute is present. -The 'IRET' instruction, instead of the 'RET' instruction, is used to return -from interrupt or exception handlers. All registers, except for the EFLAGS -register which is restored by the 'IRET' instruction, are preserved by the -compiler. - -Any interruptible-without-stack-switch code must be compiled with --mno-red-zone since interrupt handlers can and will, because of the -hardware design, touch the red zone. - -1. interrupt handler must be declared with a mandatory pointer argument: - - .. code-block:: c - - struct interrupt_frame - { - uword_t ip; - uword_t cs; - uword_t flags; - uword_t sp; - uword_t ss; - }; - - __attribute__ ((interrupt)) - void f (struct interrupt_frame *frame) { - ... - } - -2. exception handler: - - The exception handler is very similar to the interrupt handler with - a different mandatory function signature: - - .. code-block:: c - - __attribute__ ((interrupt)) - void f (struct interrupt_frame *frame, uword_t error_code) { - ... - } - - and compiler pops 'ERROR_CODE' off stack before the 'IRET' instruction. - - The exception handler should only be used for exceptions which push an - error code and all other exceptions must use the interrupt handler. - The system will crash if the wrong handler is used. - }]; -} - def AnyX86NoCallerSavedRegistersDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -2760,6 +2827,31 @@ For example: }]; } +def X86ForceAlignArgPointerDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Use this attribute to force stack alignment. + +Legacy x86 code uses 4-byte stack alignment. Newer aligned SSE instructions +(like 'movaps') that work with the stack require operands to be 16-byte aligned. +This attribute realigns the stack in the function prologue to make sure the +stack can be used with SSE instructions. + +Note that the x86_64 ABI forces 16-byte stack alignment at the call site. +Because of this, 'force_align_arg_pointer' is not needed on x86_64, except in +rare cases where the caller does not align the stack properly (e.g. flow +jumps from i386 arch code). + + .. code-block:: c + + __attribute__ ((force_align_arg_pointer)) + void f () { + ... + } + + }]; +} + def SwiftCallDocs : Documentation { let Category = DocCatVariable; let Content = [{ diff --git a/include/clang/Basic/Attributes.h b/include/clang/Basic/Attributes.h index ea9e28ae681a..c651abacd482 100644 --- a/include/clang/Basic/Attributes.h +++ b/include/clang/Basic/Attributes.h @@ -26,6 +26,8 @@ enum class AttrSyntax { Microsoft, // Is the identifier known as a C++-style attribute? CXX, + // Is the identifier known as a C-style attribute? + C, // Is the identifier known as a pragma attribute? Pragma }; diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 1ddb9beaf913..3d4deb5ed306 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -103,9 +103,9 @@ #endif // Standard libc/libm functions: -BUILTIN(__builtin_atan2 , "ddd" , "Fnc") -BUILTIN(__builtin_atan2f, "fff" , "Fnc") -BUILTIN(__builtin_atan2l, "LdLdLd", "Fnc") +BUILTIN(__builtin_atan2 , "ddd" , "Fne") +BUILTIN(__builtin_atan2f, "fff" , "Fne") +BUILTIN(__builtin_atan2l, "LdLdLd", "Fne") BUILTIN(__builtin_abs , "ii" , "ncF") BUILTIN(__builtin_copysign, "ddd", "ncF") BUILTIN(__builtin_copysignf, "fff", "ncF") @@ -113,9 +113,9 @@ BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") BUILTIN(__builtin_fabs , "dd" , "ncF") BUILTIN(__builtin_fabsf, "ff" , "ncF") BUILTIN(__builtin_fabsl, "LdLd", "ncF") -BUILTIN(__builtin_fmod , "ddd" , "Fnc") -BUILTIN(__builtin_fmodf, "fff" , "Fnc") -BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc") +BUILTIN(__builtin_fmod , "ddd" , "Fne") +BUILTIN(__builtin_fmodf, "fff" , "Fne") +BUILTIN(__builtin_fmodl, "LdLdLd", "Fne") BUILTIN(__builtin_frexp , "ddi*" , "Fn") BUILTIN(__builtin_frexpf, "ffi*" , "Fn") BUILTIN(__builtin_frexpl, "LdLdi*", "Fn") @@ -127,9 +127,9 @@ BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") BUILTIN(__builtin_labs , "LiLi" , "Fnc") BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") -BUILTIN(__builtin_ldexp , "ddi" , "Fnc") -BUILTIN(__builtin_ldexpf, "ffi" , "Fnc") -BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc") +BUILTIN(__builtin_ldexp , "ddi" , "Fne") +BUILTIN(__builtin_ldexpf, "ffi" , "Fne") +BUILTIN(__builtin_ldexpl, "LdLdi", "Fne") BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") @@ -142,119 +142,119 @@ BUILTIN(__builtin_nansl, "LdcC*", "ncF") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") -BUILTIN(__builtin_pow , "ddd" , "Fnc") -BUILTIN(__builtin_powf, "fff" , "Fnc") -BUILTIN(__builtin_powl, "LdLdLd", "Fnc") +BUILTIN(__builtin_pow , "ddd" , "Fne") +BUILTIN(__builtin_powf, "fff" , "Fne") +BUILTIN(__builtin_powl, "LdLdLd", "Fne") // Standard unary libc/libm functions with double/float/long double variants: -BUILTIN(__builtin_acos , "dd" , "Fnc") -BUILTIN(__builtin_acosf, "ff" , "Fnc") -BUILTIN(__builtin_acosl, "LdLd", "Fnc") -BUILTIN(__builtin_acosh , "dd" , "Fnc") -BUILTIN(__builtin_acoshf, "ff" , "Fnc") -BUILTIN(__builtin_acoshl, "LdLd", "Fnc") -BUILTIN(__builtin_asin , "dd" , "Fnc") -BUILTIN(__builtin_asinf, "ff" , "Fnc") -BUILTIN(__builtin_asinl, "LdLd", "Fnc") -BUILTIN(__builtin_asinh , "dd" , "Fnc") -BUILTIN(__builtin_asinhf, "ff" , "Fnc") -BUILTIN(__builtin_asinhl, "LdLd", "Fnc") -BUILTIN(__builtin_atan , "dd" , "Fnc") -BUILTIN(__builtin_atanf, "ff" , "Fnc") -BUILTIN(__builtin_atanl, "LdLd", "Fnc") -BUILTIN(__builtin_atanh , "dd", "Fnc") -BUILTIN(__builtin_atanhf, "ff", "Fnc") -BUILTIN(__builtin_atanhl, "LdLd", "Fnc") +BUILTIN(__builtin_acos , "dd" , "Fne") +BUILTIN(__builtin_acosf, "ff" , "Fne") +BUILTIN(__builtin_acosl, "LdLd", "Fne") +BUILTIN(__builtin_acosh , "dd" , "Fne") +BUILTIN(__builtin_acoshf, "ff" , "Fne") +BUILTIN(__builtin_acoshl, "LdLd", "Fne") +BUILTIN(__builtin_asin , "dd" , "Fne") +BUILTIN(__builtin_asinf, "ff" , "Fne") +BUILTIN(__builtin_asinl, "LdLd", "Fne") +BUILTIN(__builtin_asinh , "dd" , "Fne") +BUILTIN(__builtin_asinhf, "ff" , "Fne") +BUILTIN(__builtin_asinhl, "LdLd", "Fne") +BUILTIN(__builtin_atan , "dd" , "Fne") +BUILTIN(__builtin_atanf, "ff" , "Fne") +BUILTIN(__builtin_atanl, "LdLd", "Fne") +BUILTIN(__builtin_atanh , "dd", "Fne") +BUILTIN(__builtin_atanhf, "ff", "Fne") +BUILTIN(__builtin_atanhl, "LdLd", "Fne") BUILTIN(__builtin_cbrt , "dd", "Fnc") BUILTIN(__builtin_cbrtf, "ff", "Fnc") BUILTIN(__builtin_cbrtl, "LdLd", "Fnc") BUILTIN(__builtin_ceil , "dd" , "Fnc") BUILTIN(__builtin_ceilf, "ff" , "Fnc") BUILTIN(__builtin_ceill, "LdLd", "Fnc") -BUILTIN(__builtin_cos , "dd" , "Fnc") -BUILTIN(__builtin_cosf, "ff" , "Fnc") -BUILTIN(__builtin_cosh , "dd" , "Fnc") -BUILTIN(__builtin_coshf, "ff" , "Fnc") -BUILTIN(__builtin_coshl, "LdLd", "Fnc") -BUILTIN(__builtin_cosl, "LdLd", "Fnc") -BUILTIN(__builtin_erf , "dd", "Fnc") -BUILTIN(__builtin_erff, "ff", "Fnc") -BUILTIN(__builtin_erfl, "LdLd", "Fnc") -BUILTIN(__builtin_erfc , "dd", "Fnc") -BUILTIN(__builtin_erfcf, "ff", "Fnc") -BUILTIN(__builtin_erfcl, "LdLd", "Fnc") -BUILTIN(__builtin_exp , "dd" , "Fnc") -BUILTIN(__builtin_expf, "ff" , "Fnc") -BUILTIN(__builtin_expl, "LdLd", "Fnc") -BUILTIN(__builtin_exp2 , "dd" , "Fnc") -BUILTIN(__builtin_exp2f, "ff" , "Fnc") -BUILTIN(__builtin_exp2l, "LdLd", "Fnc") -BUILTIN(__builtin_expm1 , "dd", "Fnc") -BUILTIN(__builtin_expm1f, "ff", "Fnc") -BUILTIN(__builtin_expm1l, "LdLd", "Fnc") -BUILTIN(__builtin_fdim, "ddd", "Fnc") -BUILTIN(__builtin_fdimf, "fff", "Fnc") -BUILTIN(__builtin_fdiml, "LdLdLd", "Fnc") +BUILTIN(__builtin_cos , "dd" , "Fne") +BUILTIN(__builtin_cosf, "ff" , "Fne") +BUILTIN(__builtin_cosh , "dd" , "Fne") +BUILTIN(__builtin_coshf, "ff" , "Fne") +BUILTIN(__builtin_coshl, "LdLd", "Fne") +BUILTIN(__builtin_cosl, "LdLd", "Fne") +BUILTIN(__builtin_erf , "dd", "Fne") +BUILTIN(__builtin_erff, "ff", "Fne") +BUILTIN(__builtin_erfl, "LdLd", "Fne") +BUILTIN(__builtin_erfc , "dd", "Fne") +BUILTIN(__builtin_erfcf, "ff", "Fne") +BUILTIN(__builtin_erfcl, "LdLd", "Fne") +BUILTIN(__builtin_exp , "dd" , "Fne") +BUILTIN(__builtin_expf, "ff" , "Fne") +BUILTIN(__builtin_expl, "LdLd", "Fne") +BUILTIN(__builtin_exp2 , "dd" , "Fne") +BUILTIN(__builtin_exp2f, "ff" , "Fne") +BUILTIN(__builtin_exp2l, "LdLd", "Fne") +BUILTIN(__builtin_expm1 , "dd", "Fne") +BUILTIN(__builtin_expm1f, "ff", "Fne") +BUILTIN(__builtin_expm1l, "LdLd", "Fne") +BUILTIN(__builtin_fdim, "ddd", "Fne") +BUILTIN(__builtin_fdimf, "fff", "Fne") +BUILTIN(__builtin_fdiml, "LdLdLd", "Fne") BUILTIN(__builtin_floor , "dd" , "Fnc") BUILTIN(__builtin_floorf, "ff" , "Fnc") BUILTIN(__builtin_floorl, "LdLd", "Fnc") -BUILTIN(__builtin_fma, "dddd", "Fnc") -BUILTIN(__builtin_fmaf, "ffff", "Fnc") -BUILTIN(__builtin_fmal, "LdLdLdLd", "Fnc") +BUILTIN(__builtin_fma, "dddd", "Fne") +BUILTIN(__builtin_fmaf, "ffff", "Fne") +BUILTIN(__builtin_fmal, "LdLdLdLd", "Fne") BUILTIN(__builtin_fmax, "ddd", "Fnc") BUILTIN(__builtin_fmaxf, "fff", "Fnc") BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc") BUILTIN(__builtin_fmin, "ddd", "Fnc") BUILTIN(__builtin_fminf, "fff", "Fnc") BUILTIN(__builtin_fminl, "LdLdLd", "Fnc") -BUILTIN(__builtin_hypot , "ddd" , "Fnc") -BUILTIN(__builtin_hypotf, "fff" , "Fnc") -BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc") -BUILTIN(__builtin_ilogb , "id", "Fnc") -BUILTIN(__builtin_ilogbf, "if", "Fnc") -BUILTIN(__builtin_ilogbl, "iLd", "Fnc") -BUILTIN(__builtin_lgamma , "dd", "Fnc") -BUILTIN(__builtin_lgammaf, "ff", "Fnc") -BUILTIN(__builtin_lgammal, "LdLd", "Fnc") -BUILTIN(__builtin_llrint, "LLid", "Fnc") -BUILTIN(__builtin_llrintf, "LLif", "Fnc") -BUILTIN(__builtin_llrintl, "LLiLd", "Fnc") -BUILTIN(__builtin_llround , "LLid", "Fnc") -BUILTIN(__builtin_llroundf, "LLif", "Fnc") -BUILTIN(__builtin_llroundl, "LLiLd", "Fnc") -BUILTIN(__builtin_log , "dd" , "Fnc") -BUILTIN(__builtin_log10 , "dd" , "Fnc") -BUILTIN(__builtin_log10f, "ff" , "Fnc") -BUILTIN(__builtin_log10l, "LdLd", "Fnc") -BUILTIN(__builtin_log1p , "dd" , "Fnc") -BUILTIN(__builtin_log1pf, "ff" , "Fnc") -BUILTIN(__builtin_log1pl, "LdLd", "Fnc") -BUILTIN(__builtin_log2, "dd" , "Fnc") -BUILTIN(__builtin_log2f, "ff" , "Fnc") -BUILTIN(__builtin_log2l, "LdLd" , "Fnc") -BUILTIN(__builtin_logb , "dd", "Fnc") -BUILTIN(__builtin_logbf, "ff", "Fnc") -BUILTIN(__builtin_logbl, "LdLd", "Fnc") -BUILTIN(__builtin_logf, "ff" , "Fnc") -BUILTIN(__builtin_logl, "LdLd", "Fnc") -BUILTIN(__builtin_lrint , "Lid", "Fnc") -BUILTIN(__builtin_lrintf, "Lif", "Fnc") -BUILTIN(__builtin_lrintl, "LiLd", "Fnc") -BUILTIN(__builtin_lround , "Lid", "Fnc") -BUILTIN(__builtin_lroundf, "Lif", "Fnc") -BUILTIN(__builtin_lroundl, "LiLd", "Fnc") +BUILTIN(__builtin_hypot , "ddd" , "Fne") +BUILTIN(__builtin_hypotf, "fff" , "Fne") +BUILTIN(__builtin_hypotl, "LdLdLd", "Fne") +BUILTIN(__builtin_ilogb , "id", "Fne") +BUILTIN(__builtin_ilogbf, "if", "Fne") +BUILTIN(__builtin_ilogbl, "iLd", "Fne") +BUILTIN(__builtin_lgamma , "dd", "Fn") +BUILTIN(__builtin_lgammaf, "ff", "Fn") +BUILTIN(__builtin_lgammal, "LdLd", "Fn") +BUILTIN(__builtin_llrint, "LLid", "Fne") +BUILTIN(__builtin_llrintf, "LLif", "Fne") +BUILTIN(__builtin_llrintl, "LLiLd", "Fne") +BUILTIN(__builtin_llround , "LLid", "Fne") +BUILTIN(__builtin_llroundf, "LLif", "Fne") +BUILTIN(__builtin_llroundl, "LLiLd", "Fne") +BUILTIN(__builtin_log , "dd" , "Fne") +BUILTIN(__builtin_log10 , "dd" , "Fne") +BUILTIN(__builtin_log10f, "ff" , "Fne") +BUILTIN(__builtin_log10l, "LdLd", "Fne") +BUILTIN(__builtin_log1p , "dd" , "Fne") +BUILTIN(__builtin_log1pf, "ff" , "Fne") +BUILTIN(__builtin_log1pl, "LdLd", "Fne") +BUILTIN(__builtin_log2, "dd" , "Fne") +BUILTIN(__builtin_log2f, "ff" , "Fne") +BUILTIN(__builtin_log2l, "LdLd" , "Fne") +BUILTIN(__builtin_logb , "dd", "Fne") +BUILTIN(__builtin_logbf, "ff", "Fne") +BUILTIN(__builtin_logbl, "LdLd", "Fne") +BUILTIN(__builtin_logf, "ff" , "Fne") +BUILTIN(__builtin_logl, "LdLd", "Fne") +BUILTIN(__builtin_lrint , "Lid", "Fne") +BUILTIN(__builtin_lrintf, "Lif", "Fne") +BUILTIN(__builtin_lrintl, "LiLd", "Fne") +BUILTIN(__builtin_lround , "Lid", "Fne") +BUILTIN(__builtin_lroundf, "Lif", "Fne") +BUILTIN(__builtin_lroundl, "LiLd", "Fne") BUILTIN(__builtin_nearbyint , "dd", "Fnc") BUILTIN(__builtin_nearbyintf, "ff", "Fnc") BUILTIN(__builtin_nearbyintl, "LdLd", "Fnc") -BUILTIN(__builtin_nextafter , "ddd", "Fnc") -BUILTIN(__builtin_nextafterf, "fff", "Fnc") -BUILTIN(__builtin_nextafterl, "LdLdLd", "Fnc") -BUILTIN(__builtin_nexttoward , "ddLd", "Fnc") -BUILTIN(__builtin_nexttowardf, "ffLd", "Fnc") -BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fnc") -BUILTIN(__builtin_remainder , "ddd", "Fnc") -BUILTIN(__builtin_remainderf, "fff", "Fnc") -BUILTIN(__builtin_remainderl, "LdLdLd", "Fnc") +BUILTIN(__builtin_nextafter , "ddd", "Fne") +BUILTIN(__builtin_nextafterf, "fff", "Fne") +BUILTIN(__builtin_nextafterl, "LdLdLd", "Fne") +BUILTIN(__builtin_nexttoward , "ddLd", "Fne") +BUILTIN(__builtin_nexttowardf, "ffLd", "Fne") +BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fne") +BUILTIN(__builtin_remainder , "ddd", "Fne") +BUILTIN(__builtin_remainderf, "fff", "Fne") +BUILTIN(__builtin_remainderl, "LdLdLd", "Fne") BUILTIN(__builtin_remquo , "dddi*", "Fn") BUILTIN(__builtin_remquof, "fffi*", "Fn") BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn") @@ -264,101 +264,101 @@ BUILTIN(__builtin_rintl, "LdLd", "Fnc") BUILTIN(__builtin_round, "dd" , "Fnc") BUILTIN(__builtin_roundf, "ff" , "Fnc") BUILTIN(__builtin_roundl, "LdLd" , "Fnc") -BUILTIN(__builtin_scalbln , "ddLi", "Fnc") -BUILTIN(__builtin_scalblnf, "ffLi", "Fnc") -BUILTIN(__builtin_scalblnl, "LdLdLi", "Fnc") -BUILTIN(__builtin_scalbn , "ddi", "Fnc") -BUILTIN(__builtin_scalbnf, "ffi", "Fnc") -BUILTIN(__builtin_scalbnl, "LdLdi", "Fnc") -BUILTIN(__builtin_sin , "dd" , "Fnc") -BUILTIN(__builtin_sinf, "ff" , "Fnc") -BUILTIN(__builtin_sinh , "dd" , "Fnc") -BUILTIN(__builtin_sinhf, "ff" , "Fnc") -BUILTIN(__builtin_sinhl, "LdLd", "Fnc") -BUILTIN(__builtin_sinl, "LdLd", "Fnc") -BUILTIN(__builtin_sqrt , "dd" , "Fnc") -BUILTIN(__builtin_sqrtf, "ff" , "Fnc") -BUILTIN(__builtin_sqrtl, "LdLd", "Fnc") -BUILTIN(__builtin_tan , "dd" , "Fnc") -BUILTIN(__builtin_tanf, "ff" , "Fnc") -BUILTIN(__builtin_tanh , "dd" , "Fnc") -BUILTIN(__builtin_tanhf, "ff" , "Fnc") -BUILTIN(__builtin_tanhl, "LdLd", "Fnc") -BUILTIN(__builtin_tanl, "LdLd", "Fnc") -BUILTIN(__builtin_tgamma , "dd", "Fnc") -BUILTIN(__builtin_tgammaf, "ff", "Fnc") -BUILTIN(__builtin_tgammal, "LdLd", "Fnc") +BUILTIN(__builtin_scalbln , "ddLi", "Fne") +BUILTIN(__builtin_scalblnf, "ffLi", "Fne") +BUILTIN(__builtin_scalblnl, "LdLdLi", "Fne") +BUILTIN(__builtin_scalbn , "ddi", "Fne") +BUILTIN(__builtin_scalbnf, "ffi", "Fne") +BUILTIN(__builtin_scalbnl, "LdLdi", "Fne") +BUILTIN(__builtin_sin , "dd" , "Fne") +BUILTIN(__builtin_sinf, "ff" , "Fne") +BUILTIN(__builtin_sinh , "dd" , "Fne") +BUILTIN(__builtin_sinhf, "ff" , "Fne") +BUILTIN(__builtin_sinhl, "LdLd", "Fne") +BUILTIN(__builtin_sinl, "LdLd", "Fne") +BUILTIN(__builtin_sqrt , "dd" , "Fne") +BUILTIN(__builtin_sqrtf, "ff" , "Fne") +BUILTIN(__builtin_sqrtl, "LdLd", "Fne") +BUILTIN(__builtin_tan , "dd" , "Fne") +BUILTIN(__builtin_tanf, "ff" , "Fne") +BUILTIN(__builtin_tanh , "dd" , "Fne") +BUILTIN(__builtin_tanhf, "ff" , "Fne") +BUILTIN(__builtin_tanhl, "LdLd", "Fne") +BUILTIN(__builtin_tanl, "LdLd", "Fne") +BUILTIN(__builtin_tgamma , "dd", "Fne") +BUILTIN(__builtin_tgammaf, "ff", "Fne") +BUILTIN(__builtin_tgammal, "LdLd", "Fne") BUILTIN(__builtin_trunc , "dd", "Fnc") BUILTIN(__builtin_truncf, "ff", "Fnc") BUILTIN(__builtin_truncl, "LdLd", "Fnc") // C99 complex builtins -BUILTIN(__builtin_cabs, "dXd", "Fnc") -BUILTIN(__builtin_cabsf, "fXf", "Fnc") -BUILTIN(__builtin_cabsl, "LdXLd", "Fnc") -BUILTIN(__builtin_cacos, "XdXd", "Fnc") -BUILTIN(__builtin_cacosf, "XfXf", "Fnc") -BUILTIN(__builtin_cacosh, "XdXd", "Fnc") -BUILTIN(__builtin_cacoshf, "XfXf", "Fnc") -BUILTIN(__builtin_cacoshl, "XLdXLd", "Fnc") -BUILTIN(__builtin_cacosl, "XLdXLd", "Fnc") -BUILTIN(__builtin_carg, "dXd", "Fnc") -BUILTIN(__builtin_cargf, "fXf", "Fnc") -BUILTIN(__builtin_cargl, "LdXLd", "Fnc") -BUILTIN(__builtin_casin, "XdXd", "Fnc") -BUILTIN(__builtin_casinf, "XfXf", "Fnc") -BUILTIN(__builtin_casinh, "XdXd", "Fnc") -BUILTIN(__builtin_casinhf, "XfXf", "Fnc") -BUILTIN(__builtin_casinhl, "XLdXLd", "Fnc") -BUILTIN(__builtin_casinl, "XLdXLd", "Fnc") -BUILTIN(__builtin_catan, "XdXd", "Fnc") -BUILTIN(__builtin_catanf, "XfXf", "Fnc") -BUILTIN(__builtin_catanh, "XdXd", "Fnc") -BUILTIN(__builtin_catanhf, "XfXf", "Fnc") -BUILTIN(__builtin_catanhl, "XLdXLd", "Fnc") -BUILTIN(__builtin_catanl, "XLdXLd", "Fnc") -BUILTIN(__builtin_ccos, "XdXd", "Fnc") -BUILTIN(__builtin_ccosf, "XfXf", "Fnc") -BUILTIN(__builtin_ccosl, "XLdXLd", "Fnc") -BUILTIN(__builtin_ccosh, "XdXd", "Fnc") -BUILTIN(__builtin_ccoshf, "XfXf", "Fnc") -BUILTIN(__builtin_ccoshl, "XLdXLd", "Fnc") -BUILTIN(__builtin_cexp, "XdXd", "Fnc") -BUILTIN(__builtin_cexpf, "XfXf", "Fnc") -BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc") +BUILTIN(__builtin_cabs, "dXd", "Fne") +BUILTIN(__builtin_cabsf, "fXf", "Fne") +BUILTIN(__builtin_cabsl, "LdXLd", "Fne") +BUILTIN(__builtin_cacos, "XdXd", "Fne") +BUILTIN(__builtin_cacosf, "XfXf", "Fne") +BUILTIN(__builtin_cacosh, "XdXd", "Fne") +BUILTIN(__builtin_cacoshf, "XfXf", "Fne") +BUILTIN(__builtin_cacoshl, "XLdXLd", "Fne") +BUILTIN(__builtin_cacosl, "XLdXLd", "Fne") +BUILTIN(__builtin_carg, "dXd", "Fne") +BUILTIN(__builtin_cargf, "fXf", "Fne") +BUILTIN(__builtin_cargl, "LdXLd", "Fne") +BUILTIN(__builtin_casin, "XdXd", "Fne") +BUILTIN(__builtin_casinf, "XfXf", "Fne") +BUILTIN(__builtin_casinh, "XdXd", "Fne") +BUILTIN(__builtin_casinhf, "XfXf", "Fne") +BUILTIN(__builtin_casinhl, "XLdXLd", "Fne") +BUILTIN(__builtin_casinl, "XLdXLd", "Fne") +BUILTIN(__builtin_catan, "XdXd", "Fne") +BUILTIN(__builtin_catanf, "XfXf", "Fne") +BUILTIN(__builtin_catanh, "XdXd", "Fne") +BUILTIN(__builtin_catanhf, "XfXf", "Fne") +BUILTIN(__builtin_catanhl, "XLdXLd", "Fne") +BUILTIN(__builtin_catanl, "XLdXLd", "Fne") +BUILTIN(__builtin_ccos, "XdXd", "Fne") +BUILTIN(__builtin_ccosf, "XfXf", "Fne") +BUILTIN(__builtin_ccosl, "XLdXLd", "Fne") +BUILTIN(__builtin_ccosh, "XdXd", "Fne") +BUILTIN(__builtin_ccoshf, "XfXf", "Fne") +BUILTIN(__builtin_ccoshl, "XLdXLd", "Fne") +BUILTIN(__builtin_cexp, "XdXd", "Fne") +BUILTIN(__builtin_cexpf, "XfXf", "Fne") +BUILTIN(__builtin_cexpl, "XLdXLd", "Fne") BUILTIN(__builtin_cimag, "dXd", "Fnc") BUILTIN(__builtin_cimagf, "fXf", "Fnc") BUILTIN(__builtin_cimagl, "LdXLd", "Fnc") BUILTIN(__builtin_conj, "XdXd", "Fnc") BUILTIN(__builtin_conjf, "XfXf", "Fnc") BUILTIN(__builtin_conjl, "XLdXLd", "Fnc") -BUILTIN(__builtin_clog, "XdXd", "Fnc") -BUILTIN(__builtin_clogf, "XfXf", "Fnc") -BUILTIN(__builtin_clogl, "XLdXLd", "Fnc") +BUILTIN(__builtin_clog, "XdXd", "Fne") +BUILTIN(__builtin_clogf, "XfXf", "Fne") +BUILTIN(__builtin_clogl, "XLdXLd", "Fne") BUILTIN(__builtin_cproj, "XdXd", "Fnc") BUILTIN(__builtin_cprojf, "XfXf", "Fnc") BUILTIN(__builtin_cprojl, "XLdXLd", "Fnc") -BUILTIN(__builtin_cpow, "XdXdXd", "Fnc") -BUILTIN(__builtin_cpowf, "XfXfXf", "Fnc") -BUILTIN(__builtin_cpowl, "XLdXLdXLd", "Fnc") +BUILTIN(__builtin_cpow, "XdXdXd", "Fne") +BUILTIN(__builtin_cpowf, "XfXfXf", "Fne") +BUILTIN(__builtin_cpowl, "XLdXLdXLd", "Fne") BUILTIN(__builtin_creal, "dXd", "Fnc") BUILTIN(__builtin_crealf, "fXf", "Fnc") BUILTIN(__builtin_creall, "LdXLd", "Fnc") -BUILTIN(__builtin_csin, "XdXd", "Fnc") -BUILTIN(__builtin_csinf, "XfXf", "Fnc") -BUILTIN(__builtin_csinl, "XLdXLd", "Fnc") -BUILTIN(__builtin_csinh, "XdXd", "Fnc") -BUILTIN(__builtin_csinhf, "XfXf", "Fnc") -BUILTIN(__builtin_csinhl, "XLdXLd", "Fnc") -BUILTIN(__builtin_csqrt, "XdXd", "Fnc") -BUILTIN(__builtin_csqrtf, "XfXf", "Fnc") -BUILTIN(__builtin_csqrtl, "XLdXLd", "Fnc") -BUILTIN(__builtin_ctan, "XdXd", "Fnc") -BUILTIN(__builtin_ctanf, "XfXf", "Fnc") -BUILTIN(__builtin_ctanl, "XLdXLd", "Fnc") -BUILTIN(__builtin_ctanh, "XdXd", "Fnc") -BUILTIN(__builtin_ctanhf, "XfXf", "Fnc") -BUILTIN(__builtin_ctanhl, "XLdXLd", "Fnc") +BUILTIN(__builtin_csin, "XdXd", "Fne") +BUILTIN(__builtin_csinf, "XfXf", "Fne") +BUILTIN(__builtin_csinl, "XLdXLd", "Fne") +BUILTIN(__builtin_csinh, "XdXd", "Fne") +BUILTIN(__builtin_csinhf, "XfXf", "Fne") +BUILTIN(__builtin_csinhl, "XLdXLd", "Fne") +BUILTIN(__builtin_csqrt, "XdXd", "Fne") +BUILTIN(__builtin_csqrtf, "XfXf", "Fne") +BUILTIN(__builtin_csqrtl, "XLdXLd", "Fne") +BUILTIN(__builtin_ctan, "XdXd", "Fne") +BUILTIN(__builtin_ctanf, "XfXf", "Fne") +BUILTIN(__builtin_ctanl, "XLdXLd", "Fne") +BUILTIN(__builtin_ctanh, "XdXd", "Fne") +BUILTIN(__builtin_ctanhf, "XfXf", "Fne") +BUILTIN(__builtin_ctanhl, "XLdXLd", "Fne") // FP Comparisons. BUILTIN(__builtin_isgreater , "i.", "Fnc") @@ -700,6 +700,21 @@ BUILTIN(__atomic_signal_fence, "vi", "n") BUILTIN(__atomic_always_lock_free, "izvCD*", "n") BUILTIN(__atomic_is_lock_free, "izvCD*", "n") +// OpenCL 2.0 atomic builtins. +ATOMIC_BUILTIN(__opencl_atomic_init, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_load, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_store, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_exchange, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_compare_exchange_strong, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_compare_exchange_weak, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_fetch_add, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_fetch_sub, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_fetch_and, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_fetch_or, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_fetch_xor, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_fetch_min, "v.", "t") +ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t") + #undef ATOMIC_BUILTIN // Non-overloaded atomic builtins. @@ -717,6 +732,7 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn") // Microsoft builtins. These are only active with -fms-extensions. LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES) LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES) @@ -992,9 +1008,9 @@ LIBBUILTIN(modf, "ddd*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(modff, "fff*", "fn", "math.h", ALL_LANGUAGES) LIBBUILTIN(modfl, "LdLdLd*", "fn", "math.h", ALL_LANGUAGES) -LIBBUILTIN(nan, "dcC*", "fnc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(nanf, "fcC*", "fnc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(nanl, "LdcC*", "fnc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nan, "dcC*", "fUn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nanf, "fcC*", "fUn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(nanl, "LdcC*", "fUn", "math.h", ALL_LANGUAGES) LIBBUILTIN(pow, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(powf, "fff", "fne", "math.h", ALL_LANGUAGES) @@ -1024,9 +1040,9 @@ LIBBUILTIN(atanh, "dd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atanhf, "ff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(atanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES) -LIBBUILTIN(cbrt, "dd", "fne", "math.h", ALL_LANGUAGES) -LIBBUILTIN(cbrtf, "ff", "fne", "math.h", ALL_LANGUAGES) -LIBBUILTIN(cbrtl, "LdLd", "fne", "math.h", ALL_LANGUAGES) +LIBBUILTIN(cbrt, "dd", "fnc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(cbrtf, "ff", "fnc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(cbrtl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(ceil, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(ceilf, "ff", "fnc", "math.h", ALL_LANGUAGES) @@ -1146,6 +1162,10 @@ LIBBUILTIN(remainder, "ddd", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(remainderf, "fff", "fne", "math.h", ALL_LANGUAGES) LIBBUILTIN(remainderl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES) +LIBBUILTIN(remquo, "dddi*", "fn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(remquof, "fffi*", "fn", "math.h", ALL_LANGUAGES) +LIBBUILTIN(remquol, "LdLdLdi*", "fn", "math.h", ALL_LANGUAGES) + LIBBUILTIN(rint, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(rintf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(rintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) @@ -1190,49 +1210,49 @@ LIBBUILTIN(trunc, "dd", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(truncf, "ff", "fnc", "math.h", ALL_LANGUAGES) LIBBUILTIN(truncl, "LdLd", "fnc", "math.h", ALL_LANGUAGES) -LIBBUILTIN(cabs, "dXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cabsf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cabsl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cabs, "dXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cabsf, "fXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cabsl, "LdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cacos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cacosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cacosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cacos, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cacosf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cacosl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cacosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cacoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cacoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cacosh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cacoshf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cacoshl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(carg, "dXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cargf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cargl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(carg, "dXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cargf, "fXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cargl, "LdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(casin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(casinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(casinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(casin, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(casinf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(casinl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(casinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(casinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(casinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(casinh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(casinhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(casinhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(catan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(catanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(catanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(catan, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(catanf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(catanl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(catanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(catanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(catanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(catanh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(catanhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(catanhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ccos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ccosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ccosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ccos, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ccosf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ccosl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ccosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ccoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ccoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ccosh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ccoshf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ccoshl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cexp, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cexpf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cexpl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cexp, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cexpf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cexpl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cimag, "dXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cimagf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) @@ -1242,41 +1262,41 @@ LIBBUILTIN(conj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(conjf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(conjl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(clog, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(clogf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(clogl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(clog, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(clogf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(clogl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cproj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cprojf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(cprojl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cpow, "XdXdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cpowf, "XfXfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(cpowl, "XLdXLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cpow, "XdXdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cpowf, "XfXfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(cpowl, "XLdXLdXLd", "fne", "complex.h", ALL_LANGUAGES) LIBBUILTIN(creal, "dXd", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(crealf, "fXf", "fnc", "complex.h", ALL_LANGUAGES) LIBBUILTIN(creall, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csin, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csinf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csinl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csinh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csinhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csinhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csqrt, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csqrtf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(csqrtl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csqrt, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csqrtf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(csqrtl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ctan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ctanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ctanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ctan, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ctanf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ctanl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ctanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ctanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES) -LIBBUILTIN(ctanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ctanh, "XdXd", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ctanhf, "XfXf", "fne", "complex.h", ALL_LANGUAGES) +LIBBUILTIN(ctanhl, "XLdXLd", "fne", "complex.h", ALL_LANGUAGES) // __sinpi and friends are OS X specific library functions, but otherwise much // like the standard (non-complex) sin (etc). @@ -1398,18 +1418,29 @@ LANGBUILTIN(get_pipe_max_packets, "Ui.", "tn", OCLC20_LANG) // OpenCL v2.0 s6.13.17 - Enqueue kernel functions. // Custom builtin check allows to perform special check of passed block arguments. LANGBUILTIN(enqueue_kernel, "i.", "tn", OCLC20_LANG) -LANGBUILTIN(get_kernel_work_group_size, "i.", "tn", OCLC20_LANG) -LANGBUILTIN(get_kernel_preferred_work_group_size_multiple, "i.", "tn", OCLC20_LANG) +LANGBUILTIN(get_kernel_work_group_size, "Ui.", "tn", OCLC20_LANG) +LANGBUILTIN(get_kernel_preferred_work_group_size_multiple, "Ui.", "tn", OCLC20_LANG) +LANGBUILTIN(get_kernel_max_sub_group_size_for_ndrange, "Ui.", "tn", OCLC20_LANG) +LANGBUILTIN(get_kernel_sub_group_count_for_ndrange, "Ui.", "tn", OCLC20_LANG) // OpenCL v2.0 s6.13.9 - Address space qualifier functions. LANGBUILTIN(to_global, "v*v*", "tn", OCLC20_LANG) LANGBUILTIN(to_local, "v*v*", "tn", OCLC20_LANG) LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG) +// OpenCL half load/store builtin +LANGBUILTIN(__builtin_store_half, "vdh*", "n", ALL_OCLC_LANGUAGES) +LANGBUILTIN(__builtin_store_halff, "vfh*", "n", ALL_OCLC_LANGUAGES) +LANGBUILTIN(__builtin_load_half, "dhC*", "nc", ALL_OCLC_LANGUAGES) +LANGBUILTIN(__builtin_load_halff, "fhC*", "nc", ALL_OCLC_LANGUAGES) + // Builtins for os_log/os_trace BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut") BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") +// OpenMP 4.0 +LANGBUILTIN(omp_is_initial_device, "i", "nc", OMP_LANG) + // Builtins for XRay BUILTIN(__xray_customevent, "vcC*z", "") diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 87c1f93eedef..963c72ea82e0 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -36,10 +36,13 @@ enum LanguageID { CXX_LANG = 0x4, // builtin for cplusplus only. OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ MS_LANG = 0x10, // builtin requires MS mode. - OCLC20_LANG = 0x20, // builtin for OpenCL C only. + OCLC20_LANG = 0x20, // builtin for OpenCL C 2.0 only. + OCLC1X_LANG = 0x40, // builtin for OpenCL C 1.x only. + OMP_LANG = 0x80, // builtin requires OpenMP. ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. - ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. + ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG, // builtin requires MS mode. + ALL_OCLC_LANGUAGES = OCLC1X_LANG | OCLC20_LANG // builtin for OCLC languages. }; namespace Builtin { diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def index 1db4c1471029..55a4f70176d0 100644 --- a/include/clang/Basic/BuiltinsAArch64.def +++ b/include/clang/Basic/BuiltinsAArch64.def @@ -14,6 +14,10 @@ // The format of this database matches clang/Basic/Builtins.def. +#if defined(BUILTIN) && !defined(LANGBUILTIN) +# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) +#endif + // In libgcc BUILTIN(__clear_cache, "vv*v*", "i") @@ -61,4 +65,9 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc") BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) + #undef BUILTIN +#undef LANGBUILTIN diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def index 6542acafe48a..ec6a0fb91765 100644 --- a/include/clang/Basic/BuiltinsAMDGPU.def +++ b/include/clang/Basic/BuiltinsAMDGPU.def @@ -21,6 +21,7 @@ // 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") @@ -120,6 +121,8 @@ TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts") // Special builtins. //===----------------------------------------------------------------------===// BUILTIN(__builtin_amdgcn_read_exec, "LUi", "nc") +BUILTIN(__builtin_amdgcn_read_exec_lo, "Ui", "nc") +BUILTIN(__builtin_amdgcn_read_exec_hi, "Ui", "nc") //===----------------------------------------------------------------------===// // R600-NI only builtins. diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def index 4e277f8a5a6b..941d320d729f 100644 --- a/include/clang/Basic/BuiltinsARM.def +++ b/include/clang/Basic/BuiltinsARM.def @@ -36,6 +36,7 @@ BUILTIN(__builtin_arm_smulwt, "iii", "nc") // Saturating arithmetic BUILTIN(__builtin_arm_qadd, "iii", "nc") BUILTIN(__builtin_arm_qsub, "iii", "nc") +BUILTIN(__builtin_arm_qdbl, "ii", "nc") BUILTIN(__builtin_arm_ssat, "iiUi", "nc") BUILTIN(__builtin_arm_usat, "UiiUi", "nc") diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def index 14fc4adc25bc..fda50b53589b 100644 --- a/include/clang/Basic/BuiltinsHexagon.def +++ b/include/clang/Basic/BuiltinsHexagon.def @@ -17,7 +17,6 @@ // The builtins below are not autogenerated from iset.py. // Make sure you do not overwrite these. -BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "") BUILTIN(__builtin_brev_ldd, "LLi*LLi*LLi*i", "") BUILTIN(__builtin_brev_ldw, "i*i*i*i", "") BUILTIN(__builtin_brev_ldh, "s*s*s*i", "") @@ -882,6 +881,7 @@ BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","") BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","") BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","") BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_prefetch,"vv*","") BUILTIN(__builtin_HEXAGON_Y2_dccleana,"vv*","") BUILTIN(__builtin_HEXAGON_Y2_dccleaninva,"vv*","") BUILTIN(__builtin_HEXAGON_Y2_dcinva,"vv*","") @@ -1470,14 +1470,6 @@ BUILTIN(__builtin_HEXAGON_V6_vassign,"V16iV16i","v:60:") BUILTIN(__builtin_HEXAGON_V6_vassign_128B,"V32iV32i","v:60:") BUILTIN(__builtin_HEXAGON_V6_vcombine,"V32iV16iV16i","v:60:") BUILTIN(__builtin_HEXAGON_V6_vcombine_128B,"V64iV32iV32i","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb,"V16iV16iLLii","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb_128B,"V32iV32iLLii","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb_acc,"V16iV16iV16iLLii","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb_acc_128B,"V32iV32iV32iLLii","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb_dv,"V32iV32iLLii","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb_dv_128B,"V64iV64iLLii","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb_dv_acc,"V32iV32iV32iLLii","v:60:") -BUILTIN(__builtin_HEXAGON_V6_vlutb_dv_acc_128B,"V64iV64iV64iLLii","v:60:") BUILTIN(__builtin_HEXAGON_V6_vdelta,"V16iV16iV16i","v:60:") BUILTIN(__builtin_HEXAGON_V6_vdelta_128B,"V32iV32iV32i","v:60:") BUILTIN(__builtin_HEXAGON_V6_vrdelta,"V16iV16iV16i","v:60:") @@ -1508,4 +1500,216 @@ BUILTIN(__builtin_HEXAGON_V6_lo_128B,"V32iV64i","v:60:") BUILTIN(__builtin_HEXAGON_V6_vassignp,"V32iV32i","v:60:") BUILTIN(__builtin_HEXAGON_V6_vassignp_128B,"V64iV64i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_qpred_ai_128B,"vV32iv*V32i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_nqpred_ai_128B,"vV32iv*V32i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai_128B,"vV32iv*V32i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai_128B,"vV32iv*V32i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq,"vV16iv*V16i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstoreq_128B,"vV32iv*V32i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstorenq_128B,"vV32iv*V32i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentq_128B,"vV32iv*V32i","v:60:") +BUILTIN(__builtin_HEXAGON_V6_vmaskedstorentnq_128B,"vV32iv*V32i","v:60:") + +BUILTIN(__builtin_HEXAGON_M6_vabsdiffb,"LLiLLiLLi","v:62:") +BUILTIN(__builtin_HEXAGON_M6_vabsdiffub,"LLiLLiLLi","v:62:") +BUILTIN(__builtin_HEXAGON_A6_vminub_RdP,"LLiLLiLLi","v:62:") +BUILTIN(__builtin_HEXAGON_S6_vsplatrbp,"LLii","v:62:") +BUILTIN(__builtin_HEXAGON_S6_vtrunehb_ppp,"LLiLLiLLi","v:62:") +BUILTIN(__builtin_HEXAGON_S6_vtrunohb_ppp,"LLiLLiLLi","v:62:") + +BUILTIN(__builtin_HEXAGON_V6_vlsrb,"V16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlsrb_128B,"V32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat,"V16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vasrwuhrndsat_128B,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat,"V16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vasruwuhrndsat_128B,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vasrhbsat,"V16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vasrhbsat_128B,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vrounduwuh,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vrounduwuh_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vrounduhub,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vrounduhub_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vadduwsat,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vadduwsat_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vadduwsat_dv_128B,"V64iV64iV64i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubuwsat,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubuwsat_dv_128B,"V64iV64iV64i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddbsat,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddbsat_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddbsat_dv_128B,"V64iV64iV64i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubbsat,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubbsat_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubbsat_dv_128B,"V64iV64iV64i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddububb_sat_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubububb_sat_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc,"V32iV32iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddhw_acc_128B,"V64iV64iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc,"V32iV32iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vadduhw_acc_128B,"V64iV64iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc,"V32iV32iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddubh_acc_128B,"V64iV64iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64,"V32iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyewuh_64_128B,"V64iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc,"V32iV32iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyowh_64_acc_128B,"V64iV64iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpauhb,"V32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpauhb_128B,"V64iV64ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpauhb_acc_128B,"V64iV64iV64ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyiwub,"V16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_128B,"V32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc,"V16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmpyiwub_acc_128B,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandnqrt,"V16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandnqrt_128B,"V32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc,"V16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandnqrt_acc_128B,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandvqv,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandvqv_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandvnqv,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vandvnqv_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2,"V16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_pred_scalar2v2_128B,"V32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_shuffeqw,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_shuffeqw_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_shuffeqh,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_shuffeqh_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmaxb,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vmaxb_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vminb,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vminb_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsatuwuh,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsatuwuh_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_lvsplath,"V16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_lvsplath_128B,"V32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_lvsplatb,"V16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_lvsplatb_128B,"V32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddclbw,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddclbw_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddclbh,"V16iV16iV16i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddclbh_128B,"V32iV32iV32i","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvvbi,"V16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvvbi_128B,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci,"V16iV16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvvb_oracci_128B,"V32iV32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvwhi,"V32iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvwhi_128B,"V64iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci,"V32iV32iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvwh_oracci_128B,"V64iV64iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm,"V16iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvvb_nm_128B,"V32iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm,"V32iV16iV16ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vlutvwh_nm_128B,"V64iV32iV32ii","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddcarry,"V16iV16iV16iv*","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vaddcarry_128B,"V32iV32iV32iv*","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubcarry,"V16iV16iV16iv*","v:62:") +BUILTIN(__builtin_HEXAGON_V6_vsubcarry_128B,"V32iV32iV32iv*","v:62:") + +BUILTIN(__builtin_HEXAGON_A6_vcmpbeq_notany,"iLLiLLi","v:65:") +BUILTIN(__builtin_HEXAGON_A6_vcmpbeq_notany_128B,"iLLiLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt,"V32iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_128B,"V64iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc,"V32iV32iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpyub_rtt_acc_128B,"V64iV64iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt,"V32iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_128B,"V64iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc,"V32iV32iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vrmpybub_rtt_acc_128B,"V64iV64iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat,"V16iV16iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasruwuhsat_128B,"V32iV32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasruhubsat,"V16iV16iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasruhubsat_128B,"V32iV32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat,"V16iV16iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasruhubrndsat_128B,"V32iV32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vaslh_acc,"V16iV16iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vaslh_acc_128B,"V32iV32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasrh_acc,"V16iV16iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vasrh_acc_128B,"V32iV32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavguw,"V16iV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavguw_128B,"V32iV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavguwrnd,"V16iV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavguwrnd_128B,"V32iV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavgb,"V16iV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavgb_128B,"V32iV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavgbrnd,"V16iV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vavgbrnd_128B,"V32iV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vnavgb,"V16iV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vnavgb_128B,"V32iV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vabsb,"V16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vabsb_128B,"V32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vabsb_sat,"V16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vabsb_sat_128B,"V32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpabuu,"V32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpabuu_128B,"V64iV64ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc,"V32iV32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpabuu_acc_128B,"V64iV64iV64ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc,"V32iV32iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpyh_acc_128B,"V64iV64iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpahhsat,"V16iV16iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpahhsat_128B,"V32iV32iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat,"V16iV16iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpauhuhsat_128B,"V32iV32iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat,"V16iV16iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpsuhuhsat_128B,"V32iV32iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vlut4,"V16iV16iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vlut4_128B,"V32iV32iLLi","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpyuhe,"V16iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_128B,"V32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc,"V16iV16iV16ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vmpyuhe_acc_128B,"V32iV32iV32ii","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermw,"vv*iiV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermw_128B,"vv*iiV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermh,"vv*iiV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermh_128B,"vv*iiV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermhw,"vv*iiV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermhw_128B,"vv*iiV64i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermwq,"vv*V16iiiV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermwq_128B,"vv*V32iiiV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermhq,"vv*V16iiiV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermhq_128B,"vv*V32iiiV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermhwq,"vv*V16iiiV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vgathermhwq_128B,"vv*V32iiiV64i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermw,"viiV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermw_128B,"viiV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermh,"viiV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermh_128B,"viiV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermw_add,"viiV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermw_add_128B,"viiV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermh_add,"viiV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermh_add_128B,"viiV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermwq,"vV16iiiV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermwq_128B,"vV32iiiV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhq,"vV16iiiV16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhq_128B,"vV32iiiV32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhw,"viiV32iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhw_128B,"viiV64iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhwq,"vV16iiiV32iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhwq_128B,"vV32iiiV64iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add,"viiV32iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vscattermhw_add_128B,"viiV64iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vprefixqb,"V16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vprefixqb_128B,"V32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vprefixqh,"V16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vprefixqh_128B,"V32iV32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vprefixqw,"V16iV16i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vprefixqw_128B,"V32iV32i","v:65:") + +BUILTIN(__builtin_HEXAGON_V6_vdd0,"V32i","v:65:") +BUILTIN(__builtin_HEXAGON_V6_vdd0_128B,"V64i","v:65:") + + #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def index afea6cb0f1b2..7bab73a3b110 100644 --- a/include/clang/Basic/BuiltinsNVPTX.def +++ b/include/clang/Basic/BuiltinsNVPTX.def @@ -371,6 +371,9 @@ BUILTIN(__nvvm_bitcast_i2f, "fi", "") BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "") BUILTIN(__nvvm_bitcast_d2ll, "LLid", "") +// FNS +TARGET_BUILTIN(__nvvm_fns, "UiUiUii", "n", "ptx60") + // Sync BUILTIN(__syncthreads, "v", "") @@ -378,6 +381,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") // Shuffle @@ -390,6 +396,33 @@ 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") + +// Vote +BUILTIN(__nvvm_vote_all, "bb", "") +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") + +// Match +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") + // Membar BUILTIN(__nvvm_membar_cta, "v", "") @@ -451,7 +484,7 @@ 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") -BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "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") @@ -658,5 +691,18 @@ BUILTIN(__nvvm_ldg_f2, "E2fE2fC*", "") 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") + #undef BUILTIN #undef TARGET_BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 2f8f8919e5b3..d0be48467f1f 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -32,7 +32,9 @@ // Miscellaneous builtin for checking x86 cpu features. // TODO: Make this somewhat generic so that other backends // can use it? +BUILTIN(__builtin_cpu_init, "v", "n") BUILTIN(__builtin_cpu_supports, "bcC*", "nc") +BUILTIN(__builtin_cpu_is, "bcC*", "nc") // Undefined Values // @@ -264,8 +266,6 @@ 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_pavgb128, "V16cV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "", "sse2") TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "", "sse2") TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "", "sse2") TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "", "sse2") @@ -520,8 +520,6 @@ 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_pavgb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "", "avx2") TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "", "avx2") TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "", "avx2") TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "", "avx2") @@ -640,8 +638,21 @@ TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "", "xsaves") TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "", "xsavec") TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "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") + //CLFLUSHOPT -TARGET_BUILTIN(__builtin_ia32_clflushopt, "vc*", "", "clflushopt") +TARGET_BUILTIN(__builtin_ia32_clflushopt, "vvC*", "", "clflushopt") + +//CLWB +TARGET_BUILTIN(__builtin_ia32_clwb, "vvC*", "", "clwb") // ADX TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx") @@ -681,36 +692,18 @@ TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "", "sha") // FMA TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubps, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubpd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubss, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubsd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmaddps, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmaddpd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmaddss, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmaddsd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmsubps, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmsubss, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmsubsd, "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_vfmsubaddps, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd, "V2dV2dV2dV2d", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubps256, "V8fV8fV8fV8f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmsubps256, "V8fV8fV8fV8f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "", "fma|fma4") TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl") TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl") @@ -909,39 +902,10 @@ TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512 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_cmpps512_mask, "UsV16fV16fIiUsIi", "", "avx512f") TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "", "avx512vl") TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pcmpeqw512_mask, "iV32sV32si", "", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_pcmpeqb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpeqd256_mask, "cV8iV8ic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpeqq256_mask, "cV4LLiV4LLic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpeqw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw") - -TARGET_BUILTIN(__builtin_ia32_pcmpgtb512_mask, "LLiV64cV64cLLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpgtd512_mask, "sV16iV16is", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pcmpgtq512_mask, "cV8LLiV8LLic", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pcmpgtw512_mask, "iV32sV32si", "", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_pcmpgtb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpgtd256_mask, "cV8iV8ic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpgtq256_mask, "cV4LLiV4LLic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpgtw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpgtb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pcmpgtd128_mask, "cV4iV4ic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpgtq128_mask, "cV2LLiV2LLic", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pcmpgtw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw") - TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "", "avx512f") TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "", "avx512vl") TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "", "avx512vl") @@ -973,9 +937,6 @@ 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_ptestmd512, "UsV16iV16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "", "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") @@ -1072,8 +1033,6 @@ TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx51 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_pavgb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pavgw512_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") @@ -1101,6 +1060,10 @@ TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx5 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") @@ -1378,11 +1341,6 @@ TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc","","av 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_pbroadcastb512_gpr_mask, "V64ccV64cULLi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_pbroadcastb128_gpr_mask, "V16ccV16cUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pbroadcastb256_gpr_mask, "V32ccV32cUi","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pbroadcastd128_gpr_mask, "V4iiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pbroadcastd256_gpr_mask, "V8iiV8iUc","","avx512vl") TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma") TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma") TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma") @@ -1494,28 +1452,6 @@ TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_maskz, "V16iV16iV16iV16iUs","","avx 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_ptestmb512, "ULLiV64cV64cULLi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_ptestmw512, "UiV32sV32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_ptestnmb512, "ULLiV64cV64cULLi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_ptestnmw512, "UiV32sV32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_ptestmb128, "UsV16cV16cUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestmb256, "UiV32cV32cUi","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestmw128, "UcV8sV8sUc","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestmw256, "UsV16sV16sUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmb128, "UsV16cV16cUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmb256, "UiV32cV32cUi","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmw128, "UcV8sV8sUc","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmw256, "UsV16sV16sUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestmd128, "UcV4iV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestmd256, "UcV8iV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestmq128, "UcV2LLiV2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestmq256, "UcV4LLiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmd128, "UcV4iV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmd256, "UcV8iV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmq128, "UcV2LLiV2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmq256, "UcV4LLiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_ptestnmd512, "UsV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_ptestnmq512, "UcV8LLiV8LLiUc","","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") @@ -1587,20 +1523,6 @@ 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_broadcastmb512, "V8LLiUc","","avx512cd") -TARGET_BUILTIN(__builtin_ia32_broadcastmw512, "V16iUs","","avx512cd") -TARGET_BUILTIN(__builtin_ia32_broadcastmb128, "V2LLiUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcastmb256, "V4LLiUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcastmw128, "V4iUs","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcastmw256, "V8iUs","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_512_mask, "V16fV4fV16fUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_512_mask, "V16iV4iV16iUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_broadcastf32x2_256_mask, "V8fV4fV8fUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_128_mask, "V4iV4iV4iUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_broadcasti32x2_256_mask, "V8iV4iV8iUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pbroadcastw512_gpr_mask, "V32shV32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_pbroadcastw256_gpr_mask, "V16shV16sUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pbroadcastw128_gpr_mask, "V8ssV8sUc","","avx512bw,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") diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def index 4cde153d8372..fe2c887c7e0f 100644 --- a/include/clang/Basic/BuiltinsX86_64.def +++ b/include/clang/Basic/BuiltinsX86_64.def @@ -40,6 +40,7 @@ TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "LLiLLiD*LLi", "nh", "intrin.h" 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, "") +TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128, "UcLLiD*LLiLLiLLi*", "nh", "intrin.h", ALL_MS_LANGUAGES, "cx16") TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "") TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "") @@ -60,6 +61,10 @@ 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*", "", "") @@ -71,9 +76,6 @@ 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_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pbroadcastq128_gpr_mask, "V2LLiULLiV2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pbroadcastq256_gpr_mask, "V4LLiULLiV4LLiUc","","avx512vl") TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi","","avx512f") TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi","","avx512f") TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi","","avx512f") diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 3e0fb8728c48..821c405913c8 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -9,10 +9,12 @@ clang_diag_gen(Analysis) clang_diag_gen(AST) clang_diag_gen(Comment) clang_diag_gen(Common) +clang_diag_gen(CrossTU) clang_diag_gen(Driver) clang_diag_gen(Frontend) clang_diag_gen(Lex) clang_diag_gen(Parse) +clang_diag_gen(Refactoring) clang_diag_gen(Sema) clang_diag_gen(Serialization) clang_tablegen(DiagnosticGroups.inc -gen-clang-diag-groups diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h index dd9c55431e01..cc27bbb48e0d 100644 --- a/include/clang/Basic/CharInfo.h +++ b/include/clang/Basic/CharInfo.h @@ -40,14 +40,14 @@ namespace charinfo { } // end namespace charinfo /// Returns true if this is an ASCII character. -LLVM_READNONE static inline bool isASCII(char c) { +LLVM_READNONE inline bool isASCII(char c) { return static_cast<unsigned char>(c) <= 127; } /// Returns true if this is a valid first character of a C identifier, /// which is [a-zA-Z_]. -LLVM_READONLY static inline bool isIdentifierHead(unsigned char c, - bool AllowDollar = false) { +LLVM_READONLY inline bool isIdentifierHead(unsigned char c, + bool AllowDollar = false) { using namespace charinfo; if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_UNDER)) return true; @@ -56,8 +56,8 @@ LLVM_READONLY static inline bool isIdentifierHead(unsigned char c, /// Returns true if this is a body character of a C identifier, /// which is [a-zA-Z0-9_]. -LLVM_READONLY static inline bool isIdentifierBody(unsigned char c, - bool AllowDollar = false) { +LLVM_READONLY inline bool isIdentifierBody(unsigned char c, + bool AllowDollar = false) { using namespace charinfo; if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER)) return true; @@ -68,7 +68,7 @@ LLVM_READONLY static inline bool isIdentifierBody(unsigned char c, /// ' ', '\\t', '\\f', '\\v'. /// /// Note that this returns false for '\\0'. -LLVM_READONLY static inline bool isHorizontalWhitespace(unsigned char c) { +LLVM_READONLY inline bool isHorizontalWhitespace(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_SPACE)) != 0; } @@ -76,7 +76,7 @@ LLVM_READONLY static inline bool isHorizontalWhitespace(unsigned char c) { /// Returns true if this character is vertical ASCII whitespace: '\\n', '\\r'. /// /// Note that this returns false for '\\0'. -LLVM_READONLY static inline bool isVerticalWhitespace(unsigned char c) { +LLVM_READONLY inline bool isVerticalWhitespace(unsigned char c) { using namespace charinfo; return (InfoTable[c] & CHAR_VERT_WS) != 0; } @@ -85,43 +85,43 @@ LLVM_READONLY static inline bool isVerticalWhitespace(unsigned char c) { /// ' ', '\\t', '\\f', '\\v', '\\n', '\\r'. /// /// Note that this returns false for '\\0'. -LLVM_READONLY static inline bool isWhitespace(unsigned char c) { +LLVM_READONLY inline bool isWhitespace(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_VERT_WS|CHAR_SPACE)) != 0; } /// Return true if this character is an ASCII digit: [0-9] -LLVM_READONLY static inline bool isDigit(unsigned char c) { +LLVM_READONLY inline bool isDigit(unsigned char c) { using namespace charinfo; return (InfoTable[c] & CHAR_DIGIT) != 0; } /// Return true if this character is a lowercase ASCII letter: [a-z] -LLVM_READONLY static inline bool isLowercase(unsigned char c) { +LLVM_READONLY inline bool isLowercase(unsigned char c) { using namespace charinfo; return (InfoTable[c] & CHAR_LOWER) != 0; } /// Return true if this character is an uppercase ASCII letter: [A-Z] -LLVM_READONLY static inline bool isUppercase(unsigned char c) { +LLVM_READONLY inline bool isUppercase(unsigned char c) { using namespace charinfo; return (InfoTable[c] & CHAR_UPPER) != 0; } /// Return true if this character is an ASCII letter: [a-zA-Z] -LLVM_READONLY static inline bool isLetter(unsigned char c) { +LLVM_READONLY inline bool isLetter(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER)) != 0; } /// Return true if this character is an ASCII letter or digit: [a-zA-Z0-9] -LLVM_READONLY static inline bool isAlphanumeric(unsigned char c) { +LLVM_READONLY inline bool isAlphanumeric(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_DIGIT|CHAR_UPPER|CHAR_LOWER)) != 0; } /// Return true if this character is an ASCII hex digit: [0-9a-fA-F] -LLVM_READONLY static inline bool isHexDigit(unsigned char c) { +LLVM_READONLY inline bool isHexDigit(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_DIGIT|CHAR_XLETTER)) != 0; } @@ -129,7 +129,7 @@ LLVM_READONLY static inline bool isHexDigit(unsigned char c) { /// Return true if this character is an ASCII punctuation character. /// /// Note that '_' is both a punctuation character and an identifier character! -LLVM_READONLY static inline bool isPunctuation(unsigned char c) { +LLVM_READONLY inline bool isPunctuation(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_UNDER|CHAR_PERIOD|CHAR_RAWDEL|CHAR_PUNCT)) != 0; } @@ -137,7 +137,7 @@ LLVM_READONLY static inline bool isPunctuation(unsigned char c) { /// Return true if this character is an ASCII printable character; that is, a /// character that should take exactly one column to print in a fixed-width /// terminal. -LLVM_READONLY static inline bool isPrintable(unsigned char c) { +LLVM_READONLY inline bool isPrintable(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD|CHAR_PUNCT| CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL|CHAR_SPACE)) != 0; @@ -145,14 +145,14 @@ LLVM_READONLY static inline bool isPrintable(unsigned char c) { /// Return true if this is the body character of a C preprocessing number, /// which is [a-zA-Z0-9_.]. -LLVM_READONLY static inline bool isPreprocessingNumberBody(unsigned char c) { +LLVM_READONLY inline bool isPreprocessingNumberBody(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER|CHAR_PERIOD)) != 0; } /// Return true if this is the body character of a C++ raw string delimiter. -LLVM_READONLY static inline bool isRawStringDelimBody(unsigned char c) { +LLVM_READONLY inline bool isRawStringDelimBody(unsigned char c) { using namespace charinfo; return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD| CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL)) != 0; @@ -162,7 +162,7 @@ LLVM_READONLY static inline bool isRawStringDelimBody(unsigned char c) { /// Converts the given ASCII character to its lowercase equivalent. /// /// If the character is not an uppercase character, it is returned as is. -LLVM_READONLY static inline char toLowercase(char c) { +LLVM_READONLY inline char toLowercase(char c) { if (isUppercase(c)) return c + 'a' - 'A'; return c; @@ -171,7 +171,7 @@ LLVM_READONLY static inline char toLowercase(char c) { /// Converts the given ASCII character to its uppercase equivalent. /// /// If the character is not a lowercase character, it is returned as is. -LLVM_READONLY static inline char toUppercase(char c) { +LLVM_READONLY inline char toUppercase(char c) { if (isLowercase(c)) return c + 'A' - 'a'; return c; @@ -182,7 +182,7 @@ LLVM_READONLY static inline char toUppercase(char c) { /// /// Note that this is a very simple check; it does not accept '$' or UCNs as /// valid identifier characters. -LLVM_READONLY static inline bool isValidIdentifier(StringRef S) { +LLVM_READONLY inline bool isValidIdentifier(StringRef S) { if (S.empty() || !isIdentifierHead(S[0])) return false; diff --git a/include/clang/Basic/Cuda.h b/include/clang/Basic/Cuda.h index ad1139b8c197..1a0731c37a35 100644 --- a/include/clang/Basic/Cuda.h +++ b/include/clang/Basic/Cuda.h @@ -21,6 +21,8 @@ enum class CudaVersion { CUDA_70, CUDA_75, CUDA_80, + CUDA_90, + LATEST = CUDA_90, }; const char *CudaVersionToString(CudaVersion V); @@ -41,6 +43,7 @@ enum class CudaArch { SM_60, SM_61, SM_62, + SM_70, }; const char *CudaArchToString(CudaArch A); @@ -60,6 +63,7 @@ enum class CudaVirtualArch { COMPUTE_60, COMPUTE_61, COMPUTE_62, + COMPUTE_70, }; const char *CudaVirtualArchToString(CudaVirtualArch A); @@ -72,6 +76,9 @@ CudaVirtualArch VirtualArchForCudaArch(CudaArch A); /// Get the earliest CudaVersion that supports the given CudaArch. CudaVersion MinVersionForCudaArch(CudaArch A); +/// Get the latest CudaVersion that supports the given CudaArch. +CudaVersion MaxVersionForCudaArch(CudaArch A); + } // namespace clang #endif diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 3298a80e5134..67ca9e5c6c62 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -1,66 +1,68 @@ class AttrSubject; -class Decl<bit abstract = 0> : AttrSubject { +class Decl<string diagSpelling = "", bit abstract = 0> : AttrSubject { bit Abstract = abstract; + string DiagSpelling = diagSpelling; } -class DDecl<Decl base, bit abstract = 0> : Decl<abstract> { +class DDecl<Decl base, string diagSpelling = "", bit abstract = 0> + : Decl<diagSpelling, abstract> { Decl Base = base; } -class DeclContext { } +class DeclContext {} def TranslationUnit : Decl, DeclContext; def PragmaComment : Decl; def PragmaDetectMismatch : Decl; def ExternCContext : Decl, DeclContext; -def Named : Decl<1>; - def Namespace : DDecl<Named>, DeclContext; +def Named : Decl<"named declarations", 1>; + def Namespace : DDecl<Named, "namespaces">, DeclContext; def UsingDirective : DDecl<Named>; def NamespaceAlias : DDecl<Named>; - def Label : DDecl<Named>; - def Type : DDecl<Named, 1>; - def TypedefName : DDecl<Type, 1>; + def Label : DDecl<Named, "labels">; + def Type : DDecl<Named, "types", 1>; + def TypedefName : DDecl<Type, "typedefs", 1>; def Typedef : DDecl<TypedefName>; def TypeAlias : DDecl<TypedefName>; def ObjCTypeParam : DDecl<TypedefName>; def UnresolvedUsingTypename : DDecl<Type>; - def Tag : DDecl<Type, 1>, DeclContext; - def Enum : DDecl<Tag>; - def Record : DDecl<Tag>; - def CXXRecord : DDecl<Record>; + def Tag : DDecl<Type, "tag types", 1>, DeclContext; + def Enum : DDecl<Tag, "enums">; + def Record : DDecl<Tag, "structs, unions, classes">; + def CXXRecord : DDecl<Record, "classes">; def ClassTemplateSpecialization : DDecl<CXXRecord>; def ClassTemplatePartialSpecialization : DDecl<ClassTemplateSpecialization>; def TemplateTypeParm : DDecl<Type>; - def Value : DDecl<Named, 1>; - def EnumConstant : DDecl<Value>; + def Value : DDecl<Named, "value declarations", 1>; + def EnumConstant : DDecl<Value, "enumerators">; def UnresolvedUsingValue : DDecl<Value>; def IndirectField : DDecl<Value>; def Binding : DDecl<Value>; def OMPDeclareReduction : DDecl<Value>, DeclContext; - def Declarator : DDecl<Value, 1>; - def Field : DDecl<Declarator>; + def Declarator : DDecl<Value, "declarators", 1>; + def Field : DDecl<Declarator, "non-static data members">; def ObjCIvar : DDecl<Field>; def ObjCAtDefsField : DDecl<Field>; def MSProperty : DDecl<Declarator>; - def Function : DDecl<Declarator>, DeclContext; + def Function : DDecl<Declarator, "functions">, DeclContext; def CXXDeductionGuide : DDecl<Function>; def CXXMethod : DDecl<Function>; def CXXConstructor : DDecl<CXXMethod>; def CXXDestructor : DDecl<CXXMethod>; def CXXConversion : DDecl<CXXMethod>; - def Var : DDecl<Declarator>; + def Var : DDecl<Declarator, "variables">; def VarTemplateSpecialization : DDecl<Var>; def VarTemplatePartialSpecialization : DDecl<VarTemplateSpecialization>; def ImplicitParam : DDecl<Var>; - def ParmVar : DDecl<Var>; + def ParmVar : DDecl<Var, "parameters">; def Decomposition : DDecl<Var>; def OMPCapturedExpr : DDecl<Var>; def NonTypeTemplateParm : DDecl<Declarator>; - def Template : DDecl<Named, 1>; - def RedeclarableTemplate : DDecl<Template, 1>; + def Template : DDecl<Named, "templates", 1>; + def RedeclarableTemplate : DDecl<Template, "redeclarable templates", 1>; def FunctionTemplate : DDecl<RedeclarableTemplate>; def ClassTemplate : DDecl<RedeclarableTemplate>; def VarTemplate : DDecl<RedeclarableTemplate>; @@ -71,15 +73,16 @@ def Named : Decl<1>; def UsingPack : DDecl<Named>; def UsingShadow : DDecl<Named>; def ConstructorUsingShadow : DDecl<UsingShadow>; - def ObjCMethod : DDecl<Named>, DeclContext; - def ObjCContainer : DDecl<Named, 1>, DeclContext; + def ObjCMethod : DDecl<Named, "Objective-C methods">, DeclContext; + def ObjCContainer : DDecl<Named, "Objective-C containers", 1>, DeclContext; def ObjCCategory : DDecl<ObjCContainer>; - def ObjCProtocol : DDecl<ObjCContainer>; - def ObjCInterface : DDecl<ObjCContainer>; - def ObjCImpl : DDecl<ObjCContainer, 1>; + def ObjCProtocol : DDecl<ObjCContainer, "Objective-C protocols">; + def ObjCInterface : DDecl<ObjCContainer, "Objective-C interfaces">; + def ObjCImpl + : DDecl<ObjCContainer, "Objective-C implementation declarations", 1>; def ObjCCategoryImpl : DDecl<ObjCImpl>; def ObjCImplementation : DDecl<ObjCImpl>; - def ObjCProperty : DDecl<Named>; + def ObjCProperty : DDecl<Named, "Objective-C properties">; def ObjCCompatibleAlias : DDecl<Named>; def LinkageSpec : Decl, DeclContext; def Export : Decl, DeclContext; @@ -89,7 +92,7 @@ def AccessSpec : Decl; def Friend : Decl; def FriendTemplate : Decl; def StaticAssert : Decl; -def Block : Decl, DeclContext; +def Block : Decl<"blocks">, DeclContext; def Captured : Decl, DeclContext; def ClassScopeFunctionSpecialization : Decl; def Import : Decl; diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 22cded21c12d..a7458d45618e 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -575,13 +575,15 @@ public: OverloadsShown getShowOverloads() const { return ShowOverloads; } /// \brief Pretend that the last diagnostic issued was ignored, so any - /// subsequent notes will be suppressed. + /// 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. /// /// This can be used by clients who suppress diagnostics themselves. - void setLastDiagnosticIgnored() { + void setLastDiagnosticIgnored(bool Ignored = true) { if (LastDiagLevel == DiagnosticIDs::Fatal) FatalErrorOccurred = true; - LastDiagLevel = DiagnosticIDs::Ignored; + LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning; } /// \brief Determine whether the previous diagnostic was ignored. This can diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td index f25068eca132..52ccf350e651 100644 --- a/include/clang/Basic/Diagnostic.td +++ b/include/clang/Basic/Diagnostic.td @@ -133,10 +133,12 @@ include "DiagnosticASTKinds.td" include "DiagnosticAnalysisKinds.td" include "DiagnosticCommentKinds.td" include "DiagnosticCommonKinds.td" +include "DiagnosticCrossTUKinds.td" include "DiagnosticDriverKinds.td" include "DiagnosticFrontendKinds.td" include "DiagnosticLexKinds.td" include "DiagnosticParseKinds.td" +include "DiagnosticRefactoringKinds.td" include "DiagnosticSemaKinds.td" include "DiagnosticSerializationKinds.td" diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index b3cba2066edd..215580b2e9b6 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -127,6 +127,10 @@ def note_constexpr_access_null : Note< def note_constexpr_access_past_end : Note< "%select{read of|assignment to|increment of|decrement of}0 " "dereferenced one-past-the-end pointer is not allowed in a constant expression">; +def note_constexpr_access_unsized_array : Note< + "%select{read of|assignment to|increment of|decrement of}0 " + "pointer to element of array without known bound " + "is not allowed in a constant expression">; def note_constexpr_access_inactive_union_member : Note< "%select{read of|assignment to|increment of|decrement of}0 " "member %1 of union with %select{active member %3|no active member}2 " @@ -154,6 +158,11 @@ def note_constexpr_baa_insufficient_alignment : Note< def note_constexpr_baa_value_insufficient_alignment : Note< "value of the aligned pointer (%0) is not a multiple of the asserted %1 " "%plural{1:byte|:bytes}1">; +def note_constexpr_unsupported_unsized_array : Note< + "array-to-pointer decay of array member without known bound is not supported">; +def note_constexpr_unsized_array_indexed : Note< + "indexing of array without known bound is not allowed " + "in a constant expression">; def warn_integer_constant_overflow : Warning< "overflow in expression; result is %0 with type %1">, diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 98fd3c4d57ac..82ca27b7345e 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -185,6 +185,8 @@ 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 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'">; def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">; def err_target_unsupported_abi_for_triple : Error< diff --git a/include/clang/Basic/DiagnosticCrossTUKinds.td b/include/clang/Basic/DiagnosticCrossTUKinds.td new file mode 100644 index 000000000000..8b6d8b681445 --- /dev/null +++ b/include/clang/Basic/DiagnosticCrossTUKinds.td @@ -0,0 +1,18 @@ +//==--- DiagnosticCrossTUKinds.td - Cross Translation Unit diagnostics ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +let Component = "CrossTU" in { + +def err_fnmap_parsing : Error< + "error parsing index file: '%0' line: %1 'UniqueID filename' format " + "expected">; + +def err_multiple_def_index : Error< + "multiple definitions are found for the same key in index ">; +} diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index fcef881fa0ae..41b5e42b4432 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -29,9 +29,10 @@ def err_drv_no_cuda_installation : Error< def err_drv_no_cuda_libdevice : Error< "cannot find libdevice for %0. Provide path to different CUDA installation " "via --cuda-path, or pass -nocudalib to build without linking with libdevice.">; -def err_drv_cuda_version_too_low : Error< - "GPU arch %1 requires CUDA version at least %3, but installation at %0 is %2. " - "Use --cuda-path to specify a different CUDA install, or pass " +def err_drv_cuda_version_unsupported : Error< + "GPU arch %0 is supported by CUDA versions between %1 and %2 (inclusive), " + "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_invalid_thread_model_for_target : Error< @@ -69,6 +70,10 @@ def err_drv_invalid_Xarch_argument_with_args : Error< "invalid Xarch argument: '%0', options requiring arguments are unsupported">; def err_drv_invalid_Xarch_argument_isdriver : Error< "invalid Xarch argument: '%0', cannot change driver behavior inside Xarch argument">; +def err_drv_Xopenmp_target_missing_triple : Error< + "cannot deduce implicit triple value for -Xopenmp-target, specify triple using -Xopenmp-target=<triple>">; +def err_drv_invalid_Xopenmp_target_with_args : Error< + "invalid -Xopenmp-target argument: '%0', options requiring arguments are unsupported">; def err_drv_argument_only_allowed_with : Error< "invalid argument '%0' only allowed with '%1'">; def err_drv_argument_not_allowed_with : Error< @@ -97,6 +102,10 @@ def err_drv_force_crash : Error< "failing because %select{environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set|'-gen-reproducer' is used}0">; def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; +def err_drv_invalid_mtp : Error< + "invalid thread pointer reading mode '%0'">; +def err_drv_missing_arg_mtp : Error< + "missing argument to '%0'">; def err_drv_invalid_libcxx_deployment : Error< "invalid deployment target for -stdlib=libc++ (requires %0 or later)">; def err_drv_invalid_argument_to_fdebug_prefix_map : Error< @@ -106,6 +115,10 @@ def err_drv_malformed_sanitizer_blacklist : Error< def err_target_unsupported_arch : Error<"the target architecture '%0' is not supported by the target '%1'">; +def err_cpu_unsupported_isa + : Error<"CPU '%0' does not support '%1' execution mode">; +def err_arch_unsupported_isa + : Error<"Architecture '%0' does not support '%1' execution mode">; def err_drv_I_dash_not_supported : Error< "'%0' not supported, please use -iquote instead">; @@ -231,7 +244,7 @@ def warn_drv_enabling_rtti_with_exceptions : Warning< InGroup<DiagGroup<"rtti-for-exceptions">>; def warn_drv_disabling_vptr_no_rtti_default : Warning< "implicitly disabling vptr sanitizer because rtti wasn't enabled">, - InGroup<DiagGroup<"auto-disable-vptr-sanitizer">>; + 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>; @@ -251,6 +264,9 @@ def err_analyzer_config_no_value : Error< def err_analyzer_config_multiple_values : Error< "analyzer-config option '%0' should contain only one '='">; +def err_drv_invalid_hvx_length : Error< + "-mhvx-length is not supported without a -mhvx/-mhvx= flag">; + def err_drv_modules_validate_once_requires_timestamp : Error< "option '-fmodules-validate-once-per-build-session' requires " "'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">; @@ -277,9 +293,27 @@ def warn_target_unsupported_nan2008 : Warning< def warn_target_unsupported_nanlegacy : Warning< "ignoring '-mnan=legacy' option because the '%0' architecture does not support it">, InGroup<UnsupportedNan>; +def warn_target_unsupported_abslegacy : Warning< + "ignoring '-mabs=legacy' option because the '%0' architecture does not support it">, + InGroup<UnsupportedAbs>; +def warn_target_unsupported_abs2008 : Warning< + "ignoring '-mabs=2008' option because the '%0' architecture does not support it">, + InGroup<UnsupportedAbs>; def warn_target_unsupported_compact_branches : Warning< "ignoring '-mcompact-branches=' option because the '%0' architecture does not" " support it">, InGroup<UnsupportedCB>; +def warn_drv_unsupported_gpopt : Warning< + "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" + " usage of }0-mabicalls">, + InGroup<UnsupportedGPOpt>; +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">, + InGroup<OptionIgnored>; def warn_drv_unable_to_find_directory_expected : Warning< "unable to find %0 directory, expected to be in '%1'">, @@ -300,4 +334,12 @@ def warn_drv_msvc_not_found : Warning< "unable to find a Visual Studio installation; " "try running Clang from a developer command prompt">, InGroup<DiagGroup<"msvc-not-found">>; + +def warn_drv_fine_grained_bitfield_accesses_ignored : Warning< + "option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored">, + InGroup<OptionIgnored>; + +def note_drv_verify_prefix_spelling : Note< + "-verify prefixes must start with a letter and contain only alphanumeric" + " characters, hyphens, and underscores">; } diff --git a/include/clang/Basic/DiagnosticError.h b/include/clang/Basic/DiagnosticError.h new file mode 100644 index 000000000000..6b4b073736a8 --- /dev/null +++ b/include/clang/Basic/DiagnosticError.h @@ -0,0 +1,61 @@ +//===--- DiagnosticError.h - Diagnostic payload for llvm::Error -*- 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_BASIC_DIAGNOSTIC_ERROR_H +#define LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H + +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/Support/Error.h" + +namespace clang { + +/// \brief Carries a Clang diagnostic in an llvm::Error. +/// +/// Users should emit the stored diagnostic using the DiagnosticsEngine. +class DiagnosticError : public llvm::ErrorInfo<DiagnosticError> { +public: + DiagnosticError(PartialDiagnosticAt Diag) : Diag(std::move(Diag)) {} + + void log(raw_ostream &OS) const override { OS << "clang diagnostic"; } + + PartialDiagnosticAt &getDiagnostic() { return Diag; } + const PartialDiagnosticAt &getDiagnostic() const { return Diag; } + + /// Creates a new \c DiagnosticError that contains the given diagnostic at + /// the given location. + static llvm::Error create(SourceLocation Loc, PartialDiagnostic Diag) { + return llvm::make_error<DiagnosticError>( + PartialDiagnosticAt(Loc, std::move(Diag))); + } + + /// Extracts and returns the diagnostic payload from the given \c Error if + /// the error is a \c DiagnosticError. Returns none if the given error is not + /// a \c DiagnosticError. + static Optional<PartialDiagnosticAt> take(llvm::Error &Err) { + Optional<PartialDiagnosticAt> Result; + Err = llvm::handleErrors(std::move(Err), [&](DiagnosticError &E) { + Result = std::move(E.getDiagnostic()); + }); + return Result; + } + + static char ID; + +private: + // Users are not expected to use error_code. + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } + + PartialDiagnosticAt Diag; +}; + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 57c24e9be73a..392a340a3bb7 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -116,6 +116,8 @@ def err_fe_action_not_available : Error< "action %0 not compiled in">; 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 warn_fe_serialized_diag_merge_failure : Warning< "unable to merge a subprocess's serialized diagnostics">, diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 23e4d4633ae2..c23183c81ac8 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -27,11 +27,16 @@ def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">; def GNUAutoType : DiagGroup<"gnu-auto-type">; def ArrayBounds : DiagGroup<"array-bounds">; def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">; +def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; +def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; +def BinaryLiteral : DiagGroup<"binary-literal", [CXX14BinaryLiteral, + CXXPre14CompatBinaryLiteral, + GNUBinaryLiteral]>; def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">; def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">; def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">; @@ -60,7 +65,9 @@ def FloatConversion : def DoublePromotion : DiagGroup<"double-promotion">; def EnumTooLarge : DiagGroup<"enum-too-large">; def UnsupportedNan : DiagGroup<"unsupported-nan">; +def UnsupportedAbs : DiagGroup<"unsupported-abs">; def UnsupportedCB : DiagGroup<"unsupported-cb">; +def UnsupportedGPOpt : DiagGroup<"unsupported-gpopt">; def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">; def NullConversion : DiagGroup<"null-conversion">; def ImplicitConversionFloatingPointToBool : @@ -87,6 +94,7 @@ def GNUStringLiteralOperatorTemplate : DiagGroup<"gnu-string-literal-operator-template">; def UndefinedVarTemplate : DiagGroup<"undefined-var-template">; def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">; +def MissingNoEscape : DiagGroup<"missing-noescape">; def DeleteIncomplete : DiagGroup<"delete-incomplete">; def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">; @@ -162,10 +170,14 @@ def NoexceptType : DiagGroup<"noexcept-type", [CXX17CompatMangling]>; // Warnings for C++1y code which is not compatible with prior C++ standards. def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">; def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic", - [CXXPre14Compat]>; -def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">; -def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic", - [CXXPre1zCompat]>; + [CXXPre14Compat, + CXXPre14CompatBinaryLiteral]>; +def CXXPre17Compat : DiagGroup<"c++98-c++11-c++14-compat">; +def CXXPre17CompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic", + [CXXPre17Compat]>; +def CXXPre2aCompat : DiagGroup<"c++98-c++11-c++14-c++17-compat">; +def CXXPre2aCompatPedantic : DiagGroup<"c++98-c++11-c++14-c++17-compat-pedantic", + [CXXPre2aCompat]>; def CXX98CompatBindToTemporaryCopy : DiagGroup<"c++98-compat-bind-to-temporary-copy">; @@ -178,13 +190,15 @@ def CXX98Compat : DiagGroup<"c++98-compat", [CXX98CompatLocalTypeTemplateArgs, CXX98CompatUnnamedTypeTemplateArgs, CXXPre14Compat, - CXXPre1zCompat]>; + CXXPre17Compat, + CXXPre2aCompat]>; // Warnings for C++11 features which are Extensions in C++98 mode. def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat, CXX98CompatBindToTemporaryCopy, CXXPre14CompatPedantic, - CXXPre1zCompatPedantic]>; + CXXPre17CompatPedantic, + CXXPre2aCompatPedantic]>; def CXX11Narrowing : DiagGroup<"c++11-narrowing">; @@ -209,21 +223,35 @@ def CXX11Compat : DiagGroup<"c++11-compat", CXX11CompatReservedUserDefinedLiteral, CXX11CompatDeprecatedWritableStr, CXXPre14Compat, - CXXPre1zCompat]>; + CXXPre17Compat, + CXXPre2aCompat]>; def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic", - [CXXPre14CompatPedantic, - CXXPre1zCompatPedantic]>; + [CXX11Compat, + CXXPre14CompatPedantic, + CXXPre17CompatPedantic, + CXXPre2aCompatPedantic]>; -def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>; +def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre17Compat, + CXXPre2aCompat]>; def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic", - [CXXPre1zCompatPedantic]>; + [CXX14Compat, + CXXPre17CompatPedantic, + CXXPre2aCompatPedantic]>; def CXX17Compat : DiagGroup<"c++17-compat", [DeprecatedRegister, DeprecatedIncrementBool, - CXX17CompatMangling]>; + CXX17CompatMangling, + CXXPre2aCompat]>; +def CXX17CompatPedantic : DiagGroup<"c++17-compat-pedantic", + [CXX17Compat, + CXXPre2aCompatPedantic]>; def : DiagGroup<"c++1z-compat", [CXX17Compat]>; +def CXX2aCompat : DiagGroup<"c++2a-compat">; +def CXX2aCompatPedantic : DiagGroup<"c++2a-compat-pedantic", + [CXX2aCompat]>; + def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">; def FourByteMultiChar : DiagGroup<"four-char-constants">; @@ -316,6 +344,7 @@ def NonPODVarargs : DiagGroup<"non-pod-varargs">; def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>; def : DiagGroup<"nonportable-cfstrings">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; +def NullPointerArithmetic : DiagGroup<"null-pointer-arithmetic">; def : DiagGroup<"effc++", [NonVirtualDtor]>; def OveralignedType : DiagGroup<"over-aligned">; def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">; @@ -345,6 +374,7 @@ def ObjCRootClass : DiagGroup<"objc-root-class">; def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">; def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>; def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">; +def ObjCFlexibleArray : DiagGroup<"objc-flexible-array">; def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">; def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">; @@ -405,12 +435,18 @@ def StringCompare : DiagGroup<"string-compare">; def StringPlusInt : DiagGroup<"string-plus-int">; def StringPlusChar : DiagGroup<"string-plus-char">; def StrncatSize : DiagGroup<"strncat-size">; +def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">; +def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">; def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; +def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare", + [TautologicalUnsignedZeroCompare, + TautologicalUnsignedEnumZeroCompare, + TautologicalOutOfRangeCompare]>; def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">; def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">; def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">; def TautologicalCompare : DiagGroup<"tautological-compare", - [TautologicalOutOfRangeCompare, + [TautologicalConstantCompare, TautologicalPointerCompare, TautologicalOverlapCompare, TautologicalUndefinedCompare]>; @@ -454,6 +490,8 @@ def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; def SwitchBool : DiagGroup<"switch-bool">; def SwitchEnum : DiagGroup<"switch-enum">; def Switch : DiagGroup<"switch">; +def EnumCompareSwitch : DiagGroup<"enum-compare-switch">; +def EnumCompare : DiagGroup<"enum-compare", [EnumCompareSwitch]>; def ImplicitFallthroughPerFunction : DiagGroup<"implicit-fallthrough-per-function">; def ImplicitFallthrough : DiagGroup<"implicit-fallthrough", @@ -474,10 +512,15 @@ def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>; def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">; +def PragmaPackSuspiciousInclude : DiagGroup<"pragma-pack-suspicious-include">; +def PragmaPack : DiagGroup<"pragma-pack", [PragmaPackSuspiciousInclude]>; def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas, - PragmaClangAttribute]>; + PragmaClangAttribute, PragmaPack]>; def UnknownWarningOption : DiagGroup<"unknown-warning-option">; def NSobjectAttribute : DiagGroup<"NSObject-attribute">; +def NSConsumedMismatch : DiagGroup<"nsconsumed-mismatch">; +def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">; + def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">; def UnknownAttributes : DiagGroup<"unknown-attributes">; def IgnoredAttributes : DiagGroup<"ignored-attributes">; @@ -678,7 +721,8 @@ def Extra : DiagGroup<"extra", [ SemiBeforeMethodBody, MissingMethodReturnType, SignCompare, - UnusedParameter + UnusedParameter, + NullPointerArithmetic ]>; def Most : DiagGroup<"most", [ @@ -707,6 +751,7 @@ def Most : DiagGroup<"most", [ VolatileRegisterVar, ObjCMissingSuperCalls, ObjCDesignatedInit, + ObjCFlexibleArray, OverloadedVirtual, PrivateExtern, SelTypeCast, @@ -772,10 +817,14 @@ def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace, // earlier C++ versions. def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>; -// A warning group for warnings about using C++1z features as extensions in +// A warning group for warnings about using C++17 features as extensions in // earlier C++ versions. def CXX17 : DiagGroup<"c++17-extensions">; +// A warning group for warnings about using C++2a features as extensions in +// earlier C++ versions. +def CXX2a : DiagGroup<"c++2a-extensions">; + def : DiagGroup<"c++0x-extensions", [CXX11]>; def : DiagGroup<"c++1y-extensions", [CXX14]>; def : DiagGroup<"c++1z-extensions", [CXX17]>; @@ -841,6 +890,7 @@ def MicrosoftVoidPseudoDtor : DiagGroup<"microsoft-void-pseudo-dtor">; def MicrosoftAnonTag : DiagGroup<"microsoft-anon-tag">; def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">; def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">; +def MicrosoftInaccessibleBase : DiagGroup<"microsoft-inaccessible-base">; // Aliases. def : DiagGroup<"msvc-include", [MicrosoftInclude]>; // -Wmsvc-include = -Wmicrosoft-include diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index cdd358542a0d..43183a120bb9 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -26,19 +26,36 @@ namespace clang { // Import the diagnostic enums themselves. namespace diag { + // Size of each of the diagnostic categories. + enum { + DIAG_SIZE_COMMON = 300, + DIAG_SIZE_DRIVER = 200, + DIAG_SIZE_FRONTEND = 100, + DIAG_SIZE_SERIALIZATION = 120, + DIAG_SIZE_LEX = 400, + DIAG_SIZE_PARSE = 500, + DIAG_SIZE_AST = 150, + DIAG_SIZE_COMMENT = 100, + DIAG_SIZE_CROSSTU = 100, + DIAG_SIZE_SEMA = 3500, + DIAG_SIZE_ANALYSIS = 100, + DIAG_SIZE_REFACTORING = 1000, + }; // Start position for diagnostics. enum { - DIAG_START_COMMON = 0, - DIAG_START_DRIVER = DIAG_START_COMMON + 300, - DIAG_START_FRONTEND = DIAG_START_DRIVER + 200, - DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100, - DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, - DIAG_START_PARSE = DIAG_START_LEX + 400, - DIAG_START_AST = DIAG_START_PARSE + 500, - DIAG_START_COMMENT = DIAG_START_AST + 110, - DIAG_START_SEMA = DIAG_START_COMMENT + 100, - DIAG_START_ANALYSIS = DIAG_START_SEMA + 3500, - DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 + DIAG_START_COMMON = 0, + DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON, + DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER, + DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND, + DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION, + DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX, + DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE, + DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST, + DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_CROSSTU, + DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_COMMENT, + DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA, + DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS, + DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING }; class CustomDiagInfo; @@ -279,8 +296,8 @@ public: SmallVectorImpl<diag::kind> &Diags) const; /// \brief Get the set of all diagnostic IDs. - void getAllDiagnostics(diag::Flavor Flavor, - SmallVectorImpl<diag::kind> &Diags) const; + static void getAllDiagnostics(diag::Flavor Flavor, + SmallVectorImpl<diag::kind> &Diags); /// \brief Get the diagnostic option with the closest edit distance to the /// given group name. diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 706881bfdc5d..c664281ffcd4 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -31,6 +31,14 @@ def warn_cxx98_compat_less_colon_colon : Warning< "'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx17_compat_spaceship : Warning< + "'<=>' operator is incompatible with C++ standards before C++2a">, + InGroup<CXXPre2aCompat>, DefaultIgnore; +def warn_cxx2a_compat_spaceship : Warning< + "'<=>' is a single token in C++2a; " + "add a space to avoid a change in behavior">, + InGroup<CXX2aCompat>; + // Trigraphs. def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>; def trigraph_ignored_block_comment : Warning< @@ -71,6 +79,8 @@ def ext_token_used : Extension<"extension used">, def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">, InGroup<CXX11Compat>, DefaultIgnore; +def warn_cxx2a_keyword : Warning<"'%0' is a keyword in C++2a">, + InGroup<CXX2aCompat>, DefaultIgnore; def ext_unterminated_char_or_string : ExtWarn< "missing terminating %select{'|'\"'}0 character">, InGroup<InvalidPPToken>; @@ -109,6 +119,9 @@ def err_non_ascii : Error< def ext_unicode_whitespace : ExtWarn< "treating Unicode character as whitespace">, InGroup<DiagGroup<"unicode-whitespace">>; +def warn_utf8_symbol_homoglyph : Warning< + "treating Unicode character <U+%0> as identifier character rather than " + "as '%1' symbol">, InGroup<DiagGroup<"unicode-homoglyph">>; def err_hex_escape_no_digits : Error< "\\%0 used with no following hex digits">; @@ -173,8 +186,6 @@ def warn_char_constant_too_large : Warning< def err_multichar_utf_character_literal : Error< "Unicode character literals may not contain multiple characters">; def err_exponent_has_no_digits : Error<"exponent has no digits">; -def ext_imaginary_constant : Extension< - "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>; def err_hex_constant_requires : Error< "hexadecimal floating %select{constant|literal}0 requires " "%select{an exponent|a significand}1">; @@ -182,17 +193,17 @@ def ext_hex_constant_invalid : Extension< "hexadecimal floating constants are a C99 feature">, InGroup<C99>; def ext_hex_literal_invalid : Extension< "hexadecimal floating literals are a C++17 feature">, InGroup<CXX17>; -def warn_cxx1z_hex_literal : Warning< +def warn_cxx17_hex_literal : Warning< "hexadecimal floating literals are incompatible with " "C++ standards before C++17">, - InGroup<CXXPre1zCompatPedantic>, DefaultIgnore; + InGroup<CXXPre17CompatPedantic>, DefaultIgnore; def ext_binary_literal : Extension< "binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>; def ext_binary_literal_cxx14 : Extension< "binary integer literals are a C++14 extension">, InGroup<CXX14BinaryLiteral>; def warn_cxx11_compat_binary_literal : Warning< "binary integer literals are incompatible with C++ standards before C++14">, - InGroup<CXXPre14CompatPedantic>, DefaultIgnore; + InGroup<CXXPre14CompatBinaryLiteral>, DefaultIgnore; def err_pascal_string_too_long : Error<"Pascal string is too long">; def err_escape_too_large : Error< "%select{hex|octal}0 escape sequence out of range">; @@ -209,7 +220,7 @@ def warn_cxx98_compat_unicode_literal : Warning< InGroup<CXX98Compat>, DefaultIgnore; def warn_cxx14_compat_u8_character_literal : Warning< "unicode literals are incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; + InGroup<CXXPre17Compat>, DefaultIgnore; def warn_cxx11_compat_user_defined_literal : Warning< "identifier after literal will be treated as a user-defined literal suffix " "in C++11">, InGroup<CXX11Compat>, DefaultIgnore; @@ -346,6 +357,23 @@ def ext_pp_extra_tokens_at_eol : ExtWarn< def ext_pp_comma_expr : Extension<"comma operator in operand of #if">; def ext_pp_bad_vaargs_use : Extension< "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">; + +def ext_pp_bad_vaopt_use + : ExtWarn< + "__VA_OPT__ can only appear in the expansion of a variadic macro">, + InGroup<VariadicMacros>; + +def err_pp_missing_lparen_in_vaopt_use : Error< + "missing '(' following __VA_OPT__">; +def err_pp_vaopt_nested_use : Error< + "__VA_OPT__ cannot be nested within its own replacement tokens">; + +def err_vaopt_paste_at_start : Error< + "'##' cannot appear at start of __VA_OPT__ argument">; + +def err_vaopt_paste_at_end + : Error<"'##' cannot appear at end of __VA_OPT__ argument">; + def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">, InGroup<MacroRedefined>; def ext_variadic_macro : Extension<"variadic macros are a C99 feature">, InGroup<VariadicMacros>; @@ -674,6 +702,13 @@ def err_mmap_invalid_header_attribute_value : Error< "expected integer literal as value for header attribute '%0'">; def err_mmap_expected_header_attribute : Error< "expected a header attribute name ('size' or 'mtime')">; +def err_mmap_conflicting_export_as : Error< + "conflicting re-export of module '%0' as '%1' or '%2'">; +def warn_mmap_redundant_export_as : Warning< + "module '%0' already re-exported as '%1'">, + InGroup<PrivateModule>; +def err_mmap_submodule_export_as : Error< + "only top-level modules can be re-exported as public">; def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h index c195003de5c4..3844eb63f0ea 100644 --- a/include/clang/Basic/DiagnosticOptions.h +++ b/include/clang/Basic/DiagnosticOptions.h @@ -100,6 +100,10 @@ public: /// prefixes removed. std::vector<std::string> Remarks; + /// The prefixes for comment directives sought by -verify ("expected" by + /// default). + std::vector<std::string> VerifyPrefixes; + public: // Define accessors/mutators for diagnostic options of enumeration type. #define DIAGOPT(Name, Bits, Default) diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 5170c07bf666..a8d6955da3c0 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -215,7 +215,7 @@ def ext_nested_namespace_definition : ExtWarn< "define each namespace separately">, InGroup<CXX17>; def warn_cxx14_compat_nested_namespace_definition : Warning< "nested namespace definition is incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; + InGroup<CXXPre17Compat>, DefaultIgnore; def err_inline_nested_namespace_definition : Error< "nested namespace definition cannot be 'inline'">; def err_expected_semi_after_attribute_list : Error< @@ -525,13 +525,13 @@ def ext_constexpr_if : ExtWarn< "constexpr if is a C++17 extension">, InGroup<CXX17>; def warn_cxx14_compat_constexpr_if : Warning< "constexpr if is incompatible with C++ standards before C++17">, - DefaultIgnore, InGroup<CXXPre1zCompat>; + DefaultIgnore, InGroup<CXXPre17Compat>; def ext_init_statement : ExtWarn< "'%select{if|switch}0' initialization statements are a C++17 extension">, InGroup<CXX17>; def warn_cxx14_compat_init_statement : Warning< "%select{if|switch}0 initialization statements are incompatible with " - "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre1zCompat>; + "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre17Compat>; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; @@ -558,10 +558,13 @@ def warn_cxx98_compat_noexcept_expr : Warning< def warn_cxx98_compat_nullptr : Warning< "'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; -def warn_cxx14_compat_attribute : Warning< +def ext_ns_enum_attribute : Extension< + "attributes on %select{a namespace|an enumerator}0 declaration are " + "a C++17 extension">, InGroup<CXX17>; +def warn_cxx14_compat_ns_enum_attribute : Warning< "attributes on %select{a namespace|an enumerator}0 declaration are " "incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; + InGroup<CXXPre17CompatPedantic>, DefaultIgnore; def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< @@ -577,7 +580,7 @@ def err_cxx11_attribute_repeated : Error< "attribute %0 cannot appear multiple times in an attribute specifier">; def warn_cxx14_compat_using_attribute_ns : Warning< "default scope specifier for attributes is incompatible with C++ standards " - "before C++17">, InGroup<CXXPre1zCompat>, DefaultIgnore; + "before C++17">, InGroup<CXXPre17Compat>, DefaultIgnore; def ext_using_attribute_ns : ExtWarn< "default scope specifier for attributes is a C++17 extension">, InGroup<CXX17>; @@ -622,7 +625,7 @@ def ext_template_template_param_typename : ExtWarn< def warn_cxx14_compat_template_template_param_typename : Warning< "template template parameter using 'typename' is " "incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; + InGroup<CXXPre17Compat>, DefaultIgnore; def err_template_spec_syntax_non_template : Error< "identifier followed by '<' indicates a class template specialization but " "%0 %select{does not refer to a template|refers to a function template|" @@ -699,7 +702,7 @@ def ext_fold_expression : ExtWarn< InGroup<CXX17>; def warn_cxx14_compat_fold_expression : Warning< "pack fold expression is incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; + InGroup<CXXPre17Compat>, DefaultIgnore; def err_expected_fold_operator : Error< "expected a foldable binary operator in fold expression">; def err_fold_operator_mismatch : Error< @@ -730,8 +733,12 @@ def ext_nonstatic_member_init : ExtWarn< def warn_cxx98_compat_nonstatic_member_init : Warning< "in-class initialization of non-static data members is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; -def err_bitfield_member_init: Error< - "bit-field member cannot have an in-class initializer">; +def ext_bitfield_member_init: ExtWarn< + "default member initializer for bit-field is a C++2a extension">, + InGroup<CXX2a>; +def warn_cxx17_compat_bitfield_member_init: Warning< + "default member initializer for bit-field is incompatible with " + "C++ standards before C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore; def err_incomplete_array_member_init: Error< "array bound cannot be deduced from an in-class initializer">; @@ -748,19 +755,19 @@ def err_alias_declaration_specialization : Error< def err_alias_declaration_pack_expansion : Error< "alias declaration cannot be a pack expansion">; -// C++1z using-declaration pack expansions +// C++17 using-declaration pack expansions def ext_multi_using_declaration : ExtWarn< "use of multiple declarators in a single using declaration is " "a C++17 extension">, InGroup<CXX17>; -def warn_cxx1z_compat_multi_using_declaration : Warning< +def warn_cxx17_compat_multi_using_declaration : Warning< "use of multiple declarators in a single using declaration is " "incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; + InGroup<CXXPre17Compat>, DefaultIgnore; def ext_using_declaration_pack : ExtWarn< "pack expansion of using declaration is a C++17 extension">, InGroup<CXX17>; -def warn_cxx1z_compat_using_declaration_pack : Warning< +def warn_cxx17_compat_using_declaration_pack : Warning< "pack expansion using declaration is incompatible with C++ standards " - "before C++17">, InGroup<CXXPre1zCompat>, DefaultIgnore; + "before C++17">, InGroup<CXXPre17Compat>, DefaultIgnore; // C++11 override control def ext_override_control_keyword : ExtWarn< @@ -811,15 +818,15 @@ def err_lambda_missing_parens : Error< "attribute specifier|'constexpr'}0">; def err_lambda_decl_specifier_repeated : Error< "%select{'mutable'|'constexpr'}0 cannot appear multiple times in a lambda declarator">; -// C++1z lambda expressions +// C++17 lambda expressions def err_expected_star_this_capture : Error< "expected 'this' following '*' in lambda capture list">; -// C++1z constexpr lambda expressions +// C++17 constexpr lambda expressions def warn_cxx14_compat_constexpr_on_lambda : Warning< "constexpr on lambda expressions is incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; -def ext_constexpr_on_lambda_cxx1z : ExtWarn< + InGroup<CXXPre17Compat>, DefaultIgnore; +def ext_constexpr_on_lambda_cxx17 : ExtWarn< "'constexpr' on lambda expressions is a C++17 extension">, InGroup<CXX17>; // Availability attribute @@ -893,8 +900,6 @@ def err_pragma_expected_clang_section_name : Error< "expected one of [bss|data|rodata|text] section kind in '#pragma %0'">; def err_pragma_clang_section_expected_equal : Error< "expected '=' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">; -def err_pragma_clang_section_expected_name_or_clear : Error< - "expected section name or '\"\"' following '#pragma clang section %select{invalid|bss|data|rodata|text}0'">; def warn_pragma_expected_section_name : Warning< "expected a string literal for the section name in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>; diff --git a/include/clang/Basic/DiagnosticRefactoringKinds.td b/include/clang/Basic/DiagnosticRefactoringKinds.td new file mode 100644 index 000000000000..ee396b930729 --- /dev/null +++ b/include/clang/Basic/DiagnosticRefactoringKinds.td @@ -0,0 +1,34 @@ +//==--- DiagnosticRefactoringKinds.td - refactoring diagnostics -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Refactoring Diagnostics +//===----------------------------------------------------------------------===// + +let Component = "Refactoring" in { + +let CategoryName = "Refactoring Invocation Issue" in { + +def err_refactor_no_selection : Error<"refactoring action can't be initiated " + "without a selection">; +def err_refactor_selection_no_symbol : Error<"there is no symbol at the given " + "location">; +def err_refactor_selection_invalid_ast : Error<"the provided selection does " + "not overlap with the AST nodes of interest">; + +def err_refactor_code_outside_of_function : Error<"the selected code is not a " + "part of a function's / method's body">; +def err_refactor_extract_simple_expression : Error<"the selected expression " + "is too simple to extract">; +def err_refactor_extract_prohibited_expression : Error<"the selected " + "expression can't be extracted">; + +} + +} // end of Refactoring diagnostics diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 8dc6e7b460e8..29236eab5446 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -141,6 +141,10 @@ def err_vla_decl_has_extern_linkage : Error< "variable length array declaration cannot have 'extern' linkage">; def ext_vla_folded_to_constant : Extension< "variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>; +def err_vla_unsupported : Error< + "variable length arrays are not supported for the current target">; +def note_vla_unsupported : Note< + "variable length arrays are not supported for the current target">; // C99 variably modified types def err_variably_modified_template_arg : Error< @@ -194,6 +198,8 @@ def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">, InGroup<DuplicateDeclSpecifier>; def ext_plain_complex : ExtWarn< "plain '_Complex' requires a type specifier; assuming '_Complex double'">; +def ext_imaginary_constant : Extension< + "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>; def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>; @@ -293,8 +299,20 @@ def warn_empty_parens_are_function_decl : Warning< def warn_parens_disambiguated_as_function_declaration : Warning< "parentheses were disambiguated as a function declaration">, InGroup<VexingParse>; +def warn_parens_disambiguated_as_variable_declaration : Warning< + "parentheses were disambiguated as redundant parentheses around declaration " + "of variable named %0">, InGroup<VexingParse>; +def warn_redundant_parens_around_declarator : Warning< + "redundant parentheses surrounding declarator">, + InGroup<DiagGroup<"redundant-parens">>, DefaultIgnore; def note_additional_parens_for_variable_declaration : Note< "add a pair of parentheses to declare a variable">; +def note_raii_guard_add_name : Note< + "add a variable name to declare a %0 initialized with %1">; +def note_function_style_cast_add_parentheses : Note< + "add enclosing parentheses to perform a function-style cast">; +def note_remove_parens_for_variable_declaration : Note< + "remove parentheses to silence this warning">; def note_empty_parens_function_call : Note< "change this ',' to a ';' to call %0">; def note_empty_parens_default_ctor : Note< @@ -341,7 +359,7 @@ def warn_implicit_function_decl : Warning< "implicit declaration of function %0">, InGroup<ImplicitFunctionDeclare>, DefaultIgnore; def ext_implicit_function_decl : ExtWarn< - "implicit declaration of function %0 is invalid in C99">, + "implicit declaration of function %0 is invalid in %select{C99|OpenCL}1">, InGroup<ImplicitFunctionDeclare>; def note_function_suggestion : Note<"did you mean %0?">; @@ -352,8 +370,10 @@ def err_language_linkage_spec_unknown : Error<"unknown linkage language">; def err_language_linkage_spec_not_ascii : Error< "string literal in language linkage specifier cannot have an " "encoding-prefix">; -def warn_use_out_of_scope_declaration : Warning< - "use of out-of-scope declaration of %0">; +def ext_use_out_of_scope_declaration : ExtWarn< + "use of out-of-scope declaration of %0%select{| whose type is not " + "compatible with that of an implicit declaration}1">, + InGroup<DiagGroup<"out-of-scope-function">>; def err_inline_non_function : Error< "'inline' can only appear on functions%select{| and non-local variables}0">; def err_noreturn_non_function : Error< @@ -391,9 +411,12 @@ def err_decomp_decl_context : Error< "decomposition declaration not permitted in this context">; def warn_cxx14_compat_decomp_decl : Warning< "decomposition declarations are incompatible with " - "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre1zCompat>; + "C++ standards before C++17">, DefaultIgnore, InGroup<CXXPre17Compat>; def ext_decomp_decl : ExtWarn< "decomposition declarations are a C++17 extension">, InGroup<CXX17>; +def ext_decomp_decl_cond : ExtWarn< + "ISO C++17 does not permit structured binding declaration in a condition">, + InGroup<DiagGroup<"binding-in-condition">>; def err_decomp_decl_spec : Error< "decomposition declaration cannot be declared " "%plural{1:'%1'|:with '%1' specifiers}0">; @@ -505,7 +528,7 @@ def warn_deprecated_copy_operation : Warning< "for %0 is deprecated because it has a user-declared " "%select{copy %select{assignment operator|constructor}1|destructor}2">, InGroup<Deprecated>, DefaultIgnore; -def warn_cxx1z_compat_exception_spec_in_signature : Warning< +def warn_cxx17_compat_exception_spec_in_signature : Warning< "mangled name of %0 will change in C++17 due to non-throwing exception " "specification in function signature">, InGroup<CXX17CompatMangling>; @@ -581,6 +604,7 @@ def warn_redecl_library_builtin : Warning< def err_builtin_definition : Error<"definition of 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_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 " @@ -712,6 +736,19 @@ def err_pragma_options_align_mac68k_target_unsupported : Error< def warn_pragma_pack_invalid_alignment : Warning< "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">, InGroup<IgnoredPragmas>; +def warn_pragma_pack_non_default_at_include : Warning< + "non-default #pragma pack value changes the alignment of struct or union " + "members in the included file">, InGroup<PragmaPackSuspiciousInclude>, + DefaultIgnore; +def warn_pragma_pack_modified_after_include : Warning< + "the current #pragma pack aligment value is modified in the included " + "file">, InGroup<PragmaPack>; +def warn_pragma_pack_no_pop_eof : Warning<"unterminated " + "'#pragma pack (push, ...)' at end of file">, InGroup<PragmaPack>; +def note_pragma_pack_here : Note< + "previous '#pragma pack' directive that modifies alignment is here">; +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< @@ -1195,21 +1232,27 @@ def err_objc_method_unsupported_param_ret_type : Error< "%0 %select{parameter|return}1 type is unsupported; " "support for vector types for this target is introduced in %2">; +def warn_messaging_unqualified_id : Warning< + "messaging unqualified id">, DefaultIgnore, + InGroup<DiagGroup<"objc-messaging-id">>; + // C++ declarations def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">; +def err_static_assert_requirement_failed : Error< + "static_assert failed due to requirement '%0'%select{ %2|}1">; def ext_static_assert_no_message : ExtWarn< "static_assert with no message is a C++17 extension">, InGroup<CXX17>; def warn_cxx14_compat_static_assert_no_message : Warning< "static_assert with no message is incompatible with C++ standards before C++17">, - DefaultIgnore, InGroup<CXXPre1zCompat>; + DefaultIgnore, InGroup<CXXPre17Compat>; def ext_inline_variable : ExtWarn< "inline variables are a C++17 extension">, InGroup<CXX17>; def warn_cxx14_compat_inline_variable : Warning< "inline variables are incompatible with C++ standards before C++17">, - DefaultIgnore, InGroup<CXXPre1zCompat>; + DefaultIgnore, InGroup<CXXPre17Compat>; def warn_inline_namespace_reopened_noninline : Warning< "inline namespace reopened as a non-inline namespace">; @@ -1313,6 +1356,8 @@ def err_type_defined_in_alias_template : Error< "%0 cannot be defined in a type alias template">; def err_type_defined_in_condition : Error< "%0 cannot be defined in a condition">; +def err_type_defined_in_enum : Error< + "%0 cannot be defined in an enumeration">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; @@ -1637,6 +1682,11 @@ def err_conflicting_overriding_cc_attributes : Error< "virtual function %0 has different calling convention attributes " "%diff{($) than the function it overrides (which has calling convention $)|" "than the function it overrides}1,2">; +def warn_overriding_method_missing_noescape : Warning< + "parameter of overriding method should be annotated with " + "__attribute__((noescape))">, InGroup<MissingNoEscape>; +def note_overridden_marked_noescape : Note< + "parameter of overridden method is annotated with __attribute__((noescape))">; def err_covariant_return_inaccessible_base : Error< "invalid covariant return for virtual function: %1 is a " @@ -1938,8 +1988,9 @@ def err_auto_var_requires_init : Error< "declaration of variable %0 with deduced type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< "new expression for type %0 requires a constructor argument">; -def err_auto_new_list_init : Error< - "new expression for type %0 cannot use list-initialization">; +def ext_auto_new_list_init : Extension< + "ISO C++ standards before C++17 do not allow new expression for " + "type %0 to use list-initialization">, InGroup<CXX17>; def err_auto_var_init_no_expression : Error< "initializer for variable %0 with type %1 is empty">; def err_auto_var_init_multiple_expressions : Error< @@ -1964,6 +2015,9 @@ def err_auto_var_deduction_failure_from_init_list : Error< "cannot deduce actual type for variable %0 with type %1 from initializer list">; def err_auto_new_deduction_failure : Error< "new expression for type %0 has incompatible constructor argument of type %1">; +def err_auto_inconsistent_deduction : Error< + "deduced conflicting types %diff{($ vs $) |}0,1" + "for initializer list element type">; def err_auto_different_deductions : Error< "%select{'auto'|'decltype(auto)'|'__auto_type'|template arguments}0 " "deduced as %1 in declaration of %2 and " @@ -1999,7 +2053,7 @@ def err_decltype_auto_compound_type : Error< def err_decltype_auto_initializer_list : Error< "cannot deduce 'decltype(auto)' from initializer list">; -// C++1z deduced class template specialization types +// C++17 deduced class template specialization types def err_deduced_class_template_compound_type : Error< "cannot %select{form pointer to|form reference to|form array of|" "form function returning|use parentheses when declaring variable with}0 " @@ -2151,7 +2205,7 @@ def ext_for_range_begin_end_types_differ : ExtWarn< InGroup<CXX17>; def warn_for_range_begin_end_types_differ : Warning< "'begin' and 'end' returning different types (%0 and %1) is incompatible " - "with C++ standards before C++17">, InGroup<CXXPre1zCompat>, DefaultIgnore; + "with C++ standards before C++17">, InGroup<CXXPre17Compat>, DefaultIgnore; def note_in_for_range: Note< "when looking up '%select{begin|end}0' function for range expression " "of type %1">; @@ -2387,8 +2441,9 @@ 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 unsupported '%0' in the target attribute string">, - InGroup<IgnoredAttributes>; + : Warning<"ignoring %select{unsupported|duplicate}0" + "%select{| architecture}1 '%2' in the target attribute string">, + InGroup<IgnoredAttributes>; def err_attribute_unsupported : Error<"%0 attribute is not supported for this target">; // The err_*_attribute_argument_not_int are separate because they're used by @@ -2587,6 +2642,8 @@ def err_attribute_section_invalid_for_target : Error< "argument to 'section' attribute is not valid for this target: %0">; def warn_mismatched_section : Warning< "section 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_anonymous_property: Error< "anonymous property is not supported">; @@ -2729,7 +2786,7 @@ def err_attribute_weakref_not_global_context : Error< def err_attribute_weakref_without_alias : Error< "weakref declaration of %0 must also have an alias attribute">; def err_alias_not_supported_on_darwin : Error < - "only weak aliases are supported on darwin">; + "aliases are not supported on darwin">; def err_alias_to_undefined : Error< "%select{alias|ifunc}0 must point to a defined %select{variable or |}1function">; def warn_alias_to_weak_alias : Warning< @@ -2746,55 +2803,26 @@ def err_ifunc_resolver_return : Error< "ifunc resolver function must return a pointer">; def err_ifunc_resolver_params : Error< "ifunc resolver function must have no parameters">; +def warn_attribute_wrong_decl_type_str : Warning< + "%0 attribute only applies to %1">, InGroup<IgnoredAttributes>; +def err_attribute_wrong_decl_type_str : Error< + warn_attribute_wrong_decl_type_str.Text>; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{" "functions" "|unions" "|variables and functions" - "|functions and global variables" - "|functions, variables, and Objective-C interfaces" "|functions and methods" - "|parameters" "|functions, methods and blocks" - "|functions, methods, and classes" "|functions, methods, and parameters" - "|functions, methods, and global variables" - "|classes" - "|enums" "|variables" - "|methods" - "|fields and global variables" - "|structs" - "|parameters and typedefs" - "|variables and typedefs" - "|thread-local variables" "|variables and fields" "|variables, data members and tag types" "|types and namespaces" - "|Objective-C interfaces" - "|methods and properties" - "|functions, methods, and properties" - "|struct or union" - "|struct, union or class" - "|types" - "|Objective-C instance methods" - "|init methods of interface or class extension declarations" "|variables, functions and classes" - "|functions, variables, classes, and Objective-C interfaces" - "|Objective-C protocols" - "|variables with static or thread storage duration" - "|functions, methods, properties, and global variables" - "|structs, unions, and typedefs" - "|structs and typedefs" - "|interface or protocol declarations" "|kernel functions" "|non-K&R-style functions" - "|variables, enums, fields and typedefs" - "|functions, methods, enums, and classes" - "|structs, classes, variables, functions, and inline namespaces" - "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members" - "|classes and enumerations" - "|named declarations}1">, + "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members}1">, InGroup<IgnoredAttributes>; def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>; def warn_type_attribute_wrong_type : Warning< @@ -2879,25 +2907,11 @@ def warn_unguarded_availability : def warn_unguarded_availability_new : Warning<warn_unguarded_availability.Text>, InGroup<UnguardedAvailabilityNew>; -def warn_partial_availability : Warning<"%0 is only available conditionally">, - InGroup<UnguardedAvailability>, DefaultIgnore; -def warn_partial_availability_new : Warning<warn_partial_availability.Text>, - InGroup<UnguardedAvailabilityNew>; -def note_partial_availability_silence : Note< - "annotate %select{%1|anonymous %1}0 with an availability attribute to silence">; +def note_decl_unguarded_availability_silence : Note< + "annotate %select{%1|anonymous %1}0 with an availability attribute to silence this warning">; def note_unguarded_available_silence : Note< "enclose %0 in %select{an @available|a __builtin_available}1 check to silence" " this warning">; -def warn_partial_message : Warning<"%0 is partial: %1">, - InGroup<UnguardedAvailability>, DefaultIgnore; -def warn_partial_message_new : Warning<warn_partial_message.Text>, - InGroup<UnguardedAvailabilityNew>; -def warn_partial_fwdclass_message : Warning< - "%0 may be partial because the receiver type is unknown">, - InGroup<UnguardedAvailability>, DefaultIgnore; -def warn_partial_fwdclass_message_new : - Warning<warn_partial_fwdclass_message.Text>, - InGroup<UnguardedAvailabilityNew>; def warn_at_available_unchecked_use : Warning< "%select{@available|__builtin_available}0 does not guard availability here; " "use if (%select{@available|__builtin_available}0) instead">, @@ -3063,6 +3077,8 @@ def warn_impcast_vector_scalar : Warning< def warn_impcast_complex_scalar : Warning< "implicit conversion discards imaginary component: %0 to %1">, InGroup<Conversion>, DefaultIgnore; +def err_impcast_complex_scalar : Error< + "implicit conversion from %0 to %1 is not permitted in C++">; def warn_impcast_float_precision : Warning< "implicit conversion loses floating-point precision: %0 to %1">, InGroup<Conversion>, DefaultIgnore; @@ -3188,6 +3204,9 @@ def warn_int_to_void_pointer_cast : Warning< "cast to %1 from smaller integer type %0">, InGroup<IntToVoidPointerCast>; +def warn_attribute_ignored_for_field_of_type : Warning< + "%0 attribute ignored for field of type %1">, + InGroup<IgnoredAttributes>; def warn_no_underlying_type_specified_for_enum_bitfield : Warning< "enums in the Microsoft ABI are signed integers by default; consider giving " "the enum %0 an unsigned underlying type to make this code portable">, @@ -3906,7 +3925,7 @@ def err_template_nontype_parm_bad_type : Error< def warn_cxx14_compat_template_nontype_parm_auto_type : Warning< "non-type template parameters declared with %0 are incompatible with C++ " "standards before C++17">, - DefaultIgnore, InGroup<CXXPre1zCompat>; + DefaultIgnore, InGroup<CXXPre17Compat>; def err_template_param_default_arg_redefinition : Error< "template parameter redefines default argument">; def note_template_param_prev_default_arg : Note< @@ -4080,6 +4099,13 @@ def err_pointer_to_member_call_drops_quals : Error< def err_pointer_to_member_oper_value_classify: Error< "pointer-to-member function type %0 can only be called on an " "%select{rvalue|lvalue}1">; +def ext_pointer_to_const_ref_member_on_rvalue : Extension< + "invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension">, + InGroup<CXX2a>, SFINAEFailure; +def warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : Warning< + "invoking a pointer to a 'const &' member function on an rvalue is " + "incompatible with C++ standards before C++2a">, + InGroup<CXXPre2aCompatPedantic>, DefaultIgnore; def ext_ms_deref_template_argument: ExtWarn< "non-type template argument containing a dereference operation is a " "Microsoft extension">, InGroup<MicrosoftTemplate>; @@ -4681,6 +4707,14 @@ def note_deleted_assign_field : Note< def warn_undefined_internal : Warning< "%select{function|variable}0 %q1 has internal linkage but is not defined">, InGroup<DiagGroup<"undefined-internal">>; +def err_undefined_internal_type : Error< + "%select{function|variable}0 %q1 is used but not defined in this " + "translation unit, and cannot be defined in any other translation unit " + "because its type does not have linkage">; +def ext_undefined_internal_type : Extension< + "ISO C++ requires a definition in this translation unit for " + "%select{function|variable}0 %q1 because its type does not have linkage">, + InGroup<DiagGroup<"undefined-internal-type">>; def warn_undefined_inline : Warning<"inline function %q0 is not defined">, InGroup<DiagGroup<"undefined-inline">>; def err_undefined_inline_var : Error<"inline variable %q0 is not defined">; @@ -4746,6 +4780,9 @@ def err_thread_non_thread : Error< def err_thread_thread_different_kind : Error< "thread-local declaration of %0 with %select{static|dynamic}1 initialization " "follows declaration with %select{dynamic|static}1 initialization">; +def err_mismatched_owning_module : Error< + "declaration of %0 in %select{the global module|module %2}1 follows " + "declaration in %select{the global module|module %4}3">; def err_redefinition_different_type : Error< "redefinition of %0 with a different type%diff{: $ vs $|}1,2">; def err_redefinition_different_kind : Error< @@ -5164,6 +5201,28 @@ def ext_flexible_array_empty_aggregate_gnu : Extension< def ext_flexible_array_union_gnu : Extension< "flexible array member %0 in a union is a GNU extension">, InGroup<GNUFlexibleArrayUnionMember>; +def err_flexible_array_not_at_end : Error< + "flexible array member %0 with type %1 is not at the end of" + " %select{struct|interface|union|class|enum}2">; +def err_objc_variable_sized_type_not_at_end : Error< + "field %0 with variable sized type %1 is not at the end of class">; +def note_next_field_declaration : Note< + "next field declaration is here">; +def note_next_ivar_declaration : Note< + "next %select{instance variable declaration|synthesized instance variable}0" + " is here">; +def err_synthesize_variable_sized_ivar : Error< + "synthesized property with variable size type %0" + " requires an existing instance variable">; +def err_flexible_array_arc_retainable : Error< + "ARC forbids flexible array members with retainable object type">; +def warn_variable_sized_ivar_visibility : Warning< + "field %0 with variable sized type %1 is not visible to subclasses and" + " can conflict with their instance variables">, InGroup<ObjCFlexibleArray>; +def warn_superclass_variable_sized_type_not_at_end : Warning< + "field %0 can overwrite instance variable %1 with variable sized type %2" + " in superclass %3">, InGroup<ObjCFlexibleArray>; + let CategoryName = "ARC Semantic Issue" in { // ARC-mode diagnostics. @@ -5462,9 +5521,6 @@ def err_offsetof_incomplete_type : Error< def err_offsetof_record_type : Error< "offsetof requires struct, union, or class type, %0 invalid">; def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">; -def ext_offsetof_extended_field_designator : Extension< - "using extended field designator is an extension">, - InGroup<DiagGroup<"extended-offsetof">>; def ext_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">, InGroup<InvalidOffsetof>; def ext_offsetof_non_standardlayout_type : ExtWarn< @@ -5475,6 +5531,12 @@ def err_offsetof_field_of_virtual_base : Error< def warn_sub_ptr_zero_size_types : Warning< "subtraction of pointers to type %0 of zero size has undefined behavior">, InGroup<PointerArith>; +def warn_pointer_arith_null_ptr : Warning< + "performing pointer arithmetic on a null pointer has undefined behavior%select{| if the offset is nonzero}0">, + InGroup<NullPointerArithmetic>, DefaultIgnore; +def warn_gnu_null_ptr_arith : Warning< + "arithmetic on a null pointer treated as a cast from integer to pointer is a GNU extension">, + InGroup<NullPointerArithmetic>, DefaultIgnore; def warn_floatingpoint_eq : Warning< "comparing floating point with == or != is unsafe">, @@ -5862,6 +5924,8 @@ def err_typecheck_assign_const : Error< "cannot assign to %select{non-|}1static data member %2 " "with const-qualified type %3|" "cannot assign to non-static data member within const member function %1|" + "cannot assign to %select{variable %2|non-static data member %2|lvalue}1 " + "with %select{|nested }3const-qualified data member %4|" "read-only variable is not assignable}0">; def note_typecheck_assign_const : Note< @@ -5869,25 +5933,39 @@ def note_typecheck_assign_const : Note< "function %1 which returns const-qualified type %2 declared here|" "variable %1 declared const here|" "%select{non-|}1static data member %2 declared const here|" - "member function %q1 is declared const here}0">; + "member function %q1 is declared const here|" + "%select{|nested }1data member %2 declared const here}0">; + +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>; +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>; +def warn_tautological_constant_compare : Warning< + "result of comparison %select{%3|%1}0 %2 " + "%select{%1|%3}0 is always %4">, + InGroup<TautologicalConstantCompare>; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, InGroup<SignCompare>, DefaultIgnore; -def warn_lunsigned_always_true_comparison : Warning< - "comparison of unsigned%select{| enum}2 expression %0 is always %1">, - InGroup<TautologicalCompare>; def warn_out_of_range_compare : Warning< - "comparison of %select{constant %0|true|false}1 with " - "%select{expression of type %2|boolean expression}3 is always " - "%select{false|true}4">, InGroup<TautologicalOutOfRangeCompare>; -def warn_runsigned_always_true_comparison : Warning< - "comparison of %0 unsigned%select{| enum}2 expression is always %1">, - InGroup<TautologicalCompare>; + "result of comparison of %select{constant %0|true|false}1 with " + "%select{expression of type %2|boolean expression}3 is always %4">, + InGroup<TautologicalOutOfRangeCompare>; +def warn_tautological_bool_compare : Warning<warn_out_of_range_compare.Text>, + InGroup<TautologicalConstantCompare>; def warn_comparison_of_mixed_enum_types : Warning< "comparison of two values with different enumeration types" "%diff{ ($ and $)|}0,1">, - InGroup<DiagGroup<"enum-compare">>; + InGroup<EnumCompare>; +def warn_comparison_of_mixed_enum_types_switch : Warning< + "comparison of two values with different enumeration types in switch statement" + "%diff{ ($ and $)|}0,1">, + InGroup<EnumCompareSwitch>; def warn_null_in_arithmetic_operation : Warning< "use of NULL in arithmetic operation">, InGroup<NullArithmetic>; @@ -6391,12 +6469,12 @@ def warn_non_virtual_dtor : Warning< def warn_delete_non_virtual_dtor : Warning< "%select{delete|destructor}0 called on non-final %1 that has " "virtual functions but non-virtual destructor">, - InGroup<DeleteNonVirtualDtor>, DefaultIgnore; + InGroup<DeleteNonVirtualDtor>, DefaultIgnore, ShowInSystemHeader; def note_delete_non_virtual : Note< "qualify call to silence this warning">; def warn_delete_abstract_non_virtual_dtor : Warning< "%select{delete|destructor}0 called on %1 that is abstract but has " - "non-virtual destructor">, InGroup<DeleteNonVirtualDtor>; + "non-virtual destructor">, InGroup<DeleteNonVirtualDtor>, ShowInSystemHeader; def warn_overloaded_virtual : Warning< "%q0 hides overloaded virtual %select{function|functions}1">, InGroup<OverloadedVirtual>, DefaultIgnore; @@ -6420,8 +6498,8 @@ def warn_overaligned_type : Warning< "guarantees %2 bytes">, InGroup<OveralignedType>, DefaultIgnore; def warn_aligned_allocation_unavailable :Warning< - "aligned %select{allocation|deallocation}0 function of type '%1' possibly " - "unavailable on %2">, InGroup<AlignedAllocationUnavailable>, DefaultError; + "aligned %select{allocation|deallocation}0 function of type '%1' is only " + "available on %2 %3 or newer">, InGroup<AlignedAllocationUnavailable>, DefaultError; def note_silence_unligned_allocation_unavailable : Note< "if you supply your own aligned allocation functions, use " "-Wno-aligned-allocation-unavailable to silence this diagnostic">; @@ -6458,8 +6536,6 @@ let CategoryName = "Lambda Issue" in { "%0 can appear only once in a capture list">; def err_reference_capture_with_reference_default : Error< "'&' cannot precede a capture when the capture default is '&'">; - def err_this_capture_with_copy_default : Error< - "'this' cannot be explicitly captured when the capture default is '='">; def err_copy_capture_with_copy_default : Error< "'&' must precede a capture when the capture default is '='">; def err_capture_does_not_name_variable : Error< @@ -6526,12 +6602,20 @@ let CategoryName = "Lambda Issue" in { def err_init_capture_deduction_failure_from_init_list : Error< "cannot deduce type for lambda capture %0 from initializer list">; - // C++1z '*this' captures. + // C++17 '*this' captures. def warn_cxx14_compat_star_this_lambda_capture : Warning< "by value capture of '*this' is incompatible with C++ standards before C++17">, - InGroup<CXXPre1zCompat>, DefaultIgnore; - def ext_star_this_lambda_capture_cxx1z : ExtWarn< + InGroup<CXXPre17Compat>, DefaultIgnore; + def ext_star_this_lambda_capture_cxx17 : ExtWarn< "capture of '*this' by copy is a C++17 extension">, InGroup<CXX17>; + + // C++2a [=, this] captures. + def warn_cxx17_compat_equals_this_lambda_capture : Warning< + "explicit capture of 'this' with a capture default of '=' is incompatible " + "with C++ standards before C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore; + 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 err_return_in_captured_stmt : Error< @@ -6981,8 +7065,8 @@ def err_atomic_op_needs_atomic : Error< "address argument to atomic operation must be a pointer to _Atomic " "type (%0 invalid)">; def err_atomic_op_needs_non_const_atomic : Error< - "address argument to atomic operation must be a pointer to non-const _Atomic " - "type (%0 invalid)">; + "address argument to atomic operation must be a pointer to non-%select{const|constant}0 _Atomic " + "type (%1 invalid)">; def err_atomic_op_needs_non_const_pointer : Error< "address argument to atomic operation must be a pointer to non-const " "type (%0 invalid)">; @@ -6998,6 +7082,8 @@ def err_atomic_op_bitwise_needs_atomic_int : Error< def warn_atomic_op_has_invalid_memory_order : Warning< "memory order argument to atomic operation is invalid">, InGroup<DiagGroup<"atomic-memory-ordering">>; +def err_atomic_op_has_invalid_synch_scope : Error< + "synchronization scope argument to atomic operation is invalid">; def err_overflow_builtin_must_be_int : Error< "operand argument to overflow builtin must be an integer (%0 invalid)">; @@ -7199,11 +7285,11 @@ def warn_unused_volatile : Warning< def ext_cxx14_attr : Extension< "use of the %0 attribute is a C++14 extension">, InGroup<CXX14>; -def ext_cxx1z_attr : Extension< +def ext_cxx17_attr : Extension< "use of the %0 attribute is a C++17 extension">, InGroup<CXX17>; def warn_unused_comparison : Warning< - "%select{%select{|in}1equality|relational}0 comparison result unused">, + "%select{equality|inequality|relational|three-way}0 comparison result unused">, InGroup<UnusedComparison>; def note_inequality_comparison_to_or_assign : Note< "use '|=' to turn this inequality comparison into an or-assignment">; @@ -7315,8 +7401,8 @@ def err_invalid_conversion_between_vector_and_integer : Error< def err_opencl_function_pointer : Error< "pointers to functions are not allowed">; -def err_opencl_taking_function_address : Error< - "taking address of function is not allowed">; +def err_opencl_taking_address_capture : Error< + "taking address of a capture is not allowed">; def err_invalid_conversion_between_vector_and_scalar : Error< "invalid conversion between vector type %0 and scalar type %1">; @@ -7457,6 +7543,9 @@ def err_ambiguous_derived_to_base_conv : Error< def err_ambiguous_memptr_conv : Error< "ambiguous conversion from pointer to member of %select{base|derived}0 " "class %1 to pointer to member of %select{derived|base}0 class %2:%3">; +def ext_ms_ambiguous_direct_base : ExtWarn< + "accessing inaccessible direct base %0 of %1 is a Microsoft extension">, + InGroup<MicrosoftInaccessibleBase>; def err_memptr_conv_via_virtual : Error< "conversion from pointer to member of class %0 to pointer to member " @@ -7526,6 +7615,11 @@ def err_operator_delete_dependent_param_type : Error< "%0 cannot take a dependent type as first parameter; use %1 instead">; def err_operator_delete_param_type : Error< "first parameter of %0 must have type %1">; +def err_destroying_operator_delete_not_usual : Error< + "destroying operator delete can have only an optional size and optional " + "alignment parameter">; +def note_implicit_delete_this_in_destructor_here : Note< + "while checking implicit 'delete this' for virtual destructor">; // C++ literal operators def err_literal_operator_outside_namespace : Error< @@ -7831,6 +7925,8 @@ def err_type_tag_for_datatype_too_large : Error< "'type_tag_for_datatype' attribute requires the initializer to be " "an %select{integer|integral}0 constant expression " "that can be represented by a 64 bit integer">; +def err_tag_index_out_of_range : Error< + "%select{type tag|argument}0 index %1 is greater than the number of arguments specified">; def warn_type_tag_for_datatype_wrong_kind : Warning< "this type tag was not designed to be used with this function">, InGroup<TypeSafety>; @@ -7868,6 +7964,8 @@ def err_builtin_annotation_first_arg : Error< "first argument to __builtin_annotation must be an integer">; def err_builtin_annotation_second_arg : Error< "second argument to __builtin_annotation must be a non-wide string constant">; +def err_msvc_annotation_wide_str : Error< + "arguments to __annotation must be wide string constants">; // CFString checking def err_cfstring_literal_not_string_constant : Error< @@ -8195,12 +8293,12 @@ 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 err_nsconsumed_attribute_mismatch : Error< +def warn_nsconsumed_attribute_mismatch : Warning< "overriding method has mismatched ns_consumed attribute on its" - " parameter">; -def err_nsreturns_retained_attribute_mismatch : Error< + " parameter">, InGroup<NSConsumedMismatch>; +def warn_nsreturns_retained_attribute_mismatch : Warning< "overriding method has mismatched ns_returns_%select{not_retained|retained}0" - " attributes">; + " attributes">, InGroup<NSReturnsMismatch>; def note_getter_unavailable : Note< "or because setter is declared here, but no getter method %0 is found">; @@ -8364,8 +8462,6 @@ def err_opencl_scalar_type_rank_greater_than_vector_type : Error< "element. (%0 and %1)">; def err_bad_kernel_param_type : Error< "%0 cannot be used as the type of a kernel parameter">; -def err_opencl_implicit_function_decl : Error< - "implicit declaration of function %0 is invalid in OpenCL">; def err_record_with_pointers_kernel_param : Error< "%select{struct|union}0 kernel parameters may not contain pointers">; def note_within_field_of_type : Note< @@ -8518,6 +8614,8 @@ def err_omp_expected_var_name_member_expr : Error< "expected variable name%select{| or data member of current class}0">; def err_omp_expected_var_name_member_expr_or_array_item : Error< "expected variable name%select{|, data member of current class}0, array element or array section">; +def err_omp_expected_addressable_lvalue_or_array_item : Error< + "expected addressable lvalue expression, array element or array section">; def err_omp_expected_named_var_member_or_array_expression: Error< "expected expression containing only member accesses and/or array sections based on named variables">; def err_omp_bit_fields_forbidden_in_clause : Error< @@ -8525,7 +8623,7 @@ def err_omp_bit_fields_forbidden_in_clause : Error< def err_array_section_does_not_specify_contiguous_storage : Error< "array section does not specify contiguous storage">; def err_omp_union_type_not_allowed : Error< - "mapped storage cannot be derived from a union">; + "mapping of union members is not allowed">; def err_omp_expected_access_to_data_field : Error< "expected access to data field">; def err_omp_multiple_array_items_in_map_clause : Error< @@ -8612,6 +8710,8 @@ def err_omp_declare_target_to_and_link : Error< def warn_omp_not_in_target_context : Warning< "declaration is not declared in any declare target region">, InGroup<OpenMPTarget>; +def err_omp_function_in_link_clause : Error< + "function name is not allowed in 'link' clause">; def err_omp_aligned_expected_array_or_ptr : Error< "argument of aligned clause should be array" "%select{ or pointer|, pointer, reference to array or reference to pointer}1" @@ -8670,6 +8770,12 @@ def err_omp_reduction_in_task : Error< "reduction variables may not be accessed in an explicit task">; def err_omp_reduction_id_not_compatible : Error< "list item of type %0 is not valid for specified reduction operation: unable to provide default initialization value">; +def err_omp_in_reduction_not_task_reduction : Error< + "in_reduction variable must appear in a task_reduction clause">; +def err_omp_reduction_identifier_mismatch : Error< + "in_reduction variable must have the same reduction operation as in a task_reduction clause">; +def note_omp_previous_reduction_identifier : Note< + "previously marked as task_reduction with different reduction operation">; def err_omp_prohibited_region : Error< "region cannot be%select{| closely}0 nested inside '%1' region" "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|" @@ -8746,9 +8852,9 @@ def err_omp_function_expected : Error< def err_omp_wrong_cancel_region : Error< "one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">; def err_omp_parent_cancel_region_nowait : Error< - "parent region for 'omp %select{cancellation point/cancel}0' construct cannot be nowait">; + "parent region for 'omp %select{cancellation point|cancel}0' construct cannot be nowait">; def err_omp_parent_cancel_region_ordered : Error< - "parent region for 'omp %select{cancellation point/cancel}0' construct cannot be ordered">; + "parent region for 'omp %select{cancellation point|cancel}0' construct cannot be ordered">; def err_omp_reduction_wrong_type : Error<"reduction type cannot be %select{qualified with 'const', 'volatile' or 'restrict'|a function|a reference|an array}0 type">; def err_omp_wrong_var_in_declare_reduction : Error<"only %select{'omp_priv' or 'omp_orig'|'omp_in' or 'omp_out'}0 variables are allowed in %select{initializer|combiner}0 expression">; def err_omp_declare_reduction_redefinition : Error<"redefinition of user-defined reduction for type %0">; @@ -8793,16 +8899,10 @@ def err_omp_expected_base_var_name : Error< "expected variable name as a base of the array %select{subscript|section}0">; def err_omp_map_shared_storage : Error< "variable already marked as mapped in current construct">; -def err_omp_not_mappable_type : Error< - "type %0 is not mappable to target">; def err_omp_invalid_map_type_for_directive : Error< "%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">; def err_omp_no_clause_for_directive : Error< "expected at least one %0 clause for '#pragma omp %1'">; -def note_omp_polymorphic_in_target : Note< - "mappable type cannot be polymorphic">; -def note_omp_static_member_in_target : Note< - "mappable type cannot contain static members">; def err_omp_threadprivate_in_clause : Error< "threadprivate variables are not allowed in '%0' clause">; def err_omp_wrong_ordered_loop_count : Error< @@ -8821,12 +8921,6 @@ def note_omp_critical_hint_here : Note< "%select{|previous }0'hint' clause with value '%1'">; def note_omp_critical_no_hint : Note< "%select{|previous }0directive with no 'hint' clause specified">; -def err_omp_firstprivate_distribute_private_teams : Error< - "private variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">; -def err_omp_firstprivate_and_lastprivate_in_distribute : Error< - "lastprivate variable cannot be firstprivate in '#pragma omp distribute'">; -def err_omp_firstprivate_distribute_in_teams_reduction : Error< - "reduction variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">; def err_omp_depend_clause_thread_simd : Error< "'depend' clauses cannot be mixed with '%0' clause">; def err_omp_depend_sink_expected_loop_iteration : Error< @@ -8871,6 +8965,10 @@ def err_omp_reduction_non_addressable_expression : Error< "expected addressable reduction item for the task-based directives">; def err_omp_reduction_with_nogroup : Error< "'reduction' clause cannot be used with 'nogroup' clause">; +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">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { @@ -8912,6 +9010,14 @@ def err_module_redefinition : Error< "redefinition of module '%0'">; def note_prev_module_definition : Note<"previously defined here">; def note_prev_module_definition_from_ast_file : Note<"module loaded from '%0'">; +def err_module_not_defined : Error< + "definition of module '%0' is not available; use -fmodule-file= to specify " + "path to precompiled module interface">; +def err_module_redeclaration : Error< + "translation unit contains multiple module declarations">; +def note_prev_module_declaration : Note<"previous module declaration is here">; +def err_module_declaration_missing : Error< + "missing 'export module' declaration in module interface unit">; def err_module_private_specialization : Error< "%select{template|partial|member}0 specialization cannot be " "declared __module_private__">; diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 420ccebbfaf0..3949bc2146f6 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -77,6 +77,8 @@ def err_imported_module_not_found : Error< "module '%0' in AST file '%1' (imported by AST file '%2') " "is not defined in any loaded module map file; " "maybe you need to load '%3'?">, DefaultFatal; +def note_imported_by_pch_module_not_found : Note< + "consider adding '%0' to the header search path">; def err_imported_module_modmap_changed : Error< "module '%0' imported by AST file '%1' found in a different module map file" " (%2) than when the importing AST file was built (%3)">, DefaultFatal; @@ -122,6 +124,45 @@ def note_second_module_difference : Note< def err_module_odr_violation_different_instantiations : Error< "instantiation of %q0 is different in different modules">; +def err_module_odr_violation_definition_data : Error < + "%q0 has different definitions in different modules; first difference is " + "%select{definition in module '%2'|defined here}1 found " + "%select{" + "%4 base %plural{1:class|:classes}4|" + "%4 virtual base %plural{1:class|:classes}4|" + "%ordinal4 base class with type %5|" + "%ordinal4 %select{non-virtual|virtual}5 base class %6|" + "%ordinal4 base class %5 with " + "%select{public|protected|private|no}6 access specifier}3">; + +def note_module_odr_violation_definition_data : Note < + "but in '%0' found " + "%select{" + "%2 base %plural{1:class|:classes}2|" + "%2 virtual base %plural{1:class|:classes}2|" + "%ordinal2 base class with different type %3|" + "%ordinal2 %select{non-virtual|virtual}3 base class %4|" + "%ordinal2 base class %3 with " + "%select{public|protected|private|no}4 access specifier}1">; + +def err_module_odr_violation_template_parameter : Error < + "%q0 has different definitions in different modules; first difference is " + "%select{definition in module '%2'|defined here}1 found " + "%select{" + "unnamed template parameter|" + "template parameter %4|" + "template parameter with %select{no |}4default argument|" + "template parameter with default argument}3">; + + +def note_module_odr_violation_template_parameter : Note < + "but in '%0' found " + "%select{" + "unnamed template parameter %2|" + "template parameter %2|" + "template parameter with %select{no |}2default argument|" + "template parameter with different default argument}1">; + def err_module_odr_violation_mismatch_decl : Error< "%q0 has different definitions in different modules; first difference is " "%select{definition in module '%2'|defined here}1 found " diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index f94b2c9b2f42..8e3c15afbfcd 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -1,4 +1,4 @@ -//===--- IdentifierTable.h - Hash table for identifier lookup ---*- C++ -*-===// +//===- IdentifierTable.h - Hash table for identifier lookup -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,11 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and /// clang::Selector interfaces. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H @@ -18,35 +18,29 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" #include <cassert> #include <cstddef> #include <cstdint> #include <cstring> -#include <new> #include <string> #include <utility> -namespace llvm { - - template <typename T> struct DenseMapInfo; - -} // end namespace llvm - namespace clang { - class LangOptions; - class IdentifierInfo; - class IdentifierTable; - class SourceLocation; - class MultiKeywordSelector; // private class used by Selector - class DeclarationName; // AST class that stores declaration names +class IdentifierInfo; +class LangOptions; +class MultiKeywordSelector; +class SourceLocation; - /// \brief A simple pair of identifier info and location. - typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair; +/// \brief A simple pair of identifier info and location. +using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>; /// One of these records is kept for each identifier that /// is lexed. This contains information about whether the token was \#define'd, @@ -85,8 +79,10 @@ class IdentifierInfo { // keyword. // 29 bit left in 64-bit word. - void *FETokenInfo; // Managed by the language front-end. - llvm::StringMapEntry<IdentifierInfo*> *Entry; + // Managed by the language front-end. + void *FETokenInfo = nullptr; + + llvm::StringMapEntry<IdentifierInfo *> *Entry = nullptr; public: IdentifierInfo(); @@ -104,7 +100,6 @@ public: /// \brief Return the beginning of the actual null-terminated string for this /// identifier. - /// const char *getNameStart() const { if (Entry) return Entry->getKeyData(); // FIXME: This is gross. It would be best not to embed specific details @@ -112,12 +107,12 @@ public: // The 'this' pointer really points to a // std::pair<IdentifierInfo, const char*>, where internal pointer // points to the external string data. - typedef std::pair<IdentifierInfo, const char*> actualtype; + using actualtype = std::pair<IdentifierInfo, const char *>; + return ((const actualtype*) this)->second; } /// \brief 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 @@ -125,7 +120,8 @@ public: // The 'this' pointer really points to a // std::pair<IdentifierInfo, const char*>, where internal pointer // points to the external string data. - typedef std::pair<IdentifierInfo, const char*> actualtype; + using actualtype = std::pair<IdentifierInfo, const char *>; + const char* p = ((const actualtype*) this)->second - 2; return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; } @@ -465,7 +461,7 @@ public: class IdentifierTable { // Shark shows that using MallocAllocator is *much* slower than using this // BumpPtrAllocator! - typedef llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator> HashTableTy; + using HashTableTy = llvm::StringMap<IdentifierInfo *, llvm::BumpPtrAllocator>; HashTableTy HashTable; IdentifierInfoLookup* ExternalLookup; @@ -551,8 +547,8 @@ public: return *II; } - typedef HashTableTy::const_iterator iterator; - typedef HashTableTy::const_iterator const_iterator; + using iterator = HashTableTy::const_iterator; + using const_iterator = HashTableTy::const_iterator; iterator begin() const { return HashTable.begin(); } iterator end() const { return HashTable.end(); } @@ -654,7 +650,9 @@ class Selector { MultiArg = 0x3, ArgFlags = ZeroArg|OneArg }; - uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo. + + // a pointer to the MultiKeywordSelector or IdentifierInfo. + uintptr_t InfoPtr = 0; Selector(IdentifierInfo *II, unsigned nArgs) { InfoPtr = reinterpret_cast<uintptr_t>(II); @@ -662,6 +660,7 @@ class Selector { assert(nArgs < 2 && "nArgs not equal to 0/1"); InfoPtr |= nArgs+1; } + Selector(MultiKeywordSelector *SI) { InfoPtr = reinterpret_cast<uintptr_t>(SI); assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo"); @@ -692,7 +691,7 @@ public: /// The default ctor should only be used when creating data structures that /// will contain selectors. - Selector() : InfoPtr(0) {} + Selector() = default; Selector(uintptr_t V) : InfoPtr(V) {} /// operator==/!= - Indicate whether the specified selectors are identical. @@ -776,7 +775,8 @@ public: /// \brief This table allows us to fully hide how we implement /// multi-keyword caching. class SelectorTable { - void *Impl; // Actually a SelectorTableImpl + // Actually a SelectorTableImpl + void *Impl; public: SelectorTable(); @@ -793,6 +793,7 @@ public: Selector getUnarySelector(IdentifierInfo *ID) { return Selector(ID, 1); } + Selector getNullarySelector(IdentifierInfo *ID) { return Selector(ID, 0); } @@ -848,7 +849,7 @@ public: unsigned ExtraKindOrNumArgs; }; -} // end namespace clang +} // namespace clang namespace llvm { @@ -856,11 +857,11 @@ namespace llvm { /// DenseSets. template <> struct DenseMapInfo<clang::Selector> { - static inline clang::Selector getEmptyKey() { + static clang::Selector getEmptyKey() { return clang::Selector::getEmptyMarker(); } - static inline clang::Selector getTombstoneKey() { + static clang::Selector getTombstoneKey() { return clang::Selector::getTombstoneMarker(); } @@ -874,16 +875,13 @@ struct DenseMapInfo<clang::Selector> { template <> struct isPodLike<clang::Selector> { static const bool value = true; }; -template <typename T> class PointerLikeTypeTraits; - template<> -class PointerLikeTypeTraits<clang::Selector> { -public: - static inline const void *getAsVoidPointer(clang::Selector P) { +struct PointerLikeTypeTraits<clang::Selector> { + static const void *getAsVoidPointer(clang::Selector P) { return P.getAsOpaquePtr(); } - static inline clang::Selector getFromVoidPointer(const void *P) { + static clang::Selector getFromVoidPointer(const void *P) { return clang::Selector(reinterpret_cast<uintptr_t>(P)); } @@ -893,13 +891,12 @@ public: // Provide PointerLikeTypeTraits for IdentifierInfo pointers, which // are not guaranteed to be 8-byte aligned. template<> -class PointerLikeTypeTraits<clang::IdentifierInfo*> { -public: - static inline void *getAsVoidPointer(clang::IdentifierInfo* P) { +struct PointerLikeTypeTraits<clang::IdentifierInfo*> { + static void *getAsVoidPointer(clang::IdentifierInfo* P) { return P; } - static inline clang::IdentifierInfo *getFromVoidPointer(void *P) { + static clang::IdentifierInfo *getFromVoidPointer(void *P) { return static_cast<clang::IdentifierInfo*>(P); } @@ -907,19 +904,18 @@ public: }; template<> -class PointerLikeTypeTraits<const clang::IdentifierInfo*> { -public: - static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) { +struct PointerLikeTypeTraits<const clang::IdentifierInfo*> { + static const void *getAsVoidPointer(const clang::IdentifierInfo* P) { return P; } - static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) { + static const clang::IdentifierInfo *getFromVoidPointer(const void *P) { return static_cast<const clang::IdentifierInfo*>(P); } enum { NumLowBitsAvailable = 1 }; }; -} // end namespace llvm +} // namespace llvm #endif // LLVM_CLANG_BASIC_IDENTIFIERTABLE_H diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h index f32ab5e11bd4..e60284d1b445 100644 --- a/include/clang/Basic/LLVM.h +++ b/include/clang/Basic/LLVM.h @@ -35,6 +35,7 @@ namespace llvm { template<typename T, unsigned N> class SmallVector; template<typename T> class SmallVectorImpl; template<typename T> class Optional; + template <class T> class Expected; template<typename T> struct SaveAndRestore; @@ -71,6 +72,9 @@ namespace clang { using llvm::SmallVectorImpl; using llvm::SaveAndRestore; + // Error handling. + using llvm::Expected; + // Reference counting. using llvm::IntrusiveRefCntPtr; using llvm::IntrusiveRefCntPtrInfo; diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index c9230e0aaa6f..ca3a0e349d62 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -82,6 +82,7 @@ // FIXME: A lot of the BENIGN_ options should be COMPATIBLE_ instead. LANGOPT(C99 , 1, 0, "C99") LANGOPT(C11 , 1, 0, "C11") +LANGOPT(C17 , 1, 0, "C17") LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode") LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions") LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks") @@ -89,7 +90,7 @@ LANGOPT(Borland , 1, 0, "Borland extensions") LANGOPT(CPlusPlus , 1, 0, "C++") LANGOPT(CPlusPlus11 , 1, 0, "C++11") LANGOPT(CPlusPlus14 , 1, 0, "C++14") -LANGOPT(CPlusPlus1z , 1, 0, "C++1z") +LANGOPT(CPlusPlus17 , 1, 0, "C++17") LANGOPT(CPlusPlus2a , 1, 0, "C++2a") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") @@ -124,7 +125,9 @@ LANGOPT(ZVector , 1, 0, "System z vector extensions") LANGOPT(Exceptions , 1, 0, "exception handling") LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions") LANGOPT(CXXExceptions , 1, 0, "C++ exceptions") +LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") +LANGOPT(SEHExceptions , 1, 0, "SEH .xdata exception handling") LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") @@ -137,6 +140,8 @@ LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly") LANGOPT(CoroutinesTS , 1, 0, "C++ coroutines TS") LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments") +LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") + BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers") LANGOPT(POSIXThreads , 1, 0, "POSIX thread support") LANGOPT(Blocks , 1, 0, "blocks extension to C") @@ -175,7 +180,8 @@ BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __w BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") LANGOPT(CharIsSigned , 1, 1, "signed char") -LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t") +LANGOPT(WCharSize , 4, 0, "width of wchar_t") +LANGOPT(WCharIsSigned , 1, 0, "signed or unsigned wchar_t") ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method") ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default calling convention") @@ -267,6 +273,9 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan " "aggressive, 2: more aggressive)") 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.") BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0, "allow editor placeholders in source") diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 8488515d2b67..f7a43adefad0 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -77,7 +77,8 @@ public: DCC_CDecl, DCC_FastCall, DCC_StdCall, - DCC_VectorCall + DCC_VectorCall, + DCC_RegCall }; enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; @@ -197,6 +198,10 @@ public: bool allowsNonTrivialObjCLifetimeQualifiers() const { return ObjCAutoRefCount || ObjCWeak; } + + bool assumeFunctionsAreConvergent() const { + return (CUDA && CUDAIsDevice) || OpenCL; + } }; /// \brief Floating point control options diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 177175eae965..6631721e3531 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -1,4 +1,4 @@ -//===--- Module.h - Describe a module ---------------------------*- C++ -*-===// +//===- Module.h - Describe a module -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,12 +6,13 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::Module class, which describes a module in the /// source code. -/// +// //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_BASIC_MODULE_H #define LLVM_CLANG_BASIC_MODULE_H @@ -19,6 +20,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SetVector.h" @@ -26,22 +28,28 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include <array> +#include <cassert> +#include <cstdint> +#include <ctime> #include <string> #include <utility> #include <vector> namespace llvm { - class raw_ostream; -} + +class raw_ostream; + +} // namespace llvm namespace clang { class LangOptions; class TargetInfo; -class IdentifierInfo; - + /// \brief Describes the name of a module. -typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; +using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; /// The signature of a module, which is a hash of the AST content. struct ASTFileSignature : std::array<uint32_t, 5> { @@ -68,7 +76,11 @@ public: ModuleMapModule, /// \brief This is a C++ Modules TS module interface unit. - ModuleInterfaceUnit + ModuleInterfaceUnit, + + /// \brief This is a fragment of the global module within some C++ Modules + /// TS module. + GlobalModuleFragment, }; /// \brief The kind of this module. @@ -81,7 +93,7 @@ public: /// \brief The build directory of this module. This is the directory in /// which the module is notionally built, and relative to which its headers /// are found. - const DirectoryEntry *Directory; + const DirectoryEntry *Directory = nullptr; /// \brief The presumed file name for the module map defining this module. /// Only non-empty when building from preprocessed source. @@ -95,6 +107,10 @@ public: /// \brief 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 + /// eventually be exposed, for use in "private" modules. + std::string ExportAsModule; private: /// \brief The submodules of this module, indexed by name. @@ -106,7 +122,7 @@ private: /// \brief The AST file if this is a top-level module which has a /// corresponding serialized AST file, or null otherwise. - const FileEntry *ASTFile; + const FileEntry *ASTFile = nullptr; /// \brief The top-level headers associated with this module. llvm::SmallSetVector<const FileEntry *, 2> TopHeaders; @@ -173,7 +189,7 @@ public: /// \brief An individual requirement: a feature name and a flag indicating /// the required state of that feature. - typedef std::pair<std::string, bool> Requirement; + using Requirement = std::pair<std::string, bool>; /// \brief The set of language features required to use this module. /// @@ -262,7 +278,7 @@ public: /// /// The pointer is the module being re-exported, while the bit will be true /// to indicate that this is a wildcard export. - typedef llvm::PointerIntPair<Module *, 1, bool> ExportDecl; + using ExportDecl = llvm::PointerIntPair<Module *, 1, bool>; /// \brief The set of export declarations. SmallVector<ExportDecl, 2> Exports; @@ -294,9 +310,9 @@ public: /// \brief A library or framework to link against when an entity from this /// module is used. struct LinkLibrary { - LinkLibrary() : IsFramework(false) { } + LinkLibrary() = default; LinkLibrary(const std::string &Library, bool IsFramework) - : Library(Library), IsFramework(IsFramework) { } + : Library(Library), IsFramework(IsFramework) {} /// \brief The library to link against. /// @@ -305,7 +321,7 @@ public: std::string Library; /// \brief Whether this is a framework rather than a library. - bool IsFramework; + bool IsFramework = false; }; /// \brief The set of libraries or frameworks to link against when @@ -391,6 +407,15 @@ public: return IsFramework && Parent && Parent->isPartOfFramework(); } + /// Set the parent of this module. This should only be used if the parent + /// could not be set during module creation. + void setParent(Module *M) { + assert(!Parent); + Parent = M; + Parent->SubModuleIndex[Name] = Parent->SubModules.size(); + Parent->SubModules.push_back(this); + } + /// \brief 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 @@ -415,7 +440,6 @@ public: const Module *getTopLevelModule() const; /// \brief Retrieve the name of the top-level module. - /// StringRef getTopLevelModuleName() const { return getTopLevelModule()->Name; } @@ -508,8 +532,8 @@ public: unsigned getVisibilityID() const { return VisibilityID; } - typedef std::vector<Module *>::iterator submodule_iterator; - typedef std::vector<Module *>::const_iterator submodule_const_iterator; + using submodule_iterator = std::vector<Module *>::iterator; + using submodule_const_iterator = std::vector<Module *>::const_iterator; submodule_iterator submodule_begin() { return SubModules.begin(); } submodule_const_iterator submodule_begin() const {return SubModules.begin();} @@ -534,7 +558,6 @@ public: } /// \brief 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. @@ -547,7 +570,7 @@ private: /// \brief A set of visible modules. class VisibleModuleSet { public: - VisibleModuleSet() : Generation(0) {} + VisibleModuleSet() = default; VisibleModuleSet(VisibleModuleSet &&O) : ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) { O.ImportLocs.clear(); @@ -582,13 +605,15 @@ public: /// \brief A callback to call when a module is made visible (directly or /// indirectly) by a call to \ref setVisible. - typedef llvm::function_ref<void(Module *M)> VisibleCallback; + using VisibleCallback = llvm::function_ref<void(Module *M)>; + /// \brief 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. - typedef llvm::function_ref<void(ArrayRef<Module *> Path, - Module *Conflict, StringRef Message)> - ConflictCallback; + using ConflictCallback = + llvm::function_ref<void(ArrayRef<Module *> Path, Module *Conflict, + StringRef Message)>; + /// \brief Make a specific module visible. void setVisible(Module *M, SourceLocation Loc, VisibleCallback Vis = [](Module *) {}, @@ -599,11 +624,11 @@ private: /// Import locations for each visible module. Indexed by the module's /// VisibilityID. std::vector<SourceLocation> ImportLocs; + /// Visibility generation, bumped every time the visibility state changes. - unsigned Generation; + unsigned Generation = 0; }; -} // end namespace clang - +} // namespace clang #endif // LLVM_CLANG_BASIC_MODULE_H diff --git a/include/clang/Basic/OpenCLExtensions.def b/include/clang/Basic/OpenCLExtensions.def index 360fec4281ac..c3319d2d808b 100644 --- a/include/clang/Basic/OpenCLExtensions.def +++ b/include/clang/Basic/OpenCLExtensions.def @@ -79,6 +79,10 @@ OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U) OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U) OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U) +// Intel OpenCL extensions +OPENCLEXT_INTERNAL(cl_intel_subgroups, 120, ~0U) +OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U) + #undef OPENCLEXT_INTERNAL #ifdef OPENCLEXT diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index 645ed52b59ca..6a0bed7ab15f 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -274,6 +274,7 @@ OPENMP_CLAUSE(from, OMPFromClause) OPENMP_CLAUSE(use_device_ptr, OMPUseDevicePtrClause) OPENMP_CLAUSE(is_device_ptr, OMPIsDevicePtrClause) OPENMP_CLAUSE(task_reduction, OMPTaskReductionClause) +OPENMP_CLAUSE(in_reduction, OMPInReductionClause) // Clauses allowed for OpenMP directive 'parallel'. OPENMP_PARALLEL_CLAUSE(if) @@ -434,6 +435,7 @@ OPENMP_TASK_CLAUSE(untied) OPENMP_TASK_CLAUSE(mergeable) OPENMP_TASK_CLAUSE(depend) OPENMP_TASK_CLAUSE(priority) +OPENMP_TASK_CLAUSE(in_reduction) // Clauses allowed for OpenMP directive 'atomic'. OPENMP_ATOMIC_CLAUSE(read) @@ -452,6 +454,7 @@ OPENMP_TARGET_CLAUSE(depend) OPENMP_TARGET_CLAUSE(defaultmap) OPENMP_TARGET_CLAUSE(firstprivate) OPENMP_TARGET_CLAUSE(is_device_ptr) +OPENMP_TARGET_CLAUSE(reduction) // Clauses allowed for OpenMP directive 'target data'. OPENMP_TARGET_DATA_CLAUSE(if) @@ -557,6 +560,7 @@ OPENMP_TASKLOOP_CLAUSE(grainsize) OPENMP_TASKLOOP_CLAUSE(nogroup) OPENMP_TASKLOOP_CLAUSE(num_tasks) OPENMP_TASKLOOP_CLAUSE(reduction) +OPENMP_TASKLOOP_CLAUSE(in_reduction) // Clauses allowed for OpenMP directive 'taskloop simd'. OPENMP_TASKLOOP_SIMD_CLAUSE(if) @@ -578,6 +582,7 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize) OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup) OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks) OPENMP_TASKLOOP_SIMD_CLAUSE(reduction) +OPENMP_TASKLOOP_SIMD_CLAUSE(in_reduction) // Clauses allowed for OpenMP directive 'critical'. OPENMP_CRITICAL_CLAUSE(hint) @@ -741,9 +746,9 @@ OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(private) OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(shared) OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(reduction) OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(schedule) -OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(linear) OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_teams) OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(thread_limit) +OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(copyin) // Clauses allowed for OpenMP directive 'target teams'. OPENMP_TARGET_TEAMS_CLAUSE(if) @@ -801,7 +806,6 @@ OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(dist_schedule) OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_threads) OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(proc_bind) OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(schedule) -OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(linear) // Clauses allowed for OpenMP directive // 'target teams distribute parallel for simd'. diff --git a/include/clang/Basic/OperatorKinds.def b/include/clang/Basic/OperatorKinds.def index 34ad7644cd2b..d86294bac902 100644 --- a/include/clang/Basic/OperatorKinds.def +++ b/include/clang/Basic/OperatorKinds.def @@ -89,6 +89,7 @@ OVERLOADED_OPERATOR(EqualEqual , "==" , equalequal , false, t OVERLOADED_OPERATOR(ExclaimEqual , "!=" , exclaimequal , false, true , false) OVERLOADED_OPERATOR(LessEqual , "<=" , lessequal , false, true , false) OVERLOADED_OPERATOR(GreaterEqual , ">=" , greaterequal , false, true , false) +OVERLOADED_OPERATOR(Spaceship , "<=>" , spaceship , false, true , false) OVERLOADED_OPERATOR(AmpAmp , "&&" , ampamp , false, true , false) OVERLOADED_OPERATOR(PipePipe , "||" , pipepipe , false, true , false) OVERLOADED_OPERATOR(PlusPlus , "++" , plusplus , true , true , false) diff --git a/include/clang/Basic/OperatorPrecedence.h b/include/clang/Basic/OperatorPrecedence.h index 640749fdd10d..94978f81e543 100644 --- a/include/clang/Basic/OperatorPrecedence.h +++ b/include/clang/Basic/OperatorPrecedence.h @@ -36,10 +36,11 @@ namespace prec { And = 8, // & Equality = 9, // ==, != Relational = 10, // >=, <=, >, < - Shift = 11, // <<, >> - Additive = 12, // -, + - Multiplicative = 13, // *, /, % - PointerToMember = 14 // .*, ->* + Spaceship = 11, // <=> + Shift = 12, // <<, >> + Additive = 13, // -, + + Multiplicative = 14, // *, /, % + PointerToMember = 15 // .*, ->* }; } diff --git a/include/clang/Basic/SanitizerBlacklist.h b/include/clang/Basic/SanitizerBlacklist.h index e651e1831683..1ae5c36eea99 100644 --- a/include/clang/Basic/SanitizerBlacklist.h +++ b/include/clang/Basic/SanitizerBlacklist.h @@ -15,29 +15,30 @@ #define LLVM_CLANG_BASIC_SANITIZERBLACKLIST_H #include "clang/Basic/LLVM.h" +#include "clang/Basic/SanitizerSpecialCaseList.h" +#include "clang/Basic/Sanitizers.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/SpecialCaseList.h" #include <memory> namespace clang { class SanitizerBlacklist { - std::unique_ptr<llvm::SpecialCaseList> SCL; + std::unique_ptr<SanitizerSpecialCaseList> SSCL; SourceManager &SM; public: SanitizerBlacklist(const std::vector<std::string> &BlacklistPaths, SourceManager &SM); - bool isBlacklistedGlobal(StringRef GlobalName, + bool isBlacklistedGlobal(SanitizerMask Mask, StringRef GlobalName, StringRef Category = StringRef()) const; - bool isBlacklistedType(StringRef MangledTypeName, + bool isBlacklistedType(SanitizerMask Mask, StringRef MangledTypeName, StringRef Category = StringRef()) const; - bool isBlacklistedFunction(StringRef FunctionName) const; - bool isBlacklistedFile(StringRef FileName, + bool isBlacklistedFunction(SanitizerMask Mask, StringRef FunctionName) const; + bool isBlacklistedFile(SanitizerMask Mask, StringRef FileName, StringRef Category = StringRef()) const; - bool isBlacklistedLocation(SourceLocation Loc, + bool isBlacklistedLocation(SanitizerMask Mask, SourceLocation Loc, StringRef Category = StringRef()) const; }; diff --git a/include/clang/Basic/SanitizerSpecialCaseList.h b/include/clang/Basic/SanitizerSpecialCaseList.h new file mode 100644 index 000000000000..e3252022a44f --- /dev/null +++ b/include/clang/Basic/SanitizerSpecialCaseList.h @@ -0,0 +1,54 @@ +//===--- SanitizerSpecialCaseList.h - SCL for sanitizers --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// An extension of SpecialCaseList to allowing querying sections by +// SanitizerMask. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_SANITIZERSPECIALCASELIST_H +#define LLVM_CLANG_BASIC_SANITIZERSPECIALCASELIST_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Sanitizers.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SpecialCaseList.h" +#include <memory> + +namespace clang { + +class SanitizerSpecialCaseList : public llvm::SpecialCaseList { +public: + static std::unique_ptr<SanitizerSpecialCaseList> + create(const std::vector<std::string> &Paths, std::string &Error); + + static std::unique_ptr<SanitizerSpecialCaseList> + createOrDie(const std::vector<std::string> &Paths); + + // Query blacklisted entries if any bit in Mask matches the entry's section. + bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query, + StringRef Category = StringRef()) const; + +protected: + // Initialize SanitizerSections. + void createSanitizerSections(); + + struct SanitizerSection { + SanitizerSection(SanitizerMask SM, SectionEntries &E) + : Mask(SM), Entries(E){}; + + SanitizerMask Mask; + SectionEntries &Entries; + }; + + std::vector<SanitizerSection> SanitizerSections; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index 71b11974dbfd..30d5cc8166dc 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -44,12 +44,17 @@ SANITIZER("address", Address) // Kernel AddressSanitizer (KASan) SANITIZER("kernel-address", KernelAddress) +SANITIZER("hwaddress", HWAddress) + // MemorySanitizer SANITIZER("memory", Memory) // libFuzzer SANITIZER("fuzzer", Fuzzer) +// libFuzzer-required instrumentation, no linking. +SANITIZER("fuzzer-no-link", FuzzerNoLink) + // ThreadSanitizer SANITIZER("thread", Thread) @@ -60,6 +65,7 @@ SANITIZER("leak", Leak) SANITIZER("alignment", Alignment) SANITIZER("array-bounds", ArrayBounds) SANITIZER("bool", Bool) +SANITIZER("builtin", Builtin) SANITIZER("enum", Enum) SANITIZER("float-cast-overflow", FloatCastOverflow) SANITIZER("float-divide-by-zero", FloatDivideByZero) @@ -107,11 +113,12 @@ SANITIZER("safe-stack", SafeStack) // -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, - Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow | - FloatDivideByZero | IntegerDivideByZero | NonnullAttribute | - Null | ObjectSize | PointerOverflow | Return | - ReturnsNonnullAttribute | Shift | SignedIntegerOverflow | - Unreachable | VLABound | Function | Vptr) + Alignment | Bool | Builtin | ArrayBounds | Enum | + FloatCastOverflow | FloatDivideByZero | + IntegerDivideByZero | NonnullAttribute | Null | ObjectSize | + PointerOverflow | Return | ReturnsNonnullAttribute | Shift | + SignedIntegerOverflow | Unreachable | VLABound | Function | + Vptr) // -fsanitize=undefined-trap is an alias for -fsanitize=undefined. SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined) @@ -130,6 +137,9 @@ SANITIZER("efficiency-working-set", EfficiencyWorkingSet) SANITIZER_GROUP("efficiency-all", Efficiency, EfficiencyCacheFrag | EfficiencyWorkingSet) +// Scudo hardened allocator +SANITIZER("scudo", Scudo) + // Magic group, containing all sanitizers. For example, "-fno-sanitize=all" // can be used to disable all the sanitizers. SANITIZER_GROUP("all", All, ~0ULL) diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h index 5317720095e0..1b936c7d115c 100644 --- a/include/clang/Basic/Sanitizers.h +++ b/include/clang/Basic/Sanitizers.h @@ -80,7 +80,7 @@ SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups); SanitizerMask expandSanitizerGroups(SanitizerMask Kinds); /// Return the sanitizers which do not affect preprocessing. -static inline SanitizerMask getPPTransparentSanitizers() { +inline SanitizerMask getPPTransparentSanitizers() { return SanitizerKind::CFI | SanitizerKind::Integer | SanitizerKind::Nullability | SanitizerKind::Undefined; } diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 12aa0e4f5717..7418b50f9d83 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -39,10 +39,9 @@ class SourceManager; class FileID { /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is /// this module, and <-1 is something loaded from another module. - int ID; -public: - FileID() : ID(0) {} + int ID = 0; +public: bool isValid() const { return ID != 0; } bool isInvalid() const { return ID == 0; } @@ -86,17 +85,15 @@ private: /// /// It is important that this type remains small. It is currently 32 bits wide. class SourceLocation { - unsigned ID; + unsigned ID = 0; friend class SourceManager; friend class ASTReader; friend class ASTWriter; enum : unsigned { MacroIDBit = 1U << 31 }; -public: - - SourceLocation() : ID(0) {} +public: bool isFileID() const { return (ID & MacroIDBit) == 0; } bool isMacroID() const { return (ID & MacroIDBit) != 0; } @@ -172,6 +169,11 @@ public: return getFromRawEncoding((unsigned)(uintptr_t)Encoding); } + static bool isPairOfFileLocations(SourceLocation Start, SourceLocation End) { + return Start.isValid() && Start.isFileID() && End.isValid() && + End.isFileID(); + } + void print(raw_ostream &OS, const SourceManager &SM) const; std::string printToString(const SourceManager &SM) const; void dump(const SourceManager &SM) const; @@ -193,8 +195,9 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { class SourceRange { SourceLocation B; SourceLocation E; + public: - SourceRange(): B(SourceLocation()), E(SourceLocation()) {} + SourceRange() = default; SourceRange(SourceLocation loc) : B(loc), E(loc) {} SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {} @@ -225,9 +228,10 @@ public: /// range. class CharSourceRange { SourceRange Range; - bool IsTokenRange; + bool IsTokenRange = false; + public: - CharSourceRange() : IsTokenRange(false) {} + CharSourceRange() = default; CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {} static CharSourceRange getTokenRange(SourceRange R) { @@ -325,10 +329,11 @@ class FileEntry; /// /// This is useful for argument passing to functions that expect both objects. class FullSourceLoc : public SourceLocation { - const SourceManager *SrcMgr; + const SourceManager *SrcMgr = nullptr; + public: /// \brief Creates a FullSourceLoc where isValid() returns \c false. - explicit FullSourceLoc() : SrcMgr(nullptr) {} + FullSourceLoc() = default; explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) : SourceLocation(Loc), SrcMgr(&SM) {} @@ -455,8 +460,7 @@ namespace llvm { // Teach SmallPtrSet how to handle SourceLocation. template<> - class PointerLikeTypeTraits<clang::SourceLocation> { - public: + struct PointerLikeTypeTraits<clang::SourceLocation> { static inline void *getAsVoidPointer(clang::SourceLocation L) { return L.getPtrEncoding(); } diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index ed3f8dfa86e7..397ad2e77fb5 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -1,4 +1,4 @@ -//===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===// +//===- SourceManager.h - Track and cache source files -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the SourceManager interface. /// @@ -29,14 +29,13 @@ /// location in the source where the macro was originally defined, /// and the presumed location is where the line directive states that /// the line is 17, or any other line. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H #define LLVM_CLANG_BASIC_SOURCEMANAGER_H #include "clang/Basic/FileManager.h" -#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" @@ -49,10 +48,8 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" -#include <algorithm> #include <cassert> #include <cstddef> -#include <cstdint> #include <map> #include <memory> #include <string> @@ -69,7 +66,6 @@ class SourceManager; /// \brief 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, @@ -100,6 +96,7 @@ namespace SrcMgr { enum CCFlags { /// \brief Whether the buffer is invalid. InvalidFlag = 0x01, + /// \brief Whether the buffer should not be freed on destruction. DoNotFreeFlag = 0x02 }; @@ -130,12 +127,12 @@ namespace SrcMgr { /// /// This is lazily computed. This is owned by the SourceManager /// BumpPointerAllocator object. - unsigned *SourceLineCache; + unsigned *SourceLineCache = nullptr; /// \brief The number of lines in this ContentCache. /// /// This is only valid if SourceLineCache is non-null. - unsigned NumLines; + unsigned NumLines = 0; /// \brief Indicates whether the buffer itself was provided to override /// the actual file contents. @@ -157,15 +154,14 @@ namespace SrcMgr { ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt), - SourceLineCache(nullptr), NumLines(0), BufferOverridden(false), - IsSystemFile(false), IsTransient(false) {} + BufferOverridden(false), IsSystemFile(false), IsTransient(false) {} /// The copy ctor does not allow copies where source object has either /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory /// is not transferred, so this is a logical error. ContentCache(const ContentCache &RHS) - : Buffer(nullptr, false), SourceLineCache(nullptr), - BufferOverridden(false), IsSystemFile(false), IsTransient(false) { + : Buffer(nullptr, false), BufferOverridden(false), IsSystemFile(false), + IsTransient(false) { OrigEntry = RHS.OrigEntry; ContentsEntry = RHS.ContentsEntry; @@ -212,12 +208,6 @@ namespace SrcMgr { /// this content cache. This is used for performance analysis. llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; - void setBuffer(std::unique_ptr<llvm::MemoryBuffer> B) { - assert(!Buffer.getPointer() && "MemoryBuffer already set."); - Buffer.setPointer(B.release()); - Buffer.setInt(0); - } - /// \brief Get the underlying buffer, returning NULL if the buffer is not /// yet available. llvm::MemoryBuffer *getRawBuffer() const { return Buffer.getPointer(); } @@ -252,6 +242,10 @@ namespace SrcMgr { /// FileInfos contain a "ContentCache *", with the contents of the file. /// class FileInfo { + friend class clang::SourceManager; + friend class clang::ASTWriter; + friend class clang::ASTReader; + /// \brief The location of the \#include that brought in this file. /// /// This is an invalid SLOC for the main file (top of the \#include chain). @@ -270,10 +264,6 @@ namespace SrcMgr { llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind> ContentAndKind; - friend class clang::SourceManager; - friend class clang::ASTWriter; - friend class clang::ASTReader; - public: /// \brief Return a FileInfo object. static FileInfo get(SourceLocation IL, const ContentCache *Con, @@ -454,7 +444,7 @@ namespace SrcMgr { } }; -} // end SrcMgr namespace. +} // namespace SrcMgr /// \brief External source of source location entries. class ExternalSLocEntrySource { @@ -552,7 +542,7 @@ public: /// \brief The stack used when building modules on demand, which is used /// to provide a link between the source managers of the different compiler /// instances. -typedef ArrayRef<std::pair<std::string, FullSourceLoc>> ModuleBuildStack; +using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>; /// \brief This class handles loading and caching of source files into memory. /// @@ -584,7 +574,7 @@ class SourceManager : public RefCountedBase<SourceManager> { /// \brief True if the ContentCache for files that are overridden by other /// files, should report the original file name. Defaults to true. - bool OverridenFilesKeepOriginalName; + bool OverridenFilesKeepOriginalName = true; /// \brief True if non-system source files should be treated as volatile /// (likely to change while trying to use them). Defaults to false. @@ -593,12 +583,13 @@ class SourceManager : public RefCountedBase<SourceManager> { /// \brief 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; + bool FilesAreTransient = false; struct OverriddenFilesInfoTy { /// \brief 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. llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer; }; @@ -653,7 +644,7 @@ class SourceManager : public RefCountedBase<SourceManager> { llvm::BitVector SLocEntryLoaded; /// \brief An external source for source location entries. - ExternalSLocEntrySource *ExternalSLocEntries; + ExternalSLocEntrySource *ExternalSLocEntries = nullptr; /// \brief A one-entry cache to speed up getFileID. /// @@ -664,7 +655,7 @@ class SourceManager : public RefCountedBase<SourceManager> { /// \brief Holds information for \#line directives. /// /// This is referenced by indices from SLocEntryTable. - LineTableInfo *LineTable; + LineTableInfo *LineTable = nullptr; /// \brief These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. @@ -680,7 +671,8 @@ class SourceManager : public RefCountedBase<SourceManager> { FileID PreambleFileID; // Statistics for -print-stats. - mutable unsigned NumLinearScans, NumBinaryProbes; + mutable unsigned NumLinearScans = 0; + mutable unsigned NumBinaryProbes = 0; /// \brief Associates a FileID with its "included/expanded in" decomposed /// location. @@ -690,12 +682,12 @@ class SourceManager : public RefCountedBase<SourceManager> { mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned>> IncludedLocMap; /// The key value into the IsBeforeInTUCache table. - typedef std::pair<FileID, FileID> IsBeforeInTUCacheKey; + using IsBeforeInTUCacheKey = std::pair<FileID, FileID>; /// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs /// to cache results. - typedef llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry> - InBeforeInTUCache; + using InBeforeInTUCache = + llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry>; /// Cache results for the isBeforeInTranslationUnit method. mutable InBeforeInTUCache IBTUCache; @@ -712,7 +704,7 @@ class SourceManager : public RefCountedBase<SourceManager> { /// \brief Lazily computed map of macro argument chunks to their expanded /// source location. - typedef std::map<unsigned, SourceLocation> MacroArgsMap; + using MacroArgsMap = std::map<unsigned, SourceLocation>; mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>> MacroArgsCacheMap; @@ -816,7 +808,22 @@ public: SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, int LoadedID = 0, unsigned LoadedOffset = 0, SourceLocation IncludeLoc = SourceLocation()) { - return createFileID(createMemBufferContentCache(std::move(Buffer)), + return createFileID( + createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false), + IncludeLoc, FileCharacter, LoadedID, LoadedOffset); + } + + enum UnownedTag { Unowned }; + + /// \brief 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. + FileID createFileID(UnownedTag, llvm::MemoryBuffer *Buffer, + SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, + int LoadedID = 0, unsigned LoadedOffset = 0, + SourceLocation IncludeLoc = SourceLocation()) { + return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/true), IncludeLoc, FileCharacter, LoadedID, LoadedOffset); } @@ -1408,7 +1415,6 @@ public: //===--------------------------------------------------------------------===// /// \brief 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 @@ -1520,9 +1526,18 @@ public: return LHSLoaded; } + /// Return true if the Point is within Start and End. + bool isPointWithin(SourceLocation Location, SourceLocation Start, + SourceLocation End) const { + return Location == Start || Location == End || + (isBeforeInTranslationUnit(Start, Location) && + isBeforeInTranslationUnit(Location, End)); + } + // Iterators over FileInfos. - typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> - ::const_iterator fileinfo_iterator; + using fileinfo_iterator = + llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::const_iterator; + fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } bool hasFileInfo(const FileEntry *File) const { @@ -1530,7 +1545,6 @@ public: } /// \brief Print statistics to stderr. - /// void PrintStats() const; void dump() const; @@ -1621,6 +1635,9 @@ public: } private: + friend class ASTReader; + friend class ASTWriter; + llvm::MemoryBuffer *getFakeBufferForRecovery() const; const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; @@ -1691,7 +1708,7 @@ private: /// \brief Create a new ContentCache for the specified memory buffer. const SrcMgr::ContentCache * - createMemBufferContentCache(std::unique_ptr<llvm::MemoryBuffer> Buf); + createMemBufferContentCache(llvm::MemoryBuffer *Buf, bool DoNotFree); FileID getFileIDSlow(unsigned SLocOffset) const; FileID getFileIDLocal(unsigned SLocOffset) const; @@ -1712,8 +1729,6 @@ private: SourceLocation SpellLoc, SourceLocation ExpansionLoc, unsigned ExpansionLength) const; - friend class ASTReader; - friend class ASTWriter; }; /// \brief Comparison function object. @@ -1726,7 +1741,7 @@ class BeforeThanCompare<SourceLocation> { SourceManager &SM; public: - explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { } + explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} bool operator()(SourceLocation LHS, SourceLocation RHS) const { return SM.isBeforeInTranslationUnit(LHS, RHS); @@ -1739,13 +1754,13 @@ class BeforeThanCompare<SourceRange> { SourceManager &SM; public: - explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { } + explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} bool operator()(SourceRange LHS, SourceRange RHS) const { return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin()); } }; -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_BASIC_SOURCEMANAGER_H diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h index 9403dea8889c..edd910e70412 100644 --- a/include/clang/Basic/SourceManagerInternals.h +++ b/include/clang/Basic/SourceManagerInternals.h @@ -1,4 +1,4 @@ -//===--- SourceManagerInternals.h - SourceManager Internals -----*- C++ -*-===// +//===- SourceManagerInternals.h - SourceManager Internals -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines implementation details of the clang::SourceManager class. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H @@ -18,7 +18,11 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include <cassert> #include <map> +#include <vector> namespace clang { @@ -86,7 +90,8 @@ class LineTableInfo { /// \brief 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; + std::map<FileID, std::vector<LineEntry>> LineEntries; + public: void clear() { FilenameIDs.clear(); @@ -95,10 +100,12 @@ public: } unsigned getLineTableFilenameID(StringRef Str); + StringRef getFilename(unsigned ID) const { assert(ID < FilenamesByID.size() && "Invalid FilenameID"); return FilenamesByID[ID]->getKey(); } + unsigned getNumFilenames() const { return FilenamesByID.size(); } void AddLineNote(FileID FID, unsigned Offset, @@ -112,7 +119,8 @@ public: const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset); // Low-level access - typedef std::map<FileID, std::vector<LineEntry> >::iterator iterator; + using iterator = std::map<FileID, std::vector<LineEntry>>::iterator; + iterator begin() { return LineEntries.begin(); } iterator end() { return LineEntries.end(); } @@ -121,6 +129,6 @@ public: void AddEntry(FileID FID, const std::vector<LineEntry> &Entries); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 50fb936e01d1..377534baab06 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -52,6 +52,7 @@ namespace clang { TST_int, TST_int128, TST_half, // OpenCL half, ARM NEON __fp16 + TST_Float16, // C11 extension ISO/IEC TS 18661-3 TST_float, TST_double, TST_float128, diff --git a/include/clang/Basic/SyncScope.h b/include/clang/Basic/SyncScope.h new file mode 100644 index 000000000000..09ac0052185a --- /dev/null +++ b/include/clang/Basic/SyncScope.h @@ -0,0 +1,154 @@ +//===--- SyncScope.h - Atomic synchronization scopes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides definitions for the atomic synchronization scopes. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_SYNCSCOPE_H +#define LLVM_CLANG_BASIC_SYNCSCOPE_H + +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include <memory> + +namespace clang { + +/// \brief 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 +/// synch scopes. Their numerical values may be different from the corresponding +/// synch scope enums used in source languages. +/// +/// In atomic builtin and expressions, language-specific synch scope enums are +/// used. Currently only OpenCL memory scope enums are supported and assumed +/// to be used by all languages. However, in the future, other languages may +/// define their own set of synch scope enums. The language-specific synch scope +/// values are represented by class AtomicScopeModel and its derived classes. +/// +/// To add a new enum value: +/// Add the enum value to enum class SyncScope. +/// Update enum value Last if necessary. +/// Update getAsString. +/// +enum class SyncScope { + OpenCLWorkGroup, + OpenCLDevice, + OpenCLAllSVMDevices, + OpenCLSubGroup, + Last = OpenCLSubGroup +}; + +inline llvm::StringRef getAsString(SyncScope S) { + switch (S) { + case SyncScope::OpenCLWorkGroup: + return "opencl_workgroup"; + case SyncScope::OpenCLDevice: + return "opencl_device"; + case SyncScope::OpenCLAllSVMDevices: + return "opencl_allsvmdevices"; + case SyncScope::OpenCLSubGroup: + return "opencl_subgroup"; + } + llvm_unreachable("Invalid synch scope"); +} + +/// \brief Defines the kind of atomic scope models. +enum class AtomicScopeModelKind { None, OpenCL }; + +/// \brief Defines the interface for synch scope model. +class AtomicScopeModel { +public: + virtual ~AtomicScopeModel() {} + /// \brief 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 + /// is valid. + virtual bool isValid(unsigned S) const = 0; + + /// \brief 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 + /// 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. + /// \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. +class AtomicScopeOpenCLModel : public AtomicScopeModel { +public: + /// The enum values match the pre-defined macros + /// __OPENCL_MEMORY_SCOPE_*, which are used to define memory_scope_* + /// enums in opencl-c.h. + enum ID { + WorkGroup = 1, + Device = 2, + AllSVMDevices = 3, + SubGroup = 4, + Last = SubGroup + }; + + AtomicScopeOpenCLModel() {} + + SyncScope map(unsigned S) const override { + switch (static_cast<ID>(S)) { + case WorkGroup: + return SyncScope::OpenCLWorkGroup; + case Device: + return SyncScope::OpenCLDevice; + case AllSVMDevices: + return SyncScope::OpenCLAllSVMDevices; + case SubGroup: + return SyncScope::OpenCLSubGroup; + } + llvm_unreachable("Invalid language synch scope value"); + } + + bool isValid(unsigned S) const override { + return S >= static_cast<unsigned>(WorkGroup) && + S <= static_cast<unsigned>(Last); + } + + ArrayRef<unsigned> getRuntimeValues() const override { + static_assert(Last == SubGroup, "Does not include all synch scopes"); + static const unsigned Scopes[] = { + static_cast<unsigned>(WorkGroup), static_cast<unsigned>(Device), + static_cast<unsigned>(AllSVMDevices), static_cast<unsigned>(SubGroup)}; + return llvm::makeArrayRef(Scopes); + } + + unsigned getFallBackValue() const override { + return static_cast<unsigned>(AllSVMDevices); + } +}; + +inline std::unique_ptr<AtomicScopeModel> +AtomicScopeModel::create(AtomicScopeModelKind K) { + switch (K) { + case AtomicScopeModelKind::None: + return std::unique_ptr<AtomicScopeModel>{}; + case AtomicScopeModelKind::OpenCL: + return llvm::make_unique<AtomicScopeOpenCLModel>(); + } + llvm_unreachable("Invalid atomic scope model kind"); +} +} + +#endif diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index d1a9ea85dbe9..6ba58779114f 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -59,6 +59,7 @@ protected: // values are specified by the TargetInfo constructor. bool BigEndian; bool TLSSupported; + bool VLASupported; bool NoAsmVariants; // True if {|} are normal characters. bool HasFloat128; unsigned char PointerWidth, PointerAlign; @@ -85,7 +86,7 @@ protected: *LongDoubleFormat, *Float128Format; unsigned char RegParmMax, SSERegParmMax; TargetCXXABI TheCXXABI; - const LangAS::Map *AddrSpaceMap; + const LangASMap *AddrSpaceMap; mutable StringRef PlatformName; mutable VersionTuple PlatformMinVersion; @@ -247,6 +248,9 @@ public: IntType getPtrDiffType(unsigned AddrSpace) const { return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace); } + IntType getUnsignedPtrDiffType(unsigned AddrSpace) const { + return getCorrespondingUnsignedType(getPtrDiffType(AddrSpace)); + } IntType getIntPtrType() const { return IntPtrType; } IntType getUIntPtrType() const { return getCorrespondingUnsignedType(IntPtrType); @@ -318,9 +322,7 @@ public: /// \brief Get integer value for null pointer. /// \param AddrSpace address space of pointee in source language. - virtual uint64_t getNullPointerValue(unsigned AddrSpace) const { - return 0; - } + virtual uint64_t getNullPointerValue(LangAS AddrSpace) const { return 0; } /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits. unsigned getBoolWidth() const { return BoolWidth; } @@ -447,6 +449,9 @@ public: /// \brief Return the maximum width lock-free atomic operation which can be /// inlined given the supported features of the given target. unsigned getMaxAtomicInlineWidth() const { return MaxAtomicInlineWidth; } + /// \brief 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 /// operations at the specified width and alignment. virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits, @@ -464,21 +469,6 @@ public: /// types for the given target. unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; } - /// Return the alignment (in bits) of the thrown exception object. This is - /// only meaningful for targets that allocate C++ exceptions in a system - /// runtime, such as those using the Itanium C++ ABI. - virtual unsigned getExnObjectAlignment() const { - // Itanium says that an _Unwind_Exception has to be "double-word" - // aligned (and thus the end of it is also so-aligned), meaning 16 - // bytes. Of course, that was written for the actual Itanium, - // which is a 64-bit platform. Classically, the ABI doesn't really - // specify the alignment on other platforms, but in practice - // libUnwind declares the struct with __attribute__((aligned)), so - // we assume that alignment here. (It's generally 16 bytes, but - // some targets overwrite it.) - return getDefaultAlignForAttributeAligned(); - } - /// \brief Return the size of intmax_t and uintmax_t for this target, in bits. unsigned getIntMaxTWidth() const { return getTypeWidth(IntMaxType); @@ -569,6 +559,14 @@ public: return ComplexLongDoubleUsesFP2Ret; } + /// Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used + /// to convert to and from __fp16. + /// FIXME: This function should be removed once all targets stop using the + /// conversion intrinsics. + virtual bool useFP16ConversionIntrinsics() const { + return true; + } + /// \brief Specify if mangling based on address space map should be used or /// not for language specific address spaces bool useAddressSpaceMapMangling() const { @@ -869,6 +867,11 @@ public: return false; } + /// brief Determine whether this TargetInfo supports the given CPU name. + virtual bool isValidCPUName(StringRef Name) const { + return true; + } + /// \brief Use the specified ABI. /// /// \return False on error (invalid ABI name). @@ -891,6 +894,11 @@ public: Features[Name] = Enabled; } + /// \brief Determine whether this TargetInfo supports the given feature. + virtual bool isValidFeatureName(StringRef Feature) const { + return true; + } + /// \brief Perform initialization based on the user configured /// set of features (e.g., +sse4). /// @@ -916,6 +924,10 @@ public: // argument. virtual bool validateCpuSupports(StringRef Name) const { return false; } + // \brief 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. unsigned getRegParmMax() const { assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle"); @@ -935,6 +947,9 @@ public: return MaxTLSAlign; } + /// \brief Whether target supports variable-length arrays. + bool isVLASupported() const { return VLASupported; } + /// \brief Whether the target supports SEH __try. bool isSEHTrySupported() const { return getTriple().isOSWindows() && @@ -965,15 +980,13 @@ public: return nullptr; } - const LangAS::Map &getAddressSpaceMap() const { - return *AddrSpaceMap; - } + const LangASMap &getAddressSpaceMap() const { return *AddrSpaceMap; } /// \brief 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. - virtual llvm::Optional<unsigned> getConstantAddressSpace() const { + virtual llvm::Optional<LangAS> getConstantAddressSpace() const { return LangAS::Default; } @@ -1051,10 +1064,19 @@ public: return getTargetOpts().SupportedOpenCLOptions; } - /// \brief Get OpenCL image type address space. - virtual LangAS::ID getOpenCLImageAddrSpace() const { - return LangAS::opencl_global; - } + enum OpenCLTypeKind { + OCLTK_Default, + OCLTK_ClkEvent, + OCLTK_Event, + OCLTK_Image, + OCLTK_Pipe, + OCLTK_Queue, + OCLTK_ReserveID, + OCLTK_Sampler, + }; + + /// \brief Get address space for OpenCL type. + virtual LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const; /// \returns Target specific vtbl ptr address space. virtual unsigned getVtblPtrAddressSpace() const { diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 9bb19c7b79df..60becfb8ee76 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -54,8 +54,6 @@ public: /// be a list of strings starting with by '+' or '-'. std::vector<std::string> Features; - std::vector<std::string> Reciprocals; - /// Supported OpenCL extensions and optional core features. OpenCLOptions SupportedOpenCLOptions; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index be67663a1015..6ae8821a834d 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -27,8 +27,11 @@ #ifndef CXX11_KEYWORD #define CXX11_KEYWORD(X,Y) KEYWORD(X,KEYCXX11|(Y)) #endif +#ifndef CXX2A_KEYWORD +#define CXX2A_KEYWORD(X,Y) KEYWORD(X,KEYCXX2A|(Y)) +#endif #ifndef CONCEPTS_KEYWORD -#define CONCEPTS_KEYWORD(X) KEYWORD(X,KEYCONCEPTS) +#define CONCEPTS_KEYWORD(X) CXX2A_KEYWORD(X,KEYCONCEPTS) #endif #ifndef MODULES_KEYWORD #define MODULES_KEYWORD(X) KEYWORD(X,KEYMODULES) @@ -142,7 +145,7 @@ TOK(numeric_constant) // 0x123 TOK(char_constant) // 'a' TOK(wide_char_constant) // L'b' -// C++1z Character Constants +// C++17 Character Constants TOK(utf8_char_constant) // u8'a' // C++11 Character Constants @@ -191,6 +194,7 @@ PUNCTUATOR(less, "<") PUNCTUATOR(lessless, "<<") PUNCTUATOR(lessequal, "<=") PUNCTUATOR(lesslessequal, "<<=") +PUNCTUATOR(spaceship, "<=>") PUNCTUATOR(greater, ">") PUNCTUATOR(greatergreater, ">>") PUNCTUATOR(greaterequal, ">=") @@ -236,6 +240,7 @@ PUNCTUATOR(caretcaret, "^^") // implementation namespace // KEYNOCXX - This is a keyword in every non-C++ dialect. // KEYCXX11 - This is a C++ keyword introduced to C++ in C++11 +// KEYCXX2A - This is a C++ keyword introduced to C++ in C++2a // KEYCONCEPTS - This is a keyword if the C++ extensions for concepts // are enabled. // KEYMODULES - This is a keyword if the C++ extensions for modules @@ -362,7 +367,7 @@ CXX11_KEYWORD(nullptr , 0) CXX11_KEYWORD(static_assert , 0) CXX11_KEYWORD(thread_local , 0) -// C++ concepts TS keywords +// C++2a / concepts TS keywords CONCEPTS_KEYWORD(concept) CONCEPTS_KEYWORD(requires) @@ -375,6 +380,9 @@ KEYWORD(co_yield , KEYCOROUTINES) MODULES_KEYWORD(module) MODULES_KEYWORD(import) +// C11 Extension +KEYWORD(_Float16 , KEYALL) + // GNU Extensions (in impl-reserved namespace) KEYWORD(_Decimal32 , KEYALL) KEYWORD(_Decimal64 , KEYALL) @@ -390,6 +398,7 @@ 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) @@ -448,6 +457,8 @@ TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX) TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX) TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX) TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) +TYPE_TRAIT_1(__has_unique_object_representations, + HasUniqueObjectRepresentations, KEYCXX) // Clang-only C++ Type Traits TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX) @@ -810,6 +821,7 @@ ANNOTATION(module_end) #undef TYPE_TRAIT_1 #undef TYPE_TRAIT #undef CONCEPTS_KEYWORD +#undef CXX2A_KEYWORD #undef CXX11_KEYWORD #undef KEYWORD #undef PUNCTUATOR diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 6aadf795d82e..8ecd63f9c3cb 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -70,7 +70,8 @@ namespace clang { UTT_IsUnsigned, UTT_IsVoid, UTT_IsVolatile, - UTT_Last = UTT_IsVolatile, + UTT_HasUniqueObjectRepresentations, + UTT_Last = UTT_HasUniqueObjectRepresentations, BTT_IsBaseOf, BTT_IsConvertible, BTT_IsConvertibleTo, diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index e52b345e286c..245452dd12b5 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -319,16 +319,30 @@ public: explicit InMemoryFileSystem(bool UseNormalizedPaths = true); ~InMemoryFileSystem() override; - /// Add a buffer to the VFS with a path. The VFS owns the buffer. - /// \return true if the file was successfully added, false if the file already - /// exists in the file system with different contents. + /// Add a file containing a buffer or a directory to the VFS with a + /// path. The VFS owns the buffer. If present, User, Group, Type + /// and Perms apply to the newly-created file or directory. + /// \return true if the file or directory was successfully added, + /// false if the file or directory already exists in the file system with + /// different contents. bool addFile(const Twine &Path, time_t ModificationTime, - std::unique_ptr<llvm::MemoryBuffer> Buffer); + std::unique_ptr<llvm::MemoryBuffer> Buffer, + 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. - /// \return true if the file was successfully added, false if the file already - /// exists in the file system with different contents. + /// If present, User, Group, Type and Perms apply to the newly-created file + /// or directory. + /// \return true if the file or directory was successfully added, + /// false if the file or directory already exists in the file system with + /// different contents. bool addFileNoOwn(const Twine &Path, time_t ModificationTime, - llvm::MemoryBuffer *Buffer); + llvm::MemoryBuffer *Buffer, + 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); + std::string toString() const; /// Return true if this file system normalizes . and .. in paths. bool useNormalizedPaths() const { return UseNormalizedPaths; } diff --git a/include/clang/Basic/X86Target.def b/include/clang/Basic/X86Target.def new file mode 100644 index 000000000000..21550fe2dd55 --- /dev/null +++ b/include/clang/Basic/X86Target.def @@ -0,0 +1,232 @@ +//===--- X86Target.def - X86 Feature/Processor Database ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the X86-specific Features and Processors, as used by +// the X86 Targets. +// +//===----------------------------------------------------------------------===// + + +#ifndef PROC +#define PROC(ENUM, STRING, IS64BIT) +#endif + +#ifndef PROC_ALIAS +#define PROC_ALIAS(ENUM, ALIAS) +#endif + +#define PROC_64_BIT true +#define PROC_32_BIT false + +/// \name i386 +/// i386-generation processors. +//@{ +PROC(i386, "i386", PROC_32_BIT) +//@} + +/// \name i486 +/// i486-generation processors. +//@{ +PROC(i486, "i486", PROC_32_BIT) +PROC(WinChipC6, "winchip-c6", PROC_32_BIT) +PROC(WinChip2, "winchip2", PROC_32_BIT) +PROC(C3, "c3", PROC_32_BIT) +//@} + +/// \name i586 +/// i586-generation processors, P5 microarchitecture based. +//@{ +PROC(i586, "i586", PROC_32_BIT) +PROC(Pentium, "pentium", PROC_32_BIT) +PROC(PentiumMMX, "pentium-mmx", PROC_32_BIT) +//@} + +/// \name i686 +/// i686-generation processors, P6 / Pentium M microarchitecture based. +//@{ +PROC(PentiumPro, "pentiumpro", PROC_32_BIT) +PROC_ALIAS(PentiumPro, "i686") +PROC(Pentium2, "pentium2", PROC_32_BIT) +PROC(Pentium3, "pentium3", PROC_32_BIT) +PROC_ALIAS(Pentium3, "pentium3m") +PROC(PentiumM, "pentium-m", PROC_32_BIT) +PROC(C3_2, "c3-2", PROC_32_BIT) + +/// This enumerator is a bit odd, as GCC no longer accepts -march=yonah. +/// Clang however has some logic to support this. +// FIXME: Warn, deprecate, and potentially remove this. +PROC(Yonah, "yonah", PROC_32_BIT) +//@} + +/// \name Netburst +/// Netburst microarchitecture based processors. +//@{ +PROC(Pentium4, "pentium4", PROC_32_BIT) +PROC_ALIAS(Pentium4, "pentium4m") + +PROC(Prescott, "prescott", PROC_32_BIT) +PROC(Nocona, "nocona", PROC_64_BIT) +//@} + +/// \name Core +/// Core microarchitecture based processors. +//@{ +PROC(Core2, "core2", PROC_64_BIT) + +/// This enumerator, like Yonah, is a bit odd. It is another +/// codename which GCC no longer accepts as an option to -march, but Clang +/// has some logic for recognizing it. +// FIXME: Warn, deprecate, and potentially remove this. +PROC(Penryn, "penryn", PROC_64_BIT) +//@} + +/// \name Atom +/// Atom processors +//@{ +PROC(Bonnell, "bonnell", PROC_64_BIT) +PROC_ALIAS(Bonnell, "atom") + +PROC(Silvermont, "silvermont", PROC_64_BIT) +PROC_ALIAS(Silvermont, "slm") + +PROC(Goldmont, "goldmont", PROC_64_BIT) +//@} + +/// \name Nehalem +/// Nehalem microarchitecture based processors. +PROC(Nehalem, "nehalem", PROC_64_BIT) +PROC_ALIAS(Nehalem, "corei7") + +/// \name Westmere +/// Westmere microarchitecture based processors. +PROC(Westmere, "westmere", PROC_64_BIT) + +/// \name Sandy Bridge +/// Sandy Bridge microarchitecture based processors. +PROC(SandyBridge, "sandybridge", PROC_64_BIT) +PROC_ALIAS(SandyBridge, "corei7-avx") + +/// \name Ivy Bridge +/// Ivy Bridge microarchitecture based processors. +PROC(IvyBridge, "ivybridge", PROC_64_BIT) +PROC_ALIAS(IvyBridge, "core-avx-i") + +/// \name Haswell +/// Haswell microarchitecture based processors. +PROC(Haswell, "haswell", PROC_64_BIT) +PROC_ALIAS(Haswell, "core-avx2") + +/// \name Broadwell +/// Broadwell microarchitecture based processors. +PROC(Broadwell, "broadwell", PROC_64_BIT) + +/// \name Skylake Client +/// Skylake client microarchitecture based processors. +PROC(SkylakeClient, "skylake", PROC_64_BIT) + +/// \name Skylake Server +/// Skylake server microarchitecture based processors. +PROC(SkylakeServer, "skylake-avx512", PROC_64_BIT) +PROC_ALIAS(SkylakeServer, "skx") + +/// \name Cannonlake Client +/// Cannonlake client microarchitecture based processors. +PROC(Cannonlake, "cannonlake", PROC_64_BIT) + +/// \name Icelake Client +/// Icelake client microarchitecture based processors. +PROC(Icelake, "icelake", PROC_64_BIT) + +/// \name Knights Landing +/// Knights Landing processor. +PROC(KNL, "knl", PROC_64_BIT) + +/// \name Knights Mill +/// Knights Mill processor. +PROC(KNM, "knm", PROC_64_BIT) + +/// \name Lakemont +/// Lakemont microarchitecture based processors. +PROC(Lakemont, "lakemont", PROC_32_BIT) + +/// \name K6 +/// K6 architecture processors. +//@{ +PROC(K6, "k6", PROC_32_BIT) +PROC(K6_2, "k6-2", PROC_32_BIT) +PROC(K6_3, "k6-3", PROC_32_BIT) +//@} + +/// \name K7 +/// K7 architecture processors. +//@{ +PROC(Athlon, "athlon", PROC_32_BIT) +PROC_ALIAS(Athlon, "athlon-tbird") + +PROC(AthlonXP, "athlon-xp", PROC_32_BIT) +PROC_ALIAS(AthlonXP, "athlon-mp") +PROC_ALIAS(AthlonXP, "athlon-4") +//@} + +/// \name K8 +/// K8 architecture processors. +//@{ +PROC(K8, "k8", PROC_64_BIT) +PROC_ALIAS(K8, "athlon64") +PROC_ALIAS(K8, "athlon-fx") +PROC_ALIAS(K8, "opteron") + +PROC(K8SSE3, "k8-sse3", PROC_64_BIT) +PROC_ALIAS(K8SSE3, "athlon64-sse3") +PROC_ALIAS(K8SSE3, "opteron-sse3") + +PROC(AMDFAM10, "amdfam10", PROC_64_BIT) +PROC_ALIAS(AMDFAM10, "barcelona") +//@} + +/// \name Bobcat +/// Bobcat architecture processors. +//@{ +PROC(BTVER1, "btver1", PROC_64_BIT) +PROC(BTVER2, "btver2", PROC_64_BIT) +//@} + +/// \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) +//@} + +/// \name zen +/// Zen architecture processors. +//@{ +PROC(ZNVER1, "znver1", PROC_64_BIT) +//@} + +/// This specification is deprecated and will be removed in the future. +/// Users should prefer K8. +// FIXME: Warn on this when the CPU is set to it. +//@{ +PROC(x86_64, "x86-64", PROC_64_BIT) +//@} + +/// \name Geode +/// Geode processors. +//@{ +PROC(Geode, "geode", PROC_32_BIT) +//@} + + +#undef PROC_64_BIT +#undef PROC_32_BIT +#undef PROC +#undef PROC_ALIAS diff --git a/include/clang/CodeGen/CodeGenABITypes.h b/include/clang/CodeGen/CodeGenABITypes.h index 615e55c8b69f..53619fa8ef65 100644 --- a/include/clang/CodeGen/CodeGenABITypes.h +++ b/include/clang/CodeGen/CodeGenABITypes.h @@ -72,12 +72,19 @@ const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM, FunctionType::ExtInfo info, RequiredArgs args); -// Returns null if the function type is incomplete and can't be lowered. +/// Returns null if the function type is incomplete and can't be lowered. llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM, const FunctionDecl *FD); llvm::Type *convertTypeForMemory(CodeGenModule &CGM, QualType T); +/// Given a non-bitfield struct field, return its index within the elements of +/// the struct's converted type. The returned index refers to a field number in +/// the complete object type which is returned by convertTypeForMemory. FD must +/// be a field in RD directly (i.e. not an inherited field). +unsigned getLLVMFieldNumber(CodeGenModule &CGM, + const RecordDecl *RD, const FieldDecl *FD); + } // end namespace CodeGen } // end namespace clang diff --git a/include/clang/CodeGen/ConstantInitFuture.h b/include/clang/CodeGen/ConstantInitFuture.h index ef1a5d2f49af..f1a7e2264fc6 100644 --- a/include/clang/CodeGen/ConstantInitFuture.h +++ b/include/clang/CodeGen/ConstantInitFuture.h @@ -31,8 +31,7 @@ class ConstantInitBuilderBase; } namespace llvm { template <> -class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> { -public: +struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> { using T = ::clang::CodeGen::ConstantInitBuilderBase*; static inline void *getAsVoidPointer(T p) { return p; } @@ -93,8 +92,7 @@ public: namespace llvm { template <> -class PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> { -public: +struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> { using T = ::clang::CodeGen::ConstantInitFuture; static inline void *getAsVoidPointer(T future) { diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index 6f81ea9d6370..e110f6fd30c1 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -84,6 +84,10 @@ public: /// code generator will schedule the entity for emission if a /// definition has been registered with this code generator. llvm::Constant *GetAddrOfGlobal(GlobalDecl decl, bool isForDefinition); + + /// Create a new \c llvm::Module after calling HandleTranslationUnit. This + /// enable codegen in interactive processing environments. + llvm::Module* StartModule(llvm::StringRef ModuleName, llvm::LLVMContext &C); }; /// CreateLLVMCodeGen - Create a CodeGenerator instance. diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake index b138b5fcd828..daac9b7b45d1 100644 --- a/include/clang/Config/config.h.cmake +++ b/include/clang/Config/config.h.cmake @@ -17,9 +17,15 @@ /* Default runtime library to use. */ #define CLANG_DEFAULT_RTLIB "${CLANG_DEFAULT_RTLIB}" +/* Default objcopy to use */ +#define CLANG_DEFAULT_OBJCOPY "${CLANG_DEFAULT_OBJCOPY}" + /* Default OpenMP runtime used by -fopenmp. */ #define CLANG_DEFAULT_OPENMP_RUNTIME "${CLANG_DEFAULT_OPENMP_RUNTIME}" +/* Default architecture for OpenMP offloading to Nvidia GPUs. */ +#define CLANG_OPENMP_NVPTX_DEFAULT_ARCH "${CLANG_OPENMP_NVPTX_DEFAULT_ARCH}" + /* Multilib suffix for libdir. */ #define CLANG_LIBDIR_SUFFIX "${CLANG_LIBDIR_SUFFIX}" @@ -57,8 +63,8 @@ #cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS /* Enable each functionality of modules */ -#cmakedefine CLANG_ENABLE_ARCMT -#cmakedefine CLANG_ENABLE_OBJC_REWRITER -#cmakedefine CLANG_ENABLE_STATIC_ANALYZER +#cmakedefine01 CLANG_ENABLE_ARCMT +#cmakedefine01 CLANG_ENABLE_OBJC_REWRITER +#cmakedefine01 CLANG_ENABLE_STATIC_ANALYZER #endif diff --git a/include/clang/CrossTU/CrossTUDiagnostic.h b/include/clang/CrossTU/CrossTUDiagnostic.h new file mode 100644 index 000000000000..dad38309fd1a --- /dev/null +++ b/include/clang/CrossTU/CrossTUDiagnostic.h @@ -0,0 +1,29 @@ +//===--- CrossTUDiagnostic.h - Diagnostics for Cross TU ---------*- 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_CROSSTU_CROSSTUDIAGNOSTIC_H +#define LLVM_CLANG_CROSSTU_CROSSTUDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { +namespace diag { +enum { +#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, CATEGORY) \ + ENUM, +#define CROSSTUSTART +#include "clang/Basic/DiagnosticCrossTUKinds.inc" +#undef DIAG + NUM_BUILTIN_CROSSTU_DIAGNOSTICS +}; +} // end namespace diag +} // end namespace clang + +#endif // LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H diff --git a/include/clang/CrossTU/CrossTranslationUnit.h b/include/clang/CrossTU/CrossTranslationUnit.h new file mode 100644 index 000000000000..f2a169025009 --- /dev/null +++ b/include/clang/CrossTU/CrossTranslationUnit.h @@ -0,0 +1,159 @@ +//===--- CrossTranslationUnit.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 provides an interface to load binary AST dumps on demand. This +// feature can be utilized for tools that require cross translation unit +// support. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H +#define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Error.h" + +namespace clang { +class CompilerInstance; +class ASTContext; +class ASTImporter; +class ASTUnit; +class DeclContext; +class FunctionDecl; +class NamedDecl; +class TranslationUnitDecl; + +namespace cross_tu { + +enum class index_error_code { + unspecified = 1, + missing_index_file, + invalid_index_format, + multiple_definitions, + missing_definition, + failed_import, + failed_to_get_external_ast, + failed_to_generate_usr +}; + +class IndexError : public llvm::ErrorInfo<IndexError> { +public: + static char ID; + IndexError(index_error_code C) : Code(C), LineNo(0) {} + IndexError(index_error_code C, std::string FileName, int LineNo = 0) + : Code(C), FileName(std::move(FileName)), LineNo(LineNo) {} + void log(raw_ostream &OS) const override; + std::error_code convertToErrorCode() const override; + index_error_code getCode() const { return Code; } + int getLineNum() const { return LineNo; } + std::string getFileName() const { return FileName; } + +private: + index_error_code Code; + std::string FileName; + int LineNo; +}; + +/// \brief This function parses an index file that determines which +/// translation unit contains which definition. +/// +/// The index file format is the following: +/// each line consists of an USR and a filepath separated by a space. +/// +/// \return Returns a map where the USR is the key and the filepath is the value +/// or an error. +llvm::Expected<llvm::StringMap<std::string>> +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 +/// unit capability. +/// +/// This class can load function definitions from external AST files. +/// The loaded definition will be merged back to the original AST using the +/// AST Importer. +/// In order to use this class, an index file is required that describes +/// the locations of the AST files for each function definition. +/// +/// Note that this class also implements caching. +class CrossTranslationUnitContext { +public: + CrossTranslationUnitContext(CompilerInstance &CI); + ~CrossTranslationUnitContext(); + + /// \brief 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 + /// the current translation unit. A function definition with the same + /// declaration will be looked up in the index file which should be in the + /// \p CrossTUDir directory, called \p IndexName. In case the declaration is + /// found in the index the corresponding AST file will be loaded and the + /// definition of the function will be merged into the original AST using + /// the AST Importer. + /// + /// \return The declaration with the definition will be returned. + /// If no suitable definition is found in the index file or multiple + /// definitions found error will be returned. + /// + /// Note that the AST files should also be in the \p CrossTUDir. + llvm::Expected<const FunctionDecl *> + getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, + StringRef IndexName); + + /// \brief This function loads a function definition from an external AST + /// file. + /// + /// A function definition with the same declaration will be looked up in the + /// index file which should be in the \p CrossTUDir directory, called + /// \p IndexName. In case the declaration is found in the index the + /// corresponding AST file will be loaded. + /// + /// \return Returns an ASTUnit that contains the definition of the looked up + /// function. + /// + /// Note that the AST files should also be in the \p CrossTUDir. + llvm::Expected<ASTUnit *> loadExternalAST(StringRef LookupName, + StringRef CrossTUDir, + StringRef IndexName); + + /// \brief 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. + static std::string getLookupName(const NamedDecl *ND); + + /// \brief Emit diagnostics for the user for potential configuration errors. + void emitCrossTUDiagnostics(const IndexError &IE); + +private: + ASTImporter &getOrCreateASTImporter(ASTContext &From); + const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC, + StringRef LookupFnName); + + llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap; + llvm::StringMap<clang::ASTUnit *> FunctionASTUnitMap; + llvm::StringMap<std::string> FunctionFileMap; + llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>> + ASTUnitImporterMap; + CompilerInstance &CI; + ASTContext &Context; +}; + +} // namespace cross_tu +} // namespace clang + +#endif // LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 205f36b723c8..7dea88b62cc1 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -70,7 +70,7 @@ def analyzer_opt_analyze_nested_blocks : Flag<["-"], "analyzer-opt-analyze-neste def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; def analyze_function : Separate<["-"], "analyze-function">, - HelpText<"Run analysis on specific function">; + HelpText<"Run analysis on specific function (for C++ include parameters in name)">; def analyze_function_EQ : Joined<["-"], "analyze-function=">, Alias<analyze_function>; def analyzer_eagerly_assume : Flag<["-"], "analyzer-eagerly-assume">, HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">; @@ -99,7 +99,19 @@ def analyzer_stats : Flag<["-"], "analyzer-stats">, HelpText<"Print internal analyzer statistics.">; def analyzer_checker : Separate<["-"], "analyzer-checker">, - HelpText<"Choose analyzer checkers to enable">; + HelpText<"Choose analyzer checkers to enable">, + ValuesCode<[{ + const char *Values = + #define GET_CHECKERS + #define CHECKER(FULLNAME, CLASS, DESCFILE, HT, G, H) FULLNAME "," + #include "clang/StaticAnalyzer/Checkers/Checkers.inc" + #undef GET_CHECKERS + #define GET_PACKAGES + #define PACKAGE(FULLNAME, G, D) FULLNAME "," + #include "clang/StaticAnalyzer/Checkers/Checkers.inc" + #undef GET_PACKAGES + ; + }]>; def analyzer_checker_EQ : Joined<["-"], "analyzer-checker=">, Alias<analyzer_checker>; @@ -188,6 +200,12 @@ def arange_sections : Flag<["-"], "arange_sections">, def dwarf_ext_refs : Flag<["-"], "dwarf-ext-refs">, HelpText<"Generate debug info with external references to clang modules" " or precompiled headers">; +def dwarf_explicit_import : Flag<["-"], "dwarf-explicit-import">, + HelpText<"Generate explicit import from anonymous namespace to containing" + " scope">; +def debug_forward_template_params : Flag<["-"], "debug-forward-template-params">, + HelpText<"Emit complete descriptions of template parameters in forward" + " declarations">; def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def no_implicit_float : Flag<["-"], "no-implicit-float">, @@ -226,6 +244,8 @@ def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">, HelpText<"Turn off struct-path aware Type Based Alias Analysis">; +def new_struct_path_tbaa : Flag<["-"], "new-struct-path-tbaa">, + HelpText<"Enable enhanced struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, @@ -243,8 +263,12 @@ def menable_no_nans : Flag<["-"], "menable-no-nans">, def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, HelpText<"Allow unsafe floating-point math optimizations which may decrease " "precision">; +def mreassociate : Flag<["-"], "mreassociate">, + HelpText<"Allow reassociation transformations for floating-point instructions">; def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; +def mtp : Separate<["-"], "mtp">, + HelpText<"Mode for reading thread pointer">; def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">, HelpText<"Limit float precision to the given value">; def split_stacks : Flag<["-"], "split-stacks">, @@ -295,6 +319,9 @@ def fsanitize_coverage_8bit_counters def fsanitize_coverage_inline_8bit_counters : Flag<["-"], "fsanitize-coverage-inline-8bit-counters">, HelpText<"Enable inline 8-bit counters in sanitizer coverage">; +def fsanitize_coverage_pc_table + : Flag<["-"], "fsanitize-coverage-pc-table">, + HelpText<"Create a table of coverage-instrumented PCs">; def fsanitize_coverage_trace_pc : Flag<["-"], "fsanitize-coverage-trace-pc">, HelpText<"Enable PC tracing in sanitizer coverage">; @@ -304,6 +331,9 @@ def fsanitize_coverage_trace_pc_guard def fsanitize_coverage_no_prune : Flag<["-"], "fsanitize-coverage-no-prune">, HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">; +def fsanitize_coverage_stack_depth + : Flag<["-"], "fsanitize-coverage-stack-depth">, + HelpText<"Enable max stack depth tracing">; def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">, HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, " "or none">, Values<"none,clang,llvm">; @@ -372,8 +402,12 @@ def fcaret_diagnostics_max_lines : HelpText<"Set the maximum number of source lines to show in a caret diagnostic">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; +def verify_EQ : CommaJoined<["-"], "verify=">, + MetaVarName<"<prefixes>">, + HelpText<"Verify diagnostic output using comment directives that start with" + " prefixes in the comma-separated sequence <prefixes>">; def verify : Flag<["-"], "verify">, - HelpText<"Verify diagnostic output using comment directives">; + HelpText<"Equivalent to -verify=expected">; def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">, HelpText<"Ignore unexpected diagnostic messages">; def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">, @@ -409,6 +443,8 @@ def code_completion_patterns : Flag<["-"], "code-completion-patterns">, HelpText<"Include code patterns in code-completion results">; def no_code_completion_globals : Flag<["-"], "no-code-completion-globals">, HelpText<"Do not include global declarations in code-completion results.">; +def no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level-decls">, + 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 disable_free : Flag<["-"], "disable-free">, @@ -678,11 +714,17 @@ def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">, HelpText<"Allow function arguments and returns of type half">; def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, - HelpText<"Set default MS calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall">; + HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">; def finclude_default_header : Flag<["-"], "finclude-default-header">, HelpText<"Include the default header file for OpenCL">; def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">, HelpText<"Preserve 3-component vector type">; +def fwchar_type_EQ : Joined<["-"], "fwchar-type=">, + HelpText<"Select underlying type for wchar_t">, Values<"char,short,int">; +def fsigned_wchar : Flag<["-"], "fsigned-wchar">, + HelpText<"Use a signed type for wchar_t">; +def fno_signed_wchar : Flag<["-"], "fno-signed-wchar">, + HelpText<"Use an unsigned type for wchar_t">; // FIXME: Remove these entirely once functionality/tests have been excised. def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>, diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index aebb36ed0e2b..c1f0a89b5dc8 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -145,7 +145,8 @@ def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias<Wall>; def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias<Wall>; def _SLASH_W3 : CLFlag<"W3">, HelpText<"Enable -Wall">, Alias<Wall>; def _SLASH_W4 : CLFlag<"W4">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>; -def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>; +def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Weverything">, + Alias<W_Joined>, AliasArgs<["everything"]>; def _SLASH_WX : CLFlag<"WX">, HelpText<"Treat warnings as errors">, Alias<W_Joined>, AliasArgs<["error"]>; def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">, @@ -153,6 +154,8 @@ def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">, def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>; def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>, AliasArgs<["no-macro-redefined"]>; +def _SLASH_wd4018 : CLFlag<"wd4018">, Alias<W_Joined>, + AliasArgs<["no-sign-compare"]>; def _SLASH_wd4100 : CLFlag<"wd4100">, Alias<W_Joined>, AliasArgs<["no-unused-parameter"]>; def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>, @@ -302,6 +305,8 @@ def _SLASH_Gz : CLFlag<"Gz">, HelpText<"Set __stdcall as a default calling convention">; def _SLASH_Gv : CLFlag<"Gv">, HelpText<"Set __vectorcall as a default calling convention">; +def _SLASH_Gregcall : CLFlag<"Gregcall">, + HelpText<"Set __regcall as a default calling convention">; // Ignored: diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 036b04605ac7..89c0def6c57a 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -99,8 +99,8 @@ class Compilation { /// only be removed if we crash. ArgStringMap FailureResultFiles; - /// Redirection for stdout, stderr, etc. - const StringRef **Redirects; + /// Optional redirection for stdin, stdout, stderr. + std::vector<Optional<StringRef>> Redirects; /// Whether we're compiling for diagnostic purposes. bool ForDiagnostics; @@ -283,12 +283,10 @@ public: /// Redirect - Redirect output of this compilation. Can only be done once. /// - /// \param Redirects - array of pointers to paths. The array - /// should have a size of three. The inferior process's - /// stdin(0), stdout(1), and stderr(2) will be redirected to the - /// corresponding paths. This compilation instance becomes - /// the owner of Redirects and will delete the array and StringRef's. - void Redirect(const StringRef** Redirects); + /// \param Redirects - array of optional paths. The array should have a size + /// of three. The inferior process's stdin(0), stdout(1), and stderr(2) will + /// be redirected to the corresponding paths, if provided (not llvm::None). + void Redirect(ArrayRef<Optional<StringRef>> Redirects); }; } // end namespace driver diff --git a/include/clang/Driver/Distro.h b/include/clang/Driver/Distro.h index fab49862a442..4ab4e2ae9937 100644 --- a/include/clang/Driver/Distro.h +++ b/include/clang/Driver/Distro.h @@ -26,12 +26,14 @@ public: // NB: Releases of a particular Linux distro should be kept together // in this enum, because some tests are done by integer comparison against // the first and last known member in the family, e.g. IsRedHat(). + AlpineLinux, ArchLinux, DebianLenny, DebianSqueeze, DebianWheezy, DebianJessie, DebianStretch, + DebianBuster, Exherbo, RHEL5, RHEL6, @@ -58,6 +60,7 @@ public: UbuntuYakkety, UbuntuZesty, UbuntuArtful, + UbuntuBionic, UnknownDistro }; @@ -107,11 +110,15 @@ public: } bool IsDebian() const { - return DistroVal >= DebianLenny && DistroVal <= DebianStretch; + return DistroVal >= DebianLenny && DistroVal <= DebianBuster; } bool IsUbuntu() const { - return DistroVal >= UbuntuHardy && DistroVal <= UbuntuArtful; + return DistroVal >= UbuntuHardy && DistroVal <= UbuntuBionic; + } + + bool IsAlpineLinux() const { + return DistroVal == AlpineLinux; } /// @} diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 5a087eea1b4e..a3662872a953 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -129,6 +129,9 @@ public: /// The original path to the clang executable. std::string ClangExecutable; + /// Target and driver mode components extracted from clang executable name. + ParsedClangName ClangNameParts; + /// The path to the installed clang directory, if any. std::string InstalledDir; @@ -148,9 +151,6 @@ public: /// Dynamic loader prefix, if present std::string DyldPrefix; - /// If the standard library is used - bool UseStdLib; - /// Driver title to use with help. std::string DriverTitle; @@ -287,6 +287,8 @@ public: void setCheckInputsExist(bool Value) { CheckInputsExist = Value; } + void setTargetAndMode(const ParsedClangName &TM) { ClangNameParts = TM; } + const std::string &getTitle() { return DriverTitle; } void setTitle(std::string Value) { DriverTitle = std::move(Value); } @@ -423,6 +425,10 @@ public: // FIXME: This should be in CompilationInfo. std::string GetProgramPath(StringRef Name, const ToolChain &TC) const; + /// handleAutocompletions - Handle --autocomplete by searching and printing + /// possible flags, descriptions, and its arguments. + void handleAutocompletions(StringRef PassedFlags) const; + /// HandleImmediateArgs - Handle any arguments which should be /// treated before building actions or binding tools. /// diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index ff88256b8c0d..b74b3b4b35e1 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -97,8 +97,8 @@ public: virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const; - virtual int Execute(const StringRef **Redirects, std::string *ErrMsg, - bool *ExecutionFailed) const; + virtual int Execute(ArrayRef<Optional<StringRef>> Redirects, + std::string *ErrMsg, bool *ExecutionFailed) const; /// getSource - Return the Action which caused the creation of this job. const Action &getSource() const { return Source; } @@ -141,7 +141,7 @@ public: void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const override; - int Execute(const StringRef **Redirects, std::string *ErrMsg, + int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, bool *ExecutionFailed) const override; private: @@ -158,7 +158,7 @@ public: void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const override; - int Execute(const StringRef **Redirects, std::string *ErrMsg, + int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg, bool *ExecutionFailed) const override; }; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 05dc9d7eb3ad..d36e1a63220e 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -139,6 +139,10 @@ def m_arm_Features_Group : OptionGroup<"<arm features group>">, Group<m_Group>, DocName<"ARM">; def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">, Group<m_Group>, DocName<"Hexagon">; +// The features added by this group will not be added to target features. +// These are explicitly handled. +def m_hexagon_Features_HVX_Group : OptionGroup<"<hexagon features group>">, + Group<m_Group>, DocName<"Hexagon">; def m_ppc_Features_Group : OptionGroup<"<ppc features group>">, Group<m_Group>, DocName<"PowerPC">; def m_wasm_Features_Group : OptionGroup<"<wasm features group>">, @@ -459,6 +463,10 @@ def Xcuda_fatbinary : Separate<["-"], "Xcuda-fatbinary">, HelpText<"Pass <arg> to fatbinary invocation">, MetaVarName<"<arg>">; def Xcuda_ptxas : Separate<["-"], "Xcuda-ptxas">, HelpText<"Pass <arg> to the ptxas assembler">, MetaVarName<"<arg>">; +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>">; def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">, Group<Link_Group>; @@ -511,7 +519,7 @@ def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-round def client__name : JoinedOrSeparate<["-"], "client_name">; def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>; def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">; -def coverage : Flag<["-", "--"], "coverage">; +def coverage : Flag<["-", "--"], "coverage">, Flags<[CoreOption]>; def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>; def current__version : JoinedOrSeparate<["-"], "current_version">; def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>, @@ -588,7 +596,9 @@ def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]> HelpText<"Use Apple's kernel extensions ABI">; def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable Apple gcc-compatible #pragma pack handling">; -def shared_libasan : Flag<["-"], "shared-libasan">; +def shared_libsan : Flag<["-"], "shared-libsan">; +def static_libsan : Flag<["-"], "static-libsan">; +def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>; def fasm : Flag<["-"], "fasm">, Group<f_Group>; def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]>; @@ -600,6 +610,13 @@ def fastf : Flag<["-"], "fastf">, Group<f_Group>; def fast : Flag<["-"], "fast">, Group<f_Group>; def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group<f_Group>; +def fdouble_square_bracket_attributes : Flag<[ "-" ], "fdouble-square-bracket-attributes">, + Group<f_Group>, Flags<[DriverOption, CC1Option]>, + HelpText<"Enable '[[]]' attributes in all C and C++ language modes">; +def fno_double_square_bracket_attributes : Flag<[ "-" ], "fno-double-square-bracket-attributes">, + Group<f_Group>, Flags<[DriverOption, CC1Option]>, + HelpText<"Disable '[[]]' attributes in all C and C++ language modes">; + def fautolink : Flag <["-"], "fautolink">, Group<f_Group>; def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, @@ -633,12 +650,25 @@ def fno_profile_sample_use : Flag<["-"], "fno-profile-sample-use">, Group<f_Grou def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, HelpText<"Enable sample-based profile guided optimizations">; +def fprofile_sample_accurate : Flag<["-"], "fprofile-sample-accurate">, + Group<f_Group>, Flags<[DriverOption, CC1Option]>, + HelpText<"Specifies that the sample profile is accurate">, + DocBrief<[{Specifies that the sample profile is accurate. If the sample + profile is accurate, callsites without profile samples are marked + as cold. Otherwise, treat callsites without profile samples as if + we have no profile}]>; +def fno_profile_sample_accurate : Flag<["-"], "fno-profile-sample-accurate">, + Group<f_Group>, Flags<[DriverOption]>; def fauto_profile : Flag<["-"], "fauto-profile">, Group<f_Group>, Alias<fprofile_sample_use>; def fno_auto_profile : Flag<["-"], "fno-auto-profile">, Group<f_Group>, Alias<fno_profile_sample_use>; def fauto_profile_EQ : Joined<["-"], "fauto-profile=">, Alias<fprofile_sample_use_EQ>; +def fauto_profile_accurate : Flag<["-"], "fauto-profile-accurate">, + Group<f_Group>, Alias<fprofile_sample_accurate>; +def fno_auto_profile_accurate : Flag<["-"], "fno-auto-profile-accurate">, + Group<f_Group>, Alias<fno_profile_sample_accurate>; def fdebug_info_for_profiling : Flag<["-"], "fdebug-info-for-profiling">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Emit extra debug info to make sample profile more accurate.">; @@ -770,8 +800,12 @@ def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>; def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>; def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; +def fdwarf_exceptions : Flag<["-"], "fdwarf-exceptions">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Use DWARF style exceptions">; def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">; +def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group<clang_ignored_gcc_optimization_f_Group>; def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>; @@ -834,6 +868,9 @@ def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-o def fsanitize_memory_use_after_dtor : Flag<["-"], "fsanitize-memory-use-after-dtor">, Group<f_clang_Group>, HelpText<"Enable use-after-destroy detection in MemorySanitizer">; +def fno_sanitize_memory_use_after_dtor : Flag<["-"], "fno-sanitize-memory-use-after-dtor">, + Group<f_clang_Group>, + HelpText<"Disable use-after-destroy detection in MemorySanitizer">; def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">, Group<f_clang_Group>, HelpText<"Level of field padding for AddressSanitizer">; @@ -868,6 +905,10 @@ def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on Group<f_clang_Group>; def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, Group<f_clang_Group>; +def fsanitize_minimal_runtime : Flag<["-"], "fsanitize-minimal-runtime">, + Group<f_clang_Group>; +def fno_sanitize_minimal_runtime : Flag<["-"], "fno-sanitize-minimal-runtime">, + Group<f_clang_Group>; def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">, Group<f_clang_Group>; def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">, @@ -877,6 +918,9 @@ def fno_sanitize_cfi_cross_dso : Flag<["-"], "fno-sanitize-cfi-cross-dso">, Flags<[CoreOption, DriverOption]>, Group<f_clang_Group>, HelpText<"Disable control flow integrity (CFI) checks for cross-DSO calls.">; +def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-generalize-pointers">, + Group<f_clang_Group>, + HelpText<"Generalize pointers in CFI indirect call type signature checks">; def fsanitize_stats : Flag<["-"], "fsanitize-stats">, Group<f_clang_Group>, HelpText<"Enable sanitizer statistics gathering.">; @@ -988,6 +1032,10 @@ def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>; def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>; def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Generate calls to instrument function entry and exit">; +def finstrument_functions_after_inlining : Flag<["-"], "finstrument-functions-after-inlining">, Group<f_Group>, Flags<[CC1Option]>, + 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 fxray_instrument : Flag<["-"], "fxray-instrument">, Group<f_Group>, Flags<[CC1Option]>, @@ -1012,6 +1060,19 @@ def fxray_never_instrument : Group<f_Group>, Flags<[CC1Option]>, HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; +def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Determine whether to always emit __xray_customevent(...) calls even if the function it appears in is not always instrumented.">; +def fnoxray_always_emit_customevents : Flag<["-"], "fno-xray-always-emit-customevents">, Group<f_Group>, + Flags<[CC1Option]>; + +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.">; +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.">; + def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>; @@ -1104,8 +1165,8 @@ def fmodule_map_file : Joined<["-"], "fmodule-map-file=">, Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<file>">, HelpText<"Load this module map file">; def fmodule_file : Joined<["-"], "fmodule-file=">, - Group<f_Group>, Flags<[DriverOption,CC1Option]>, - HelpText<"Load this precompiled module file">, MetaVarName<"<file>">; + Group<i_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"[<name>=]<file>">, + HelpText<"Specify the mapping of module name to precompiled module file, or load a module file if name is omitted.">; def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Ignore the definition of the given macro when building and loading modules">; def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>, @@ -1310,6 +1371,10 @@ def fopenmp_targets_EQ : CommaJoined<["-"], "fopenmp-targets=">, Flags<[DriverOp 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 fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">; @@ -1333,6 +1398,10 @@ def fpic : Flag<["-"], "fpic">, Group<f_Group>; 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 fplt : Flag<["-"], "fplt">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use the PLT to make function calls">; +def fno_plt : Flag<["-"], "fno-plt">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Do not use the PLT to make function calls">; def fropi : Flag<["-"], "fropi">, Group<f_Group>; def fno_ropi : Flag<["-"], "fno-ropi">, Group<f_Group>; def frwpi : Flag<["-"], "frwpi">, Group<f_Group>; @@ -1352,9 +1421,9 @@ 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 fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>, +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>, Flags<[CC1Option]>, +def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, HelpText<"Force wchar_t to be an unsigned int">; def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Which overload candidates to show when overload resolution fails: " @@ -1477,9 +1546,10 @@ def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group> HelpText<"Give global types 'default' visibility and global functions and " "variables 'hidden' visibility by default">; def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Group>, - Flags<[CC1Option]>, + Flags<[CoreOption, CC1Option]>, HelpText<"Enables whole-program vtable optimization. Requires -flto">; -def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>; +def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-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]>, @@ -1571,7 +1641,7 @@ def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>; def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[CoreOption]>; 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>; +def ggnu_pubnames : Flag<["-"], "ggnu-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" @@ -1644,8 +1714,6 @@ def m16 : Flag<["-"], "m16">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>, HelpText<"Enable hexagon-qdsp6 backward compatibility">; -def m3dnowa : Flag<["-"], "m3dnowa">, Group<m_x86_Features_Group>; -def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>; def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def mx32 : Flag<["-"], "mx32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>; @@ -1664,6 +1732,8 @@ def mexecute_only : Flag<["-"], "mexecute-only">, Group<m_arm_Features_Group>, HelpText<"Disallow generation of data access to code sections (ARM only)">; def mno_execute_only : Flag<["-"], "mno-execute-only">, Group<m_arm_Features_Group>, HelpText<"Allow generation of data access to code sections (ARM only)">; +def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft, cp15">, + HelpText<"Read thread pointer from coprocessor register (ARM only)">; def mpure_code : Flag<["-"], "mpure-code">, Alias<mexecute_only>; // Alias for GCC compatibility def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias<mno_execute_only>; def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>; @@ -1730,13 +1800,9 @@ def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1 def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">, Values<"default,4,5,gnu">; -def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>; -def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>; -def mno_3dnow : Flag<["-"], "mno-3dnow">, Group<m_x86_Features_Group>; def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group<m_Group>; def mno_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Disable merging of globals">; -def mno_mmx : Flag<["-"], "mno-mmx">, Group<m_x86_Features_Group>; def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">, Alias<fno_pascal_strings>; def mno_red_zone : Flag<["-"], "mno-red-zone">, Group<m_Group>; @@ -1744,65 +1810,6 @@ def mno_relax_all : Flag<["-"], "mno-relax-all">, Group<m_Group>; 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 mno_x87 : Flag<["-"], "mno-x87">, Group<m_x86_Features_Group>; -def mno_80387 : Flag<["-"], "mno-80387">, Alias<mno_x87>; -def mno_sse2 : Flag<["-"], "mno-sse2">, Group<m_x86_Features_Group>; -def mno_sse3 : Flag<["-"], "mno-sse3">, Group<m_x86_Features_Group>; -def mno_sse4a : Flag<["-"], "mno-sse4a">, Group<m_x86_Features_Group>; -def mno_sse4_1 : Flag<["-"], "mno-sse4.1">, Group<m_x86_Features_Group>; -def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group<m_x86_Features_Group>; -// -mno-sse4 turns off sse4.1 which has the effect of turning off everything -// later than 4.1. -msse4 turns on 4.2 which has the effect of turning on -// everything earlier than 4.2. -def mno_sse4 : Flag<["-"], "mno-sse4">, Alias<mno_sse4_1>; -def mno_sse : Flag<["-"], "mno-sse">, Group<m_x86_Features_Group>; -def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group<m_x86_Features_Group>; -def mno_aes : Flag<["-"], "mno-aes">, Group<m_x86_Features_Group>; -def mno_avx : Flag<["-"], "mno-avx">, Group<m_x86_Features_Group>; -def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>; -def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>; -def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>; -def mno_avx512vpopcntdq : Flag<["-"], "mno-avx512vpopcntdq">, Group<m_x86_Features_Group>; -def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>; -def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>; -def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>; -def mno_avx512bw : Flag<["-"], "mno-avx512bw">, Group<m_x86_Features_Group>; -def mno_avx512vl : Flag<["-"], "mno-avx512vl">, Group<m_x86_Features_Group>; -def mno_avx512vbmi : Flag<["-"], "mno-avx512vbmi">, Group<m_x86_Features_Group>; -def mno_avx512ifma : Flag<["-"], "mno-avx512ifma">, Group<m_x86_Features_Group>; -def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>; -def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>; -def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>; -def mno_fsgsbase : Flag<["-"], "mno-fsgsbase">, Group<m_x86_Features_Group>; -def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>; -def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>; -def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>; -def mno_tbm : Flag<["-"], "mno-tbm">, Group<m_x86_Features_Group>; -def mno_lwp : Flag<["-"], "mno-lwp">, Group<m_x86_Features_Group>; -def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>; -def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>; -def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>; -def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>; -def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>; -def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>; -def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>; -def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>; -def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>; -def mno_cx16 : Flag<["-"], "mno-cx16">, Group<m_x86_Features_Group>; -def mno_fxsr : Flag<["-"], "mno-fxsr">, Group<m_x86_Features_Group>; -def mno_xsave : Flag<["-"], "mno-xsave">, Group<m_x86_Features_Group>; -def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>; -def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>; -def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>; -def mno_mwaitx : Flag<["-"], "mno-mwaitx">, Group<m_x86_Features_Group>; -def mno_clzero : Flag<["-"], "mno-clzero">, Group<m_x86_Features_Group>; -def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>; -def mno_clflushopt : Flag<["-"], "mno-clflushopt">, Group<m_x86_Features_Group>; -def mno_clwb : Flag<["-"], "mno-clwb">, Group<m_x86_Features_Group>; -def mno_movbe : Flag<["-"], "mno-movbe">, Group<m_x86_Features_Group>; -def mno_mpx : Flag<["-"], "mno-mpx">, Group<m_x86_Features_Group>; -def mno_sgx : Flag<["-"], "mno-sgx">, Group<m_x86_Features_Group>; -def mno_prefetchwt1 : Flag<["-"], "mno-prefetchwt1">, Group<m_x86_Features_Group>; def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">; @@ -1829,7 +1836,6 @@ def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group<m_arm_Features_ def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>, HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">; - def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">, Group<m_aarch64_Features_Group>, HelpText<"Workaround Cortex-A53 erratum 835769 (AArch64 only)">; @@ -1841,12 +1847,18 @@ def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>, 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 mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">, Flags<[HelpHidden]>, Group<m_Group>, HelpText<"Generate additional code for specified <version> of debugger ABI (AMDGPU only)">, MetaVarName<"<version>">; +def mxnack : Flag<["-"], "mxnack">, Group<m_amdgpu_Features_Group>, + HelpText<"Enable XNACK (AMDGPU only)">; +def mno_xnack : Flag<["-"], "mno-xnack">, Group<m_amdgpu_Features_Group>, + HelpText<"Disable XNACK (AMDGPU only)">; def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[DriverOption]>; def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[DriverOption]>; @@ -1942,68 +1954,14 @@ def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>, def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>; def mrecip : Flag<["-"], "mrecip">, Group<m_Group>; def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>; +def mprefer_vector_width_EQ : Joined<["-"], "mprefer-vector-width=">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions.">; def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Use copy relocations support for PIE builds">; 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 mx87 : Flag<["-"], "mx87">, Group<m_x86_Features_Group>; -def m80387 : Flag<["-"], "m80387">, Alias<mx87>; -def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>; -def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>; -def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>; -def msse4_1 : Flag<["-"], "msse4.1">, Group<m_x86_Features_Group>; -def msse4_2 : Flag<["-"], "msse4.2">, Group<m_x86_Features_Group>; -def msse4 : Flag<["-"], "msse4">, Alias<msse4_2>; -def msse : Flag<["-"], "msse">, Group<m_x86_Features_Group>; -def mssse3 : Flag<["-"], "mssse3">, Group<m_x86_Features_Group>; -def maes : Flag<["-"], "maes">, Group<m_x86_Features_Group>; -def mavx : Flag<["-"], "mavx">, Group<m_x86_Features_Group>; -def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>; -def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>; -def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>; -def mavx512vpopcntdq : Flag<["-"], "mavx512vpopcntdq">, Group<m_x86_Features_Group>; -def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>; -def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>; -def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>; -def mavx512bw : Flag<["-"], "mavx512bw">, Group<m_x86_Features_Group>; -def mavx512vl : Flag<["-"], "mavx512vl">, Group<m_x86_Features_Group>; -def mavx512vbmi : Flag<["-"], "mavx512vbmi">, Group<m_x86_Features_Group>; -def mavx512ifma : Flag<["-"], "mavx512ifma">, Group<m_x86_Features_Group>; -def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>; -def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>; -def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>; -def mfsgsbase : Flag<["-"], "mfsgsbase">, Group<m_x86_Features_Group>; -def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>; -def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>; -def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>; -def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>; -def mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>; -def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>; -def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>; -def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>; -def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>; -def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>; -def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>; -def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>; -def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>; -def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>; -def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>; -def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>; -def mfxsr : Flag<["-"], "mfxsr">, Group<m_x86_Features_Group>; -def mxsave : Flag<["-"], "mxsave">, Group<m_x86_Features_Group>; -def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>; -def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>; -def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>; -def mmwaitx : Flag<["-"], "mmwaitx">, Group<m_x86_Features_Group>; -def mclzero : Flag<["-"], "mclzero">, Group<m_x86_Features_Group>; -def mclflushopt : Flag<["-"], "mclflushopt">, Group<m_x86_Features_Group>; -def mclwb : Flag<["-"], "mclwb">, Group<m_x86_Features_Group>; -def mmovbe : Flag<["-"], "mmovbe">, Group<m_x86_Features_Group>; -def mmpx : Flag<["-"], "mmpx">, Group<m_x86_Features_Group>; -def msgx : Flag<["-"], "msgx">, Group<m_x86_Features_Group>; -def mprefetchwt1 : Flag<["-"], "mprefetchwt1">, Group<m_x86_Features_Group>; def mips16 : Flag<["-"], "mips16">, Group<m_Group>; def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>; def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>; @@ -2016,6 +1974,10 @@ def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, Group<m_Group>; def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">, Group<m_Group>; def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, Group<m_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>; @@ -2038,7 +2000,30 @@ def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>, HelpText<"Use 64-bit floating point registers (MIPS only)">; def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>, HelpText<"Use 32-bit floating point registers (MIPS only)">; +def mgpopt : Flag<["-"], "mgpopt">, Group<m_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>, + 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>, + HelpText<"Extend the -G behaviour to object local data (MIPS)">; +def mno_local_sdata : Flag<["-"], "mno-local-sdata">, Group<m_Group>, + HelpText<"Do not extend the -G behaviour to object local data (MIPS)">; +def mextern_sdata : Flag<["-"], "mextern-sdata">, Group<m_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>, + 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>, + 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>, + 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>, HelpText<"Enable SVR4-style position-independent code (Mips only)">; def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_Group>, @@ -2131,6 +2116,7 @@ def nostdlibinc : Flag<["-"], "nostdlibinc">; def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>, HelpText<"Disable standard #include directories for the C++ standard library">; def nostdlib : Flag<["-"], "nostdlib">; +def nostdlibxx : Flag<["-"], "nostdlib++">; def object : Flag<["-"], "object">; def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>, HelpText<"Write output to <file>">, MetaVarName<"<file>">; @@ -2225,7 +2211,14 @@ def static_libstdcxx : Flag<["-"], "static-libstdc++">; def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>; def std_default_EQ : Joined<["-"], "std-default=">; def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, - Group<CompileOnly_Group>, HelpText<"Language standard to compile for">; + Group<CompileOnly_Group>, HelpText<"Language standard to compile for">, + ValuesCode<[{ + const char *Values = + #define LANGSTANDARD(id, name, lang, desc, features) name "," + #define LANGSTANDARD_ALIAS(id, alias) alias "," + #include "clang/Frontend/LangStandards.def" + ; + }]>; def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>, HelpText<"C++ standard library to use">, Values<"libc++,libstdc++,platform">; def sub__library : JoinedOrSeparate<["-"], "sub_library">; @@ -2383,7 +2376,8 @@ def _rtlib : Separate<["--"], "rtlib">, Alias<rtlib_EQ>; def _serialize_diags : Separate<["-", "--"], "serialize-diagnostics">, Flags<[DriverOption]>, HelpText<"Serialize compiler diagnostics to a file">; // We give --version different semantics from -version. -def _version : Flag<["--"], "version">, Flags<[CC1Option]>; +def _version : Flag<["--"], "version">, Flags<[CoreOption, CC1Option]>, + HelpText<"Print version information">; def _signed_char : Flag<["--"], "signed-char">, Alias<fsigned_char>; def _std : Separate<["--"], "std">, Alias<std_EQ>; def _stdlib : Separate<["--"], "stdlib">, Alias<stdlib_EQ>; @@ -2413,14 +2407,156 @@ def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>; def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>; -def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_Group>, - Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">; -def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>, - Flags<[CC1Option]>, HelpText<"Disable Hexagon Vector eXtensions">; -def mhexagon_hvx_double : Flag<["-"], "mhvx-double">, Group<m_hexagon_Features_Group>, - Flags<[CC1Option]>, HelpText<"Enable Hexagon Double Vector eXtensions">; -def mno_hexagon_hvx_double : Flag<["-"], "mno-hvx-double">, Group<m_hexagon_Features_Group>, - Flags<[CC1Option]>, HelpText<"Disable Hexagon Double Vector eXtensions">; +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">; + + +// X86 feature flags +def mx87 : Flag<["-"], "mx87">, Group<m_x86_Features_Group>; +def mno_x87 : Flag<["-"], "mno-x87">, Group<m_x86_Features_Group>; +def m80387 : Flag<["-"], "m80387">, Alias<mx87>; +def mno_80387 : Flag<["-"], "mno-80387">, Alias<mno_x87>; +def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>; +def mno_mmx : Flag<["-"], "mno-mmx">, Group<m_x86_Features_Group>; +def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>; +def mno_3dnow : Flag<["-"], "mno-3dnow">, Group<m_x86_Features_Group>; +def m3dnowa : Flag<["-"], "m3dnowa">, Group<m_x86_Features_Group>; +def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>; +def msse : Flag<["-"], "msse">, Group<m_x86_Features_Group>; +def mno_sse : Flag<["-"], "mno-sse">, Group<m_x86_Features_Group>; +def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>; +def mno_sse2 : Flag<["-"], "mno-sse2">, Group<m_x86_Features_Group>; +def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>; +def mno_sse3 : Flag<["-"], "mno-sse3">, Group<m_x86_Features_Group>; +def mssse3 : Flag<["-"], "mssse3">, Group<m_x86_Features_Group>; +def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group<m_x86_Features_Group>; +def msse4_1 : Flag<["-"], "msse4.1">, Group<m_x86_Features_Group>; +def mno_sse4_1 : Flag<["-"], "mno-sse4.1">, Group<m_x86_Features_Group>; +def msse4_2 : Flag<["-"], "msse4.2">, Group<m_x86_Features_Group>; +def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group<m_x86_Features_Group>; +def msse4 : Flag<["-"], "msse4">, Alias<msse4_2>; +// -mno-sse4 turns off sse4.1 which has the effect of turning off everything +// later than 4.1. -msse4 turns on 4.2 which has the effect of turning on +// everything earlier than 4.2. +def mno_sse4 : Flag<["-"], "mno-sse4">, Alias<mno_sse4_1>; +def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>; +def mno_sse4a : Flag<["-"], "mno-sse4a">, Group<m_x86_Features_Group>; +def mavx : Flag<["-"], "mavx">, Group<m_x86_Features_Group>; +def mno_avx : Flag<["-"], "mno-avx">, Group<m_x86_Features_Group>; +def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>; +def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>; +def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>; +def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>; +def mavx512bw : Flag<["-"], "mavx512bw">, Group<m_x86_Features_Group>; +def mno_avx512bw : Flag<["-"], "mno-avx512bw">, Group<m_x86_Features_Group>; +def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>; +def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>; +def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>; +def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>; +def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>; +def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>; +def mavx512ifma : Flag<["-"], "mavx512ifma">, Group<m_x86_Features_Group>; +def mno_avx512ifma : Flag<["-"], "mno-avx512ifma">, Group<m_x86_Features_Group>; +def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>; +def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>; +def mavx512vbmi : Flag<["-"], "mavx512vbmi">, Group<m_x86_Features_Group>; +def mno_avx512vbmi : Flag<["-"], "mno-avx512vbmi">, Group<m_x86_Features_Group>; +def mavx512vl : Flag<["-"], "mavx512vl">, Group<m_x86_Features_Group>; +def mno_avx512vl : Flag<["-"], "mno-avx512vl">, Group<m_x86_Features_Group>; +def mavx512vpopcntdq : Flag<["-"], "mavx512vpopcntdq">, Group<m_x86_Features_Group>; +def mno_avx512vpopcntdq : Flag<["-"], "mno-avx512vpopcntdq">, Group<m_x86_Features_Group>; +def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>; +def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>; +def maes : Flag<["-"], "maes">, Group<m_x86_Features_Group>; +def mno_aes : Flag<["-"], "mno-aes">, Group<m_x86_Features_Group>; +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 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 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>; +def mno_cx16 : Flag<["-"], "mno-cx16">, Group<m_x86_Features_Group>; +def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>; +def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>; +def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>; +def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>; +def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>; +def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>; +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 mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>; +def mno_lwp : Flag<["-"], "mno-lwp">, Group<m_x86_Features_Group>; +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 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>; +def mno_mwaitx : Flag<["-"], "mno-mwaitx">, Group<m_x86_Features_Group>; +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 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 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 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>; +def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>; +def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>; +def mno_tbm : Flag<["-"], "mno-tbm">, 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>; +def mno_xsave : Flag<["-"], "mno-xsave">, Group<m_x86_Features_Group>; +def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>; +def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>; +def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>; +def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>; +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>; // 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 diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index a9645d463fa1..a31ac05afc1b 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -32,41 +32,49 @@ class SanitizerArgs { int MsanTrackOrigins = 0; bool MsanUseAfterDtor = false; bool CfiCrossDso = false; + bool CfiICallGeneralizePointers = false; int AsanFieldPadding = 0; - bool AsanSharedRuntime = false; + bool SharedRuntime = false; bool AsanUseAfterScope = true; bool AsanGlobalsDeadStripping = false; bool LinkCXXRuntimes = false; bool NeedPIE = false; + bool SafeStackRuntime = false; bool Stats = false; bool TsanMemoryAccess = true; bool TsanFuncEntryExit = true; bool TsanAtomics = true; + bool MinimalRuntime = false; + // True if cross-dso CFI support if provided by the system (i.e. Android). + bool ImplicitCfiRuntime = false; public: /// Parses the sanitizer arguments from an argument list. SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); + bool needsSharedRt() const { return SharedRuntime; } + bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); } - bool needsSharedAsanRt() const { return AsanSharedRuntime; } + bool needsHwasanRt() const { return Sanitizers.has(SanitizerKind::HWAddress); } bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); } bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); } bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); } bool needsLsanRt() const { return Sanitizers.has(SanitizerKind::Leak) && - !Sanitizers.has(SanitizerKind::Address); + !Sanitizers.has(SanitizerKind::Address) && + !Sanitizers.has(SanitizerKind::HWAddress); } bool needsUbsanRt() const; + bool requiresMinimalRuntime() const { return MinimalRuntime; } bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); } - bool needsSafeStackRt() const { - return Sanitizers.has(SanitizerKind::SafeStack); - } + bool needsSafeStackRt() const { return SafeStackRuntime; } bool needsCfiRt() const; bool needsCfiDiagRt() const; bool needsStatsRt() const { return Stats; } bool needsEsanRt() const { return Sanitizers.hasOneOf(SanitizerKind::Efficiency); } + bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); } bool requiresPIE() const; bool needsUnwindTables() const; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 6651491e5b27..13f54d3718b4 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -40,12 +40,35 @@ namespace driver { class Compilation; class CudaInstallationDetector; class Driver; + class InputInfo; class JobAction; class RegisterEffectiveTriple; 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; + /// True if TargetPrefix is recognized as a registered target name. + bool TargetIsValid; + + ParsedClangName() : DriverMode(nullptr), TargetIsValid(false) {} + ParsedClangName(std::string Suffix, const char *Mode) + : ModeSuffix(Suffix), DriverMode(Mode), TargetIsValid(false) {} + ParsedClangName(std::string Target, std::string Suffix, const char *Mode, + bool IsRegistered) + : TargetPrefix(Target), ModeSuffix(Suffix), DriverMode(Mode), + TargetIsValid(IsRegistered) {} +}; + /// ToolChain - Access to tools for a single platform. class ToolChain { public: @@ -70,7 +93,7 @@ public: private: const Driver &D; - const llvm::Triple Triple; + llvm::Triple Triple; const llvm::opt::ArgList &Args; // We need to initialize CachedRTTIArg before CachedRTTIMode const llvm::opt::Arg *const CachedRTTIArg; @@ -113,6 +136,8 @@ protected: ToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args); + void setTripleEnvironment(llvm::Triple::EnvironmentType Env); + virtual Tool *buildAssembler() const; virtual Tool *buildLinker() const; virtual Tool *getTool(Action::ActionClass AC) const; @@ -150,6 +175,11 @@ public: /// while the aux triple is the host (CPU) toolchain, e.g. x86-linux-gnu. virtual const llvm::Triple *getAuxTriple() const { return nullptr; } + /// Some toolchains need to modify the file name, for example to replace the + /// extension for object files with .cubin for OpenMP offloading to Nvidia + /// GPUs. + virtual std::string getInputFilename(const InputInfo &Input) const; + llvm::Triple::ArchType getArch() const { return Triple.getArch(); } StringRef getArchName() const { return Triple.getArchName(); } StringRef getPlatform() const { return Triple.getVendorName(); } @@ -193,13 +223,16 @@ public: /// For example, when called with i686-linux-android-g++, the first element /// of the return value will be set to `"i686-linux-android"` and the second /// will be set to "--driver-mode=g++"`. + /// It is OK if the target name is not registered. In this case the return + /// value contains false in the field TargetIsValid. /// /// \pre `llvm::InitializeAllTargets()` has been called. /// \param ProgName The name the Clang driver was invoked with (from, - /// e.g., argv[0]) - /// \return A pair of (`target`, `mode-flag`), where one or both may be empty. - static std::pair<std::string, std::string> - getTargetAndModeFromProgramName(StringRef ProgName); + /// e.g., argv[0]). + /// \return A structure of type ParsedClangName that contains the executable + /// name parts. + /// + static ParsedClangName getTargetAndModeFromProgramName(StringRef ProgName); // Tool access. @@ -217,6 +250,13 @@ public: return nullptr; } + /// TranslateOpenMPTargetArgs - Create a new derived argument list for + /// that contains the OpenMP target specific flags passed via + /// -Xopenmp-target -opt=val OR -Xopenmp-target=<triple> -opt=val + virtual llvm::opt::DerivedArgList *TranslateOpenMPTargetArgs( + const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, + SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const; + /// Choose a tool to use to handle the action \p JA. /// /// This can be overridden when a particular ToolChain needs to use @@ -278,6 +318,9 @@ public: /// mixed dispatch method be used? virtual bool UseObjCMixedDispatch() const { return false; } + /// \brief Check whether to enable x86 relax relocations by default. + virtual bool useRelaxRelocations() const; + /// GetDefaultStackProtectorLevel - Get the default stack protector level for /// this tool chain (0=off, 1=on, 2=strong, 3=all). virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const { @@ -298,6 +341,8 @@ public: return ToolChain::CST_Libstdcxx; } + virtual std::string getCompilerRTPath() const; + virtual std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, bool Shared = false) const; @@ -332,9 +377,6 @@ public: /// SupportsProfiling - Does this tool chain support -pg. virtual bool SupportsProfiling() const { return true; } - /// Does this tool chain support Objective-C garbage collection. - virtual bool SupportsObjCGC() const { return true; } - /// Complain if this tool chain doesn't support Objective-C ARC. virtual void CheckObjCARC() const {} @@ -357,10 +399,9 @@ public: return llvm::DebuggerKind::GDB; } - /// UseSjLjExceptions - Does this tool chain use SjLj exceptions. - virtual bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const { - return false; - } + /// GetExceptionModel - Return the tool chain exception model. + virtual llvm::ExceptionHandling + GetExceptionModel(const llvm::opt::ArgList &Args) const; /// SupportsEmbeddedBitcode - Does this tool chain support embedded bitcode. virtual bool SupportsEmbeddedBitcode() const { @@ -432,6 +473,10 @@ public: AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; + /// Returns if the C++ standard library should be linked in. + /// Note that e.g. -lm should still be linked even if this returns false. + bool ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const; + /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use /// for the given C++ standard library type. virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, diff --git a/include/clang/Driver/XRayArgs.h b/include/clang/Driver/XRayArgs.h index 83210d100a12..e5b76162de8e 100644 --- a/include/clang/Driver/XRayArgs.h +++ b/include/clang/Driver/XRayArgs.h @@ -24,6 +24,7 @@ class XRayArgs { std::vector<std::string> ExtraDeps; bool XRayInstrument = false; int InstructionThreshold = 200; + bool XRayAlwaysEmitCustomEvents = false; public: /// Parses the XRay arguments from an argument list. diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 99d54e55e828..d27d934f7679 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -151,13 +151,20 @@ struct FormatStyle { /// \endcode bool AlignTrailingComments; - /// \brief Allow putting all parameters of a function declaration onto + /// \brief 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 - /// true: false: - /// myFunction(foo, vs. myFunction(foo, bar, plop); - /// bar, - /// plop); + /// true: + /// void myFunction( + /// int a, int b, int c, int d, int e); + /// + /// false: + /// void myFunction(int a, + /// int b, + /// int c, + /// int d, + /// int e); /// \endcode bool AllowAllParametersOfDeclarationOnNextLine; @@ -674,6 +681,20 @@ struct FormatStyle { /// } /// \endcode bool AfterUnion; + /// \brief Wrap extern blocks. + /// \code + /// true: + /// extern "C" + /// { + /// int foo(); + /// } + /// + /// false: + /// extern "C" { + /// int foo(); + /// } + /// \endcode + bool AfterExternBlock; /// \brief Wrap before ``catch``. /// \code /// true: @@ -746,6 +767,14 @@ struct FormatStyle { /// /// If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how /// each individual brace case should be handled. Otherwise, this is ignored. + /// \code{.yaml} + /// # Example of usage: + /// BreakBeforeBraces: Custom + /// BraceWrapping: + /// AfterEnum: true + /// AfterStruct: false + /// SplitEmptyFunction: false + /// \endcode BraceWrappingFlags BraceWrapping; /// \brief If ``true``, ternary operators will be placed after line breaks. @@ -956,6 +985,40 @@ 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. @@ -1024,6 +1087,31 @@ struct FormatStyle { /// \endcode bool IndentCaseLabels; + /// \brief Options for indenting preprocessor directives. + enum PPDirectiveIndentStyle { + /// Does not indent any directives. + /// \code + /// #if FOO + /// #if BAR + /// #include <foo> + /// #endif + /// #endif + /// \endcode + PPDIS_None, + /// Indents directives after the hash. + /// \code + /// #if FOO + /// # if BAR + /// # include <foo> + /// # endif + /// #endif + /// \endcode + PPDIS_AfterHash + }; + + /// \brief The preprocessor directive indenting style to use. + PPDirectiveIndentStyle IndentPPDirectives; + /// \brief The number of columns to use for indentation. /// \code /// IndentWidth: 3 @@ -1273,6 +1361,41 @@ struct FormatStyle { /// \brief 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. + LanguageKind Language; + /// \brief 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 && + BasedOnStyle == Other.BasedOnStyle; + } + }; + + /// \brief Raw string delimiters denoting that the raw string contents are + /// code in a particular language and can be reformatted. + /// + /// 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. + /// + /// To configure this in the .clang-format file, use: + /// \code{.yaml} + /// RawStringFormats: + /// - Delimiter: 'pb' + /// Language: TextProto + /// BasedOnStyle: llvm + /// - Delimiter: 'proto' + /// Language: TextProto + /// BasedOnStyle: google + /// \endcode + std::vector<RawStringFormat> RawStringFormats; + /// \brief If ``true``, clang-format will attempt to re-flow comments. /// \code /// false: @@ -1296,6 +1419,14 @@ struct FormatStyle { bool SortIncludes; /// \brief 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 + /// element of each list is a non-namespace name; all others are namespace + /// names. Sort the lists of names lexicographically, where the sort order of + /// individual names is that all non-namespace names come before all namespace + /// names, and within those groups, names are in case-insensitive + /// lexicographic order. /// \code /// false: true: /// using std::cout; vs. using std::cin; @@ -1512,8 +1643,10 @@ struct FormatStyle { R.ExperimentalAutoDetectBinPacking && FixNamespaceComments == R.FixNamespaceComments && ForEachMacros == R.ForEachMacros && + IncludeBlocks == R.IncludeBlocks && IncludeCategories == R.IncludeCategories && IndentCaseLabels == R.IndentCaseLabels && + IndentPPDirectives == R.IndentPPDirectives && IndentWidth == R.IndentWidth && Language == R.Language && IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && JavaScriptQuotes == R.JavaScriptQuotes && @@ -1537,6 +1670,7 @@ struct FormatStyle { PenaltyExcessCharacter == R.PenaltyExcessCharacter && PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine && PointerAlignment == R.PointerAlignment && + RawStringFormats == R.RawStringFormats && SpaceAfterCStyleCast == R.SpaceAfterCStyleCast && SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword && SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators && diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 1ac4f07a3549..5d04dcd19119 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -448,7 +448,7 @@ public: IntrusiveRefCntPtr<ASTReader> getASTReader() const; - StringRef getOriginalSourceFileName() { + StringRef getOriginalSourceFileName() const { return OriginalSourceFile; } @@ -524,26 +524,26 @@ public: /// \brief 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); + SourceLocation mapLocationFromPreamble(SourceLocation Loc) const; /// \brief 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); + SourceLocation mapLocationToPreamble(SourceLocation Loc) const; - bool isInPreambleFileID(SourceLocation Loc); - bool isInMainFileID(SourceLocation Loc); - SourceLocation getStartOfMainFileID(); - SourceLocation getEndOfPreambleFileID(); + bool isInPreambleFileID(SourceLocation Loc) const; + bool isInMainFileID(SourceLocation Loc) const; + SourceLocation getStartOfMainFileID() const; + SourceLocation getEndOfPreambleFileID() const; /// \see mapLocationFromPreamble. - SourceRange mapRangeFromPreamble(SourceRange R) { + SourceRange mapRangeFromPreamble(SourceRange R) const { return SourceRange(mapLocationFromPreamble(R.getBegin()), mapLocationFromPreamble(R.getEnd())); } /// \see mapLocationToPreamble. - SourceRange mapRangeToPreamble(SourceRange R) { + SourceRange mapRangeToPreamble(SourceRange R) const { return SourceRange(mapLocationToPreamble(R.getBegin()), mapLocationToPreamble(R.getEnd())); } @@ -607,7 +607,7 @@ public: /// \brief Returns true if the ASTUnit was constructed from a serialized /// module file. - bool isModuleFile(); + bool isModuleFile() const; std::unique_ptr<llvm::MemoryBuffer> getBufferForFile(StringRef Filename, std::string *ErrorStr = nullptr); diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 4002415adc45..bb91cf5f742b 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -76,10 +76,17 @@ CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is ///< enabled. +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(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is ///< enabled. +///< Set when -fxray-always-emit-customevents is enabled. +CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) + ///< Set the minimum number of instructions in a function to determine selective ///< XRay instrumentation. VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200) @@ -110,6 +117,7 @@ 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(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. @@ -142,6 +150,7 @@ ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Defa CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. +CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection ///< in AddressSanitizer @@ -152,6 +161,10 @@ CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection ///< in MemorySanitizer CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI. +CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime for + ///< diagnostics. +CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in + ///< CFI icall function signatures CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage ///< instrumentation. CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage @@ -171,10 +184,13 @@ CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters. +CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table. CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. +CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. +CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. @@ -185,6 +201,7 @@ CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns. CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables. CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer. +CODEGENOPT(ProfileSampleAccurate, 1, 0) ///< Sample profile is accurate. /// Attempt to use register sized accesses to bit-fields in structures, when /// possible. @@ -214,6 +231,10 @@ 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. +CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete + ///< template parameter descriptions in + ///< forward declarations (versus just + ///< including them in the name). CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists. @@ -282,6 +303,11 @@ CODEGENOPT(DebugInfoForProfiling, 1, 0) /// Whether 3-component vector type is preserved. CODEGENOPT(PreserveVec3Type, 1, 0) +/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames. +CODEGENOPT(GnuPubnames, 1, 0) + +CODEGENOPT(NoPLT, 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 71730a21dbe2..6b8d2b935fdd 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -251,6 +251,13 @@ public: /// \brief A list of all -fno-builtin-* function names (e.g., memset). std::vector<std::string> NoBuiltinFuncs; + std::vector<std::string> Reciprocals; + + /// The preferred width for auto-vectorization transforms. This is intended to + /// override default transforms based on the width of the architected vector + /// registers. + std::string PreferVectorWidth; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/include/clang/Frontend/CommandLineSourceLoc.h b/include/clang/Frontend/CommandLineSourceLoc.h index a78c96d23afa..f5c1e1a8a67d 100644 --- a/include/clang/Frontend/CommandLineSourceLoc.h +++ b/include/clang/Frontend/CommandLineSourceLoc.h @@ -51,6 +51,52 @@ public: } }; +/// A source range that has been parsed on the command line. +struct ParsedSourceRange { + std::string FileName; + /// The starting location of the range. The first element is the line and + /// the second element is the column. + std::pair<unsigned, unsigned> Begin; + /// The ending location of the range. The first element is the line and the + /// second element is the column. + std::pair<unsigned, unsigned> End; + + /// Returns a parsed source range from a string or None if the string is + /// invalid. + /// + /// These source string has the following format: + /// + /// file:start_line:start_column[-end_line:end_column] + /// + /// If the end line and column are omitted, the starting line and columns + /// are used as the end values. + static Optional<ParsedSourceRange> fromString(StringRef Str) { + std::pair<StringRef, StringRef> RangeSplit = Str.rsplit('-'); + unsigned EndLine, EndColumn; + bool HasEndLoc = false; + if (!RangeSplit.second.empty()) { + std::pair<StringRef, StringRef> Split = RangeSplit.second.rsplit(':'); + if (Split.first.getAsInteger(10, EndLine) || + Split.second.getAsInteger(10, EndColumn)) { + // The string does not end in end_line:end_column, so the '-' + // probably belongs to the filename which menas the whole + // string should be parsed. + RangeSplit.first = Str; + } else + HasEndLoc = true; + } + auto Begin = ParsedSourceLocation::FromString(RangeSplit.first); + if (Begin.FileName.empty()) + return None; + if (!HasEndLoc) { + EndLine = Begin.Line; + EndColumn = Begin.Column; + } + return ParsedSourceRange{std::move(Begin.FileName), + {Begin.Line, Begin.Column}, + {EndLine, EndColumn}}; + } +}; } namespace llvm { diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 5b5c75298a31..90a9501475b5 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -640,7 +640,9 @@ public: const CodeGenOptions *CodeGenOpts = nullptr); /// Create the file manager and replace any existing one with it. - void createFileManager(); + /// + /// \return The new file manager on success, or null on failure. + FileManager *createFileManager(); /// Create the source manager and replace any existing one with it. void createSourceManager(FileManager &FileMgr); diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index c45aeaa208c8..fa1529a3d65d 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -86,10 +86,15 @@ public: /// \brief Compute the AST consumer arguments that will be used to /// create the PCHGenerator instance returned by CreateASTConsumer. /// - /// \returns true if an error occurred, false otherwise. - static std::unique_ptr<raw_pwrite_stream> - ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile, - std::string &Sysroot, std::string &OutputFile); + /// \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 + /// into. On error, returns null. + static std::unique_ptr<llvm::raw_pwrite_stream> + CreateOutputFile(CompilerInstance &CI, StringRef InFile, + std::string &OutputFile); bool BeginSourceFileAction(CompilerInstance &CI) override; }; diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index e757a7e397e3..5192a3774cc1 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -128,21 +128,24 @@ class FrontendInputFile { /// \brief The file name, or "-" to read from standard input. std::string File; - llvm::MemoryBuffer *Buffer; + /// The input, if it comes from a buffer rather than a file. This object + /// does not own the buffer, and the caller is responsible for ensuring + /// that it outlives any users. + llvm::MemoryBuffer *Buffer = nullptr; /// \brief 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). - bool IsSystem; + bool IsSystem = false; public: - FrontendInputFile() : Buffer(nullptr), Kind(), IsSystem(false) { } + FrontendInputFile() { } FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) - : File(File.str()), Buffer(nullptr), Kind(Kind), IsSystem(IsSystem) { } - FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind, + : 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; } diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h index 6731e08bcae8..83e452d884b6 100644 --- a/include/clang/Frontend/LangStandard.h +++ b/include/clang/Frontend/LangStandard.h @@ -22,16 +22,17 @@ enum LangFeatures { LineComment = (1 << 0), C99 = (1 << 1), C11 = (1 << 2), - CPlusPlus = (1 << 3), - CPlusPlus11 = (1 << 4), - CPlusPlus14 = (1 << 5), - CPlusPlus1z = (1 << 6), - CPlusPlus2a = (1 << 7), - Digraphs = (1 << 8), - GNUMode = (1 << 9), - HexFloat = (1 << 10), - ImplicitInt = (1 << 11), - OpenCL = (1 << 12) + C17 = (1 << 3), + CPlusPlus = (1 << 4), + CPlusPlus11 = (1 << 5), + CPlusPlus14 = (1 << 6), + CPlusPlus17 = (1 << 7), + CPlusPlus2a = (1 << 8), + Digraphs = (1 << 9), + GNUMode = (1 << 10), + HexFloat = (1 << 11), + ImplicitInt = (1 << 12), + OpenCL = (1 << 13) }; } @@ -70,6 +71,9 @@ public: /// isC11 - Language is a superset of C11. bool isC11() const { return Flags & frontend::C11; } + /// isC17 - Language is a superset of C17. + bool isC17() const { return Flags & frontend::C17; } + /// isCPlusPlus - Language is a C++ variant. bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } @@ -79,8 +83,8 @@ public: /// isCPlusPlus14 - Language is a C++14 variant (or later). bool isCPlusPlus14() const { return Flags & frontend::CPlusPlus14; } - /// isCPlusPlus1z - Language is a C++17 variant (or later). - bool isCPlusPlus1z() const { return Flags & frontend::CPlusPlus1z; } + /// isCPlusPlus17 - Language is a C++17 variant (or later). + bool isCPlusPlus17() const { return Flags & frontend::CPlusPlus17; } /// isCPlusPlus2a - Language is a post-C++17 variant (or later). bool isCPlusPlus2a() const { return Flags & frontend::CPlusPlus2a; } diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index a019d6392214..e7a081dc2aa7 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -77,6 +77,15 @@ LANGSTANDARD(gnu11, "gnu11", LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat) LANGSTANDARD_ALIAS_DEPR(gnu11, "gnu1x") +// C17 modes +LANGSTANDARD(c17, "c17", + C, "ISO C 2017", + LineComment | C99 | C11 | C17 | Digraphs | HexFloat) +LANGSTANDARD_ALIAS(c17, "iso9899:2017") +LANGSTANDARD(gnu17, "gnu17", + C, "ISO C 2017 with GNU extensions", + LineComment | C99 | C11 | C17 | Digraphs | GNUMode | HexFloat) + // C++ modes LANGSTANDARD(cxx98, "c++98", CXX, "ISO C++ 1998 with amendments", @@ -111,24 +120,24 @@ LANGSTANDARD_ALIAS_DEPR(gnucxx14, "gnu++1y") LANGSTANDARD(cxx17, "c++17", CXX, "ISO C++ 2017 with amendments", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | Digraphs | HexFloat) LANGSTANDARD_ALIAS_DEPR(cxx17, "c++1z") LANGSTANDARD(gnucxx17, "gnu++17", CXX, "ISO C++ 2017 with amendments and GNU extensions", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | Digraphs | HexFloat | GNUMode) LANGSTANDARD_ALIAS_DEPR(gnucxx17, "gnu++1z") LANGSTANDARD(cxx2a, "c++2a", CXX, "Working draft for ISO C++ 2020", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | CPlusPlus2a | Digraphs | HexFloat) LANGSTANDARD(gnucxx2a, "gnu++2a", CXX, "Working draft for ISO C++ 2020 with GNU extensions", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | CPlusPlus2a | Digraphs | HexFloat | GNUMode) // OpenCL diff --git a/include/clang/Frontend/PrecompiledPreamble.h b/include/clang/Frontend/PrecompiledPreamble.h index 8307392e7feb..64342b1dffa8 100644 --- a/include/clang/Frontend/PrecompiledPreamble.h +++ b/include/clang/Frontend/PrecompiledPreamble.h @@ -17,6 +17,7 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/MD5.h" #include <memory> #include <system_error> @@ -36,21 +37,6 @@ class CompilerInvocation; class DeclGroupRef; class PCHContainerOperations; -/// A size of the preamble and a flag required by -/// PreprocessorOptions::PrecompiledPreambleBytes. -struct PreambleBounds { - PreambleBounds(unsigned Size, bool PreambleEndsAtStartOfLine) - : Size(Size), PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {} - - /// \brief Size of the preamble in bytes. - unsigned Size; - /// \brief 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. - bool PreambleEndsAtStartOfLine; -}; - /// \brief Runs lexer to compute suggested preamble bounds. PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, llvm::MemoryBuffer *Buffer, @@ -62,7 +48,7 @@ class PreambleCallbacks; /// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and /// CanReusePreamble + AddImplicitPreamble to make use of it. class PrecompiledPreamble { - class TempPCHFile; + class PCHStorage; struct PreambleFileHash; public: @@ -85,6 +71,9 @@ public: /// /// \param PCHContainerOps An instance of PCHContainerOperations. /// + /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in + /// a temporary file. + /// /// \param Callbacks A set of callbacks to be executed when building /// the preamble. static llvm::ErrorOr<PrecompiledPreamble> @@ -92,12 +81,12 @@ public: const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS, std::shared_ptr<PCHContainerOperations> PCHContainerOps, - PreambleCallbacks &Callbacks); + bool StoreInMemory, PreambleCallbacks &Callbacks); PrecompiledPreamble(PrecompiledPreamble &&) = default; PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default; - /// PreambleBounds used to build the preamble + /// PreambleBounds used to build the preamble. PreambleBounds getBounds() const; /// Check whether PrecompiledPreamble can be reused for the new contents(\p @@ -107,12 +96,18 @@ public: vfs::FileSystem *VFS) const; /// Changes options inside \p CI to use PCH from this preamble. Also remaps - /// main file to \p MainFileBuffer. + /// 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. void AddImplicitPreamble(CompilerInvocation &CI, + IntrusiveRefCntPtr<vfs::FileSystem> &VFS, llvm::MemoryBuffer *MainFileBuffer) const; private: - PrecompiledPreamble(TempPCHFile PCHFile, std::vector<char> PreambleBytes, + PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes, bool PreambleEndsAtStartOfLine, llvm::StringMap<PreambleFileHash> FilesInPreamble); @@ -154,6 +149,44 @@ private: llvm::Optional<std::string> FilePath; }; + class InMemoryPreamble { + public: + std::string Data; + }; + + class PCHStorage { + public: + enum class Kind { Empty, InMemory, TempFile }; + + PCHStorage() = default; + PCHStorage(TempPCHFile File); + PCHStorage(InMemoryPreamble Memory); + + PCHStorage(const PCHStorage &) = delete; + PCHStorage &operator=(const PCHStorage &) = delete; + + PCHStorage(PCHStorage &&Other); + PCHStorage &operator=(PCHStorage &&Other); + + ~PCHStorage(); + + Kind getKind() const; + + TempPCHFile &asFile(); + const TempPCHFile &asFile() const; + + InMemoryPreamble &asMemory(); + const InMemoryPreamble &asMemory() const; + + private: + void destroy(); + void setEmpty(); + + private: + Kind StorageKind = Kind::Empty; + llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {}; + }; + /// Data used to determine if a file used in the preamble has been changed. struct PreambleFileHash { /// All files have size set. @@ -183,8 +216,15 @@ private: } }; - /// Manages the lifetime of temporary file that stores a PCH. - TempPCHFile PCHFile; + /// 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. + static void setupPreambleStorage(const PCHStorage &Storage, + PreprocessorOptions &PreprocessorOpts, + IntrusiveRefCntPtr<vfs::FileSystem> &VFS); + + /// Manages the memory buffer or temporary file that stores the PCH. + PCHStorage Storage; /// Keeps track of the files that were used when computing the /// preamble, with both their buffer size and their modification time. /// @@ -215,11 +255,9 @@ public: /// NOTE: To allow more flexibility a custom ASTConsumer could probably be /// used instead, but having only this method allows a simpler API. virtual void HandleTopLevelDecl(DeclGroupRef DG); - /// Called for each macro defined in the Preamble. - /// NOTE: To allow more flexibility a custom PPCallbacks could probably be - /// used instead, but having only this method allows a simpler API. - virtual void HandleMacroDefined(const Token &MacroNameTok, - const MacroDirective *MD); + /// Creates wrapper class for PPCallbacks so we can also process information + /// about includes that are inside of a preamble + virtual std::unique_ptr<PPCallbacks> createPPCallbacks(); }; enum class BuildPreambleError { diff --git a/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h index 3bcf824455e2..23f168e2232d 100644 --- a/include/clang/Frontend/TextDiagnosticBuffer.h +++ b/include/clang/Frontend/TextDiagnosticBuffer.h @@ -29,6 +29,11 @@ public: typedef DiagList::const_iterator 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(); } diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h index 475f07f9dc06..8d71fb98b0bb 100644 --- a/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -176,7 +176,8 @@ public: : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) { assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!"); - assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!"); + assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) && + "DiagnosticLoc is invalid!"); } private: diff --git a/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h index 315437048345..080f4cb4d097 100644 --- a/include/clang/Index/IndexDataConsumer.h +++ b/include/clang/Index/IndexDataConsumer.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_INDEX_INDEXDATACONSUMER_H #include "clang/Index/IndexSymbol.h" +#include "clang/Lex/Preprocessor.h" namespace clang { class ASTContext; @@ -36,6 +37,8 @@ public: virtual void initialize(ASTContext &Ctx) {} + virtual void setPreprocessor(std::shared_ptr<Preprocessor> PP) {} + /// \returns true to continue indexing, or false to abort. virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations, diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index abb132f9e4ce..ae591364f229 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -53,6 +53,7 @@ enum class SymbolKind : uint8_t { ConversionFunction, Parameter, + Using, }; enum class SymbolLanguage { @@ -69,6 +70,8 @@ enum class SymbolSubKind { CXXMoveConstructor, AccessorGetter, AccessorSetter, + UsingTypename, + UsingValue, }; /// Set of properties that provide additional info about a symbol. diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 1b7f80c87ff1..6b9dbfcd1e93 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -1,4 +1,4 @@ -//===--- HeaderSearch.h - Resolve Header File Locations ---------*- C++ -*-===// +//===- HeaderSearch.h - Resolve Header File Locations -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,25 +14,37 @@ #ifndef LLVM_CLANG_LEX_HEADERSEARCH_H #define LLVM_CLANG_LEX_HEADERSEARCH_H +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleMap.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstddef> #include <memory> +#include <string> +#include <utility> #include <vector> namespace clang { - -class DiagnosticsEngine; + +class DiagnosticsEngine; +class DirectoryEntry; class ExternalPreprocessorSource; class FileEntry; class FileManager; +class HeaderMap; class HeaderSearchOptions; class IdentifierInfo; +class LangOptions; +class Module; class Preprocessor; +class TargetInfo; /// \brief The preprocessor keeps track of this information for each /// file that is \#included. @@ -76,14 +88,14 @@ struct HeaderFileInfo { unsigned IsValid : 1; /// \brief The number of times the file has been included already. - unsigned short NumIncludes; + unsigned short NumIncludes = 0; /// \brief 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 /// external storage. - unsigned ControllingMacroID; + unsigned ControllingMacroID = 0; /// If this file has a \#ifndef XXX (or equivalent) guard that /// protects the entire contents of the file, this is the identifier @@ -93,17 +105,16 @@ struct HeaderFileInfo { /// the controlling macro of this header, since /// getControllingMacro() is able to load a controlling macro from /// external storage. - const IdentifierInfo *ControllingMacro; + const IdentifierInfo *ControllingMacro = nullptr; /// \brief If this header came from a framework include, this is the name /// of the framework. StringRef Framework; HeaderFileInfo() - : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), - External(false), isModuleHeader(false), isCompilingModuleHeader(false), - Resolved(false), IndexHeaderMapHeader(false), IsValid(0), - NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {} + : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User), + External(false), isModuleHeader(false), isCompilingModuleHeader(false), + Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {} /// \brief Retrieve the controlling macro for this header file, if /// any. @@ -135,6 +146,8 @@ public: /// \brief Encapsulates the information needed to find the file referenced /// by a \#include or \#include_next, (sub-)framework lookup, etc. class HeaderSearch { + friend class DirectoryLookup; + /// This structure is used to record entries in our framework cache. struct FrameworkCacheEntry { /// The directory entry which should be used for the cached framework. @@ -151,6 +164,7 @@ class HeaderSearch { DiagnosticsEngine &Diags; FileManager &FileMgr; + /// \#include search path information. Requests for \#include "x" search the /// directory of the \#including file first, then each directory in SearchDirs /// consecutively. Requests for <x> search the current dir first, then each @@ -158,9 +172,9 @@ class HeaderSearch { /// NoCurDirSearch is true, then the check for the file in the current /// directory is suppressed. std::vector<DirectoryLookup> SearchDirs; - unsigned AngledDirIdx; - unsigned SystemDirIdx; - bool NoCurDirSearch; + unsigned AngledDirIdx = 0; + unsigned SystemDirIdx = 0; + bool NoCurDirSearch = false; /// \brief \#include prefixes for which the 'system header' property is /// overridden. @@ -168,7 +182,7 @@ class HeaderSearch { /// For a \#include "x" or \#include \<x> directive, the last string in this /// list which is a prefix of 'x' determines whether the file is treated as /// a system header. - std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes; + std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes; /// \brief The path to the module cache. std::string ModuleCachePath; @@ -182,15 +196,17 @@ class HeaderSearch { /// Starting index in SearchDirs that the cached search was performed from. /// If there is a hit and this value doesn't match the current query, the /// cache has to be ignored. - unsigned StartIdx; + unsigned StartIdx = 0; + /// The entry in SearchDirs that satisfied the query. - unsigned HitIdx; + unsigned HitIdx = 0; + /// This is non-null if the original filename was mapped to a framework /// include via a headermap. - const char *MappedName; + const char *MappedName = nullptr; /// Default constructor -- Initialize all members with zero. - LookupFileCacheInfo(): StartIdx(0), HitIdx(0), MappedName(nullptr) {} + LookupFileCacheInfo() = default; void reset(unsigned StartIdx) { this->StartIdx = StartIdx; @@ -206,13 +222,13 @@ class HeaderSearch { /// IncludeAliases - maps include file names (including the quotes or /// angle brackets) to other include file names. This is used to support the /// include_alias pragma for Microsoft compatibility. - typedef llvm::StringMap<std::string, llvm::BumpPtrAllocator> - IncludeAliasMap; + using IncludeAliasMap = + llvm::StringMap<std::string, llvm::BumpPtrAllocator>; std::unique_ptr<IncludeAliasMap> IncludeAliases; /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing /// headermaps. This vector owns the headermap. - std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps; + std::vector<std::pair<const FileEntry *, const HeaderMap *>> HeaderMaps; /// \brief The mapping between modules and headers. mutable ModuleMap ModMap; @@ -231,26 +247,23 @@ class HeaderSearch { /// \brief Entity used to resolve the identifier IDs of controlling /// macros into IdentifierInfo pointers, and keep the identifire up to date, /// as needed. - ExternalPreprocessorSource *ExternalLookup; + ExternalPreprocessorSource *ExternalLookup = nullptr; /// \brief Entity used to look up stored header file information. - ExternalHeaderFileInfoSource *ExternalSource; + ExternalHeaderFileInfoSource *ExternalSource = nullptr; // Various statistics we track for performance analysis. - unsigned NumIncluded; - unsigned NumMultiIncludeFileOptzn; - unsigned NumFrameworkLookups, NumSubFrameworkLookups; + unsigned NumIncluded = 0; + unsigned NumMultiIncludeFileOptzn = 0; + unsigned NumFrameworkLookups = 0; + unsigned NumSubFrameworkLookups = 0; - // HeaderSearch doesn't support default or copy construction. - HeaderSearch(const HeaderSearch&) = delete; - void operator=(const HeaderSearch&) = delete; - - friend class DirectoryLookup; - public: HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts, SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target); + HeaderSearch(const HeaderSearch &) = delete; + HeaderSearch &operator=(const HeaderSearch &) = delete; ~HeaderSearch(); /// \brief Retrieve the header-search options with which this header search @@ -282,7 +295,7 @@ public: } /// \brief Set the list of system header prefixes. - void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool> > P) { + void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) { SystemHeaderPrefixes.assign(P.begin(), P.end()); } @@ -310,7 +323,7 @@ public: IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source); if (Iter != IncludeAliases->end()) return Iter->second; - return StringRef(); + return {}; } /// \brief Set the path to the module cache. @@ -471,29 +484,40 @@ public: /// \brief Get filenames for all registered header maps. void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const; - /// \brief Retrieve the name of the module file that should be used to - /// load the given module. + /// \brief 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. /// /// \returns The name of the module file that corresponds to this module, /// or an empty string if this module does not correspond to any module file. - std::string getModuleFileName(Module *Module); + std::string getCachedModuleFileName(Module *Module); + + /// \brief 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. + /// + /// \param FileMapOnly If true, then only look in the explicit module name + // to file name map and skip the directory search. + /// + /// \returns The name of the module file that corresponds to this module, + /// or an empty string if this module does not correspond to any module file. + std::string getPrebuiltModuleFileName(StringRef ModuleName, + bool FileMapOnly = false); - /// \brief Retrieve the name of the module file that should be used to - /// load a module with the given name. + /// \brief 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. /// /// \param ModuleMapPath A path that when combined with \c ModuleName /// uniquely identifies this module. See Module::ModuleMap. /// - /// \param UsePrebuiltPath Whether we should use the prebuilt module path. - /// /// \returns The name of the module file that corresponds to this module, /// or an empty string if this module does not correspond to any module file. - std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath, - bool UsePrebuiltPath); + std::string getCachedModuleFileName(StringRef ModuleName, + StringRef ModuleMapPath); /// \brief Lookup a module Search for a module with the given name. /// @@ -560,7 +584,6 @@ public: void loadTopLevelSystemModules(); private: - /// \brief Lookup a module with the given module name and search-name. /// /// \param ModuleName The name of the module we're looking for. @@ -640,7 +663,8 @@ public: bool WantExternal = true) const; // Used by external tools - typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator; + using search_dir_iterator = std::vector<DirectoryLookup>::const_iterator; + search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); } search_dir_iterator search_dir_end() const { return SearchDirs.end(); } unsigned search_dir_size() const { return SearchDirs.size(); } @@ -648,6 +672,7 @@ public: search_dir_iterator quoted_dir_begin() const { return SearchDirs.begin(); } + search_dir_iterator quoted_dir_end() const { return SearchDirs.begin() + AngledDirIdx; } @@ -655,6 +680,7 @@ public: search_dir_iterator angled_dir_begin() const { return SearchDirs.begin() + AngledDirIdx; } + search_dir_iterator angled_dir_end() const { return SearchDirs.begin() + SystemDirIdx; } @@ -662,6 +688,7 @@ public: search_dir_iterator system_dir_begin() const { return SearchDirs.begin() + SystemDirIdx; } + search_dir_iterator system_dir_end() const { return SearchDirs.end(); } /// \brief Retrieve a uniqued framework name. @@ -684,10 +711,13 @@ private: enum LoadModuleMapResult { /// \brief The module map file had already been loaded. LMM_AlreadyLoaded, + /// \brief The module map file was loaded by this invocation. LMM_NewlyLoaded, + /// \brief There is was directory with the given name. LMM_NoDirectory, + /// \brief There was either no module map file or the module map file was /// invalid. LMM_InvalidModuleMap @@ -723,6 +753,6 @@ private: bool IsSystem, bool IsFramework); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_HEADERSEARCH_H diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index ca3a84e75e18..937ad9863db3 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -1,4 +1,4 @@ -//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===// +//===- HeaderSearchOptions.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,35 +12,55 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/CachedHashString.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringRef.h" +#include <cstdint> #include <string> #include <vector> +#include <map> namespace clang { namespace frontend { - /// IncludeDirGroup - Identifies the group an include Entry belongs to, - /// representing its relative positive in the search list. - /// \#include directives whose paths are enclosed by string quotes ("") - /// start searching at the Quoted group (specified by '-iquote'), - /// then search the Angled group, then the System group, etc. - enum IncludeDirGroup { - Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'. - Angled, ///< Paths for '\#include <>' added by '-I'. - IndexHeaderMap, ///< Like Angled, but marks header maps used when - /// building frameworks. - System, ///< Like Angled, but marks system directories. - ExternCSystem, ///< Like System, but headers are implicitly wrapped in - /// extern "C". - CSystem, ///< Like System, but only used for C. - CXXSystem, ///< Like System, but only used for C++. - ObjCSystem, ///< Like System, but only used for ObjC. - ObjCXXSystem, ///< Like System, but only used for ObjC++. - After ///< Like System, but searched after the system directories. - }; -} + +/// IncludeDirGroup - Identifies the group an include Entry belongs to, +/// representing its relative positive in the search list. +/// \#include directives whose paths are enclosed by string quotes ("") +/// start searching at the Quoted group (specified by '-iquote'), +/// then search the Angled group, then the System group, etc. +enum IncludeDirGroup { + /// '\#include ""' paths, added by 'gcc -iquote'. + Quoted = 0, + + /// Paths for '\#include <>' added by '-I'. + Angled, + + /// Like Angled, but marks header maps used when building frameworks. + IndexHeaderMap, + + /// Like Angled, but marks system directories. + System, + + /// Like System, but headers are implicitly wrapped in extern "C". + ExternCSystem, + + /// Like System, but only used for C. + CSystem, + + /// Like System, but only used for C++. + CXXSystem, + + /// Like System, but only used for ObjC. + ObjCSystem, + + /// Like System, but only used for ObjC++. + ObjCXXSystem, + + /// Like System, but searched after the system directories. + After +}; + +} // namespace frontend /// HeaderSearchOptions - Helper class for storing options related to the /// initialization of the HeaderSearch object. @@ -58,8 +78,8 @@ public: Entry(StringRef path, frontend::IncludeDirGroup group, bool isFramework, bool ignoreSysRoot) - : Path(path), Group(group), IsFramework(isFramework), - IgnoreSysRoot(ignoreSysRoot) {} + : Path(path), Group(group), IsFramework(isFramework), + IgnoreSysRoot(ignoreSysRoot) {} }; struct SystemHeaderPrefix { @@ -71,7 +91,7 @@ public: bool IsSystemHeader; SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) - : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} + : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} }; /// If non-empty, the directory to use as a "virtual system root" for include @@ -94,6 +114,9 @@ public: /// \brief The directory used for a user build. std::string ModuleUserBuildPath; + /// \brief 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. std::vector<std::string> PrebuiltModulePaths; @@ -126,7 +149,7 @@ public: /// files. /// /// The default value is large, e.g., the operation runs once a week. - unsigned ModuleCachePruneInterval; + unsigned ModuleCachePruneInterval = 7 * 24 * 60 * 60; /// \brief The time (in seconds) after which an unused module file will be /// considered unused and will, therefore, be pruned. @@ -135,13 +158,13 @@ public: /// accessed in this many seconds will be removed. The default value is /// large, e.g., a month, to avoid forcing infrequently-used modules to be /// regenerated often. - unsigned ModuleCachePruneAfter; + unsigned ModuleCachePruneAfter = 31 * 24 * 60 * 60; /// \brief 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; + uint64_t BuildSessionTimestamp = 0; /// \brief The set of macro names that should be ignored for the purposes /// of computing the module hash. @@ -181,10 +204,8 @@ public: unsigned ModulesHashContent : 1; HeaderSearchOptions(StringRef _Sysroot = "/") - : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0), - ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0), - ModuleCachePruneInterval(7 * 24 * 60 * 60), - ModuleCachePruneAfter(31 * 24 * 60 * 60), BuildSessionTimestamp(0), + : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false), + ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false), UseBuiltinIncludes(true), UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false), ModulesValidateOncePerBuildSession(false), @@ -213,6 +234,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 3be733167e5c..d58849654cb8 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -1,4 +1,4 @@ -//===--- Lexer.h - C Language Family Lexer ----------------------*- C++ -*-===// +//===- Lexer.h - C Language Family Lexer ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,45 +15,88 @@ #define LLVM_CLANG_LEX_LEXER_H #include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/PreprocessorLexer.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include <cassert> +#include <cstdint> #include <string> +namespace llvm { + +class MemoryBuffer; + +} // namespace llvm + namespace clang { -class DiagnosticsEngine; -class SourceManager; -class Preprocessor; + class DiagnosticBuilder; +class Preprocessor; +class SourceManager; /// ConflictMarkerKind - Kinds of conflict marker which the lexer might be /// recovering from. enum ConflictMarkerKind { /// Not within a conflict marker. CMK_None, + /// A normal or diff3 conflict marker, initiated by at least 7 "<"s, /// separated by at least 7 "="s or "|"s, and terminated by at least 7 ">"s. CMK_Normal, + /// A Perforce-style conflict marker, initiated by 4 ">"s, /// separated by 4 "="s, and terminated by 4 "<"s. CMK_Perforce }; +/// Describes the bounds (start, size) of the preamble and a flag required by +/// PreprocessorOptions::PrecompiledPreambleBytes. +/// The preamble includes the BOM, if any. +struct PreambleBounds { + /// \brief Size of the preamble in bytes. + unsigned Size; + + /// \brief 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. + bool PreambleEndsAtStartOfLine; + + PreambleBounds(unsigned Size, bool PreambleEndsAtStartOfLine) + : Size(Size), PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {} +}; + /// Lexer - This provides a simple interface that turns a text buffer into a /// stream of tokens. This provides no support for file reading or buffering, /// or buffering/seeking of tokens, only forward lexing is supported. It relies /// on the specified Preprocessor object to handle preprocessor directives, etc. class Lexer : public PreprocessorLexer { + friend class Preprocessor; + void anchor() override; //===--------------------------------------------------------------------===// // Constant configuration values for this lexer. - const char *BufferStart; // Start of the buffer. - const char *BufferEnd; // End of the buffer. - SourceLocation FileLoc; // Location for start of file. - LangOptions LangOpts; // LangOpts enabled by this language (cache). - bool Is_PragmaLexer; // True if lexer for _Pragma handling. - + + // Start of the buffer. + const char *BufferStart; + + // End of the buffer. + const char *BufferEnd; + + // Location for start of file. + SourceLocation FileLoc; + + // LangOpts enabled by this language (cache). + LangOptions LangOpts; + + // True if lexer for _Pragma handling. + bool Is_PragmaLexer; + //===--------------------------------------------------------------------===// // Context-specific lexing flags set by the preprocessor. // @@ -89,13 +132,9 @@ class Lexer : public PreprocessorLexer { // CurrentConflictMarkerState - The kind of conflict marker we are handling. ConflictMarkerKind CurrentConflictMarkerState; - Lexer(const Lexer &) = delete; - void operator=(const Lexer &) = delete; - friend class Preprocessor; - void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd); -public: +public: /// Lexer constructor - Create a new lexer object for the specified buffer /// with the specified preprocessor managing the lexing process. This lexer /// assumes that the associated file buffer and Preprocessor objects will @@ -114,6 +153,9 @@ public: Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, const SourceManager &SM, const LangOptions &LangOpts); + Lexer(const Lexer &) = delete; + Lexer &operator=(const Lexer &) = delete; + /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for /// _Pragma expansion. This has a variety of magic semantics that this method /// sets up. It returns a new'd Lexer that must be delete'd when done. @@ -122,7 +164,6 @@ public: SourceLocation ExpansionLocEnd, unsigned TokLen, Preprocessor &PP); - /// getLangOpts - Return the language features currently enabled. /// NOTE: this lexer modifies features as a file is parsed! const LangOptions &getLangOpts() const { return LangOpts; } @@ -224,17 +265,16 @@ public: /// \brief Return the current location in the buffer. const char *getBufferLocation() const { return BufferPtr; } - - /// Stringify - Convert the specified string into a C string by escaping '\' - /// and " characters. This does not add surrounding ""'s to the string. + + /// Stringify - Convert the specified string into a C string by i) escaping + /// '\\' and " characters and ii) replacing newline character(s) with "\\n". /// If Charify is true, this escapes the ' character instead of ". static std::string Stringify(StringRef Str, bool Charify = false); - /// Stringify - Convert the specified string into a C string by escaping '\' - /// and " characters. This does not add surrounding ""'s to the string. + /// Stringify - Convert the specified string into a C string by i) escaping + /// '\\' and " characters and ii) replacing newline character(s) with "\\n". static void Stringify(SmallVectorImpl<char> &Str); - /// getSpelling - This method is used to 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 guaranteed to be at least @@ -245,11 +285,11 @@ public: /// to point to a constant buffer with the data already in it (avoiding a /// copy). The caller is not allowed to modify the returned buffer pointer /// if an internal buffer is returned. - static unsigned getSpelling(const Token &Tok, const char *&Buffer, + static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid = nullptr); - + /// getSpelling() - 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 particular, this @@ -257,7 +297,7 @@ public: /// UCNs, etc. static std::string getSpelling(const Token &Tok, const SourceManager &SourceMgr, - const LangOptions &LangOpts, + const LangOptions &LangOpts, bool *Invalid = nullptr); /// getSpelling - This method is used to get the spelling of the @@ -273,7 +313,7 @@ public: const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *invalid = nullptr); - + /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. /// includes a trigraph or an escaped newline) then this count includes bytes @@ -295,7 +335,7 @@ public: static SourceLocation GetBeginningOfToken(SourceLocation Loc, 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. @@ -303,7 +343,7 @@ public: unsigned Character, const SourceManager &SM, const LangOptions &LangOpts); - + /// \brief Computes the source location just past the end of the /// token at this source location. /// @@ -443,11 +483,18 @@ public: /// to fewer than this number of lines. /// /// \returns The offset into the file where the preamble ends and the rest - /// of the file begins along with a boolean value indicating whether + /// of the file begins along with a boolean value indicating whether /// the preamble ends at the beginning of a new line. - static std::pair<unsigned, bool> ComputePreamble(StringRef Buffer, - const LangOptions &LangOpts, - unsigned MaxLines = 0); + static PreambleBounds ComputePreamble(StringRef Buffer, + const LangOptions &LangOpts, + unsigned MaxLines = 0); + + /// Finds the token that comes right after the given location. + /// + /// Returns the next token, or none if the location is inside a macro. + static Optional<Token> findNextToken(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts); /// \brief Checks that the given token is the first token that occurs after /// the given location (this excludes comments and whitespace). Returns the @@ -463,6 +510,10 @@ public: /// \brief 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 + /// sequence. + static bool isNewLineEscaped(const char *BufferStart, const char *Str); + /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever /// emit a warning. static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size, @@ -483,9 +534,9 @@ public: static StringRef getIndentationForLine(SourceLocation Loc, const SourceManager &SM); +private: //===--------------------------------------------------------------------===// // Internal implementation interfaces. -private: /// LexTokenInternal - Internal interface to lex a preprocessing token. Called /// by Lex. @@ -614,7 +665,7 @@ private: //===--------------------------------------------------------------------===// // Other lexer functions. - void SkipBytes(unsigned Bytes, bool StartOfLine); + void SetByteOffset(unsigned Offset, bool StartOfLine); void PropagateLineStartLeadingSpaceInfo(Token &Result); @@ -639,7 +690,7 @@ private: bool SkipBlockComment (Token &Result, const char *CurPtr, bool &TokAtPhysicalStartOfLine); bool SaveLineComment (Token &Result, const char *CurPtr); - + bool IsStartOfConflictMarker(const char *CurPtr); bool HandleEndOfConflictMarker(const char *CurPtr); @@ -658,7 +709,7 @@ private: /// valid), this parameter will be updated to point to the /// character after the UCN. /// \param SlashLoc The position in the source buffer of the '\'. - /// \param Tok The token being formed. Pass \c NULL to suppress diagnostics + /// \param Tok The token being formed. Pass \c nullptr to suppress diagnostics /// and handle token formation in the caller. /// /// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is @@ -687,6 +738,6 @@ private: bool tryConsumeIdentifierUTF8Char(const char *&CurPtr); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_LEXER_H diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index b66581b428b1..cc9223eb7dbb 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -65,6 +65,7 @@ public: bool isHalf : 1; // 1.0h bool isFloat : 1; // 1.0f bool isImaginary : 1; // 1.0i + bool isFloat16 : 1; // 1.0f16 bool isFloat128 : 1; // 1.0q uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. diff --git a/include/clang/Lex/MacroArgs.h b/include/clang/Lex/MacroArgs.h index cfe46ceb0979..a202550da3b3 100644 --- a/include/clang/Lex/MacroArgs.h +++ b/include/clang/Lex/MacroArgs.h @@ -17,6 +17,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/TrailingObjects.h" #include <vector> namespace clang { @@ -26,7 +27,10 @@ namespace clang { /// MacroArgs - An instance of this class captures information about /// the formal arguments specified to a function-like macro invocation. -class MacroArgs { +class MacroArgs final + : private llvm::TrailingObjects<MacroArgs, Token> { + + friend TrailingObjects; /// NumUnexpArgTokens - The number of raw, unexpanded tokens for the /// arguments. All of the actual argument tokens are allocated immediately /// after the MacroArgs object in memory. This is all of the arguments @@ -89,7 +93,7 @@ public: /// getPreExpArgument - Return the pre-expanded form of the specified /// argument. const std::vector<Token> & - getPreExpArgument(unsigned Arg, const MacroInfo *MI, Preprocessor &PP); + getPreExpArgument(unsigned Arg, Preprocessor &PP); /// getStringifiedArgument - Compute, cache, and return the specified argument /// that has been 'stringified' as required by the # operator. @@ -108,6 +112,20 @@ public: /// argument, this returns false. bool isVarargsElidedUse() const { return VarargsElided; } + /// Returns true if the macro was defined with a variadic (ellipsis) parameter + /// AND was invoked with at least one token supplied as a variadic argument. + /// + /// \code + /// #define F(a) a + /// #define V(a, ...) __VA_OPT__(a) + /// F() <-- returns false on this invocation. + /// V(,a) <-- returns true on this invocation. + /// V(,) <-- returns false on this invocation. + /// \endcode + /// + + bool invokedWithVariadicArgument(const MacroInfo *const MI) const; + /// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of /// tokens into the literal string token that should be produced by the C # /// preprocessor operator. If Charify is true, then it should be turned into diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index d25431b55fdc..3029294209ec 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -1,4 +1,4 @@ -//===--- MacroInfo.h - Information about #defined identifiers ---*- C++ -*-===// +//===- MacroInfo.h - Information about #defined identifiers -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,27 +6,33 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::MacroInfo and clang::MacroDirective classes. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_MACROINFO_H #define LLVM_CLANG_LEX_MACROINFO_H #include "clang/Lex/Token.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" +#include <algorithm> #include <cassert> namespace clang { + +class DefMacroDirective; +class IdentifierInfo; class Module; -class ModuleMacro; class Preprocessor; +class SourceManager; /// \brief Encapsulates the data about a macro definition (e.g. its tokens). /// @@ -37,6 +43,7 @@ class MacroInfo { /// \brief The location the macro is defined. SourceLocation Location; + /// \brief The location of the last token in the macro. SourceLocation EndLocation; @@ -46,10 +53,10 @@ class MacroInfo { /// /// This can be empty, for, e.g. "#define X()". In a C99-style variadic /// macro, this includes the \c __VA_ARGS__ identifier on the list. - IdentifierInfo **ParameterList; + IdentifierInfo **ParameterList = nullptr; /// \see ParameterList - unsigned NumParameters; + unsigned NumParameters = 0; /// \brief This is the list of tokens that the macro is defined to. SmallVector<Token, 8> ReplacementTokens; @@ -169,7 +176,7 @@ public: /// Parameters - The list of parameters for a function-like macro. This can /// be empty, for, e.g. "#define X()". - typedef IdentifierInfo *const *param_iterator; + using param_iterator = IdentifierInfo *const *; bool param_empty() const { return NumParameters == 0; } param_iterator param_begin() const { return ParameterList; } param_iterator param_end() const { return ParameterList + NumParameters; } @@ -224,7 +231,6 @@ public: bool isWarnIfUnused() const { return IsWarnIfUnused; } /// \brief Return the number of tokens that this macro expands to. - /// unsigned getNumTokens() const { return ReplacementTokens.size(); } const Token &getReplacementToken(unsigned Tok) const { @@ -232,7 +238,8 @@ public: return ReplacementTokens[Tok]; } - typedef SmallVectorImpl<Token>::const_iterator tokens_iterator; + using tokens_iterator = SmallVectorImpl<Token>::const_iterator; + tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); } tokens_iterator tokens_end() const { return ReplacementTokens.end(); } bool tokens_empty() const { return ReplacementTokens.empty(); } @@ -269,12 +276,10 @@ public: void dump() const; private: - unsigned getDefinitionLengthSlow(const SourceManager &SM) const; - friend class Preprocessor; -}; -class DefMacroDirective; + unsigned getDefinitionLengthSlow(const SourceManager &SM) const; +}; /// \brief Encapsulates changes to the "macros namespace" (the location where /// the macro name became active, the location where it was undefined, etc.). @@ -285,11 +290,15 @@ class DefMacroDirective; /// create additional DefMacroDirectives for the same MacroInfo. class MacroDirective { public: - enum Kind { MD_Define, MD_Undefine, MD_Visibility }; + enum Kind { + MD_Define, + MD_Undefine, + MD_Visibility + }; protected: - /// \brief Previous macro directive for the same identifier, or NULL. - MacroDirective *Previous; + /// \brief Previous macro directive for the same identifier, or nullptr. + MacroDirective *Previous = nullptr; SourceLocation Loc; @@ -306,8 +315,7 @@ protected: unsigned IsPublic : 1; MacroDirective(Kind K, SourceLocation Loc) - : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false), - IsPublic(true) {} + : Loc(Loc), MDKind(K), IsFromPCH(false), IsPublic(true) {} public: Kind getKind() const { return Kind(MDKind); } @@ -329,13 +337,12 @@ public: void setIsFromPCH() { IsFromPCH = true; } class DefInfo { - DefMacroDirective *DefDirective; + DefMacroDirective *DefDirective = nullptr; SourceLocation UndefLoc; - bool IsPublic; + bool IsPublic = true; public: - DefInfo() : DefDirective(nullptr), IsPublic(true) {} - + DefInfo() = default; DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc, bool isPublic) : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {} @@ -345,6 +352,7 @@ public: inline SourceLocation getLocation() const; inline MacroInfo *getMacroInfo(); + const MacroInfo *getMacroInfo() const { return const_cast<DefInfo *>(this)->getMacroInfo(); } @@ -360,6 +368,7 @@ public: explicit operator bool() const { return isValid(); } inline DefInfo getPreviousDefinition(); + const DefInfo getPreviousDefinition() const { return const_cast<DefInfo *>(this)->getPreviousDefinition(); } @@ -412,6 +421,7 @@ public: static bool classof(const MacroDirective *MD) { return MD->getKind() == MD_Define; } + static bool classof(const DefMacroDirective *) { return true; } }; @@ -426,6 +436,7 @@ public: static bool classof(const MacroDirective *MD) { return MD->getKind() == MD_Undefine; } + static bool classof(const UndefMacroDirective *) { return true; } }; @@ -444,12 +455,13 @@ public: static bool classof(const MacroDirective *MD) { return MD->getKind() == MD_Visibility; } + static bool classof(const VisibilityMacroDirective *) { return true; } }; inline SourceLocation MacroDirective::DefInfo::getLocation() const { if (isInvalid()) - return SourceLocation(); + return {}; return DefDirective->getLocation(); } @@ -462,7 +474,7 @@ inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() { inline MacroDirective::DefInfo MacroDirective::DefInfo::getPreviousDefinition() { if (isInvalid() || DefDirective->getPrevious() == nullptr) - return DefInfo(); + return {}; return DefDirective->getPrevious()->getDefinition(); } @@ -474,23 +486,26 @@ MacroDirective::DefInfo::getPreviousDefinition() { /// /// These are stored in a FoldingSet in the preprocessor. class ModuleMacro : public llvm::FoldingSetNode { + friend class Preprocessor; + /// The name defined by the macro. IdentifierInfo *II; + /// The body of the #define, or nullptr if this is a #undef. MacroInfo *Macro; + /// The module that exports this macro. Module *OwningModule; + /// The number of module macros that override this one. - unsigned NumOverriddenBy; + unsigned NumOverriddenBy = 0; + /// The number of modules whose macros are directly overridden by this one. unsigned NumOverrides; - // ModuleMacro *OverriddenMacros[NumOverrides]; - - friend class Preprocessor; ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro, ArrayRef<ModuleMacro *> Overrides) - : II(II), Macro(Macro), OwningModule(OwningModule), NumOverriddenBy(0), + : II(II), Macro(Macro), OwningModule(OwningModule), NumOverrides(Overrides.size()) { std::copy(Overrides.begin(), Overrides.end(), reinterpret_cast<ModuleMacro **>(this + 1)); @@ -504,12 +519,16 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const { return Profile(ID, OwningModule, II); } + static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule, IdentifierInfo *II) { ID.AddPointer(OwningModule); ID.AddPointer(II); } + /// Get the name of the macro. + IdentifierInfo *getName() const { return II; } + /// Get the ID of the module that exports this macro. Module *getOwningModule() const { return OwningModule; } @@ -519,13 +538,16 @@ public: /// Iterators over the overridden module IDs. /// \{ - typedef ModuleMacro *const *overrides_iterator; + using overrides_iterator = ModuleMacro *const *; + overrides_iterator overrides_begin() const { return reinterpret_cast<overrides_iterator>(this + 1); } + overrides_iterator overrides_end() const { return overrides_begin() + NumOverrides; } + ArrayRef<ModuleMacro *> overrides() const { return llvm::makeArrayRef(overrides_begin(), overrides_end()); } @@ -544,7 +566,7 @@ class MacroDefinition { ArrayRef<ModuleMacro *> ModuleMacros; public: - MacroDefinition() : LatestLocalAndAmbiguous(), ModuleMacros() {} + MacroDefinition() = default; MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs, bool IsAmbiguous) : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {} @@ -583,6 +605,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_MACROINFO_H diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index ee0638b57f87..30ea583b71e0 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -1,4 +1,4 @@ -//===--- ModuleLoader.h - Module Loader Interface ---------------*- C++ -*-===// +//===- ModuleLoader.h - Module Loader Interface -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,23 +11,26 @@ // loading named modules. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_LEX_MODULELOADER_H #define LLVM_CLANG_LEX_MODULELOADER_H +#include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringRef.h" +#include <utility> namespace clang { class GlobalModuleIndex; class IdentifierInfo; -class Module; /// \brief A sequence of identifier/location pairs used to describe a particular /// module or submodule, e.g., std.vector. -typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation> > ModuleIdPath; +using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>; /// \brief Describes the result of attempting to load a module. class ModuleLoadResult { @@ -35,16 +38,18 @@ public: enum LoadResultKind { // We either succeeded or failed to load the named module. Normal, + // The module exists, but does not actually contain the named submodule. // This should only happen if the named submodule was inferred from an // umbrella directory, but not actually part of the umbrella header. MissingExpected, + // The module exists but cannot be imported due to a configuration mismatch. ConfigMismatch }; llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage; - ModuleLoadResult() : Storage() { } + ModuleLoadResult() = default; ModuleLoadResult(Module *M) : Storage(M, Normal) {} ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {} @@ -69,10 +74,10 @@ public: class ModuleLoader { // Building a module if true. bool BuildingModule; + public: - explicit ModuleLoader(bool BuildingModule = false) : - BuildingModule(BuildingModule), - HadFatalFailure(false) {} + explicit ModuleLoader(bool BuildingModule = false) + : BuildingModule(BuildingModule) {} virtual ~ModuleLoader(); @@ -80,6 +85,7 @@ public: bool buildingModule() const { return BuildingModule; } + /// \brief Flag indicating whether this instance is building a module. void setBuildingModule(bool BuildingModuleFlag) { BuildingModule = BuildingModuleFlag; @@ -144,7 +150,7 @@ public: virtual bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) = 0; - bool HadFatalFailure; + bool HadFatalFailure = false; }; /// A module loader that doesn't know how to load modules. @@ -153,7 +159,7 @@ public: ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective) override { - return ModuleLoadResult(); + return {}; } void loadModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName, @@ -165,12 +171,13 @@ public: GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override { return nullptr; } + bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override { - return 0; + return false; } }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_MODULELOADER_H diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 11506939f9b1..41ed8e49b6c1 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -1,4 +1,4 @@ -//===--- ModuleMap.h - Describe the layout of modules -----------*- C++ -*-===// +//===- ModuleMap.h - Describe the layout of modules -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,7 +18,6 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" @@ -28,20 +27,19 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/Twine.h" -#include <algorithm> +#include <ctime> #include <memory> #include <string> #include <utility> namespace clang { +class DiagnosticsEngine; class DirectoryEntry; class FileEntry; class FileManager; -class DiagnosticConsumer; -class DiagnosticsEngine; class HeaderSearch; -class ModuleMapParser; +class SourceManager; /// \brief A mechanism to observe the actions of the module map parser as it /// reads module map files. @@ -82,33 +80,40 @@ class ModuleMap { /// \brief The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". - const DirectoryEntry *BuiltinIncludeDir; + const DirectoryEntry *BuiltinIncludeDir = nullptr; /// \brief Language options used to parse the module map itself. /// /// These are always simple C language options. LangOptions MMapLangOpts; - // The module that the main source file is associated with (the module - // named LangOpts::CurrentModule, if we've loaded it). - Module *SourceModule; + /// The module that the main source file is associated with (the module + /// named LangOpts::CurrentModule, if we've loaded it). + Module *SourceModule = nullptr; + + /// The global module for the current TU, if we still own it. (Ownership is + /// transferred if/when we create an enclosing module. + std::unique_ptr<Module> PendingGlobalModule; /// \brief The top-level modules that are known. llvm::StringMap<Module *> Modules; /// \brief The number of modules we have created in total. - unsigned NumCreatedModules; + unsigned NumCreatedModules = 0; public: /// \brief Flags describing the role of a module header. enum ModuleHeaderRole { /// \brief This header is normally included in the module. NormalHeader = 0x0, + /// \brief This header is included but private. PrivateHeader = 0x1, + /// \brief This header is part of the module (for layering purposes) but /// should be textually included. TextualHeader = 0x2, + // Caution: Adding an enumerator needs other changes. // Adjust the number of bits for KnownHeader::Storage. // Adjust the bitfield HeaderFileInfo::HeaderRole size. @@ -119,6 +124,7 @@ public: /// Convert a header kind to a role. Requires Kind to not be HK_Excluded. static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind); + /// Convert a header role to a kind. static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role); @@ -128,8 +134,8 @@ public: llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage; public: - KnownHeader() : Storage(nullptr, NormalHeader) { } - KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { } + KnownHeader() : Storage(nullptr, NormalHeader) {} + KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) {} friend bool operator==(const KnownHeader &A, const KnownHeader &B) { return A.Storage == B.Storage; @@ -162,11 +168,13 @@ public: } }; - typedef llvm::SmallPtrSet<const FileEntry *, 1> AdditionalModMapsSet; + using AdditionalModMapsSet = llvm::SmallPtrSet<const FileEntry *, 1>; private: - typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>> - HeadersMap; + friend class ModuleMapParser; + + using HeadersMap = + llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>; /// \brief Mapping from each header to the module that owns the contents of /// that header. @@ -174,6 +182,7 @@ private: /// Map from file sizes to modules with lazy header directives of that size. mutable llvm::DenseMap<off_t, llvm::TinyPtrVector<Module*>> LazyHeadersBySize; + /// Map from mtimes to modules with lazy header directives with those mtimes. mutable llvm::DenseMap<time_t, llvm::TinyPtrVector<Module*>> LazyHeadersByModTime; @@ -188,9 +197,6 @@ private: /// \brief The set of attributes that can be attached to a module. struct Attributes { - Attributes() - : IsSystem(), IsExternC(), IsExhaustive(), NoUndeclaredIncludes() {} - /// \brief Whether this is a system module. unsigned IsSystem : 1; @@ -203,12 +209,14 @@ private: /// \brief Whether files in this module can only include non-modular headers /// and headers from used modules. unsigned NoUndeclaredIncludes : 1; + + Attributes() + : IsSystem(false), IsExternC(false), IsExhaustive(false), + NoUndeclaredIncludes(false) {} }; /// \brief A directory for which framework modules can be inferred. struct InferredDirectory { - InferredDirectory() : InferModules() {} - /// \brief Whether to infer modules from this directory. unsigned InferModules : 1; @@ -222,6 +230,8 @@ private: /// \brief 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 @@ -238,8 +248,6 @@ private: /// map. llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap; - friend class ModuleMapParser; - /// \brief Resolve the given export declaration into an actual export /// declaration. /// @@ -341,7 +349,6 @@ public: HeaderSearch &HeaderInfo); /// \brief Destroy the module map. - /// ~ModuleMap(); /// \brief Set the target information. @@ -460,7 +467,7 @@ public: /// \param Name The name of the module to find or create. /// /// \param Parent The module that will act as the parent of this submodule, - /// or NULL to indicate that this is a top-level module. + /// or nullptr to indicate that this is a top-level module. /// /// \param IsFramework Whether this is a framework module. /// @@ -472,6 +479,14 @@ public: bool IsFramework, bool IsExplicit); + /// \brief 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. + /// Unfortunately, we can't create the module interface unit's Module until + /// 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. /// The module must not already exist, and will be configured for the current /// compilation. @@ -479,7 +494,8 @@ public: /// Note that this also sets the current module to the newly-created module. /// /// \returns The newly-created module. - Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name); + Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name, + Module *GlobalModule); /// \brief Infer the contents of a framework module map from the given /// framework directory. @@ -492,7 +508,7 @@ public: /// \param Module The module whose module map file will be returned, if known. /// /// \returns The file entry for the module map file containing the given - /// module, or NULL if the module definition was inferred. + /// 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 @@ -599,11 +615,12 @@ public: /// \brief Dump the contents of the module map, for debugging purposes. void dump(); - typedef llvm::StringMap<Module *>::const_iterator module_iterator; + using module_iterator = llvm::StringMap<Module *>::const_iterator; + module_iterator module_begin() const { return Modules.begin(); } module_iterator module_end() const { return Modules.end(); } }; -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_LEX_MODULEMAP_H diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h index 83e6f99078df..3967f8688966 100644 --- a/include/clang/Lex/MultipleIncludeOpt.h +++ b/include/clang/Lex/MultipleIncludeOpt.h @@ -92,7 +92,7 @@ public: TheMacro = nullptr; } - /// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the + /// getHasReadAnyTokensVal - This is used for the \#ifndef handshake at the /// top of the file when reading preprocessor directives. Otherwise, reading /// the "ifndef x" would count as reading tokens. bool getHasReadAnyTokensVal() const { return ReadAnyTokens; } diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 81c3bd7d14ec..19bce4dd32e8 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -235,6 +235,14 @@ public: virtual void PragmaWarningPop(SourceLocation Loc) { } + /// \brief 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 + /// is read. + virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {} + /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a /// macro invocation is found. virtual void MacroExpands(const Token &MacroNameTok, @@ -266,7 +274,10 @@ public: /// \brief 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. - virtual void SourceRangeSkipped(SourceRange Range) { + /// \param EndifLoc The end location of the 'endif' token, which may precede + /// the range skipped by the directive (e.g excluding comments after an + /// 'endif'). + virtual void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) { } enum ConditionValueKind { @@ -381,6 +392,12 @@ public: Second->Ident(Loc, str); } + void PragmaDirective(SourceLocation Loc, + PragmaIntroducerKind Introducer) override { + First->PragmaDirective(Loc, Introducer); + Second->PragmaDirective(Loc, Introducer); + } + void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, StringRef Str) override { First->PragmaComment(Loc, Kind, Str); @@ -393,6 +410,11 @@ public: Second->PragmaDetectMismatch(Loc, Name, Value); } + void PragmaDebug(SourceLocation Loc, StringRef DebugType) override { + First->PragmaDebug(Loc, DebugType); + Second->PragmaDebug(Loc, DebugType); + } + void PragmaMessage(SourceLocation Loc, StringRef Namespace, PragmaMessageKind Kind, StringRef Str) override { First->PragmaMessage(Loc, Namespace, Kind, Str); @@ -437,6 +459,16 @@ public: Second->PragmaWarningPop(Loc); } + void PragmaAssumeNonNullBegin(SourceLocation Loc) override { + First->PragmaAssumeNonNullBegin(Loc); + Second->PragmaAssumeNonNullBegin(Loc); + } + + void PragmaAssumeNonNullEnd(SourceLocation Loc) override { + First->PragmaAssumeNonNullEnd(Loc); + Second->PragmaAssumeNonNullEnd(Loc); + } + void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override { First->MacroExpands(MacroNameTok, MD, Range, Args); @@ -462,9 +494,9 @@ public: Second->Defined(MacroNameTok, MD, Range); } - void SourceRangeSkipped(SourceRange Range) override { - First->SourceRangeSkipped(Range); - Second->SourceRangeSkipped(Range); + void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { + First->SourceRangeSkipped(Range, EndifLoc); + Second->SourceRangeSkipped(Range, EndifLoc); } /// \brief Hook called whenever an \#if is seen. diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index f96af665b157..f122a008e4aa 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -1,4 +1,4 @@ -//===--- PTHLexer.h - Lexer based on Pre-tokenized input --------*- C++ -*-===// +//===- PTHLexer.h - Lexer based on Pre-tokenized input ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,12 +14,15 @@ #ifndef LLVM_CLANG_LEX_PTHLEXER_H #define LLVM_CLANG_LEX_PTHLEXER_H +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/PreprocessorLexer.h" +#include "clang/Lex/Token.h" namespace clang { +class Preprocessor; class PTHManager; -class PTHSpellingSearch; class PTHLexer : public PreprocessorLexer { SourceLocation FileStartLoc; @@ -33,7 +36,7 @@ class PTHLexer : public PreprocessorLexer { /// LastHashTokPtr - Pointer into TokBuf of the last processed '#' /// token that appears at the start of a line. - const unsigned char* LastHashTokPtr; + const unsigned char* LastHashTokPtr = nullptr; /// PPCond - Pointer to a side table in the PTH file that provides a /// a concise summary of the preprocessor conditional block structure. @@ -44,11 +47,8 @@ class PTHLexer : public PreprocessorLexer { /// to process when doing quick skipping of preprocessor blocks. const unsigned char* CurPPCondPtr; - PTHLexer(const PTHLexer &) = delete; - void operator=(const PTHLexer &) = delete; - /// ReadToken - Used by PTHLexer to read tokens TokBuf. - void ReadToken(Token& T); + void ReadToken(Token &T); bool LexEndOfFile(Token &Result); @@ -61,10 +61,13 @@ protected: friend class PTHManager; /// Create a PTHLexer for the specified token stream. - PTHLexer(Preprocessor& pp, FileID FID, const unsigned char *D, + PTHLexer(Preprocessor &pp, FileID FID, const unsigned char *D, const unsigned char* ppcond, PTHManager &PM); + public: - ~PTHLexer() override {} + PTHLexer(const PTHLexer &) = delete; + PTHLexer &operator=(const PTHLexer &) = delete; + ~PTHLexer() override = default; /// Lex - Return the next token. bool Lex(Token &Tok); @@ -99,6 +102,6 @@ public: bool SkipBlock(); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PTHLEXER_H diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index f4e4774429f9..483b69f23a9c 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -1,4 +1,4 @@ -//===--- PTHManager.h - Manager object for PTH processing -------*- C++ -*-===// +//===- PTHManager.h - Manager object for PTH processing ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,30 +17,33 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/OnDiskHashTable.h" +#include <memory> namespace llvm { - class MemoryBuffer; -} + +class MemoryBuffer; + +} // namespace llvm namespace clang { -class FileEntry; -class Preprocessor; -class PTHLexer; class DiagnosticsEngine; class FileSystemStatCache; +class Preprocessor; +class PTHLexer; class PTHManager : public IdentifierInfoLookup { friend class PTHLexer; - friend class PTHStatCache; - class PTHStringLookupTrait; class PTHFileLookupTrait; - typedef llvm::OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup; - typedef llvm::OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup; + class PTHStringLookupTrait; + + using PTHStringIdLookup = llvm::OnDiskChainedHashTable<PTHStringLookupTrait>; + using PTHFileLookup = llvm::OnDiskChainedHashTable<PTHFileLookupTrait>; /// The memory mapped PTH file. std::unique_ptr<const llvm::MemoryBuffer> Buf; @@ -70,7 +73,7 @@ class PTHManager : public IdentifierInfoLookup { /// PP - The Preprocessor object that will use this PTHManager to create /// PTHLexer objects. - Preprocessor* PP; + Preprocessor* PP = nullptr; /// SpellingBase - The base offset within the PTH memory buffer that /// contains the cached spellings for literals. @@ -89,16 +92,13 @@ class PTHManager : public IdentifierInfoLookup { std::unique_ptr<PTHStringIdLookup> stringIdLookup, unsigned numIds, const unsigned char *spellingBase, const char *originalSourceFile); - PTHManager(const PTHManager &) = delete; - void operator=(const PTHManager &) = delete; - /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached /// spelling for a token. unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer); /// GetIdentifierInfo - Used to reconstruct IdentifierInfo objects from the /// PTH file. - inline IdentifierInfo* GetIdentifierInfo(unsigned PersistentID) { + IdentifierInfo *GetIdentifierInfo(unsigned PersistentID) { // Check if the IdentifierInfo has already been resolved. if (IdentifierInfo* II = PerIDCache[PersistentID]) return II; @@ -110,6 +110,8 @@ public: // The current PTH version. enum { Version = 10 }; + PTHManager(const PTHManager &) = delete; + PTHManager &operator=(const PTHManager &) = delete; ~PTHManager() override; /// getOriginalSourceFile - Return the full path to the original header @@ -120,18 +122,18 @@ public: /// get - Return the identifier token info 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 + /// of a reference. If the pointer is nullptr then the IdentifierInfo cannot /// be found. IdentifierInfo *get(StringRef Name) override; /// Create - This method creates PTHManager objects. The 'file' argument - /// is the name of the PTH file. This method returns NULL upon failure. + /// is the name of the PTH file. This method returns nullptr upon failure. static PTHManager *Create(StringRef file, DiagnosticsEngine &Diags); void setPreprocessor(Preprocessor *pp) { PP = pp; } /// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the - /// specified file. This method returns NULL if no cached tokens exist. + /// specified file. This method returns nullptr if no cached tokens exist. /// It is the responsibility of the caller to 'delete' the returned object. PTHLexer *CreateLexer(FileID FID); @@ -142,6 +144,6 @@ public: std::unique_ptr<FileSystemStatCache> createStatCache(); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PTHMANAGER_H diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index 274f0dad3dd0..090ae2a98236 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -1,4 +1,4 @@ -//===--- Pragma.h - Pragma registration and handling ------------*- C++ -*-===// +//===- Pragma.h - Pragma registration and handling --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,13 +17,13 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include <cassert> +#include <string> namespace clang { - class Preprocessor; - class Token; - class IdentifierInfo; - class PragmaNamespace; + +class PragmaNamespace; +class Preprocessor; +class Token; /** * \brief Describes how the pragma was introduced, e.g., with \#pragma, @@ -58,9 +58,10 @@ namespace clang { /// pragmas. class PragmaHandler { std::string Name; + public: + PragmaHandler() = default; explicit PragmaHandler(StringRef name) : Name(name) {} - PragmaHandler() {} virtual ~PragmaHandler(); StringRef getName() const { return Name; } @@ -89,8 +90,8 @@ public: class PragmaNamespace : public PragmaHandler { /// Handlers - This is a map of the handlers in this namespace with their name /// as key. - /// - llvm::StringMap<PragmaHandler*> Handlers; + llvm::StringMap<PragmaHandler *> Handlers; + public: explicit PragmaNamespace(StringRef Name) : PragmaHandler(Name) {} ~PragmaNamespace() override; @@ -103,16 +104,13 @@ public: bool IgnoreNull = true) const; /// AddPragma - Add a pragma to this namespace. - /// void AddPragma(PragmaHandler *Handler); /// RemovePragmaHandler - Remove the given handler from the /// namespace. void RemovePragmaHandler(PragmaHandler *Handler); - bool IsEmpty() { - return Handlers.empty(); - } + bool IsEmpty() const { return Handlers.empty(); } void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken) override; @@ -120,7 +118,6 @@ public: PragmaNamespace *getIfNamespace() override { return this; } }; +} // namespace clang -} // end namespace clang - -#endif +#endif // LLVM_CLANG_LEX_PRAGMA_H diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index fc2c50700400..5f7a6efcef10 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -1,4 +1,4 @@ -//===--- PreprocessingRecord.h - Record of Preprocessing --------*- C++ -*-===// +//===- PreprocessingRecord.h - Record of Preprocessing ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,24 +11,33 @@ // of what occurred during preprocessing. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H #define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H -#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <utility> #include <vector> namespace clang { - class IdentifierInfo; - class MacroInfo; - class PreprocessingRecord; -} + +class PreprocessingRecord; + +} // namespace clang /// \brief Allocates memory within a Clang preprocessing record. void *operator new(size_t bytes, clang::PreprocessingRecord &PR, @@ -39,8 +48,12 @@ void operator delete(void *ptr, clang::PreprocessingRecord &PR, unsigned) noexcept; namespace clang { - class MacroDefinitionRecord; - class FileEntry; + +class FileEntry; +class IdentifierInfo; +class MacroInfo; +class SourceManager; +class Token; /// \brief Base class that describes a preprocessed entity, which may be a /// preprocessor directive or macro expansion. @@ -78,11 +91,11 @@ namespace clang { SourceRange Range; protected: - PreprocessedEntity(EntityKind Kind, SourceRange Range) - : Kind(Kind), Range(Range) { } - friend class PreprocessingRecord; + PreprocessedEntity(EntityKind Kind, SourceRange Range) + : Kind(Kind), Range(Range) {} + public: /// \brief Retrieve the kind of preprocessed entity stored in this object. EntityKind getKind() const { return Kind; } @@ -122,7 +135,7 @@ namespace clang { class PreprocessingDirective : public PreprocessedEntity { public: PreprocessingDirective(EntityKind Kind, SourceRange Range) - : PreprocessedEntity(Kind, Range) { } + : PreprocessedEntity(Kind, Range) {} // Implement isa/cast/dyncast/etc. static bool classof(const PreprocessedEntity *PD) { @@ -199,10 +212,13 @@ namespace clang { enum InclusionKind { /// \brief An \c \#include directive. Include, + /// \brief An Objective-C \c \#import directive. Import, + /// \brief A GNU \c \#include_next directive. IncludeNext, + /// \brief A Clang \c \#__include_macros directive. IncludeMacros }; @@ -316,11 +332,14 @@ namespace clang { /// value 1 corresponds to element 0 in the local entities vector, /// value 2 corresponds to element 1 in the local entities vector, etc. class PPEntityID { - int ID; - explicit PPEntityID(int ID) : ID(ID) {} friend class PreprocessingRecord; + + int ID = 0; + + explicit PPEntityID(int ID) : ID(ID) {} + public: - PPEntityID() : ID(0) {} + PPEntityID() = default; }; static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) { @@ -331,7 +350,7 @@ namespace clang { llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions; /// \brief External source of preprocessed entities. - ExternalPreprocessingRecordSource *ExternalSource; + ExternalPreprocessingRecordSource *ExternalSource = nullptr; /// \brief Retrieve the preprocessed entity at the given ID. PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID); @@ -371,7 +390,7 @@ namespace clang { } /// \brief Deallocate memory in the preprocessing record. - void Deallocate(void *Ptr) { } + void Deallocate(void *Ptr) {} size_t getTotalMemory() const; @@ -397,11 +416,12 @@ namespace clang { iterator, int, std::random_access_iterator_tag, PreprocessedEntity *, int, PreprocessedEntity *, PreprocessedEntity *> { + friend class PreprocessingRecord; + PreprocessingRecord *Self; iterator(PreprocessingRecord *Self, int Position) : iterator::iterator_adaptor_base(Position), Self(Self) {} - friend class PreprocessingRecord; public: iterator() : iterator(nullptr, 0) {} @@ -451,7 +471,6 @@ namespace clang { /// encompasses. /// /// \param R the range to look for preprocessed entities. - /// llvm::iterator_range<iterator> getPreprocessedEntitiesInRange(SourceRange R); @@ -485,6 +504,9 @@ namespace clang { } private: + friend class ASTReader; + friend class ASTWriter; + void MacroExpands(const Token &Id, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override; void MacroDefined(const Token &Id, const MacroDirective *MD) override; @@ -500,11 +522,13 @@ namespace clang { const MacroDefinition &MD) override; void Ifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override; + /// \brief Hook called whenever the 'defined' operator is seen. void Defined(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range) override; - void SourceRangeSkipped(SourceRange Range) override; + void SourceRangeSkipped(SourceRange Range, + SourceLocation EndifLoc) override; void addMacroExpansion(const Token &Id, const MacroInfo *MI, SourceRange Range); @@ -517,11 +541,9 @@ namespace clang { } CachedRangeQuery; std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R); - - friend class ASTReader; - friend class ASTWriter; }; -} // end namespace clang + +} // namespace clang inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR, unsigned alignment) noexcept { diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index dba4b80f6071..485600f12232 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -1,4 +1,4 @@ -//===--- Preprocessor.h - C Language Family Preprocessor --------*- C++ -*-===// +//===- Preprocessor.h - C Language Family Preprocessor ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::Preprocessor interface. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_PREPROCESSOR_H @@ -18,48 +18,70 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/MacroInfo.h" +#include "clang/Lex/ModuleLoader.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/PTHLexer.h" +#include "clang/Lex/Token.h" #include "clang/Lex/TokenLexer.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Registry.h" +#include <cassert> +#include <cstddef> +#include <cstdint> #include <memory> +#include <map> +#include <string> +#include <utility> #include <vector> namespace llvm { - template<unsigned InternalLen> class SmallString; -} + +template<unsigned InternalLen> class SmallString; + +} // namespace llvm namespace clang { -class SourceManager; +class CodeCompletionHandler; +class CommentHandler; +class DirectoryEntry; +class DirectoryLookup; class ExternalPreprocessorSource; -class FileManager; class FileEntry; +class FileManager; class HeaderSearch; +class MacroArgs; class MemoryBufferCache; -class PragmaNamespace; class PragmaHandler; -class CommentHandler; -class ScratchBuffer; -class TargetInfo; -class PPCallbacks; -class CodeCompletionHandler; -class DirectoryLookup; +class PragmaNamespace; class PreprocessingRecord; -class ModuleLoader; -class PTHManager; +class PreprocessorLexer; class PreprocessorOptions; +class PTHManager; +class ScratchBuffer; +class TargetInfo; /// \brief Stores token information for comparing actual tokens with /// predefined values. Only handles simple tokens and identifiers. @@ -75,7 +97,9 @@ public: assert(!tok::isLiteral(Kind) && "Literals are not supported."); assert(!tok::isAnnotation(Kind) && "Annotations are not supported."); } + TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {} + bool operator==(const Token &Tok) const { return Tok.getKind() == Kind && (!II || II == Tok.getIdentifierInfo()); @@ -84,9 +108,14 @@ public: /// \brief Context in which macro name is used. enum MacroUse { - MU_Other = 0, // other than #define or #undef - MU_Define = 1, // macro name specified in #define - MU_Undef = 2 // macro name specified in #undef + // other than #define or #undef + MU_Other = 0, + + // macro name specified in #define + MU_Define = 1, + + // macro name specified in #undef + MU_Undef = 2 }; /// \brief Engages in a tight little dance with the lexer to efficiently @@ -96,11 +125,14 @@ enum MacroUse { /// know anything about preprocessor-level issues like the \#include stack, /// token expansion, etc. class Preprocessor { + friend class VAOptDefinitionContext; + friend class VariadicMacroScopeGuard; + std::shared_ptr<PreprocessorOptions> PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; - const TargetInfo *Target; - const TargetInfo *AuxTarget; + const TargetInfo *Target = nullptr; + const TargetInfo *AuxTarget = nullptr; FileManager &FileMgr; SourceManager &SourceMgr; MemoryBufferCache &PCMCache; @@ -111,7 +143,6 @@ class Preprocessor { /// \brief External source of macros. ExternalPreprocessorSource *ExternalSource; - /// An optional PTHManager object used for getting tokens from /// a token cache rather than lexing the original source file. std::unique_ptr<PTHManager> PTH; @@ -130,6 +161,7 @@ class Preprocessor { IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma IdentifierInfo *Ident__identifier; // __identifier IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ + IdentifierInfo *Ident__VA_OPT__; // __VA_OPT__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin @@ -141,10 +173,17 @@ class Preprocessor { IdentifierInfo *Ident__building_module; // __building_module IdentifierInfo *Ident__MODULE__; // __MODULE__ IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute + IdentifierInfo *Ident__has_c_attribute; // __has_c_attribute IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute + IdentifierInfo *Ident__is_target_arch; // __is_target_arch + IdentifierInfo *Ident__is_target_vendor; // __is_target_vendor + IdentifierInfo *Ident__is_target_os; // __is_target_os + IdentifierInfo *Ident__is_target_environment; // __is_target_environment SourceLocation DATELoc, TIMELoc; - unsigned CounterValue; // Next __COUNTER__ value. + + // Next __COUNTER__ value, starts at 0. + unsigned CounterValue = 0; enum { /// \brief Maximum depth of \#includes. @@ -218,19 +257,19 @@ class Preprocessor { /// \brief True if we want to ignore EOF token and continue later on (thus /// avoid tearing the Lexer and etc. down). - bool IncrementalProcessing; + bool IncrementalProcessing = false; /// The kind of translation unit we are processing. TranslationUnitKind TUKind; /// \brief The code-completion handler. - CodeCompletionHandler *CodeComplete; + CodeCompletionHandler *CodeComplete = nullptr; /// \brief The file that we're performing code-completion for, if any. - const FileEntry *CodeCompletionFile; + const FileEntry *CodeCompletionFile = nullptr; /// \brief The offset in file for the code-completion point. - unsigned CodeCompletionOffset; + unsigned CodeCompletionOffset = 0; /// \brief The location for the code-completion point. This gets instantiated /// when the CodeCompletionFile gets \#include'ed for preprocessing. @@ -250,11 +289,11 @@ class Preprocessor { SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath; /// \brief Whether the last token we lexed was an '@'. - bool LastTokenWasAt; + bool LastTokenWasAt = false; /// \brief Whether the module import expects an identifier next. Otherwise, /// it expects a '.' or ';'. - bool ModuleImportExpectsIdentifier; + bool ModuleImportExpectsIdentifier = false; /// \brief The source location of the currently-active /// \#pragma clang arc_cf_code_audited begin. @@ -265,16 +304,16 @@ class Preprocessor { SourceLocation PragmaAssumeNonNullLoc; /// \brief True if we hit the code-completion point. - bool CodeCompletionReached; + bool CodeCompletionReached = false; /// \brief The code completion token containing the information /// on the stem that is to be code completed. - IdentifierInfo *CodeCompletionII; + IdentifierInfo *CodeCompletionII = nullptr; /// \brief The directory that the main file should be considered to occupy, /// if it does not correspond to a real file (as happens when building a /// module). - const DirectoryEntry *MainFileDir; + const DirectoryEntry *MainFileDir = nullptr; /// \brief The number of bytes that we will initially skip when entering the /// main file, along with a flag that indicates whether skipping this number @@ -283,6 +322,26 @@ class Preprocessor { /// This is used when loading a precompiled preamble. std::pair<int, bool> SkipMainFilePreamble; +public: + struct PreambleSkipInfo { + SourceLocation HashTokenLoc; + SourceLocation IfTokenLoc; + bool FoundNonSkipPortion; + bool FoundElse; + SourceLocation ElseLoc; + + PreambleSkipInfo(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc, + bool FoundNonSkipPortion, bool FoundElse, + SourceLocation ElseLoc) + : HashTokenLoc(HashTokenLoc), IfTokenLoc(IfTokenLoc), + FoundNonSkipPortion(FoundNonSkipPortion), FoundElse(FoundElse), + ElseLoc(ElseLoc) {} + }; + +private: + friend class ASTReader; + friend class MacroArgs; + class PreambleConditionalStackStore { enum State { Off = 0, @@ -291,7 +350,7 @@ class Preprocessor { }; public: - PreambleConditionalStackStore() : ConditionalStackState(Off) {} + PreambleConditionalStackStore() = default; void startRecording() { ConditionalStackState = Recording; } void startReplaying() { ConditionalStackState = Replaying; } @@ -316,9 +375,15 @@ class Preprocessor { bool hasRecordedPreamble() const { return !ConditionalStack.empty(); } + bool reachedEOFWhileSkipping() const { return SkipInfo.hasValue(); } + + void clearSkipInfo() { SkipInfo.reset(); } + + llvm::Optional<PreambleSkipInfo> SkipInfo; + private: SmallVector<PPConditionalInfo, 4> ConditionalStack; - State ConditionalStackState; + State ConditionalStackState = Off; } PreambleConditionalStack; /// \brief The current top of the stack that we're lexing from if @@ -337,14 +402,14 @@ class Preprocessor { /// if not expanding a macro. /// /// This is an alias for either CurLexer or CurPTHLexer. - PreprocessorLexer *CurPPLexer; + PreprocessorLexer *CurPPLexer = nullptr; /// \brief 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; + const DirectoryLookup *CurDirLookup = nullptr; /// \brief The current macro we are expanding, if we are expanding a macro. /// @@ -358,11 +423,11 @@ class Preprocessor { CLK_TokenLexer, CLK_CachingLexer, CLK_LexAfterModuleImport - } CurLexerKind; + } CurLexerKind = CLK_Lexer; /// \brief If the current lexer is for a submodule that is being built, this /// is that submodule. - Module *CurLexerSubmodule; + Module *CurLexerSubmodule = nullptr; /// \brief Keeps track of the stack of files currently /// \#included, and macros currently being expanded from, not counting @@ -401,27 +466,31 @@ class Preprocessor { Token Tok; MacroDefinition MD; SourceRange Range; + MacroExpandsInfo(Token Tok, MacroDefinition MD, SourceRange Range) - : Tok(Tok), MD(MD), Range(Range) { } + : Tok(Tok), MD(MD), Range(Range) {} }; SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; /// Information about a name that has been used to define a module macro. struct ModuleMacroInfo { - ModuleMacroInfo(MacroDirective *MD) - : MD(MD), ActiveModuleMacrosGeneration(0), IsAmbiguous(false) {} - /// The most recent macro directive for this identifier. MacroDirective *MD; + /// The active module macros for this identifier. - llvm::TinyPtrVector<ModuleMacro*> ActiveModuleMacros; + llvm::TinyPtrVector<ModuleMacro *> ActiveModuleMacros; + /// The generation number at which we last updated ActiveModuleMacros. /// \see Preprocessor::VisibleModules. - unsigned ActiveModuleMacrosGeneration; + unsigned ActiveModuleMacrosGeneration = 0; + /// Whether this macro name is ambiguous. - bool IsAmbiguous; + bool IsAmbiguous = false; + /// The module macros that are overridden by this macro. - llvm::TinyPtrVector<ModuleMacro*> OverriddenMacros; + llvm::TinyPtrVector<ModuleMacro *> OverriddenMacros; + + ModuleMacroInfo(MacroDirective *MD) : MD(MD) {} }; /// The state of a macro for an identifier. @@ -456,15 +525,18 @@ class Preprocessor { public: MacroState() : MacroState(nullptr) {} MacroState(MacroDirective *MD) : State(MD) {} + MacroState(MacroState &&O) noexcept : State(O.State) { O.State = (MacroDirective *)nullptr; } + MacroState &operator=(MacroState &&O) noexcept { auto S = O.State; O.State = (MacroDirective *)nullptr; State = S; return *this; } + ~MacroState() { if (auto *Info = State.dyn_cast<ModuleMacroInfo*>()) Info->~ModuleMacroInfo(); @@ -475,6 +547,7 @@ class Preprocessor { return Info->MD; return State.get<MacroDirective*>(); } + void setLatest(MacroDirective *MD) { if (auto *Info = State.dyn_cast<ModuleMacroInfo*>()) Info->MD = MD; @@ -486,6 +559,7 @@ class Preprocessor { auto *Info = getModuleInfo(PP, II); return Info ? Info->IsAmbiguous : false; } + ArrayRef<ModuleMacro *> getActiveModuleMacros(Preprocessor &PP, const IdentifierInfo *II) const { if (auto *Info = getModuleInfo(PP, II)) @@ -498,7 +572,7 @@ class Preprocessor { // FIXME: Incorporate module macros into the result of this. if (auto *Latest = getLatest()) return Latest->findDirectiveAtLoc(Loc, SourceMgr); - return MacroDirective::DefInfo(); + return {}; } void overrideActiveModuleMacros(Preprocessor &PP, IdentifierInfo *II) { @@ -510,11 +584,13 @@ class Preprocessor { Info->IsAmbiguous = false; } } + ArrayRef<ModuleMacro*> getOverriddenMacros() const { if (auto *Info = State.dyn_cast<ModuleMacroInfo*>()) return Info->OverriddenMacros; return None; } + void setOverriddenMacros(Preprocessor &PP, ArrayRef<ModuleMacro *> Overrides) { auto *Info = State.dyn_cast<ModuleMacroInfo*>(); @@ -537,31 +613,33 @@ class Preprocessor { /// the reverse order (the latest one is in the head of the list). /// /// This mapping lives within the \p CurSubmoduleState. - typedef llvm::DenseMap<const IdentifierInfo *, MacroState> MacroMap; - - friend class ASTReader; + using MacroMap = llvm::DenseMap<const IdentifierInfo *, MacroState>; struct SubmoduleState; /// \brief Information about a submodule that we're currently building. struct BuildingSubmoduleInfo { - BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma, - SubmoduleState *OuterSubmoduleState, - unsigned OuterPendingModuleMacroNames) - : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma), - OuterSubmoduleState(OuterSubmoduleState), - OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {} - /// The module that we are building. Module *M; + /// The location at which the module was included. SourceLocation ImportLoc; + /// Whether we entered this submodule via a pragma. bool IsPragma; + /// The previous SubmoduleState. SubmoduleState *OuterSubmoduleState; + /// The number of pending module macro names when we started building this. unsigned OuterPendingModuleMacroNames; + + BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma, + SubmoduleState *OuterSubmoduleState, + unsigned OuterPendingModuleMacroNames) + : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma), + OuterSubmoduleState(OuterSubmoduleState), + OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {} }; SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack; @@ -569,12 +647,14 @@ class Preprocessor { struct SubmoduleState { /// The macros for the submodule. MacroMap Macros; + /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; - std::map<Module*, SubmoduleState> Submodules; + std::map<Module *, SubmoduleState> Submodules; /// The preprocessor state for preprocessing outside of any submodule. SubmoduleState NullSubmoduleState; @@ -587,11 +667,11 @@ class Preprocessor { llvm::FoldingSet<ModuleMacro> ModuleMacros; /// The names of potential module macros that we've not yet processed. - llvm::SmallVector<const IdentifierInfo*, 32> PendingModuleMacroNames; + llvm::SmallVector<const IdentifierInfo *, 32> PendingModuleMacroNames; /// The list of module macros, for each identifier, that are not overridden by /// any other module macro. - llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro*>> + llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro *>> LeafModuleMacros; /// \brief Macros that we want to warn because they are not used at the end @@ -603,25 +683,35 @@ class Preprocessor { /// just so that we can report that they are unused, we just warn using /// the SourceLocations of this set (that will be filled by the ASTReader). /// We are using SmallPtrSet instead of a vector for faster removal. - typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy; + using WarnUnusedMacroLocsTy = llvm::SmallPtrSet<SourceLocation, 32>; WarnUnusedMacroLocsTy WarnUnusedMacroLocs; /// \brief A "freelist" of MacroArg objects that can be /// reused for quick allocation. - MacroArgs *MacroArgCache; - friend class MacroArgs; + MacroArgs *MacroArgCache = nullptr; /// For each IdentifierInfo used in a \#pragma push_macro directive, /// we keep a MacroInfo stack used to restore the previous macro value. - llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; + llvm::DenseMap<IdentifierInfo *, std::vector<MacroInfo *>> + PragmaPushMacroInfo; // Various statistics we track for performance analysis. - unsigned NumDirectives, NumDefined, NumUndefined, NumPragma; - unsigned NumIf, NumElse, NumEndif; - unsigned NumEnteredSourceFiles, MaxIncludeStackDepth; - unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded; - unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste; - unsigned NumSkipped; + unsigned NumDirectives = 0; + unsigned NumDefined = 0; + unsigned NumUndefined = 0; + unsigned NumPragma = 0; + unsigned NumIf = 0; + unsigned NumElse = 0; + unsigned NumEndif = 0; + unsigned NumEnteredSourceFiles = 0; + unsigned MaxIncludeStackDepth = 0; + unsigned NumMacroExpanded = 0; + unsigned NumFnMacroExpanded = 0; + unsigned NumBuiltinMacroExpanded = 0; + unsigned NumFastMacroExpanded = 0; + unsigned NumTokenPaste = 0; + unsigned NumFastTokenPaste = 0; + unsigned NumSkipped = 0; /// \brief The predefined macros that preprocessor should use from the /// command line etc. @@ -643,17 +733,17 @@ class Preprocessor { /// going to lex in the cache and when it finishes the tokens are removed /// from the end of the cache. SmallVector<Token, 16> MacroExpandedTokens; - std::vector<std::pair<TokenLexer *, size_t> > MacroExpandingLexersStack; + std::vector<std::pair<TokenLexer *, size_t>> MacroExpandingLexersStack; /// \brief A record of the macro definitions and expansions that /// occurred during preprocessing. /// /// This is an optional side structure that can be enabled with /// \c createPreprocessingRecord() prior to preprocessing. - PreprocessingRecord *Record; + PreprocessingRecord *Record = nullptr; /// Cached tokens state. - typedef SmallVector<Token, 1> CachedTokensTy; + using CachedTokensTy = SmallVector<Token, 1>; /// \brief Cached tokens are stored here when we do backtracking or /// lookahead. They are "lexed" by the CachingLex() method. @@ -664,7 +754,7 @@ class Preprocessor { /// /// If it points beyond the CachedTokens vector, it means that a normal /// Lex() should be invoked. - CachedTokensTy::size_type CachedLexPos; + CachedTokensTy::size_type CachedLexPos = 0; /// \brief Stack of backtrack positions, allowing nested backtracks. /// @@ -680,7 +770,7 @@ class Preprocessor { /// MacroInfos are managed as a chain for easy disposal. This is the head /// of that list. - MacroInfoChain *MIChainHead; + MacroInfoChain *MIChainHead = nullptr; void updateOutOfDateIdentifier(IdentifierInfo &II) const; @@ -853,7 +943,7 @@ public: MacroDefinition getMacroDefinition(const IdentifierInfo *II) { if (!II->hasMacroDefinition()) - return MacroDefinition(); + return {}; MacroState &S = CurSubmoduleState->Macros[II]; auto *MD = S.getLatest(); @@ -867,7 +957,7 @@ public: MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc) { if (!II->hadMacroDefinition()) - return MacroDefinition(); + return {}; MacroState &S = CurSubmoduleState->Macros[II]; MacroDirective::DefInfo DI; @@ -923,6 +1013,7 @@ public: MacroInfo *MI) { return appendDefMacroDirective(II, MI, MI->getDefinitionLoc()); } + /// \brief Set a MacroDirective that was loaded from a PCH file. void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED, MacroDirective *MD); @@ -946,10 +1037,12 @@ public: /// Iterators for the macro history table. Currently defined macros have /// IdentifierInfo::hasMacroDefinition() set and an empty /// MacroInfo::getUndefLoc() at the head of the list. - typedef MacroMap::const_iterator macro_iterator; + using macro_iterator = MacroMap::const_iterator; + macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; llvm::iterator_range<macro_iterator> + macros(bool IncludeExternalMacros = true) const { return llvm::make_range(macro_begin(IncludeExternalMacros), macro_end(IncludeExternalMacros)); @@ -963,6 +1056,7 @@ public: ArrayRef<TokenValue> Tokens) const; const std::string &getPredefines() const { return Predefines; } + /// \brief Set the predefines for this Preprocessor. /// /// These predefines are automatically injected when parsing the main file. @@ -1087,6 +1181,7 @@ public: bool DisableMacroExpansion) { EnterTokenStream(Toks.release(), NumToks, DisableMacroExpansion, true); } + void EnterTokenStream(ArrayRef<Token> Toks, bool DisableMacroExpansion) { EnterTokenStream(Toks.data(), Toks.size(), DisableMacroExpansion, false); } @@ -1605,7 +1700,6 @@ private: llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons; public: - /// \brief Specifies the reason for poisoning an identifier. /// /// If that identifier is accessed while poisoned, then this reason will be @@ -1655,7 +1749,6 @@ public: /// lex again. bool HandleIdentifier(Token &Identifier); - /// \brief Callback invoked when the lexer hits the end of the current file. /// /// This either returns the EOF token and returns true, or @@ -1760,6 +1853,8 @@ public: Module *LeaveSubmodule(bool ForPragma); private: + friend void TokenLexer::ExpandFunctionArguments(); + void PushIncludeMacroStack() { assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer"); IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule, @@ -1818,7 +1913,6 @@ private: /// /// Either returns a pointer to a MacroInfo object OR emits a diagnostic and /// returns a nullptr if an invalid sequence of tokens is encountered. - MacroInfo *ReadOptionalMacroParameterListAndBody( const Token &MacroNameTok, bool ImmediatelyAfterHeaderGuard); @@ -1836,7 +1930,8 @@ private: /// \p FoundElse is false, then \#else directives are ok, if not, then we have /// already seen one so a \#else directive is a duplicate. When this returns, /// the caller can lex the first valid token. - void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, + void SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, + SourceLocation IfTokenLoc, bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc = SourceLocation()); @@ -1848,6 +1943,7 @@ private: struct DirectiveEvalResult { /// Whether the expression was evaluated as true or not. bool Conditional; + /// True if the expression contained identifiers that were undefined. bool IncludedUndefinedIds; }; @@ -1877,8 +1973,8 @@ private: /// from the end of the cache. Token *cacheMacroExpandedTokens(TokenLexer *tokLexer, ArrayRef<Token> tokens); + void removeCachedMacroExpandedTokensOfLastLexer(); - friend void TokenLexer::ExpandFunctionArguments(); /// Determine whether the next preprocessor token to be /// lexed is a '('. If so, consume the token and return true, if not, this @@ -1934,17 +2030,21 @@ private: //===--------------------------------------------------------------------===// // Caching stuff. void CachingLex(Token &Result); + bool InCachingLexMode() const { // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means // that we are past EOF, not that we are in CachingLex mode. return !CurPPLexer && !CurTokenLexer && !CurPTHLexer && !IncludeMacroStack.empty(); } + void EnterCachingLexMode(); + void ExitCachingLexMode() { if (InCachingLexMode()) RemoveTopOfLexerStack(); } + const Token &PeekAhead(unsigned N); void AnnotatePreviousCachedTokens(const Token &Tok); @@ -2015,9 +2115,15 @@ public: PreambleConditionalStack.setStack(s); } - void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s) { + void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s, + llvm::Optional<PreambleSkipInfo> SkipInfo) { PreambleConditionalStack.startReplaying(); PreambleConditionalStack.setStack(s); + PreambleConditionalStack.SkipInfo = SkipInfo; + } + + llvm::Optional<PreambleSkipInfo> getPreambleSkipInfo() const { + return PreambleConditionalStack.SkipInfo; } private: @@ -2030,16 +2136,18 @@ private: void HandleUndefDirective(); // Conditional Inclusion. - void HandleIfdefDirective(Token &Tok, bool isIfndef, - bool ReadAnyTokensBeforeDirective); - void HandleIfDirective(Token &Tok, bool ReadAnyTokensBeforeDirective); + void HandleIfdefDirective(Token &Tok, const Token &HashToken, + bool isIfndef, bool ReadAnyTokensBeforeDirective); + void HandleIfDirective(Token &Tok, const Token &HashToken, + bool ReadAnyTokensBeforeDirective); void HandleEndifDirective(Token &Tok); - void HandleElseDirective(Token &Tok); - void HandleElifDirective(Token &Tok); + void HandleElseDirective(Token &Tok, const Token &HashToken); + void HandleElifDirective(Token &Tok, const Token &HashToken); // Pragmas. void HandlePragmaDirective(SourceLocation IntroducerLoc, PragmaIntroducerKind Introducer); + public: void HandlePragmaOnce(Token &OnceTok); void HandlePragmaMark(); @@ -2073,8 +2181,8 @@ public: }; /// \brief Registry of pragma handlers added by plugins -typedef llvm::Registry<PragmaHandler> PragmaHandlerRegistry; +using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PREPROCESSOR_H diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index 5c2e4d41454b..ff71d11b4511 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -1,4 +1,4 @@ -//===--- PreprocessorLexer.h - C Language Family Lexer ----------*- C++ -*-===// +//===- PreprocessorLexer.h - C Language Family Lexer ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the PreprocessorLexer interface. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H @@ -17,8 +17,10 @@ #include "clang/Lex/MultipleIncludeOpt.h" #include "clang/Lex/Token.h" +#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include <cassert> namespace clang { @@ -27,25 +29,29 @@ class Preprocessor; class PreprocessorLexer { virtual void anchor(); + protected: - Preprocessor *PP; // Preprocessor object controlling lexing. + friend class Preprocessor; + + // Preprocessor object controlling lexing. + Preprocessor *PP = nullptr; /// The SourceManager FileID corresponding to the file being lexed. const FileID FID; /// \brief Number of SLocEntries before lexing the file. - unsigned InitialNumSLocEntries; + unsigned InitialNumSLocEntries = 0; //===--------------------------------------------------------------------===// // Context-specific lexing flags set by the preprocessor. //===--------------------------------------------------------------------===// /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token. - bool ParsingPreprocessorDirective; + bool ParsingPreprocessorDirective = false; /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal /// token. - bool ParsingFilename; + bool ParsingFilename = false; /// \brief True if in raw mode. /// @@ -60,7 +66,7 @@ protected: /// 5. No callbacks are made into the preprocessor. /// /// Note that in raw mode that the PP pointer may be null. - bool LexingRawMode; + bool LexingRawMode = false; /// \brief A state machine that detects the \#ifndef-wrapping a file /// idiom for the multiple-include optimization. @@ -70,19 +76,9 @@ protected: /// we are currently in. SmallVector<PPConditionalInfo, 4> ConditionalStack; - PreprocessorLexer(const PreprocessorLexer &) = delete; - void operator=(const PreprocessorLexer &) = delete; - friend class Preprocessor; - + PreprocessorLexer() : FID() {} PreprocessorLexer(Preprocessor *pp, FileID fid); - - PreprocessorLexer() - : PP(nullptr), InitialNumSLocEntries(0), - ParsingPreprocessorDirective(false), - ParsingFilename(false), - LexingRawMode(false) {} - - virtual ~PreprocessorLexer() {} + virtual ~PreprocessorLexer() = default; virtual void IndirectLex(Token& Result) = 0; @@ -128,6 +124,8 @@ protected: unsigned getConditionalStackDepth() const { return ConditionalStack.size(); } public: + PreprocessorLexer(const PreprocessorLexer &) = delete; + PreprocessorLexer &operator=(const PreprocessorLexer &) = delete; //===--------------------------------------------------------------------===// // Misc. lexing methods. @@ -168,12 +166,13 @@ public: /// \brief Iterator that traverses the current stack of preprocessor /// conditional directives (\#if/\#ifdef/\#ifndef). - typedef SmallVectorImpl<PPConditionalInfo>::const_iterator - conditional_iterator; + using conditional_iterator = + SmallVectorImpl<PPConditionalInfo>::const_iterator; conditional_iterator conditional_begin() const { return ConditionalStack.begin(); } + conditional_iterator conditional_end() const { return ConditionalStack.end(); } @@ -184,6 +183,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index d91c665cf1dd..55fc305dc295 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -1,4 +1,4 @@ -//===--- PreprocessorOptions.h ----------------------------------*- C++ -*-===// +//===- PreprocessorOptions.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,30 +10,30 @@ #ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ #define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" -#include <cassert> +#include <memory> #include <set> #include <string> #include <utility> #include <vector> namespace llvm { - class MemoryBuffer; -} -namespace clang { +class MemoryBuffer; + +} // namespace llvm -class Preprocessor; -class LangOptions; +namespace clang { /// \brief Enumerate the kinds of standard library that enum ObjCXXARCStandardLibraryKind { ARCXX_nolib, + /// \brief libc++ ARCXX_libcxx, + /// \brief libstdc++ ARCXX_libstdcxx }; @@ -42,17 +42,17 @@ enum ObjCXXARCStandardLibraryKind { /// used in preprocessor initialization to InitializePreprocessor(). class PreprocessorOptions { public: - std::vector<std::pair<std::string, bool/*isUndef*/> > Macros; + std::vector<std::pair<std::string, bool/*isUndef*/>> Macros; std::vector<std::string> Includes; std::vector<std::string> MacroIncludes; /// \brief Initialize the preprocessor with the compiler and target specific /// predefines. - unsigned UsePredefines : 1; + bool UsePredefines = true; /// \brief Whether we should maintain a detailed record of all macro /// definitions and expansions. - unsigned DetailedRecord : 1; + bool DetailedRecord = false; /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; @@ -62,13 +62,13 @@ public: /// \brief When true, disables most of the normal validation performed on /// precompiled headers. - bool DisablePCHValidation; + bool DisablePCHValidation = false; /// \brief When true, a PCH with compiler errors will not be rejected. - bool AllowPCHWithCompilerErrors; + bool AllowPCHWithCompilerErrors = false; /// \brief Dump declarations that are deserialized from PCH, for testing. - bool DumpDeserializedPCHDecls; + bool DumpDeserializedPCHDecls = false; /// \brief 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. @@ -86,7 +86,7 @@ public: /// 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; + bool GeneratePreamble = false; /// The implicit PTH input included at the start of the translation unit, or /// empty. @@ -107,7 +107,7 @@ public: /// \brief 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; + bool RemappedFilesKeepOriginalName = true; /// \brief The set of file remappings, which take existing files on /// the system (the first part of each pair) and gives them the @@ -126,12 +126,12 @@ public: /// This flag defaults to false; it can be set true only through direct /// manipulation of the compiler invocation object, in cases where the /// compiler invocation and its buffers will be reused. - bool RetainRemappedFileBuffers; + bool RetainRemappedFileBuffers = false; /// \brief 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; + ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary = ARCXX_nolib; /// \brief Records the set of modules class FailedModulesSet { @@ -156,18 +156,11 @@ public: std::shared_ptr<FailedModulesSet> FailedModules; public: - PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DisablePCHValidation(false), - AllowPCHWithCompilerErrors(false), - DumpDeserializedPCHDecls(false), - PrecompiledPreambleBytes(0, true), - GeneratePreamble(false), - RemappedFilesKeepOriginalName(true), - RetainRemappedFileBuffers(false), - ObjCXXARCStandardLibrary(ARCXX_nolib) { } + PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); } void addMacroUndef(StringRef Name) { Macros.emplace_back(Name, true); } + void addRemappedFile(StringRef From, StringRef To) { RemappedFiles.emplace_back(From, To); } @@ -195,10 +188,10 @@ public: LexEditorPlaceholders = true; RetainRemappedFileBuffers = true; PrecompiledPreambleBytes.first = 0; - PrecompiledPreambleBytes.second = 0; + PrecompiledPreambleBytes.second = false; } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_ diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index fdeed44d8f9b..b8b0beabf2ba 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -1,4 +1,4 @@ -//===--- TokenLexer.h - Lex from a token buffer -----------------*- C++ -*-===// +//===- TokenLexer.h - Lex from a token buffer -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,29 +15,31 @@ #define LLVM_CLANG_LEX_TOKENLEXER_H #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" namespace clang { - class MacroInfo; - class Preprocessor; - class Token; - class MacroArgs; + +class MacroArgs; +class MacroInfo; +class Preprocessor; +class Token; +class VAOptExpansionContext; /// TokenLexer - This implements a lexer that returns tokens from a macro body /// or token stream instead of lexing from a character buffer. This is used for /// macro expansion and _Pragma handling, for example. -/// class TokenLexer { + friend class Preprocessor; + /// Macro - The macro we are expanding from. This is null if expanding a /// token stream. - /// - MacroInfo *Macro; + MacroInfo *Macro = nullptr; /// ActualArgs - The actual arguments specified for a function-like macro, or /// null. The TokenLexer owns the pointed-to object. - MacroArgs *ActualArgs; + MacroArgs *ActualArgs = nullptr; /// PP - The current preprocessor object we are expanding for. - /// Preprocessor &PP; /// Tokens - This is the pointer to an array of tokens that the macro is @@ -49,15 +51,12 @@ class TokenLexer { /// Note that if it points into Preprocessor's cache buffer, the Preprocessor /// may update the pointer as needed. const Token *Tokens; - friend class Preprocessor; /// NumTokens - This is the length of the Tokens array. - /// unsigned NumTokens; - /// CurToken - This is the next token that Lex will return. - /// - unsigned CurToken; + /// This is the index of the next token that Lex will return. + unsigned CurTokenIdx; /// ExpandLocStart/End - The source location range where this macro was /// expanded. @@ -73,6 +72,7 @@ class TokenLexer { /// \brief Location of the macro definition. SourceLocation MacroDefStart; + /// \brief Length of the macro definition. unsigned MacroDefLength; @@ -99,8 +99,6 @@ class TokenLexer { /// should not be subject to further macro expansion. bool DisableMacroExpansion : 1; - TokenLexer(const TokenLexer &) = delete; - void operator=(const TokenLexer &) = delete; public: /// Create a TokenLexer for the specified macro with the specified actual /// arguments. Note that this ctor takes ownership of the ActualArgs pointer. @@ -108,26 +106,30 @@ public: /// identifier for an object-like macro. TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, MacroArgs *ActualArgs, Preprocessor &pp) - : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) { + : PP(pp), OwnsTokens(false) { Init(Tok, ILEnd, MI, ActualArgs); } - /// Init - Initialize this TokenLexer to expand from the specified macro - /// with the specified argument information. Note that this ctor takes - /// ownership of the ActualArgs pointer. ILEnd specifies the location of the - /// ')' for a function-like macro or the identifier for an object-like macro. - void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, - MacroArgs *ActualArgs); - /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is /// specified, this takes ownership of the tokens and delete[]'s them when /// the token lexer is empty. TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion, bool ownsTokens, Preprocessor &pp) - : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) { + : PP(pp), OwnsTokens(false) { Init(TokArray, NumToks, DisableExpansion, ownsTokens); } + TokenLexer(const TokenLexer &) = delete; + TokenLexer &operator=(const TokenLexer &) = delete; + ~TokenLexer() { destroy(); } + + /// Init - Initialize this TokenLexer to expand from the specified macro + /// with the specified argument information. Note that this ctor takes + /// ownership of the ActualArgs pointer. ILEnd specifies the location of the + /// ')' for a function-like macro or the identifier for an object-like macro. + void Init(Token &Tok, SourceLocation ILEnd, MacroInfo *MI, + MacroArgs *ActualArgs); + /// Init - Initialize this TokenLexer with the specified token stream. /// This does not take ownership of the specified token vector. /// @@ -136,8 +138,6 @@ public: void Init(const Token *TokArray, unsigned NumToks, bool DisableMacroExpansion, bool OwnsTokens); - ~TokenLexer() { destroy(); } - /// isNextTokenLParen - If the next token lexed will pop this macro off the /// expansion stack, return 2. If the next unexpanded token is a '(', return /// 1, otherwise return 0. @@ -156,15 +156,54 @@ private: /// isAtEnd - Return true if the next lex call will pop this macro off the /// include stack. bool isAtEnd() const { - return CurToken == NumTokens; + return CurTokenIdx == NumTokens; } - /// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ## - /// operator. Read the ## and RHS, and paste the LHS/RHS together. If there - /// are is another ## after it, chomp it iteratively. Return the result as - /// Tok. If this returns true, the caller should immediately return the + /// Concatenates the next (sub-)sequence of \p Tokens separated by '##' + /// starting with LHSTok - stopping when we encounter a token that is neither + /// '##' nor preceded by '##'. Places the result back into \p LHSTok and sets + /// \p CurIdx to point to the token following the last one that was pasted. + /// + /// Also performs the MSVC extension wide-literal token pasting involved with: + /// \code L #macro-arg. \endcode + /// + /// \param[in,out] LHSTok - Contains the token to the left of '##' in \p + /// Tokens upon entry and will contain the resulting concatenated Token upon + /// exit. + /// + /// \param[in] TokenStream - The stream of Tokens we are lexing from. + /// + /// \param[in,out] CurIdx - Upon entry, \pTokens[\pCurIdx] must equal '##' + /// (with the exception of the MSVC extension mentioned above). Upon exit, it + /// is set to the index of the token following the last token that was + /// concatenated together. + /// + /// \returns If this returns true, the caller should immediately return the /// token. - bool PasteTokens(Token &Tok); + bool pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream, + unsigned int &CurIdx); + + /// Calls pasteTokens above, passing in the '*this' object's Tokens and + /// CurTokenIdx data members. + bool pasteTokens(Token &Tok); + + + /// Takes the tail sequence of tokens within ReplacementToks that represent + /// the just expanded __VA_OPT__ tokens (possibly zero tokens) and transforms + /// them into a string. \p VCtx is used to determine which token represents + /// the first __VA_OPT__ replacement token. + /// + /// \param[in,out] ReplacementToks - Contains the current Replacement Tokens + /// (prior to rescanning and token pasting), the tail end of which represents + /// 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 + /// state of the tokens around and including the __VA_OPT__ token, necessary + /// for stringification. + void stringifyVAOPTContents(SmallVectorImpl<Token> &ReplacementToks, + const VAOptExpansionContext &VCtx, + SourceLocation VAOPTClosingParenLoc); /// Expand the arguments of a function-like macro so that we can quickly /// return preexpanded tokens from Tokens. @@ -200,6 +239,6 @@ private: void PropagateLineStartLeadingSpaceInfo(Token &Result); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_LEX_TOKENLEXER_H diff --git a/include/clang/Lex/VariadicMacroSupport.h b/include/clang/Lex/VariadicMacroSupport.h new file mode 100644 index 000000000000..cebaf15187de --- /dev/null +++ b/include/clang/Lex/VariadicMacroSupport.h @@ -0,0 +1,226 @@ +//===- VariadicMacroSupport.h - state machines and scope guards -*- 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 support types to help with preprocessing variadic macro +// (i.e. macros that use: ellipses __VA_ARGS__ ) definitions and +// expansions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H +#define LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H + +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class Preprocessor; + + /// An RAII class that tracks when the Preprocessor starts and stops lexing + /// the definition of a (ISO C/C++) variadic macro. As an example, this is + /// useful for unpoisoning and repoisoning certain identifiers (such as + /// __VA_ARGS__) that are only allowed in this context. Also, being a friend + /// of the Preprocessor class allows it to access PP's cached identifiers + /// directly (as opposed to performing a lookup each time). + class VariadicMacroScopeGuard { + const Preprocessor &PP; + IdentifierInfo *const Ident__VA_ARGS__; + IdentifierInfo *const Ident__VA_OPT__; + + public: + VariadicMacroScopeGuard(const Preprocessor &P) + : PP(P), Ident__VA_ARGS__(PP.Ident__VA_ARGS__), + Ident__VA_OPT__(PP.Ident__VA_OPT__) { + assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned " + "outside an ISO C/C++ variadic " + "macro definition!"); + assert( + !Ident__VA_OPT__ || + (Ident__VA_OPT__->isPoisoned() && "__VA_OPT__ should be poisoned!")); + } + + /// Client code should call this function just before the Preprocessor is + /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro. + void enterScope() { + Ident__VA_ARGS__->setIsPoisoned(false); + if (Ident__VA_OPT__) + Ident__VA_OPT__->setIsPoisoned(false); + } + + /// 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 + /// (might be explicitly called, and then reinvoked via the destructor). + void exitScope() { + Ident__VA_ARGS__->setIsPoisoned(true); + if (Ident__VA_OPT__) + Ident__VA_OPT__->setIsPoisoned(true); + } + + ~VariadicMacroScopeGuard() { exitScope(); } + }; + + /// \brief 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. + SmallVector<SourceLocation, 8> UnmatchedOpeningParens; + + const IdentifierInfo *const Ident__VA_OPT__; + + + public: + VAOptDefinitionContext(Preprocessor &PP) + : Ident__VA_OPT__(PP.Ident__VA_OPT__) {} + + bool isVAOptToken(const Token &T) const { + return Ident__VA_OPT__ && T.getIdentifierInfo() == Ident__VA_OPT__; + } + + /// Returns true if we have seen the __VA_OPT__ and '(' but before having + /// seen the matching ')'. + bool isInVAOpt() const { return UnmatchedOpeningParens.size(); } + + /// Call this function as soon as you see __VA_OPT__ and '('. + void sawVAOptFollowedByOpeningParens(const SourceLocation LParenLoc) { + assert(!isInVAOpt() && "Must NOT be within VAOPT context to call this"); + UnmatchedOpeningParens.push_back(LParenLoc); + + } + + SourceLocation getUnmatchedOpeningParenLoc() const { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + return UnmatchedOpeningParens.back(); + } + + /// Call this function each time an rparen is seen. It returns true only if + /// the rparen that was just seen was the eventual (non-nested) closing + /// paren for VAOPT, and ejects us out of the VAOPT context. + bool sawClosingParen() { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + UnmatchedOpeningParens.pop_back(); + return !UnmatchedOpeningParens.size(); + } + + /// Call this function each time an lparen is seen. + void sawOpeningParen(SourceLocation LParenLoc) { + assert(isInVAOpt() && "Must be within VAOPT context to call this"); + UnmatchedOpeningParens.push_back(LParenLoc); + } + + }; + + /// \brief 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 { + + Token SyntheticEOFToken; + + // The (spelling) location of the current __VA_OPT__ in the replacement list + // of the function-like macro being expanded. + SourceLocation VAOptLoc; + + // NumOfTokensPriorToVAOpt : when != -1, contains the index *of* the first + // token of the current VAOPT contents (so we know where to start eager + // token-pasting and stringification) *within* the substituted tokens of + // the function-like macro's new replacement list. + int NumOfTokensPriorToVAOpt = -1; + + unsigned LeadingSpaceForStringifiedToken : 1; + + unsigned StringifyBefore : 1; + unsigned CharifyBefore : 1; + + + bool hasStringifyBefore() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return StringifyBefore; + } + + bool isReset() const { + return NumOfTokensPriorToVAOpt == -1 || + VAOptLoc.isInvalid(); + } + + public: + VAOptExpansionContext(Preprocessor &PP) + : VAOptDefinitionContext(PP), LeadingSpaceForStringifiedToken(false), + StringifyBefore(false), CharifyBefore(false) { + SyntheticEOFToken.startToken(); + SyntheticEOFToken.setKind(tok::eof); + } + + void reset() { + VAOptLoc = SourceLocation(); + NumOfTokensPriorToVAOpt = -1; + LeadingSpaceForStringifiedToken = false; + StringifyBefore = false; + CharifyBefore = false; + } + + const Token &getEOFTok() const { return SyntheticEOFToken; } + + void sawHashOrHashAtBefore(const bool HasLeadingSpace, + const bool IsHashAt) { + + StringifyBefore = !IsHashAt; + CharifyBefore = IsHashAt; + LeadingSpaceForStringifiedToken = HasLeadingSpace; + } + + + + bool hasCharifyBefore() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return CharifyBefore; + } + bool hasStringifyOrCharifyBefore() const { + return hasStringifyBefore() || hasCharifyBefore(); + } + + unsigned int getNumberOfTokensPriorToVAOpt() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + return NumOfTokensPriorToVAOpt; + } + + bool getLeadingSpaceForStringifiedToken() const { + assert(hasStringifyBefore() && + "Must only be called if this has been marked for stringification"); + return LeadingSpaceForStringifiedToken; + } + + void sawVAOptFollowedByOpeningParens(const SourceLocation VAOptLoc, + const unsigned int NumPriorTokens) { + assert(VAOptLoc.isFileID() && "Must not come from a macro expansion"); + assert(isReset() && "Must only be called if the state has been reset"); + VAOptDefinitionContext::sawVAOptFollowedByOpeningParens(SourceLocation()); + this->VAOptLoc = VAOptLoc; + NumOfTokensPriorToVAOpt = NumPriorTokens; + assert(NumOfTokensPriorToVAOpt > -1 && + "Too many prior tokens"); + } + + SourceLocation getVAOptLoc() const { + assert(!isReset() && + "Must only be called if the state has not been reset"); + assert(VAOptLoc.isValid() && "__VA_OPT__ location must be valid"); + return VAOptLoc; + } + using VAOptDefinitionContext::isVAOptToken; + using VAOptDefinitionContext::isInVAOpt; + using VAOptDefinitionContext::sawClosingParen; + using VAOptDefinitionContext::sawOpeningParen; + + }; +} // end namespace clang + +#endif diff --git a/include/clang/Parse/ParseAST.h b/include/clang/Parse/ParseAST.h index 21f9701c3ed8..34c96816ebdf 100644 --- a/include/clang/Parse/ParseAST.h +++ b/include/clang/Parse/ParseAST.h @@ -29,10 +29,13 @@ namespace clang { /// This operation inserts the parsed decls into the translation /// unit held by Ctx. /// + /// \param PrintStats Whether to print LLVM statistics related to parsing. /// \param TUKind The kind of translation unit being parsed. - /// /// \param CompletionConsumer If given, an object to consume code completion /// results. + /// \param SkipFunctionBodies Whether to skip parsing of function bodies. + /// This option can be used, for example, to speed up searches for + /// declarations/definitions when indexing. void ParseAST(Preprocessor &pp, ASTConsumer *C, ASTContext &Ctx, bool PrintStats = false, TranslationUnitKind TUKind = TU_Complete, @@ -43,7 +46,7 @@ namespace clang { /// abstract syntax tree. void ParseAST(Sema &S, bool PrintStats = false, bool SkipFunctionBodies = false); - + } // end namespace clang #endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 21d699ec402e..396b5a9aa394 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -253,6 +253,10 @@ class Parser : public CodeCompletionHandler { /// be NULL. bool ParsingInObjCContainer; + /// Whether to skip parsing of function bodies. + /// + /// This option can be used, for example, to speed up searches for + /// declarations/definitions when indexing. bool SkipFunctionBodies; /// The location of the expression statement that is being parsed right now. @@ -334,6 +338,27 @@ public: return true; } + /// ConsumeAnyToken - Dispatch to the right Consume* method based on the + /// current token type. This should only be used in cases where the type of + /// the token really isn't known, e.g. in error recovery. + SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) { + if (isTokenParen()) + return ConsumeParen(); + if (isTokenBracket()) + return ConsumeBracket(); + if (isTokenBrace()) + return ConsumeBrace(); + if (isTokenStringLiteral()) + return ConsumeStringToken(); + if (Tok.is(tok::code_completion)) + return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken() + : handleUnexpectedCodeCompletionToken(); + if (Tok.isAnnotation()) + return ConsumeAnnotationToken(); + return ConsumeToken(); + } + + SourceLocation getEndOfPreviousToken() { return PP.getLocForEndOfToken(PrevTokLocation); } @@ -384,26 +409,6 @@ private: PP.EnterToken(Next); } - /// ConsumeAnyToken - Dispatch to the right Consume* method based on the - /// current token type. This should only be used in cases where the type of - /// the token really isn't known, e.g. in error recovery. - SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) { - if (isTokenParen()) - return ConsumeParen(); - if (isTokenBracket()) - return ConsumeBracket(); - if (isTokenBrace()) - return ConsumeBrace(); - if (isTokenStringLiteral()) - return ConsumeStringToken(); - if (Tok.is(tok::code_completion)) - return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken() - : handleUnexpectedCodeCompletionToken(); - if (Tok.isAnnotation()) - return ConsumeAnnotationToken(); - return ConsumeToken(); - } - SourceLocation ConsumeAnnotationToken() { assert(Tok.isAnnotation() && "wrong consume method"); SourceLocation Loc = Tok.getLocation(); @@ -501,6 +506,12 @@ 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. + bool isFoldOperator(prec::Level Level) const; + + /// \brief Checks if the \p Kind is a valid operator for fold expressions. + bool isFoldOperator(tok::TokenKind Kind) const; + /// \brief Initialize all pragma handlers. void initializePragmaHandlers(); @@ -1470,7 +1481,6 @@ public: ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, unsigned &NumLineToksConsumed, - void *Info, bool IsUnevaluated); private: @@ -1517,9 +1527,10 @@ private: typedef SmallVector<SourceLocation, 20> CommaLocsTy; /// ParseExpressionList - Used for C/C++ (argument-)expression-list. - bool ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, - SmallVectorImpl<SourceLocation> &CommaLocs, - std::function<void()> Completer = nullptr); + bool ParseExpressionList( + SmallVectorImpl<Expr *> &Exprs, + SmallVectorImpl<SourceLocation> &CommaLocs, + llvm::function_ref<void()> Completer = llvm::function_ref<void()>()); /// ParseSimpleExpressionList - A simple comma-separated list of expressions, /// used for misc language extensions. @@ -2159,18 +2170,25 @@ public: private: void ParseBlockId(SourceLocation CaretLoc); - // Check for the start of a C++11 attribute-specifier-seq in a context where - // an attribute is not allowed. + /// Are [[]] attributes enabled? + bool standardAttributesAllowed() const { + const LangOptions &LO = getLangOpts(); + return LO.DoubleSquareBracketAttributes; + } + + // Check for the start of an attribute-specifier-seq in a context where an + // attribute is not allowed. bool CheckProhibitedCXX11Attribute() { assert(Tok.is(tok::l_square)); - if (!getLangOpts().CPlusPlus11 || NextToken().isNot(tok::l_square)) + if (!standardAttributesAllowed() || NextToken().isNot(tok::l_square)) return false; return DiagnoseProhibitedCXX11Attribute(); } + bool DiagnoseProhibitedCXX11Attribute(); void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, SourceLocation CorrectLocation) { - if (!getLangOpts().CPlusPlus11) + if (!standardAttributesAllowed()) return; if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) && Tok.isNot(tok::kw_alignas)) @@ -2190,17 +2208,18 @@ private: } void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs); - // Forbid C++11 attributes that appear on certain syntactic - // locations which standard permits but we don't supported yet, - // for example, attributes appertain to decl specifiers. + // Forbid C++11 and C2x attributes that appear on certain syntactic locations + // which standard permits but we don't supported yet, for example, attributes + // appertain to decl specifiers. void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID); - /// \brief Skip C++11 attributes and return the end location of the last one. + /// \brief 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 attributes that appear in syntactic + /// \brief Diagnose and skip C++11 and C2x attributes that appear in syntactic /// locations where attributes are not allowed. void DiagnoseAndSkipCXX11Attributes(); @@ -2250,7 +2269,7 @@ private: AttributeList::Syntax Syntax); void MaybeParseCXX11Attributes(Declarator &D) { - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); SourceLocation endLoc; ParseCXX11Attributes(attrs, &endLoc); @@ -2259,7 +2278,7 @@ private: } void MaybeParseCXX11Attributes(ParsedAttributes &attrs, SourceLocation *endLoc = nullptr) { - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrsWithRange(AttrFactory); ParseCXX11Attributes(attrsWithRange, endLoc); attrs.takeAllFrom(attrsWithRange); @@ -2268,8 +2287,8 @@ private: void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *endLoc = nullptr, bool OuterMightBeMessageSend = false) { - if (getLangOpts().CPlusPlus11 && - isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) + if (standardAttributesAllowed() && + isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) ParseCXX11Attributes(attrs, endLoc); } @@ -2277,8 +2296,8 @@ private: SourceLocation *EndLoc = nullptr); void ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *EndLoc = nullptr); - /// \brief Parses a C++-style attribute argument list. Returns true if this - /// results in adding an attribute to the ParsedAttributes list. + /// \brief 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, ParsedAttributes &Attrs, SourceLocation *EndLoc, @@ -2608,6 +2627,9 @@ private: Decl *TagDecl = nullptr); /// \brief 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. /// @@ -2720,11 +2742,11 @@ private: AccessSpecifier AS=AS_none, AttributeList *AccessAttrs = nullptr); bool ParseTemplateParameters(unsigned Depth, - SmallVectorImpl<Decl*> &TemplateParams, + SmallVectorImpl<NamedDecl *> &TemplateParams, SourceLocation &LAngleLoc, SourceLocation &RAngleLoc); bool ParseTemplateParameterList(unsigned Depth, - SmallVectorImpl<Decl*> &TemplateParams); + SmallVectorImpl<NamedDecl*> &TemplateParams); bool isStartOfTemplateTypeParameter(); Decl *ParseTemplateParameter(unsigned Depth, unsigned Position); Decl *ParseTypeParameter(unsigned Depth, unsigned Position); @@ -2766,7 +2788,7 @@ private: //===--------------------------------------------------------------------===// // Modules DeclGroupPtrTy ParseModuleDecl(); - DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc); + Decl *ParseModuleImport(SourceLocation AtLoc); bool parseMisplacedModuleImport(); bool tryParseMisplacedModuleImport() { tok::TokenKind Kind = Tok.getKind(); diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 6bdd9d5fcdb6..4e806116c4d9 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -100,16 +100,20 @@ public: AS_GNU, /// [[...]] AS_CXX11, + /// [[...]] + AS_C2x, /// __declspec(...) AS_Declspec, /// [uuid("...")] class Foo AS_Microsoft, /// __ptr16, alignas(...), etc. AS_Keyword, - /// Context-sensitive version of a keyword attribute. - AS_ContextSensitiveKeyword, /// #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. + AS_ContextSensitiveKeyword, }; private: @@ -376,6 +380,9 @@ public: 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; } @@ -893,50 +900,17 @@ enum AttributeDeclKind { ExpectedFunction, ExpectedUnion, ExpectedVariableOrFunction, - ExpectedFunctionOrGlobalVar, - ExpectedFunctionVariableOrObjCInterface, ExpectedFunctionOrMethod, - ExpectedParameter, ExpectedFunctionMethodOrBlock, - ExpectedFunctionMethodOrClass, ExpectedFunctionMethodOrParameter, - ExpectedFunctionMethodOrGlobalVar, - ExpectedClass, - ExpectedEnum, ExpectedVariable, - ExpectedMethod, - ExpectedFieldOrGlobalVar, - ExpectedStruct, - ExpectedParameterOrTypedef, - ExpectedVariableOrTypedef, - ExpectedTLSVar, ExpectedVariableOrField, ExpectedVariableFieldOrTag, ExpectedTypeOrNamespace, - ExpectedObjectiveCInterface, - ExpectedMethodOrProperty, - ExpectedFunctionOrMethodOrProperty, - ExpectedStructOrUnion, - ExpectedStructOrUnionOrClass, - ExpectedType, - ExpectedObjCInstanceMethod, - ExpectedObjCInterfaceDeclInitMethod, ExpectedFunctionVariableOrClass, - ExpectedFunctionVariableClassOrObjCInterface, - ExpectedObjectiveCProtocol, - ExpectedStaticOrTLSVar, - ExpectedFunctionGlobalVarMethodOrProperty, - ExpectedStructOrUnionOrTypedef, - ExpectedStructOrTypedef, - ExpectedObjectiveCInterfaceOrProtocol, ExpectedKernelFunction, ExpectedFunctionWithProtoType, - ExpectedVariableEnumFieldOrTypedef, - ExpectedFunctionMethodEnumOrClass, - ExpectedStructClassVariableFunctionOrInlineNamespace, ExpectedForMaybeUnused, - ExpectedEnumOrClass, - ExpectedNamedDecl, }; } // end namespace clang diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index dee53dc14a8c..5d280b5608e7 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/Type.h" #include "clang/Sema/CodeCompleteOptions.h" +#include "clang/Sema/DeclSpec.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -280,6 +281,10 @@ private: /// \brief The identifiers for Objective-C selector parts. ArrayRef<IdentifierInfo *> SelIdents; + /// \brief The scope specifier that comes before the completion token e.g. + /// "a::b::" + llvm::Optional<CXXScopeSpec> ScopeSpecifier; + public: /// \brief Construct a new code-completion context of the given kind. CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { } @@ -315,8 +320,20 @@ public: /// \brief 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. + /// 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); + } + + llvm::Optional<const CXXScopeSpec *> getCXXScopeSpecifier() { + if (ScopeSpecifier) + return ScopeSpecifier.getPointer(); + return llvm::None; + } +}; /// \brief A "string" used to describe how code completion can /// be performed for an entity. @@ -777,6 +794,12 @@ public: CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments); + /// \brief 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. + StringRef getOrderedName(std::string &Saved) const; + private: void computeCursorKindAndAvailability(bool Accessible = true); }; @@ -896,8 +919,13 @@ public: } /// \brief Whether to include global (top-level) declaration results. - bool includeGlobals() const { - return CodeCompleteOpts.IncludeGlobals; + bool includeGlobals() const { return CodeCompleteOpts.IncludeGlobals; } + + /// \brief 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 diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h index fc7713c79571..091d8ca60505 100644 --- a/include/clang/Sema/CodeCompleteOptions.h +++ b/include/clang/Sema/CodeCompleteOptions.h @@ -24,15 +24,20 @@ public: /// Show top-level decls in code completion results. unsigned IncludeGlobals : 1; + /// Show decls in namespace (including the global namespace) in code + /// completion results. If this is 0, `IncludeGlobals` will be ignored. + /// + /// Currently, this only works when completing qualified IDs (i.e. + /// `Sema::CodeCompleteQualifiedId`). + /// FIXME: consider supporting more completion cases with this option. + unsigned IncludeNamespaceLevelDecls : 1; + /// Show brief documentation comments in code completion results. unsigned IncludeBriefComments : 1; - CodeCompleteOptions() : - IncludeMacros(0), - IncludeCodePatterns(0), - IncludeGlobals(1), - IncludeBriefComments(0) - { } + CodeCompleteOptions() + : IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1), + IncludeNamespaceLevelDecls(1), IncludeBriefComments(0) {} }; } // namespace clang diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index bc817150ab82..760a04d3c8d2 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -280,6 +280,7 @@ public: static const TST TST_half = clang::TST_half; 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_float128 = clang::TST_float128; static const TST TST_bool = clang::TST_bool; static const TST TST_decimal32 = clang::TST_decimal32; @@ -360,9 +361,6 @@ private: // constexpr-specifier unsigned Constexpr_specified : 1; - // concept-specifier - unsigned Concept_specified : 1; - union { UnionParsedType TypeRep; Decl *DeclRep; @@ -392,7 +390,7 @@ private: TQ_unalignedLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; SourceLocation FS_forceinlineLoc; - SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc; + SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc; SourceLocation TQ_pipeLoc; WrittenBuiltinSpecs writtenBS; @@ -438,7 +436,6 @@ public: FS_noreturn_specified(false), Friend_specified(false), Constexpr_specified(false), - Concept_specified(false), Attrs(attrFactory), writtenBS(), ObjCQualifiers(nullptr) { @@ -696,8 +693,6 @@ public: unsigned &DiagID); bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); - bool SetConceptSpec(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID); bool isFriendSpecified() const { return Friend_specified; } SourceLocation getFriendSpecLoc() const { return FriendLoc; } @@ -708,19 +703,11 @@ public: bool isConstexprSpecified() const { return Constexpr_specified; } SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } - bool isConceptSpecified() const { return Concept_specified; } - SourceLocation getConceptSpecLoc() const { return ConceptLoc; } - void ClearConstexprSpec() { Constexpr_specified = false; ConstexprLoc = SourceLocation(); } - void ClearConceptSpec() { - Concept_specified = false; - ConceptLoc = SourceLocation(); - } - AttributePool &getAttributePool() const { return Attrs.getPool(); } @@ -2008,9 +1995,9 @@ public: case BlockContext: case ForContext: case InitStmtContext: + case ConditionContext: return true; - case ConditionContext: case MemberContext: case PrototypeContext: case TemplateParamContext: @@ -2300,6 +2287,42 @@ public: } llvm_unreachable("unknown context kind!"); } + + /// Determine whether this declaration appears in a context where an + /// 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: + return false; + + case BlockContext: + case ForContext: + case InitStmtContext: + case ConditionContext: + case TemplateTypeArgContext: + return true; + } + + llvm_unreachable("unknown context kind!"); + } /// \brief Return true if a function declarator at this position would be a /// function declaration. diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index ea32997d4066..546df8842a35 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -139,6 +139,7 @@ public: LookupKind(LookupKind), IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), + ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration), AllowHidden(false), @@ -161,6 +162,7 @@ public: LookupKind(LookupKind), IDNS(0), Redecl(Redecl != Sema::NotForRedeclaration), + ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), HideTags(true), Diagnose(Redecl == Sema::NotForRedeclaration), AllowHidden(false), @@ -181,6 +183,7 @@ public: LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl), + ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags), Diagnose(false), AllowHidden(Other.AllowHidden), @@ -201,7 +204,9 @@ public: SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)), NameContextRange(std::move(Other.NameContextRange)), LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)), - Redecl(std::move(Other.Redecl)), HideTags(std::move(Other.HideTags)), + Redecl(std::move(Other.Redecl)), + ExternalRedecl(std::move(Other.ExternalRedecl)), + HideTags(std::move(Other.HideTags)), Diagnose(std::move(Other.Diagnose)), AllowHidden(std::move(Other.AllowHidden)), Shadowed(std::move(Other.Shadowed)) { @@ -221,6 +226,7 @@ public: LookupKind = std::move(Other.LookupKind); IDNS = std::move(Other.IDNS); Redecl = std::move(Other.Redecl); + ExternalRedecl = std::move(Other.ExternalRedecl); HideTags = std::move(Other.HideTags); Diagnose = std::move(Other.Diagnose); AllowHidden = std::move(Other.AllowHidden); @@ -265,6 +271,17 @@ public: return Redecl; } + /// True if this lookup is just looking for an existing declaration to link + /// against a declaration with external linkage. + bool isForExternalRedeclaration() const { + return ExternalRedecl; + } + + Sema::RedeclarationKind redeclarationKind() const { + return ExternalRedecl ? Sema::ForExternalRedeclaration : + Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration; + } + /// \brief Specify whether hidden declarations are visible, e.g., /// for recovery reasons. void setAllowHidden(bool AH) { @@ -275,7 +292,7 @@ public: /// declarations, such as those in modules that have not yet been imported. bool isHiddenDeclarationVisible(NamedDecl *ND) const { return AllowHidden || - (isForRedeclaration() && ND->hasExternalFormalLinkage()); + (isForExternalRedeclaration() && ND->isExternallyDeclarable()); } /// Sets whether tag declarations should be hidden by non-tag @@ -556,7 +573,8 @@ public: /// \brief Change this lookup's redeclaration kind. void setRedeclarationKind(Sema::RedeclarationKind RK) { - Redecl = RK; + Redecl = (RK != Sema::NotForRedeclaration); + ExternalRedecl = (RK == Sema::ForExternalRedeclaration); configure(); } @@ -719,6 +737,7 @@ private: unsigned IDNS; // set by configure() bool Redecl; + bool ExternalRedecl; /// \brief True if tag declarations should be hidden if non-tags /// are present diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index ffdf011d1dcb..05cfe53666ca 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -726,11 +726,20 @@ namespace clang { enum CandidateSetKind { /// Normal lookup. CSK_Normal, - /// Lookup for candidates for 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.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. + CSK_InitByConstructor, }; private: @@ -795,7 +804,7 @@ namespace clang { } /// \brief Clear out all of the candidates. - void clear(); + void clear(CandidateSetKind CSK); typedef SmallVectorImpl<OverloadCandidate>::iterator iterator; iterator begin() { return Candidates.begin(); } @@ -835,8 +844,7 @@ namespace clang { /// Find the best viable function on this overload set, if it exists. OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, - OverloadCandidateSet::iterator& Best, - bool UserDefinedConversion = false); + OverloadCandidateSet::iterator& Best); void NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, @@ -848,10 +856,10 @@ namespace clang { }; bool isBetterOverloadCandidate(Sema &S, - const OverloadCandidate& Cand1, - const OverloadCandidate& Cand2, + const OverloadCandidate &Cand1, + const OverloadCandidate &Cand2, SourceLocation Loc, - bool UserDefinedConversion = false); + OverloadCandidateSet::CandidateSetKind Kind); struct ConstructorInfo { DeclAccessPair FoundDecl; diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h index 848837a1decc..1e35316fd5dd 100644 --- a/include/clang/Sema/Ownership.h +++ b/include/clang/Sema/Ownership.h @@ -107,8 +107,7 @@ namespace clang { namespace llvm { template <class T> - class PointerLikeTypeTraits<clang::OpaquePtr<T> > { - public: + struct PointerLikeTypeTraits<clang::OpaquePtr<T> > { static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) { // FIXME: Doesn't work? return P.getAs< void >(); return P.getAsOpaquePtr(); diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index d0b006b82ec6..cd58a9910f98 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -124,6 +124,12 @@ public: /// We are currently in the filter expression of an SEH except block. SEHFilterScope = 0x200000, + + /// This is a compound statement scope. + CompoundStmtScope = 0x400000, + + /// 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 @@ -429,6 +435,11 @@ public: /// \brief 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. + bool isCompoundStmtScope() const { + return getFlags() & Scope::CompoundStmtScope; + } + /// \brief Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index 4251fa649a82..c707a3e8ef07 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -560,6 +560,7 @@ public: void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } VarDecl *getVariable() const { + assert(isVariableCapture()); return VarAndNestedAndThis.getPointer(); } @@ -833,6 +834,12 @@ public: return FSI->Kind == SK_Lambda; } + /// Is this scope known to be for a generic lambda? (This will be false until + /// we parse the first 'auto'-typed parameter. + bool isGenericLambda() const { + return !AutoTemplateParams.empty() || GLTemplateParameterList; + } + /// /// \brief Add a variable that might potentially be captured by the /// lambda and therefore the enclosing lambdas. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5a708545705c..47cea3029bd9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -64,7 +64,7 @@ namespace llvm { template <typename ValueT> struct DenseMapInfo; template <typename ValueT, typename ValueInfoT> class DenseSet; class SmallBitVector; - class InlineAsmIdentifierInfo; + struct InlineAsmIdentifierInfo; } namespace clang { @@ -208,6 +208,7 @@ namespace sema { class FunctionScopeInfo; class LambdaScopeInfo; class PossiblyUnreachableDiag; + class SemaPPCallbacks; class TemplateDeductionInfo; } @@ -228,6 +229,10 @@ struct FileNullability { /// not have a corresponding nullability annotation. SourceLocation PointerLoc; + /// The end location for the first pointer declarator in the file. Used for + /// placing fix-its. + SourceLocation PointerEndLoc; + /// Which kind of pointer declarator we saw. uint8_t PointerKind; @@ -280,15 +285,21 @@ class Sema { bool isVisibleSlow(const NamedDecl *D); + /// Determine whether two declarations should be linked together, given that + /// the old declaration might not be visible and the new declaration might + /// not have external linkage. bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old, const NamedDecl *New) { - // We are about to link these. It is now safe to compute the linkage of - // the new decl. If the new decl has external linkage, we will - // link it with the hidden decl (which also has external linkage) and - // it will keep having external linkage. If it has internal linkage, we - // will not link it. Since it has no previous decls, it will remain - // with internal linkage. - return isVisible(Old) || New->isExternallyVisible(); + if (isVisible(Old)) + return true; + // See comment in below overload for why it's safe to compute the linkage + // of the new declaration here. + if (New->isExternallyDeclarable()) { + assert(Old->isExternallyDeclarable() && + "should not have found a non-externally-declarable previous decl"); + return true; + } + return false; } bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New); @@ -381,11 +392,12 @@ public: llvm::StringRef StackSlotLabel; ValueType Value; SourceLocation PragmaLocation; - Slot(llvm::StringRef StackSlotLabel, - ValueType Value, - SourceLocation PragmaLocation) - : StackSlotLabel(StackSlotLabel), Value(Value), - PragmaLocation(PragmaLocation) {} + SourceLocation PragmaPushLocation; + Slot(llvm::StringRef StackSlotLabel, ValueType Value, + SourceLocation PragmaLocation, SourceLocation PragmaPushLocation) + : StackSlotLabel(StackSlotLabel), Value(Value), + PragmaLocation(PragmaLocation), + PragmaPushLocation(PragmaPushLocation) {} }; void Act(SourceLocation PragmaLocation, PragmaMsStackAction Action, @@ -416,6 +428,8 @@ public: explicit PragmaStack(const ValueType &Default) : DefaultValue(Default), CurrentValue(Default) {} + bool hasValue() const { return CurrentValue != DefaultValue; } + SmallVector<Slot, 2> Stack; ValueType DefaultValue; // Value used for PSK_Reset action. ValueType CurrentValue; @@ -437,6 +451,13 @@ public: // Sentinel to represent when the stack is set to mac68k alignment. static const unsigned kMac68kAlignmentSentinel = ~0U; PragmaStack<unsigned> PackStack; + // The current #pragma pack values and locations at each #include. + struct PackIncludeState { + unsigned CurrentValue; + SourceLocation CurrentPragmaLocation; + bool HasNonDefaultValue, ShouldWarnOnInclude; + }; + SmallVector<PackIncludeState, 8> PackIncludeStack; // Segment #pragmas. PragmaStack<StringLiteral *> DataSegStack; PragmaStack<StringLiteral *> BSSSegStack; @@ -1075,6 +1096,11 @@ public: /// definition in this translation unit. llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed; + /// Determine if VD, which must be a variable or function, is an external + /// symbol that nonetheless can't be referenced from outside this translation + /// unit because its type has no linkage and it's not extern "C". + bool isExternalWithNoLinkageType(ValueDecl *VD); + /// Obtain a sorted list of functions that are undefined but ODR-used. void getUndefinedButUsed( SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined); @@ -1110,12 +1136,13 @@ public: CXXInvalid }; - typedef std::pair<CXXRecordDecl*, CXXSpecialMember> SpecialMemberDecl; + typedef llvm::PointerIntPair<CXXRecordDecl *, 3, CXXSpecialMember> + SpecialMemberDecl; /// The C++ special members which we are currently in the process of /// declaring. If this process recursively triggers the declaration of the /// same special member, we should act as if it is not yet declared. - llvm::SmallSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared; + llvm::SmallPtrSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared; /// The function definitions which were renamed as part of typo-correction /// to match their respective declarations. We want to keep track of them @@ -1357,6 +1384,8 @@ public: SourceRange Brackets, DeclarationName Entity); QualType BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc); + QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, + SourceLocation AttrLoc); bool CheckFunctionReturnType(QualType T, SourceLocation Loc); @@ -1504,7 +1533,8 @@ private: TypeDiagnoser *Diagnoser); struct ModuleScope { - clang::Module *Module; + clang::Module *Module = nullptr; + bool ModuleInterface = false; VisibleModuleSet OuterVisibleModules; }; /// The modules we're currently parsing. @@ -1525,7 +1555,7 @@ public: /// visible at the specified location. void makeMergedDefinitionVisible(NamedDecl *ND); - bool isModuleVisible(Module *M) { return VisibleModules.isVisible(M); } + bool isModuleVisible(const Module *M) { return VisibleModules.isVisible(M); } /// Determine whether a declaration is visible to name lookup. bool isVisible(const NamedDecl *D) { @@ -1694,7 +1724,6 @@ public: ExprResult Expr; TemplateName Template; ParsedType Type; - const IdentifierInfo *Keyword; explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {} @@ -1703,8 +1732,7 @@ public: NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {} - NameClassification(const IdentifierInfo *Keyword) - : Kind(NC_Keyword), Keyword(Keyword) { } + NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {} static NameClassification Error() { return NameClassification(NC_Error); @@ -2022,9 +2050,9 @@ public: SourceLocation SemiLoc); enum class ModuleDeclKind { - Module, ///< 'module X;' + Interface, ///< 'export module X;' + Implementation, ///< 'module X;' Partition, ///< 'module partition X;' - Implementation, ///< 'module implementation X;' }; /// The parser has processed a module-declaration that begins the definition @@ -2677,7 +2705,8 @@ public: OverloadCandidateSet &CandidateSet, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, bool SuppressUserConversions = false, - bool PartialOverloading = false); + bool PartialOverloading = false, + bool FirstArgumentIsBase = false); void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, @@ -2725,13 +2754,15 @@ public: CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet& CandidateSet, - bool AllowObjCConversionOnExplicit); + bool AllowObjCConversionOnExplicit, + bool AllowResultConversion = true); void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, - bool AllowObjCConversionOnExplicit); + bool AllowObjCConversionOnExplicit, + bool AllowResultConversion = true); void AddSurrogateCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -2771,6 +2802,14 @@ public: EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, bool MissingImplicitThis = false); + /// Find the failed Boolean condition within a given Boolean + /// constant expression, and describe it with a string. + /// + /// \param AllowTopLevelCond Whether to allow the result to be the + /// complete top-level condition. + std::pair<Expr *, std::string> + findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond); + /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any /// non-ArgDependent DiagnoseIfAttrs. /// @@ -2881,12 +2920,13 @@ public: ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *input); + Expr *input, bool RequiresADL = true); ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS); + Expr *LHS, Expr *RHS, + bool RequiresADL = true); ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, SourceLocation RLoc, @@ -3001,14 +3041,31 @@ public: /// purpose of redeclaring the name. NotForRedeclaration = 0, /// \brief The lookup results will be used for redeclaration of a name, - /// if an entity by that name already exists. - ForRedeclaration + /// if an entity by that name already exists and is visible. + ForVisibleRedeclaration, + /// \brief 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 }; + RedeclarationKind forRedeclarationInCurContext() { + // A declaration with an owning module for linkage can never link against + // anything that is not visible. We don't need to check linkage here; if + // the context has internal linkage, redeclaration lookup won't find things + // from other TUs, and we can't safely compute linkage yet in general. + if (cast<Decl>(CurContext) + ->getOwningModuleForLinkage(/*IgnoreLinkage*/true)) + return ForVisibleRedeclaration; + return ForExternalRedeclaration; + } + /// \brief The possible outcomes of name lookup for a literal operator. enum LiteralOperatorLookupResult { /// \brief The lookup resulted in an error. LOLR_Error, + /// \brief The lookup found no match but no diagnostic was issued. + LOLR_ErrorNoDiagnostic, /// \brief The lookup found a single 'cooked' literal operator, which /// expects a normal literal to be built and passed to it. LOLR_Cooked, @@ -3133,7 +3190,8 @@ public: ArrayRef<QualType> ArgTys, bool AllowRaw, bool AllowTemplate, - bool AllowStringTemplate); + bool AllowStringTemplate, + bool DiagnoseMissing); bool isKnownName(StringRef name); void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, @@ -3229,6 +3287,8 @@ public: void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace); + bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old); + void DiagnoseAmbiguousLookup(LookupResult &Result); //@} @@ -3271,7 +3331,7 @@ public: unsigned ArgNum, StringRef &Str, SourceLocation *ArgLocation = nullptr); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); - void checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); + bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); bool checkMSInheritanceAttrOnDefinition( CXXRecordDecl *RD, SourceRange Range, bool BestCase, MSInheritanceAttr::Spelling SemanticSpelling); @@ -3754,15 +3814,15 @@ public: Expr *AsmString, MultiExprArg Clobbers, SourceLocation RParenLoc); + void FillInlineAsmIdentifierInfo(Expr *Res, + llvm::InlineAsmIdentifierInfo &Info); ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, - llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext); bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc); ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, - llvm::InlineAsmIdentifierInfo &Info, SourceLocation AsmLoc); StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef<Token> AsmToks, @@ -6038,7 +6098,7 @@ public: SourceLocation ExportLoc, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef<Decl *> Params, + ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc, Expr *RequiresClause); @@ -7368,13 +7428,16 @@ public: unsigned PrevSFINAEErrors; bool PrevInNonInstantiationSFINAEContext; bool PrevAccessCheckingSFINAE; + bool PrevLastDiagnosticIgnored; public: explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false) : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors), PrevInNonInstantiationSFINAEContext( SemaRef.InNonInstantiationSFINAEContext), - PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE) + PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE), + PrevLastDiagnosticIgnored( + SemaRef.getDiagnostics().isLastDiagnosticIgnored()) { if (!SemaRef.isSFINAEContext()) SemaRef.InNonInstantiationSFINAEContext = true; @@ -7386,6 +7449,8 @@ public: SemaRef.InNonInstantiationSFINAEContext = PrevInNonInstantiationSFINAEContext; SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE; + SemaRef.getDiagnostics().setLastDiagnosticIgnored( + PrevLastDiagnosticIgnored); } /// \brief Determine whether any SFINAE errors have been trapped. @@ -7725,11 +7790,6 @@ public: VarDecl *Var, bool Recursive = false, bool DefinitionRequired = false, bool AtEndOfTU = false); - void InstantiateStaticDataMemberDefinition( - SourceLocation PointOfInstantiation, - VarDecl *Var, - bool Recursive = false, - bool DefinitionRequired = false); void InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, @@ -8182,6 +8242,15 @@ public: void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, StringRef SlotLabel, Expr *Alignment); + enum class PragmaPackDiagnoseKind { + NonDefaultStateAtInclude, + ChangedStateAtExit + }; + + void DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind, + SourceLocation IncludeLoc); + void DiagnoseUnterminatedPragmaPack(); + /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off]. void ActOnPragmaMSStruct(PragmaMSStructKind Kind); @@ -8467,6 +8536,10 @@ private: /// Returns OpenMP nesting level for current directive. unsigned getOpenMPNestingLevel() const; + /// Adjusts the function scopes index for the target-based regions. + void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex, + unsigned Level) const; + /// Push new OpenMP function region for non-capturing function. void pushOpenMPFunctionRegion(); @@ -8507,6 +8580,11 @@ public: /// is performed. bool isOpenMPPrivateDecl(ValueDecl *D, unsigned Level); + /// 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); + /// \brief Check if the specified variable is captured by 'target' directive. /// \param Level Relative level of nested OpenMP construct for that the check /// is performed. @@ -8559,9 +8637,11 @@ public: /// \brief Finish current declare reduction construct initializer. void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner); /// \brief Initialize declare reduction construct initializer. - void ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); + /// \return omp_priv variable. + VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); /// \brief Finish current declare reduction construct initializer. - void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer); + void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, + VarDecl *OmpPrivParm); /// \brief Called at the end of '#pragma omp declare reduction'. DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd( Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid); @@ -8576,11 +8656,20 @@ public: OMPDeclareTargetDeclAttr::MapTypeTy MT, NamedDeclSetType &SameDirectiveDecls); /// Check declaration inside target region. - void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D); - /// Return true inside OpenMP target region. + void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, + SourceLocation IdLoc = SourceLocation()); + /// Return true inside OpenMP declare target region. bool isInOpenMPDeclareTargetContext() const { return IsInOpenMPDeclareTargetContext; } + /// Return true inside OpenMP target region. + bool isInOpenMPTargetExecutionDirective() const; + /// Return true if (un)supported features for the current target should be + /// diagnosed if OpenMP (offloading) is enabled. + bool shouldDiagnoseTargetSupportFromOpenMP() const { + return !getLangOpts().OpenMPIsDevice || isInOpenMPDeclareTargetContext() || + isInOpenMPTargetExecutionDirective(); + } /// Return the number of captured regions created for an OpenMP directive. static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind); @@ -8710,12 +8799,14 @@ public: /// parsing of the associated statement. StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, - SourceLocation EndLoc); + SourceLocation EndLoc, + Stmt *AStmt); /// \brief Called on well-formed '\#pragma omp target exit data' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, - SourceLocation EndLoc); + SourceLocation EndLoc, + Stmt *AStmt); /// \brief Called on well-formed '\#pragma omp target parallel' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses, @@ -8764,7 +8855,8 @@ public: /// \brief Called on well-formed '\#pragma omp target update'. StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, - SourceLocation EndLoc); + SourceLocation EndLoc, + Stmt *AStmt); /// \brief Called on well-formed '\#pragma omp distribute parallel for' after /// parsing of the associated statement. StmtResult ActOnOpenMPDistributeParallelForDirective( @@ -9029,6 +9121,13 @@ public: CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef<Expr *> UnresolvedReductions = llvm::None); + /// Called on well-formed 'in_reduction' clause. + OMPClause *ActOnOpenMPInReductionClause( + ArrayRef<Expr *> VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId, + ArrayRef<Expr *> UnresolvedReductions = llvm::None); /// \brief Called on well-formed 'linear' clause. OMPClause * ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, @@ -10126,8 +10225,7 @@ public: void CodeCompleteObjCPropertyDefinition(Scope *S); void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, IdentifierInfo *PropertyName); - void CodeCompleteObjCMethodDecl(Scope *S, - bool IsInstanceMethod, + void CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, ParsedType ReturnType); void CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, @@ -10211,7 +10309,7 @@ private: bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall); - bool SemaBuiltinVAStartARM(CallExpr *Call); + bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs); bool SemaBuiltinVSX(CallExpr *TheCall); @@ -10362,7 +10460,8 @@ private: /// \brief 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 Expr * const *ExprArgs); + const ArrayRef<const Expr *> ExprArgs, + SourceLocation CallSiteLoc); /// \brief Check if we are taking the address of a packed field /// as this may be a problem if the pointer value is dereferenced. @@ -10383,6 +10482,12 @@ private: IdentifierInfo *Ident_NSError = nullptr; + /// \brief The handler for the FileChanged preprocessor events. + /// + /// Used for diagnostics that implement custom semantic analysis for #include + /// directives, like -Wpragma-pack. + sema::SemaPPCallbacks *SemaPPCallbackHandler; + protected: friend class Parser; friend class InitializationSequence; @@ -10446,6 +10551,36 @@ public: SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses; private: + class SavePendingParsedClassStateRAII { + public: + SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); } + + ~SavePendingParsedClassStateRAII() { + assert(S.DelayedExceptionSpecChecks.empty() && + "there shouldn't be any pending delayed exception spec checks"); + assert(S.DelayedDefaultedMemberExceptionSpecs.empty() && + "there shouldn't be any pending delayed defaulted member " + "exception specs"); + assert(S.DelayedDllExportClasses.empty() && + "there shouldn't be any pending delayed DLL export classes"); + swapSavedState(); + } + + private: + Sema &S; + decltype(DelayedExceptionSpecChecks) SavedExceptionSpecChecks; + decltype(DelayedDefaultedMemberExceptionSpecs) + SavedDefaultedMemberExceptionSpecs; + decltype(DelayedDllExportClasses) SavedDllExportClasses; + + void swapSavedState() { + SavedExceptionSpecChecks.swap(S.DelayedExceptionSpecChecks); + SavedDefaultedMemberExceptionSpecs.swap( + S.DelayedDefaultedMemberExceptionSpecs); + SavedDllExportClasses.swap(S.DelayedDllExportClasses); + } + }; + /// \brief Helper class that collects misaligned member designations and /// their location info for delayed diagnostics. struct MisalignedMember { diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h index a01e8d639f60..4dc215ba21cb 100644 --- a/include/clang/Sema/SemaInternal.h +++ b/include/clang/Sema/SemaInternal.h @@ -73,7 +73,8 @@ inline void MarkVarDeclODRUsed(VarDecl *Var, // Keep track of used but undefined variables. // FIXME: We shouldn't suppress this warning for static data members. if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && - (!Var->isExternallyVisible() || Var->isInline()) && + (!Var->isExternallyVisible() || Var->isInline() || + SemaRef.isExternalWithNoLinkageType(Var)) && !(Var->isStaticDataMember() && Var->hasInit())) { SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()]; if (old.isInvalid()) diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 9227b33d2c53..34a7bb330174 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -14,17 +14,23 @@ // respective lists. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" -#include "llvm/ADT/DenseMap.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Bitcode/BitCodes.h" -#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <cstdint> namespace clang { - namespace serialization { +namespace serialization { + /// \brief AST file major version number supported by this version of /// Clang. /// @@ -52,7 +58,7 @@ namespace clang { /// /// The ID numbers of identifiers are consecutive (in order of discovery) /// and start at 1. 0 is reserved for NULL. - typedef uint32_t IdentifierID; + using IdentifierID = uint32_t; /// \brief An ID number that refers to a declaration in an AST file. /// @@ -60,12 +66,12 @@ namespace clang { /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved. /// At the start of a chain of precompiled headers, declaration ID 1 is /// used for the translation unit declaration. - typedef uint32_t DeclID; + using DeclID = uint32_t; // FIXME: Turn these into classes so we can have some type safety when // we go from local ID to global and vice-versa. - typedef DeclID LocalDeclID; - typedef DeclID GlobalDeclID; + using LocalDeclID = DeclID; + using GlobalDeclID = DeclID; /// \brief An ID number that refers to a type in an AST file. /// @@ -77,22 +83,25 @@ namespace clang { /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are /// other types that have serialized representations. - typedef uint32_t TypeID; + using TypeID = uint32_t; /// \brief A type index; the type ID with the qualifier bits removed. class TypeIdx { - uint32_t Idx; + uint32_t Idx = 0; + public: - TypeIdx() : Idx(0) { } - explicit TypeIdx(uint32_t index) : Idx(index) { } + TypeIdx() = default; + explicit TypeIdx(uint32_t index) : Idx(index) {} uint32_t getIndex() const { return Idx; } + TypeID asTypeID(unsigned FastQuals) const { if (Idx == uint32_t(-1)) return TypeID(-1); return (Idx << Qualifiers::FastWidth) | FastQuals; } + static TypeIdx fromTypeID(TypeID ID) { if (ID == TypeID(-1)) return TypeIdx(-1); @@ -104,14 +113,17 @@ namespace clang { /// A structure for putting "fast"-unqualified QualTypes into a /// DenseMap. This uses the standard pointer hash function. struct UnsafeQualTypeDenseMapInfo { - static inline bool isEqual(QualType A, QualType B) { return A == B; } - static inline QualType getEmptyKey() { + static bool isEqual(QualType A, QualType B) { return A == B; } + + static QualType getEmptyKey() { return QualType::getFromOpaquePtr((void*) 1); } - static inline QualType getTombstoneKey() { + + static QualType getTombstoneKey() { return QualType::getFromOpaquePtr((void*) 2); } - static inline unsigned getHashValue(QualType T) { + + static unsigned getHashValue(QualType T) { assert(!T.getLocalFastQualifiers() && "hash invalid for types with fast quals"); uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); @@ -120,44 +132,44 @@ namespace clang { }; /// \brief An ID number that refers to an identifier in an AST file. - typedef uint32_t IdentID; + using IdentID = uint32_t; /// \brief 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. - typedef uint32_t MacroID; + using MacroID = uint32_t; /// \brief A global ID number that refers to a macro in an AST file. - typedef uint32_t GlobalMacroID; + using GlobalMacroID = uint32_t; /// \brief A local to a module ID number that refers to a macro in an /// AST file. - typedef uint32_t LocalMacroID; + using LocalMacroID = uint32_t; /// \brief 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. - typedef uint32_t SelectorID; + using SelectorID = uint32_t; /// \brief 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 /// AST file. - typedef uint32_t CXXBaseSpecifiersID; + using CXXBaseSpecifiersID = uint32_t; /// \brief An ID number that refers to a list of CXXCtorInitializers in an /// AST file. - typedef uint32_t CXXCtorInitializersID; + using CXXCtorInitializersID = uint32_t; /// \brief An ID number that refers to an entity in the detailed /// preprocessing record. - typedef uint32_t PreprocessedEntityID; + using PreprocessedEntityID = uint32_t; /// \brief An ID number that refers to a submodule in a module file. - typedef uint32_t SubmoduleID; + using SubmoduleID = uint32_t; /// \brief The number of predefined submodule IDs. const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1; @@ -166,18 +178,21 @@ namespace clang { struct PPEntityOffset { /// \brief Raw source location of beginning of range. unsigned Begin; + /// \brief Raw source location of end of range. unsigned End; + /// \brief Offset in the AST file. uint32_t BitOffset; PPEntityOffset(SourceRange R, uint32_t BitOffset) : Begin(R.getBegin().getRawEncoding()), - End(R.getEnd().getRawEncoding()), - BitOffset(BitOffset) { } + End(R.getEnd().getRawEncoding()), BitOffset(BitOffset) {} + SourceLocation getBegin() const { return SourceLocation::getFromRawEncoding(Begin); } + SourceLocation getEnd() const { return SourceLocation::getFromRawEncoding(End); } @@ -186,17 +201,19 @@ namespace clang { /// \brief Source range/offset of a preprocessed entity. struct DeclOffset { /// \brief Raw source location. - unsigned Loc; + unsigned Loc = 0; + /// \brief Offset in the AST file. - uint32_t BitOffset; + uint32_t BitOffset = 0; - DeclOffset() : Loc(0), BitOffset(0) { } + DeclOffset() = default; DeclOffset(SourceLocation Loc, uint32_t BitOffset) - : Loc(Loc.getRawEncoding()), - BitOffset(BitOffset) { } + : Loc(Loc.getRawEncoding()), BitOffset(BitOffset) {} + void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); } + SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Loc); } @@ -617,17 +634,21 @@ namespace clang { /// \brief Describes a source location entry (SLocEntry) for a /// file. SM_SLOC_FILE_ENTRY = 1, + /// \brief 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 /// 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 /// a buffer entry. SM_SLOC_BUFFER_BLOB_COMPRESSED = 4, + /// \brief Describes a source location entry (SLocEntry) for a /// macro expansion. SM_SLOC_EXPANSION_ENTRY = 5 @@ -676,46 +697,66 @@ namespace clang { enum SubmoduleRecordTypes { /// \brief Metadata for submodules as a whole. SUBMODULE_METADATA = 0, + /// \brief 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, /// if any. SUBMODULE_UMBRELLA_HEADER = 2, + /// \brief Specifies a header that falls into this (sub)module. SUBMODULE_HEADER = 3, + /// \brief Specifies a top-level header that falls into this (sub)module. SUBMODULE_TOPHEADER = 4, + /// \brief Specifies an umbrella directory. SUBMODULE_UMBRELLA_DIR = 5, + /// \brief Specifies the submodules that are imported by this /// submodule. SUBMODULE_IMPORTS = 6, + /// \brief Specifies the submodules that are re-exported from this /// submodule. SUBMODULE_EXPORTS = 7, + /// \brief Specifies a required feature. SUBMODULE_REQUIRES = 8, + /// \brief Specifies a header that has been explicitly excluded /// from this submodule. SUBMODULE_EXCLUDED_HEADER = 9, + /// \brief Specifies a library or framework to link against. SUBMODULE_LINK_LIBRARY = 10, + /// \brief Specifies a configuration macro for this module. SUBMODULE_CONFIG_MACRO = 11, + /// \brief Specifies a conflict with another module. SUBMODULE_CONFLICT = 12, + /// \brief 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 /// textually included. SUBMODULE_TEXTUAL_HEADER = 14, + /// \brief Specifies a header that is private to this submodule but /// must be textually included. SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15, + /// \brief 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 + /// re-export the entities in this module. + SUBMODULE_EXPORT_AS = 17, }; /// \brief Record types used within a comments block. @@ -740,92 +781,139 @@ namespace clang { enum PredefinedTypeIDs { /// \brief The NULL type. PREDEF_TYPE_NULL_ID = 0, + /// \brief The void type. PREDEF_TYPE_VOID_ID = 1, + /// \brief The 'bool' or '_Bool' type. PREDEF_TYPE_BOOL_ID = 2, + /// \brief The 'char' type, when it is unsigned. PREDEF_TYPE_CHAR_U_ID = 3, + /// \brief The 'unsigned char' type. PREDEF_TYPE_UCHAR_ID = 4, + /// \brief The 'unsigned short' type. PREDEF_TYPE_USHORT_ID = 5, + /// \brief The 'unsigned int' type. PREDEF_TYPE_UINT_ID = 6, + /// \brief The 'unsigned long' type. PREDEF_TYPE_ULONG_ID = 7, + /// \brief The 'unsigned long long' type. PREDEF_TYPE_ULONGLONG_ID = 8, + /// \brief The 'char' type, when it is signed. PREDEF_TYPE_CHAR_S_ID = 9, + /// \brief The 'signed char' type. PREDEF_TYPE_SCHAR_ID = 10, + /// \brief The C++ 'wchar_t' type. PREDEF_TYPE_WCHAR_ID = 11, + /// \brief The (signed) 'short' type. PREDEF_TYPE_SHORT_ID = 12, + /// \brief The (signed) 'int' type. PREDEF_TYPE_INT_ID = 13, + /// \brief The (signed) 'long' type. PREDEF_TYPE_LONG_ID = 14, + /// \brief The (signed) 'long long' type. PREDEF_TYPE_LONGLONG_ID = 15, + /// \brief The 'float' type. PREDEF_TYPE_FLOAT_ID = 16, + /// \brief The 'double' type. PREDEF_TYPE_DOUBLE_ID = 17, + /// \brief The 'long double' type. PREDEF_TYPE_LONGDOUBLE_ID = 18, + /// \brief The placeholder type for overloaded function sets. PREDEF_TYPE_OVERLOAD_ID = 19, + /// \brief The placeholder type for dependent types. PREDEF_TYPE_DEPENDENT_ID = 20, + /// \brief The '__uint128_t' type. PREDEF_TYPE_UINT128_ID = 21, + /// \brief The '__int128_t' type. PREDEF_TYPE_INT128_ID = 22, + /// \brief The type of 'nullptr'. PREDEF_TYPE_NULLPTR_ID = 23, + /// \brief The C++ 'char16_t' type. PREDEF_TYPE_CHAR16_ID = 24, + /// \brief The C++ 'char32_t' type. PREDEF_TYPE_CHAR32_ID = 25, + /// \brief The ObjC 'id' type. PREDEF_TYPE_OBJC_ID = 26, + /// \brief The ObjC 'Class' type. PREDEF_TYPE_OBJC_CLASS = 27, + /// \brief The ObjC 'SEL' type. PREDEF_TYPE_OBJC_SEL = 28, + /// \brief The 'unknown any' placeholder type. PREDEF_TYPE_UNKNOWN_ANY = 29, + /// \brief The placeholder type for bound member functions. PREDEF_TYPE_BOUND_MEMBER = 30, + /// \brief The "auto" deduction type. PREDEF_TYPE_AUTO_DEDUCT = 31, + /// \brief The "auto &&" deduction type. PREDEF_TYPE_AUTO_RREF_DEDUCT = 32, + /// \brief The OpenCL 'half' / ARM NEON __fp16 type. PREDEF_TYPE_HALF_ID = 33, + /// \brief ARC's unbridged-cast placeholder type. PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34, + /// \brief The pseudo-object placeholder type. PREDEF_TYPE_PSEUDO_OBJECT = 35, + /// \brief The placeholder type for builtin functions. PREDEF_TYPE_BUILTIN_FN = 36, + /// \brief OpenCL event type. PREDEF_TYPE_EVENT_ID = 37, + /// \brief OpenCL clk event type. PREDEF_TYPE_CLK_EVENT_ID = 38, + /// \brief OpenCL sampler type. PREDEF_TYPE_SAMPLER_ID = 39, + /// \brief OpenCL queue type. PREDEF_TYPE_QUEUE_ID = 40, + /// \brief OpenCL reserve_id type. PREDEF_TYPE_RESERVE_ID_ID = 41, + /// \brief The placeholder type for OpenMP array section. PREDEF_TYPE_OMP_ARRAY_SECTION = 42, + /// \brief The '__float128' type PREDEF_TYPE_FLOAT128_ID = 43, + + /// \brief The '_Float16' type + PREDEF_TYPE_FLOAT16_ID = 44, + /// \brief OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, @@ -848,94 +936,141 @@ namespace clang { enum TypeCode { /// \brief An ExtQualType record. TYPE_EXT_QUAL = 1, + /// \brief A ComplexType record. TYPE_COMPLEX = 3, + /// \brief A PointerType record. TYPE_POINTER = 4, + /// \brief A BlockPointerType record. TYPE_BLOCK_POINTER = 5, + /// \brief An LValueReferenceType record. TYPE_LVALUE_REFERENCE = 6, + /// \brief An RValueReferenceType record. TYPE_RVALUE_REFERENCE = 7, + /// \brief A MemberPointerType record. TYPE_MEMBER_POINTER = 8, + /// \brief A ConstantArrayType record. TYPE_CONSTANT_ARRAY = 9, + /// \brief An IncompleteArrayType record. TYPE_INCOMPLETE_ARRAY = 10, + /// \brief A VariableArrayType record. TYPE_VARIABLE_ARRAY = 11, + /// \brief A VectorType record. TYPE_VECTOR = 12, + /// \brief An ExtVectorType record. TYPE_EXT_VECTOR = 13, + /// \brief A FunctionNoProtoType record. TYPE_FUNCTION_NO_PROTO = 14, + /// \brief A FunctionProtoType record. TYPE_FUNCTION_PROTO = 15, + /// \brief A TypedefType record. TYPE_TYPEDEF = 16, + /// \brief A TypeOfExprType record. TYPE_TYPEOF_EXPR = 17, + /// \brief A TypeOfType record. TYPE_TYPEOF = 18, + /// \brief A RecordType record. TYPE_RECORD = 19, + /// \brief An EnumType record. TYPE_ENUM = 20, + /// \brief An ObjCInterfaceType record. TYPE_OBJC_INTERFACE = 21, + /// \brief An ObjCObjectPointerType record. TYPE_OBJC_OBJECT_POINTER = 22, + /// \brief a DecltypeType record. TYPE_DECLTYPE = 23, + /// \brief An ElaboratedType record. TYPE_ELABORATED = 24, + /// \brief A SubstTemplateTypeParmType record. TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, + /// \brief An UnresolvedUsingType record. TYPE_UNRESOLVED_USING = 26, + /// \brief An InjectedClassNameType record. TYPE_INJECTED_CLASS_NAME = 27, + /// \brief An ObjCObjectType record. TYPE_OBJC_OBJECT = 28, + /// \brief An TemplateTypeParmType record. TYPE_TEMPLATE_TYPE_PARM = 29, + /// \brief An TemplateSpecializationType record. TYPE_TEMPLATE_SPECIALIZATION = 30, + /// \brief A DependentNameType record. TYPE_DEPENDENT_NAME = 31, + /// \brief A DependentTemplateSpecializationType record. TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32, + /// \brief A DependentSizedArrayType record. TYPE_DEPENDENT_SIZED_ARRAY = 33, + /// \brief A ParenType record. TYPE_PAREN = 34, + /// \brief A PackExpansionType record. TYPE_PACK_EXPANSION = 35, + /// \brief An AttributedType record. TYPE_ATTRIBUTED = 36, + /// \brief A SubstTemplateTypeParmPackType record. TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37, + /// \brief A AutoType record. TYPE_AUTO = 38, + /// \brief A UnaryTransformType record. TYPE_UNARY_TRANSFORM = 39, + /// \brief An AtomicType record. TYPE_ATOMIC = 40, + /// \brief A DecayedType record. TYPE_DECAYED = 41, + /// \brief An AdjustedType record. TYPE_ADJUSTED = 42, + /// \brief A PipeType record. TYPE_PIPE = 43, + /// \brief An ObjCTypeParamType record. TYPE_OBJC_TYPE_PARAM = 44, + /// \brief A DeducedTemplateSpecializationType record. TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45, + /// \brief A DependentSizedExtVectorType record. - TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46 + TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46, + + /// \brief A DependentAddressSpaceType record. + TYPE_DEPENDENT_ADDRESS_SPACE = 47 }; /// \brief The type IDs for special types constructed by semantic @@ -946,18 +1081,25 @@ namespace clang { enum SpecialTypeIDs { /// \brief CFConstantString type SPECIAL_TYPE_CF_CONSTANT_STRING = 0, + /// \brief C FILE typedef type SPECIAL_TYPE_FILE = 1, + /// \brief C jmp_buf typedef type SPECIAL_TYPE_JMP_BUF = 2, + /// \brief C sigjmp_buf typedef type SPECIAL_TYPE_SIGJMP_BUF = 3, + /// \brief Objective-C "id" redefinition type SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4, + /// \brief Objective-C "Class" redefinition type SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5, + /// \brief Objective-C "SEL" redefinition type SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6, + /// \brief C ucontext_t typedef type SPECIAL_TYPE_UCONTEXT_T = 7 }; @@ -1048,57 +1190,84 @@ namespace clang { /// \brief A TypedefDecl record. DECL_TYPEDEF = 51, /// \brief A TypeAliasDecl record. + DECL_TYPEALIAS, + /// \brief An EnumDecl record. DECL_ENUM, + /// \brief A RecordDecl record. DECL_RECORD, + /// \brief An EnumConstantDecl record. DECL_ENUM_CONSTANT, + /// \brief A FunctionDecl record. DECL_FUNCTION, + /// \brief A ObjCMethodDecl record. DECL_OBJC_METHOD, + /// \brief A ObjCInterfaceDecl record. DECL_OBJC_INTERFACE, + /// \brief A ObjCProtocolDecl record. DECL_OBJC_PROTOCOL, + /// \brief A ObjCIvarDecl record. DECL_OBJC_IVAR, + /// \brief A ObjCAtDefsFieldDecl record. DECL_OBJC_AT_DEFS_FIELD, + /// \brief A ObjCCategoryDecl record. DECL_OBJC_CATEGORY, + /// \brief A ObjCCategoryImplDecl record. DECL_OBJC_CATEGORY_IMPL, + /// \brief A ObjCImplementationDecl record. DECL_OBJC_IMPLEMENTATION, + /// \brief A ObjCCompatibleAliasDecl record. DECL_OBJC_COMPATIBLE_ALIAS, + /// \brief A ObjCPropertyDecl record. DECL_OBJC_PROPERTY, + /// \brief A ObjCPropertyImplDecl record. DECL_OBJC_PROPERTY_IMPL, + /// \brief A FieldDecl record. DECL_FIELD, + /// \brief A MSPropertyDecl record. DECL_MS_PROPERTY, + /// \brief A VarDecl record. DECL_VAR, + /// \brief An ImplicitParamDecl record. DECL_IMPLICIT_PARAM, + /// \brief A ParmVarDecl record. DECL_PARM_VAR, + /// \brief A DecompositionDecl record. DECL_DECOMPOSITION, + /// \brief A BindingDecl record. DECL_BINDING, + /// \brief A FileScopeAsmDecl record. DECL_FILE_SCOPE_ASM, + /// \brief A BlockDecl record. DECL_BLOCK, + /// \brief A CapturedDecl record. DECL_CAPTURED, + /// \brief A record that stores the set of declarations that are /// lexically stored within a given DeclContext. /// @@ -1108,6 +1277,7 @@ namespace clang { /// the contents of a DeclContext, e.g., via /// DeclContext::decls_begin() and DeclContext::decls_end(). DECL_CONTEXT_LEXICAL, + /// \brief A record that stores the set of declarations that are /// visible from a given DeclContext. /// @@ -1116,104 +1286,151 @@ namespace clang { /// IDs. This data is used when performing qualified name lookup /// into a DeclContext via DeclContext::lookup. DECL_CONTEXT_VISIBLE, + /// \brief A LabelDecl record. DECL_LABEL, + /// \brief A NamespaceDecl record. DECL_NAMESPACE, + /// \brief A NamespaceAliasDecl record. DECL_NAMESPACE_ALIAS, + /// \brief A UsingDecl record. DECL_USING, + /// \brief A UsingPackDecl record. DECL_USING_PACK, + /// \brief A UsingShadowDecl record. DECL_USING_SHADOW, + /// \brief A ConstructorUsingShadowDecl record. DECL_CONSTRUCTOR_USING_SHADOW, + /// \brief A UsingDirecitveDecl record. DECL_USING_DIRECTIVE, + /// \brief An UnresolvedUsingValueDecl record. DECL_UNRESOLVED_USING_VALUE, + /// \brief An UnresolvedUsingTypenameDecl record. DECL_UNRESOLVED_USING_TYPENAME, + /// \brief A LinkageSpecDecl record. DECL_LINKAGE_SPEC, + /// \brief An ExportDecl record. DECL_EXPORT, + /// \brief A CXXRecordDecl record. DECL_CXX_RECORD, + /// \brief A CXXDeductionGuideDecl record. DECL_CXX_DEDUCTION_GUIDE, + /// \brief A CXXMethodDecl record. DECL_CXX_METHOD, + /// \brief A CXXConstructorDecl record. DECL_CXX_CONSTRUCTOR, + /// \brief A CXXConstructorDecl record for an inherited constructor. DECL_CXX_INHERITED_CONSTRUCTOR, + /// \brief A CXXDestructorDecl record. DECL_CXX_DESTRUCTOR, + /// \brief A CXXConversionDecl record. DECL_CXX_CONVERSION, + /// \brief An AccessSpecDecl record. DECL_ACCESS_SPEC, /// \brief A FriendDecl record. DECL_FRIEND, + /// \brief A FriendTemplateDecl record. DECL_FRIEND_TEMPLATE, + /// \brief A ClassTemplateDecl record. DECL_CLASS_TEMPLATE, + /// \brief A ClassTemplateSpecializationDecl record. DECL_CLASS_TEMPLATE_SPECIALIZATION, + /// \brief A ClassTemplatePartialSpecializationDecl record. DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, + /// \brief A VarTemplateDecl record. DECL_VAR_TEMPLATE, + /// \brief A VarTemplateSpecializationDecl record. DECL_VAR_TEMPLATE_SPECIALIZATION, + /// \brief A VarTemplatePartialSpecializationDecl record. DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION, + /// \brief A FunctionTemplateDecl record. DECL_FUNCTION_TEMPLATE, + /// \brief A TemplateTypeParmDecl record. DECL_TEMPLATE_TYPE_PARM, + /// \brief A NonTypeTemplateParmDecl record. DECL_NON_TYPE_TEMPLATE_PARM, + /// \brief A TemplateTemplateParmDecl record. DECL_TEMPLATE_TEMPLATE_PARM, + /// \brief A TypeAliasTemplateDecl record. DECL_TYPE_ALIAS_TEMPLATE, + /// \brief A StaticAssertDecl record. DECL_STATIC_ASSERT, + /// \brief A record containing CXXBaseSpecifiers. DECL_CXX_BASE_SPECIFIERS, + /// \brief A record containing CXXCtorInitializers. DECL_CXX_CTOR_INITIALIZERS, + /// \brief A IndirectFieldDecl record. DECL_INDIRECTFIELD, + /// \brief 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 /// template template parameter pack. DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK, + /// \brief A ClassScopeFunctionSpecializationDecl record a class scope /// function specialization. (Microsoft extension). DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION, + /// \brief An ImportDecl recording a module import. DECL_IMPORT, + /// \brief An OMPThreadPrivateDecl record. DECL_OMP_THREADPRIVATE, + /// \brief An EmptyDecl record. DECL_EMPTY, + /// \brief An ObjCTypeParamDecl record. DECL_OBJC_TYPE_PARAM, + /// \brief An OMPCapturedExprDecl record. DECL_OMP_CAPTUREDEXPR, + /// \brief A PragmaCommentDecl record. DECL_PRAGMA_COMMENT, + /// \brief A PragmaDetectMismatchDecl record. DECL_PRAGMA_DETECT_MISMATCH, + /// \brief An OMPDeclareReductionDecl record. DECL_OMP_DECLARE_REDUCTION, }; @@ -1229,128 +1446,190 @@ namespace clang { /// \brief A marker record that indicates that we are at the end /// of an expression. STMT_STOP = 128, + /// \brief A NULL expression. STMT_NULL_PTR, + /// \brief A reference to a previously [de]serialized Stmt record. STMT_REF_PTR, + /// \brief A NullStmt record. STMT_NULL, + /// \brief A CompoundStmt record. STMT_COMPOUND, + /// \brief A CaseStmt record. STMT_CASE, + /// \brief A DefaultStmt record. STMT_DEFAULT, + /// \brief A LabelStmt record. STMT_LABEL, + /// \brief An AttributedStmt record. STMT_ATTRIBUTED, + /// \brief An IfStmt record. STMT_IF, + /// \brief A SwitchStmt record. STMT_SWITCH, + /// \brief A WhileStmt record. STMT_WHILE, + /// \brief A DoStmt record. STMT_DO, + /// \brief A ForStmt record. STMT_FOR, + /// \brief A GotoStmt record. STMT_GOTO, + /// \brief An IndirectGotoStmt record. STMT_INDIRECT_GOTO, + /// \brief A ContinueStmt record. STMT_CONTINUE, + /// \brief A BreakStmt record. STMT_BREAK, + /// \brief A ReturnStmt record. STMT_RETURN, + /// \brief A DeclStmt record. STMT_DECL, + /// \brief A CapturedStmt record. STMT_CAPTURED, + /// \brief A GCC-style AsmStmt record. STMT_GCCASM, + /// \brief A MS-style AsmStmt record. STMT_MSASM, + /// \brief A PredefinedExpr record. EXPR_PREDEFINED, + /// \brief A DeclRefExpr record. EXPR_DECL_REF, + /// \brief An IntegerLiteral record. EXPR_INTEGER_LITERAL, + /// \brief A FloatingLiteral record. EXPR_FLOATING_LITERAL, + /// \brief An ImaginaryLiteral record. EXPR_IMAGINARY_LITERAL, + /// \brief A StringLiteral record. EXPR_STRING_LITERAL, + /// \brief A CharacterLiteral record. EXPR_CHARACTER_LITERAL, + /// \brief A ParenExpr record. EXPR_PAREN, + /// \brief A ParenListExpr record. EXPR_PAREN_LIST, + /// \brief A UnaryOperator record. EXPR_UNARY_OPERATOR, + /// \brief An OffsetOfExpr record. EXPR_OFFSETOF, + /// \brief A SizefAlignOfExpr record. EXPR_SIZEOF_ALIGN_OF, + /// \brief An ArraySubscriptExpr record. EXPR_ARRAY_SUBSCRIPT, + /// \brief A CallExpr record. EXPR_CALL, + /// \brief A MemberExpr record. EXPR_MEMBER, + /// \brief A BinaryOperator record. EXPR_BINARY_OPERATOR, + /// \brief A CompoundAssignOperator record. EXPR_COMPOUND_ASSIGN_OPERATOR, + /// \brief A ConditionOperator record. EXPR_CONDITIONAL_OPERATOR, + /// \brief An ImplicitCastExpr record. EXPR_IMPLICIT_CAST, + /// \brief A CStyleCastExpr record. EXPR_CSTYLE_CAST, + /// \brief A CompoundLiteralExpr record. EXPR_COMPOUND_LITERAL, + /// \brief An ExtVectorElementExpr record. EXPR_EXT_VECTOR_ELEMENT, + /// \brief An InitListExpr record. EXPR_INIT_LIST, + /// \brief A DesignatedInitExpr record. EXPR_DESIGNATED_INIT, + /// \brief A DesignatedInitUpdateExpr record. EXPR_DESIGNATED_INIT_UPDATE, + /// \brief An NoInitExpr record. EXPR_NO_INIT, + /// \brief An ArrayInitLoopExpr record. EXPR_ARRAY_INIT_LOOP, + /// \brief An ArrayInitIndexExpr record. EXPR_ARRAY_INIT_INDEX, + /// \brief An ImplicitValueInitExpr record. EXPR_IMPLICIT_VALUE_INIT, + /// \brief A VAArgExpr record. EXPR_VA_ARG, + /// \brief An AddrLabelExpr record. EXPR_ADDR_LABEL, + /// \brief A StmtExpr record. EXPR_STMT, + /// \brief A ChooseExpr record. EXPR_CHOOSE, + /// \brief A GNUNullExpr record. EXPR_GNU_NULL, + /// \brief A ShuffleVectorExpr record. EXPR_SHUFFLE_VECTOR, + /// \brief A ConvertVectorExpr record. EXPR_CONVERT_VECTOR, + /// \brief BlockExpr EXPR_BLOCK, + /// \brief A GenericSelectionExpr record. EXPR_GENERIC_SELECTION, + /// \brief A PseudoObjectExpr record. EXPR_PSEUDO_OBJECT, + /// \brief An AtomicExpr record. EXPR_ATOMIC, @@ -1362,45 +1641,61 @@ namespace clang { EXPR_OBJC_BOXED_EXPRESSION, EXPR_OBJC_ARRAY_LITERAL, EXPR_OBJC_DICTIONARY_LITERAL, - - + /// \brief An ObjCEncodeExpr record. EXPR_OBJC_ENCODE, + /// \brief An ObjCSelectorExpr record. EXPR_OBJC_SELECTOR_EXPR, + /// \brief An ObjCProtocolExpr record. EXPR_OBJC_PROTOCOL_EXPR, + /// \brief An ObjCIvarRefExpr record. EXPR_OBJC_IVAR_REF_EXPR, + /// \brief An ObjCPropertyRefExpr record. EXPR_OBJC_PROPERTY_REF_EXPR, + /// \brief An ObjCSubscriptRefExpr record. EXPR_OBJC_SUBSCRIPT_REF_EXPR, + /// \brief UNUSED EXPR_OBJC_KVC_REF_EXPR, + /// \brief An ObjCMessageExpr record. EXPR_OBJC_MESSAGE_EXPR, + /// \brief An ObjCIsa Expr record. EXPR_OBJC_ISA, + /// \brief An ObjCIndirectCopyRestoreExpr record. EXPR_OBJC_INDIRECT_COPY_RESTORE, /// \brief An ObjCForCollectionStmt record. STMT_OBJC_FOR_COLLECTION, + /// \brief An ObjCAtCatchStmt record. STMT_OBJC_CATCH, + /// \brief An ObjCAtFinallyStmt record. STMT_OBJC_FINALLY, + /// \brief An ObjCAtTryStmt record. STMT_OBJC_AT_TRY, + /// \brief An ObjCAtSynchronizedStmt record. STMT_OBJC_AT_SYNCHRONIZED, + /// \brief An ObjCAtThrowStmt record. STMT_OBJC_AT_THROW, + /// \brief An ObjCAutoreleasePoolStmt record. STMT_OBJC_AUTORELEASE_POOL, + /// \brief An ObjCBoolLiteralExpr record. EXPR_OBJC_BOOL_LITERAL, + /// \brief An ObjCAvailabilityCheckExpr record. EXPR_OBJC_AVAILABILITY_CHECK, @@ -1408,37 +1703,52 @@ namespace clang { /// \brief A CXXCatchStmt record. STMT_CXX_CATCH, + /// \brief A CXXTryStmt record. STMT_CXX_TRY, /// \brief A CXXForRangeStmt record. + STMT_CXX_FOR_RANGE, /// \brief A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, + /// \brief A CXXMemberCallExpr record. EXPR_CXX_MEMBER_CALL, + /// \brief A CXXConstructExpr record. EXPR_CXX_CONSTRUCT, + /// \brief A CXXInheritedCtorInitExpr record. EXPR_CXX_INHERITED_CTOR_INIT, + /// \brief A CXXTemporaryObjectExpr record. EXPR_CXX_TEMPORARY_OBJECT, + /// \brief A CXXStaticCastExpr record. EXPR_CXX_STATIC_CAST, + /// \brief A CXXDynamicCastExpr record. EXPR_CXX_DYNAMIC_CAST, + /// \brief A CXXReinterpretCastExpr record. EXPR_CXX_REINTERPRET_CAST, + /// \brief A CXXConstCastExpr record. EXPR_CXX_CONST_CAST, + /// \brief A CXXFunctionalCastExpr record. EXPR_CXX_FUNCTIONAL_CAST, + /// \brief A UserDefinedLiteral record. EXPR_USER_DEFINED_LITERAL, + /// \brief A CXXStdInitializerListExpr record. EXPR_CXX_STD_INITIALIZER_LIST, + /// \brief A CXXBoolLiteralExpr record. EXPR_CXX_BOOL_LITERAL, + EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr). EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type). @@ -1560,11 +1870,14 @@ namespace clang { enum DesignatorTypes { /// \brief Field designator where only the field name is known. DESIG_FIELD_NAME = 0, + /// \brief Field designator where the field has been resolved to /// a declaration. DESIG_FIELD_DECL = 1, + /// \brief Array designator. DESIG_ARRAY = 2, + /// \brief GNU array range designator. DESIG_ARRAY_RANGE = 3 }; @@ -1580,8 +1893,11 @@ namespace clang { /// \brief Describes the redeclarations of a declaration. struct LocalRedeclarationsInfo { - DeclID FirstID; // The ID of the first declaration - unsigned Offset; // Offset into the array of redeclaration chains. + // The ID of the first declaration + DeclID FirstID; + + // Offset into the array of redeclaration chains. + unsigned Offset; friend bool operator<(const LocalRedeclarationsInfo &X, const LocalRedeclarationsInfo &Y) { @@ -1606,8 +1922,11 @@ namespace clang { /// \brief Describes the categories of an Objective-C class. struct ObjCCategoriesInfo { - DeclID DefinitionID; // The ID of the definition - unsigned Offset; // Offset into the array of category lists. + // The ID of the definition + DeclID DefinitionID; + + // Offset into the array of category lists. + unsigned Offset; friend bool operator<(const ObjCCategoriesInfo &X, const ObjCCategoriesInfo &Y) { @@ -1636,15 +1955,14 @@ namespace clang { /// same key can occasionally represent multiple names (for names that /// contain types, in particular). class DeclarationNameKey { - typedef unsigned NameKind; + using NameKind = unsigned; - NameKind Kind; - uint64_t Data; + NameKind Kind = 0; + uint64_t Data = 0; public: - DeclarationNameKey() : Kind(), Data() {} + DeclarationNameKey() = default; DeclarationNameKey(DeclarationName Name); - DeclarationNameKey(NameKind Kind, uint64_t Data) : Kind(Kind), Data(Data) {} @@ -1656,12 +1974,14 @@ namespace clang { Kind == DeclarationName::CXXDeductionGuideName); return (IdentifierInfo *)Data; } + Selector getSelector() const { assert(Kind == DeclarationName::ObjCZeroArgSelector || Kind == DeclarationName::ObjCOneArgSelector || Kind == DeclarationName::ObjCMultiArgSelector); return Selector(Data); } + OverloadedOperatorKind getOperatorKind() const { assert(Kind == DeclarationName::CXXOperatorName); return (OverloadedOperatorKind)Data; @@ -1677,26 +1997,32 @@ namespace clang { }; /// @} - } -} // end namespace clang + +} // namespace serialization +} // namespace clang namespace llvm { + template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> { static clang::serialization::DeclarationNameKey getEmptyKey() { return clang::serialization::DeclarationNameKey(-1, 1); } + static clang::serialization::DeclarationNameKey getTombstoneKey() { return clang::serialization::DeclarationNameKey(-1, 2); } + static unsigned getHashValue(const clang::serialization::DeclarationNameKey &Key) { return Key.getHash(); } + static bool isEqual(const clang::serialization::DeclarationNameKey &L, const clang::serialization::DeclarationNameKey &R) { return L == R; } }; -} -#endif +} // namespace llvm + +#endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index eafa05175832..7b71fee95de2 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1,4 +1,4 @@ -//===--- ASTReader.h - AST File Reader --------------------------*- C++ -*-===// +//===- ASTReader.h - AST File Reader ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,13 +17,21 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclarationName.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" +#include "clang/Lex/Token.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/IdentifierResolver.h" #include "clang/Serialization/ASTBitCodes.h" @@ -31,70 +39,86 @@ #include "clang/Serialization/Module.h" #include "clang/Serialization/ModuleFileExtension.h" #include "clang/Serialization/ModuleManager.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/TinyPtrVector.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Timer.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <ctime> #include <deque> #include <memory> +#include <set> #include <string> #include <utility> #include <vector> -namespace llvm { - class BitstreamCursor; - class MemoryBuffer; - class APInt; - class APSInt; - class APFloat; -} - namespace clang { -class SourceManager; -class HeaderSearchOptions; -class FileManager; -class AddrLabelExpr; class ASTConsumer; class ASTContext; -class ASTIdentifierIterator; -class ASTUnit; // FIXME: Layering violation and egregious hack. -class Attr; -class Decl; -class DeclContext; -class DefMacroDirective; -class DiagnosticOptions; -class NestedNameSpecifier; +class ASTDeserializationListener; +class ASTReader; +class ASTRecordReader; class CXXBaseSpecifier; class CXXConstructorDecl; class CXXCtorInitializer; +class CXXTemporary; +class Decl; +class DeclaratorDecl; +class DeclContext; +class EnumDecl; +class Expr; +class FieldDecl; +class FileEntry; +class FileManager; +class FileSystemOptions; +class FunctionDecl; class GlobalModuleIndex; -class GotoStmt; -class MacroDefinition; -class MacroDirective; -class ModuleMacro; +struct HeaderFileInfo; +class HeaderSearchOptions; +class LangOptions; +class LazyASTUnresolvedSet; +class MacroInfo; +class MemoryBufferCache; class NamedDecl; -class OpaqueValueExpr; +class NamespaceDecl; +class NestedNameSpecifier; +class ObjCCategoryDecl; +class ObjCInterfaceDecl; +class PCHContainerReader; class Preprocessor; class PreprocessorOptions; +struct QualifierInfo; class Sema; +class SourceManager; +class Stmt; class SwitchCase; -class ASTDeserializationListener; -class ASTWriter; -class ASTReader; -class ASTDeclReader; -class ASTStmtReader; -class ASTRecordReader; -class TypeLocReader; -struct HeaderFileInfo; -class VersionTuple; class TargetOptions; -class LazyASTUnresolvedSet; +class TemplateParameterList; +class TypedefNameDecl; +class TypeSourceInfo; +class ValueDecl; +class VarDecl; /// \brief Abstract interface for callback invocations by the ASTReader. /// @@ -189,9 +213,11 @@ public: /// \brief 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 /// 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 /// each non-system input file of the AST File. If /// \c needsSystemInputFileVisitation is true, then it is called for all @@ -206,6 +232,7 @@ public: /// \brief Returns true if this \c ASTReaderListener wants to receive the /// imports of the AST file via \c visitImport, false otherwise. virtual bool needsImportVisitation() const { return false; } + /// \brief If needsImportVisitation returns \c true, this is called for each /// AST file imported by this AST file. virtual void visitImport(StringRef Filename) {} @@ -306,12 +333,15 @@ namespace serialization { class ReadMethodPoolVisitor; namespace reader { - class ASTIdentifierLookupTrait; - /// \brief The on-disk hash table(s) used for DeclContext name lookup. - struct DeclContextLookupTable; -} -} // end namespace serialization +class ASTIdentifierLookupTrait; + +/// \brief 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 /// unit. @@ -334,8 +364,20 @@ class ASTReader public ExternalSLocEntrySource { public: - typedef SmallVector<uint64_t, 64> RecordData; - typedef SmallVectorImpl<uint64_t> RecordDataImpl; + /// \brief Types of AST files. + friend class ASTDeclReader; + friend class ASTIdentifierIterator; + friend class ASTRecordReader; + friend class ASTStmtReader; + friend class ASTUnit; // ASTUnit needs to remap source locations. + friend class ASTWriter; + friend class PCHValidator; + friend class serialization::reader::ASTIdentifierLookupTrait; + friend class serialization::ReadMethodPoolVisitor; + friend class TypeLocReader; + + using RecordData = SmallVector<uint64_t, 64>; + using RecordDataImpl = SmallVectorImpl<uint64_t>; /// \brief The result of reading the control block of an AST file, which /// can fail for various reasons. @@ -343,41 +385,34 @@ public: /// \brief 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. Failure, + /// \brief The AST file was missing. Missing, + /// \brief 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. VersionMismatch, + /// \brief The AST file was writtten with a different language/target /// configuration. ConfigurationMismatch, + /// \brief The AST file has errors. HadErrors }; - /// \brief Types of AST files. - friend class PCHValidator; - friend class ASTDeclReader; - friend class ASTStmtReader; - friend class ASTIdentifierIterator; - friend class serialization::reader::ASTIdentifierLookupTrait; - friend class TypeLocReader; - friend class ASTRecordReader; - friend class ASTWriter; - friend class ASTUnit; // ASTUnit needs to remap source locations. - friend class serialization::ReadMethodPoolVisitor; - - typedef serialization::ModuleFile ModuleFile; - typedef serialization::ModuleKind ModuleKind; - typedef serialization::ModuleManager ModuleManager; - - typedef ModuleManager::ModuleIterator ModuleIterator; - typedef ModuleManager::ModuleConstIterator ModuleConstIterator; - typedef ModuleManager::ModuleReverseIterator ModuleReverseIterator; + using ModuleFile = serialization::ModuleFile; + using ModuleKind = serialization::ModuleKind; + using ModuleManager = serialization::ModuleManager; + using ModuleIterator = ModuleManager::ModuleIterator; + using ModuleConstIterator = ModuleManager::ModuleConstIterator; + using ModuleReverseIterator = ModuleManager::ModuleReverseIterator; private: /// \brief The receiver of some callbacks invoked by ASTReader. @@ -385,6 +420,7 @@ private: /// \brief The receiver of deserialization events. ASTDeserializationListener *DeserializationListener = nullptr; + bool OwnsDeserializationListener = false; SourceManager &SourceMgr; @@ -436,7 +472,8 @@ private: /// \brief A map of negated SLocEntryIDs to the modules containing them. ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocEntryMap; - typedef ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocOffsetMapType; + using GlobalSLocOffsetMapType = + ContinuousRangeMap<unsigned, ModuleFile *, 64>; /// \brief A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset) /// SourceLocation offsets to the modules containing them. @@ -448,8 +485,8 @@ private: /// ID = (I + 1) << FastQual::Width has already been loaded std::vector<QualType> TypesLoaded; - typedef ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4> - GlobalTypeMapType; + using GlobalTypeMapType = + ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>; /// \brief Mapping from global type IDs to the module in which the /// type resides along with the offset that should be added to the @@ -462,17 +499,17 @@ private: /// = I + 1 has already been loaded. std::vector<Decl *> DeclsLoaded; - typedef ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4> - GlobalDeclMapType; + using GlobalDeclMapType = + ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>; /// \brief Mapping from global declaration IDs to the module in which the /// declaration resides. GlobalDeclMapType GlobalDeclMap; - typedef std::pair<ModuleFile *, uint64_t> FileOffset; - typedef SmallVector<FileOffset, 2> FileOffsetsTy; - typedef llvm::DenseMap<serialization::DeclID, FileOffsetsTy> - DeclUpdateOffsetsMap; + using FileOffset = std::pair<ModuleFile *, uint64_t>; + using FileOffsetsTy = SmallVector<FileOffset, 2>; + using DeclUpdateOffsetsMap = + llvm::DenseMap<serialization::DeclID, FileOffsetsTy>; /// \brief Declarations that have modifications residing in a later file /// in the chain. @@ -481,12 +518,15 @@ private: struct PendingUpdateRecord { Decl *D; serialization::GlobalDeclID ID; + // Whether the declaration was just deserialized. bool JustLoaded; + PendingUpdateRecord(serialization::GlobalDeclID ID, Decl *D, bool JustLoaded) : D(D), ID(ID), JustLoaded(JustLoaded) {} }; + /// \brief Declaration updates for already-loaded declarations that we need /// to apply once we finish processing an import. llvm::SmallVector<PendingUpdateRecord, 16> PendingUpdateRecords; @@ -505,7 +545,7 @@ private: /// \brief Declarations that have been imported and have typedef names for /// linkage purposes. - llvm::DenseMap<std::pair<DeclContext*, IdentifierInfo*>, NamedDecl*> + llvm::DenseMap<std::pair<DeclContext *, IdentifierInfo *>, NamedDecl *> ImportedTypedefNamesForLinkage; /// \brief Mergeable declaration contexts that have anonymous declarations @@ -514,10 +554,10 @@ private: AnonymousDeclarationsForMerging; struct FileDeclsInfo { - ModuleFile *Mod; + ModuleFile *Mod = nullptr; ArrayRef<serialization::LocalDeclID> Decls; - FileDeclsInfo() : Mod(nullptr) {} + FileDeclsInfo() = default; FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls) : Mod(Mod), Decls(Decls) {} }; @@ -527,7 +567,7 @@ private: /// \brief An array of lexical contents of a declaration context, as a sequence of /// Decl::Kind, DeclID pairs. - typedef ArrayRef<llvm::support::unaligned_uint32_t> LexicalContents; + using LexicalContents = ArrayRef<llvm::support::unaligned_uint32_t>; /// \brief Map from a DeclContext to its lexical contents. llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>> @@ -548,7 +588,7 @@ private: ModuleFile *Mod; const unsigned char *Data; }; - typedef SmallVector<PendingVisibleUpdate, 1> DeclContextVisibleUpdates; + using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>; /// \brief Updates to the visible declarations of declaration contexts that /// haven't been loaded yet. @@ -559,22 +599,23 @@ private: /// declarations that have not yet been linked to their definitions. llvm::SmallPtrSet<Decl *, 4> PendingDefinitions; - typedef llvm::MapVector<Decl *, uint64_t, - llvm::SmallDenseMap<Decl *, unsigned, 4>, - SmallVector<std::pair<Decl *, uint64_t>, 4> > - PendingBodiesMap; + using PendingBodiesMap = + llvm::MapVector<Decl *, uint64_t, + llvm::SmallDenseMap<Decl *, unsigned, 4>, + SmallVector<std::pair<Decl *, uint64_t>, 4>>; /// \brief Functions or methods that have bodies that will be attached. PendingBodiesMap PendingBodies; /// \brief Definitions for which we have added merged definitions but not yet /// performed deduplication. - llvm::SetVector<NamedDecl*> PendingMergedDefinitionsToDeduplicate; + llvm::SetVector<NamedDecl *> PendingMergedDefinitionsToDeduplicate; /// \brief 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. bool ReadVisibleDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, @@ -588,8 +629,8 @@ private: /// been loaded. std::vector<IdentifierInfo *> IdentifiersLoaded; - typedef ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4> - GlobalIdentifierMapType; + using GlobalIdentifierMapType = + ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4>; /// \brief Mapping from global identifier IDs to the module in which the /// identifier resides along with the offset that should be added to the @@ -604,16 +645,16 @@ private: /// been loaded. std::vector<MacroInfo *> MacrosLoaded; - typedef std::pair<IdentifierInfo *, serialization::SubmoduleID> - LoadedMacroInfo; + using LoadedMacroInfo = + std::pair<IdentifierInfo *, serialization::SubmoduleID>; /// \brief 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; - typedef ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4> - GlobalMacroMapType; + using GlobalMacroMapType = + ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4>; /// \brief Mapping from global macro IDs to the module in which the /// macro resides along with the offset that should be added to the @@ -626,8 +667,8 @@ private: /// indicate that the particular submodule ID has not yet been loaded. SmallVector<Module *, 2> SubmodulesLoaded; - typedef ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4> - GlobalSubmoduleMapType; + using GlobalSubmoduleMapType = + ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4>; /// \brief Mapping from global submodule IDs to the module file in which the /// submodule resides along with the offset that should be added to the @@ -635,14 +676,13 @@ private: GlobalSubmoduleMapType GlobalSubmoduleMap; /// \brief A set of hidden declarations. - typedef SmallVector<Decl*, 2> HiddenNames; - typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType; + using HiddenNames = SmallVector<Decl *, 2>; + using HiddenNamesMapType = llvm::DenseMap<Module *, HiddenNames>; /// \brief 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. struct UnresolvedModuleRef { /// \brief The file in which this module resides. @@ -675,11 +715,10 @@ private: /// been loaded. SmallVector<Selector, 16> SelectorsLoaded; - typedef ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4> - GlobalSelectorMapType; + using GlobalSelectorMapType = + ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4>; /// \brief Mapping from global selector IDs to the module in which the - /// global selector ID to produce a local ID. GlobalSelectorMapType GlobalSelectorMap; @@ -699,15 +738,15 @@ private: : M(M), MacroDirectivesOffset(MacroDirectivesOffset) {} }; - typedef llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2> > - PendingMacroIDsMap; + using PendingMacroIDsMap = + llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2>>; /// \brief 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; - typedef ContinuousRangeMap<unsigned, ModuleFile *, 4> - GlobalPreprocessedEntityMapType; + using GlobalPreprocessedEntityMapType = + ContinuousRangeMap<unsigned, ModuleFile *, 4>; /// \brief Mapping from global preprocessing entity IDs to the module in /// which the preprocessed entity resides along with the offset that should be @@ -825,6 +864,7 @@ private: struct PragmaPackStackEntry { unsigned Value; SourceLocation Location; + SourceLocation PushLocation; StringRef SlotLabel; }; llvm::SmallVector<PragmaPackStackEntry, 2> PragmaPackStack; @@ -867,9 +907,6 @@ private: SmallVector<ImportedSubmodule, 2> ImportedModules; //@} - /// \brief The directory that the PCH we are reading is stored in. - std::string CurrentDir; - /// \brief The system include root to be used when loading the /// precompiled header. std::string isysroot; @@ -897,7 +934,8 @@ private: ///\brief Whether we are currently processing update records. bool ProcessingUpdateRecords = false; - typedef llvm::DenseMap<unsigned, SwitchCase *> SwitchCaseMapTy; + using SwitchCaseMapTy = llvm::DenseMap<unsigned, SwitchCase *>; + /// \brief 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 @@ -981,7 +1019,7 @@ private: /// /// The declarations on the identifier chain for these identifiers will be /// loaded once the recursive loading has completed. - llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4> > + llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4>> PendingIdentifierInfos; /// \brief The set of lookup results that we have faked in order to support @@ -1000,7 +1038,9 @@ private: public: InterestingDecl(Decl *D, bool HasBody) : D(D), DeclHasPendingBody(HasBody) {} + Decl *getDecl() { return D; } + /// Whether the declaration has a pending body. bool hasPendingBody() { return DeclHasPendingBody; } }; @@ -1045,8 +1085,11 @@ private: /// once recursing loading has been completed. llvm::SmallVector<NamedDecl *, 16> PendingOdrMergeChecks; + using DataPointers = + std::pair<CXXRecordDecl *, struct CXXRecordDecl::DefinitionData *>; + /// \brief Record definitions in which we found an ODR violation. - llvm::SmallDenseMap<CXXRecordDecl *, llvm::TinyPtrVector<CXXRecordDecl *>, 2> + llvm::SmallDenseMap<CXXRecordDecl *, llvm::SmallVector<DataPointers, 2>, 2> PendingOdrMergeFailures; /// \brief DeclContexts in which we have diagnosed an ODR violation. @@ -1061,8 +1104,8 @@ private: /// module is loaded. SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; - typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> > - KeyDeclsMap; + using KeyDeclsMap = + llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2>>; /// \brief A mapping from canonical declarations to the set of global /// declaration IDs for key declaration that have been merged with that @@ -1096,15 +1139,14 @@ private: ASTReader &Reader; enum ReadingKind PrevKind; - ReadingKindTracker(const ReadingKindTracker &) = delete; - void operator=(const ReadingKindTracker &) = delete; - public: ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader) : Reader(reader), PrevKind(Reader.ReadingKind) { Reader.ReadingKind = newKind; } + ReadingKindTracker(const ReadingKindTracker &) = delete; + ReadingKindTracker &operator=(const ReadingKindTracker &) = delete; ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; } }; @@ -1113,15 +1155,15 @@ private: ASTReader &Reader; bool PrevState; - ProcessingUpdatesRAIIObj(const ProcessingUpdatesRAIIObj &) = delete; - void operator=(const ProcessingUpdatesRAIIObj &) = delete; - public: ProcessingUpdatesRAIIObj(ASTReader &reader) : Reader(reader), PrevState(Reader.ProcessingUpdateRecords) { Reader.ProcessingUpdateRecords = true; } + ProcessingUpdatesRAIIObj(const ProcessingUpdatesRAIIObj &) = delete; + ProcessingUpdatesRAIIObj & + operator=(const ProcessingUpdatesRAIIObj &) = delete; ~ProcessingUpdatesRAIIObj() { Reader.ProcessingUpdateRecords = PrevState; } }; @@ -1135,7 +1177,7 @@ private: /// predefines buffer may contain additional definitions. std::string SuggestedPredefines; - llvm::DenseMap<const Decl *, bool> BodySource; + llvm::DenseMap<const Decl *, bool> DefinitionSource; /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); @@ -1204,7 +1246,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, @@ -1265,10 +1307,11 @@ private: std::string &SuggestedPredefines); struct RecordLocation { - RecordLocation(ModuleFile *M, uint64_t O) - : F(M), Offset(O) {} ModuleFile *F; uint64_t Offset; + + RecordLocation(ModuleFile *M, uint64_t O) + : F(M), Offset(O) {} }; QualType readTypeRecord(unsigned Index); @@ -1327,12 +1370,11 @@ public: ModuleDeclIterator, const serialization::LocalDeclID *, std::random_access_iterator_tag, const Decl *, ptrdiff_t, const Decl *, const Decl *> { - ASTReader *Reader; - ModuleFile *Mod; + ASTReader *Reader = nullptr; + ModuleFile *Mod = nullptr; public: - ModuleDeclIterator() - : iterator_adaptor_base(nullptr), Reader(nullptr), Mod(nullptr) {} + ModuleDeclIterator() : iterator_adaptor_base(nullptr) {} ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod, const serialization::LocalDeclID *Pos) @@ -1341,6 +1383,7 @@ public: value_type operator*() const { return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, *I)); } + value_type operator->() const { return **this; } bool operator==(const ModuleDeclIterator &RHS) const { @@ -1377,8 +1420,6 @@ private: void Error(unsigned DiagID, StringRef Arg1 = StringRef(), StringRef Arg2 = StringRef()) const; - ASTReader(const ASTReader &) = delete; - void operator=(const ASTReader &) = delete; public: /// \brief Load the AST file and validate its contents against the given /// Preprocessor. @@ -1427,7 +1468,8 @@ public: bool AllowConfigurationMismatch = false, bool ValidateSystemInputs = false, bool UseGlobalIndex = true, std::unique_ptr<llvm::Timer> ReadTimer = {}); - + ASTReader(const ASTReader &) = delete; + ASTReader &operator=(const ASTReader &) = delete; ~ASTReader() override; SourceManager &getSourceManager() const { return SourceMgr; } @@ -1442,15 +1484,19 @@ public: enum LoadFailureCapabilities { /// \brief 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 /// is missing. ARR_Missing = 0x1, + /// \brief 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 /// 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 /// compiled configuration doesn't match that of the context it was /// loaded into. @@ -1521,11 +1567,11 @@ public: /// RAII object to temporarily add an AST callback listener. class ListenerScope { ASTReader &Reader; - bool Chained; + bool Chained = false; public: ListenerScope(ASTReader &Reader, std::unique_ptr<ASTReaderListener> L) - : Reader(Reader), Chained(false) { + : Reader(Reader) { auto Old = Reader.takeListener(); if (Old) { Chained = true; @@ -1534,6 +1580,7 @@ public: } Reader.setListener(std::move(L)); } + ~ListenerScope() { auto New = Reader.takeListener(); if (Chained) @@ -1932,16 +1979,16 @@ public: llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override; void ReadReferencedSelectors( - SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) override; + SmallVectorImpl<std::pair<Selector, SourceLocation>> &Sels) override; void ReadWeakUndeclaredIdentifiers( - SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) override; + SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo>> &WI) override; void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override; void ReadPendingInstantiations( - SmallVectorImpl<std::pair<ValueDecl *, - SourceLocation> > &Pending) override; + SmallVectorImpl<std::pair<ValueDecl *, + SourceLocation>> &Pending) override; void ReadLateParsedTemplates( llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>> @@ -2144,9 +2191,19 @@ public: // \brief Read a string static std::string ReadString(const RecordData &Record, unsigned &Idx); + // \brief Skip a string + static void SkipString(const RecordData &Record, unsigned &Idx) { + Idx += Record[Idx] + 1; + } + // \brief Read a path std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx); + // \brief Skip a path + static void SkipPath(const RecordData &Record, unsigned &Idx) { + SkipString(Record, Idx); + } + /// \brief Read a version tuple. static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); @@ -2264,20 +2321,19 @@ public: /// \brief An object for streaming information from a record. class ASTRecordReader { - typedef serialization::ModuleFile ModuleFile; + using ModuleFile = serialization::ModuleFile; ASTReader *Reader; ModuleFile *F; unsigned Idx = 0; ASTReader::RecordData Record; - typedef ASTReader::RecordData RecordData; - typedef ASTReader::RecordDataImpl RecordDataImpl; + using RecordData = ASTReader::RecordData; + using RecordDataImpl = ASTReader::RecordDataImpl; public: /// Construct an ASTRecordReader that uses the default encoding scheme. - ASTRecordReader(ASTReader &Reader, ModuleFile &F) - : Reader(&Reader), F(&F) {} + ASTRecordReader(ASTReader &Reader, ModuleFile &F) : Reader(&Reader), F(&F) {} /// \brief Reads a record with id AbbrevID from Cursor, resetting the /// internal state. @@ -2291,17 +2347,20 @@ public: /// \brief The current position in this record. unsigned getIdx() const { return Idx; } + /// \brief The length of this record. size_t size() const { return Record.size(); } /// \brief An arbitrary index in this record. const uint64_t &operator[](size_t N) { return Record[N]; } + /// \brief 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 /// next value. const uint64_t &readInt() { return Record[Idx++]; } + /// \brief Returns the current value in this record, without advancing. const uint64_t &peekInt() { return Record[Idx]; } @@ -2555,7 +2614,7 @@ public: /// 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); @@ -2570,6 +2629,6 @@ inline void PCHValidator::Error(const char *Msg) { Reader.Error(Msg); } -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_SERIALIZATION_ASTREADER_H diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index f14dfc73baa9..9437bf7f2c9f 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -1,4 +1,4 @@ -//===--- ASTWriter.h - AST File Writer --------------------------*- C++ -*-===// +//===- ASTWriter.h - AST File Writer ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,67 +11,89 @@ // containing a serialized representation of a translation unit. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SERIALIZATION_ASTWRITER_H #define LLVM_CLANG_SERIALIZATION_ASTWRITER_H #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Decl.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/AST/TypeLoc.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Frontend/PCHContainerOperations.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTDeserializationListener.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitstreamWriter.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <ctime> +#include <memory> #include <queue> +#include <string> +#include <utility> #include <vector> namespace llvm { - class APFloat; - class APInt; -} + +class APFloat; +class APInt; +class APSInt; + +} // namespace llvm namespace clang { -class DeclarationName; class ASTContext; +class ASTReader; +class ASTUnresolvedSet; class Attr; -class NestedNameSpecifier; class CXXBaseSpecifier; class CXXCtorInitializer; +class CXXRecordDecl; +class CXXTemporary; class FileEntry; class FPOptions; +class FunctionDecl; class HeaderSearch; class HeaderSearchOptions; class IdentifierResolver; +class LangOptions; class MacroDefinitionRecord; -class MacroDirective; class MacroInfo; -class OpaqueValueExpr; -class OpenCLOptions; -class ASTReader; class MemoryBufferCache; class Module; class ModuleFileExtension; class ModuleFileExtensionWriter; -class PreprocessedEntity; +class NamedDecl; +class NestedNameSpecifier; +class ObjCInterfaceDecl; class PreprocessingRecord; class Preprocessor; +struct QualifierInfo; class RecordDecl; class Sema; class SourceManager; +class Stmt; struct StoredDeclsList; class SwitchCase; -class TargetInfo; +class TemplateParameterList; class Token; +class TypeSourceInfo; class VersionTuple; -class ASTUnresolvedSet; - -namespace SrcMgr { class SLocEntry; } /// \brief Writes an AST file containing the contents of a translation unit. /// @@ -82,14 +104,15 @@ namespace SrcMgr { class SLocEntry; } class ASTWriter : public ASTDeserializationListener, public ASTMutationListener { public: - typedef SmallVector<uint64_t, 64> RecordData; - typedef SmallVectorImpl<uint64_t> RecordDataImpl; - typedef ArrayRef<uint64_t> RecordDataRef; - friend class ASTDeclWriter; + friend class ASTRecordWriter; friend class ASTStmtWriter; friend class ASTTypeWriter; - friend class ASTRecordWriter; + + using RecordData = SmallVector<uint64_t, 64>; + using RecordDataImpl = SmallVectorImpl<uint64_t>; + using RecordDataRef = ArrayRef<uint64_t>; + private: /// \brief Map that provides the ID numbers of each type within the /// output stream, plus those deserialized from a chained PCH. @@ -100,9 +123,8 @@ private: /// allow for the const/volatile qualifiers. /// /// Keys in the map never have const/volatile qualifiers. - typedef llvm::DenseMap<QualType, serialization::TypeIdx, - serialization::UnsafeQualTypeDenseMapInfo> - TypeIdxMap; + using TypeIdxMap = llvm::DenseMap<QualType, serialization::TypeIdx, + serialization::UnsafeQualTypeDenseMapInfo>; /// \brief The bitstream writer used to emit this precompiled header. llvm::BitstreamWriter &Stream; @@ -152,8 +174,8 @@ private: /// \brief Stores a declaration or a type to be written to the AST file. class DeclOrType { public: - DeclOrType(Decl *D) : Stored(D), IsType(false) { } - DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { } + DeclOrType(Decl *D) : Stored(D), IsType(false) {} + DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) {} bool isType() const { return IsType; } bool isDecl() const { return !IsType; } @@ -195,15 +217,16 @@ private: std::vector<serialization::DeclOffset> DeclOffsets; /// \brief Sorted (by file offset) vector of pairs of file offset/DeclID. - typedef SmallVector<std::pair<unsigned, serialization::DeclID>, 64> - LocDeclIDsTy; + 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 /// indicates the index that this particular vector has in the global one. unsigned FirstDeclIndex; }; - typedef llvm::DenseMap<FileID, DeclIDInFileInfo *> FileDeclIDsTy; + using FileDeclIDsTy = llvm::DenseMap<FileID, DeclIDInFileInfo *>; /// \brief Map from file SLocEntries to info about the file-level declarations /// that it contains. @@ -260,6 +283,7 @@ private: MacroInfo *MI; serialization::MacroID ID; }; + /// \brief The macro infos to emit. std::vector<MacroInfoToEmitData> MacroInfosToEmit; @@ -331,31 +355,33 @@ private: : Kind(Kind), Type(Type.getAsOpaquePtr()) {} DeclUpdate(unsigned Kind, SourceLocation Loc) : Kind(Kind), Loc(Loc.getRawEncoding()) {} - DeclUpdate(unsigned Kind, unsigned Val) - : Kind(Kind), Val(Val) {} - DeclUpdate(unsigned Kind, Module *M) - : Kind(Kind), Mod(M) {} + DeclUpdate(unsigned Kind, unsigned Val) : Kind(Kind), Val(Val) {} + DeclUpdate(unsigned Kind, Module *M) : Kind(Kind), Mod(M) {} DeclUpdate(unsigned Kind, const Attr *Attribute) : Kind(Kind), Attribute(Attribute) {} unsigned getKind() const { return Kind; } const Decl *getDecl() const { return Dcl; } QualType getType() const { return QualType::getFromOpaquePtr(Type); } + SourceLocation getLoc() const { return SourceLocation::getFromRawEncoding(Loc); } + unsigned getNumber() const { return Val; } Module *getModule() const { return Mod; } const Attr *getAttr() const { return Attribute; } }; - typedef SmallVector<DeclUpdate, 1> UpdateRecord; - typedef llvm::MapVector<const Decl *, UpdateRecord> DeclUpdateMap; + using UpdateRecord = SmallVector<DeclUpdate, 1>; + using DeclUpdateMap = llvm::MapVector<const Decl *, UpdateRecord>; + /// \brief Mapping from declarations that came from a chained PCH to the /// record containing modifications to them. DeclUpdateMap DeclUpdates; - typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap; + using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>; + /// \brief Map of first declarations from a chained PCH that point to the /// most recent declarations in another PCH. FirstLatestDeclMap FirstLatestDecls; @@ -600,7 +626,6 @@ public: /// \brief Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordDataImpl &Record); - /// \brief Force a declaration to be emitted and get its ID. serialization::DeclID GetDeclRef(const Decl *D); @@ -651,6 +676,7 @@ public: unsigned getTypeExtQualAbbrev() const { return TypeExtQualAbbrev; } + unsigned getTypeFunctionProtoAbbrev() const { return TypeFunctionProtoAbbrev; } @@ -698,12 +724,14 @@ private: void ResolvedExceptionSpec(const FunctionDecl *FD) override; void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override; void ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) override; + const FunctionDecl *Delete, + Expr *ThisArg) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; - void StaticDataMemberInstantiated(const VarDecl *D) override; + void InstantiationRequested(const ValueDecl *D) override; + void VariableDefinitionInstantiated(const VarDecl *D) override; + void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void DefaultArgumentInstantiated(const ParmVarDecl *D) override; void DefaultMemberInitializerInstantiated(const FieldDecl *D) override; - void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) override; void DeclarationMarkedUsed(const Decl *D) override; @@ -756,8 +784,8 @@ public: : Writer(Parent.Writer), Record(&Record) {} /// Copying an ASTRecordWriter is almost certainly a bug. - ASTRecordWriter(const ASTRecordWriter&) = delete; - void operator=(const ASTRecordWriter&) = delete; + ASTRecordWriter(const ASTRecordWriter &) = delete; + ASTRecordWriter &operator=(const ASTRecordWriter &) = delete; /// \brief Extract the underlying record storage. ASTWriter::RecordDataImpl &getRecordData() const { return *Record; } @@ -909,7 +937,7 @@ public: void AddUnresolvedSet(const ASTUnresolvedSet &Set); /// \brief Emit a CXXCtorInitializer array. - void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer*> CtorInits); + void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer *> CtorInits); void AddCXXDefinitionData(const CXXRecordDecl *D); @@ -955,6 +983,7 @@ public: ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, bool AllowASTWithErrors = false, bool IncludeTimestamps = true); ~PCHGenerator() override; + void InitializeSema(Sema &S) override { SemaPtr = &S; } void HandleTranslationUnit(ASTContext &Ctx) override; ASTMutationListener *GetASTMutationListener() override; @@ -962,6 +991,6 @@ public: bool hasEmittedPCH() const { return Buffer->IsComplete; } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_SERIALIZATION_ASTWRITER_H diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h index 244b01b22aa1..24bfadd0f867 100644 --- a/include/clang/Serialization/ContinuousRangeMap.h +++ b/include/clang/Serialization/ContinuousRangeMap.h @@ -1,4 +1,4 @@ -//===--- ContinuousRangeMap.h - Map with int range as key -------*- C++ -*-===// +//===- ContinuousRangeMap.h - Map with int range as key ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" #include <algorithm> +#include <cassert> #include <utility> namespace clang { @@ -35,14 +36,15 @@ namespace clang { template <typename Int, typename V, unsigned InitialCapacity> class ContinuousRangeMap { public: - typedef std::pair<Int, V> value_type; - typedef value_type &reference; - typedef const value_type &const_reference; - typedef value_type *pointer; - typedef const value_type *const_pointer; + using value_type = std::pair<Int, V>; + using reference = value_type &; + using const_reference = const value_type &; + using pointer = value_type *; + using const_pointer = const value_type *; private: - typedef SmallVector<value_type, InitialCapacity> Representation; + using Representation = SmallVector<value_type, InitialCapacity>; + Representation Rep; struct Compare { @@ -52,7 +54,7 @@ private: bool operator ()(Int L, const_reference R) const { return L < R.first; } - bool operator ()(Int L, Int R) const { + bool operator ()(Int L, Int R) const { return L < R; } bool operator ()(const_reference L, const_reference R) const { @@ -80,8 +82,8 @@ public: Rep.insert(I, Val); } - typedef typename Representation::iterator iterator; - typedef typename Representation::const_iterator const_iterator; + using iterator = typename Representation::iterator; + using const_iterator = typename Representation::const_iterator; iterator begin() { return Rep.begin(); } iterator end() { return Rep.end(); } @@ -108,13 +110,12 @@ public: /// from a set of values. class Builder { ContinuousRangeMap &Self; - + + public: + explicit Builder(ContinuousRangeMap &Self) : Self(Self) {} Builder(const Builder&) = delete; Builder &operator=(const Builder&) = delete; - public: - explicit Builder(ContinuousRangeMap &Self) : Self(Self) { } - ~Builder() { std::sort(Self.Rep.begin(), Self.Rep.end(), Compare()); std::unique(Self.Rep.begin(), Self.Rep.end(), @@ -131,9 +132,10 @@ public: Self.Rep.push_back(Val); } }; + friend class Builder; }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index fae387cac7e2..147a6910aa29 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -1,4 +1,4 @@ -//===--- ModuleManager.cpp - Module Manager ---------------------*- C++ -*-===// +//===- ModuleManager.cpp - Module Manager -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,15 +15,30 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H #define LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H -#include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Serialization/Module.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include <cstdint> +#include <ctime> +#include <memory> +#include <string> +#include <utility> -namespace clang { +namespace clang { +class FileEntry; +class FileManager; class GlobalModuleIndex; +class HeaderSearch; class MemoryBufferCache; class ModuleMap; class PCHContainerReader; @@ -58,6 +73,9 @@ class ModuleManager { /// \brief Knows how to unwrap module containers. const PCHContainerReader &PCHContainerRdr; + /// \brief Preprocessor's HeaderSearchInfo containing the module map. + const HeaderSearch &HeaderSearchInfo; + /// \brief A lookup of in-memory (virtual file) buffers llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>> InMemoryBuffers; @@ -79,14 +97,12 @@ class ModuleManager { /// /// The global module index will actually be owned by the ASTReader; this is /// just an non-owning pointer. - GlobalModuleIndex *GlobalIndex; + GlobalModuleIndex *GlobalIndex = nullptr; /// \brief State used by the "visit" operation to avoid malloc traffic in /// calls to visit(). struct VisitState { - explicit VisitState(unsigned N) - : VisitNumber(N, 0), NextVisitNumber(1), NextState(nullptr) - { + explicit VisitState(unsigned N) : VisitNumber(N, 0) { Stack.reserve(N); } @@ -103,46 +119,47 @@ class ModuleManager { SmallVector<unsigned, 4> VisitNumber; /// \brief The next visit number to use to mark visited module files. - unsigned NextVisitNumber; + unsigned NextVisitNumber = 1; /// \brief The next visit state. - VisitState *NextState; + VisitState *NextState = nullptr; }; /// \brief The first visit() state in the chain. - VisitState *FirstVisitState; + VisitState *FirstVisitState = nullptr; VisitState *allocateVisitState(); void returnVisitState(VisitState *State); public: - typedef llvm::pointee_iterator< - SmallVectorImpl<std::unique_ptr<ModuleFile>>::iterator> - ModuleIterator; - typedef llvm::pointee_iterator< - SmallVectorImpl<std::unique_ptr<ModuleFile>>::const_iterator> - ModuleConstIterator; - typedef llvm::pointee_iterator< - SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator> - ModuleReverseIterator; - typedef std::pair<uint32_t, StringRef> ModuleOffset; + using ModuleIterator = llvm::pointee_iterator< + SmallVectorImpl<std::unique_ptr<ModuleFile>>::iterator>; + using ModuleConstIterator = llvm::pointee_iterator< + SmallVectorImpl<std::unique_ptr<ModuleFile>>::const_iterator>; + using ModuleReverseIterator = llvm::pointee_iterator< + SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>; + using ModuleOffset = std::pair<uint32_t, StringRef>; explicit ModuleManager(FileManager &FileMgr, MemoryBufferCache &PCMCache, - const PCHContainerReader &PCHContainerRdr); + const PCHContainerReader &PCHContainerRdr, + const HeaderSearch &HeaderSearchInfo); ~ModuleManager(); /// \brief Forward iterator to traverse all loaded modules. ModuleIterator begin() { return Chain.begin(); } + /// \brief Forward iterator end-point to traverse all loaded modules ModuleIterator end() { return Chain.end(); } /// \brief 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 ModuleConstIterator end() const { return Chain.end(); } /// \brief Reverse iterator to traverse all loaded modules. ModuleReverseIterator rbegin() { return Chain.rbegin(); } + /// \brief Reverse iterator end-point to traverse all loaded modules. ModuleReverseIterator rend() { return Chain.rend(); } @@ -163,8 +180,11 @@ public: /// \brief Returns the module associated with the given index ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; } - /// \brief Returns the module associated with the given name - ModuleFile *lookup(StringRef Name) const; + /// \brief Returns the module associated with the given file name. + ModuleFile *lookupByFileName(StringRef FileName) const; + + /// \brief Returns the module associated with the given module name. + ModuleFile *lookupByModuleName(StringRef ModName) const; /// \brief Returns the module associated with the given module file. ModuleFile *lookup(const FileEntry *File) const; @@ -179,15 +199,18 @@ public: enum AddModuleResult { /// \brief The module file had already been loaded. AlreadyLoaded, + /// \brief The module file was just loaded in response to this call. NewlyLoaded, + /// \brief The module file is missing. Missing, + /// \brief The module file is out-of-date. OutOfDate }; - typedef ASTFileSignature(*ASTFileSignatureReader)(StringRef); + using ASTFileSignatureReader = ASTFileSignature (*)(StringRef); /// \brief Attempts to create a new module and add it to the list of known /// modules. @@ -298,6 +321,8 @@ public: MemoryBufferCache &getPCMCache() const { return *PCMCache; } }; -} } // end namespace clang::serialization +} // namespace serialization + +} // namespace clang -#endif +#endif // LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 82ab720af8dc..e510e84e938a 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -132,6 +132,10 @@ def DynamicTypePropagation : Checker<"DynamicTypePropagation">, HelpText<"Generate dynamic type information">, DescFile<"DynamicTypePropagation.cpp">; +def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">, + HelpText<"Assume that const string-like globals are non-null">, + DescFile<"NonilStringConstantsChecker.cpp">; + } // end "core" let ParentPackage = CoreAlpha in { @@ -184,6 +188,10 @@ def DynamicTypeChecker : Checker<"DynamicTypeChecker">, HelpText<"Check for cases where the dynamic and the static type of an object are unrelated.">, DescFile<"DynamicTypeChecker.cpp">; +def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">, + HelpText<"Check that addresses to stack memory do not escape the function">, + DescFile<"StackAddrEscapeChecker.cpp">; + } // end "alpha.core" let ParentPackage = Nullability in { @@ -284,6 +292,11 @@ def VirtualCallChecker : Checker<"VirtualCall">, let ParentPackage = CplusplusAlpha in { +def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, + HelpText<"Reports destructions of polymorphic objects with a non-virtual " + "destructor in their base class">, + DescFile<"DeleteWithNonVirtualDtorChecker.cpp">; + def IteratorRangeChecker : Checker<"IteratorRange">, HelpText<"Check for iterators used outside their valid ranges">, DescFile<"IteratorChecker.cpp">; @@ -740,10 +753,6 @@ def ExplodedGraphViewer : Checker<"ViewExplodedGraph">, HelpText<"View Exploded Graphs using GraphViz">, DescFile<"DebugCheckers.cpp">; -def BugHashDumper : Checker<"DumpBugHash">, - HelpText<"Dump the bug hash for all statements.">, - DescFile<"DebugCheckers.cpp">; - } // end "debug" diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h index 25886545e2f7..e5e857e97029 100644 --- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h +++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h @@ -145,9 +145,11 @@ public: /// Indicates that the tracked object is an Objective-C object. ObjC, /// Indicates that the tracked object could be a CF or Objective-C object. - AnyObj + AnyObj, + /// Indicates that the tracked object is a generalized object. + Generalized }; - + private: Kind K; ObjKind O; diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def index 04bf41bfde4f..281a2ac3a66f 100644 --- a/include/clang/StaticAnalyzer/Core/Analyses.def +++ b/include/clang/StaticAnalyzer/Core/Analyses.def @@ -28,9 +28,10 @@ ANALYSIS_CONSTRAINTS(Z3Constraints, "z3", "Use Z3 contraint solver", CreateZ3Con #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) #endif -ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(HTML_SINGLE_FILE, "html-single-file", "Output analysis results using HTML (not allowing for multi-file bugs)", createHTMLSingleFileDiagnosticConsumer) ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer) -ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for multi-file bugs)", createPlistMultiFileDiagnosticConsumer) ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer) ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer) diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 5dd6bdf38496..ce50cc582d1e 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -214,6 +214,9 @@ private: /// \sa IncludeLifetimeInCFG Optional<bool> IncludeLifetimeInCFG; + /// \sa IncludeLoopExitInCFG + Optional<bool> IncludeLoopExitInCFG; + /// \sa mayInlineCXXStandardLibrary Optional<bool> InlineCXXStandardLibrary; @@ -275,6 +278,9 @@ private: /// \sa shouldWidenLoops Optional<bool> WidenLoops; + /// \sa shouldUnrollLoops + Optional<bool> UnrollLoops; + /// \sa shouldDisplayNotesAsEvents Optional<bool> DisplayNotesAsEvents; @@ -415,6 +421,13 @@ public: /// the values "true" and "false". bool includeLifetimeInCFG(); + /// Returns whether or not the end of the loop information should be included + /// in the CFG. + /// + /// This is controlled by the 'cfg-loopexit' config option, which accepts + /// the values "true" and "false". + bool includeLoopExitInCFG(); + /// Returns whether or not C++ standard library functions may be considered /// for inlining. /// @@ -560,6 +573,10 @@ public: /// This is controlled by the 'widen-loops' config option. bool shouldWidenLoops(); + /// Returns true if the analysis should try to unroll loops with known bounds. + /// This is controlled by the 'unroll-loops' config option. + bool shouldUnrollLoops(); + /// Returns true if the bug reporter should transparently treat extra note /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic /// consumer doesn't support the extra note pieces. diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 0f1eb096c495..cd1355d03b63 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -17,7 +17,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.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" diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index b72bce5fc9f8..2043896fd26f 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -1,4 +1,4 @@ -//===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- C++ -*-===// +//===--- BugReporterVisitors.h - Generate PathDiagnostics -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H -#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H +#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/FoldingSet.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 3e0913ec4eea..15b930bc3f1e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index fa7ee62ab704..9fec217aca72 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -19,7 +19,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/SourceManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" @@ -436,20 +436,7 @@ public: return cast<FunctionDecl>(CallEvent::getDecl()); } - RuntimeDefinition getRuntimeDefinition() const override { - const FunctionDecl *FD = getDecl(); - // Note that the AnalysisDeclContext will have the FunctionDecl with - // the definition (if one exists). - if (FD) { - AnalysisDeclContext *AD = - getLocationContext()->getAnalysisDeclContext()-> - getManager()->getContext(FD); - if (AD->getBody()) - return RuntimeDefinition(AD->getDecl()); - } - - return RuntimeDefinition(); - } + RuntimeDefinition getRuntimeDefinition() const override; bool argumentsMayEscape() const override; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index e380982d43ea..78d38a3d598d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -196,6 +196,13 @@ public: return getState()->getSVal(S, getLocationContext()); } + /// \brief 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 /// (ExplodedGraph). Uses the default CheckerContext predecessor node. /// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 12ec5b6c64a4..7472a7147fca 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -16,7 +16,7 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H #include "clang/AST/Expr.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index a66e1a1aed01..c63ed4a013aa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/ImmutableMap.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index a710ae68be60..dcea5e461d27 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -20,14 +20,14 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H #include "clang/AST/Decl.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/ProgramPoint.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include <memory> @@ -404,7 +404,7 @@ private: }; class ExplodedNodeSet { - typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy; + typedef llvm::SmallSetVector<ExplodedNode*, 4> ImplTy; ImplTy Impl; public: @@ -424,7 +424,7 @@ public: unsigned size() const { return Impl.size(); } bool empty() const { return Impl.empty(); } - bool erase(ExplodedNode *N) { return Impl.erase(N); } + bool erase(ExplodedNode *N) { return Impl.remove(N); } void clear() { Impl.clear(); } void insert(const ExplodedNodeSet &S) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 067d70610868..712cd6361e11 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -196,6 +196,8 @@ public: void ProcessStmt(const CFGStmt S, ExplodedNode *Pred); + void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred); + void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred); void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred); @@ -330,9 +332,9 @@ public: void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// VisitArraySubscriptExpr - Transfer function for array accesses. - void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *Ex, - ExplodedNode *Pred, - ExplodedNodeSet &Dst); + void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex, + ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// VisitGCCAsmStmt - Transfer function logic for inline asm. void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h new file mode 100644 index 000000000000..a4c505ce5f23 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h @@ -0,0 +1,50 @@ +//===--- LoopUnrolling.h - Unroll loops -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// This header contains the declarations of functions which are used to decide +/// which loops should be completely unrolled and mark their corresponding +/// CFGBlocks. It is done by tracking a stack of loops in the ProgramState. This +/// way specific loops can be marked as completely unrolled. For considering a +/// loop to be completely unrolled it has to fulfill the following requirements: +/// - Currently only forStmts can be considered. +/// - The bound has to be known. +/// - The counter variable has not escaped before/in the body of the loop and +/// changed only in the increment statement corresponding to the loop. It also +/// has to be initialized by a literal in the corresponding initStmt. +/// - Does not contain goto, switch and returnStmt. +/// +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPUNROLLING_H + +#include "clang/Analysis/CFG.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" +namespace clang { +namespace ento { +class AnalysisManager; + +/// Returns if the given State indicates that is inside a completely unrolled +/// loop. +bool isUnrolledState(ProgramStateRef State); + +/// Updates the stack of loops contained by the ProgramState. +ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx, + ExplodedNode* Pred, unsigned maxVisitOnPath); + +/// Updates the given ProgramState. In current implementation it removes the top +/// element of the stack of loops. +ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State); + +} // end namespace ento +} // end namespace clang + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 29b1c4cdca04..8ab665623088 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -21,7 +21,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/FoldingSet.h" @@ -1412,21 +1412,18 @@ public: bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const; bool hasTrait(const MemRegion *MR, InvalidationKinds IK) const; }; - -} // end GR namespace - -} // end clang namespace //===----------------------------------------------------------------------===// // Pretty-printing regions. //===----------------------------------------------------------------------===// - -namespace llvm { -static inline raw_ostream &operator<<(raw_ostream &os, - const clang::ento::MemRegion* R) { +inline raw_ostream &operator<<(raw_ostream &os, + const clang::ento::MemRegion *R) { R->dumpToStream(os); return os; } -} // end llvm namespace + +} // namespace ento + +} // namespace clang #endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index e3a2164b11ff..dd2564b0a3c3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -308,8 +308,12 @@ public: /// \brief Return the value bound to the specified location. /// Returns UnknownVal() if none found. - SVal getSVal(const MemRegion* R) const; + SVal getSVal(const MemRegion* R, QualType T = QualType()) const; + /// \brief 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 @@ -758,9 +762,10 @@ inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const { return getStateManager().StoreMgr->getBinding(getStore(), LV, T); } -inline SVal ProgramState::getSVal(const MemRegion* R) const { +inline SVal ProgramState::getSVal(const MemRegion* R, QualType T) const { return getStateManager().StoreMgr->getBinding(getStore(), - loc::MemRegionVal(R)); + loc::MemRegionVal(R), + T); } inline BasicValueFactory &ProgramState::getBasicVals() const { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 935f0018324a..06132587b4aa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -103,9 +103,6 @@ public: return *static_cast<const T *>(this); } - /// BufferTy - A temporary buffer to hold a set of SVals. - typedef SmallVector<SVal,5> BufferTy; - inline unsigned getRawKind() const { return Kind; } inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; } @@ -198,6 +195,10 @@ public: } }; +inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) { + V.dumpToStream(os); + return os; +} class UndefinedVal : public SVal { public: @@ -622,11 +623,6 @@ private: } // end clang namespace namespace llvm { -static inline raw_ostream &operator<<(raw_ostream &os, - clang::ento::SVal V) { - V.dumpToStream(os); - return os; -} template <typename T> struct isPodLike; template <> struct isPodLike<clang::ento::SVal> { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 7619f22f4013..25d20a17afaa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -51,7 +51,7 @@ public: virtual ~StoreManager() {} /// Return the value bound to specified location in a given state. - /// \param[in] store The analysis state. + /// \param[in] store The store in which to make the lookup. /// \param[in] loc The symbolic memory location. /// \param[in] T An optional type that provides a hint indicating the /// expected type of the returned value. This is used if the value is @@ -83,12 +83,12 @@ public: return getDefaultBinding(lcv.getStore(), lcv.getRegion()); } - /// Return a state with the specified value bound to the given location. - /// \param[in] store The analysis state. + /// Return a store with the specified value bound to the given location. + /// \param[in] store The store in which to make the binding. /// \param[in] loc The symbolic memory location. /// \param[in] val The value to bind to location \c loc. - /// \return A pointer to a ProgramState object that contains the same - /// bindings as \c state with the addition of having the value specified + /// \return A StoreRef object that contains the same + /// bindings as \c store with the addition of having the value specified /// by \c val bound to the location given for \c loc. virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index f72033955ec3..9780d0144746 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -98,6 +98,12 @@ public: virtual const MemRegion *getOriginRegion() const { return nullptr; } }; +inline raw_ostream &operator<<(raw_ostream &os, + const clang::ento::SymExpr *SE) { + SE->dumpToStream(os); + return os; +} + typedef const SymExpr *SymbolRef; typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index e9701142cd9e..7d2e5ad8ba91 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -17,7 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" @@ -633,11 +633,4 @@ public: } // end clang namespace -namespace llvm { -static inline raw_ostream &operator<<(raw_ostream &os, - const clang::ento::SymExpr *SE) { - SE->dumpToStream(os); - return os; -} -} // end llvm namespace #endif diff --git a/include/clang/Tooling/ASTDiff/ASTDiff.h b/include/clang/Tooling/ASTDiff/ASTDiff.h new file mode 100644 index 000000000000..dd11c91ac0dd --- /dev/null +++ b/include/clang/Tooling/ASTDiff/ASTDiff.h @@ -0,0 +1,127 @@ +//===- ASTDiff.h - AST differencing API -----------------------*- C++ -*- -===// +// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file specifies an interface that can be used to compare C++ syntax +// trees. +// +// We use the gumtree algorithm which combines a heuristic top-down search that +// is able to match large subtrees that are equivalent, with an optimal +// algorithm to match small subtrees. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H +#define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H + +#include "clang/Tooling/ASTDiff/ASTDiffInternal.h" + +namespace clang { +namespace diff { + +enum ChangeKind { + None, + Delete, // (Src): delete node Src. + Update, // (Src, Dst): update the value of node Src to match Dst. + Insert, // (Src, Dst, Pos): insert Src as child of Dst at offset Pos. + Move, // (Src, Dst, Pos): move Src to be a child of Dst at offset Pos. + UpdateMove // Same as Move plus Update. +}; + +/// Represents a Clang AST node, alongside some additional information. +struct Node { + NodeId Parent, LeftMostDescendant, RightMostDescendant; + int Depth, Height, Shift = 0; + ast_type_traits::DynTypedNode ASTNode; + SmallVector<NodeId, 4> Children; + ChangeKind Change = None; + + ast_type_traits::ASTNodeKind getType() const; + StringRef getTypeLabel() const; + bool isLeaf() const { return Children.empty(); } + llvm::Optional<StringRef> getIdentifier() const; + llvm::Optional<std::string> getQualifiedIdentifier() const; +}; + +class ASTDiff { +public: + ASTDiff(SyntaxTree &Src, SyntaxTree &Dst, const ComparisonOptions &Options); + ~ASTDiff(); + + // Returns the ID of the node that is mapped to the given node in SourceTree. + NodeId getMapped(const SyntaxTree &SourceTree, NodeId Id) const; + + class Impl; + +private: + std::unique_ptr<Impl> DiffImpl; +}; + +/// SyntaxTree objects represent subtrees of the AST. +/// They can be constructed from any Decl or Stmt. +class SyntaxTree { +public: + /// Constructs a tree from a translation unit. + SyntaxTree(ASTContext &AST); + /// Constructs a tree from any AST node. + template <class T> + SyntaxTree(T *Node, ASTContext &AST) + : TreeImpl(llvm::make_unique<Impl>(this, Node, AST)) {} + SyntaxTree(SyntaxTree &&Other) = default; + ~SyntaxTree(); + + const ASTContext &getASTContext() const; + StringRef getFilename() const; + + int getSize() const; + NodeId getRootId() const; + using PreorderIterator = NodeId; + PreorderIterator begin() const; + PreorderIterator end() const; + + const Node &getNode(NodeId Id) const; + int findPositionInParent(NodeId Id) const; + + // Returns the starting and ending offset of the node in its source file. + std::pair<unsigned, unsigned> getSourceRangeOffsets(const Node &N) const; + + /// Serialize the node attributes to a string representation. This should + /// uniquely distinguish nodes of the same kind. Note that this function just + /// returns a representation of the node value, not considering descendants. + std::string getNodeValue(NodeId Id) const; + std::string getNodeValue(const Node &Node) const; + + class Impl; + std::unique_ptr<Impl> TreeImpl; +}; + +struct ComparisonOptions { + /// During top-down matching, only consider nodes of at least this height. + int MinHeight = 2; + + /// During bottom-up matching, match only nodes with at least this value as + /// the ratio of their common descendants. + double MinSimilarity = 0.5; + + /// Whenever two subtrees are matched in the bottom-up phase, the optimal + /// mapping is computed, unless the size of either subtrees exceeds this. + int MaxSize = 100; + + bool StopAfterTopDown = false; + + /// Returns false if the nodes should never be matched. + bool isMatchingAllowed(const Node &N1, const Node &N2) const { + return N1.getType().isSame(N2.getType()); + } +}; + +} // end namespace diff +} // end namespace clang + +#endif diff --git a/include/clang/Tooling/ASTDiff/ASTDiffInternal.h b/include/clang/Tooling/ASTDiff/ASTDiffInternal.h new file mode 100644 index 000000000000..a76ad37336a6 --- /dev/null +++ b/include/clang/Tooling/ASTDiff/ASTDiffInternal.h @@ -0,0 +1,48 @@ +//===- ASTDiffInternal.h --------------------------------------*- 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_ASTDIFF_ASTDIFFINTERNAL_H +#define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFFINTERNAL_H + +#include "clang/AST/ASTTypeTraits.h" + +namespace clang { +namespace diff { + +using DynTypedNode = ast_type_traits::DynTypedNode; + +class SyntaxTree; +class SyntaxTreeImpl; +struct ComparisonOptions; + +/// Within a tree, this identifies a node by its preorder offset. +struct NodeId { +private: + static constexpr int InvalidNodeId = -1; + +public: + int Id; + + NodeId() : Id(InvalidNodeId) {} + NodeId(int Id) : Id(Id) {} + + operator int() const { return Id; } + NodeId &operator++() { return ++Id, *this; } + NodeId &operator--() { return --Id, *this; } + // Support defining iterators on NodeId. + NodeId &operator*() { return *this; } + + bool isValid() const { return Id != InvalidNodeId; } + bool isInvalid() const { return Id == InvalidNodeId; } +}; + +} // end namespace diff +} // end namespace clang +#endif diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h index 3d630c5f7609..15e8161dd76f 100644 --- a/include/clang/Tooling/CommonOptionsParser.h +++ b/include/clang/Tooling/CommonOptionsParser.h @@ -27,8 +27,10 @@ #ifndef LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H #define LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H +#include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" namespace clang { namespace tooling { @@ -84,14 +86,19 @@ public: /// /// All options not belonging to \p Category become hidden. /// - /// I also allows calls to set the required number of positional parameters. - /// - /// This constructor exits program in case of error. + /// It also allows calls to set the required number of positional parameters. CommonOptionsParser(int &argc, const char **argv, llvm::cl::OptionCategory &Category, llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview = nullptr); + /// \brief 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, + llvm::cl::NumOccurrencesFlag OccurrencesFlag, + const char *Overview = nullptr); + /// Returns a reference to the loaded compilations database. CompilationDatabase &getCompilations() { return *Compilations; @@ -102,13 +109,46 @@ public: return SourcePathList; } + /// Returns the argument adjuster calculated from "--extra-arg" and + //"--extra-arg-before" options. + ArgumentsAdjuster getArgumentsAdjuster() { return Adjuster; } + static const char *const HelpMessage; private: + CommonOptionsParser() = default; + + llvm::Error init(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + llvm::cl::NumOccurrencesFlag OccurrencesFlag, + const char *Overview); + std::unique_ptr<CompilationDatabase> Compilations; std::vector<std::string> SourcePathList; - std::vector<std::string> ExtraArgsBefore; - std::vector<std::string> ExtraArgsAfter; + ArgumentsAdjuster Adjuster; +}; + +class ArgumentsAdjustingCompilations : public CompilationDatabase { +public: + ArgumentsAdjustingCompilations( + std::unique_ptr<CompilationDatabase> Compilations) + : Compilations(std::move(Compilations)) {} + + void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster); + + std::vector<CompileCommand> + getCompileCommands(StringRef FilePath) const override; + + std::vector<std::string> getAllFiles() const override; + + std::vector<CompileCommand> getAllCompileCommands() const override; + +private: + std::unique_ptr<CompilationDatabase> Compilations; + std::vector<ArgumentsAdjuster> Adjusters; + + std::vector<CompileCommand> + adjustCommands(std::vector<CompileCommand> Commands) const; }; } // namespace tooling diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h index e988b84b6eae..bc3e67b77de2 100644 --- a/include/clang/Tooling/CompilationDatabase.h +++ b/include/clang/Tooling/CompilationDatabase.h @@ -64,10 +64,12 @@ struct CompileCommand { /// \brief Interface for compilation databases. /// -/// A compilation database allows the user to retrieve all compile command lines -/// that a specified file is compiled with in a project. -/// The retrieved compile command lines can be used to run clang tools over -/// a subset of the files in a project. +/// A compilation database allows the user to retrieve compile command lines +/// for the files in a project. +/// +/// Many implementations are enumerable, allowing all command lines to be +/// retrieved. These can be used to run clang tools over a subset of the files +/// in a project. class CompilationDatabase { public: virtual ~CompilationDatabase(); @@ -104,7 +106,7 @@ public: /// \brief Returns all compile commands in which the specified file was /// compiled. /// - /// This includes compile comamnds that span multiple source files. + /// This includes compile commands that span multiple source files. /// For example, consider a project with the following compilations: /// $ clang++ -o test a.cc b.cc t.cc /// $ clang++ -o production a.cc b.cc -DPRODUCTION @@ -114,7 +116,10 @@ public: StringRef FilePath) const = 0; /// \brief Returns the list of all files available in the compilation database. - virtual std::vector<std::string> getAllFiles() const = 0; + /// + /// 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 /// database. @@ -122,7 +127,10 @@ public: /// FIXME: Add a layer in Tooling that provides an interface to run a tool /// over all files in a compilation database. Not all build systems have the /// ability to provide a feasible implementation for \c getAllCompileCommands. - virtual std::vector<CompileCommand> getAllCompileCommands() const = 0; + /// + /// By default, this is implemented in terms of getAllFiles() and + /// getCompileCommands(). Subclasses may override this for efficiency. + virtual std::vector<CompileCommand> getAllCompileCommands() const; }; /// \brief Interface for compilation database plugins. @@ -149,6 +157,7 @@ public: /// \brief 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 "--". @@ -182,6 +191,11 @@ public: int &Argc, const char *const *Argv, std::string &ErrorMsg, Twine Directory = "."); + /// Reads flags from the given file, one-per line. + /// Returns nullptr and sets ErrorMessage if we can't read the file. + static std::unique_ptr<FixedCompilationDatabase> + loadFromFile(StringRef Path, std::string &ErrorMsg); + /// \brief Constructs a compilation data base from a specified directory /// and command line. FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine); @@ -194,17 +208,6 @@ public: std::vector<CompileCommand> getCompileCommands(StringRef FilePath) const override; - /// \brief Returns the list of all files available in the compilation database. - /// - /// Note: This is always an empty list for the fixed compilation database. - std::vector<std::string> getAllFiles() const override; - - /// \brief Returns all compile commands for all the files in the compilation - /// database. - /// - /// Note: This is always an empty list for the fixed compilation database. - std::vector<CompileCommand> getAllCompileCommands() const override; - private: /// This is built up to contain a single entry vector to be returned from /// getCompileCommands after adding the positional argument. diff --git a/include/clang/Tooling/Core/Replacement.h b/include/clang/Tooling/Core/Replacement.h index 8d4a22adf368..3fea9aee604c 100644 --- a/include/clang/Tooling/Core/Replacement.h +++ b/include/clang/Tooling/Core/Replacement.h @@ -255,7 +255,7 @@ class Replacements { /// \brief Merges \p Replaces into the current replacements. \p Replaces /// refers to code after applying the current replacements. - Replacements merge(const Replacements &Replaces) const; + LLVM_NODISCARD Replacements merge(const Replacements &Replaces) const; // Returns the affected ranges in the changed code. std::vector<Range> getAffectedRanges() const; diff --git a/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h new file mode 100644 index 000000000000..1a44c4788c49 --- /dev/null +++ b/include/clang/Tooling/Execution.h @@ -0,0 +1,175 @@ +//===--- Execution.h - Executing clang frontend actions -*- 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 framework for executing clang frontend actions. +// +// The framework can be extended to support different execution plans including +// standalone execution on the given TUs or parallel execution on all TUs in +// the codebase. +// +// In order to enable multiprocessing execution, tool actions are expected to +// output result into the ToolResults provided by the executor. The +// `ToolResults` is an interface that abstracts how results are stored e.g. +// in-memory for standalone execution or on-disk for large-scale execution. +// +// New executors can be registered as ToolExecutorPlugins via the +// `ToolExecutorPluginRegistry`. CLI tools can use +// `createExecutorFromCommandLineArgs` to create a specific registered executor +// according to the command-line arguments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_EXECUTION_H +#define LLVM_CLANG_TOOLING_EXECUTION_H + +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Registry.h" + +namespace clang { +namespace tooling { + +/// \brief 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 +/// can use source location as key and a replacement in YAML format as value. +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 void forEachResult( + llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0; +}; + +class InMemoryToolResults : public ToolResults { +public: + void addResult(StringRef Key, StringRef Value) override; + std::vector<std::pair<std::string, std::string>> AllKVResults() override; + void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)> + Callback) override; + +private: + std::vector<std::pair<std::string, std::string>> KVResults; +}; + +/// \brief 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`. + explicit ExecutionContext(ToolResults *Results) : Results(Results) {} + + /// \brief 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. + // Otherwise returns an empty string. + virtual std::string getRevision() { return ""; } + + // Returns the corpus being analyzed, e.g. "llvm" for the LLVM codebase, if + // applicable. + virtual std::string getCorpus() { return ""; } + + // Returns the currently processed compilation unit if available. + virtual std::string getCurrentCompilationUnit() { return ""; } + +private: + ToolResults *Results; +}; + +/// \brief 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. +/// +/// New executors can be registered as ToolExecutorPlugins via the +/// `ToolExecutorPluginRegistry`. CLI tools can use +/// `createExecutorFromCommandLineArgs` to create a specific registered +/// executor according to the command-line arguments. +class ToolExecutor { +public: + virtual ~ToolExecutor() {} + + /// \brief Returns the name of a specific executor. + virtual StringRef getExecutorName() const = 0; + + /// \brief 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`. + 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. + /// + /// 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. + /// + /// 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. + /// + /// \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 +/// used as a plugin to be registered into ToolExecutorPluginRegistry. +class ToolExecutorPlugin { +public: + virtual ~ToolExecutorPlugin() {} + + /// \brief 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 +/// commandline arguments. +/// +/// This picks the right executor based on the `--executor` option. This parses +/// the commandline arguments with `CommonOptionsParser`, so caller does not +/// need to parse again. +/// +/// By default, this creates a `StandaloneToolExecutor` ("standalone") if +/// `--executor` is not provided. +llvm::Expected<std::unique_ptr<ToolExecutor>> +createExecutorFromCommandLineArgs(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview = nullptr); + +namespace internal { +llvm::Expected<std::unique_ptr<ToolExecutor>> +createExecutorFromCommandLineArgsImpl(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview = nullptr); +} // end namespace internal + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_EXECUTION_H diff --git a/include/clang/Tooling/Refactoring/ASTSelection.h b/include/clang/Tooling/Refactoring/ASTSelection.h new file mode 100644 index 000000000000..aa02a6899e8f --- /dev/null +++ b/include/clang/Tooling/Refactoring/ASTSelection.h @@ -0,0 +1,155 @@ +//===--- ASTSelection.h - Clang refactoring library -----------------------===// +// +// 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_REFACTOR_AST_SELECTION_H +#define LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H + +#include "clang/AST/ASTTypeTraits.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include <vector> + +namespace clang { + +class ASTContext; + +namespace tooling { + +enum class SourceSelectionKind { + /// A node that's not selected. + None, + + /// A node that's considered to be selected because the whole selection range + /// is inside of its source range. + ContainsSelection, + /// A node that's considered to be selected because the start of the selection + /// range is inside its source range. + ContainsSelectionStart, + /// A node that's considered to be selected because the end of the selection + /// range is inside its source range. + ContainsSelectionEnd, + + /// A node that's considered to be selected because the node is entirely in + /// the selection range. + InsideSelection, +}; + +/// Represents a selected AST node. +/// +/// AST selection is represented using a tree of \c SelectedASTNode. The tree +/// follows the top-down shape of the actual AST. Each selected node has +/// a selection kind. The kind might be none as the node itself might not +/// actually be selected, e.g. a statement in macro whose child is in a macro +/// argument. +struct SelectedASTNode { + ast_type_traits::DynTypedNode Node; + SourceSelectionKind SelectionKind; + std::vector<SelectedASTNode> Children; + + SelectedASTNode(const ast_type_traits::DynTypedNode &Node, + SourceSelectionKind SelectionKind) + : Node(Node), SelectionKind(SelectionKind) {} + SelectedASTNode(SelectedASTNode &&) = default; + SelectedASTNode &operator=(SelectedASTNode &&) = default; + + void dump(llvm::raw_ostream &OS = llvm::errs()) const; + + using ReferenceType = std::reference_wrapper<const SelectedASTNode>; +}; + +/// Traverses the given ASTContext and creates a tree of selected AST nodes. +/// +/// \returns None if no nodes are selected in the AST, or a selected AST node +/// that corresponds to the TranslationUnitDecl otherwise. +Optional<SelectedASTNode> findSelectedASTNodes(const ASTContext &Context, + SourceRange SelectionRange); + +/// An AST selection value that corresponds to a selection of a set of +/// statements that belong to one body of code (like one function). +/// +/// For example, the following selection in the source. +/// +/// \code +/// void function() { +/// // selection begin: +/// int x = 0; +/// { +/// // selection end +/// x = 1; +/// } +/// x = 2; +/// } +/// \endcode +/// +/// Would correspond to a code range selection of statements "int x = 0" +/// and the entire compound statement that follows it. +/// +/// A \c CodeRangeASTSelection value stores references to the full +/// \c SelectedASTNode tree and should not outlive it. +class CodeRangeASTSelection { +public: + CodeRangeASTSelection(CodeRangeASTSelection &&) = default; + CodeRangeASTSelection &operator=(CodeRangeASTSelection &&) = default; + + /// Returns the parent hierarchy (top to bottom) for the selected nodes. + ArrayRef<SelectedASTNode::ReferenceType> getParents() { return Parents; } + + /// Returns the number of selected statements. + size_t size() const { + if (!AreChildrenSelected) + return 1; + return SelectedNode.get().Children.size(); + } + + const Stmt *operator[](size_t I) const { + if (!AreChildrenSelected) { + assert(I == 0 && "Invalid index"); + return SelectedNode.get().Node.get<Stmt>(); + } + return SelectedNode.get().Children[I].Node.get<Stmt>(); + } + + /// Returns true when a selected code range is in a function-like body + /// of code, like a function, method or a block. + /// + /// This function can be used to test against selected expressions that are + /// located outside of a function, e.g. global variable initializers, default + /// argument values, or even template arguments. + /// + /// Use the \c getFunctionLikeNearestParent to get the function-like parent + /// declaration. + bool isInFunctionLikeBodyOfCode() const; + + /// Returns the nearest function-like parent declaration or null if such + /// declaration doesn't exist. + const Decl *getFunctionLikeNearestParent() const; + + static Optional<CodeRangeASTSelection> + create(SourceRange SelectionRange, const SelectedASTNode &ASTSelection); + +private: + CodeRangeASTSelection(SelectedASTNode::ReferenceType SelectedNode, + ArrayRef<SelectedASTNode::ReferenceType> Parents, + bool AreChildrenSelected) + : SelectedNode(SelectedNode), Parents(Parents.begin(), Parents.end()), + AreChildrenSelected(AreChildrenSelected) {} + + /// The reference to the selected node (or reference to the selected + /// child nodes). + SelectedASTNode::ReferenceType SelectedNode; + /// The parent hierarchy (top to bottom) for the selected noe. + llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents; + /// True only when the children of the selected node are actually selected. + bool AreChildrenSelected; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H diff --git a/include/clang/Tooling/Refactoring/AtomicChange.h b/include/clang/Tooling/Refactoring/AtomicChange.h index 9cccd78677b1..8a468a6de84e 100644 --- a/include/clang/Tooling/Refactoring/AtomicChange.h +++ b/include/clang/Tooling/Refactoring/AtomicChange.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H #include "clang/Basic/SourceManager.h" +#include "clang/Format/Format.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -45,6 +46,14 @@ public: AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key) : Key(Key), FilePath(FilePath) {} + AtomicChange(AtomicChange &&) = default; + AtomicChange(const AtomicChange &) = default; + + AtomicChange &operator=(AtomicChange &&) = default; + AtomicChange &operator=(const AtomicChange &) = default; + + bool operator==(const AtomicChange &Other) const; + /// \brief Returns the atomic change as a YAML string. std::string toYAMLString(); @@ -129,6 +138,41 @@ private: tooling::Replacements Replaces; }; +using AtomicChanges = std::vector<AtomicChange>; + +// Defines specs for applying changes. +struct ApplyChangesSpec { + // If true, cleans up redundant/erroneous code around changed code with + // clang-format's cleanup functionality, e.g. redundant commas around deleted + // parameter or empty namespaces introduced by deletions. + bool Cleanup = true; + + format::FormatStyle Style = format::getNoStyle(); + + // Options for selectively formatting changes with clang-format: + // kAll: Format all changed lines. + // kNone: Don't format anything. + // kViolations: Format lines exceeding the `ColumnLimit` in `Style`. + enum FormatOption { kAll, kNone, kViolations }; + + FormatOption Format = kNone; +}; + +/// \brief 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 +/// the same file. +/// +/// \returns The changed code if all changes are applied successfully; +/// otherwise, an llvm::Error carrying llvm::StringError is returned (the Error +/// message can be converted to string with `llvm::toString()` and the +/// error_code should be ignored). +llvm::Expected<std::string> +applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code, + llvm::ArrayRef<AtomicChange> Changes, + const ApplyChangesSpec &Spec); + } // end namespace tooling } // end namespace clang diff --git a/include/clang/Tooling/Refactoring/Extract/Extract.h b/include/clang/Tooling/Refactoring/Extract/Extract.h new file mode 100644 index 000000000000..2fd76d252c62 --- /dev/null +++ b/include/clang/Tooling/Refactoring/Extract/Extract.h @@ -0,0 +1,53 @@ +//===--- Extract.h - Clang refactoring library ----------------------------===// +// +// 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_REFACTOR_EXTRACT_EXTRACT_H +#define LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H + +#include "clang/Tooling/Refactoring/ASTSelection.h" +#include "clang/Tooling/Refactoring/RefactoringActionRules.h" + +namespace clang { +namespace tooling { + +/// An "Extract Function" refactoring moves code into a new function that's +/// then called from the place where the original code was. +class ExtractFunction final : public SourceChangeRefactoringRule { +public: + /// Initiates the extract function refactoring operation. + /// + /// \param Code The selected set of statements. + /// \param DeclName The name name of the extract function. If None, + /// "extracted" is used. + static Expected<ExtractFunction> initiate(RefactoringRuleContext &Context, + CodeRangeASTSelection Code, + Optional<std::string> DeclName); + + static const RefactoringDescriptor &describe(); + +private: + ExtractFunction(CodeRangeASTSelection Code, Optional<std::string> DeclName) + : Code(std::move(Code)), + DeclName(DeclName ? std::move(*DeclName) : "extracted") {} + + Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) override; + + CodeRangeASTSelection Code; + + // FIXME: Account for naming collisions: + // - error when name is specified by user. + // - rename to "extractedN" when name is implicit. + std::string DeclName; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H diff --git a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h index 8b01a61256f6..d96ad78ad876 100644 --- a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h +++ b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -70,6 +70,18 @@ public: return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc()); } + bool VisitOffsetOfExpr(const OffsetOfExpr *S) { + for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { + const OffsetOfNode &Component = S->getComponent(I); + if (Component.getKind() == OffsetOfNode::Field) { + if (!visit(Component.getField(), Component.getLocEnd())) + return false; + } + // FIXME: Try to resolve dependent field references. + } + return true; + } + // Other visitors: bool VisitTypeLoc(const TypeLoc Loc) { diff --git a/include/clang/Tooling/Refactoring/RefactoringAction.h b/include/clang/Tooling/Refactoring/RefactoringAction.h new file mode 100644 index 000000000000..c4080237f1c3 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringAction.h @@ -0,0 +1,64 @@ +//===--- RefactoringAction.h - Clang refactoring library ------------------===// +// +// 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_REFACTOR_REFACTORING_ACTION_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringActionRules.h" +#include <vector> + +namespace clang { +namespace tooling { + +/// A refactoring action is a class that defines a set of related refactoring +/// action rules. These rules get grouped under a common umbrella - a single +/// clang-refactor subcommand. +/// +/// A subclass of \c RefactoringAction is responsible for creating the set of +/// grouped refactoring action rules that represent one refactoring operation. +/// Although the rules in one action may have a number of different +/// implementations, they should strive to produce a similar result. It should +/// be easy for users to identify which refactoring action produced the result +/// regardless of which refactoring action rule was used. +/// +/// The distinction between actions and rules enables the creation of action +/// that uses very different rules, for example: +/// - local vs global: a refactoring operation like +/// "add missing switch cases" can be applied to one switch when it's +/// selected in an editor, or to all switches in a project when an enum +/// constant is added to an enum. +/// - tool vs editor: some refactoring operation can be initiated in the +/// editor when a declaration is selected, or in a tool when the name of +/// the declaration is passed using a command-line argument. +class RefactoringAction { +public: + virtual ~RefactoringAction() {} + + /// Returns the name of the subcommand that's used by clang-refactor for this + /// action. + virtual StringRef getCommand() const = 0; + + virtual StringRef getDescription() const = 0; + + RefactoringActionRules createActiveActionRules(); + +protected: + /// Returns a set of refactoring actions rules that are defined by this + /// action. + virtual RefactoringActionRules createActionRules() const = 0; +}; + +/// Returns the list of all the available refactoring actions. +std::vector<std::unique_ptr<RefactoringAction>> createRefactoringActions(); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRule.h b/include/clang/Tooling/Refactoring/RefactoringActionRule.h new file mode 100644 index 000000000000..4130e29d8dea --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringActionRule.h @@ -0,0 +1,74 @@ +//===--- RefactoringActionRule.h - Clang refactoring library -------------===// +// +// 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_REFACTOR_REFACTORING_ACTION_RULE_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace clang { +namespace tooling { + +class RefactoringOptionVisitor; +class RefactoringResultConsumer; +class RefactoringRuleContext; + +struct RefactoringDescriptor { + /// A unique identifier for the specific refactoring. + StringRef Name; + /// A human readable title for the refactoring. + StringRef Title; + /// A human readable description of what the refactoring does. + StringRef Description; +}; + +/// A common refactoring action rule interface that defines the 'invoke' +/// function that performs the refactoring operation (either fully or +/// partially). +class RefactoringActionRuleBase { +public: + virtual ~RefactoringActionRuleBase() {} + + /// Initiates and performs a specific refactoring action. + /// + /// The specific rule will invoke an appropriate \c handle method on a + /// consumer to propagate the result of the refactoring action. + virtual void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) = 0; + + /// Returns the structure that describes the refactoring. + // static const RefactoringDescriptor &describe() = 0; +}; + +/// A refactoring action rule is a wrapper class around a specific refactoring +/// action rule (SourceChangeRefactoringRule, etc) that, in addition to invoking +/// the action, describes the requirements that determine when the action can be +/// initiated. +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. + virtual bool hasSelectionRequirement() = 0; + + /// Traverses each refactoring option used by the rule and invokes the + /// \c visit callback in the consumer for each option. + /// + /// Options are visited in the order of use, e.g. if a rule has two + /// requirements that use options, the options from the first requirement + /// are visited before the options in the second requirement. + virtual void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) = 0; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h b/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h new file mode 100644 index 000000000000..355a6a55f22f --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h @@ -0,0 +1,123 @@ +//===--- RefactoringActionRuleRequirements.h - Clang refactoring library --===// +// +// 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_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/ASTSelection.h" +#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h" +#include "clang/Tooling/Refactoring/RefactoringOption.h" +#include "clang/Tooling/Refactoring/RefactoringRuleContext.h" +#include "llvm/Support/Error.h" +#include <type_traits> + +namespace clang { +namespace tooling { + +/// A refactoring action rule requirement determines when a refactoring action +/// rule can be invoked. The rule can be invoked only when all of the +/// requirements are satisfied. +/// +/// Subclasses must implement the +/// 'Expected<T> evaluate(RefactoringRuleContext &) const' member function. +/// \c T is used to determine the return type that is passed to the +/// refactoring rule's constructor. +/// For example, the \c SourceRangeSelectionRequirement subclass defines +/// 'Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const' +/// function. When this function returns a non-error value, the resulting +/// source range is passed to the specific refactoring action rule +/// constructor (provided all other requirements are satisfied). +class RefactoringActionRuleRequirement { + // Expected<T> evaluate(RefactoringRuleContext &Context) const; +}; + +/// A base class for any requirement that expects some part of the source to be +/// selected in an editor (or the refactoring tool with the -selection option). +class SourceSelectionRequirement : public RefactoringActionRuleRequirement {}; + +/// A selection requirement that is satisfied when any portion of the source +/// text is selected. +class SourceRangeSelectionRequirement : public SourceSelectionRequirement { +public: + Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const { + if (Context.getSelectionRange().isValid()) + return Context.getSelectionRange(); + return Context.createDiagnosticError(diag::err_refactor_no_selection); + } +}; + +/// An AST selection requirement is satisfied when any portion of the AST +/// overlaps with the selection range. +/// +/// The requirement will be evaluated only once during the initiation and +/// search of matching refactoring action rules. +class ASTSelectionRequirement : public SourceRangeSelectionRequirement { +public: + Expected<SelectedASTNode> evaluate(RefactoringRuleContext &Context) const; +}; + +/// A selection requirement that is satisfied when the selection range overlaps +/// with a number of neighbouring statements in the AST. The statemenst must be +/// contained in declaration like a function. The selection range must be a +/// non-empty source selection (i.e. cursors won't be accepted). +/// +/// The requirement will be evaluated only once during the initiation and search +/// of matching refactoring action rules. +/// +/// \see CodeRangeASTSelection +class CodeRangeASTSelectionRequirement : public ASTSelectionRequirement { +public: + Expected<CodeRangeASTSelection> + evaluate(RefactoringRuleContext &Context) const; +}; + +/// A base class for any requirement that requires some refactoring options. +class RefactoringOptionsRequirement : public RefactoringActionRuleRequirement { +public: + virtual ~RefactoringOptionsRequirement() {} + + /// Returns the set of refactoring options that are used when evaluating this + /// requirement. + virtual ArrayRef<std::shared_ptr<RefactoringOption>> + getRefactoringOptions() const = 0; +}; + +/// A requirement that evaluates to the value of the given \c OptionType when +/// the \c OptionType is a required option. When the \c OptionType is an +/// optional option, the requirement will evaluate to \c None if the option is +/// not specified or to an appropriate value otherwise. +template <typename OptionType> +class OptionRequirement : public RefactoringOptionsRequirement { +public: + OptionRequirement() : Opt(createRefactoringOption<OptionType>()) {} + + ArrayRef<std::shared_ptr<RefactoringOption>> + getRefactoringOptions() const final override { + return Opt; + } + + Expected<typename OptionType::ValueType> + evaluate(RefactoringRuleContext &) const { + return static_cast<OptionType *>(Opt.get())->getValue(); + } + +private: + /// The partially-owned option. + /// + /// The ownership of the option is shared among the different requirements + /// because the same option can be used by multiple rules in one refactoring + /// action. + std::shared_ptr<RefactoringOption> Opt; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRules.h b/include/clang/Tooling/Refactoring/RefactoringActionRules.h new file mode 100644 index 000000000000..33206d9a5dd1 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringActionRules.h @@ -0,0 +1,94 @@ +//===--- RefactoringActionRules.h - Clang refactoring library -------------===// +// +// 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_REFACTOR_REFACTORING_ACTION_RULES_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H + +#include "clang/Tooling/Refactoring/RefactoringActionRule.h" +#include "clang/Tooling/Refactoring/RefactoringActionRulesInternal.h" + +namespace clang { +namespace tooling { + +/// Creates a new refactoring action rule that constructs and invokes the +/// \c RuleType rule when all of the requirements are satisfied. +/// +/// This function takes in a list of values whose type derives from +/// \c RefactoringActionRuleRequirement. These values describe the initiation +/// requirements that have to be satisfied by the refactoring engine before +/// the provided action rule can be constructed and invoked. The engine +/// verifies that the requirements are satisfied by evaluating them (using the +/// 'evaluate' member function) and checking that the results don't contain +/// any errors. Once all requirements are satisfied, the provided refactoring +/// rule is constructed by passing in the values returned by the requirements' +/// evaluate functions as arguments to the constructor. The rule is then invoked +/// immediately after construction. +/// +/// The separation of requirements, their evaluation and the invocation of the +/// refactoring action rule allows the refactoring clients to: +/// - Disable refactoring action rules whose requirements are not supported. +/// - Gather the set of options and define a command-line / visual interface +/// that allows users to input these options without ever invoking the +/// action. +template <typename RuleType, typename... RequirementTypes> +std::unique_ptr<RefactoringActionRule> +createRefactoringActionRule(const RequirementTypes &... Requirements); + +/// A set of refactoring action rules that should have unique initiation +/// requirements. +using RefactoringActionRules = + std::vector<std::unique_ptr<RefactoringActionRule>>; + +/// A type of refactoring action rule that produces source replacements in the +/// form of atomic changes. +/// +/// This action rule is typically used for local refactorings that replace +/// source in a single AST unit. +class SourceChangeRefactoringRule : public RefactoringActionRuleBase { +public: + void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) final override { + Expected<AtomicChanges> Changes = createSourceReplacements(Context); + if (!Changes) + Consumer.handleError(Changes.takeError()); + else + Consumer.handle(std::move(*Changes)); + } + +private: + virtual Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) = 0; +}; + +/// A type of refactoring action rule that finds a set of symbol occurrences +/// that reference a particular symbol. +/// +/// This action rule is typically used for an interactive rename that allows +/// users to specify the new name and the set of selected occurrences during +/// the refactoring. +class FindSymbolOccurrencesRefactoringRule : public RefactoringActionRuleBase { +public: + void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) final override { + Expected<SymbolOccurrences> Occurrences = findSymbolOccurrences(Context); + if (!Occurrences) + Consumer.handleError(Occurrences.takeError()); + else + Consumer.handle(std::move(*Occurrences)); + } + +private: + virtual Expected<SymbolOccurrences> + findSymbolOccurrences(RefactoringRuleContext &Context) = 0; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h b/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h new file mode 100644 index 000000000000..75b6c8f70d17 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h @@ -0,0 +1,158 @@ +//===--- RefactoringActionRulesInternal.h - Clang refactoring library -----===// +// +// 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_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringActionRule.h" +#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h" +#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h" +#include "clang/Tooling/Refactoring/RefactoringRuleContext.h" +#include "llvm/Support/Error.h" +#include <type_traits> + +namespace clang { +namespace tooling { +namespace internal { + +inline llvm::Error findError() { return llvm::Error::success(); } + +inline void ignoreError() {} + +template <typename FirstT, typename... RestT> +void ignoreError(Expected<FirstT> &First, Expected<RestT> &... Rest) { + if (!First) + llvm::consumeError(First.takeError()); + ignoreError(Rest...); +} + +/// Scans the tuple and returns a valid \c Error if any of the values are +/// invalid. +template <typename FirstT, typename... RestT> +llvm::Error findError(Expected<FirstT> &First, Expected<RestT> &... Rest) { + if (!First) { + ignoreError(Rest...); + return First.takeError(); + } + return findError(Rest...); +} + +template <typename RuleType, typename... RequirementTypes, size_t... Is> +void invokeRuleAfterValidatingRequirements( + RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context, + const std::tuple<RequirementTypes...> &Requirements, + llvm::index_sequence<Is...>) { + // Check if the requirements we're interested in can be evaluated. + auto Values = + std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...); + auto Err = findError(std::get<Is>(Values)...); + if (Err) + return Consumer.handleError(std::move(Err)); + // Construct the target action rule by extracting the evaluated + // requirements from Expected<> wrappers and then run it. + auto Rule = + RuleType::initiate(Context, std::move((*std::get<Is>(Values)))...); + if (!Rule) + return Consumer.handleError(Rule.takeError()); + Rule->invoke(Consumer, Context); +} + +inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {} + +/// Scans the list of requirements in a rule and visits all the refactoring +/// options that are used by all the requirements. +template <typename FirstT, typename... RestT> +void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor, + const FirstT &First, const RestT &... Rest) { + struct OptionGatherer { + RefactoringOptionVisitor &Visitor; + + void operator()(const RefactoringOptionsRequirement &Requirement) { + for (const auto &Option : Requirement.getRefactoringOptions()) + Option->passToVisitor(Visitor); + } + void operator()(const RefactoringActionRuleRequirement &) {} + }; + (OptionGatherer{Visitor})(First); + return visitRefactoringOptionsImpl(Visitor, Rest...); +} + +template <typename... RequirementTypes, size_t... Is> +void visitRefactoringOptions( + RefactoringOptionVisitor &Visitor, + const std::tuple<RequirementTypes...> &Requirements, + llvm::index_sequence<Is...>) { + visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...); +} + +/// A type trait that returns true when the given type list has at least one +/// type whose base is the given base type. +template <typename Base, typename First, typename... Rest> +struct HasBaseOf : std::conditional<HasBaseOf<Base, First>::value || + HasBaseOf<Base, Rest...>::value, + std::true_type, std::false_type>::type {}; + +template <typename Base, typename T> +struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {}; + +/// A type trait that returns true when the given type list contains types that +/// derive from Base. +template <typename Base, typename First, typename... Rest> +struct AreBaseOf : std::conditional<AreBaseOf<Base, First>::value && + AreBaseOf<Base, Rest...>::value, + std::true_type, std::false_type>::type {}; + +template <typename Base, typename T> +struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {}; + +} // end namespace internal + +template <typename RuleType, typename... RequirementTypes> +std::unique_ptr<RefactoringActionRule> +createRefactoringActionRule(const RequirementTypes &... Requirements) { + static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value, + "Expected a refactoring action rule type"); + static_assert(internal::AreBaseOf<RefactoringActionRuleRequirement, + RequirementTypes...>::value, + "Expected a list of refactoring action rules"); + + class Rule final : public RefactoringActionRule { + public: + Rule(std::tuple<RequirementTypes...> Requirements) + : Requirements(Requirements) {} + + void invoke(RefactoringResultConsumer &Consumer, + RefactoringRuleContext &Context) override { + internal::invokeRuleAfterValidatingRequirements<RuleType>( + Consumer, Context, Requirements, + llvm::index_sequence_for<RequirementTypes...>()); + } + + bool hasSelectionRequirement() override { + return internal::HasBaseOf<SourceSelectionRequirement, + RequirementTypes...>::value; + } + + void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override { + internal::visitRefactoringOptions( + Visitor, Requirements, + llvm::index_sequence_for<RequirementTypes...>()); + } + private: + std::tuple<RequirementTypes...> Requirements; + }; + + return llvm::make_unique<Rule>(std::make_tuple(Requirements...)); +} + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H diff --git a/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h b/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h new file mode 100644 index 000000000000..6767dc708e01 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h @@ -0,0 +1,30 @@ +//===--- RefactoringDiagnostic.h - ------------------------------*- 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_REFACTORING_REFACTORINGDIAGNOSTIC_H +#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/PartialDiagnostic.h" + +namespace clang { +namespace diag { +enum { +#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, CATEGORY) \ + ENUM, +#define REFACTORINGSTART +#include "clang/Basic/DiagnosticRefactoringKinds.inc" +#undef DIAG + NUM_BUILTIN_REFACTORING_DIAGNOSTICS +}; +} // end namespace diag +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H diff --git a/include/clang/Tooling/Refactoring/RefactoringOption.h b/include/clang/Tooling/Refactoring/RefactoringOption.h new file mode 100644 index 000000000000..5011223cce69 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringOption.h @@ -0,0 +1,64 @@ +//===--- RefactoringOption.h - Clang refactoring library ------------------===// +// +// 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_REFACTOR_REFACTORING_OPTION_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H + +#include "clang/Basic/LLVM.h" +#include <memory> +#include <type_traits> + +namespace clang { +namespace tooling { + +class RefactoringOptionVisitor; + +/// A refactoring option is an interface that describes a value that +/// has an impact on the outcome of a refactoring. +/// +/// Refactoring options can be specified using command-line arguments when +/// the clang-refactor tool is used. +class RefactoringOption { +public: + virtual ~RefactoringOption() {} + + /// Returns the name of the refactoring option. + /// + /// Each refactoring option must have a unique name. + virtual StringRef getName() const = 0; + + virtual StringRef getDescription() const = 0; + + /// True when this option must be specified before invoking the refactoring + /// action. + virtual bool isRequired() const = 0; + + /// Invokes the \c visit method in the option consumer that's appropriate + /// for the option's value type. + /// + /// For example, if the option stores a string value, this method will + /// invoke the \c visit method with a reference to an std::string value. + virtual void passToVisitor(RefactoringOptionVisitor &Visitor) = 0; +}; + +/// Constructs a refactoring option of the given type. +/// +/// The ownership of options is shared among requirements that use it because +/// one option can be used by multiple rules in a refactoring action. +template <typename OptionType> +std::shared_ptr<OptionType> createRefactoringOption() { + static_assert(std::is_base_of<RefactoringOption, OptionType>::value, + "invalid option type"); + return std::make_shared<OptionType>(); +} + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H diff --git a/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h b/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h new file mode 100644 index 000000000000..aea8fa549392 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h @@ -0,0 +1,62 @@ +//===--- RefactoringOptionVisitor.h - Clang refactoring library -----------===// +// +// 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_REFACTOR_REFACTORING_OPTION_VISITOR_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H + +#include "clang/Basic/LLVM.h" +#include <type_traits> + +namespace clang { +namespace tooling { + +class RefactoringOption; + +/// An interface that declares functions that handle different refactoring +/// option types. +/// +/// A valid refactoring option type must have a corresponding \c visit +/// declaration in this interface. +class RefactoringOptionVisitor { +public: + virtual ~RefactoringOptionVisitor() {} + + virtual void visit(const RefactoringOption &Opt, + Optional<std::string> &Value) = 0; +}; + +namespace traits { +namespace internal { + +template <typename T> struct HasHandle { +private: + template <typename ClassT> + static auto check(ClassT *) -> typename std::is_same< + decltype(std::declval<RefactoringOptionVisitor>().visit( + std::declval<RefactoringOption>(), *std::declval<Optional<T> *>())), + void>::type; + + template <typename> static std::false_type check(...); + +public: + using Type = decltype(check<RefactoringOptionVisitor>(nullptr)); +}; + +} // end namespace internal + +/// A type trait that returns true iff the given type is a type that can be +/// stored in a refactoring option. +template <typename T> +struct IsValidOptionType : internal::HasHandle<T>::Type {}; + +} // end namespace traits +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H diff --git a/include/clang/Tooling/Refactoring/RefactoringOptions.h b/include/clang/Tooling/Refactoring/RefactoringOptions.h new file mode 100644 index 000000000000..e45c0a09fd67 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringOptions.h @@ -0,0 +1,58 @@ +//===--- RefactoringOptions.h - Clang refactoring library -----------------===// +// +// 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_REFACTOR_REFACTORING_OPTIONS_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h" +#include "clang/Tooling/Refactoring/RefactoringOption.h" +#include "clang/Tooling/Refactoring/RefactoringOptionVisitor.h" +#include "llvm/Support/Error.h" +#include <type_traits> + +namespace clang { +namespace tooling { + +/// A refactoring option that stores a value of type \c T. +template <typename T, typename = typename std::enable_if< + traits::IsValidOptionType<T>::value>::type> +class OptionalRefactoringOption : public RefactoringOption { +public: + void passToVisitor(RefactoringOptionVisitor &Visitor) final override { + Visitor.visit(*this, Value); + } + + bool isRequired() const override { return false; } + + using ValueType = Optional<T>; + + const ValueType &getValue() const { return Value; } + +protected: + Optional<T> Value; +}; + +/// A required refactoring option that stores a value of type \c T. +template <typename T, typename = typename std::enable_if< + traits::IsValidOptionType<T>::value>::type> +class RequiredRefactoringOption : public OptionalRefactoringOption<T> { +public: + using ValueType = T; + + const ValueType &getValue() const { + return *OptionalRefactoringOption<T>::Value; + } + bool isRequired() const final override { return true; } +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H diff --git a/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h b/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h new file mode 100644 index 000000000000..fe7738e73499 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h @@ -0,0 +1,52 @@ +//===--- RefactoringResultConsumer.h - Clang refactoring library ----------===// +// +// 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_REFACTOR_REFACTORING_RESULT_CONSUMER_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H + +#include "clang/Basic/LLVM.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h" +#include "llvm/Support/Error.h" + +namespace clang { +namespace tooling { + +/// An abstract interface that consumes the various refactoring results that can +/// be produced by refactoring actions. +/// +/// A valid refactoring result must be handled by a \c handle method. +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. + virtual void handleError(llvm::Error Err) = 0; + + /// Handles the source replacements that are produced by a refactoring action. + virtual void handle(AtomicChanges SourceReplacements) { + defaultResultHandler(); + } + + /// Handles the symbol occurrences that are found by an interactive + /// refactoring action. + virtual void handle(SymbolOccurrences Occurrences) { defaultResultHandler(); } + +private: + void defaultResultHandler() { + handleError(llvm::make_error<llvm::StringError>( + "unsupported refactoring result", llvm::inconvertibleErrorCode())); + } +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H diff --git a/include/clang/Tooling/Refactoring/RefactoringRuleContext.h b/include/clang/Tooling/Refactoring/RefactoringRuleContext.h new file mode 100644 index 000000000000..882ab824b639 --- /dev/null +++ b/include/clang/Tooling/Refactoring/RefactoringRuleContext.h @@ -0,0 +1,90 @@ +//===--- RefactoringRuleContext.h - Clang refactoring library -------------===// +// +// 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_REFACTOR_REFACTORING_RULE_CONTEXT_H +#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H + +#include "clang/Basic/DiagnosticError.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Tooling/Refactoring/ASTSelection.h" + +namespace clang { + +class ASTContext; + +namespace tooling { + +/// The refactoring rule context stores all of the inputs that might be needed +/// by a refactoring action rule. It can create the specialized +/// \c ASTRefactoringOperation or \c PreprocessorRefactoringOperation values +/// that can be used by the refactoring action rules. +/// +/// The following inputs are stored by the operation: +/// +/// - SourceManager: a reference to a valid source manager. +/// +/// - SelectionRange: an optional source selection ranges that can be used +/// to represent a selection in an editor. +class RefactoringRuleContext { +public: + RefactoringRuleContext(const SourceManager &SM) : SM(SM) {} + + const SourceManager &getSources() const { return SM; } + + /// Returns the current source selection range as set by the + /// refactoring engine. Can be invalid. + SourceRange getSelectionRange() const { return SelectionRange; } + + void setSelectionRange(SourceRange R) { SelectionRange = R; } + + bool hasASTContext() const { return AST; } + + ASTContext &getASTContext() const { + assert(AST && "no AST!"); + return *AST; + } + + void setASTContext(ASTContext &Context) { AST = &Context; } + + /// Creates an llvm::Error value that contains a diagnostic. + /// + /// The errors should not outlive the context. + llvm::Error createDiagnosticError(SourceLocation Loc, unsigned DiagID) { + return DiagnosticError::create(Loc, PartialDiagnostic(DiagID, DiagStorage)); + } + + llvm::Error createDiagnosticError(unsigned DiagID) { + return createDiagnosticError(SourceLocation(), DiagID); + } + + void setASTSelection(std::unique_ptr<SelectedASTNode> Node) { + ASTNodeSelection = std::move(Node); + } + +private: + /// The source manager for the translation unit / file on which a refactoring + /// action might operate on. + const SourceManager &SM; + /// An optional source selection range that's commonly used to represent + /// a selection in an editor. + SourceRange SelectionRange; + /// An optional AST for the translation unit on which a refactoring action + /// might operate on. + ASTContext *AST = nullptr; + /// The allocator for diagnostics. + PartialDiagnostic::StorageAllocator DiagStorage; + + // FIXME: Remove when memoized. + std::unique_ptr<SelectedASTNode> ASTNodeSelection; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H diff --git a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h index 099eaca6c42a..734b624d777b 100644 --- a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h +++ b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h @@ -16,6 +16,11 @@ #define LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H #include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Refactoring/RefactoringActionRules.h" +#include "clang/Tooling/Refactoring/RefactoringOptions.h" +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h" +#include "llvm/Support/Error.h" namespace clang { class ASTConsumer; @@ -42,6 +47,53 @@ private: bool PrintLocations; }; +class RenameOccurrences final : public SourceChangeRefactoringRule { +public: + static Expected<RenameOccurrences> initiate(RefactoringRuleContext &Context, + SourceRange SelectionRange, + std::string NewName); + + static const RefactoringDescriptor &describe(); + +private: + RenameOccurrences(const NamedDecl *ND, std::string NewName) + : ND(ND), NewName(std::move(NewName)) {} + + Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) override; + + const NamedDecl *ND; + std::string NewName; +}; + +class QualifiedRenameRule final : public SourceChangeRefactoringRule { +public: + static Expected<QualifiedRenameRule> initiate(RefactoringRuleContext &Context, + std::string OldQualifiedName, + std::string NewQualifiedName); + + static const RefactoringDescriptor &describe(); + +private: + QualifiedRenameRule(const NamedDecl *ND, + std::string NewQualifiedName) + : ND(ND), NewQualifiedName(std::move(NewQualifiedName)) {} + + Expected<AtomicChanges> + createSourceReplacements(RefactoringRuleContext &Context) override; + + // A NamedDecl which indentifies the the symbol being renamed. + const NamedDecl *ND; + // The new qualified name to change the symbol to. + std::string NewQualifiedName; +}; + +/// Returns source replacements that correspond to the rename of the given +/// symbol occurrences. +llvm::Expected<std::vector<AtomicChange>> +createRenameReplacements(const SymbolOccurrences &Occurrences, + const SourceManager &SM, const SymbolName &NewName); + /// Rename all symbols identified by the given USRs. class QualifiedRenamingAction { public: diff --git a/include/clang/Tooling/Refactoring/Rename/SymbolName.h b/include/clang/Tooling/Refactoring/Rename/SymbolName.h new file mode 100644 index 000000000000..e69d2908b5d3 --- /dev/null +++ b/include/clang/Tooling/Refactoring/Rename/SymbolName.h @@ -0,0 +1,49 @@ +//===--- SymbolName.h - Clang refactoring library -------------------------===// +// +// 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_REFACTOR_RENAME_SYMBOL_NAME_H +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { +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: +/// +/// \code +/// - (void) myMethodNamePiece: (int)x anotherNamePieces:(int)y; +/// // ^~ string 0 ~~~~~ ^~ string 1 ~~~~~ +/// \endcode +class SymbolName { +public: + explicit SymbolName(StringRef Name) { + // While empty symbol names are valid (Objective-C selectors can have empty + // name pieces), occurrences Objective-C selectors are created using an + // array of strings instead of just one string. + assert(!Name.empty() && "Invalid symbol name!"); + this->Name.push_back(Name.str()); + } + + ArrayRef<std::string> getNamePieces() const { return Name; } + +private: + llvm::SmallVector<std::string, 1> Name; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H diff --git a/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h b/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h new file mode 100644 index 000000000000..0f853011978f --- /dev/null +++ b/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h @@ -0,0 +1,91 @@ +//===--- SymbolOccurrences.h - Clang refactoring library ------------------===// +// +// 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_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace clang { +namespace tooling { + +class SymbolName; + +/// An occurrence of a symbol in the source. +/// +/// Occurrences can have difference kinds, that describe whether this occurrence +/// is an exact semantic match, or whether this is a weaker textual match that's +/// not guaranteed to represent the exact declaration. +/// +/// A single occurrence of a symbol can span more than one source range. For +/// example, Objective-C selectors can contain multiple argument labels: +/// +/// \code +/// [object selectorPiece1: ... selectorPiece2: ...]; +/// // ^~~ range 0 ~~ ^~~ range 1 ~~ +/// \endcode +/// +/// We have to replace the text in both range 0 and range 1 when renaming the +/// Objective-C method 'selectorPiece1:selectorPiece2'. +class SymbolOccurrence { +public: + enum OccurrenceKind { + /// This occurrence is an exact match and can be renamed automatically. + /// + /// Note: + /// Symbol occurrences in macro arguments that expand to different + /// declarations get marked as exact matches, and thus the renaming engine + /// will rename them e.g.: + /// + /// \code + /// #define MACRO(x) x + ns::x + /// int foo(int var) { + /// return MACRO(var); // var is renamed automatically here when + /// // either var or ns::var is renamed. + /// }; + /// \endcode + /// + /// The user will have to fix their code manually after performing such a + /// rename. + /// FIXME: The rename verifier should notify user about this issue. + MatchingSymbol + }; + + SymbolOccurrence(const SymbolName &Name, OccurrenceKind Kind, + ArrayRef<SourceLocation> Locations); + + SymbolOccurrence(SymbolOccurrence &&) = default; + SymbolOccurrence &operator=(SymbolOccurrence &&) = default; + + OccurrenceKind getKind() const { return Kind; } + + ArrayRef<SourceRange> getNameRanges() const { + if (MultipleRanges) { + return llvm::makeArrayRef(MultipleRanges.get(), + RangeOrNumRanges.getBegin().getRawEncoding()); + } + return RangeOrNumRanges; + } + +private: + OccurrenceKind Kind; + std::unique_ptr<SourceRange[]> MultipleRanges; + SourceRange RangeOrNumRanges; +}; + +using SymbolOccurrences = std::vector<SymbolOccurrence>; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H diff --git a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h index 8aafee95bc09..f1c5ae60f875 100644 --- a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h +++ b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h @@ -23,11 +23,25 @@ namespace clang { class ASTConsumer; +class ASTContext; class CompilerInstance; class NamedDecl; namespace tooling { +/// Returns the canonical declaration that best represents a symbol that can be +/// renamed. +/// +/// The following canonicalization rules are currently used: +/// +/// - A constructor is canonicalized to its class. +/// - A destructor is canonicalized to its class. +const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl); + +/// Returns the set of USRs that correspond to the given declaration. +std::vector<std::string> getUSRsForDeclaration(const NamedDecl *ND, + ASTContext &Context); + struct USRFindingAction { USRFindingAction(ArrayRef<unsigned> SymbolOffsets, ArrayRef<std::string> QualifiedNames, bool Force) diff --git a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h index 733ea1a6ac9e..801a8ad9e99c 100644 --- a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h +++ b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h @@ -19,6 +19,7 @@ #include "clang/AST/AST.h" #include "clang/Tooling/Core/Replacement.h" #include "clang/Tooling/Refactoring/AtomicChange.h" +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h" #include "llvm/ADT/StringRef.h" #include <string> #include <vector> @@ -38,10 +39,13 @@ std::vector<tooling::AtomicChange> createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs, llvm::StringRef NewName, Decl *TranslationUnitDecl); -// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree! -std::vector<SourceLocation> -getLocationsOfUSRs(const std::vector<std::string> &USRs, - llvm::StringRef PrevName, Decl *Decl); +/// Finds the symbol occurrences for the symbol that's identified by the given +/// USR set. +/// +/// \return SymbolOccurrences that can be converted to AtomicChanges when +/// renaming. +SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs, + StringRef PrevName, Decl *Decl); } // end namespace tooling } // end namespace clang diff --git a/include/clang/Tooling/StandaloneExecution.h b/include/clang/Tooling/StandaloneExecution.h new file mode 100644 index 000000000000..f5f32d737a45 --- /dev/null +++ b/include/clang/Tooling/StandaloneExecution.h @@ -0,0 +1,97 @@ +//===--- StandaloneExecution.h - Standalone execution. -*- 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 standalone execution of clang tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H +#define LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H + +#include "clang/Tooling/ArgumentsAdjusters.h" +#include "clang/Tooling/Execution.h" + +namespace clang { +namespace tooling { + +/// \brief 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 +/// in `clang/Tooling/ArgumentsAdjusters.h`): +/// - `getClangStripOutputAdjuster()` +/// - `getClangSyntaxOnlyAdjuster()` +/// - `getClangStripDependencyFileAdjuster()` +class StandaloneToolExecutor : public ToolExecutor { +public: + static const char *ExecutorName; + + /// \brief Init with \p CompilationDatabase and the paths of all files to be + /// proccessed. + StandaloneToolExecutor( + const CompilationDatabase &Compilations, + llvm::ArrayRef<std::string> SourcePaths, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + /// \brief Init with \p CommonOptionsParser. This is expected to be used by + /// `createExecutorFromCommandLineArgs` based on commandline options. + /// + /// The executor takes ownership of \p Options. + StandaloneToolExecutor( + CommonOptionsParser Options, + 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; + + /// \brief Set a \c DiagnosticConsumer to use during parsing. + void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { + Tool.setDiagnosticConsumer(DiagConsumer); + } + + ExecutionContext *getExecutionContext() override { return &Context; }; + + ToolResults *getToolResults() override { return &Results; } + + llvm::ArrayRef<std::string> getSourcePaths() const { + return Tool.getSourcePaths(); + } + + void mapVirtualFile(StringRef FilePath, StringRef Content) override { + Tool.mapVirtualFile(FilePath, Content); + } + + /// \brief Returns the file manager used in the tool. + /// + /// The file manager is shared between all translation units. + FileManager &getFiles() { return Tool.getFiles(); } + +private: + // Used to store the parser when the executor is initialized with parser. + llvm::Optional<CommonOptionsParser> OptionsParser; + // FIXME: The standalone executor is currently just a wrapper of `ClangTool`. + // Merge `ClangTool` implementation into the this. + ClangTool Tool; + ExecutionContext Context; + InMemoryToolResults Results; + ArgumentsAdjuster ArgsAdjuster; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H diff --git a/include/clang/Tooling/ToolExecutorPluginRegistry.h b/include/clang/Tooling/ToolExecutorPluginRegistry.h new file mode 100644 index 000000000000..11ba89546e9e --- /dev/null +++ b/include/clang/Tooling/ToolExecutorPluginRegistry.h @@ -0,0 +1,24 @@ +//===--- ToolExecutorPluginRegistry.h - -------------------------*- 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_TOOLEXECUTORPLUGINREGISTRY_H +#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H + +#include "clang/Tooling/Execution.h" +#include "llvm/Support/Registry.h" + +namespace clang { +namespace tooling { + +typedef llvm::Registry<ToolExecutorPlugin> ToolExecutorPluginRegistry; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 6f9bc9e1a150..e64be07d9ab4 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -31,12 +31,12 @@ #define LLVM_CLANG_TOOLING_TOOLING_H #include "clang/AST/ASTConsumer.h" -#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Util.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" @@ -337,7 +337,9 @@ class ClangTool { /// The file manager is shared between all translation units. FileManager &getFiles() { return *Files; } - private: + llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; } + +private: const CompilationDatabase &Compilations; std::vector<std::string> SourcePaths; std::shared_ptr<PCHContainerOperations> PCHContainerOps; diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap index d850bd552e1f..4097ad2dc716 100644 --- a/include/clang/module.modulemap +++ b/include/clang/module.modulemap @@ -49,6 +49,7 @@ module Clang_Basic { textual header "Basic/OperatorKinds.def" textual header "Basic/Sanitizers.def" textual header "Basic/TokenKinds.def" + textual header "Basic/X86Target.def" module * { export * } } @@ -69,9 +70,9 @@ module Clang_Diagnostics { module Frontend { header "Frontend/FrontendDiagnostic.h" export * } module Lex { header "Lex/LexDiagnostic.h" export * } module Parse { header "Parse/ParseDiagnostic.h" export * } - // FIXME: This breaks the build of Clang_Sema, for unknown reasons. - //module Sema { header "Sema/SemaDiagnostic.h" export * } + module Sema { header "Sema/SemaDiagnostic.h" export * } module Serialization { header "Serialization/SerializationDiagnostic.h" export * } + module Refactoring { header "Tooling/Refactoring/RefactoringDiagnostic.h" export * } } module Clang_Driver { @@ -90,7 +91,6 @@ module Clang_Frontend { requires cplusplus umbrella "Frontend" - textual header "Frontend/CodeGenOptions.def" textual header "Frontend/LangStandards.def" module * { export * } @@ -99,11 +99,20 @@ module Clang_Frontend { exclude header "Frontend/PCHContainerOperations.h" } +// Used in clangBasic +module Clang_Frontend_CodeGenOptions { + requires cplusplus + header "Frontend/CodeGenOptions.h" + textual header "Frontend/CodeGenOptions.def" + export * +} + module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } } module Clang_Index { requires cplusplus umbrella "Index" module * { export * } } module Clang_Lex { requires cplusplus umbrella "Lex" module * { export * } } module Clang_Parse { requires cplusplus umbrella "Parse" module * { export * } } -module Clang_Rewrite { requires cplusplus umbrella "Rewrite" module * { export * } } +module Clang_Rewrite { requires cplusplus umbrella "Rewrite/Core" module * { export * } } +module Clang_RewriteFrontend { requires cplusplus umbrella "Rewrite/Frontend" module * { export * } } module Clang_Sema { requires cplusplus umbrella "Sema" module * { export * } } module Clang_Serialization { requires cplusplus umbrella "Serialization" module * { export * } } @@ -139,3 +148,8 @@ module Clang_Tooling { // matchers (and thus the AST), which clang-format should not have. exclude header "Tooling/RefactoringCallbacks.h" } + +module Clang_ToolingCore { + requires cplusplus + umbrella "Tooling/Core" module * { export * } +} |