diff options
author | dim <dim@FreeBSD.org> | 2015-12-30 11:49:41 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-12-30 11:49:41 +0000 |
commit | 3176e97f130184ece0e1a21352c8124cc83ff24a (patch) | |
tree | 0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /include/clang/AST | |
parent | 1e9b8d38881c3213d1e67b0c47ab9b2c00721a5c (diff) | |
download | FreeBSD-src-3176e97f130184ece0e1a21352c8124cc83ff24a.zip FreeBSD-src-3176e97f130184ece0e1a21352c8124cc83ff24a.tar.gz |
Vendor import of clang trunk r256633:
https://llvm.org/svn/llvm-project/cfe/trunk@256633
Diffstat (limited to 'include/clang/AST')
40 files changed, 4231 insertions, 4826 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a2bd55a..b66009e 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -28,6 +28,7 @@ #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/Module.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SanitizerBlacklist.h" @@ -70,6 +71,7 @@ namespace clang { class VTableContextBase; namespace Builtin { class Context; } + enum BuiltinTemplateKind : int; namespace comments { class FullComment; @@ -176,8 +178,9 @@ class ASTContext : public RefCountedBase<ASTContext> { ClassScopeSpecializationPattern; /// \brief Mapping from materialized temporaries with static storage duration - /// that appear in constant initializers to their evaluated values. - llvm::DenseMap<const MaterializeTemporaryExpr*, APValue> + /// that appear in constant initializers to their evaluated values. These are + /// allocated in a std::map because their address must be stable. + llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *> MaterializedTemporaryValues; /// \brief Representation of a "canonical" template template parameter that @@ -215,6 +218,9 @@ class ASTContext : public RefCountedBase<ASTContext> { /// __builtin_va_list type. mutable TypedefDecl *BuiltinVaListDecl; + /// The typedef for the predefined \c __builtin_ms_va_list type. + mutable TypedefDecl *BuiltinMSVaListDecl; + /// \brief The typedef for the predefined \c id type. mutable TypedefDecl *ObjCIdDecl; @@ -242,6 +248,9 @@ class ASTContext : public RefCountedBase<ASTContext> { /// The identifier 'NSCopying'. IdentifierInfo *NSCopyingName = nullptr; + /// The identifier '__make_integer_seq'. + mutable IdentifierInfo *MakeIntegerSeqName = nullptr; + QualType ObjCConstantStringType; mutable RecordDecl *CFConstantStringTypeDecl; @@ -395,6 +404,7 @@ private: TranslationUnitDecl *TUDecl; mutable ExternCContextDecl *ExternCContext; + mutable BuiltinTemplateDecl *MakeIntegerSeqDecl; /// \brief The associated SourceManager object.a SourceManager &SourceMgr; @@ -433,6 +443,7 @@ private: friend class CXXRecordDecl; const TargetInfo *Target; + const TargetInfo *AuxTarget; clang::PrintingPolicy PrintingPolicy; public: @@ -446,10 +457,59 @@ public: /// \brief Contains parents of a node. typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector; - /// \brief Maps from a node to its parents. + /// \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::PointerUnion<ast_type_traits::DynTypedNode *, - ParentVector *>> ParentMap; + llvm::PointerUnion4<const Decl *, const Stmt *, + ast_type_traits::DynTypedNode *, + ParentVector *>> ParentMapPointers; + + /// 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; + + /// Container for either a single DynTypedNode or for an ArrayRef to + /// DynTypedNode. For use with ParentMap. + class DynTypedNodeList { + typedef ast_type_traits::DynTypedNode DynTypedNode; + llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode, + ArrayRef<DynTypedNode>> Storage; + bool IsSingleNode; + + public: + DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { + new (Storage.buffer) DynTypedNode(N); + } + DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) { + new (Storage.buffer) ArrayRef<DynTypedNode>(A); + } + + const ast_type_traits::DynTypedNode *begin() const { + if (!IsSingleNode) + return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) + ->begin(); + return reinterpret_cast<const DynTypedNode *>(Storage.buffer); + } + + const ast_type_traits::DynTypedNode *end() const { + if (!IsSingleNode) + return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) + ->end(); + return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1; + } + + size_t size() const { return end() - begin(); } + bool empty() const { return begin() == end(); } + const DynTypedNode &operator[](size_t N) const { + assert(N < size() && "Out of bounds!"); + return *(begin() + N); + } + }; /// \brief Returns the parents of the given node. /// @@ -475,13 +535,11 @@ public: /// /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, /// NestedNameSpecifier or NestedNameSpecifierLoc. - template <typename NodeT> - ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) { + template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) { return getParents(ast_type_traits::DynTypedNode::create(Node)); } - ArrayRef<ast_type_traits::DynTypedNode> - getParents(const ast_type_traits::DynTypedNode &Node); + DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node); const clang::PrintingPolicy &getPrintingPolicy() const { return PrintingPolicy; @@ -501,6 +559,9 @@ public: void *Allocate(size_t Size, unsigned Align = 8) const { return BumpAlloc.Allocate(Size, Align); } + template <typename T> T *Allocate(size_t Num = 1) const { + return static_cast<T *>(Allocate(Num * sizeof(T), llvm::alignOf<T>())); + } void Deallocate(void *Ptr) const { } /// Return the total amount of physical memory allocated for representing @@ -516,7 +577,8 @@ public: } const TargetInfo &getTargetInfo() const { return *Target; } - + const TargetInfo *getAuxTargetInfo() const { return AuxTarget; } + /// getIntTypeForBitwidth - /// sets integer QualTy according to specified details: /// bitwidth, signed/unsigned. @@ -812,6 +874,7 @@ public: TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } ExternCContextDecl *getExternCContextDecl() const; + BuiltinTemplateDecl *getMakeIntegerSeqDecl() const; // Builtin Types. CanQualType VoidTy; @@ -835,17 +898,21 @@ public: CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; CanQualType ObjCBuiltinBoolTy; CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy; - CanQualType OCLImage2dTy, OCLImage2dArrayTy; + CanQualType OCLImage2dTy, OCLImage2dArrayTy, OCLImage2dDepthTy; + CanQualType OCLImage2dArrayDepthTy, OCLImage2dMSAATy, OCLImage2dArrayMSAATy; + CanQualType OCLImage2dMSAADepthTy, OCLImage2dArrayMSAADepthTy; CanQualType OCLImage3dTy; - CanQualType OCLSamplerTy, OCLEventTy; + CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy; + CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy; + CanQualType OMPArraySectionTy; // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'. - // Type used to help define __builtin_va_list for some targets. - // The type is built when constructing 'BuiltinVaListDecl'. - mutable QualType VaListTagTy; + // Decl used to help define __builtin_va_list for some targets. + // The decl is built when constructing 'BuiltinVaListDecl'. + mutable Decl *VaListTagDecl; ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins); @@ -881,6 +948,9 @@ public: void PrintStats() const; const SmallVectorImpl<Type *>& getTypes() const { return Types; } + BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK, + const IdentifierInfo *II) const; + /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl /// declaration. RecordDecl *buildImplicitRecord(StringRef Name, @@ -955,6 +1025,9 @@ public: const FunctionType *adjustFunctionType(const FunctionType *Fn, FunctionType::ExtInfo EInfo); + /// Adjust the given function result type. + CanQualType getCanonicalFunctionResultType(QualType ResultType) const; + /// \brief Change the result type of a function type once it is deduced. void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); @@ -1227,7 +1300,7 @@ public: UnaryTransformType::UTTKind UKind) const; /// \brief C++11 deduced auto type. - QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto, + QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent) const; /// \brief C++11 deduction pattern for 'auto' type. @@ -1381,6 +1454,12 @@ public: return NSCopyingName; } + IdentifierInfo *getMakeIntegerSeqName() const { + if (!MakeIntegerSeqName) + MakeIntegerSeqName = &Idents.get("__make_integer_seq"); + return MakeIntegerSeqName; + } + /// \brief Retrieve the Objective-C "instancetype" type, if already known; /// otherwise, returns a NULL type; QualType getObjCInstanceType() { @@ -1569,7 +1648,16 @@ public: /// \brief Retrieve the C type declaration corresponding to the predefined /// \c __va_list_tag type used to help define the \c __builtin_va_list type /// for some targets. - QualType getVaListTagType() const; + Decl *getVaListTagDecl() const; + + /// Retrieve the C type declaration corresponding to the predefined + /// \c __builtin_ms_va_list type. + TypedefDecl *getBuiltinMSVaListDecl() const; + + /// Retrieve the type of the \c __builtin_ms_va_list type. + QualType getBuiltinMSVaListType() const { + return getTypeDeclType(getBuiltinMSVaListDecl()); + } /// \brief Return a type with additional \c const, \c volatile, or /// \c restrict qualifiers. @@ -1774,7 +1862,6 @@ public: /// record (struct/union/class) \p D, which indicates its size and field /// position information. const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const; - const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const; /// \brief Get or compute information about the layout of the specified /// Objective-C interface. @@ -2170,9 +2257,7 @@ public: const FunctionProtoType *FromFunctionType, const FunctionProtoType *ToFunctionType); - void ResetObjCLayout(const ObjCContainerDecl *CD) { - ObjCLayouts[CD] = nullptr; - } + void ResetObjCLayout(const ObjCContainerDecl *CD); //===--------------------------------------------------------------------===// // Integer Predicates @@ -2188,16 +2273,6 @@ public: QualType getCorrespondingUnsignedType(QualType T) const; //===--------------------------------------------------------------------===// - // Type Iterators. - //===--------------------------------------------------------------------===// - typedef llvm::iterator_range<SmallVectorImpl<Type *>::const_iterator> - type_const_range; - - type_const_range types() const { - return type_const_range(Types.begin(), Types.end()); - } - - //===--------------------------------------------------------------------===// // Integer Values //===--------------------------------------------------------------------===// @@ -2233,16 +2308,11 @@ public: /// \brief Get the duplicate declaration of a ObjCMethod in the same /// interface, or null if none exists. - const ObjCMethodDecl *getObjCMethodRedeclaration( - const ObjCMethodDecl *MD) const { - return ObjCMethodRedecls.lookup(MD); - } + const ObjCMethodDecl * + getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const; void setObjCMethodRedeclaration(const ObjCMethodDecl *MD, - const ObjCMethodDecl *Redecl) { - assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration"); - ObjCMethodRedecls[MD] = Redecl; - } + const ObjCMethodDecl *Redecl); /// \brief Returns the Objective-C interface that \p ND belongs to if it is /// an Objective-C method/property/ivar etc. that is part of an interface, @@ -2307,6 +2377,14 @@ public: Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD, unsigned ParmIdx); + void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND); + + TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD); + + void addDeclaratorForUnnamedTagDecl(TagDecl *TD, DeclaratorDecl *DD); + + DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD); + void setManglingNumber(const NamedDecl *ND, unsigned Number); unsigned getManglingNumber(const NamedDecl *ND) const; @@ -2388,9 +2466,10 @@ public: /// This routine may only be invoked once for a given ASTContext object. /// It is normally invoked after ASTContext construction. /// - /// \param Target The target - void InitBuiltinTypes(const TargetInfo &Target); - + /// \param Target The target + void InitBuiltinTypes(const TargetInfo &Target, + const TargetInfo *AuxTarget = nullptr); + private: void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); @@ -2429,9 +2508,15 @@ private: /// \brief A set of deallocations that should be performed when the /// ASTContext is destroyed. - typedef llvm::SmallDenseMap<void(*)(void*), llvm::SmallVector<void*, 16> > - DeallocationMap; - DeallocationMap Deallocations; + // FIXME: We really should have a better mechanism in the ASTContext to + // manage running destructors for types which do variable sized allocation + // within the AST. In some places we thread the AST bump pointer allocator + // 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; + DeallocationFunctionsAndArguments Deallocations; // FIXME: This currently contains the set of StoredDeclMaps used // by DeclContext objects. This probably should not be in ASTContext, @@ -2443,7 +2528,8 @@ private: void ReleaseDeclContextMaps(); void ReleaseParentMapEntries(); - std::unique_ptr<ParentMap> AllParents; + std::unique_ptr<ParentMapPointers> PointerParents; + std::unique_ptr<ParentMapOtherNodes> OtherParents; std::unique_ptr<VTableContextBase> VTContext; diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index f4026e9..3ff392d 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -92,18 +92,6 @@ public: virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) {} - /// \brief A objc class extension redeclared or introduced a property. - /// - /// \param Prop the property in the class extension - /// - /// \param OrigProp the property from the original interface that was declared - /// or null if the property was introduced. - /// - /// \param ClassExt the class extension. - virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, - const ObjCPropertyDecl *OrigProp, - const ObjCCategoryDecl *ClassExt) {} - /// \brief A declaration is marked used which was not previously marked used. /// /// \param D the declaration marked used diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index dc3c34f..dcaac80 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -106,18 +106,25 @@ public: } }; + /// Check if the given ASTNodeKind identifies a type that offers pointer + /// identity. This is useful for the fast path in DynTypedNode. + bool hasPointerIdentity() const { + return KindId > NKI_LastKindWithoutPointerIdentity; + } + private: /// \brief Kind ids. /// /// Includes all possible base and derived kinds. enum NodeKindId { NKI_None, - NKI_CXXCtorInitializer, NKI_TemplateArgument, - NKI_NestedNameSpecifier, NKI_NestedNameSpecifierLoc, NKI_QualType, NKI_TypeLoc, + NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, + NKI_CXXCtorInitializer, + NKI_NestedNameSpecifier, NKI_Decl, #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, #include "clang/AST/DeclNodes.inc" @@ -238,7 +245,11 @@ public: /// Note that this is not supported by all AST nodes. For AST nodes /// that don't have a pointer-defined identity inside the AST, this /// method returns NULL. - const void *getMemoizationData() const { return MemoizationData; } + const void *getMemoizationData() const { + return NodeKind.hasPointerIdentity() + ? *reinterpret_cast<void *const *>(Storage.buffer) + : nullptr; + } /// \brief Prints the node to the given output stream. void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; @@ -257,6 +268,32 @@ public: /// FIXME: Implement comparsion for other node types (currently /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data). bool operator<(const DynTypedNode &Other) const { + if (!NodeKind.isSame(Other.NodeKind)) + return NodeKind < Other.NodeKind; + + if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) + return getUnchecked<QualType>().getAsOpaquePtr() < + Other.getUnchecked<QualType>().getAsOpaquePtr(); + + if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) { + auto TLA = getUnchecked<TypeLoc>(); + auto TLB = Other.getUnchecked<TypeLoc>(); + return std::make_pair(TLA.getType().getAsOpaquePtr(), + TLA.getOpaqueData()) < + std::make_pair(TLB.getType().getAsOpaquePtr(), + TLB.getOpaqueData()); + } + + if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( + NodeKind)) { + auto NNSLA = getUnchecked<NestedNameSpecifierLoc>(); + auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>(); + return std::make_pair(NNSLA.getNestedNameSpecifier(), + NNSLA.getOpaqueData()) < + std::make_pair(NNSLB.getNestedNameSpecifier(), + NNSLB.getOpaqueData()); + } + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() < Other.getMemoizationData(); } @@ -270,6 +307,13 @@ public: if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); + if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) + return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>(); + + if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind)) + return getUnchecked<NestedNameSpecifierLoc>() == + Other.getUnchecked<NestedNameSpecifierLoc>(); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() == Other.getMemoizationData(); } @@ -278,6 +322,47 @@ public: } /// @} + /// \brief Hooks for using DynTypedNode as a key in a DenseMap. + struct DenseMapInfo { + static inline DynTypedNode getEmptyKey() { + DynTypedNode Node; + Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey(); + return Node; + } + static inline DynTypedNode getTombstoneKey() { + DynTypedNode Node; + Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey(); + return Node; + } + static unsigned getHashValue(const DynTypedNode &Val) { + // FIXME: Add hashing support for the remaining types. + if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) { + auto TL = Val.getUnchecked<TypeLoc>(); + return llvm::hash_combine(TL.getType().getAsOpaquePtr(), + TL.getOpaqueData()); + } + + if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( + Val.NodeKind)) { + auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>(); + return llvm::hash_combine(NNSL.getNestedNameSpecifier(), + NNSL.getOpaqueData()); + } + + assert(Val.getMemoizationData()); + return llvm::hash_value(Val.getMemoizationData()); + } + static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) { + auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey(); + auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey(); + return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) && + ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) || + (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) && + ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) || + LHS == RHS; + } + }; + private: /// \brief Takes care of converting from and to \c T. template <typename T, typename EnablerT = void> struct BaseConverter; @@ -286,18 +371,18 @@ private: template <typename T, typename BaseT> struct DynCastPtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) - return cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + return &getUnchecked(NodeKind, Storage); return nullptr; } static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); - return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + return *cast<T>(static_cast<const BaseT *>( + *reinterpret_cast<const void *const *>(Storage))); } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNode(Node); - Result.MemoizationData = &Node; - new (Result.Storage.buffer) const BaseT * (&Node); + new (Result.Storage.buffer) const void *(&Node); return Result; } }; @@ -306,18 +391,18 @@ private: template <typename T> struct PtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) - return *reinterpret_cast<T *const *>(Storage); + return &getUnchecked(NodeKind, Storage); return nullptr; } static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); - return **reinterpret_cast<T *const *>(Storage); + return *static_cast<const T *>( + *reinterpret_cast<const void *const *>(Storage)); } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); - Result.MemoizationData = &Node; - new (Result.Storage.buffer) const T * (&Node); + new (Result.Storage.buffer) const void *(&Node); return Result; } }; @@ -336,14 +421,12 @@ private: static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); - Result.MemoizationData = nullptr; new (Result.Storage.buffer) T(Node); return Result; } }; ASTNodeKind NodeKind; - const void *MemoizationData; /// \brief Stores the data of the node. /// @@ -353,12 +436,9 @@ private: /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and /// \c TemplateArguments on the other hand do not have storage or unique /// pointers and thus need to be stored by value. - typedef llvm::AlignedCharArrayUnion< - Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *> - KindsByPointer; - llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument, - NestedNameSpecifierLoc, QualType, TypeLoc> - Storage; + llvm::AlignedCharArrayUnion<const void *, TemplateArgument, + NestedNameSpecifierLoc, QualType, + TypeLoc> Storage; }; template <typename T> @@ -420,6 +500,10 @@ template <> struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; +template <> +struct DenseMapInfo<clang::ast_type_traits::DynTypedNode> + : clang::ast_type_traits::DynTypedNode::DenseMapInfo {}; + } // end namespace llvm #endif diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 4e282d6..8b80e9f 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -56,21 +56,21 @@ protected: bool IsLateParsed : 1; bool DuplicatesAllowed : 1; - void* operator new(size_t bytes) throw() { + void *operator new(size_t bytes) LLVM_NOEXCEPT { llvm_unreachable("Attrs cannot be allocated with regular 'new'."); } - void operator delete(void* data) throw() { + void operator delete(void *data) LLVM_NOEXCEPT { llvm_unreachable("Attrs cannot be released with regular 'delete'."); } public: // Forward so that the regular new and delete do not hide global ones. - void* operator new(size_t Bytes, ASTContext &C, - size_t Alignment = 8) throw() { + void *operator new(size_t Bytes, ASTContext &C, + size_t Alignment = 8) LLVM_NOEXCEPT { return ::operator new(Bytes, C, Alignment); } void operator delete(void *Ptr, ASTContext &C, - size_t Alignment) throw() { + size_t Alignment) LLVM_NOEXCEPT { return ::operator delete(Ptr, C, Alignment); } diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index 488cace..85e237a 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -160,6 +160,12 @@ BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy) BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy) BUILTIN_TYPE(OCLImage2d, OCLImage2dTy) BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy) +BUILTIN_TYPE(OCLImage2dDepth, OCLImage2dDepthTy) +BUILTIN_TYPE(OCLImage2dArrayDepth, OCLImage2dArrayDepthTy) +BUILTIN_TYPE(OCLImage2dMSAA, OCLImage2dMSAATy) +BUILTIN_TYPE(OCLImage2dArrayMSAA, OCLImage2dArrayMSAATy) +BUILTIN_TYPE(OCLImage2dMSAADepth, OCLImage2dMSAADepthTy) +BUILTIN_TYPE(OCLImage2dArrayMSAADepth, OCLImage2dArrayMSAADepthTy) BUILTIN_TYPE(OCLImage3d, OCLImage3dTy) // OpenCL sampler_t. @@ -168,6 +174,18 @@ BUILTIN_TYPE(OCLSampler, OCLSamplerTy) // OpenCL event_t. BUILTIN_TYPE(OCLEvent, OCLEventTy) +// OpenCL clk_event_t. +BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy) + +// OpenCL queue_t. +BUILTIN_TYPE(OCLQueue, OCLQueueTy) + +// OpenCL ndrange_t. +BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy) + +// OpenCL reserve_id_t. +BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy) + // This represents the type of an expression whose type is // totally unknown, e.g. 'T::foo'. It is permitted for this to // appear in situations where the structure of the type is @@ -227,8 +245,11 @@ PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy) // context. PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy) +// A placeholder type for OpenMP array sections. +PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy) + #ifdef LAST_BUILTIN_TYPE -LAST_BUILTIN_TYPE(ARCUnbridgedCast) +LAST_BUILTIN_TYPE(OMPArraySection) #undef LAST_BUILTIN_TYPE #endif diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index f7612f2..8587260 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -155,17 +155,16 @@ class CXXBasePaths { /// \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. - NamedDecl **DeclsFound; + std::unique_ptr<NamedDecl *[]> DeclsFound; unsigned NumDeclsFound; friend class CXXRecordDecl; void ComputeDeclsFound(); - bool lookupInBases(ASTContext &Context, - const CXXRecordDecl *Record, - CXXRecordDecl::BaseMatchesCallback *BaseMatches, - void *UserData); + bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record, + CXXRecordDecl::BaseMatchesCallback BaseMatches); + public: typedef std::list<CXXBasePath>::iterator paths_iterator; typedef std::list<CXXBasePath>::const_iterator const_paths_iterator; @@ -173,15 +172,12 @@ public: /// BasePaths - Construct a new BasePaths structure to record the /// paths for a derived-to-base search. - explicit CXXBasePaths(bool FindAmbiguities = true, - bool RecordPaths = true, + explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true, bool DetectVirtual = true) - : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), - DetectVirtual(DetectVirtual), DetectedVirtual(nullptr), - DeclsFound(nullptr), NumDeclsFound(0) { } - - ~CXXBasePaths() { delete [] DeclsFound; } - + : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), + DetectVirtual(DetectVirtual), DetectedVirtual(nullptr), + NumDeclsFound(0) {} + paths_iterator begin() { return Paths.begin(); } paths_iterator end() { return Paths.end(); } const_paths_iterator begin() const { return Paths.begin(); } diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 72ca9f5..1d22bcc 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -130,6 +130,14 @@ namespace clang { return (Quantity & -Quantity) == Quantity; } + /// Test whether this is a multiple of the other value. + /// + /// Among other things, this promises that + /// self.RoundUpToAlignment(N) will just return self. + bool isMultipleOf(CharUnits N) const { + return (*this % N) == 0; + } + // Arithmetic operators. CharUnits operator* (QuantityType N) const { return CharUnits(Quantity * N); @@ -172,10 +180,20 @@ namespace clang { /// Given that this is a non-zero alignment value, what is the /// alignment at the given offset? - CharUnits alignmentAtOffset(CharUnits offset) { + CharUnits alignmentAtOffset(CharUnits offset) const { + assert(Quantity != 0 && "offsetting from unknown alignment?"); return CharUnits(llvm::MinAlign(Quantity, offset.Quantity)); } + /// Given that this is the alignment of the first element of an + /// array, return the minimum alignment of any element in the array. + CharUnits alignmentOfArrayElement(CharUnits elementSize) const { + // Since we don't track offsetted alignments, the alignment of + // the second element (or any odd element) will be minimally + // aligned. + return alignmentAtOffset(elementSize); + } + }; // class CharUnit } // namespace clang diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 9b05d39..6a80383 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -79,12 +79,8 @@ public: /// Returns a copy of array, owned by Sema's allocator. template<typename T> ArrayRef<T> copyArray(ArrayRef<T> Source) { - size_t Size = Source.size(); - if (Size != 0) { - T *Mem = Allocator.Allocate<T>(Size); - std::uninitialized_copy(Source.begin(), Source.end(), Mem); - return llvm::makeArrayRef(Mem, Size); - } + if (!Source.empty()) + return Source.copy(Allocator); return None; } diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h deleted file mode 100644 index dd167fe..0000000 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ /dev/null @@ -1,2691 +0,0 @@ -//===--- DataRecursiveASTVisitor.h - Data-Recursive AST Visitor -*- 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 DataRecursiveASTVisitor interface, which recursively -// traverses the entire AST, using data recursion for Stmts/Exprs. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H -#define LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_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/DeclOpenMP.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/StmtOpenMP.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/TemplateName.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLoc.h" - -// The following three macros are used for meta programming. The code -// using them is responsible for defining macro OPERATOR(). - -// All unary operators. -#define UNARYOP_LIST() \ - OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \ - OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \ - OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) - -// All binary operators (excluding compound assign operators). -#define BINOP_LIST() \ - 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) - -// All compound assign operators. -#define CAO_LIST() \ - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ - OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) - -namespace clang { - -// Reduce the diff between RecursiveASTVisitor / DataRecursiveASTVisitor to -// make it easier to track changes and keep the two in sync. -#define RecursiveASTVisitor DataRecursiveASTVisitor - -// A helper macro to implement short-circuiting when recursing. It -// invokes CALL_EXPR, which must be a method call, on the derived -// object (s.t. a user of RecursiveASTVisitor can override the method -// in CALL_EXPR). -#define TRY_TO(CALL_EXPR) \ - do { \ - if (!getDerived().CALL_EXPR) \ - return false; \ - } while (0) - -/// \brief A class that does preorder depth-first traversal on the -/// entire Clang AST and visits each node. -/// -/// This class performs three distinct tasks: -/// 1. traverse the AST (i.e. go to each node); -/// 2. at a given node, walk up the class hierarchy, starting from -/// the node's dynamic type, until the top-most class (e.g. Stmt, -/// Decl, or Type) is reached. -/// 3. given a (node, class) combination, where 'class' is some base -/// class of the dynamic type of 'node', call a user-overridable -/// function to actually visit the node. -/// -/// These tasks are done by three groups of methods, respectively: -/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point -/// for traversing an AST rooted at x. This method simply -/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo -/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and -/// then recursively visits the child nodes of x. -/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work -/// similarly. -/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit -/// any child node of x. Instead, it first calls WalkUpFromBar(x) -/// where Bar is the direct parent class of Foo (unless Foo has -/// no parent), and then calls VisitFoo(x) (see the next list item). -/// 3. VisitFoo(Foo *x) does task #3. -/// -/// These three method groups are tiered (Traverse* > WalkUpFrom* > -/// Visit*). A method (e.g. Traverse*) may call methods from the same -/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). -/// It may not call methods from a higher tier. -/// -/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar -/// is Foo's super class) before calling VisitFoo(), the result is -/// that the Visit*() methods for a given node are called in the -/// top-down order (e.g. for a node of type NamespaceDecl, the order will -/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). -/// -/// This scheme guarantees that all Visit*() calls for the same AST -/// node are grouped together. In other words, Visit*() methods for -/// different nodes are never interleaved. -/// -/// Stmts are traversed internally using a data queue to avoid a stack overflow -/// with hugely nested ASTs. -/// -/// Clients of this visitor should subclass the visitor (providing -/// themselves as the template argument, using the curiously recurring -/// template pattern) and override any of the Traverse*, WalkUpFrom*, -/// and Visit* methods for declarations, types, statements, -/// expressions, or other AST nodes where the visitor should customize -/// behavior. Most users only need to override Visit*. Advanced -/// users may override Traverse* and WalkUpFrom* to implement custom -/// traversal strategies. Returning false from one of these overridden -/// functions will abort the entire traversal. -/// -/// By default, this visitor tries to visit every part of the explicit -/// source code exactly once. The default policy towards templates -/// is to descend into the 'pattern' class or function body, not any -/// explicit or implicit instantiations. Explicit specializations -/// are still visited, and the patterns of partial specializations -/// are visited separately. This behavior can be changed by -/// overriding shouldVisitTemplateInstantiations() in the derived class -/// to return true, in which case all known implicit and explicit -/// instantiations will be visited at the same time as the pattern -/// from which they were produced. -template <typename Derived> class RecursiveASTVisitor { -public: - /// \brief Return a reference to the derived class. - Derived &getDerived() { return *static_cast<Derived *>(this); } - - /// \brief Return whether this visitor should recurse into - /// template instantiations. - bool shouldVisitTemplateInstantiations() const { return false; } - - /// \brief Return whether this visitor should recurse into the types of - /// TypeLocs. - bool shouldWalkTypesOfTypeLocs() const { return true; } - - /// \brief Recursively visit a statement or expression, by - /// dispatching to Traverse*() based on the argument's dynamic type. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is NULL). - bool TraverseStmt(Stmt *S); - - /// \brief Recursively visit a type, by dispatching to - /// Traverse*Type() based on the argument's getTypeClass() property. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is a Null type). - bool TraverseType(QualType T); - - /// \brief Recursively visit a type with location, by dispatching to - /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is a Null type location). - bool TraverseTypeLoc(TypeLoc TL); - - /// \brief Recursively visit an attribute, by dispatching to - /// Traverse*Attr() based on the argument's dynamic type. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is a Null type location). - bool TraverseAttr(Attr *At); - - /// \brief Recursively visit a declaration, by dispatching to - /// Traverse*Decl() based on the argument's dynamic type. - /// - /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is NULL). - bool TraverseDecl(Decl *D); - - /// \brief Recursively visit a C++ nested-name-specifier. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); - - /// \brief Recursively visit a C++ nested-name-specifier with location - /// information. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); - - /// \brief Recursively visit a name with its location information. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); - - /// \brief Recursively visit a template name and dispatch to the - /// appropriate method. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseTemplateName(TemplateName Template); - - /// \brief Recursively visit a template argument and dispatch to the - /// appropriate method for the argument type. - /// - /// \returns false if the visitation was terminated early, true otherwise. - // FIXME: migrate callers to TemplateArgumentLoc instead. - bool TraverseTemplateArgument(const TemplateArgument &Arg); - - /// \brief Recursively visit a template argument location and dispatch to the - /// appropriate method for the argument type. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); - - /// \brief Recursively visit a set of template arguments. - /// This can be overridden by a subclass, but it's not expected that - /// will be needed -- this visitor always dispatches to another. - /// - /// \returns false if the visitation was terminated early, true otherwise. - // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. - bool TraverseTemplateArguments(const TemplateArgument *Args, - unsigned NumArgs); - - /// \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 - /// be overridden for clients that need access to the name. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseConstructorInitializer(CXXCtorInitializer *Init); - - /// \brief Recursively visit a lambda capture. - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C); - - /// \brief Recursively visit the body of a lambda expression. - /// - /// This provides a hook for visitors that need more context when visiting - /// \c LE->getBody(). - /// - /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaBody(LambdaExpr *LE); - - // ---- Methods on Attrs ---- - - // \brief Visit an attribute. - bool VisitAttr(Attr *A) { return true; } - -// Declare Traverse* and empty Visit* for all Attr classes. -#define ATTR_VISITOR_DECLS_ONLY -#include "clang/AST/AttrVisitor.inc" -#undef ATTR_VISITOR_DECLS_ONLY - -// ---- Methods on Stmts ---- - -// Declare Traverse*() for all concrete Stmt classes. -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S); -#include "clang/AST/StmtNodes.inc" - // The above header #undefs ABSTRACT_STMT and STMT upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. - bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } - bool VisitStmt(Stmt *S) { return true; } -#define STMT(CLASS, PARENT) \ - bool WalkUpFrom##CLASS(CLASS *S) { \ - TRY_TO(WalkUpFrom##PARENT(S)); \ - TRY_TO(Visit##CLASS(S)); \ - return true; \ - } \ - bool Visit##CLASS(CLASS *S) { return true; } -#include "clang/AST/StmtNodes.inc" - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary -// operator methods. Unary operators are not classes in themselves -// (they're all opcodes in UnaryOperator) but do have visitors. -#define OPERATOR(NAME) \ - bool TraverseUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnary##NAME(S)); \ - StmtQueueAction StmtQueue(*this); \ - StmtQueue.queue(S->getSubExpr()); \ - return true; \ - } \ - bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnaryOperator(S)); \ - TRY_TO(VisitUnary##NAME(S)); \ - return true; \ - } \ - bool VisitUnary##NAME(UnaryOperator *S) { return true; } - - UNARYOP_LIST() -#undef OPERATOR - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary -// operator methods. Binary operators are not classes in themselves -// (they're all opcodes in BinaryOperator) but do have visitors. -#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ - bool TraverseBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFromBin##NAME(S)); \ - StmtQueueAction StmtQueue(*this); \ - StmtQueue.queue(S->getLHS()); \ - StmtQueue.queue(S->getRHS()); \ - return true; \ - } \ - bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ - TRY_TO(VisitBin##NAME(S)); \ - return true; \ - } \ - bool VisitBin##NAME(BINOP_TYPE *S) { return true; } - -#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) - BINOP_LIST() -#undef OPERATOR - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound -// assignment methods. Compound assignment operators are not -// classes in themselves (they're all opcodes in -// CompoundAssignOperator) but do have visitors. -#define OPERATOR(NAME) \ - GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) - - CAO_LIST() -#undef OPERATOR -#undef GENERAL_BINOP_FALLBACK - -// ---- Methods on Types ---- -// FIXME: revamp to take TypeLoc's rather than Types. - -// Declare Traverse*() for all concrete Type classes. -#define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); -#include "clang/AST/TypeNodes.def" - // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Type classes. - bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } - bool VisitType(Type *T) { return true; } -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ - TRY_TO(WalkUpFrom##BASE(T)); \ - TRY_TO(Visit##CLASS##Type(T)); \ - return true; \ - } \ - bool Visit##CLASS##Type(CLASS##Type *T) { return true; } -#include "clang/AST/TypeNodes.def" - -// ---- Methods on TypeLocs ---- -// FIXME: this currently just calls the matching Type methods - -// Declare Traverse*() for all concrete TypeLoc classes. -#define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); -#include "clang/AST/TypeLocNodes.def" - // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. - bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } - bool VisitTypeLoc(TypeLoc TL) { return true; } - - // QualifiedTypeLoc and UnqualTypeLoc are not declared in - // TypeNodes.def and thus need to be handled specially. - bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { - return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); - } - bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } - bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { - return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); - } - bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } - -// Note that BASE includes trailing 'Type' which CLASS doesn't. -#define TYPE(CLASS, BASE) \ - bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ - TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ - TRY_TO(Visit##CLASS##TypeLoc(TL)); \ - return true; \ - } \ - bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } -#include "clang/AST/TypeNodes.def" - -// ---- Methods on Decls ---- - -// Declare Traverse*() for all concrete Decl classes. -#define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D); -#include "clang/AST/DeclNodes.inc" - // The above header #undefs ABSTRACT_DECL and DECL upon exit. - - // Define WalkUpFrom*() and empty Visit*() for all Decl classes. - bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } - bool VisitDecl(Decl *D) { return true; } -#define DECL(CLASS, BASE) \ - bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ - TRY_TO(WalkUpFrom##BASE(D)); \ - TRY_TO(Visit##CLASS##Decl(D)); \ - return true; \ - } \ - bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } -#include "clang/AST/DeclNodes.inc" - -private: - // These are helper methods used by more than one Traverse* method. - bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - bool TraverseClassInstantiations(ClassTemplateDecl *D); - bool TraverseVariableInstantiations(VarTemplateDecl *D); - bool TraverseFunctionInstantiations(FunctionTemplateDecl *D); - bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, - unsigned Count); - bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); - bool TraverseRecordHelper(RecordDecl *D); - bool TraverseCXXRecordHelper(CXXRecordDecl *D); - bool TraverseDeclaratorHelper(DeclaratorDecl *D); - bool TraverseDeclContextHelper(DeclContext *DC); - bool TraverseFunctionHelper(FunctionDecl *D); - bool TraverseVarHelper(VarDecl *D); - bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); - bool TraverseOMPLoopDirective(OMPLoopDirective *S); - bool TraverseOMPClause(OMPClause *C); -#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); -#include "clang/Basic/OpenMPKinds.def" - /// \brief Process clauses with list of variables. - template <typename T> bool VisitOMPClauseList(T *Node); - - typedef SmallVector<Stmt *, 16> StmtsTy; - typedef SmallVector<StmtsTy *, 4> QueuesTy; - - QueuesTy Queues; - - class NewQueueRAII { - RecursiveASTVisitor &RAV; - - public: - NewQueueRAII(StmtsTy &queue, RecursiveASTVisitor &RAV) : RAV(RAV) { - RAV.Queues.push_back(&queue); - } - ~NewQueueRAII() { RAV.Queues.pop_back(); } - }; - - StmtsTy &getCurrentQueue() { - assert(!Queues.empty() && "base TraverseStmt was never called?"); - return *Queues.back(); - } - -public: - class StmtQueueAction { - StmtsTy &CurrQueue; - - public: - explicit StmtQueueAction(RecursiveASTVisitor &RAV) - : CurrQueue(RAV.getCurrentQueue()) {} - - void queue(Stmt *S) { CurrQueue.push_back(S); } - }; -}; - -#define DISPATCH(NAME, CLASS, VAR) \ - return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { - if (!S) - return true; - - StmtsTy Queue, StmtsToEnqueue; - Queue.push_back(S); - NewQueueRAII NQ(StmtsToEnqueue, *this); - - while (!Queue.empty()) { - S = Queue.pop_back_val(); - if (!S) - continue; - - StmtsToEnqueue.clear(); - -#define DISPATCH_STMT(NAME, CLASS, VAR) \ - TRY_TO(Traverse##NAME(static_cast<CLASS *>(VAR))); \ - break - - // 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. - if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { - switch (BinOp->getOpcode()) { -#define OPERATOR(NAME) \ - case BO_##NAME: \ - DISPATCH_STMT(Bin##NAME, BinaryOperator, S); - - BINOP_LIST() -#undef OPERATOR -#undef BINOP_LIST - -#define OPERATOR(NAME) \ - case BO_##NAME##Assign: \ - DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); - - CAO_LIST() -#undef OPERATOR -#undef CAO_LIST - } - } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { - switch (UnOp->getOpcode()) { -#define OPERATOR(NAME) \ - case UO_##NAME: \ - DISPATCH_STMT(Unary##NAME, UnaryOperator, S); - - UNARYOP_LIST() -#undef OPERATOR -#undef UNARYOP_LIST - } - } else { - - // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. - switch (S->getStmtClass()) { - case Stmt::NoStmtClass: - break; -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - case Stmt::CLASS##Class: \ - DISPATCH_STMT(CLASS, CLASS, S); -#include "clang/AST/StmtNodes.inc" - } - } - - Queue.append(StmtsToEnqueue.rbegin(), StmtsToEnqueue.rend()); - } - - return true; -} - -#undef DISPATCH_STMT - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { - if (T.isNull()) - return true; - - switch (T->getTypeClass()) { -#define ABSTRACT_TYPE(CLASS, BASE) -#define TYPE(CLASS, BASE) \ - case Type::CLASS: \ - DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr())); -#include "clang/AST/TypeNodes.def" - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { - if (TL.isNull()) - return true; - - switch (TL.getTypeLocClass()) { -#define ABSTRACT_TYPELOC(CLASS, BASE) -#define TYPELOC(CLASS, BASE) \ - case TypeLoc::CLASS: \ - return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>()); -#include "clang/AST/TypeLocNodes.def" - } - - return true; -} - -// Define the Traverse*Attr(Attr* A) methods -#define VISITORCLASS RecursiveASTVisitor -#include "clang/AST/AttrVisitor.inc" -#undef VISITORCLASS - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { - if (!D) - return true; - - // As a syntax visitor, we want to ignore declarations for - // implicitly-defined declarations (ones not typed explicitly by the - // user). - if (D->isImplicit()) - return true; - - switch (D->getKind()) { -#define ABSTRACT_DECL(DECL) -#define DECL(CLASS, BASE) \ - case Decl::CLASS: \ - if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \ - return false; \ - break; -#include "clang/AST/DeclNodes.inc" - } - - // Visit any attributes attached to this declaration. - for (auto *I : D->attrs()) { - if (!getDerived().TraverseAttr(I)) - return false; - } - return true; -} - -#undef DISPATCH - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( - NestedNameSpecifier *NNS) { - if (!NNS) - return true; - - if (NNS->getPrefix()) - TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - return true; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( - NestedNameSpecifierLoc NNS) { - if (!NNS) - return true; - - if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) - TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); - - switch (NNS.getNestedNameSpecifier()->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - return true; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); - break; - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo( - DeclarationNameInfo NameInfo) { - switch (NameInfo.getName().getNameKind()) { - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) - TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc())); - - break; - - case DeclarationName::Identifier: - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - case DeclarationName::CXXOperatorName: - case DeclarationName::CXXLiteralOperatorName: - case DeclarationName::CXXUsingDirective: - break; - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { - if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) - TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); - else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( - const TemplateArgument &Arg) { - switch (Arg.getKind()) { - case TemplateArgument::Null: - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - case TemplateArgument::NullPtr: - return true; - - case TemplateArgument::Type: - return getDerived().TraverseType(Arg.getAsType()); - - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Expression: - return getDerived().TraverseStmt(Arg.getAsExpr()); - - case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); - } - - return true; -} - -// FIXME: no template name location? -// FIXME: no source locations for a template argument pack? -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( - const TemplateArgumentLoc &ArgLoc) { - const TemplateArgument &Arg = ArgLoc.getArgument(); - - switch (Arg.getKind()) { - case TemplateArgument::Null: - case TemplateArgument::Declaration: - case TemplateArgument::Integral: - case TemplateArgument::NullPtr: - return true; - - case TemplateArgument::Type: { - // FIXME: how can TSI ever be NULL? - if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) - return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); - else - return getDerived().TraverseType(Arg.getAsType()); - } - - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - if (ArgLoc.getTemplateQualifierLoc()) - TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( - ArgLoc.getTemplateQualifierLoc())); - return getDerived().TraverseTemplateName( - Arg.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Expression: - return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); - - case TemplateArgument::Pack: - return getDerived().TraverseTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( - const TemplateArgument *Args, unsigned NumArgs) { - for (unsigned I = 0; I != NumArgs; ++I) { - TRY_TO(TraverseTemplateArgument(Args[I])); - } - - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( - CXXCtorInitializer *Init) { - if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); - - if (Init->isWritten()) - TRY_TO(TraverseStmt(Init->getInit())); - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, - const LambdaCapture *C) { - if (LE->isInitCapture(C)) - TRY_TO(TraverseDecl(C->getCapturedVar())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) { - StmtQueueAction StmtQueue(*this); - StmtQueue.queue(LE->getBody()); - return true; -} - -// ----------------- Type traversal ----------------- - -// This macro makes available a variable T, the passed-in type. -#define DEF_TRAVERSE_TYPE(TYPE, CODE) \ - template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \ - TRY_TO(WalkUpFrom##TYPE(T)); \ - { CODE; } \ - return true; \ - } - -DEF_TRAVERSE_TYPE(BuiltinType, {}) - -DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(BlockPointerType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(LValueReferenceType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(RValueReferenceType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(MemberPointerType, { - TRY_TO(TraverseType(QualType(T->getClass(), 0))); - TRY_TO(TraverseType(T->getPointeeType())); -}) - -DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) - -DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) - -DEF_TRAVERSE_TYPE(ConstantArrayType, - { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(IncompleteArrayType, - { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(VariableArrayType, { - TRY_TO(TraverseType(T->getElementType())); - TRY_TO(TraverseStmt(T->getSizeExpr())); -}) - -DEF_TRAVERSE_TYPE(DependentSizedArrayType, { - TRY_TO(TraverseType(T->getElementType())); - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); -}) - -DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { - if (T->getSizeExpr()) - TRY_TO(TraverseStmt(T->getSizeExpr())); - TRY_TO(TraverseType(T->getElementType())); -}) - -DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) - -DEF_TRAVERSE_TYPE(FunctionNoProtoType, - { TRY_TO(TraverseType(T->getReturnType())); }) - -DEF_TRAVERSE_TYPE(FunctionProtoType, { - TRY_TO(TraverseType(T->getReturnType())); - - for (const auto &A : T->param_types()) { - TRY_TO(TraverseType(A)); - } - - for (const auto &E : T->exceptions()) { - TRY_TO(TraverseType(E)); - } - - if (Expr *NE = T->getNoexceptExpr()) - TRY_TO(TraverseStmt(NE)); -}) - -DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) -DEF_TRAVERSE_TYPE(TypedefType, {}) - -DEF_TRAVERSE_TYPE(TypeOfExprType, - { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) - -DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); }) - -DEF_TRAVERSE_TYPE(DecltypeType, - { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); }) - -DEF_TRAVERSE_TYPE(UnaryTransformType, { - TRY_TO(TraverseType(T->getBaseType())); - TRY_TO(TraverseType(T->getUnderlyingType())); -}) - -DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); }) - -DEF_TRAVERSE_TYPE(RecordType, {}) -DEF_TRAVERSE_TYPE(EnumType, {}) -DEF_TRAVERSE_TYPE(TemplateTypeParmType, {}) -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {}) -DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {}) - -DEF_TRAVERSE_TYPE(TemplateSpecializationType, { - TRY_TO(TraverseTemplateName(T->getTemplateName())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); -}) - -DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) - -DEF_TRAVERSE_TYPE(AttributedType, - { TRY_TO(TraverseType(T->getModifiedType())); }) - -DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); }) - -DEF_TRAVERSE_TYPE(ElaboratedType, { - if (T->getQualifier()) { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - } - TRY_TO(TraverseType(T->getNamedType())); -}) - -DEF_TRAVERSE_TYPE(DependentNameType, - { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); }) - -DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); -}) - -DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); }) - -DEF_TRAVERSE_TYPE(ObjCInterfaceType, {}) - -DEF_TRAVERSE_TYPE(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (T->getBaseType().getTypePtr() != T) - TRY_TO(TraverseType(T->getBaseType())); - for (auto typeArg : T->getTypeArgsAsWritten()) { - TRY_TO(TraverseType(typeArg)); - } -}) - -DEF_TRAVERSE_TYPE(ObjCObjectPointerType, - { TRY_TO(TraverseType(T->getPointeeType())); }) - -DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) - -#undef DEF_TRAVERSE_TYPE - -// ----------------- TypeLoc traversal ----------------- - -// This macro makes available a variable TL, the passed-in TypeLoc. -// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc, -// in addition to WalkUpFrom* for the TypeLoc itself, such that existing -// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods -// continue to work. -#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ - template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ - if (getDerived().shouldWalkTypesOfTypeLocs()) \ - TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ - TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ - { CODE; } \ - return true; \ - } - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { - // Move this over to the 'main' typeloc tree. Note that this is a - // move -- we pretend that we were really looking at the unqualified - // typeloc all along -- rather than a recursion, so we don't follow - // the normal CRTP plan of going through - // getDerived().TraverseTypeLoc. If we did, we'd be traversing - // twice for the same type (once as a QualifiedTypeLoc version of - // the type, once as an UnqualifiedTypeLoc version of the type), - // which in effect means we'd call VisitTypeLoc twice with the - // 'same' type. This solves that problem, at the cost of never - // seeing the qualified version of the type (unless the client - // subclasses TraverseQualifiedTypeLoc themselves). It's not a - // perfect solution. A perfect solution probably requires making - // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a - // wrapper around Type* -- rather than being its own class in the - // type hierarchy. - return TraverseTypeLoc(TL.getUnqualifiedLoc()); -} - -DEF_TRAVERSE_TYPELOC(BuiltinType, {}) - -// FIXME: ComplexTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(ComplexType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -DEF_TRAVERSE_TYPELOC(PointerType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(BlockPointerType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(LValueReferenceType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(RValueReferenceType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -// FIXME: location of base class? -// We traverse this in the type case as well, but how is it not reached through -// the pointee type? -DEF_TRAVERSE_TYPELOC(MemberPointerType, { - TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); - TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); -}) - -DEF_TRAVERSE_TYPELOC(AdjustedType, - { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) - -DEF_TRAVERSE_TYPELOC(DecayedType, - { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); }) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { - // This isn't available for ArrayType, but is for the ArrayTypeLoc. - TRY_TO(TraverseStmt(TL.getSizeExpr())); - return true; -} - -DEF_TRAVERSE_TYPELOC(ConstantArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -DEF_TRAVERSE_TYPELOC(VariableArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { - TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); -}) - -// FIXME: order? why not size expr first? -// FIXME: base VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { - if (TL.getTypePtr()->getSizeExpr()) - TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -// FIXME: VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(VectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -// FIXME: size and attributes -// FIXME: base VectorTypeLoc is unfinished -DEF_TRAVERSE_TYPELOC(ExtVectorType, { - TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); -}) - -DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, - { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) - -// FIXME: location of exception specifications (attributes?) -DEF_TRAVERSE_TYPELOC(FunctionProtoType, { - TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); - - const FunctionProtoType *T = TL.getTypePtr(); - - for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { - if (TL.getParam(I)) { - TRY_TO(TraverseDecl(TL.getParam(I))); - } else if (I < T->getNumParams()) { - TRY_TO(TraverseType(T->getParamType(I))); - } - } - - for (const auto &E : T->exceptions()) { - TRY_TO(TraverseType(E)); - } - - if (Expr *NE = T->getNoexceptExpr()) - TRY_TO(TraverseStmt(NE)); -}) - -DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) -DEF_TRAVERSE_TYPELOC(TypedefType, {}) - -DEF_TRAVERSE_TYPELOC(TypeOfExprType, - { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); }) - -DEF_TRAVERSE_TYPELOC(TypeOfType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); -}) - -// FIXME: location of underlying expr -DEF_TRAVERSE_TYPELOC(DecltypeType, { - TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); -}) - -DEF_TRAVERSE_TYPELOC(UnaryTransformType, { - TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_TYPELOC(AutoType, { - TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); -}) - -DEF_TRAVERSE_TYPELOC(RecordType, {}) -DEF_TRAVERSE_TYPELOC(EnumType, {}) -DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {}) -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {}) -DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {}) - -// FIXME: use the loc for the template name? -DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { - TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } -}) - -DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {}) - -DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) - -DEF_TRAVERSE_TYPELOC(AttributedType, - { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) - -DEF_TRAVERSE_TYPELOC(ElaboratedType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } - TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); -}) - -DEF_TRAVERSE_TYPELOC(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); -}) - -DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - if (TL.getQualifierLoc()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); - } - - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); - } -}) - -DEF_TRAVERSE_TYPELOC(PackExpansionType, - { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); }) - -DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {}) - -DEF_TRAVERSE_TYPELOC(ObjCObjectType, { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) - TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); - for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i) - TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc())); -}) - -DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, - { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) - -DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) - -#undef DEF_TRAVERSE_TYPELOC - -// ----------------- Decl traversal ----------------- -// -// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing -// the children that come from the DeclContext associated with it. -// Therefore each Traverse* only needs to worry about children other -// than those. - -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)) - TRY_TO(TraverseDecl(Child)); - } - - return true; -} - -// This macro makes available a variable D, the passed-in decl. -#define DEF_TRAVERSE_DECL(DECL, CODE) \ - template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \ - TRY_TO(WalkUpFrom##DECL(D)); \ - { CODE; } \ - TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ - return true; \ - } - -DEF_TRAVERSE_DECL(AccessSpecDecl, {}) - -DEF_TRAVERSE_DECL(BlockDecl, { - if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); - TRY_TO(TraverseStmt(D->getBody())); - for (const auto &I : D->captures()) { - if (I.hasCopyExpr()) { - TRY_TO(TraverseStmt(I.getCopyExpr())); - } - } - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; -}) - -DEF_TRAVERSE_DECL(CapturedDecl, { - TRY_TO(TraverseStmt(D->getBody())); - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; -}) - -DEF_TRAVERSE_DECL(EmptyDecl, {}) - -DEF_TRAVERSE_DECL(FileScopeAsmDecl, - { TRY_TO(TraverseStmt(D->getAsmString())); }) - -DEF_TRAVERSE_DECL(ImportDecl, {}) - -DEF_TRAVERSE_DECL(FriendDecl, { - // Friend is either decl or a type. - if (D->getFriendType()) - TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); - else - TRY_TO(TraverseDecl(D->getFriendDecl())); -}) - -DEF_TRAVERSE_DECL(FriendTemplateDecl, { - if (D->getFriendType()) - TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc())); - else - TRY_TO(TraverseDecl(D->getFriendDecl())); - for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { - TemplateParameterList *TPL = D->getTemplateParameterList(I); - for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end(); - ITPL != ETPL; ++ITPL) { - TRY_TO(TraverseDecl(*ITPL)); - } - } -}) - -DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, - { TRY_TO(TraverseDecl(D->getSpecialization())); }) - -DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) - -DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this - }) - -DEF_TRAVERSE_DECL(StaticAssertDecl, { - TRY_TO(TraverseStmt(D->getAssertExpr())); - TRY_TO(TraverseStmt(D->getMessage())); -}) - -DEF_TRAVERSE_DECL( - TranslationUnitDecl, - {// Code in an unnamed namespace shows up automatically in - // decls_begin()/decls_end(). Thus we don't need to recurse on - // D->getAnonymousNamespace(). - }) - -DEF_TRAVERSE_DECL(ExternCContextDecl, {}) - -DEF_TRAVERSE_DECL(NamespaceAliasDecl, { - // We shouldn't traverse an aliased namespace, since it will be - // defined (and, therefore, traversed) somewhere else. - // - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; -}) - -DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl. - }) - -DEF_TRAVERSE_DECL( - NamespaceDecl, - {// Code in an unnamed namespace shows up automatically in - // decls_begin()/decls_end(). Thus we don't need to recurse on - // D->getAnonymousNamespace(). - }) - -DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement - if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) { - for (auto typeParam : *typeParamList) { - TRY_TO(TraverseObjCTypeParamDecl(typeParam)); - } - } - return true; -}) - -DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement - if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) { - for (auto typeParam : *typeParamList) { - TRY_TO(TraverseObjCTypeParamDecl(typeParam)); - } - } - - if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) { - TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc())); - } -}) - -DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement - }) - -DEF_TRAVERSE_DECL(ObjCMethodDecl, { - if (D->getReturnTypeSourceInfo()) { - TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); - } - for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseStmt(D->getBody())); - } - return true; -}) - -DEF_TRAVERSE_DECL(ObjCTypeParamDecl, { - if (D->hasExplicitBound()) { - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type alias, not something that was written in the - // source. - } -}) - -DEF_TRAVERSE_DECL(ObjCPropertyDecl, { - if (D->getTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - else - TRY_TO(TraverseType(D->getType())); - return true; -}) - -DEF_TRAVERSE_DECL(UsingDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); -}) - -DEF_TRAVERSE_DECL(UsingDirectiveDecl, { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); -}) - -DEF_TRAVERSE_DECL(UsingShadowDecl, {}) - -DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { - for (auto *I : D->varlists()) { - TRY_TO(TraverseStmt(I)); - } -}) - -// A helper method for TemplateDecl's children. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( - TemplateParameterList *TPL) { - if (TPL) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - } - return true; -} - -// A helper method for traversing the implicit instantiations of a -// class template. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations( - ClassTemplateDecl *D) { - for (auto *SD : D->specializations()) { - for (auto *RD : SD->redecls()) { - // We don't want to visit injected-class-names in this traversal. - if (cast<CXXRecordDecl>(RD)->isInjectedClassName()) - continue; - - switch ( - cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(RD)); - break; - - // We don't need to do anything on an explicit instantiation - // or explicit specialization because there will be an explicit - // node for it elsewhere. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitSpecialization: - break; - } - } - } - - return true; -} - -DEF_TRAVERSE_DECL(ClassTemplateDecl, { - CXXRecordDecl *TempDecl = D->getTemplatedDecl(); - TRY_TO(TraverseDecl(TempDecl)); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // class templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the class instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseClassInstantiations(D)); - - // Note that getInstantiatedFromMemberTemplate() is just a link - // from a template instantiation back to the template from which - // it was instantiated, and thus should not be traversed. -}) - -// A helper method for traversing the implicit instantiations of a -// class template. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations( - VarTemplateDecl *D) { - for (auto *SD : D->specializations()) { - for (auto *RD : SD->redecls()) { - switch ( - cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(RD)); - break; - - // We don't need to do anything on an explicit instantiation - // or explicit specialization because there will be an explicit - // node for it elsewhere. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitSpecialization: - break; - } - } - } - - return true; -} - -DEF_TRAVERSE_DECL(VarTemplateDecl, { - VarDecl *TempDecl = D->getTemplatedDecl(); - TRY_TO(TraverseDecl(TempDecl)); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // variable templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the variable instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseVariableInstantiations(D)); - - // Note that getInstantiatedFromMemberTemplate() is just a link - // from a template instantiation back to the template from which - // it was instantiated, and thus should not be traversed. -}) - -// A helper method for traversing the instantiations of a -// function while skipping its specializations. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( - FunctionTemplateDecl *D) { - for (auto *FD : D->specializations()) { - for (auto *RD : FD->redecls()) { - switch (RD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - // We don't know what kind of FunctionDecl this is. - TRY_TO(TraverseDecl(RD)); - break; - - // No need to visit explicit instantiations, we'll find the node - // eventually. - // FIXME: This is incorrect; there is no other node for an explicit - // instantiation of a function template specialization. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - break; - - case TSK_ExplicitSpecialization: - break; - } - } - } - - return true; -} - -DEF_TRAVERSE_DECL(FunctionTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // function templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the function instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseFunctionInstantiations(D)); -}) - -DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { - // D is the "T" in something like - // template <template <typename> class T> class container { }; - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - if (D->hasDefaultArgument()) { - TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); - } - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); -}) - -DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { - // D is the "T" in something like "template<typename T> class vector;" - if (D->getTypeForDecl()) - TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - if (D->hasDefaultArgument()) - TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_DECL(TypedefDecl, { - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the typedef, not something that was written in the - // source. -}) - -DEF_TRAVERSE_DECL(TypeAliasDecl, { - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type alias, not something that was written in the - // source. -}) - -DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); -}) - -DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { - // A dependent using declaration which was marked with 'typename'. - // template<class T> class A : public B<T> { using typename B<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type, not something that was written in the - // source. -}) - -DEF_TRAVERSE_DECL(EnumDecl, { - if (D->getTypeForDecl()) - TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - // The enumerators are already traversed by - // decls_begin()/decls_end(). -}) - -// Helper methods for RecordDecl and its children. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) { - // We shouldn't traverse D->getTypeForDecl(); it's a result of - // declaring the type, not something that was written in the source. - - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - 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())); - } - // We don't traverse the friends or the conversions, as they are - // already in decls_begin()/decls_end(). - } - return true; -} - -DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) - -DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) - -DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, { - // For implicit instantiations ("set<int> x;"), we don't want to - // recurse at all, since the instatiated class isn't written in - // the source code anywhere. (Note the instatiated *type* -- - // set<int> -- is written, and will still get a callback of - // TemplateSpecializationType). For explicit instantiations - // ("template set<int>;"), we do need a callback, since this - // is the only callback that's made for this instantiation. - // We use getTypeAsWritten() to distinguish. - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); - - if (!getDerived().shouldVisitTemplateInstantiations() && - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) - // Returning from here skips traversing the - // declaration context of the ClassTemplateSpecializationDecl - // (embedded in the DEF_TRAVERSE_DECL() macro) - // which contains the instantiated members of the class. - return true; -}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( - const TemplateArgumentLoc *TAL, unsigned Count) { - for (unsigned I = 0; I < Count; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); - } - return true; -} - -DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { - // The partial specialization. - if (TemplateParameterList *TPL = D->getTemplateParameters()) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - } - // The args that remains unspecialized. - TRY_TO(TraverseTemplateArgumentLocsHelper( - D->getTemplateArgsAsWritten()->getTemplateArgs(), - D->getTemplateArgsAsWritten()->NumTemplateArgs)); - - // Don't need the ClassTemplatePartialSpecializationHelper, even - // though that's our parent class -- we already visit all the - // template args here. - TRY_TO(TraverseCXXRecordHelper(D)); - - // Instantiations will have been visited with the primary template. -}) - -DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); }) - -DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { - // Like UnresolvedUsingTypenameDecl, but without the 'typename': - // template <class T> Class A : public Base<T> { using Base<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); -}) - -DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - if (D->getTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - else - TRY_TO(TraverseType(D->getType())); - return true; -} - -DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) - -DEF_TRAVERSE_DECL(FieldDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - else if (D->hasInClassInitializer()) - TRY_TO(TraverseStmt(D->getInClassInitializer())); -}) - -DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - // FIXME: implement the rest. -}) - -DEF_TRAVERSE_DECL(ObjCIvarDecl, { - TRY_TO(TraverseDeclaratorHelper(D)); - if (D->isBitField()) - TRY_TO(TraverseStmt(D->getBitWidth())); - // FIXME: implement the rest. -}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { - TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); - - // If we're an explicit template specialization, iterate over the - // template args that were explicitly specified. If we were doing - // this in typing order, we'd do it between the return type and - // the function args, but both are handled by the FunctionTypeLoc - // above, so we have to choose one side. I've decided to do before. - if (const FunctionTemplateSpecializationInfo *FTSI = - D->getTemplateSpecializationInfo()) { - if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared && - FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { - // A specialization might not have explicit template arguments if it has - // a templated return type and concrete arguments. - if (const ASTTemplateArgumentListInfo *TALI = - FTSI->TemplateArgumentsAsWritten) { - TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(), - TALI->NumTemplateArgs)); - } - } - } - - // Visit the function type itself, which can be either - // FunctionNoProtoType or FunctionProtoType, or a typedef. This - // also covers the return type and the function parameters, - // including exception specifications. - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); - - if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { - // Constructor initializers. - for (auto *I : Ctor->inits()) { - TRY_TO(TraverseConstructorInitializer(I)); - } - } - - if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseStmt(D->getBody())); // Function body. - } - return true; -} - -DEF_TRAVERSE_DECL(FunctionDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -DEF_TRAVERSE_DECL(CXXMethodDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -DEF_TRAVERSE_DECL(CXXConstructorDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -// CXXConversionDecl is the declaration of a type conversion operator. -// It's not a cast expression. -DEF_TRAVERSE_DECL(CXXConversionDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -DEF_TRAVERSE_DECL(CXXDestructorDecl, { - // We skip decls_begin/decls_end, which are already covered by - // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); -}) - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { - TRY_TO(TraverseDeclaratorHelper(D)); - // Default params are taken care of when we traverse the ParmVarDecl. - if (!isa<ParmVarDecl>(D)) - TRY_TO(TraverseStmt(D->getInit())); - return true; -} - -DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); }) - -DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, { - // For implicit instantiations, we don't want to - // recurse at all, since the instatiated class isn't written in - // the source code anywhere. - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); - - if (!getDerived().shouldVisitTemplateInstantiations() && - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) - // Returning from here skips traversing the - // declaration context of the VarTemplateSpecializationDecl - // (embedded in the DEF_TRAVERSE_DECL() macro). - return true; -}) - -DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, { - // The partial specialization. - if (TemplateParameterList *TPL = D->getTemplateParameters()) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - } - // The args that remains unspecialized. - TRY_TO(TraverseTemplateArgumentLocsHelper( - D->getTemplateArgsAsWritten()->getTemplateArgs(), - D->getTemplateArgsAsWritten()->NumTemplateArgs)); - - // Don't need the VarTemplatePartialSpecializationHelper, even - // though that's our parent class -- we already visit all the - // template args here. - TRY_TO(TraverseVarHelper(D)); - - // Instantiations will have been visited with the primary - // template. -}) - -DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); }) - -DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { - // A non-type template parameter, e.g. "S" in template<int S> class Foo ... - TRY_TO(TraverseDeclaratorHelper(D)); - TRY_TO(TraverseStmt(D->getDefaultArgument())); -}) - -DEF_TRAVERSE_DECL(ParmVarDecl, { - TRY_TO(TraverseVarHelper(D)); - - if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() && - !D->hasUnparsedDefaultArg()) - TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); - - if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() && - !D->hasUnparsedDefaultArg()) - TRY_TO(TraverseStmt(D->getDefaultArg())); -}) - -#undef DEF_TRAVERSE_DECL - -// ----------------- Stmt traversal ----------------- -// -// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating -// over the children defined in children() (every stmt defines these, -// though sometimes the range is empty). Each individual Traverse* -// method only needs to worry about children other than those. To see -// what children() does for a given class, see, e.g., -// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html - -// This macro makes available a variable S, the passed-in stmt. -#define DEF_TRAVERSE_STMT(STMT, CODE) \ - template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \ - TRY_TO(WalkUpFrom##STMT(S)); \ - StmtQueueAction StmtQueue(*this); \ - { CODE; } \ - for (Stmt *SubStmt : S->children()) { \ - StmtQueue.queue(SubStmt); \ - } \ - return true; \ - } - -DEF_TRAVERSE_STMT(GCCAsmStmt, { - StmtQueue.queue(S->getAsmString()); - for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { - StmtQueue.queue(S->getInputConstraintLiteral(I)); - } - for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { - StmtQueue.queue(S->getOutputConstraintLiteral(I)); - } - for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { - StmtQueue.queue(S->getClobberStringLiteral(I)); - } - // children() iterates over inputExpr and outputExpr. -}) - -DEF_TRAVERSE_STMT( - MSAsmStmt, - {// FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once - // added this needs to be implemented. - }) - -DEF_TRAVERSE_STMT(CXXCatchStmt, { - TRY_TO(TraverseDecl(S->getExceptionDecl())); - // children() iterates over the handler block. -}) - -DEF_TRAVERSE_STMT(DeclStmt, { - for (auto *I : S->decls()) { - TRY_TO(TraverseDecl(I)); - } - // Suppress the default iteration over children() by - // returning. Here's why: A DeclStmt looks like 'type var [= - // initializer]'. The decls above already traverse over the - // initializers, so we don't have to do it again (which - // children() would do). - return true; -}) - -// These non-expr stmts (most of them), do not need any action except -// iterating over the children. -DEF_TRAVERSE_STMT(BreakStmt, {}) -DEF_TRAVERSE_STMT(CXXTryStmt, {}) -DEF_TRAVERSE_STMT(CaseStmt, {}) -DEF_TRAVERSE_STMT(CompoundStmt, {}) -DEF_TRAVERSE_STMT(ContinueStmt, {}) -DEF_TRAVERSE_STMT(DefaultStmt, {}) -DEF_TRAVERSE_STMT(DoStmt, {}) -DEF_TRAVERSE_STMT(ForStmt, {}) -DEF_TRAVERSE_STMT(GotoStmt, {}) -DEF_TRAVERSE_STMT(IfStmt, {}) -DEF_TRAVERSE_STMT(IndirectGotoStmt, {}) -DEF_TRAVERSE_STMT(LabelStmt, {}) -DEF_TRAVERSE_STMT(AttributedStmt, {}) -DEF_TRAVERSE_STMT(NullStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {}) -DEF_TRAVERSE_STMT(ObjCAtTryStmt, {}) -DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {}) -DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {}) -DEF_TRAVERSE_STMT(CXXForRangeStmt, {}) -DEF_TRAVERSE_STMT(MSDependentExistsStmt, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); -}) -DEF_TRAVERSE_STMT(ReturnStmt, {}) -DEF_TRAVERSE_STMT(SwitchStmt, {}) -DEF_TRAVERSE_STMT(WhileStmt, {}) - -DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(DeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); -}) - -DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper( - S->getExplicitTemplateArgs().getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(MemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo())); - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); -}) - -DEF_TRAVERSE_STMT( - ImplicitCastExpr, - {// We don't traverse the cast type, as it's not written in the - // source code. - }) - -DEF_TRAVERSE_STMT(CStyleCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXConstCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXDynamicCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXStaticCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) - -// InitListExpr is a tricky one, because we want to do all our work on -// the syntactic form of the listexpr, but this method takes the -// semantic form by default. We can't use the macro helper because it -// calls WalkUp*() on the semantic form, before our code can convert -// to the syntactic form. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { - if (InitListExpr *Syn = S->getSyntacticForm()) - S = Syn; - TRY_TO(WalkUpFromInitListExpr(S)); - StmtQueueAction StmtQueue(*this); - // All we need are the default actions. FIXME: use a helper function. - for (Stmt *SubStmt : S->children()) { - StmtQueue.queue(SubStmt); - } - return true; -} - -// GenericSelectionExpr is a special case because the types and expressions -// are interleaved. We also need to watch out for null types (default -// generic associations). -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr( - GenericSelectionExpr *S) { - TRY_TO(WalkUpFromGenericSelectionExpr(S)); - StmtQueueAction StmtQueue(*this); - StmtQueue.queue(S->getControllingExpr()); - for (unsigned i = 0; i != S->getNumAssocs(); ++i) { - if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) - TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); - StmtQueue.queue(S->getAssocExpr(i)); - } - return true; -} - -// PseudoObjectExpr is a special case because of the wierdness with -// syntactic expressions and opaque values. -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) { - TRY_TO(WalkUpFromPseudoObjectExpr(S)); - StmtQueueAction StmtQueue(*this); - StmtQueue.queue(S->getSyntacticForm()); - for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(), - e = S->semantics_end(); - i != e; ++i) { - Expr *sub = *i; - if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub)) - sub = OVE->getSourceExpr(); - StmtQueue.queue(sub); - } - return true; -} - -DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { - // This is called for code like 'return T()' where T is a built-in - // (i.e. non-class) type. - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXNewExpr, { - // The child-iterator will pick up the other arguments. - TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(OffsetOfExpr, { - // The child-iterator will pick up the expression representing - // the field. - // FIMXE: for code like offsetof(Foo, a.b.c), should we get - // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c? - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { - // The child-iterator will pick up the arg if it's an expression, - // but not if it's a type. - if (S->isArgumentType()) - TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXTypeidExpr, { - // The child-iterator will pick up the arg if it's an expression, - // but not if it's a type. - if (S->isTypeOperand()) - TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(MSPropertyRefExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); -}) - -DEF_TRAVERSE_STMT(CXXUuidofExpr, { - // The child-iterator will pick up the arg if it's an expression, - // but not if it's a type. - if (S->isTypeOperand()) - TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(TypeTraitExpr, { - for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) - TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { - TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(ExpressionTraitExpr, - { StmtQueue.queue(S->getQueriedExpression()); }) - -DEF_TRAVERSE_STMT(VAArgExpr, { - // The child-iterator will pick up the expression argument. - TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); -}) - -DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { - // This is called for code like 'return T()' where T is a class type. - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) - -// Walk only the visible parts of lambda expressions. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { - TRY_TO(WalkUpFromLambdaExpr(S)); - - for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), - CEnd = S->explicit_capture_end(); - C != CEnd; ++C) { - TRY_TO(TraverseLambdaCapture(S, C)); - } - - TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>(); - - if (S->hasExplicitParameters() && S->hasExplicitResultType()) { - // Visit the whole type. - TRY_TO(TraverseTypeLoc(TL)); - } else { - if (S->hasExplicitParameters()) { - // Visit parameters. - for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { - TRY_TO(TraverseDecl(Proto.getParam(I))); - } - } else if (S->hasExplicitResultType()) { - TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); - } - - auto *T = Proto.getTypePtr(); - for (const auto &E : T->exceptions()) { - TRY_TO(TraverseType(E)); - } - - if (Expr *NE = T->getNoexceptExpr()) - TRY_TO(TraverseStmt(NE)); - } - - TRY_TO(TraverseLambdaBody(S)); - return true; -} - -DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { - // This is called for code like 'T()', where T is a template argument. - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) - -// These expressions all might take explicit template arguments. -// We traverse those if so. FIXME: implement these. -DEF_TRAVERSE_STMT(CXXConstructExpr, {}) -DEF_TRAVERSE_STMT(CallExpr, {}) -DEF_TRAVERSE_STMT(CXXMemberCallExpr, {}) - -// These exprs (most of them), do not need any action except iterating -// over the children. -DEF_TRAVERSE_STMT(AddrLabelExpr, {}) -DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) -DEF_TRAVERSE_STMT(BlockExpr, { - TRY_TO(TraverseDecl(S->getBlockDecl())); - return true; // no child statements to loop through. -}) -DEF_TRAVERSE_STMT(ChooseExpr, {}) -DEF_TRAVERSE_STMT(CompoundLiteralExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {}) -DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {}) -DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {}) -DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {}) -DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) -DEF_TRAVERSE_STMT(ExprWithCleanups, {}) -DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {}) -DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {}) -DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) - TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc())); - if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo()) - TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(CXXThisExpr, {}) -DEF_TRAVERSE_STMT(CXXThrowExpr, {}) -DEF_TRAVERSE_STMT(UserDefinedLiteral, {}) -DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) -DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {}) -DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) -DEF_TRAVERSE_STMT(GNUNullExpr, {}) -DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) -DEF_TRAVERSE_STMT(NoInitExpr, {}) -DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {}) -DEF_TRAVERSE_STMT(ObjCEncodeExpr, { - if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(ObjCIsaExpr, {}) -DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {}) -DEF_TRAVERSE_STMT(ObjCMessageExpr, { - if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo()) - TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {}) -DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {}) -DEF_TRAVERSE_STMT(ObjCProtocolExpr, {}) -DEF_TRAVERSE_STMT(ObjCSelectorExpr, {}) -DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {}) -DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, { - TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); -}) -DEF_TRAVERSE_STMT(ParenExpr, {}) -DEF_TRAVERSE_STMT(ParenListExpr, {}) -DEF_TRAVERSE_STMT(PredefinedExpr, {}) -DEF_TRAVERSE_STMT(ShuffleVectorExpr, {}) -DEF_TRAVERSE_STMT(ConvertVectorExpr, {}) -DEF_TRAVERSE_STMT(StmtExpr, {}) -DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { - TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); - if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), - S->getNumTemplateArgs())); - } -}) - -DEF_TRAVERSE_STMT(SEHTryStmt, {}) -DEF_TRAVERSE_STMT(SEHExceptStmt, {}) -DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) -DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) -DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) - -DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) -DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) -DEF_TRAVERSE_STMT(TypoExpr, {}) -DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) - -// These operators (all of them) do not need any action except -// iterating over the children. -DEF_TRAVERSE_STMT(BinaryConditionalOperator, {}) -DEF_TRAVERSE_STMT(ConditionalOperator, {}) -DEF_TRAVERSE_STMT(UnaryOperator, {}) -DEF_TRAVERSE_STMT(BinaryOperator, {}) -DEF_TRAVERSE_STMT(CompoundAssignOperator, {}) -DEF_TRAVERSE_STMT(CXXNoexceptExpr, {}) -DEF_TRAVERSE_STMT(PackExpansionExpr, {}) -DEF_TRAVERSE_STMT(SizeOfPackExpr, {}) -DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) -DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) -DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) -DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) -DEF_TRAVERSE_STMT(CXXFoldExpr, {}) -DEF_TRAVERSE_STMT(AtomicExpr, {}) - -// These literals (all of them) do not need any action. -DEF_TRAVERSE_STMT(IntegerLiteral, {}) -DEF_TRAVERSE_STMT(CharacterLiteral, {}) -DEF_TRAVERSE_STMT(FloatingLiteral, {}) -DEF_TRAVERSE_STMT(ImaginaryLiteral, {}) -DEF_TRAVERSE_STMT(StringLiteral, {}) -DEF_TRAVERSE_STMT(ObjCStringLiteral, {}) -DEF_TRAVERSE_STMT(ObjCBoxedExpr, {}) -DEF_TRAVERSE_STMT(ObjCArrayLiteral, {}) -DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {}) - -// Traverse OpenCL: AsType, Convert. -DEF_TRAVERSE_STMT(AsTypeExpr, {}) - -// OpenMP directives. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( - OMPExecutableDirective *S) { - for (auto *C : S->clauses()) { - TRY_TO(TraverseOMPClause(C)); - } - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { - return TraverseOMPExecutableDirective(S); -} - -DEF_TRAVERSE_STMT(OMPParallelDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSimdDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPForDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPForSimdDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSectionsDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSectionDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPSingleDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPMasterDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPCriticalDirective, { - TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); - TRY_TO(TraverseOMPExecutableDirective(S)); -}) - -DEF_TRAVERSE_STMT(OMPParallelForDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskyieldDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPBarrierDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskwaitDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTaskgroupDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPCancellationPointDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPCancelDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPFlushDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPOrderedDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPAtomicDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTargetDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -DEF_TRAVERSE_STMT(OMPTeamsDirective, - { TRY_TO(TraverseOMPExecutableDirective(S)); }) - -// OpenMP clauses. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { - if (!C) - return true; - switch (C->getClauseKind()) { -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_##Name: \ - TRY_TO(Visit##Class(static_cast<Class *>(C))); \ - break; -#include "clang/Basic/OpenMPKinds.def" - case OMPC_threadprivate: - case OMPC_unknown: - break; - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { - TRY_TO(TraverseStmt(C->getCondition())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { - TRY_TO(TraverseStmt(C->getCondition())); - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { - TRY_TO(TraverseStmt(C->getNumThreads())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) { - TRY_TO(TraverseStmt(C->getSafelen())); - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) { - TRY_TO(TraverseStmt(C->getNumForLoops())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) { - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { - TRY_TO(TraverseStmt(C->getChunkSize())); - TRY_TO(TraverseStmt(C->getHelperChunkSize())); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) { - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { - return true; -} - -template <typename Derived> -template <typename T> -bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { - for (auto *E : Node->varlists()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->private_copies()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( - OMPFirstprivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->private_copies()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->inits()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause( - OMPLastprivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->private_copies()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->source_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->destination_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->assignment_ops()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) { - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) { - TRY_TO(TraverseStmt(C->getStep())); - TRY_TO(TraverseStmt(C->getCalcStep())); - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->inits()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->updates()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->finals()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) { - TRY_TO(TraverseStmt(C->getAlignment())); - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->source_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->destination_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->assignment_ops()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause( - OMPCopyprivateClause *C) { - TRY_TO(VisitOMPClauseList(C)); - for (auto *E : C->source_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->destination_exprs()) { - TRY_TO(TraverseStmt(E)); - } - for (auto *E : C->assignment_ops()) { - TRY_TO(TraverseStmt(E)); - } - return true; -} - -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { - TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); - TRY_TO(VisitOMPClauseList(C)); - 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)); - } - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) { - TRY_TO(VisitOMPClauseList(C)); - return true; -} - -// FIXME: look at the following tricky-seeming exprs to see if we -// need to recurse on anything. These are ones that have methods -// returning decls or qualtypes or nestednamespecifier -- though I'm -// not sure if they own them -- or just seemed very complicated, or -// had lots of sub-types to explore. -// -// VisitOverloadExpr and its children: recurse on template args? etc? - -// FIXME: go through all the stmts and exprs again, and see which of them -// create new types, and recurse on the types (TypeLocs?) of those. -// Candidates: -// -// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html -// Every class that has getQualifier. - -#undef DEF_TRAVERSE_STMT - -#undef TRY_TO - -#undef RecursiveASTVisitor - -} // end namespace clang - -#endif // LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index e06b58b..046ce70 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -21,11 +21,13 @@ #include "clang/AST/Redeclarable.h" #include "clang/AST/Type.h" #include "clang/Basic/Linkage.h" +#include "clang/Basic/Module.h" #include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/TrailingObjects.h" namespace clang { struct ASTTemplateArgumentListInfo; @@ -37,7 +39,6 @@ class FunctionTemplateDecl; class FunctionTemplateSpecializationInfo; class LabelStmt; class MemberSpecializationInfo; -class Module; class NestedNameSpecifier; class ParmVarDecl; class Stmt; @@ -318,7 +319,8 @@ public: NamedDecl *getUnderlyingDecl() { // Fast-path the common case. if (this->getKind() != UsingShadow && - this->getKind() != ObjCCompatibleAlias) + this->getKind() != ObjCCompatibleAlias && + this->getKind() != NamespaceAlias) return this; return getUnderlyingDeclImpl(); @@ -462,25 +464,15 @@ public: } /// \brief Get the original (first) namespace declaration. - NamespaceDecl *getOriginalNamespace() { - if (isFirstDecl()) - return this; - - return AnonOrFirstNamespaceAndInline.getPointer(); - } + NamespaceDecl *getOriginalNamespace(); /// \brief Get the original (first) namespace declaration. - const NamespaceDecl *getOriginalNamespace() const { - if (isFirstDecl()) - return this; - - return AnonOrFirstNamespaceAndInline.getPointer(); - } + const NamespaceDecl *getOriginalNamespace() const; /// \brief Return true if this declaration is an original (first) declaration /// of the namespace. This is false for non-original (subsequent) namespace /// declarations and anonymous namespaces. - bool isOriginalNamespace() const { return isFirstDecl(); } + bool isOriginalNamespace() const; /// \brief Retrieve the anonymous namespace nested inside this namespace, /// if any. @@ -572,8 +564,7 @@ struct QualifierInfo { /// setTemplateParameterListsInfo - Sets info about "outer" template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, - unsigned NumTPLists, - TemplateParameterList **TPLists); + ArrayRef<TemplateParameterList *> TPLists); private: // Copy constructor and copy assignment are disabled. @@ -658,8 +649,8 @@ public: assert(index < getNumTemplateParameterLists()); return getExtInfo()->TemplParamLists[index]; } - void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists); + void setTemplateParameterListsInfo(ASTContext &Context, + ArrayRef<TemplateParameterList *> TPLists); SourceLocation getTypeSpecStartLoc() const; @@ -728,17 +719,14 @@ public: }; protected: - /// \brief Placeholder type used in Init to denote an unparsed C++ default - /// argument. - struct UnparsedDefaultArgument; - - /// \brief Placeholder type used in Init to denote an uninstantiated C++ - /// default argument. - struct UninstantiatedDefaultArgument; - - typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *, - UnparsedDefaultArgument *, - UninstantiatedDefaultArgument *> InitType; + // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we + // have allocated the auxilliary struct of information there. + // + // TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for + // 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; /// \brief The initializer for this variable or, for a ParmVarDecl, the /// C++ default argument. @@ -762,6 +750,13 @@ private: protected: enum { NumParameterIndexBits = 8 }; + enum DefaultArgKind { + DAK_None, + DAK_Unparsed, + DAK_Uninstantiated, + DAK_Normal + }; + class ParmVarDeclBitfields { friend class ParmVarDecl; friend class ASTDeclReader; @@ -772,6 +767,12 @@ protected: /// prior declaration. unsigned HasInheritedDefaultArg : 1; + /// Describes the kind of default argument for this parameter. By default + /// this is none. If this is normal, then the default argument is stored in + /// the \c VarDecl initalizer expression unless we were unble to parse + /// (even an invalid) expression for the default argument. + unsigned DefaultArgKind : 2; + /// Whether this parameter undergoes K&R argument promotion. unsigned IsKNRPromoted : 1; @@ -815,6 +816,9 @@ protected: /// \brief Whether this variable is (C++0x) constexpr. unsigned IsConstexpr : 1; + /// \brief Whether this variable is a (C++ Concepts TS) concept. + unsigned IsConcept : 1; + /// \brief Whether this variable is the implicit variable for a lambda /// init-capture. unsigned IsInitCapture : 1; @@ -1062,47 +1066,14 @@ public: /// declaration it is attached to. Also get that declaration. const Expr *getAnyInitializer(const VarDecl *&D) const; - bool hasInit() const { - return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>()); - } + bool hasInit() const; const Expr *getInit() const { - if (Init.isNull()) - return nullptr; - - const Stmt *S = Init.dyn_cast<Stmt *>(); - if (!S) { - if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) - S = ES->Value; - } - return (const Expr*) S; - } - Expr *getInit() { - if (Init.isNull()) - return nullptr; - - Stmt *S = Init.dyn_cast<Stmt *>(); - if (!S) { - if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) - S = ES->Value; - } - - return (Expr*) S; + return const_cast<VarDecl *>(this)->getInit(); } + Expr *getInit(); /// \brief Retrieve the address of the initializer expression. - Stmt **getInitAddress() { - if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>()) - return &ES->Value; - - // This union hack tip-toes around strict-aliasing rules. - union { - InitType *InitPtr; - Stmt **StmtPtr; - }; - - InitPtr = &Init; - return StmtPtr; - } + Stmt **getInitAddress(); void setInit(Expr *I); @@ -1124,33 +1095,18 @@ public: /// \brief Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer /// to untyped APValue if the value could not be evaluated. - APValue *getEvaluatedValue() const { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) - if (Eval->WasEvaluated) - return &Eval->Evaluated; - - return nullptr; - } + APValue *getEvaluatedValue() const; /// \brief Determines whether it is already known whether the /// initializer is an integral constant expression or not. - bool isInitKnownICE() const { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) - return Eval->CheckedICE; - - return false; - } + bool isInitKnownICE() const; /// \brief Determines whether the initializer is an integral constant /// expression, or in C++11, whether the initializer is a constant /// expression. /// /// \pre isInitKnownICE() - bool isInitICE() const { - assert(isInitKnownICE() && - "Check whether we already know that the initializer is an ICE"); - return Init.get<EvaluatedStmt *>()->IsICE; - } + bool isInitICE() const; /// \brief Determine whether the value of the initializer attached to this /// declaration is an integral constant expression. @@ -1238,6 +1194,15 @@ public: NonParmVarDeclBits.IsConstexpr = IC; } + /// Whether this variable is (C++ Concepts TS) concept. + bool isConcept() const { + return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConcept; + } + void setConcept(bool IC) { + assert(!isa<ParmVarDecl>(this)); + NonParmVarDeclBits.IsConcept = IC; + } + /// Whether this variable is the implicit variable for a lambda init-capture. bool isInitCapture() const { return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture; @@ -1342,6 +1307,7 @@ protected: TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) : VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) { assert(ParmVarDeclBits.HasInheritedDefaultArg == false); + assert(ParmVarDeclBits.DefaultArgKind == DAK_None); assert(ParmVarDeclBits.IsKNRPromoted == false); assert(ParmVarDeclBits.IsObjCMethodParam == false); setDefaultArg(DefArg); @@ -1416,29 +1382,20 @@ public: return const_cast<ParmVarDecl *>(this)->getDefaultArg(); } - void setDefaultArg(Expr *defarg) { - Init = reinterpret_cast<Stmt *>(defarg); - } + void setDefaultArg(Expr *defarg); /// \brief Retrieve the source range that covers the entire default /// argument. SourceRange getDefaultArgRange() const; - void setUninstantiatedDefaultArg(Expr *arg) { - Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg); - } - Expr *getUninstantiatedDefaultArg() { - return (Expr *)Init.get<UninstantiatedDefaultArgument *>(); - } + void setUninstantiatedDefaultArg(Expr *arg); + Expr *getUninstantiatedDefaultArg(); const Expr *getUninstantiatedDefaultArg() const { - return (const Expr *)Init.get<UninstantiatedDefaultArgument *>(); + return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg(); } /// hasDefaultArg - Determines whether this parameter has a default argument, /// either parsed or not. - bool hasDefaultArg() const { - return getInit() || hasUnparsedDefaultArg() || - hasUninstantiatedDefaultArg(); - } + bool hasDefaultArg() const; /// hasUnparsedDefaultArg - Determines whether this parameter has a /// default argument that has not yet been parsed. This will occur @@ -1451,11 +1408,11 @@ public: /// }; // x has a regular default argument now /// @endcode bool hasUnparsedDefaultArg() const { - return Init.is<UnparsedDefaultArgument*>(); + return ParmVarDeclBits.DefaultArgKind == DAK_Unparsed; } bool hasUninstantiatedDefaultArg() const { - return Init.is<UninstantiatedDefaultArgument*>(); + return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated; } /// setUnparsedDefaultArg - Specify that this parameter has an @@ -1463,7 +1420,9 @@ public: /// real default argument via setDefaultArg when the class /// definition enclosing the function declaration that owns this /// default argument is completed. - void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)nullptr; } + void setUnparsedDefaultArg() { + ParmVarDeclBits.DefaultArgKind = DAK_Unparsed; + } bool hasInheritedDefaultArg() const { return ParmVarDeclBits.HasInheritedDefaultArg; @@ -1546,25 +1505,25 @@ private: LazyDeclStmtPtr Body; - // FIXME: This can be packed into the bitfields in Decl. - // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum + // FIXME: This can be packed into the bitfields in DeclContext. + // NOTE: VC++ packs bitfields poorly if the types differ. unsigned SClass : 2; - bool IsInline : 1; - bool IsInlineSpecified : 1; - bool IsVirtualAsWritten : 1; - bool IsPure : 1; - bool HasInheritedPrototype : 1; - bool HasWrittenPrototype : 1; - bool IsDeleted : 1; - bool IsTrivial : 1; // sunk from CXXMethodDecl - bool IsDefaulted : 1; // sunk from CXXMethoDecl - bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl - bool HasImplicitReturnZero : 1; - bool IsLateTemplateParsed : 1; - bool IsConstexpr : 1; + unsigned IsInline : 1; + unsigned IsInlineSpecified : 1; + unsigned IsVirtualAsWritten : 1; + unsigned IsPure : 1; + unsigned HasInheritedPrototype : 1; + unsigned HasWrittenPrototype : 1; + unsigned IsDeleted : 1; + unsigned IsTrivial : 1; // sunk from CXXMethodDecl + unsigned IsDefaulted : 1; // sunk from CXXMethoDecl + unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl + unsigned HasImplicitReturnZero : 1; + unsigned IsLateTemplateParsed : 1; + unsigned IsConstexpr : 1; /// \brief Indicates if the function uses __try. - bool UsesSEHTry : 1; + unsigned UsesSEHTry : 1; /// \brief Indicates if the function was a definition but its body was /// skipped. @@ -1835,7 +1794,7 @@ public: bool isConstexpr() const { return IsConstexpr; } void setConstexpr(bool IC) { IsConstexpr = IC; } - /// Whether this is a (C++11) constexpr function or constexpr constructor. + /// \brief Indicates the function uses __try. bool usesSEHTry() const { return UsesSEHTry; } void setUsesSEHTry(bool UST) { UsesSEHTry = UST; } @@ -2084,9 +2043,7 @@ public: /// \brief If this function is an instantiation of a member function of a /// class template specialization, retrieves the member specialization /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const { - return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); - } + MemberSpecializationInfo *getMemberSpecializationInfo() const; /// \brief Specify that this record is an instantiation of the /// member function FD. @@ -2107,13 +2064,9 @@ public: /// FunctionDecl that describes the function template, /// getDescribedFunctionTemplate() retrieves the /// FunctionTemplateDecl from a FunctionDecl. - FunctionTemplateDecl *getDescribedFunctionTemplate() const { - return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl*>(); - } + FunctionTemplateDecl *getDescribedFunctionTemplate() const; - void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { - TemplateOrSpecialization = Template; - } + void setDescribedFunctionTemplate(FunctionTemplateDecl *Template); /// \brief Determine whether this function is a function template /// specialization. @@ -2128,10 +2081,7 @@ public: /// \brief If this function is actually a function template specialization, /// retrieve information about this function template specialization. /// Otherwise, returns NULL. - FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const { - return TemplateOrSpecialization. - dyn_cast<FunctionTemplateSpecializationInfo*>(); - } + FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const; /// \brief Determines whether this function is a function template /// specialization or a member of a class template specialization that can @@ -2208,10 +2158,7 @@ public: const TemplateArgumentListInfo &TemplateArgs); DependentFunctionTemplateSpecializationInfo * - getDependentSpecializationInfo() const { - return TemplateOrSpecialization. - dyn_cast<DependentFunctionTemplateSpecializationInfo*>(); - } + getDependentSpecializationInfo() const; /// \brief Determine what kind of template instantiation this function /// represents. @@ -2487,7 +2434,8 @@ public: /// IndirectFieldDecl - An instance of this class is created to represent a /// field injected from an anonymous union/struct into the parent scope. /// IndirectFieldDecl are always implicit. -class IndirectFieldDecl : public ValueDecl { +class IndirectFieldDecl : public ValueDecl, + public Mergeable<IndirectFieldDecl> { void anchor() override; NamedDecl **Chaining; unsigned ChainingSize; @@ -2525,6 +2473,9 @@ public: return dyn_cast<VarDecl>(*chain_begin()); } + IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); } + const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == IndirectField; } @@ -2762,12 +2713,12 @@ private: /// declaration specifier for variables, it points to the first VarDecl (used /// for mangling); /// otherwise, it is a null (TypedefNameDecl) pointer. - llvm::PointerUnion<NamedDecl *, ExtInfo *> NamedDeclOrQualifier; + llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier; - bool hasExtInfo() const { return NamedDeclOrQualifier.is<ExtInfo *>(); } - ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get<ExtInfo *>(); } + bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); } + ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); } const ExtInfo *getExtInfo() const { - return NamedDeclOrQualifier.get<ExtInfo *>(); + return TypedefNameDeclOrQualifier.get<ExtInfo *>(); } protected: @@ -2778,7 +2729,7 @@ protected: TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false), IsEmbeddedInDeclarator(false), IsFreeStanding(false), IsCompleteDefinitionRequired(false), - NamedDeclOrQualifier((NamedDecl *)nullptr) { + TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); setPreviousDecl(PrevDecl); @@ -2925,22 +2876,11 @@ public: return (getDeclName() || getTypedefNameForAnonDecl()); } - bool hasDeclaratorForAnonDecl() const { - return dyn_cast_or_null<DeclaratorDecl>( - NamedDeclOrQualifier.get<NamedDecl *>()); - } - DeclaratorDecl *getDeclaratorForAnonDecl() const { - return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>( - NamedDeclOrQualifier.get<NamedDecl *>()); - } - TypedefNameDecl *getTypedefNameForAnonDecl() const { - return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>( - NamedDeclOrQualifier.get<NamedDecl *>()); + return hasExtInfo() ? nullptr + : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>(); } - void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; } - void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); /// \brief Retrieve the nested-name-specifier that qualifies the name of this @@ -2967,8 +2907,8 @@ public: assert(i < getNumTemplateParameterLists()); return getExtInfo()->TemplParamLists[i]; } - void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists); + void setTemplateParameterListsInfo(ASTContext &Context, + ArrayRef<TemplateParameterList *> TPLists); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -3301,7 +3241,14 @@ public: bool hasVolatileMember() const { return HasVolatileMember; } void setHasVolatileMember (bool val) { HasVolatileMember = val; } - + + bool hasLoadedFieldsFromExternalStorage() const { + return LoadedFieldsFromExternalStorage; + } + void setHasLoadedFieldsFromExternalStorage(bool val) { + LoadedFieldsFromExternalStorage = val; + } + /// \brief Determines whether this declaration represents the /// injected class name. /// @@ -3475,7 +3422,7 @@ private: Stmt *Body; TypeSourceInfo *SignatureAsWritten; - Capture *Captures; + const Capture *Captures; unsigned NumCaptures; unsigned ManglingNumber; @@ -3581,10 +3528,8 @@ public: bool capturesVariable(const VarDecl *var) const; - void setCaptures(ASTContext &Context, - const Capture *begin, - const Capture *end, - bool capturesCXXThis); + void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures, + bool CapturesCXXThis); unsigned getBlockManglingNumber() const { return ManglingNumber; @@ -3613,7 +3558,15 @@ public: /// \brief This represents the body of a CapturedStmt, and serves as its /// DeclContext. -class CapturedDecl : public Decl, public DeclContext { +class CapturedDecl final + : public Decl, + public DeclContext, + private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> { +protected: + size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) { + return NumParams; + } + private: /// \brief The number of parameters to the outlined function. unsigned NumParams; @@ -3622,13 +3575,14 @@ private: /// \brief The body of the outlined function. llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow; - explicit CapturedDecl(DeclContext *DC, unsigned NumParams) - : Decl(Captured, DC, SourceLocation()), DeclContext(Captured), - NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) { } + explicit CapturedDecl(DeclContext *DC, unsigned NumParams); + + ImplicitParamDecl *const *getParams() const { + return getTrailingObjects<ImplicitParamDecl *>(); + } - ImplicitParamDecl **getParams() const { - return reinterpret_cast<ImplicitParamDecl **>( - const_cast<CapturedDecl *>(this) + 1); + ImplicitParamDecl **getParams() { + return getTrailingObjects<ImplicitParamDecl *>(); } public: @@ -3637,11 +3591,11 @@ public: static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumParams); - Stmt *getBody() const override { return BodyAndNothrow.getPointer(); } - void setBody(Stmt *B) { BodyAndNothrow.setPointer(B); } + Stmt *getBody() const override; + void setBody(Stmt *B); - bool isNothrow() const { return BodyAndNothrow.getInt(); } - void setNothrow(bool Nothrow = true) { BodyAndNothrow.setInt(Nothrow); } + bool isNothrow() const; + void setNothrow(bool Nothrow = true); unsigned getNumParams() const { return NumParams; } @@ -3666,7 +3620,7 @@ public: } unsigned getContextParamPosition() const { return ContextParam; } - typedef ImplicitParamDecl **param_iterator; + typedef ImplicitParamDecl *const *param_iterator; typedef llvm::iterator_range<param_iterator> param_range; /// \brief Retrieve an iterator pointing to the first parameter decl. @@ -3689,6 +3643,7 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; + friend TrailingObjects; }; /// \brief Describes a module import declaration, which makes the contents @@ -3701,7 +3656,8 @@ public: /// /// Import declarations can also be implicitly generated from /// \#include/\#import directives. -class ImportDecl : public Decl { +class ImportDecl final : public Decl, + llvm::TrailingObjects<ImportDecl, SourceLocation> { /// \brief The imported module, along with a bit that indicates whether /// we have source-location information for each identifier in the module /// name. @@ -3717,7 +3673,8 @@ class ImportDecl : public Decl { friend class ASTReader; friend class ASTDeclReader; friend class ASTContext; - + friend TrailingObjects; + ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs); diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 6b6ac3f..05b2a12 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -70,8 +70,15 @@ namespace clang { /// Decl - This represents one declaration (or definition), e.g. a variable, /// typedef, function, struct, etc. /// +/// Note: There are objects tacked on before the *beginning* of Decl +/// (and its subclasses) in its Decl::operator new(). Proper alignment +/// of all subclasses (not requiring more than DeclObjAlignment) is +/// asserted in DeclBase.cpp. class Decl { public: + /// \brief Alignment guaranteed when allocating Decl and any subtypes. + enum { DeclObjAlignment = llvm::AlignOf<uint64_t>::Alignment }; + /// \brief Lists the kind of concrete classes of Decl. enum Kind { #define DECL(DERIVED, BASE) DERIVED, @@ -468,8 +475,7 @@ public: template <typename T> llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const { - return llvm::iterator_range<specific_attr_iterator<T>>( - specific_attr_begin<T>(), specific_attr_end<T>()); + return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>()); } template <typename T> @@ -721,6 +727,15 @@ public: return getParentFunctionOrMethod() == nullptr; } + /// \brief Returns true if this declaration lexically is inside a function. + /// It recognizes non-defining declarations as well as members of local + /// classes: + /// \code + /// void foo() { void bar(); } + /// void foo2() { class ABC { void bar(); }; } + /// \endcode + bool isLexicallyWithinFunctionOrMethod() const; + /// \brief If this decl is defined inside a function/method/block it returns /// the corresponding DeclContext, otherwise it returns null. const DeclContext *getParentFunctionOrMethod() const; @@ -1126,6 +1141,11 @@ class DeclContext { /// that are missing from the lookup table. mutable bool HasLazyExternalLexicalLookups : 1; + /// \brief If \c true, lookups should only return identifier from + /// DeclContext scope (for example TranslationUnit). Used in + /// LookupQualifiedName() + mutable bool UseQualifiedLookup : 1; + /// \brief Pointer to the data structure used to lookup declarations /// within this context (or a DependentStoredDeclsMap if this is a /// dependent context). We maintain the invariant that, if the map @@ -1160,6 +1180,7 @@ protected: ExternalVisibleStorage(false), NeedToReconcileExternalVisibleStorage(false), HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false), + UseQualifiedLookup(false), LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {} public: @@ -1740,6 +1761,16 @@ public: D == LastDecl); } + bool setUseQualifiedLookup(bool use = true) { + bool old_value = UseQualifiedLookup; + UseQualifiedLookup = use; + return old_value; + } + + bool shouldUseQualifiedLookup() const { + return UseQualifiedLookup; + } + static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 08451c0..7c54901 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1344,9 +1344,7 @@ public: /// \brief If this class is an instantiation of a member class of a /// class template specialization, retrieves the member specialization /// information. - MemberSpecializationInfo *getMemberSpecializationInfo() const { - return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>(); - } + MemberSpecializationInfo *getMemberSpecializationInfo() const; /// \brief Specify that this record is an instantiation of the /// member class \p RD. @@ -1364,13 +1362,9 @@ public: /// CXXRecordDecl that from a ClassTemplateDecl, while /// getDescribedClassTemplate() retrieves the ClassTemplateDecl from /// a CXXRecordDecl. - ClassTemplateDecl *getDescribedClassTemplate() const { - return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>(); - } + ClassTemplateDecl *getDescribedClassTemplate() const; - void setDescribedClassTemplate(ClassTemplateDecl *Template) { - TemplateOrInstantiation = Template; - } + void setDescribedClassTemplate(ClassTemplateDecl *Template); /// \brief Determine whether this particular class is a specialization or /// instantiation of a class template or member class of a class template, @@ -1468,8 +1462,8 @@ public: /// \param BaseDefinition the definition of the base class /// /// \returns true if this base matched the search criteria - typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition, - void *UserData); + typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)> + ForallBasesCallback; /// \brief Determines if the given callback holds for all the direct /// or indirect base classes of this type. @@ -1481,13 +1475,10 @@ public: /// class of this type, or if \p AllowShortCircuit is true then until a call /// returns false. /// - /// \param UserData Passed as the second argument of every call to - /// \p BaseMatches. - /// /// \param AllowShortCircuit if false, forces the callback to be called /// for every base class, even if a dependent or non-matching base was /// found. - bool forallBases(ForallBasesCallback *BaseMatches, void *UserData, + bool forallBases(ForallBasesCallback BaseMatches, bool AllowShortCircuit = true) const; /// \brief Function type used by lookupInBases() to determine whether a @@ -1499,13 +1490,9 @@ public: /// \param Path the current path, from the most-derived class down to the /// base named by the \p Specifier. /// - /// \param UserData a single pointer to user-specified data, provided to - /// lookupInBases(). - /// /// \returns true if this base matched the search criteria, false otherwise. - typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - void *UserData); + typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path)> BaseMatchesCallback; /// \brief Look for entities within the base classes of this C++ class, /// transitively searching all base class subobjects. @@ -1520,14 +1507,12 @@ public: /// \param BaseMatches callback function used to determine whether a given /// base matches the user-defined search criteria. /// - /// \param UserData user data pointer that will be provided to \p BaseMatches. - /// /// \param Paths used to record the paths from this class to its base class /// subobjects that match the search criteria. /// /// \returns true if there exists any path from this class to a base class /// subobject that matches the search criteria. - bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, + bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths) const; /// \brief Base-class lookup callback that determines whether the given @@ -1535,10 +1520,10 @@ public: /// /// This callback can be used with \c lookupInBases() to determine whether /// a given derived class has is a base class subobject of a particular type. - /// The user data pointer should refer to the canonical CXXRecordDecl of the + /// The base record pointer should refer to the canonical CXXRecordDecl of the /// base class that we are searching for. static bool FindBaseClass(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, void *BaseRecord); + CXXBasePath &Path, const CXXRecordDecl *BaseRecord); /// \brief Base-class lookup callback that determines whether the /// given base class specifier refers to a specific class @@ -1546,39 +1531,38 @@ public: /// /// This callback can be used with \c lookupInBases() to determine /// whether a given derived class has is a virtual base class - /// subobject of a particular type. The user data pointer should + /// subobject of a particular type. The base record pointer should /// refer to the canonical CXXRecordDecl of the base class that we /// are searching for. static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, void *BaseRecord); + CXXBasePath &Path, + const CXXRecordDecl *BaseRecord); /// \brief Base-class lookup callback that determines whether there exists /// a tag with the given name. /// /// This callback can be used with \c lookupInBases() to find tag members - /// of the given name within a C++ class hierarchy. The user data pointer - /// is an opaque \c DeclarationName pointer. + /// of the given name within a C++ class hierarchy. static bool FindTagMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, void *Name); + CXXBasePath &Path, DeclarationName Name); /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name. /// /// This callback can be used with \c lookupInBases() to find members - /// of the given name within a C++ class hierarchy. The user data pointer - /// is an opaque \c DeclarationName pointer. + /// of the given name within a C++ class hierarchy. static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, void *Name); + CXXBasePath &Path, DeclarationName Name); /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name that can be used in a nested-name-specifier. /// - /// This callback can be used with \c lookupInBases() to find membes of + /// This callback can be used with \c lookupInBases() to find members of /// the given name within a C++ class hierarchy that can occur within /// nested-name-specifiers. static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *UserData); + DeclarationName Name); /// \brief Retrieve the final overriders for each virtual member /// function in the class hierarchy where this class is the @@ -1898,7 +1882,8 @@ public: /// B(A& a) : A(a), f(3.14159) { } /// }; /// \endcode -class CXXCtorInitializer { +class CXXCtorInitializer final + : private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> { /// \brief Either the base class name/delegating constructor type (stored as /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field /// (IndirectFieldDecl*) being initialized. @@ -2114,24 +2099,26 @@ public: /// describe an array member initialization. VarDecl *getArrayIndex(unsigned I) { assert(I < getNumArrayIndices() && "Out of bounds member array index"); - return reinterpret_cast<VarDecl **>(this + 1)[I]; + return getTrailingObjects<VarDecl *>()[I]; } const VarDecl *getArrayIndex(unsigned I) const { assert(I < getNumArrayIndices() && "Out of bounds member array index"); - return reinterpret_cast<const VarDecl * const *>(this + 1)[I]; + return getTrailingObjects<VarDecl *>()[I]; } void setArrayIndex(unsigned I, VarDecl *Index) { assert(I < getNumArrayIndices() && "Out of bounds member array index"); - reinterpret_cast<VarDecl **>(this + 1)[I] = Index; + getTrailingObjects<VarDecl *>()[I] = Index; } ArrayRef<VarDecl *> getArrayIndexes() { assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init"); - return llvm::makeArrayRef(reinterpret_cast<VarDecl **>(this + 1), + return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(), getNumArrayIndices()); } /// \brief Get the initializer. Expr *getInit() const { return static_cast<Expr*>(Init); } + + friend TrailingObjects; }; /// \brief Represents a C++ constructor within a class. @@ -2289,14 +2276,14 @@ public: } /// \brief Determine whether this constructor is a move constructor - /// (C++0x [class.copy]p3), which can be used to move values of the class. + /// (C++11 [class.copy]p3), which can be used to move values of the class. /// /// \param TypeQuals If this constructor is a move constructor, will be set /// to the type qualifiers on the referent of the first parameter's type. bool isMoveConstructor(unsigned &TypeQuals) const; /// \brief Determine whether this constructor is a move constructor - /// (C++0x [class.copy]p3), which can be used to move values of the class. + /// (C++11 [class.copy]p3), which can be used to move values of the class. bool isMoveConstructor() const { unsigned TypeQuals = 0; return isMoveConstructor(TypeQuals); @@ -2406,7 +2393,7 @@ class CXXConversionDecl : public CXXMethodDecl { void anchor() override; /// Whether this conversion function declaration is marked /// "explicit", meaning that it can only be applied when the user - /// explicitly wrote a cast. This is a C++0x feature. + /// explicitly wrote a cast. This is a C++11 feature. bool IsExplicitSpecified : 1; CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 12b93b4..27b0388 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -37,7 +37,9 @@ namespace clang { /// @endcode /// /// The semantic context of a friend decl is its declaring class. -class FriendDecl : public Decl { +class FriendDecl final + : public Decl, + private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> { virtual void anchor(); public: typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; @@ -62,14 +64,6 @@ private: // template <class T> friend class A<T>::B; unsigned NumTPLists : 31; - // The tail-allocated friend type template parameter lists (if any). - TemplateParameterList* const *getTPLists() const { - return reinterpret_cast<TemplateParameterList* const *>(this + 1); - } - TemplateParameterList **getTPLists() { - return reinterpret_cast<TemplateParameterList**>(this + 1); - } - friend class CXXRecordDecl::friend_iterator; friend class CXXRecordDecl; @@ -83,7 +77,7 @@ private: UnsupportedFriend(false), NumTPLists(FriendTypeTPLists.size()) { for (unsigned i = 0; i < NumTPLists; ++i) - getTPLists()[i] = FriendTypeTPLists[i]; + getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i]; } FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists) @@ -118,7 +112,7 @@ public: } TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const { assert(N < NumTPLists); - return getTPLists()[N]; + return getTrailingObjects<TemplateParameterList *>()[N]; } /// If this friend declaration doesn't name a type, return the inner @@ -148,9 +142,10 @@ public: return SourceRange(getFriendLoc(), ND->getLocEnd()); } else if (TypeSourceInfo *TInfo = getFriendType()) { - SourceLocation StartL = (NumTPLists == 0) - ? getFriendLoc() - : getTPLists()[0]->getTemplateLoc(); + SourceLocation StartL = + (NumTPLists == 0) ? getFriendLoc() + : getTrailingObjects<TemplateParameterList *>()[0] + ->getTemplateLoc(); return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc()); } else @@ -171,6 +166,7 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; + friend TrailingObjects; }; /// An iterator over the friend declarations of a class. diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h index bd3dbd8..c84bb5e 100644 --- a/include/clang/AST/DeclGroup.h +++ b/include/clang/AST/DeclGroup.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_DECLGROUP_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/TrailingObjects.h" #include <cassert> namespace clang { @@ -24,13 +25,9 @@ class Decl; class DeclGroup; class DeclGroupIterator; -class DeclGroup { +class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> { // FIXME: Include a TypeSpecifier object. - union { - unsigned NumDecls; - - Decl *Aligner; - }; + unsigned NumDecls; private: DeclGroup() : NumDecls(0) {} @@ -43,13 +40,15 @@ public: Decl*& operator[](unsigned i) { assert (i < NumDecls && "Out-of-bounds access."); - return ((Decl**) (this+1))[i]; + return getTrailingObjects<Decl *>()[i]; } Decl* const& operator[](unsigned i) const { assert (i < NumDecls && "Out-of-bounds access."); - return ((Decl* const*) (this+1))[i]; + return getTrailingObjects<Decl *>()[i]; } + + friend TrailingObjects; }; class DeclGroupRef { diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index c42764b..f46078f 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -612,7 +612,8 @@ public: /// @interface NSArray<T> // stores the <T> /// @end /// \endcode -class ObjCTypeParamList { +class ObjCTypeParamList final + : private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> { /// Stores the components of a SourceRange as a POD. struct PODSourceRange { unsigned Begin; @@ -644,7 +645,7 @@ public: /// Iterate through the type parameters in the list. typedef ObjCTypeParamDecl **iterator; - iterator begin() { return reinterpret_cast<ObjCTypeParamDecl **>(this + 1); } + iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); } iterator end() { return begin() + size(); } @@ -655,7 +656,7 @@ public: typedef ObjCTypeParamDecl * const *const_iterator; const_iterator begin() const { - return reinterpret_cast<ObjCTypeParamDecl * const *>(this + 1); + return getTrailingObjects<ObjCTypeParamDecl *>(); } const_iterator end() const { @@ -685,6 +686,7 @@ 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; }; /// ObjCContainerDecl - Represents a container for method declarations. @@ -1202,13 +1204,8 @@ public: // might bring in a definition. // Note: a null value indicates that we don't have a definition and that // modules are enabled. - if (!Data.getOpaqueValue()) { - if (IdentifierInfo *II = getIdentifier()) { - if (II->isOutOfDate()) { - updateOutOfDate(*II); - } - } - } + if (!Data.getOpaqueValue()) + getMostRecentDecl(); return Data.getPointer(); } @@ -1851,13 +1848,8 @@ public: // might bring in a definition. // Note: a null value indicates that we don't have a definition and that // modules are enabled. - if (!Data.getOpaqueValue()) { - if (IdentifierInfo *II = getIdentifier()) { - if (II->isOutOfDate()) { - updateOutOfDate(*II); - } - } - } + if (!Data.getOpaqueValue()) + getMostRecentDecl(); return Data.getPointer(); } @@ -2519,26 +2511,18 @@ public: void setPropertyAttributes(PropertyAttributeKind PRVal) { PropertyAttributes |= PRVal; } + void overwritePropertyAttributes(unsigned PRVal) { + PropertyAttributes = PRVal; + } PropertyAttributeKind getPropertyAttributesAsWritten() const { return PropertyAttributeKind(PropertyAttributesAsWritten); } - bool hasWrittenStorageAttribute() const { - return PropertyAttributesAsWritten & (OBJC_PR_assign | OBJC_PR_copy | - OBJC_PR_unsafe_unretained | OBJC_PR_retain | OBJC_PR_strong | - OBJC_PR_weak); - } - void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { PropertyAttributesAsWritten = PRVal; } - void makeitReadWriteAttribute() { - PropertyAttributes &= ~OBJC_PR_readonly; - PropertyAttributes |= OBJC_PR_readwrite; - } - // Helper methods for accessing attributes. /// isReadOnly - Return true iff the property has a setter. diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h index 7f0616f..598f418 100644 --- a/include/clang/AST/DeclOpenMP.h +++ b/include/clang/AST/DeclOpenMP.h @@ -33,8 +33,12 @@ class Expr; /// }; /// \endcode /// -class OMPThreadPrivateDecl : public Decl { +class OMPThreadPrivateDecl final + : public Decl, + private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> { friend class ASTDeclReader; + friend TrailingObjects; + unsigned NumVars; virtual void anchor(); @@ -43,14 +47,11 @@ class OMPThreadPrivateDecl : public Decl { Decl(DK, DC, L), NumVars(0) { } ArrayRef<const Expr *> getVars() const { - return llvm::makeArrayRef(reinterpret_cast<const Expr * const *>(this + 1), - NumVars); + return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars); } MutableArrayRef<Expr *> getVars() { - return MutableArrayRef<Expr *>( - reinterpret_cast<Expr **>(this + 1), - NumVars); + return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars); } void setVars(ArrayRef<Expr *> VL); diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 0fc9b49..a9109ef 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -20,10 +20,12 @@ #include "clang/AST/TemplateBase.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" #include <limits> namespace clang { +enum BuiltinTemplateKind : int; class TemplateParameterList; class TemplateDecl; class RedeclarableTemplateDecl; @@ -43,7 +45,9 @@ typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*, /// \brief Stores a list of template parameters for a TemplateDecl and its /// derived classes. -class TemplateParameterList { +class TemplateParameterList final + : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> { + /// The location of the 'template' keyword. SourceLocation TemplateLoc; @@ -59,16 +63,18 @@ class TemplateParameterList { unsigned ContainsUnexpandedParameterPack : 1; protected: + size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { + return NumParams; + } + TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - NamedDecl **Params, unsigned NumParams, - SourceLocation RAngleLoc); + ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc); public: static TemplateParameterList *Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - NamedDecl **Params, - unsigned NumParams, + ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc); /// \brief Iterates through the template parameters in this list. @@ -77,10 +83,8 @@ public: /// \brief Iterates through the template parameters in this list. typedef NamedDecl* const* const_iterator; - iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); } - const_iterator begin() const { - return reinterpret_cast<NamedDecl * const *>(this + 1); - } + iterator begin() { return getTrailingObjects<NamedDecl *>(); } + const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); } iterator end() { return begin() + NumParams; } const_iterator end() const { return begin() + NumParams; } @@ -130,29 +134,45 @@ public: SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TemplateLoc, RAngleLoc); } + + friend TrailingObjects; + template <size_t N> friend class FixedSizeTemplateParameterListStorage; }; /// \brief Stores a list of template parameters for a TemplateDecl and its /// derived classes. Suitable for creating on the stack. -template<size_t N> -class FixedSizeTemplateParameterList : public TemplateParameterList { +template <size_t N> class FixedSizeTemplateParameterListStorage { + // This is kinda ugly: TemplateParameterList usually gets allocated + // in a block of memory with NamedDecls appended to it. Here, to get + // it stack allocated, we include the params as a separate + // variable. After allocation, the TemplateParameterList object + // treats them as part of itself. + TemplateParameterList List; NamedDecl *Params[N]; public: - FixedSizeTemplateParameterList(SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - NamedDecl **Params, SourceLocation RAngleLoc) : - TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) { - } + FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> Params, + SourceLocation RAngleLoc) + : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) { + // Because we're doing an evil layout hack above, have some + // asserts, just to double-check everything is laid out like + // expected. + assert(sizeof(*this) == + TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) && + "Object layout not as expected"); + assert(this->Params == List.getTrailingObjects<NamedDecl *>() && + "Object layout not as expected"); + } + TemplateParameterList *get() { return &List; } }; /// \brief A template argument list. -class TemplateArgumentList { +class TemplateArgumentList final + : private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> { /// \brief The template argument list. - /// - /// The integer value will be non-zero to indicate that this - /// template argument list does own the pointer. - llvm::PointerIntPair<const TemplateArgument *, 1> Arguments; + const TemplateArgument *Arguments; /// \brief The number of template arguments in this template /// argument list. @@ -161,9 +181,9 @@ class TemplateArgumentList { TemplateArgumentList(const TemplateArgumentList &Other) = delete; void operator=(const TemplateArgumentList &Other) = delete; - TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs, - bool Owned) - : Arguments(Args, Owned), NumArguments(NumArgs) { } + // Constructs an instance with an internal Argument list, containing + // a copy of the Args array. (Called by CreateCopy) + TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs); public: /// \brief Type used to indicate that the template argument list itself is a @@ -180,9 +200,9 @@ public: /// /// The template argument list does not own the template arguments /// provided. - explicit TemplateArgumentList(OnStackType, - const TemplateArgument *Args, unsigned NumArgs) - : Arguments(Args, false), NumArguments(NumArgs) { } + explicit TemplateArgumentList(OnStackType, const TemplateArgument *Args, + unsigned NumArgs) + : Arguments(Args), NumArguments(NumArgs) {} /// \brief Produces a shallow copy of the given template argument list. /// @@ -191,7 +211,7 @@ public: /// constructor, since this really really isn't safe to use that /// way. explicit TemplateArgumentList(const TemplateArgumentList *Other) - : Arguments(Other->data(), false), NumArguments(Other->size()) { } + : Arguments(Other->data()), NumArguments(Other->size()) {} /// \brief Retrieve the template argument at a given index. const TemplateArgument &get(unsigned Idx) const { @@ -212,9 +232,9 @@ public: unsigned size() const { return NumArguments; } /// \brief Retrieve a pointer to the template argument list. - const TemplateArgument *data() const { - return Arguments.getPointer(); - } + const TemplateArgument *data() const { return Arguments; } + + friend TrailingObjects; }; void *allocateDefaultArgStorageChain(const ASTContext &C); @@ -426,17 +446,8 @@ public: /// explicit instantiation declaration, or explicit instantiation /// definition. bool isExplicitInstantiationOrSpecialization() const { - switch (getTemplateSpecializationKind()) { - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - return true; - - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - return false; - } - llvm_unreachable("bad template specialization kind"); + return isTemplateExplicitInstantiationOrSpecialization( + getTemplateSpecializationKind()); } /// \brief Set the template specialization kind. @@ -542,56 +553,52 @@ public: /// friend void foo<>(T); /// }; /// \endcode -class DependentFunctionTemplateSpecializationInfo { - struct CA { - /// The number of potential template candidates. - unsigned NumTemplates; +class DependentFunctionTemplateSpecializationInfo final + : private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo, + TemplateArgumentLoc, + FunctionTemplateDecl *> { + /// The number of potential template candidates. + unsigned NumTemplates; - /// The number of template arguments. - unsigned NumArgs; - }; - - union { - // Force sizeof to be a multiple of sizeof(void*) so that the - // trailing data is aligned. - void *Aligner; - struct CA d; - }; + /// The number of template arguments. + unsigned NumArgs; /// The locations of the left and right angle brackets. SourceRange AngleLocs; - FunctionTemplateDecl * const *getTemplates() const { - return reinterpret_cast<FunctionTemplateDecl*const*>(this+1); + size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const { + return NumArgs; + } + size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const { + return NumTemplates; } -public: DependentFunctionTemplateSpecializationInfo( const UnresolvedSetImpl &Templates, const TemplateArgumentListInfo &TemplateArgs); +public: + static DependentFunctionTemplateSpecializationInfo * + Create(ASTContext &Context, const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs); + /// \brief Returns the number of function templates that this might /// be a specialization of. - unsigned getNumTemplates() const { - return d.NumTemplates; - } + unsigned getNumTemplates() const { return NumTemplates; } /// \brief Returns the i'th template candidate. FunctionTemplateDecl *getTemplate(unsigned I) const { assert(I < getNumTemplates() && "template index out of range"); - return getTemplates()[I]; + return getTrailingObjects<FunctionTemplateDecl *>()[I]; } /// \brief Returns the explicit template arguments that were given. const TemplateArgumentLoc *getTemplateArgs() const { - return reinterpret_cast<const TemplateArgumentLoc*>( - &getTemplates()[getNumTemplates()]); + return getTrailingObjects<TemplateArgumentLoc>(); } /// \brief Returns the number of explicit template arguments that were given. - unsigned getNumTemplateArgs() const { - return d.NumArgs; - } + unsigned getNumTemplateArgs() const { return NumArgs; } /// \brief Returns the nth template argument. const TemplateArgumentLoc &getTemplateArg(unsigned I) const { @@ -606,6 +613,8 @@ public: SourceLocation getRAngleLoc() const { return AngleLocs.getEnd(); } + + friend TrailingObjects; }; /// Declaration of a redeclarable template. @@ -926,7 +935,7 @@ public: return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl(); } - FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { + FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const { return cast_or_null<FunctionTemplateDecl>( RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } @@ -1120,8 +1129,11 @@ public: /// @code /// template<int Size> class array { }; /// @endcode -class NonTypeTemplateParmDecl - : public DeclaratorDecl, protected TemplateParmPosition { +class NonTypeTemplateParmDecl final + : public DeclaratorDecl, + protected TemplateParmPosition, + private llvm::TrailingObjects<NonTypeTemplateParmDecl, + std::pair<QualType, TypeSourceInfo *>> { /// \brief The default template argument, if any, and whether or not /// it was inherited. typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage; @@ -1141,6 +1153,11 @@ class NonTypeTemplateParmDecl /// \brief The number of types in an expanded parameter pack. unsigned NumExpandedTypes; + size_t numTrailingObjects( + OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const { + return NumExpandedTypes; + } + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, @@ -1159,6 +1176,7 @@ class NonTypeTemplateParmDecl TypeSourceInfo **ExpandedTInfos); friend class ASTDeclReader; + friend TrailingObjects; public: static NonTypeTemplateParmDecl * @@ -1274,16 +1292,18 @@ public: /// pack. QualType getExpansionType(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); - void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1); - return QualType::getFromOpaquePtr(TypesAndInfos[2*I]); + auto TypesAndInfos = + getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>(); + return TypesAndInfos[I].first; } /// \brief Retrieve a particular expansion type source info within an /// expanded parameter pack. TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); - void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1); - return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]); + auto TypesAndInfos = + getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>(); + return TypesAndInfos[I].second; } // Implement isa/cast/dyncast/etc. @@ -1298,9 +1318,11 @@ public: /// @endcode /// A template template parameter is a TemplateDecl because it defines the /// name of a template and the template parameters allowable for substitution. -class TemplateTemplateParmDecl : public TemplateDecl, - protected TemplateParmPosition -{ +class TemplateTemplateParmDecl final + : public TemplateDecl, + protected TemplateParmPosition, + private llvm::TrailingObjects<TemplateTemplateParmDecl, + TemplateParameterList *> { void anchor() override; /// \brief The default template argument, if any. @@ -1404,7 +1426,7 @@ public: /// pack. TemplateParameterList *getExpansionTemplateParameters(unsigned I) const { assert(I < NumExpandedParams && "Out-of-range expansion type index"); - return reinterpret_cast<TemplateParameterList *const *>(this + 1)[I]; + return getTrailingObjects<TemplateParameterList *>()[I]; } const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } @@ -1454,6 +1476,36 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; + friend TrailingObjects; +}; + +/// \brief Represents the builtin template declaration which is used to +/// implement __make_integer_seq. It serves no real purpose beyond existing as +/// a place to hold template parameters. +class BuiltinTemplateDecl : public TemplateDecl { + void anchor() override; + + BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, + DeclarationName Name, BuiltinTemplateKind BTK); + + BuiltinTemplateKind BTK; + +public: + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == BuiltinTemplate; } + + static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC, + DeclarationName Name, + BuiltinTemplateKind BTK) { + return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK); + } + + SourceRange getSourceRange() const override LLVM_READONLY { + return SourceRange(); + } + + BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; } }; /// \brief Represents a class template specialization, which refers to @@ -1580,17 +1632,8 @@ public: /// explicit instantiation declaration, or explicit instantiation /// definition. bool isExplicitInstantiationOrSpecialization() const { - switch (getTemplateSpecializationKind()) { - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - return true; - - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - return false; - } - llvm_unreachable("bad template specialization kind"); + return isTemplateExplicitInstantiationOrSpecialization( + getTemplateSpecializationKind()); } void setSpecializationKind(TemplateSpecializationKind TSK) { @@ -1819,8 +1862,8 @@ public: /// template partial specialization \c Outer<T>::Inner<U*>. Given /// \c Outer<float>::Inner<U*>, this function would return /// \c Outer<T>::Inner<U*>. - ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() { - ClassTemplatePartialSpecializationDecl *First = + ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const { + const ClassTemplatePartialSpecializationDecl *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); return First->InstantiatedFromMember.getPointer(); } @@ -2000,7 +2043,7 @@ public: return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl(); } - ClassTemplateDecl *getInstantiatedFromMemberTemplate() { + ClassTemplateDecl *getInstantiatedFromMemberTemplate() const { return cast_or_null<ClassTemplateDecl>( RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } @@ -2230,7 +2273,7 @@ public: this)->getPreviousDecl()); } - TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() { + TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() const { return cast_or_null<TypeAliasTemplateDecl>( RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } @@ -2435,17 +2478,8 @@ public: /// explicit instantiation declaration, or explicit instantiation /// definition. bool isExplicitInstantiationOrSpecialization() const { - switch (getTemplateSpecializationKind()) { - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - return true; - - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - return false; - } - llvm_unreachable("bad template specialization kind"); + return isTemplateExplicitInstantiationOrSpecialization( + getTemplateSpecializationKind()); } void setSpecializationKind(TemplateSpecializationKind TSK) { @@ -2668,8 +2702,8 @@ public: /// variable template partial specialization \c Outer<T>::Inner<U*>. Given /// \c Outer<float>::Inner<U*>, this function would return /// \c Outer<T>::Inner<U*>. - VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() { - VarTemplatePartialSpecializationDecl *First = + VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const { + const VarTemplatePartialSpecializationDecl *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); return First->InstantiatedFromMember.getPointer(); } @@ -2833,7 +2867,7 @@ public: return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl(); } - VarTemplateDecl *getInstantiatedFromMemberTemplate() { + VarTemplateDecl *getInstantiatedFromMemberTemplate() const { return cast_or_null<VarTemplateDecl>( RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index ad52873..aad7726 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -88,8 +88,8 @@ public: void VisitLambdaExpr(PTR(LambdaExpr) LE) { // Only visit the capture initializers, and not the body. - for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(), - E = LE->capture_init_end(); + for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(), + E = LE->capture_init_end(); I != E; ++I) if (*I) this->Visit(*I); diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2a5b4c0..f9f1995 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -23,6 +23,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" @@ -61,7 +62,6 @@ struct SubobjectAdjustment { MemberPointerAdjustment } Kind; - struct DTB { const CastExpr *BasePath; const CXXRecordDecl *DerivedClass; @@ -148,8 +148,6 @@ public: /// \brief Set whether this expression is value-dependent or not. void setValueDependent(bool VD) { ExprBits.ValueDependent = VD; - if (VD) - ExprBits.InstantiationDependent = true; } /// isTypeDependent - Determines whether this expression is @@ -168,8 +166,6 @@ public: /// \brief Set whether this expression is type-dependent or not. void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; - if (TD) - ExprBits.InstantiationDependent = true; } /// \brief Whether this expression is instantiation-dependent, meaning that @@ -458,6 +454,10 @@ public: /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; + /// \brief Returns whether this expression refers to a global register + /// variable. + bool refersToGlobalRegisterVar() const; + /// \brief Returns whether this expression has a placeholder type. bool hasPlaceholderType() const { return getType()->isPlaceholderType(); @@ -529,10 +529,15 @@ public: /// EvalStatus is a struct with detailed info about an evaluation in progress. struct EvalStatus { - /// HasSideEffects - Whether the evaluated expression has side effects. + /// \brief Whether the evaluated expression has side effects. /// For example, (f() && 0) can be folded, but it still has side effects. bool HasSideEffects; + /// \brief Whether the evaluation hit undefined behavior. + /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior. + /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. + bool HasUndefinedBehavior; + /// Diag - If this is non-null, it will be filled in with a stack of notes /// indicating why evaluation failed (or why it failed to produce a constant /// expression). @@ -542,7 +547,8 @@ public: /// expression *is* a constant expression, no notes will be produced. SmallVectorImpl<PartialDiagnosticAt> *Diag; - EvalStatus() : HasSideEffects(false), Diag(nullptr) {} + EvalStatus() + : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {} // hasSideEffects - Return true if the evaluated expression has // side effects. @@ -575,7 +581,12 @@ public: /// side-effects. bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; - enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects }; + enum SideEffectsKind { + SE_NoSideEffects, ///< Strictly evaluate the expression. + SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not + ///< arbitrary unmodeled side effects. + SE_AllowSideEffects ///< Allow any unmodeled side effect. + }; /// EvaluateAsInt - Return true if this is a constant which we can fold and /// convert to an integer, using any crazy technique that we want to. @@ -584,7 +595,8 @@ public: /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be /// constant folded without side-effects, but discard the result. - bool isEvaluatable(const ASTContext &Ctx) const; + bool isEvaluatable(const ASTContext &Ctx, + SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; /// HasSideEffects - This routine returns true for all those expressions /// which have any effect other than producing a value. Example is a function @@ -628,6 +640,16 @@ public: const FunctionDecl *Callee, ArrayRef<const Expr*> Args) const; + /// \brief If the current Expr is a pointer, this will try to statically + /// determine the number of bytes available where the pointer is pointing. + /// Returns true if all of the above holds and we were able to figure out the + /// size, false otherwise. + /// + /// \param Type - How to evaluate the size of the Expr, as defined by the + /// "type" parameter of __builtin_object_size + bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, + unsigned Type) const; + /// \brief Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). enum NullPointerConstantKind { @@ -806,7 +828,6 @@ public: } }; - //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// @@ -856,7 +877,9 @@ public: return Loc; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } /// The source expression of an opaque value expression is the /// expression which originally generated the value. This is @@ -896,7 +919,11 @@ public: /// DeclRefExprBits.RefersToEnclosingVariableOrCapture /// Specifies when this declaration reference expression (validly) /// refers to an enclosed local or a captured variable. -class DeclRefExpr : public Expr { +class DeclRefExpr final + : public Expr, + private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc, + NamedDecl *, ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { /// \brief The declaration that we are referencing. ValueDecl *D; @@ -907,36 +934,22 @@ class DeclRefExpr : public Expr { /// embedded in D. DeclarationNameLoc DNLoc; - /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. - NestedNameSpecifierLoc &getInternalQualifierLoc() { - assert(hasQualifier()); - return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1); + size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const { + return hasQualifier() ? 1 : 0; + } + + size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { + return hasFoundDecl() ? 1 : 0; } - /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. - const NestedNameSpecifierLoc &getInternalQualifierLoc() const { - return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc(); + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo() ? 1 : 0; } /// \brief Test whether there is a distinct FoundDecl attached to the end of /// this DRE. bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } - /// \brief Helper to retrieve the optional NamedDecl through which this - /// reference occurred. - NamedDecl *&getInternalFoundDecl() { - assert(hasFoundDecl()); - if (hasQualifier()) - return *reinterpret_cast<NamedDecl **>(&getInternalQualifierLoc() + 1); - return *reinterpret_cast<NamedDecl **>(this + 1); - } - - /// \brief Helper to retrieve the optional NamedDecl through which this - /// reference occurred. - NamedDecl *getInternalFoundDecl() const { - return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl(); - } - DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -1009,21 +1022,17 @@ public: bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } /// \brief If the name was qualified, retrieves the nested-name-specifier - /// that precedes the name. Otherwise, returns NULL. - NestedNameSpecifier *getQualifier() const { - if (!hasQualifier()) - return nullptr; - - return getInternalQualifierLoc().getNestedNameSpecifier(); - } - - /// \brief If the name was qualified, retrieves the nested-name-specifier /// that precedes the name, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { if (!hasQualifier()) return NestedNameSpecifierLoc(); + return *getTrailingObjects<NestedNameSpecifierLoc>(); + } - return getInternalQualifierLoc(); + /// \brief If the name was qualified, retrieves the nested-name-specifier + /// that precedes the name. Otherwise, returns NULL. + NestedNameSpecifier *getQualifier() const { + return getQualifierLoc().getNestedNameSpecifier(); } /// \brief Get the NamedDecl through which this reference occurred. @@ -1031,60 +1040,40 @@ public: /// This Decl may be different from the ValueDecl actually referred to in the /// presence of using declarations, etc. It always returns non-NULL, and may /// simple return the ValueDecl when appropriate. + NamedDecl *getFoundDecl() { - return hasFoundDecl() ? getInternalFoundDecl() : D; + return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; } /// \brief Get the NamedDecl through which this reference occurred. /// See non-const variant. const NamedDecl *getFoundDecl() const { - return hasFoundDecl() ? getInternalFoundDecl() : D; + return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; } bool hasTemplateKWAndArgsInfo() const { return DeclRefExprBits.HasTemplateKWAndArgsInfo; } - /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!hasTemplateKWAndArgsInfo()) - return nullptr; - - if (hasFoundDecl()) - return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( - &getInternalFoundDecl() + 1); - - if (hasQualifier()) - return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( - &getInternalQualifierLoc() + 1); - - return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1); - } - - /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<DeclRefExpr*>(this)->getTemplateKWAndArgsInfo(); - } - /// \brief Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } /// \brief Determines whether the name in this declaration reference @@ -1095,32 +1084,12 @@ public: /// explicit template argument list. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *getTemplateKWAndArgsInfo(); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs(); - } - - /// \brief Retrieves the optional explicit template arguments. - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); - } - /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) - getExplicitTemplateArgs().copyInto(List); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); } /// \brief Retrieve the template arguments provided as part of this @@ -1129,7 +1098,7 @@ public: if (!hasExplicitTemplateArgs()) return nullptr; - return getExplicitTemplateArgs().getTemplateArgs(); + return getTrailingObjects<TemplateArgumentLoc>(); } /// \brief Retrieve the number of template arguments provided as part of this @@ -1138,7 +1107,7 @@ public: if (!hasExplicitTemplateArgs()) return 0; - return getExplicitTemplateArgs().NumTemplateArgs; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; } /// \brief Returns true if this expression refers to a function that @@ -1164,8 +1133,11 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -1310,7 +1282,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; class CharacterLiteral : public Expr { @@ -1357,7 +1331,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; class FloatingLiteral : public Expr, private APFloatStorage { @@ -1419,7 +1395,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// ImaginaryLiteral - We support imaginary integer and floating point literals, @@ -1596,13 +1574,15 @@ public: /// and can have escape sequences in them in addition to the usual trigraph /// and escaped newline business. This routine handles this complexity. /// - SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, - const LangOptions &Features, - const TargetInfo &Target) const; + SourceLocation + getLocationOfByte(unsigned ByteNo, const SourceManager &SM, + const LangOptions &Features, const TargetInfo &Target, + unsigned *StartToken = nullptr, + unsigned *StartTokenByteOffset = nullptr) const; typedef const SourceLocation *tokloc_iterator; tokloc_iterator tokloc_begin() const { return TokLocs; } - tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; } + tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; } SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; } SourceLocation getLocEnd() const LLVM_READONLY { @@ -1614,7 +1594,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// ParenExpr - This represents a parethesized expression, e.g. "(1)". This @@ -1658,7 +1640,6 @@ public: child_range children() { return child_range(&Val, &Val+1); } }; - /// UnaryOperator - This represents the unary-expression's (except sizeof and /// alignof), the postinc/postdec operators from postfix-expression, and various /// extensions. @@ -1768,6 +1749,99 @@ public: child_range children() { return child_range(&Val, &Val+1); } }; +/// Helper class for OffsetOfExpr. + +// __builtin_offsetof(type, identifier(.identifier|[expr])*) +class OffsetOfNode { +public: + /// \brief The kind of offsetof node we have. + enum Kind { + /// \brief An index into an array. + Array = 0x00, + /// \brief A field. + Field = 0x01, + /// \brief A field in a dependent type, known only by its name. + Identifier = 0x02, + /// \brief An implicit indirection through a C++ base class, when the + /// field found is in a base class. + Base = 0x03 + }; + +private: + enum { MaskBits = 2, Mask = 0x03 }; + + /// \brief The source range that covers this part of the designator. + SourceRange Range; + + /// \brief The data describing the designator, which comes in three + /// different forms, depending on the lower two bits. + /// - An unsigned index into the array of Expr*'s stored after this node + /// in memory, for [constant-expression] designators. + /// - A FieldDecl*, for references to a known field. + /// - An IdentifierInfo*, for references to a field with a given name + /// when the class type is dependent. + /// - A CXXBaseSpecifier*, for references that look at a field in a + /// base class. + uintptr_t Data; + +public: + /// \brief Create an offsetof node that refers to an array element. + OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, + SourceLocation RBracketLoc) + : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {} + + /// \brief Create an offsetof node that refers to a field. + OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc) + : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), + Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {} + + /// \brief Create an offsetof node that refers to an identifier. + OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, + SourceLocation NameLoc) + : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), + Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {} + + /// \brief Create an offsetof node that refers into a C++ base class. + explicit OffsetOfNode(const CXXBaseSpecifier *Base) + : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} + + /// \brief Determine what kind of offsetof node this is. + Kind getKind() const { return static_cast<Kind>(Data & Mask); } + + /// \brief For an array element node, returns the index into the array + /// of expressions. + unsigned getArrayExprIndex() const { + assert(getKind() == Array); + return Data >> 2; + } + + /// \brief For a field offsetof node, returns the field. + FieldDecl *getField() const { + assert(getKind() == Field); + return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); + } + + /// \brief For a field or identifier offsetof node, returns the name of + /// the field. + IdentifierInfo *getFieldName() const; + + /// \brief For a base class node, returns the base specifier. + CXXBaseSpecifier *getBase() const { + assert(getKind() == Base); + return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); + } + + /// \brief Retrieve the source range that covers this offsetof node. + /// + /// For an array element node, the source range contains the locations of + /// the square brackets. For a field or identifier node, the source range + /// contains the location of the period (if there is one) and the + /// identifier. + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } +}; + /// OffsetOfExpr - [C99 7.17] - This represents an expression of the form /// offsetof(record-type, member-designator). For example, given: /// @code @@ -1782,104 +1856,9 @@ public: /// @endcode /// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). -class OffsetOfExpr : public Expr { -public: - // __builtin_offsetof(type, identifier(.identifier|[expr])*) - class OffsetOfNode { - public: - /// \brief The kind of offsetof node we have. - enum Kind { - /// \brief An index into an array. - Array = 0x00, - /// \brief A field. - Field = 0x01, - /// \brief A field in a dependent type, known only by its name. - Identifier = 0x02, - /// \brief An implicit indirection through a C++ base class, when the - /// field found is in a base class. - Base = 0x03 - }; - - private: - enum { MaskBits = 2, Mask = 0x03 }; - - /// \brief The source range that covers this part of the designator. - SourceRange Range; - - /// \brief The data describing the designator, which comes in three - /// different forms, depending on the lower two bits. - /// - An unsigned index into the array of Expr*'s stored after this node - /// in memory, for [constant-expression] designators. - /// - A FieldDecl*, for references to a known field. - /// - An IdentifierInfo*, for references to a field with a given name - /// when the class type is dependent. - /// - A CXXBaseSpecifier*, for references that look at a field in a - /// base class. - uintptr_t Data; - - public: - /// \brief Create an offsetof node that refers to an array element. - OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, - SourceLocation RBracketLoc) - : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { } - - /// \brief Create an offsetof node that refers to a field. - OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, - SourceLocation NameLoc) - : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), - Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { } - - /// \brief Create an offsetof node that refers to an identifier. - OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, - SourceLocation NameLoc) - : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), - Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { } - - /// \brief Create an offsetof node that refers into a C++ base class. - explicit OffsetOfNode(const CXXBaseSpecifier *Base) - : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} - - /// \brief Determine what kind of offsetof node this is. - Kind getKind() const { - return static_cast<Kind>(Data & Mask); - } - - /// \brief For an array element node, returns the index into the array - /// of expressions. - unsigned getArrayExprIndex() const { - assert(getKind() == Array); - return Data >> 2; - } - - /// \brief For a field offsetof node, returns the field. - FieldDecl *getField() const { - assert(getKind() == Field); - return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); - } - - /// \brief For a field or identifier offsetof node, returns the name of - /// the field. - IdentifierInfo *getFieldName() const; - - /// \brief For a base class node, returns the base specifier. - CXXBaseSpecifier *getBase() const { - assert(getKind() == Base); - return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); - } - - /// \brief Retrieve the source range that covers this offsetof node. - /// - /// For an array element node, the source range contains the locations of - /// the square brackets. For a field or identifier node, the source range - /// contains the location of the period (if there is one) and the - /// identifier. - SourceRange getSourceRange() const LLVM_READONLY { return Range; } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - }; - -private: - +class OffsetOfExpr final + : public Expr, + private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> { SourceLocation OperatorLoc, RParenLoc; // Base type; TypeSourceInfo *TSInfo; @@ -1888,6 +1867,10 @@ private: // Number of sub-expressions (i.e. array subscript expressions). unsigned NumExprs; + size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const { + return NumComps; + } + OffsetOfExpr(const ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs, @@ -1924,12 +1907,12 @@ public: const OffsetOfNode &getComponent(unsigned Idx) const { assert(Idx < NumComps && "Subscript out of range"); - return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx]; + return getTrailingObjects<OffsetOfNode>()[Idx]; } void setComponent(unsigned Idx, OffsetOfNode ON) { assert(Idx < NumComps && "Subscript out of range"); - reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON; + getTrailingObjects<OffsetOfNode>()[Idx] = ON; } unsigned getNumComponents() const { @@ -1938,17 +1921,17 @@ public: Expr* getIndexExpr(unsigned Idx) { assert(Idx < NumExprs && "Subscript out of range"); - return reinterpret_cast<Expr **>( - reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx]; + return getTrailingObjects<Expr *>()[Idx]; } + const Expr *getIndexExpr(unsigned Idx) const { - return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx); + assert(Idx < NumExprs && "Subscript out of range"); + return getTrailingObjects<Expr *>()[Idx]; } void setIndexExpr(unsigned Idx, Expr* E) { assert(Idx < NumComps && "Subscript out of range"); - reinterpret_cast<Expr **>( - reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E; + getTrailingObjects<Expr *>()[Idx] = E; } unsigned getNumExpressions() const { @@ -1964,11 +1947,10 @@ public: // Iterators child_range children() { - Stmt **begin = - reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1) - + NumComps); + Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); return child_range(begin, begin + NumExprs); } + friend TrailingObjects; }; /// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) @@ -2142,7 +2124,6 @@ public: } }; - /// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). /// CallExpr itself represents a normal function call, e.g., "f(x, 2)", /// while its subclasses may represent alternative syntax that (semantically) @@ -2298,20 +2279,24 @@ public: } }; +/// Extra data stored in some MemberExpr objects. +struct MemberExprNameQualifier { + /// \brief The nested-name-specifier that qualifies the name, including + /// source-location information. + NestedNameSpecifierLoc QualifierLoc; + + /// \brief The DeclAccessPair through which the MemberDecl was found due to + /// name qualifiers. + DeclAccessPair FoundDecl; +}; + /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// -class MemberExpr : public Expr { - /// Extra data stored in some member expressions. - struct MemberNameQualifier { - /// \brief The nested-name-specifier that qualifies the name, including - /// source-location information. - NestedNameSpecifierLoc QualifierLoc; - - /// \brief The DeclAccessPair through which the MemberDecl was found due to - /// name qualifiers. - DeclAccessPair FoundDecl; - }; - +class MemberExpr final + : public Expr, + private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { /// Base - the expression for the base pointer or structure references. In /// X.F, this is "X". Stmt *Base; @@ -2335,7 +2320,7 @@ class MemberExpr : public Expr { /// \brief True if this member expression used a nested-name-specifier to /// refer to the member, e.g., "x->Base::f", or found its member via a using - /// declaration. When true, a MemberNameQualifier + /// declaration. When true, a MemberExprNameQualifier /// structure is allocated immediately after the MemberExpr. bool HasQualifierOrFoundDecl : 1; @@ -2343,24 +2328,19 @@ class MemberExpr : public Expr { /// and/or a template argument list explicitly, e.g., x->f<int>, /// x->template f, x->template f<int>. /// When true, an ASTTemplateKWAndArgsInfo structure and its - /// TemplateArguments (if any) are allocated immediately after - /// the MemberExpr or, if the member expression also has a qualifier, - /// after the MemberNameQualifier structure. + /// TemplateArguments (if any) are present. bool HasTemplateKWAndArgsInfo : 1; /// \brief True if this member expression refers to a method that /// was resolved from an overloaded set having size greater than 1. bool HadMultipleCandidates : 1; - /// \brief Retrieve the qualifier that preceded the member name, if any. - MemberNameQualifier *getMemberQualifier() { - assert(HasQualifierOrFoundDecl); - return reinterpret_cast<MemberNameQualifier *> (this + 1); + size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const { + return HasQualifierOrFoundDecl ? 1 : 0; } - /// \brief Retrieve the qualifier that preceded the member name, if any. - const MemberNameQualifier *getMemberQualifier() const { - return const_cast<MemberExpr *>(this)->getMemberQualifier(); + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; } public: @@ -2416,7 +2396,7 @@ public: if (!HasQualifierOrFoundDecl) return DeclAccessPair::make(getMemberDecl(), getMemberDecl()->getAccess()); - return getMemberQualifier()->FoundDecl; + return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl; } /// \brief Determines whether this member expression actually had @@ -2425,61 +2405,41 @@ public: bool hasQualifier() const { return getQualifier() != nullptr; } /// \brief If the member name was qualified, retrieves the - /// nested-name-specifier that precedes the member name. Otherwise, returns - /// NULL. - NestedNameSpecifier *getQualifier() const { - if (!HasQualifierOrFoundDecl) - return nullptr; - - return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier(); - } - - /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name, with source-location /// information. NestedNameSpecifierLoc getQualifierLoc() const { - if (!hasQualifier()) - return NestedNameSpecifierLoc(); - - return getMemberQualifier()->QualifierLoc; - } - - /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) - return nullptr; - if (!HasQualifierOrFoundDecl) - return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1); + return NestedNameSpecifierLoc(); - return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( - getMemberQualifier() + 1); + return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc; } - /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<MemberExpr*>(this)->getTemplateKWAndArgsInfo(); + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name. Otherwise, returns + /// NULL. + NestedNameSpecifier *getQualifier() const { + return getQualifierLoc().getNestedNameSpecifier(); } /// \brief Retrieve the location of the template keyword preceding /// the member name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the member name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the member name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } /// Determines whether the member name was preceded by the template keyword. @@ -2493,30 +2453,8 @@ public: /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) - getExplicitTemplateArgs().copyInto(List); - } - - /// \brief Retrieve the explicit template argument list that - /// follow the member template name. This must only be called on an - /// expression with explicit template arguments. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *getTemplateKWAndArgsInfo(); - } - - /// \brief Retrieve the explicit template argument list that - /// followed the member template name. This must only be called on - /// an expression with explicit template arguments. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs(); - } - - /// \brief Retrieves the optional explicit template arguments. - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); } /// \brief Retrieve the template arguments provided as part of this @@ -2525,7 +2463,7 @@ public: if (!hasExplicitTemplateArgs()) return nullptr; - return getExplicitTemplateArgs().getTemplateArgs(); + return getTrailingObjects<TemplateArgumentLoc>(); } /// \brief Retrieve the number of template arguments provided as part of this @@ -2534,7 +2472,7 @@ public: if (!hasExplicitTemplateArgs()) return 0; - return getExplicitTemplateArgs().NumTemplateArgs; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; } /// \brief Retrieve the member declaration name info. @@ -2575,6 +2513,14 @@ public: HadMultipleCandidates = V; } + /// \brief Returns true if virtual dispatch is performed. + /// If the member access is fully qualified, (i.e. X::f()), virtual + /// dispatching is not performed. In -fapple-kext mode qualified + /// calls to virtual method will still go through the vtable. + bool performsVirtualDispatch(const LangOptions &LO) const { + return LO.AppleKext || !hasQualifier(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } @@ -2582,6 +2528,7 @@ public: // Iterators child_range children() { return child_range(&Base, &Base+1); } + friend TrailingObjects; friend class ASTReader; friend class ASTStmtWriter; }; @@ -2731,8 +2678,6 @@ public: path_const_iterator path_begin() const { return path_buffer(); } path_const_iterator path_end() const { return path_buffer() + path_size(); } - void setCastPath(const CXXCastPath &Path); - static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCastExprConstant && T->getStmtClass() <= lastCastExprConstant; @@ -2762,7 +2707,9 @@ public: /// // to an xvalue of type Base /// } /// @endcode -class ImplicitCastExpr : public CastExpr { +class ImplicitCastExpr final + : public CastExpr, + private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> { private: ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, unsigned BasePathLength, ExprValueKind VK) @@ -2798,6 +2745,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitCastExprClass; } + + friend TrailingObjects; + friend class CastExpr; }; inline Expr *Expr::IgnoreImpCasts() { @@ -2857,7 +2807,9 @@ public: /// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style /// cast in C++ (C++ [expr.cast]), which uses the syntax /// (Type)expr. For example: @c (int)f. -class CStyleCastExpr : public ExplicitCastExpr { +class CStyleCastExpr final + : public ExplicitCastExpr, + private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren @@ -2895,6 +2847,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CStyleCastExprClass; } + + friend TrailingObjects; + friend class CastExpr; }; /// \brief A builtin binary operation expression such as "x + y" or "x <= y". @@ -2989,7 +2944,10 @@ public: /// predicates to categorize the respective opcodes. bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; } - bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; } + static bool isMultiplicativeOp(Opcode Opc) { + return Opc >= BO_Mul && Opc <= BO_Rem; + } + bool isMultiplicativeOp() const { return isMultiplicativeOp(getOpcode()); } static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; } bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); } static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; } @@ -3384,7 +3342,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}). @@ -3429,7 +3389,6 @@ public: child_range children() { return child_range(&SubStmt, &SubStmt+1); } }; - /// ShuffleVectorExpr - clang-specific builtin-in function /// __builtin_shufflevector. /// This AST node represents a operator that does a constant @@ -3663,36 +3622,40 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; -/// VAArgExpr, used for the builtin function __builtin_va_arg. +/// Represents a call to the builtin function \c __builtin_va_arg. class VAArgExpr : public Expr { Stmt *Val; - TypeSourceInfo *TInfo; + llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo; SourceLocation BuiltinLoc, RParenLoc; public: - VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo, - SourceLocation RPLoc, QualType t) - : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, - t->isDependentType(), false, - (TInfo->getType()->isInstantiationDependentType() || - e->isInstantiationDependent()), - (TInfo->getType()->containsUnexpandedParameterPack() || - e->containsUnexpandedParameterPack())), - Val(e), TInfo(TInfo), - BuiltinLoc(BLoc), - RParenLoc(RPLoc) { } - - /// \brief Create an empty __builtin_va_arg expression. - explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { } + VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo, + SourceLocation RPLoc, QualType t, bool IsMS) + : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(), + false, (TInfo->getType()->isInstantiationDependentType() || + e->isInstantiationDependent()), + (TInfo->getType()->containsUnexpandedParameterPack() || + e->containsUnexpandedParameterPack())), + Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {} + + /// Create an empty __builtin_va_arg expression. + explicit VAArgExpr(EmptyShell Empty) + : Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {} const Expr *getSubExpr() const { return cast<Expr>(Val); } Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; } - void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; } + /// Returns whether this is really a Win64 ABI va_arg expression. + bool isMicrosoftABI() const { return TInfo.getInt(); } + void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); } + + TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); } + void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } @@ -3791,6 +3754,10 @@ public: /// \brief Retrieve the set of initializers. Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } + ArrayRef<Expr *> inits() { + return llvm::makeArrayRef(getInits(), getNumInits()); + } + const Expr *getInit(unsigned Init) const { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null<Expr>(InitExprs[Init]); @@ -3916,7 +3883,8 @@ public: // Iterators child_range children() { // FIXME: This does not include the array filler expression. - if (InitExprs.empty()) return child_range(); + if (InitExprs.empty()) + return child_range(child_iterator(), child_iterator()); return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size()); } @@ -4293,7 +4261,9 @@ public: SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; // In cases like: @@ -4367,10 +4337,11 @@ public: SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; - class ParenListExpr : public Expr { Stmt **Exprs; unsigned NumExprs; @@ -4397,6 +4368,10 @@ public: Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); } + ArrayRef<Expr *> exprs() { + return llvm::makeArrayRef(getExprs(), getNumExprs()); + } + SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -4416,7 +4391,6 @@ public: friend class ASTStmtWriter; }; - /// \brief Represents a C11 generic selection. /// /// A generic selection (C11 6.5.1.1) contains an unevaluated controlling @@ -4532,7 +4506,6 @@ public: // Clang Extensions //===----------------------------------------------------------------------===// - /// ExtVectorElementExpr - This represents access to specific elements of a /// vector, and may occur on the left hand side or right hand side. For example /// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. @@ -4577,7 +4550,7 @@ public: /// getEncodedElementAccess - Encode the elements accessed into an llvm /// aggregate Constant of ConstantInt(s). - void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const; + void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const; SourceLocation getLocStart() const LLVM_READONLY { return getBase()->getLocStart(); @@ -4596,7 +4569,6 @@ public: child_range children() { return child_range(&Base, &Base+1); } }; - /// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } class BlockExpr : public Expr { @@ -4633,7 +4605,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] @@ -4789,6 +4763,14 @@ public: const_semantics_iterator semantics_end() const { return getSubExprsBuffer() + getNumSubExprs(); } + + llvm::iterator_range<semantics_iterator> semantics() { + return llvm::make_range(semantics_begin(), semantics_end()); + } + llvm::iterator_range<const_semantics_iterator> semantics() const { + return llvm::make_range(semantics_begin(), semantics_end()); + } + Expr *getSemanticExpr(unsigned index) { assert(index + 1 < getNumSubExprs()); return getSubExprsBuffer()[index + 1]; @@ -4935,10 +4917,17 @@ public: assert(T->isDependentType() && "TypoExpr given a non-dependent type"); } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == TypoExprClass; + } + }; -} // end namespace clang +} // end namespace clang -#endif +#endif // LLVM_CLANG_AST_EXPR_H diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 1dbf574..707aeed 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -235,7 +235,9 @@ public: /// /// This expression node represents a C++ static cast, e.g., /// \c static_cast<int>(1.0). -class CXXStaticCastExpr : public CXXNamedCastExpr { +class CXXStaticCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> { CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -259,6 +261,9 @@ 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]). @@ -266,7 +271,9 @@ public: /// This expression node represents a dynamic cast, e.g., /// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time /// check to determine how to perform the type conversion. -class CXXDynamicCastExpr : public CXXNamedCastExpr { +class CXXDynamicCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> { CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -293,6 +300,9 @@ 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]). @@ -303,7 +313,10 @@ public: /// A reinterpret_cast provides a differently-typed view of a value but /// (in Clang, as in most C++ implementations) performs no actual work at /// run time. -class CXXReinterpretCastExpr : public CXXNamedCastExpr { +class CXXReinterpretCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXReinterpretCastExpr, + CXXBaseSpecifier *> { CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, @@ -328,6 +341,9 @@ 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]). @@ -337,7 +353,9 @@ public: /// /// A const_cast can remove type qualifiers but does not change the underlying /// value. -class CXXConstCastExpr : public CXXNamedCastExpr { +class CXXConstCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> { CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) @@ -358,6 +376,9 @@ 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]) @@ -457,7 +478,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief The null pointer literal (C++11 [lex.nullptr]) @@ -484,7 +507,9 @@ public: return T->getStmtClass() == CXXNullPtrLiteralExprClass; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Implicit construction of a std::initializer_list<T> object from an @@ -607,7 +632,8 @@ public: // Iterators child_range children() { - if (isTypeOperand()) return child_range(); + if (isTypeOperand()) + return child_range(child_iterator(), child_iterator()); Stmt **begin = reinterpret_cast<Stmt**>(&Operand); return child_range(begin, begin + 1); } @@ -672,6 +698,69 @@ public: friend class ASTStmtReader; }; +/// MS property subscript expression. +/// MSVC supports 'property' attribute and allows to apply it to the +/// declaration of an empty array in a class or structure definition. +/// For example: +/// \code +/// __declspec(property(get=GetX, put=PutX)) int x[]; +/// \endcode +/// The above statement indicates that x[] can be used with one or more array +/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and +/// p->x[a][b] = i will be turned into p->PutX(a, b, i). +/// 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; + + void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; } + void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; } + +public: + MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK, + ExprObjectKind OK, SourceLocation RBracketLoc) + : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(), + Idx->isValueDependent(), Idx->isInstantiationDependent(), + Idx->containsUnexpandedParameterPack()), + RBracketLoc(RBracketLoc) { + SubExprs[BASE_EXPR] = Base; + SubExprs[IDX_EXPR] = Idx; + } + + /// \brief Create an empty array subscript expression. + explicit MSPropertySubscriptExpr(EmptyShell Shell) + : Expr(MSPropertySubscriptExprClass, Shell) {} + + Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); } + const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); } + + Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); } + const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); } + + SourceLocation getLocStart() const LLVM_READONLY { + return getBase()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } + + SourceLocation getRBracketLoc() const { return RBracketLoc; } + void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } + + SourceLocation getExprLoc() const LLVM_READONLY { + return getBase()->getExprLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSPropertySubscriptExprClass; + } + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS); + } +}; + /// A Microsoft C++ @c __uuidof expression, which gets /// the _GUID that corresponds to the supplied type or expression. /// @@ -749,7 +838,8 @@ public: // Iterators child_range children() { - if (isTypeOperand()) return child_range(); + if (isTypeOperand()) + return child_range(child_iterator(), child_iterator()); Stmt **begin = reinterpret_cast<Stmt**>(&Operand); return child_range(begin, begin + 1); } @@ -797,7 +887,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief A C++ throw-expression (C++ [except.throw]). @@ -935,7 +1027,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -991,7 +1085,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTReader; friend class ASTStmtReader; @@ -1238,7 +1334,9 @@ public: /// \code /// x = int(0.5); /// \endcode -class CXXFunctionalCastExpr : public ExplicitCastExpr { +class CXXFunctionalCastExpr final + : public ExplicitCastExpr, + private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> { SourceLocation LParenLoc; SourceLocation RParenLoc; @@ -1275,6 +1373,9 @@ 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 @@ -1401,25 +1502,39 @@ class LambdaExpr : public Expr { ExplicitResultType(false), HasArrayIndexVars(true) { getStoredStmts()[NumCaptures] = nullptr; } - - Stmt **getStoredStmts() const { - return reinterpret_cast<Stmt **>(const_cast<LambdaExpr *>(this) + 1); + + Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); } + + Stmt *const *getStoredStmts() const { + return reinterpret_cast<Stmt *const *>(this + 1); } - + /// \brief Retrieve the mapping from captures to the first array index /// variable. - unsigned *getArrayIndexStarts() const { + unsigned *getArrayIndexStarts() { return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1); } + const unsigned *getArrayIndexStarts() const { + return reinterpret_cast<const unsigned *>(getStoredStmts() + NumCaptures + + 1); + } + /// \brief Retrieve the complete set of array-index variables. - VarDecl **getArrayIndexVars() const { + VarDecl **getArrayIndexVars() { unsigned ArrayIndexSize = llvm::RoundUpToAlignment( sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>()); return reinterpret_cast<VarDecl **>( reinterpret_cast<char *>(getArrayIndexStarts()) + ArrayIndexSize); } + VarDecl *const *getArrayIndexVars() const { + unsigned ArrayIndexSize = llvm::RoundUpToAlignment( + sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>()); + return reinterpret_cast<VarDecl *const *>( + reinterpret_cast<const char *>(getArrayIndexStarts()) + ArrayIndexSize); + } + public: /// \brief Construct a new lambda expression. static LambdaExpr *Create(const ASTContext &C, @@ -1501,31 +1616,52 @@ public: /// arguments. typedef Expr **capture_init_iterator; + /// \brief Const iterator that walks over the capture initialization + /// arguments. + typedef Expr *const *const_capture_init_iterator; + + /// \brief Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range<capture_init_iterator> capture_inits() { + return llvm::make_range(capture_init_begin(), capture_init_end()); + } + /// \brief Retrieve the initialization expressions for this lambda's captures. - llvm::iterator_range<capture_init_iterator> capture_inits() const { - return llvm::iterator_range<capture_init_iterator>(capture_init_begin(), - capture_init_end()); + llvm::iterator_range<const_capture_init_iterator> capture_inits() const { + return llvm::make_range(capture_init_begin(), capture_init_end()); } /// \brief Retrieve the first initialization argument for this /// lambda expression (which initializes the first capture field). - capture_init_iterator capture_init_begin() const { + capture_init_iterator capture_init_begin() { return reinterpret_cast<Expr **>(getStoredStmts()); } + /// \brief Retrieve the first initialization argument for this + /// lambda expression (which initializes the first capture field). + const_capture_init_iterator capture_init_begin() const { + return reinterpret_cast<Expr *const *>(getStoredStmts()); + } + /// \brief Retrieve the iterator pointing one past the last /// initialization argument for this lambda expression. - capture_init_iterator capture_init_end() const { - return capture_init_begin() + NumCaptures; + capture_init_iterator capture_init_end() { + return capture_init_begin() + NumCaptures; } - /// \brief Retrieve the set of index variables used in the capture + /// \brief Retrieve the iterator pointing one past the last + /// initialization argument for this lambda expression. + const_capture_init_iterator capture_init_end() const { + return capture_init_begin() + NumCaptures; + } + + /// \brief Retrieve the set of index variables used in the capture /// initializer of an array captured by copy. /// - /// \param Iter The iterator that points at the capture initializer for + /// \param Iter The iterator that points at the capture initializer for /// which we are extracting the corresponding index variables. - ArrayRef<VarDecl *> getCaptureInitIndexVars(capture_init_iterator Iter) const; - + ArrayRef<VarDecl *> + getCaptureInitIndexVars(const_capture_init_iterator Iter) const; + /// \brief Retrieve the source range covering the lambda introducer, /// which contains the explicit capture list surrounded by square /// brackets ([...]). @@ -1615,7 +1751,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a new-expression for memory allocation and constructor @@ -1770,6 +1908,14 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; + llvm::iterator_range<arg_iterator> placement_arguments() { + return llvm::make_range(placement_arg_begin(), placement_arg_end()); + } + + llvm::iterator_range<const_arg_iterator> placement_arguments() const { + return llvm::make_range(placement_arg_begin(), placement_arg_end()); + } + arg_iterator placement_arg_begin() { return SubExprs + Array + hasInitializer(); } @@ -2164,8 +2310,10 @@ public: } // Iterators - child_range children() { return child_range(); } - + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + friend class ASTStmtReader; friend class ASTStmtWriter; @@ -2237,7 +2385,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; }; @@ -2294,7 +2444,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; }; @@ -2322,13 +2474,18 @@ protected: bool HasTemplateKWAndArgsInfo; /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo(); // defined far below. + ASTTemplateKWAndArgsInfo * + getTrailingASTTemplateKWAndArgsInfo(); // defined far below. /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<OverloadExpr*>(this)->getTemplateKWAndArgsInfo(); + const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { + return const_cast<OverloadExpr *>(this) + ->getTrailingASTTemplateKWAndArgsInfo(); } + /// Return the optional template arguments. + TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below + OverloadExpr(StmtClass K, const ASTContext &C, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -2391,7 +2548,7 @@ public: return UnresolvedSetIterator(Results + NumResults); } llvm::iterator_range<decls_iterator> decls() const { - return llvm::iterator_range<decls_iterator>(decls_begin(), decls_end()); + return llvm::make_range(decls_begin(), decls_end()); } /// \brief Gets the number of declarations in the unresolved set. @@ -2419,21 +2576,21 @@ public: /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; } /// \brief Determines whether the name was preceded by the template keyword. @@ -2442,39 +2599,23 @@ public: /// \brief Determines whether this expression had explicit template arguments. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - // Note that, inconsistently with the explicit-template-argument AST - // nodes, users are *forbidden* from calling these methods on objects - // without explicit template arguments. - - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *getTemplateKWAndArgsInfo(); - } - - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); - } - TemplateArgumentLoc const *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); + if (!hasExplicitTemplateArgs()) + return nullptr; + return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); } unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs; } /// \brief Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); - } - - /// \brief Retrieves the optional explicit template arguments. - /// - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); + if (hasExplicitTemplateArgs()) + getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List); } static bool classof(const Stmt *T) { @@ -2497,7 +2638,10 @@ public: /// /// These never include UnresolvedUsingValueDecls, which are always class /// members and therefore appear only in UnresolvedMemberLookupExprs. -class UnresolvedLookupExpr : public OverloadExpr { +class UnresolvedLookupExpr final + : public OverloadExpr, + private llvm::TrailingObjects< + UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { /// True if these lookup results should be extended by /// argument-dependent lookup if this is the operand of a function /// call. @@ -2514,6 +2658,10 @@ class UnresolvedLookupExpr : public OverloadExpr { /// against the qualified-lookup bits. CXXRecordDecl *NamingClass; + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; + } + UnresolvedLookupExpr(const ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, @@ -2533,6 +2681,8 @@ class UnresolvedLookupExpr : public OverloadExpr { RequiresADL(false), Overloaded(false), NamingClass(nullptr) {} + friend TrailingObjects; + friend class OverloadExpr; friend class ASTStmtReader; public: @@ -2585,7 +2735,9 @@ public: return getNameInfo().getLocEnd(); } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } static bool classof(const Stmt *T) { return T->getStmtClass() == UnresolvedLookupExprClass; @@ -2606,7 +2758,11 @@ public: /// qualifier (X<T>::) and the name of the entity being referenced /// ("value"). Such expressions will instantiate to a DeclRefExpr once the /// declaration can be found. -class DependentScopeDeclRefExpr : public Expr { +class DependentScopeDeclRefExpr final + : public Expr, + private llvm::TrailingObjects<DependentScopeDeclRefExpr, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { /// \brief The nested-name-specifier that qualifies this unresolved /// declaration name. NestedNameSpecifierLoc QualifierLoc; @@ -2618,15 +2774,8 @@ class DependentScopeDeclRefExpr : public Expr { /// keyword and arguments. bool HasTemplateKWAndArgsInfo; - /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return nullptr; - return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); - } - /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<DependentScopeDeclRefExpr*>(this) - ->getTemplateKWAndArgsInfo(); + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; } DependentScopeDeclRefExpr(QualType T, @@ -2671,21 +2820,21 @@ public: /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } /// Determines whether the name was preceded by the template keyword. @@ -2694,42 +2843,26 @@ public: /// Determines whether this lookup had explicit template arguments. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - // Note that, inconsistently with the explicit-template-argument AST - // nodes, users are *forbidden* from calling these methods on objects - // without explicit template arguments. - - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<ASTTemplateArgumentListInfo*>(this + 1); - } - - /// Gets a reference to the explicit template argument list. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<const ASTTemplateArgumentListInfo*>(this + 1); - } - - /// \brief Retrieves the optional explicit template arguments. - /// - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); - } - /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); + if (hasExplicitTemplateArgs()) + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); } TemplateArgumentLoc const *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); + if (!hasExplicitTemplateArgs()) + return nullptr; + + return getTrailingObjects<TemplateArgumentLoc>(); } unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; } /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr, @@ -2747,8 +2880,11 @@ public: return T->getStmtClass() == DependentScopeDeclRefExprClass; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -2951,7 +3087,11 @@ public: /// Like UnresolvedMemberExprs, these can be either implicit or /// explicit accesses. It is only possible to get one of these with /// an implicit access if a qualifier is provided. -class CXXDependentScopeMemberExpr : public Expr { +class CXXDependentScopeMemberExpr final + : public Expr, + private llvm::TrailingObjects<CXXDependentScopeMemberExpr, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { /// \brief The expression for the base pointer or class reference, /// e.g., the \c x in x.f. Can be null in implicit accesses. Stmt *Base; @@ -2989,15 +3129,8 @@ class CXXDependentScopeMemberExpr : public Expr { /// FIXME: could also be a template-id DeclarationNameInfo MemberNameInfo; - /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return nullptr; - return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); - } - /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<CXXDependentScopeMemberExpr*>(this) - ->getTemplateKWAndArgsInfo(); + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; } CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, @@ -3093,21 +3226,21 @@ public: /// member name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the member name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the member name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } /// Determines whether the member name was preceded by the template keyword. @@ -3117,50 +3250,30 @@ public: /// template argument list explicitly specified, e.g., x.f<int>. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - return const_cast<CXXDependentScopeMemberExpr *>(this) - ->getExplicitTemplateArgs(); - } - - /// \brief Retrieves the optional explicit template arguments. - /// - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); - } - /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); - } - - /// \brief Initializes the template arguments using the given structure. - void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) { - getExplicitTemplateArgs().initializeFrom(List); + if (hasExplicitTemplateArgs()) + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); + if (!hasExplicitTemplateArgs()) + return nullptr; + + return getTrailingObjects<TemplateArgumentLoc>(); } /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; } SourceLocation getLocStart() const LLVM_READONLY { @@ -3169,8 +3282,8 @@ public: if (getQualifier()) return getQualifierLoc().getBeginLoc(); return MemberNameInfo.getBeginLoc(); - } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); @@ -3183,10 +3296,12 @@ public: // Iterators child_range children() { - if (isImplicitAccess()) return child_range(); + if (isImplicitAccess()) + return child_range(child_iterator(), child_iterator()); return child_range(&Base, &Base + 1); } + friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -3206,7 +3321,10 @@ public: /// In the final AST, an explicit access always becomes a MemberExpr. /// An implicit access may become either a MemberExpr or a /// DeclRefExpr, depending on whether the member is static. -class UnresolvedMemberExpr : public OverloadExpr { +class UnresolvedMemberExpr final + : public OverloadExpr, + private llvm::TrailingObjects< + UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { /// \brief Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; @@ -3227,6 +3345,10 @@ class UnresolvedMemberExpr : public OverloadExpr { /// \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, @@ -3240,6 +3362,8 @@ class UnresolvedMemberExpr : public OverloadExpr { : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), HasUnresolvedUsing(false), Base(nullptr) { } + friend TrailingObjects; + friend class OverloadExpr; friend class ASTStmtReader; public: @@ -3325,11 +3449,34 @@ public: // Iterators child_range children() { - if (isImplicitAccess()) return child_range(); + if (isImplicitAccess()) + return child_range(child_iterator(), child_iterator()); return child_range(&Base, &Base + 1); } }; +inline ASTTemplateKWAndArgsInfo * +OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) + return nullptr; + + if (isa<UnresolvedLookupExpr>(this)) + return cast<UnresolvedLookupExpr>(this) + ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); + else + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); +} + +inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { + if (isa<UnresolvedLookupExpr>(this)) + return cast<UnresolvedLookupExpr>(this) + ->getTrailingObjects<TemplateArgumentLoc>(); + else + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<TemplateArgumentLoc>(); +} + /// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). /// /// The noexcept expression tests whether a given expression might throw. Its @@ -3451,15 +3598,6 @@ public: } }; -inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return nullptr; - if (isa<UnresolvedLookupExpr>(this)) - return reinterpret_cast<ASTTemplateKWAndArgsInfo*> - (cast<UnresolvedLookupExpr>(this) + 1); - else - return reinterpret_cast<ASTTemplateKWAndArgsInfo*> - (cast<UnresolvedMemberExpr>(this) + 1); -} /// \brief Represents an expression that computes the length of a parameter /// pack. @@ -3482,43 +3620,51 @@ class SizeOfPackExpr : public Expr { /// \brief The length of the parameter pack, if known. /// - /// When this expression is value-dependent, the length of the parameter pack - /// is unknown. When this expression is not value-dependent, the length is - /// known. + /// When this expression is not value-dependent, this is the length of + /// the pack. When the expression was parsed rather than instantiated + /// (and thus is value-dependent), this is zero. + /// + /// After partial substitution into a sizeof...(X) expression (for instance, + /// within an alias template or during function template argument deduction), + /// we store a trailing array of partially-substituted TemplateArguments, + /// and this is the length of that array. unsigned Length; - /// \brief The parameter pack itself. + /// \brief The parameter pack. NamedDecl *Pack; friend class ASTStmtReader; friend class ASTStmtWriter; -public: - /// \brief Create a value-dependent expression that computes the length of - /// the given parameter pack. - SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, - SourceLocation PackLoc, SourceLocation RParenLoc) - : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/true, - /*InstantiationDependent=*/true, - /*ContainsUnexpandedParameterPack=*/false), - OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), - Length(0), Pack(Pack) { } - /// \brief Create an expression that computes the length of - /// the given parameter pack, which is already known. + /// the given parameter pack. SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, - unsigned Length) - : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/false, - /*InstantiationDependent=*/false, - /*ContainsUnexpandedParameterPack=*/false), - OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), - Length(Length), Pack(Pack) { } + Optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs) + : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/!Length, + /*InstantiationDependent=*/!Length, + /*ContainsUnexpandedParameterPack=*/false), + OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), + Length(Length ? *Length : PartialArgs.size()), Pack(Pack) { + assert((!Length || PartialArgs.empty()) && + "have partial args for non-dependent sizeof... expression"); + TemplateArgument *Args = reinterpret_cast<TemplateArgument *>(this + 1); + std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args); + } /// \brief Create an empty expression. - SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { } + SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs) + : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs), Pack() {} + +public: + static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc, + NamedDecl *Pack, SourceLocation PackLoc, + SourceLocation RParenLoc, + Optional<unsigned> Length = None, + ArrayRef<TemplateArgument> PartialArgs = None); + static SizeOfPackExpr *CreateDeserialized(ASTContext &Context, + unsigned NumPartialArgs); /// \brief Determine the location of the 'sizeof' keyword. SourceLocation getOperatorLoc() const { return OperatorLoc; } @@ -3542,6 +3688,23 @@ public: return Length; } + /// \brief Determine whether this represents a partially-substituted sizeof... + /// expression, such as is produced for: + /// + /// template<typename ...Ts> using X = int[sizeof...(Ts)]; + /// template<typename ...Us> void f(X<Us..., 1, 2, 3, Us...>); + bool isPartiallySubstituted() const { + return isValueDependent() && Length; + } + + /// \brief Get + ArrayRef<TemplateArgument> getPartialArguments() const { + assert(isPartiallySubstituted()); + const TemplateArgument *Args = + reinterpret_cast<const TemplateArgument *>(this + 1); + return llvm::makeArrayRef(Args, Args + Length); + } + SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } @@ -3550,7 +3713,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a reference to a non-type template parameter @@ -3653,7 +3818,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a reference to a function parameter pack that has been @@ -3682,7 +3849,7 @@ class FunctionParmPackExpr : public Expr { FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, unsigned NumParams, - Decl * const *Params); + ParmVarDecl *const *Params); friend class ASTReader; friend class ASTStmtReader; @@ -3691,7 +3858,7 @@ public: static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, - ArrayRef<Decl *> Params); + ArrayRef<ParmVarDecl *> Params); static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context, unsigned NumParams); @@ -3720,7 +3887,9 @@ public: return T->getStmtClass() == FunctionParmPackExprClass; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a prvalue temporary that is written into memory so that @@ -3901,6 +4070,136 @@ public: child_range children() { return child_range(SubExprs, SubExprs + 2); } }; +/// \brief Represents an expression that might suspend coroutine execution; +/// either a co_await or co_yield expression. +/// +/// Evaluation of this expression first evaluates its 'ready' expression. If +/// that returns 'false': +/// -- execution of the coroutine is suspended +/// -- the 'suspend' expression is evaluated +/// -- if the 'suspend' expression returns 'false', the coroutine is +/// resumed +/// -- otherwise, control passes back to the resumer. +/// If the coroutine is not suspended, or when it is resumed, the 'resume' +/// expression is evaluated, and its result is the result of the overall +/// expression. +class CoroutineSuspendExpr : public Expr { + SourceLocation KeywordLoc; + + enum SubExpr { Common, Ready, Suspend, Resume, Count }; + Stmt *SubExprs[SubExpr::Count]; + + friend class ASTStmtReader; +public: + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common, + Expr *Ready, Expr *Suspend, Expr *Resume) + : Expr(SC, Resume->getType(), Resume->getValueKind(), + Resume->getObjectKind(), Resume->isTypeDependent(), + Resume->isValueDependent(), Common->isInstantiationDependent(), + Common->containsUnexpandedParameterPack()), + KeywordLoc(KeywordLoc) { + SubExprs[SubExpr::Common] = Common; + SubExprs[SubExpr::Ready] = Ready; + 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, + Common->containsUnexpandedParameterPack()), + KeywordLoc(KeywordLoc) { + assert(Common->isTypeDependent() && Ty->isDependentType() && + "wrong constructor for non-dependent co_await/co_yield expression"); + SubExprs[SubExpr::Common] = Common; + SubExprs[SubExpr::Ready] = nullptr; + SubExprs[SubExpr::Suspend] = nullptr; + SubExprs[SubExpr::Resume] = nullptr; + } + CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { + SubExprs[SubExpr::Common] = nullptr; + SubExprs[SubExpr::Ready] = nullptr; + SubExprs[SubExpr::Suspend] = nullptr; + SubExprs[SubExpr::Resume] = nullptr; + } + + SourceLocation getKeywordLoc() const { return KeywordLoc; } + Expr *getCommonExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Common]); + } + + 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]); + } + + SourceLocation getLocStart() const LLVM_READONLY { + return KeywordLoc; + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getCommonExpr()->getLocEnd(); + } + + child_range children() { + return child_range(SubExprs, SubExprs + SubExpr::Count); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoawaitExprClass || + T->getStmtClass() == CoyieldExprClass; + } +}; + +/// \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) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready, + Suspend, Resume) {} + CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {} + CoawaitExpr(EmptyShell Empty) + : CoroutineSuspendExpr(CoawaitExprClass, Empty) {} + + Expr *getOperand() const { + // FIXME: Dig out the actual operand or store it. + return getCommonExpr(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoawaitExprClass; + } +}; + +/// \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) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready, + Suspend, Resume) {} + CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {} + CoyieldExpr(EmptyShell Empty) + : CoroutineSuspendExpr(CoyieldExprClass, Empty) {} + + Expr *getOperand() const { + // FIXME: Dig out the actual operand or store it. + return getCommonExpr(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoyieldExprClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index f28e519..38fa718 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -82,7 +82,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// ObjCBoxedExpr - used for generalized expression boxing. @@ -341,6 +343,8 @@ public: child_range children() { // Note: we're taking advantage of the layout of the KeyValuePair struct // here. If that struct changes, this code will need to change as well. + static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2, + "KeyValuePair is expected size"); return child_range(reinterpret_cast<Stmt **>(this + 1), reinterpret_cast<Stmt **>(this + 1) + NumElements * 2); } @@ -389,7 +393,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// ObjCSelectorExpr used for \@selector in Objective-C. @@ -424,7 +430,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// ObjCProtocolExpr used for protocol expression in Objective-C. @@ -464,7 +472,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -713,7 +723,7 @@ public: Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack! return child_range(begin, begin+1); } - return child_range(); + return child_range(child_iterator(), child_iterator()); } private: @@ -1350,6 +1360,14 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; + llvm::iterator_range<arg_iterator> arguments() { + return llvm::make_range(arg_begin(), arg_end()); + } + + llvm::iterator_range<const_arg_iterator> arguments() const { + return llvm::make_range(arg_begin(), arg_end()); + } + arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); } arg_iterator arg_end() { return reinterpret_cast<Stmt **>(getArgs() + NumArgs); @@ -1503,11 +1521,15 @@ public: /// \code /// NSString *str = (__bridge_transfer NSString *)CFCreateString(); /// \endcode -class ObjCBridgedCastExpr : public ExplicitCastExpr { +class ObjCBridgedCastExpr final + : public ExplicitCastExpr, + private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> { SourceLocation LParenLoc; SourceLocation BridgeKeywordLoc; unsigned Kind : 2; - + + friend TrailingObjects; + friend class CastExpr; friend class ASTStmtReader; friend class ASTStmtWriter; diff --git a/include/clang/AST/ExprOpenMP.h b/include/clang/AST/ExprOpenMP.h new file mode 100644 index 0000000..2d71a3a --- /dev/null +++ b/include/clang/AST/ExprOpenMP.h @@ -0,0 +1,129 @@ +//===--- ExprOpenMP.h - Classes for representing expressions ----*- 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 Expr interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPROPENMP_H +#define LLVM_CLANG_AST_EXPROPENMP_H + +#include "clang/AST/Expr.h" + +namespace clang { +/// \brief OpenMP 4.0 [2.4, Array Sections]. +/// To specify an array section in an OpenMP construct, array subscript +/// expressions are extended with the following syntax: +/// \code +/// [ lower-bound : length ] +/// [ lower-bound : ] +/// [ : length ] +/// [ : ] +/// \endcode +/// The array section must be a subset of the original array. +/// Array sections are allowed on multidimensional arrays. Base language array +/// subscript expressions can be used to specify length-one dimensions of +/// multidimensional array sections. +/// The lower-bound and length are integral type expressions. When evaluated +/// they represent a set of integer values as follows: +/// \code +/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length - +/// 1 } +/// \endcode +/// The lower-bound and length must evaluate to non-negative integers. +/// When the size of the array dimension is not known, the length must be +/// specified explicitly. +/// When the length is absent, it defaults to the size of the array dimension +/// minus the lower-bound. +/// When the lower-bound is absent it defaults to 0. +class OMPArraySectionExpr : public Expr { + enum { BASE, LOWER_BOUND, LENGTH, END_EXPR }; + Stmt *SubExprs[END_EXPR]; + SourceLocation ColonLoc; + SourceLocation RBracketLoc; + +public: + OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type, + ExprValueKind VK, ExprObjectKind OK, + SourceLocation ColonLoc, SourceLocation RBracketLoc) + : Expr( + OMPArraySectionExprClass, Type, VK, OK, + Base->isTypeDependent() || + (LowerBound && LowerBound->isTypeDependent()) || + (Length && Length->isTypeDependent()), + Base->isValueDependent() || + (LowerBound && LowerBound->isValueDependent()) || + (Length && Length->isValueDependent()), + Base->isInstantiationDependent() || + (LowerBound && LowerBound->isInstantiationDependent()) || + (Length && Length->isInstantiationDependent()), + Base->containsUnexpandedParameterPack() || + (LowerBound && LowerBound->containsUnexpandedParameterPack()) || + (Length && Length->containsUnexpandedParameterPack())), + ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) { + SubExprs[BASE] = Base; + SubExprs[LOWER_BOUND] = LowerBound; + SubExprs[LENGTH] = Length; + } + + /// \brief Create an empty array section expression. + explicit OMPArraySectionExpr(EmptyShell Shell) + : Expr(OMPArraySectionExprClass, Shell) {} + + /// An array section can be written only as Base[LowerBound:Length]. + + /// \brief Get base of the array section. + Expr *getBase() { return cast<Expr>(SubExprs[BASE]); } + const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); } + /// \brief Set base of the array section. + void setBase(Expr *E) { SubExprs[BASE] = E; } + + /// \brief Return original type of the base expression for array section. + static QualType getBaseOriginalType(Expr *Base); + + /// \brief Get lower bound of array section. + Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); } + const Expr *getLowerBound() const { + return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); + } + /// \brief Set lower bound of the array section. + void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; } + + /// \brief Get length of array section. + Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); } + const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); } + /// \brief Set length of the array section. + void setLength(Expr *E) { SubExprs[LENGTH] = E; } + + SourceLocation getLocStart() const LLVM_READONLY { + return getBase()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } + + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation L) { ColonLoc = L; } + + SourceLocation getRBracketLoc() const { return RBracketLoc; } + void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } + + SourceLocation getExprLoc() const LLVM_READONLY { + return getBase()->getExprLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPArraySectionExprClass; + } + + child_range children() { + return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]); + } +}; +} // end namespace clang + +#endif diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 08c2e0c..81cf631 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -33,20 +33,6 @@ class Selector; class Stmt; class TagDecl; -/// \brief Enumeration describing the result of loading information from -/// an external source. -enum ExternalLoadResult { - /// \brief Loading the external information has succeeded. - ELR_Success, - - /// \brief Loading the external information has failed. - ELR_Failure, - - /// \brief The external information has already been loaded, and therefore - /// no additional processing is required. - ELR_AlreadyLoaded -}; - /// \brief Abstract interface for external sources of AST nodes. /// /// External AST sources provide AST nodes constructed from some @@ -156,47 +142,50 @@ public: /// \brief Retrieve the module that corresponds to the given module ID. virtual Module *getModule(unsigned ID) { return nullptr; } - /// \brief Holds everything needed to generate debug info for an - /// imported module or precompiled header file. - struct ASTSourceDescriptor { - std::string ModuleName; - std::string Path; - std::string ASTFile; - uint64_t Signature; + /// Abstracts clang modules and precompiled header files and holds + /// everything needed to generate debug info for an imported module + /// or PCH. + class ASTSourceDescriptor { + StringRef PCHModuleName; + StringRef Path; + StringRef ASTFile; + uint64_t Signature = 0; + const Module *ClangModule = nullptr; + + public: + ASTSourceDescriptor(){}; + ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile, + uint64_t Signature) + : PCHModuleName(std::move(Name)), Path(std::move(Path)), + ASTFile(std::move(ASTFile)), Signature(Signature){}; + ASTSourceDescriptor(const Module &M); + std::string getModuleName() const; + StringRef getPath() const { return Path; } + StringRef getASTFile() const { return ASTFile; } + uint64_t getSignature() const { return Signature; } + const Module *getModuleOrNull() const { return ClangModule; } }; - /// \brief Return a descriptor for the corresponding module, if one exists. + /// Return a descriptor for the corresponding module, if one exists. virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID); - /// \brief Return a descriptor for the module. - virtual ASTSourceDescriptor getSourceDescriptor(const Module &M); /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. /// - /// \param isKindWeWant a predicate function that returns true if the passed - /// declaration kind is one we are looking for. If NULL, all declarations - /// are returned. - /// - /// \return an indication of whether the load succeeded or failed. + /// \param IsKindWeWant a predicate function that returns true if the passed + /// declaration kind is one we are looking for. /// /// The default implementation of this method is a no-op. - virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, - bool (*isKindWeWant)(Decl::Kind), - SmallVectorImpl<Decl*> &Result); + virtual void + FindExternalLexicalDecls(const DeclContext *DC, + llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, + SmallVectorImpl<Decl *> &Result); /// \brief Finds all declarations lexically contained within the given /// DeclContext. - /// - /// \return true if an error occurred - ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, - SmallVectorImpl<Decl*> &Result) { - return FindExternalLexicalDecls(DC, nullptr, Result); - } - - template <typename DeclTy> - ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC, - SmallVectorImpl<Decl*> &Result) { - return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); + void FindExternalLexicalDecls(const DeclContext *DC, + SmallVectorImpl<Decl *> &Result) { + FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result); } /// \brief Get the decls that are contained in a file in the Offset/Length diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index 735ae11..7b725b6 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -144,9 +144,6 @@ public: /// across translation units so it can be used with LTO. virtual void mangleTypeName(QualType T, raw_ostream &) = 0; - virtual void mangleCXXVTableBitSet(const CXXRecordDecl *RD, - raw_ostream &) = 0; - /// @} }; diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 4da17b0..b1ff9bd 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -217,7 +217,8 @@ public: /// \brief Dump the nested name specifier to standard output to aid /// in debugging. - void dump(const LangOptions &LO); + void dump(const LangOptions &LO) const; + void dump() const; }; /// \brief A C++ nested-name-specifier augmented with source location diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index fcfa1dd..bb982f3 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -57,9 +57,15 @@ public: bool isImplicit() const { return StartLoc.isInvalid(); } - StmtRange children(); - ConstStmtRange children() const { - return const_cast<OMPClause *>(this)->children(); + 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; + + 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; } }; @@ -146,10 +152,10 @@ public: /// \brief This represents 'if' clause in the '#pragma omp ...' directive. /// /// \code -/// #pragma omp parallel if(a > 5) +/// #pragma omp parallel if(parallel:a > 5) /// \endcode -/// In this example directive '#pragma omp parallel' has simple 'if' -/// clause with condition 'a > 5'. +/// In this example directive '#pragma omp parallel' has simple 'if' clause with +/// condition 'a > 5' and directive name modifier 'parallel'. /// class OMPIfClause : public OMPClause { friend class OMPClauseReader; @@ -157,43 +163,73 @@ class OMPIfClause : public OMPClause { SourceLocation LParenLoc; /// \brief Condition of the 'if' clause. Stmt *Condition; + /// \brief Location of ':' (if any). + SourceLocation ColonLoc; + /// \brief Directive name modifier for the clause. + OpenMPDirectiveKind NameModifier; + /// \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: /// \brief Build 'if' clause with condition \a Cond. /// + /// \param NameModifier [OpenMP 4.1] Directive name modifier of clause. + /// \param Cond Condition of the clause. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. - /// \param Cond Condition of the clause. + /// \param NameModifierLoc Location of directive name modifier. + /// \param ColonLoc [OpenMP 4.1] Location of ':'. /// \param EndLoc Ending location of the clause. /// - OMPIfClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc, + OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc) : OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc), - Condition(Cond) {} + Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier), + NameModifierLoc(NameModifierLoc) {} /// \brief Build an empty clause. /// OMPIfClause() - : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), - LParenLoc(SourceLocation()), Condition(nullptr) {} + : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(), + Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown), + NameModifierLoc() {} /// \brief Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } /// \brief Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } + /// \brief Return the location of ':'. + SourceLocation getColonLoc() const { return ColonLoc; } + /// \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; } static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_if; } - StmtRange children() { return StmtRange(&Condition, &Condition + 1); } + child_range children() { return child_range(&Condition, &Condition + 1); } }; /// \brief This represents 'final' clause in the '#pragma omp ...' directive. @@ -246,7 +282,7 @@ public: return T->getClauseKind() == OMPC_final; } - StmtRange children() { return StmtRange(&Condition, &Condition + 1); } + child_range children() { return child_range(&Condition, &Condition + 1); } }; /// \brief This represents 'num_threads' clause in the '#pragma omp ...' @@ -300,7 +336,7 @@ public: return T->getClauseKind() == OMPC_num_threads; } - StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); } + child_range children() { return child_range(&NumThreads, &NumThreads + 1); } }; /// \brief This represents 'safelen' clause in the '#pragma omp ...' @@ -356,7 +392,62 @@ public: return T->getClauseKind() == OMPC_safelen; } - StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); } + child_range children() { return child_range(&Safelen, &Safelen + 1); } +}; + +/// \brief This represents 'simdlen' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp simd simdlen(4) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'simdlen' +/// with single expression '4'. +/// 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; + + /// \brief Set simdlen. + void setSimdlen(Expr *Len) { Simdlen = Len; } + +public: + /// \brief Build 'simdlen' clause. + /// + /// \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) {} + + /// \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); } + + 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 ...' @@ -412,7 +503,7 @@ public: return T->getClauseKind() == OMPC_collapse; } - StmtRange children() { return StmtRange(&NumForLoops, &NumForLoops + 1); } + child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } }; /// \brief This represents 'default' clause in the '#pragma omp ...' directive. @@ -481,7 +572,9 @@ public: return T->getClauseKind() == OMPC_default; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'proc_bind' clause in the '#pragma omp ...' @@ -552,7 +645,9 @@ public: return T->getClauseKind() == OMPC_proc_bind; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'schedule' clause in the '#pragma omp ...' directive. @@ -569,6 +664,11 @@ class OMPScheduleClause : public OMPClause { SourceLocation LParenLoc; /// \brief A kind of the 'schedule' clause. OpenMPScheduleClauseKind Kind; + /// \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). @@ -583,6 +683,42 @@ class OMPScheduleClause : public OMPClause { /// \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; + else { + assert(Modifiers[SECOND] == OMPC_SCHEDULE_MODIFIER_unknown); + Modifiers[SECOND] = M; + } + } /// \brief Sets the location of '('. /// /// \param Loc Location of '('. @@ -621,15 +757,25 @@ public: /// \param Kind Schedule kind. /// \param ChunkSize Chunk size. /// \param HelperChunkSize Helper chunk size for combined directives. + /// \param M1 The first modifier applied to 'schedule' clause. + /// \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, - Expr *ChunkSize, Expr *HelperChunkSize) + Expr *ChunkSize, Expr *HelperChunkSize, + OpenMPScheduleClauseModifier M1, SourceLocation M1Loc, + OpenMPScheduleClauseModifier M2, SourceLocation M2Loc) : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc), Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) { ChunkSizes[CHUNK_SIZE] = ChunkSize; ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize; + Modifiers[FIRST] = M1; + Modifiers[SECOND] = M2; + ModifiersLoc[FIRST] = M1Loc; + ModifiersLoc[SECOND] = M2Loc; } /// \brief Build an empty clause. @@ -639,17 +785,39 @@ public: Kind(OMPC_SCHEDULE_unknown) { ChunkSizes[CHUNK_SIZE] = nullptr; ChunkSizes[HELPER_CHUNK_SIZE] = nullptr; + 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; } @@ -676,38 +844,61 @@ public: return T->getClauseKind() == OMPC_schedule; } - StmtRange children() { - return StmtRange(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1); + child_range children() { + return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1); } }; /// \brief This represents 'ordered' clause in the '#pragma omp ...' directive. /// /// \code -/// #pragma omp for ordered +/// #pragma omp for ordered (2) /// \endcode -/// In this example directive '#pragma omp for' has 'ordered' clause. +/// 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; + + /// \brief Set the number of associated for-loops. + void setNumForLoops(Expr *Num) { NumForLoops = Num; } + public: /// \brief Build 'ordered' clause. /// + /// \param Num Expression, possibly associated with this clause. /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// - OMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_ordered, StartLoc, EndLoc) {} + OMPOrderedClause(Expr *Num, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), + NumForLoops(Num) {} /// \brief Build an empty clause. /// - OMPOrderedClause() - : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {} + explicit OMPOrderedClause() + : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), NumForLoops(nullptr) {} + + /// \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); } static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_ordered; } - StmtRange children() { return StmtRange(); } + child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } }; /// \brief This represents 'nowait' clause in the '#pragma omp ...' directive. @@ -736,7 +927,9 @@ public: return T->getClauseKind() == OMPC_nowait; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'untied' clause in the '#pragma omp ...' directive. @@ -765,7 +958,9 @@ public: return T->getClauseKind() == OMPC_untied; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'mergeable' clause in the '#pragma omp ...' @@ -795,7 +990,9 @@ public: return T->getClauseKind() == OMPC_mergeable; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'read' clause in the '#pragma omp atomic' directive. @@ -823,7 +1020,9 @@ public: return T->getClauseKind() == OMPC_read; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'write' clause in the '#pragma omp atomic' directive. @@ -852,7 +1051,9 @@ public: return T->getClauseKind() == OMPC_write; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'update' clause in the '#pragma omp atomic' @@ -882,7 +1083,9 @@ public: return T->getClauseKind() == OMPC_update; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'capture' clause in the '#pragma omp atomic' @@ -912,7 +1115,9 @@ public: return T->getClauseKind() == OMPC_capture; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents 'seq_cst' clause in the '#pragma omp atomic' @@ -942,7 +1147,9 @@ public: return T->getClauseKind() == OMPC_seq_cst; } - StmtRange children() { return StmtRange(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This represents clause 'private' in the '#pragma omp ...' directives. @@ -1026,9 +1233,9 @@ public: getPrivateCopies().end()); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1147,9 +1354,9 @@ public: return inits_const_range(getInits().begin(), getInits().end()); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1332,9 +1539,9 @@ public: getAssignmentOps().end()); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1391,9 +1598,9 @@ public: /// static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N); - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1455,16 +1662,29 @@ class OMPReductionClause : public OMPVarListClause<OMPReductionClause> { void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; } /// \brief Set list of helper expressions, required for proper codegen of the + /// clause. These expressions represent private copy of the reduction + /// variable. + void setPrivates(ArrayRef<Expr *> Privates); + + /// \brief Get the list of helper privates. + MutableArrayRef<Expr *> getPrivates() { + return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); + } + ArrayRef<const Expr *> getPrivates() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + + /// \brief Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent LHS expression in the final /// reduction expression performed by the reduction clause. void setLHSExprs(ArrayRef<Expr *> LHSExprs); /// \brief Get the list of helper LHS expressions. MutableArrayRef<Expr *> getLHSExprs() { - return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); + return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); } ArrayRef<const Expr *> getLHSExprs() const { - return llvm::makeArrayRef(varlist_end(), varlist_size()); + return llvm::makeArrayRef(getPrivates().end(), varlist_size()); } /// \brief Set list of helper expressions, required for proper codegen of the @@ -1506,6 +1726,8 @@ public: /// \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. @@ -1528,8 +1750,9 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> LHSExprs, - ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps); + const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates, + ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, + ArrayRef<Expr *> ReductionOps); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -1550,6 +1773,12 @@ public: typedef llvm::iterator_range<helper_expr_const_iterator> helper_expr_const_range; + 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()); } @@ -1571,9 +1800,9 @@ public: getReductionOps().end()); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1592,6 +1821,10 @@ public: /// class OMPLinearClause : public OMPVarListClause<OMPLinearClause> { friend class OMPClauseReader; + /// \brief Modifier of 'linear' clause. + OpenMPLinearClauseKind Modifier; + /// \brief Location of linear modifier if any. + SourceLocation ModifierLoc; /// \brief Location of ':'. SourceLocation ColonLoc; @@ -1610,11 +1843,12 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> { /// \param NumVars Number of variables. /// OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc, + OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned NumVars) : OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc, EndLoc, NumVars), - ColonLoc(ColonLoc) {} + Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {} /// \brief Build an empty clause. /// @@ -1624,7 +1858,7 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> { : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(), SourceLocation(), SourceLocation(), NumVars), - ColonLoc(SourceLocation()) {} + Modifier(OMPC_LINEAR_val), ModifierLoc(), ColonLoc() {} /// \brief Gets the list of initial values for linear variables. /// @@ -1636,16 +1870,23 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> { /// expressions - linear step and a helper to calculate it before the /// loop body (used when the linear step is not constant): /// - /// { Vars[] /* in OMPVarListClause */; Inits[]; Updates[]; Finals[]; - /// Step; CalcStep; } + /// { Vars[] /* in OMPVarListClause */; Privates[]; Inits[]; Updates[]; + /// Finals[]; Step; CalcStep; } /// - MutableArrayRef<Expr *> getInits() { + MutableArrayRef<Expr *> getPrivates() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } - ArrayRef<const Expr *> getInits() const { + ArrayRef<const Expr *> getPrivates() const { return llvm::makeArrayRef(varlist_end(), varlist_size()); } + MutableArrayRef<Expr *> getInits() { + return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); + } + ArrayRef<const Expr *> getInits() const { + return llvm::makeArrayRef(getPrivates().end(), varlist_size()); + } + /// \brief Sets the list of update expressions for linear variables. MutableArrayRef<Expr *> getUpdates() { return MutableArrayRef<Expr *>(getInits().end(), varlist_size()); @@ -1662,6 +1903,10 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> { return llvm::makeArrayRef(getUpdates().end(), varlist_size()); } + /// \brief Sets the list of the copies of original linear variables. + /// \param PL List of expressions. + void setPrivates(ArrayRef<Expr *> PL); + /// \brief Sets the list of the initial values for linear variables. /// \param IL List of expressions. void setInits(ArrayRef<Expr *> IL); @@ -1673,17 +1918,20 @@ public: /// \param C AST Context. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. + /// \param Modifier Modifier of 'linear' clause. + /// \param ModifierLoc Modifier location. /// \param ColonLoc Location of ':'. /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. + /// \param PL List of private copies of original variables. /// \param IL List of initial values for the variables. /// \param Step Linear step. /// \param CalcStep Calculation of the linear step. - static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, - ArrayRef<Expr *> VL, ArrayRef<Expr *> IL, - Expr *Step, Expr *CalcStep); + static OMPLinearClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, + ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep); /// \brief Creates an empty clause with the place for \a NumVars variables. /// @@ -1692,9 +1940,19 @@ public: /// 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 '('. + /// \brief Returns the location of ':'. SourceLocation getColonLoc() const { return ColonLoc; } /// \brief Returns linear step. @@ -1714,6 +1972,18 @@ 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; + + 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; @@ -1750,9 +2020,9 @@ public: return finals_const_range(getFinals().begin(), getFinals().end()); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1835,9 +2105,9 @@ public: /// \brief Returns alignment. const Expr *getAlignment() const { return *varlist_end(); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -1993,9 +2263,9 @@ public: getAssignmentOps().end()); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -2138,9 +2408,9 @@ public: getAssignmentOps().end()); } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -2202,9 +2472,9 @@ public: /// static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N); - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -2290,9 +2560,9 @@ public: /// \brief Get colon location. SourceLocation getColonLoc() const { return ColonLoc; } - StmtRange children() { - return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), - reinterpret_cast<Stmt **>(varlist_end())); + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } static bool classof(const OMPClause *T) { @@ -2300,7 +2570,590 @@ public: } }; -} // end namespace clang +/// \brief This represents 'device' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp target device(a) +/// \endcode +/// In this example directive '#pragma omp target' has clause 'device' +/// with single expression 'a'. +/// +class OMPDeviceClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Device number. + Stmt *Device; + /// \brief Set the device number. + /// + /// \param E Device number. + /// + void setDevice(Expr *E) { Device = E; } + +public: + /// \brief Build 'device' clause. + /// + /// \param E Expression associated with this clause. + /// \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) {} + + /// \brief Build an empty clause. + /// + OMPDeviceClause() + : OMPClause(OMPC_device, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Device(nullptr) {} + /// \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); } + + 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. +/// +/// \code +/// #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()); + } +}; + +/// \brief This represents 'simd' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #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()); + } +}; + +/// \brief This represents clause 'map' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target map(a,b) +/// \endcode +/// In this example directive '#pragma omp target' has clause 'map' +/// with the variables 'a' and 'b'. +/// +class OMPMapClause : public OMPVarListClause<OMPMapClause> { + friend class OMPClauseReader; + + /// \brief Map type modifier for the 'map' clause. + OpenMPMapClauseKind MapTypeModifier; + /// \brief Map type for the 'map' clause. + OpenMPMapClauseKind MapType; + /// \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 clause with number of variables \a N. + /// + /// \param MapTypeModifier Map type modifier. + /// \param MapType Map type. + /// \param MapLoc Location of the map type. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier, + OpenMPMapClauseKind MapType, SourceLocation MapLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPMapClause>(OMPC_map, StartLoc, LParenLoc, EndLoc, N), + MapTypeModifier(MapTypeModifier), MapType(MapType), MapLoc(MapLoc) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPMapClause(unsigned N) + : OMPVarListClause<OMPMapClause>(OMPC_map, SourceLocation(), + SourceLocation(), SourceLocation(), N), + MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), MapLoc() {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// \param TypeModifier Map type modifier. + /// \param Type Map type. + /// \param TypeLoc Location of the map type. + /// + static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL, + OpenMPMapClauseKind TypeModifier, + OpenMPMapClauseKind Type, SourceLocation TypeLoc); + /// \brief Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned N); + + /// \brief Fetches mapping kind for the clause. + OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; } + + /// \brief Fetches the map type modifier for the clause. + OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY { + return MapTypeModifier; + } + + /// \brief Fetches location of clause mapping kind. + SourceLocation getMapLoc() const LLVM_READONLY { return MapLoc; } + + /// \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())); + } +}; + +/// \brief This represents 'num_teams' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp teams num_teams(n) +/// \endcode +/// In this example directive '#pragma omp teams' has clause 'num_teams' +/// with single expression 'n'. +/// +class OMPNumTeamsClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief NumTeams number. + Stmt *NumTeams; + /// \brief Set the NumTeams number. + /// + /// \param E NumTeams number. + /// + void setNumTeams(Expr *E) { NumTeams = E; } + +public: + /// \brief Build 'num_teams' clause. + /// + /// \param E Expression associated with this clause. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPNumTeamsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_num_teams, StartLoc, EndLoc), LParenLoc(LParenLoc), + NumTeams(E) {} + + /// \brief Build an empty clause. + /// + OMPNumTeamsClause() + : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), NumTeams(nullptr) {} + /// \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); } + + 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 ...' +/// directive. +/// +/// \code +/// #pragma omp teams thread_limit(n) +/// \endcode +/// In this example directive '#pragma omp teams' has clause 'thread_limit' +/// with single expression 'n'. +/// +class OMPThreadLimitClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief ThreadLimit number. + Stmt *ThreadLimit; + /// \brief Set the ThreadLimit number. + /// + /// \param E ThreadLimit number. + /// + void setThreadLimit(Expr *E) { ThreadLimit = E; } + +public: + /// \brief Build 'thread_limit' clause. + /// + /// \param E Expression associated with this clause. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPThreadLimitClause(Expr *E, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), LParenLoc(LParenLoc), + ThreadLimit(E) {} + + /// \brief Build an empty clause. + /// + OMPThreadLimitClause() + : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), ThreadLimit(nullptr) {} + /// \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); } + + 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 ...' +/// directive. +/// +/// \code +/// #pragma omp task priority(n) +/// \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; + /// \brief Set the Priority number. + /// + /// \param E Priority number. + /// + void setPriority(Expr *E) { Priority = E; } + +public: + /// \brief Build 'priority' clause. + /// + /// \param E Expression associated with this clause. + /// \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) {} + /// \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); } + + 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 ...' +/// directive. +/// +/// \code +/// #pragma omp taskloop grainsize(4) +/// \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; + + /// \brief Set safelen. + void setGrainsize(Expr *Size) { Grainsize = Size; } + +public: + /// \brief Build 'grainsize' clause. + /// + /// \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) {} + + /// \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); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_grainsize; + } -#endif + child_range children() { return child_range(&Grainsize, &Grainsize + 1); } +}; + +/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #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()); + } +}; + +/// \brief This represents 'num_tasks' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp taskloop num_tasks(4) +/// \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; + + /// \brief Set safelen. + void setNumTasks(Expr *Size) { NumTasks = Size; } + +public: + /// \brief Build 'num_tasks' clause. + /// + /// \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) {} + + /// \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); } + + 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. +/// +/// \code +/// #pragma omp critical (name) hint(6) +/// \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; + + /// \brief Set hint expression. + /// + void setHint(Expr *H) { Hint = H; } + +public: + /// \brief Build 'hint' clause with expression \a Hint. + /// + /// \param Hint Hint expression. + /// \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) {} + + /// \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); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_hint; + } + + child_range children() { return child_range(&Hint, &Hint + 1); } +}; + +} // end namespace clang +#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index e3f0126..2235c10 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -334,7 +334,8 @@ enum UnaryOperatorKind { UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension. - UO_Extension // __extension__ marker. + UO_Extension, // __extension__ marker. + UO_Coawait // [C++ Coroutines] co_await operator }; /// \brief The kind of bridging performed by the Objective-C bridge cast. diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 35ceabb..8ab3f617 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -42,7 +42,7 @@ struct PrintingPolicy { SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), - IncludeNewlines(true) { } + IncludeNewlines(true), MSVCFormatting(false) { } /// \brief What language we're printing. LangOptions LangOpts; @@ -109,7 +109,7 @@ struct PrintingPolicy { /// \brief Whether we should print the sizes of constant array expressions /// as written in the sources. /// - /// This flag is determines whether arrays types declared as + /// This flag determines whether array types declared as /// /// \code /// int a[4+10*10]; @@ -163,6 +163,11 @@ struct PrintingPolicy { /// \brief 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. + bool MSVCFormatting : 1; }; } // end namespace clang diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 1017656..e6f7583 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -14,6 +14,8 @@ #ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H #define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H +#include <type_traits> + #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -24,6 +26,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" @@ -42,7 +45,7 @@ OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \ OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \ OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) + OPERATOR(Extension) OPERATOR(Coawait) // All binary operators (excluding compound assign operators). #define BINOP_LIST() \ @@ -132,6 +135,12 @@ namespace clang { /// from which they were produced. template <typename Derived> class RecursiveASTVisitor { public: + /// A queue used for performing data recursion over statements. + /// Parameters involving this type are used to implement data + /// recursion over Stmts and Exprs within this class, and should + /// typically not be explicitly specified by derived classes. + typedef SmallVectorImpl<Stmt *> DataRecursionQueue; + /// \brief Return a reference to the derived class. Derived &getDerived() { return *static_cast<Derived *>(this); } @@ -147,19 +156,12 @@ public: /// code, e.g., implicit constructors and destructors. bool shouldVisitImplicitCode() const { return false; } - /// \brief Return whether \param S should be traversed using data recursion - /// to avoid a stack overflow with extreme cases. - bool shouldUseDataRecursionFor(Stmt *S) const { - return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) || - isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S); - } - /// \brief Recursively visit a statement or expression, by /// dispatching to Traverse*() based on the argument's dynamic type. /// /// \returns false if the visitation was terminated early, true - /// otherwise (including when the argument is NULL). - bool TraverseStmt(Stmt *S); + /// otherwise (including when the argument is nullptr). + bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr); /// \brief Recursively visit a type, by dispatching to /// Traverse*Type() based on the argument's getTypeClass() property. @@ -252,7 +254,14 @@ public: /// \c LE->getBody(). /// /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaBody(LambdaExpr *LE); + bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr); + + /// \brief Recursively visit the syntactic or semantic form of an + /// initialization list. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseSynOrSemInitListExpr(InitListExpr *S, + DataRecursionQueue *Queue = nullptr); // ---- Methods on Attrs ---- @@ -266,9 +275,44 @@ public: // ---- Methods on Stmts ---- +private: + template<typename T, typename U> + struct has_same_member_pointer_type : std::false_type {}; + template<typename T, typename U, typename R, typename... P> + struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> + : std::true_type {}; + + // Traverse the given statement. If the most-derived traverse function takes a + // data recursion queue, pass it on; otherwise, discard it. Note that the + // first branch of this conditional must compile whether or not the derived + // class can take a queue, so if we're taking the second arm, make the first + // arm call our function rather than the derived class version. +#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \ + (has_same_member_pointer_type<decltype( \ + &RecursiveASTVisitor::Traverse##NAME), \ + decltype(&Derived::Traverse##NAME)>::value \ + ? static_cast<typename std::conditional< \ + has_same_member_pointer_type< \ + decltype(&RecursiveASTVisitor::Traverse##NAME), \ + decltype(&Derived::Traverse##NAME)>::value, \ + Derived &, RecursiveASTVisitor &>::type>(*this) \ + .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \ + : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))) + +// Try to traverse the given statement, or enqueue it if we're performing data +// recursion in the middle of traversing another statement. Can only be called +// from within a DEF_TRAVERSE_STMT body or similar context. +#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \ + do { \ + if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \ + return false; \ + } while (0) + +public: // Declare Traverse*() for all concrete Stmt classes. #define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S); +#define STMT(CLASS, PARENT) \ + bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr); #include "clang/AST/StmtNodes.inc" // The above header #undefs ABSTRACT_STMT and STMT upon exit. @@ -288,9 +332,10 @@ public: // operator methods. Unary operators are not classes in themselves // (they're all opcodes in UnaryOperator) but do have visitors. #define OPERATOR(NAME) \ - bool TraverseUnary##NAME(UnaryOperator *S) { \ + bool TraverseUnary##NAME(UnaryOperator *S, \ + DataRecursionQueue *Queue = nullptr) { \ TRY_TO(WalkUpFromUnary##NAME(S)); \ - TRY_TO(TraverseStmt(S->getSubExpr())); \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \ return true; \ } \ bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ @@ -307,10 +352,10 @@ public: // operator methods. Binary operators are not classes in themselves // (they're all opcodes in BinaryOperator) but do have visitors. #define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ - bool TraverseBin##NAME(BINOP_TYPE *S) { \ + bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \ TRY_TO(WalkUpFromBin##NAME(S)); \ - TRY_TO(TraverseStmt(S->getLHS())); \ - TRY_TO(TraverseStmt(S->getRHS())); \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \ return true; \ } \ bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ @@ -436,98 +481,45 @@ private: /// \brief Process clauses with list of variables. template <typename T> bool VisitOMPClauseList(T *Node); - struct EnqueueJob { - Stmt *S; - Stmt::child_iterator StmtIt; - - EnqueueJob(Stmt *S) : S(S), StmtIt() {} - }; - bool dataTraverse(Stmt *S); - bool dataTraverseNode(Stmt *S, bool &EnqueueChildren); + bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); }; template <typename Derived> -bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) { - - SmallVector<EnqueueJob, 16> Queue; - Queue.push_back(S); - - while (!Queue.empty()) { - EnqueueJob &job = Queue.back(); - Stmt *CurrS = job.S; - if (!CurrS) { - Queue.pop_back(); - continue; - } - - if (getDerived().shouldUseDataRecursionFor(CurrS)) { - if (job.StmtIt == Stmt::child_iterator()) { - bool EnqueueChildren = true; - if (!dataTraverseNode(CurrS, EnqueueChildren)) - return false; - if (!EnqueueChildren) { - Queue.pop_back(); - continue; - } - job.StmtIt = CurrS->child_begin(); - } else { - ++job.StmtIt; - } - - if (job.StmtIt != CurrS->child_end()) - Queue.push_back(*job.StmtIt); - else - Queue.pop_back(); - continue; - } - - Queue.pop_back(); - TRY_TO(TraverseStmt(CurrS)); - } - - return true; -} - -template <typename Derived> bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, - bool &EnqueueChildren) { - -// Dispatch to the corresponding WalkUpFrom* function only if the derived -// class didn't override Traverse* (and thus the traversal is trivial). -#define DISPATCH_WALK(NAME, CLASS, VAR) \ - { \ - bool (Derived::*DerivedFn)(CLASS *) = &Derived::Traverse##NAME; \ - bool (Derived::*BaseFn)(CLASS *) = &RecursiveASTVisitor::Traverse##NAME; \ - if (DerivedFn == BaseFn) \ - return getDerived().WalkUpFrom##NAME(static_cast<CLASS *>(VAR)); \ - } \ - EnqueueChildren = false; \ - return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)); + DataRecursionQueue *Queue) { +#define DISPATCH_STMT(NAME, CLASS, VAR) \ + return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue); + // 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. if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { #define OPERATOR(NAME) \ case BO_##NAME: \ - DISPATCH_WALK(Bin##NAME, BinaryOperator, S); + DISPATCH_STMT(Bin##NAME, BinaryOperator, S); BINOP_LIST() #undef OPERATOR +#undef BINOP_LIST #define OPERATOR(NAME) \ case BO_##NAME##Assign: \ - DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S); + DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); CAO_LIST() #undef OPERATOR +#undef CAO_LIST } } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { #define OPERATOR(NAME) \ case UO_##NAME: \ - DISPATCH_WALK(Unary##NAME, UnaryOperator, S); + DISPATCH_STMT(Unary##NAME, UnaryOperator, S); UNARYOP_LIST() #undef OPERATOR +#undef UNARYOP_LIST } } @@ -538,76 +530,43 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, #define ABSTRACT_STMT(STMT) #define STMT(CLASS, PARENT) \ case Stmt::CLASS##Class: \ - DISPATCH_WALK(CLASS, CLASS, S); + DISPATCH_STMT(CLASS, CLASS, S); #include "clang/AST/StmtNodes.inc" } -#undef DISPATCH_WALK - return true; } -#define DISPATCH(NAME, CLASS, VAR) \ - return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) +#undef DISPATCH_STMT template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { +bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S, + DataRecursionQueue *Queue) { if (!S) return true; -#define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR) - - if (getDerived().shouldUseDataRecursionFor(S)) - return dataTraverse(S); - - // 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. - if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { - switch (BinOp->getOpcode()) { -#define OPERATOR(NAME) \ - case BO_##NAME: \ - DISPATCH_STMT(Bin##NAME, BinaryOperator, S); - - BINOP_LIST() -#undef OPERATOR -#undef BINOP_LIST + if (Queue) { + Queue->push_back(S); + return true; + } -#define OPERATOR(NAME) \ - case BO_##NAME##Assign: \ - DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); + SmallVector<Stmt *, 8> LocalQueue; + LocalQueue.push_back(S); - CAO_LIST() -#undef OPERATOR -#undef CAO_LIST - } - } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { - switch (UnOp->getOpcode()) { -#define OPERATOR(NAME) \ - case UO_##NAME: \ - DISPATCH_STMT(Unary##NAME, UnaryOperator, S); + while (!LocalQueue.empty()) { + Stmt *CurrS = LocalQueue.pop_back_val(); - UNARYOP_LIST() -#undef OPERATOR -#undef UNARYOP_LIST - } - } - - // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. - switch (S->getStmtClass()) { - case Stmt::NoStmtClass: - break; -#define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ - case Stmt::CLASS##Class: \ - DISPATCH_STMT(CLASS, CLASS, S); -#include "clang/AST/StmtNodes.inc" + size_t N = LocalQueue.size(); + TRY_TO(dataTraverseNode(CurrS, &LocalQueue)); + // Process new children in the order they were added. + std::reverse(LocalQueue.begin() + N, LocalQueue.end()); } return true; } -#undef DISPATCH_STMT +#define DISPATCH(NAME, CLASS, VAR) \ + return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { @@ -863,8 +822,9 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE, } template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) { - TRY_TO(TraverseStmt(LE->getBody())); +bool RecursiveASTVisitor<Derived>::TraverseLambdaBody( + LambdaExpr *LE, DataRecursionQueue *Queue) { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody()); return true; } @@ -1364,6 +1324,8 @@ DEF_TRAVERSE_DECL( DEF_TRAVERSE_DECL(ExternCContextDecl, {}) DEF_TRAVERSE_DECL(NamespaceAliasDecl, { + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); + // We shouldn't traverse an aliased namespace, since it will be // defined (and, therefore, traversed) somewhere else. // @@ -1596,6 +1558,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); }) +DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); +}) + DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { // D is the "T" in something like "template<typename T> class vector;" if (D->getTypeForDecl()) @@ -1906,25 +1872,26 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { // This macro makes available a variable S, the passed-in stmt. #define DEF_TRAVERSE_STMT(STMT, CODE) \ template <typename Derived> \ - bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \ + bool RecursiveASTVisitor<Derived>::Traverse##STMT( \ + STMT *S, DataRecursionQueue *Queue) { \ TRY_TO(WalkUpFrom##STMT(S)); \ { CODE; } \ for (Stmt *SubStmt : S->children()) { \ - TRY_TO(TraverseStmt(SubStmt)); \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \ } \ return true; \ } DEF_TRAVERSE_STMT(GCCAsmStmt, { - TRY_TO(TraverseStmt(S->getAsmString())); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString()); for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { - TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I))); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I)); } for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { - TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I))); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I)); } for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { - TRY_TO(TraverseStmt(S->getClobberStringLiteral(I))); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I)); } // children() iterates over inputExpr and outputExpr. }) @@ -1977,9 +1944,9 @@ DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {}) DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {}) DEF_TRAVERSE_STMT(CXXForRangeStmt, { if (!getDerived().shouldVisitImplicitCode()) { - TRY_TO(TraverseStmt(S->getLoopVarStmt())); - TRY_TO(TraverseStmt(S->getRangeInit())); - TRY_TO(TraverseStmt(S->getBody())); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); // Visit everything else only if shouldVisitImplicitCode(). return true; } @@ -2012,9 +1979,8 @@ DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); if (S->hasExplicitTemplateArgs()) { - TRY_TO(TraverseTemplateArgumentLocsHelper( - S->getExplicitTemplateArgs().getTemplateArgs(), - S->getNumTemplateArgs())); + TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), + S->getNumTemplateArgs())); } }) @@ -2055,64 +2021,60 @@ DEF_TRAVERSE_STMT(CXXStaticCastExpr, { TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) -// InitListExpr is a tricky one, because we want to do all our work on -// the syntactic form of the listexpr, but this method takes the -// semantic form by default. We can't use the macro helper because it -// calls WalkUp*() on the semantic form, before our code can convert -// to the syntactic form. template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { - InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S; - if (Syn) { - TRY_TO(WalkUpFromInitListExpr(Syn)); +bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr( + InitListExpr *S, DataRecursionQueue *Queue) { + if (S) { + TRY_TO(WalkUpFromInitListExpr(S)); // All we need are the default actions. FIXME: use a helper function. - for (Stmt *SubStmt : Syn->children()) { - TRY_TO(TraverseStmt(SubStmt)); - } - } - InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm(); - if (Sem) { - TRY_TO(WalkUpFromInitListExpr(Sem)); - for (Stmt *SubStmt : Sem->children()) { - TRY_TO(TraverseStmt(SubStmt)); + for (Stmt *SubStmt : S->children()) { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); } } return true; } +// This method is called once for each pair of syntactic and semantic +// InitListExpr, and it traverses the subtrees defined by the two forms. This +// may cause some of the children to be visited twice, if they appear both in +// the syntactic and the semantic form. +// +// There is no guarantee about which form \p S takes when this method is called. +DEF_TRAVERSE_STMT(InitListExpr, { + TRY_TO(TraverseSynOrSemInitListExpr( + S->isSemanticForm() ? S->getSyntacticForm() : S, Queue)); + TRY_TO(TraverseSynOrSemInitListExpr( + S->isSemanticForm() ? S : S->getSemanticForm(), Queue)); + return true; +}) + // GenericSelectionExpr is a special case because the types and expressions // are interleaved. We also need to watch out for null types (default // generic associations). -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr( - GenericSelectionExpr *S) { - TRY_TO(WalkUpFromGenericSelectionExpr(S)); +DEF_TRAVERSE_STMT(GenericSelectionExpr, { TRY_TO(TraverseStmt(S->getControllingExpr())); for (unsigned i = 0; i != S->getNumAssocs(); ++i) { if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); - TRY_TO(TraverseStmt(S->getAssocExpr(i))); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i)); } return true; -} +}) -// PseudoObjectExpr is a special case because of the wierdness with +// PseudoObjectExpr is a special case because of the weirdness with // syntactic expressions and opaque values. -template <typename Derived> -bool -RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) { - TRY_TO(WalkUpFromPseudoObjectExpr(S)); - TRY_TO(TraverseStmt(S->getSyntacticForm())); +DEF_TRAVERSE_STMT(PseudoObjectExpr, { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm()); for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) { Expr *sub = *i; if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub)) sub = OVE->getSourceExpr(); - TRY_TO(TraverseStmt(sub)); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub); } return true; -} +}) DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { // This is called for code like 'return T()' where T is a built-in @@ -2151,6 +2113,8 @@ DEF_TRAVERSE_STMT(MSPropertyRefExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); }) +DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {}) + DEF_TRAVERSE_STMT(CXXUuidofExpr, { // The child-iterator will pick up the arg if it's an expression, // but not if it's a type. @@ -2168,7 +2132,7 @@ DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { }) DEF_TRAVERSE_STMT(ExpressionTraitExpr, - { TRY_TO(TraverseStmt(S->getQueriedExpression())); }) + { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); }) DEF_TRAVERSE_STMT(VAArgExpr, { // The child-iterator will pick up the expression argument. @@ -2181,10 +2145,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { }) // Walk only the visible parts of lambda expressions. -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { - TRY_TO(WalkUpFromLambdaExpr(S)); - +DEF_TRAVERSE_STMT(LambdaExpr, { for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), CEnd = S->explicit_capture_end(); C != CEnd; ++C) { @@ -2213,12 +2174,11 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { } if (Expr *NE = T->getNoexceptExpr()) - TRY_TO(TraverseStmt(NE)); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE); } - TRY_TO(TraverseLambdaBody(S)); - return true; -} + return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue); +}) DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { // This is called for code like 'T()', where T is a template argument. @@ -2235,6 +2195,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {}) // over the children. DEF_TRAVERSE_STMT(AddrLabelExpr, {}) DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) +DEF_TRAVERSE_STMT(OMPArraySectionExpr, {}) DEF_TRAVERSE_STMT(BlockExpr, { TRY_TO(TraverseDecl(S->getBlockDecl())); return true; // no child statements to loop through. @@ -2336,6 +2297,34 @@ DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) DEF_TRAVERSE_STMT(CXXFoldExpr, {}) DEF_TRAVERSE_STMT(AtomicExpr, {}) +// For coroutines expressions, traverse either the operand +// as written or the implied calls, depending on what the +// derived class requests. +DEF_TRAVERSE_STMT(CoroutineBodyStmt, { + if (!getDerived().shouldVisitImplicitCode()) { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); + return true; + } +}) +DEF_TRAVERSE_STMT(CoreturnStmt, { + if (!getDerived().shouldVisitImplicitCode()) { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); + return true; + } +}) +DEF_TRAVERSE_STMT(CoawaitExpr, { + if (!getDerived().shouldVisitImplicitCode()) { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); + return true; + } +}) +DEF_TRAVERSE_STMT(CoyieldExpr, { + if (!getDerived().shouldVisitImplicitCode()) { + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); + return true; + } +}) + // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, {}) DEF_TRAVERSE_STMT(CharacterLiteral, {}) @@ -2437,9 +2426,21 @@ DEF_TRAVERSE_STMT(OMPAtomicDirective, DEF_TRAVERSE_STMT(OMPTargetDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTargetDataDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPTeamsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPDistributeDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { @@ -2484,6 +2485,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSimdlenClause(OMPSimdlenClause *C) { + TRY_TO(TraverseStmt(C->getSimdlen())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) { TRY_TO(TraverseStmt(C->getNumForLoops())); @@ -2509,7 +2516,8 @@ RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) { } template <typename Derived> -bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) { +bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) { + TRY_TO(TraverseStmt(C->getNumForLoops())); return true; } @@ -2555,6 +2563,21 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -2615,6 +2638,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) { TRY_TO(TraverseStmt(C->getStep())); TRY_TO(TraverseStmt(C->getCalcStep())); TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->privates()) { + TRY_TO(TraverseStmt(E)); + } for (auto *E : C->inits()) { TRY_TO(TraverseStmt(E)); } @@ -2671,6 +2697,9 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->privates()) { + TRY_TO(TraverseStmt(E)); + } for (auto *E : C->lhs_exprs()) { TRY_TO(TraverseStmt(E)); } @@ -2695,6 +2724,59 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) { return true; } +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) { + TRY_TO(TraverseStmt(C->getDevice())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause( + OMPNumTeamsClause *C) { + TRY_TO(TraverseStmt(C->getNumTeams())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause( + OMPThreadLimitClause *C) { + TRY_TO(TraverseStmt(C->getThreadLimit())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause( + OMPPriorityClause *C) { + TRY_TO(TraverseStmt(C->getPriority())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause( + OMPGrainsizeClause *C) { + TRY_TO(TraverseStmt(C->getGrainsize())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause( + OMPNumTasksClause *C) { + TRY_TO(TraverseStmt(C->getNumTasks())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) { + TRY_TO(TraverseStmt(C->getHint())); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm @@ -2713,6 +2795,8 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) { // Every class that has getQualifier. #undef DEF_TRAVERSE_STMT +#undef TRAVERSE_STMT +#undef TRAVERSE_STMT_BASE #undef TRY_TO diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 92046d5..eaa22f8 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -20,6 +20,7 @@ #include <iterator> namespace clang { +class ASTContext; /// \brief Provides common interface for the Decls that can be redeclared. template<typename decl_type> @@ -32,7 +33,11 @@ protected: &ExternalASTSource::CompleteRedeclChain> KnownLatest; - typedef const ASTContext *UninitializedLatest; + /// 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; + typedef Decl *Previous; /// A pointer to either an uninitialized latest declaration (where either @@ -47,7 +52,7 @@ protected: enum LatestTag { LatestLink }; DeclLink(LatestTag, const ASTContext &Ctx) - : Next(NotKnownLatest(&Ctx)) {} + : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {} DeclLink(PreviousTag, decl_type *D) : Next(NotKnownLatest(Previous(D))) {} @@ -67,7 +72,8 @@ protected: return static_cast<decl_type*>(NKL.get<Previous>()); // Allocate the generational 'most recent' cache now, if needed. - Next = KnownLatest(*NKL.get<UninitializedLatest>(), + Next = KnownLatest(*reinterpret_cast<const ASTContext *>( + NKL.get<UninitializedLatest>()), const_cast<decl_type *>(D)); } @@ -83,7 +89,9 @@ protected: assert(NextIsLatest() && "decl became canonical unexpectedly"); if (Next.is<NotKnownLatest>()) { NotKnownLatest NKL = Next.get<NotKnownLatest>(); - Next = KnownLatest(*NKL.get<UninitializedLatest>(), D); + Next = KnownLatest(*reinterpret_cast<const ASTContext *>( + NKL.get<UninitializedLatest>()), + D); } else { auto Latest = Next.get<KnownLatest>(); Latest.set(D); diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index ce9449d..e48b7dc 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -22,6 +22,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include <string> @@ -49,57 +50,6 @@ namespace clang { class Token; class VarDecl; - //===--------------------------------------------------------------------===// - // ExprIterator - Iterators for iterating over Stmt* arrays that contain - // only Expr*. This is needed because AST nodes use Stmt* arrays to store - // references to children (to be compatible with StmtIterator). - //===--------------------------------------------------------------------===// - - class Stmt; - class Expr; - - class ExprIterator : public std::iterator<std::forward_iterator_tag, - Expr *&, ptrdiff_t, - Expr *&, Expr *&> { - Stmt** I; - public: - ExprIterator(Stmt** i) : I(i) {} - ExprIterator() : I(nullptr) {} - ExprIterator& operator++() { ++I; return *this; } - ExprIterator operator-(size_t i) { return I-i; } - ExprIterator operator+(size_t i) { return I+i; } - Expr* operator[](size_t idx); - // FIXME: Verify that this will correctly return a signed distance. - signed operator-(const ExprIterator& R) const { return I - R.I; } - Expr* operator*() const; - Expr* operator->() const; - bool operator==(const ExprIterator& R) const { return I == R.I; } - bool operator!=(const ExprIterator& R) const { return I != R.I; } - bool operator>(const ExprIterator& R) const { return I > R.I; } - bool operator>=(const ExprIterator& R) const { return I >= R.I; } - }; - - class ConstExprIterator : public std::iterator<std::forward_iterator_tag, - const Expr *&, ptrdiff_t, - const Expr *&, - const Expr *&> { - const Stmt * const *I; - public: - ConstExprIterator(const Stmt * const *i) : I(i) {} - ConstExprIterator() : I(nullptr) {} - ConstExprIterator& operator++() { ++I; return *this; } - ConstExprIterator operator+(size_t i) const { return I+i; } - ConstExprIterator operator-(size_t i) const { return I-i; } - const Expr * operator[](size_t idx) const; - signed operator-(const ConstExprIterator& R) const { return I - R.I; } - const Expr * operator*() const; - const Expr * operator->() const; - bool operator==(const ConstExprIterator& R) const { return I == R.I; } - bool operator!=(const ConstExprIterator& R) const { return I != R.I; } - bool operator>(const ConstExprIterator& R) const { return I > R.I; } - bool operator>=(const ConstExprIterator& R) const { return I >= R.I; } - }; - //===----------------------------------------------------------------------===// // AST classes for statements. //===----------------------------------------------------------------------===// @@ -121,10 +71,10 @@ public: // Make vanilla 'new' and 'delete' illegal for Stmts. protected: - void* operator new(size_t bytes) throw() { + void *operator new(size_t bytes) LLVM_NOEXCEPT { llvm_unreachable("Stmts cannot be allocated with regular 'new'."); } - void operator delete(void* data) throw() { + void operator delete(void *data) LLVM_NOEXCEPT { llvm_unreachable("Stmts cannot be released with regular 'delete'."); } @@ -322,14 +272,12 @@ public: return operator new(bytes, *C, alignment); } - void* operator new(size_t bytes, void* mem) throw() { - return mem; - } + void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; } - void operator delete(void*, const ASTContext&, unsigned) throw() { } - void operator delete(void*, const ASTContext*, unsigned) throw() { } - void operator delete(void*, size_t) throw() { } - void operator delete(void*, void*) throw() { } + void operator delete(void *, const ASTContext &, unsigned) LLVM_NOEXCEPT {} + void operator delete(void *, const ASTContext *, unsigned) LLVM_NOEXCEPT {} + void operator delete(void *, size_t) LLVM_NOEXCEPT {} + void operator delete(void *, void *) LLVM_NOEXCEPT {} public: /// \brief A placeholder type used to construct an empty shell of a @@ -337,6 +285,39 @@ public: /// de-serialization). struct EmptyShell { }; +protected: + /// Iterator for iterating over Stmt * arrays that contain only Expr * + /// + /// This is needed because AST nodes use Stmt* arrays to store + /// references to children (to be compatible with StmtIterator). + struct ExprIterator + : llvm::iterator_adaptor_base<ExprIterator, Stmt **, + std::random_access_iterator_tag, Expr *> { + ExprIterator() : iterator_adaptor_base(nullptr) {} + ExprIterator(Stmt **I) : iterator_adaptor_base(I) {} + + reference operator*() const { + assert((*I)->getStmtClass() >= firstExprConstant && + (*I)->getStmtClass() <= lastExprConstant); + return *reinterpret_cast<Expr **>(I); + } + }; + + /// Const iterator for iterating over Stmt * arrays that contain only Expr * + struct ConstExprIterator + : llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const *, + std::random_access_iterator_tag, + const Expr *const> { + ConstExprIterator() : iterator_adaptor_base(nullptr) {} + ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {} + + reference operator*() const { + assert((*I)->getStmtClass() >= firstExprConstant && + (*I)->getStmtClass() <= lastExprConstant); + return *reinterpret_cast<const Expr *const *>(I); + } + }; + private: /// \brief Whether statistic collection is enabled. static bool StatisticsEnabled; @@ -411,19 +392,20 @@ public: typedef StmtIterator child_iterator; typedef ConstStmtIterator const_child_iterator; - typedef StmtRange child_range; - typedef ConstStmtRange const_child_range; + typedef llvm::iterator_range<child_iterator> child_range; + typedef llvm::iterator_range<const_child_iterator> const_child_range; child_range children(); const_child_range children() const { - return const_cast<Stmt*>(this)->children(); + auto Children = const_cast<Stmt *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); } - child_iterator child_begin() { return children().first; } - child_iterator child_end() { return children().second; } + child_iterator child_begin() { return children().begin(); } + child_iterator child_end() { return children().end(); } - const_child_iterator child_begin() const { return children().first; } - const_child_iterator child_end() const { return children().second; } + const_child_iterator child_begin() const { return children().begin(); } + const_child_iterator child_end() const { return children().end(); } /// \brief Produce a unique representation of the given statement. /// @@ -544,7 +526,9 @@ public: return T->getStmtClass() == NullStmtClass; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -574,7 +558,7 @@ public: CompoundStmtBits.NumStmts = 0; } - void setStmts(const ASTContext &C, Stmt **Stmts, unsigned NumStmts); + void setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts); bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } unsigned size() const { return CompoundStmtBits.NumStmts; } @@ -643,7 +627,8 @@ public: } const_child_range children() const { - return child_range(Body, Body + CompoundStmtBits.NumStmts); + return const_child_range(child_iterator(Body), + child_iterator(Body + CompoundStmtBits.NumStmts)); } }; @@ -840,18 +825,20 @@ class AttributedStmt : public Stmt { AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt) : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc), NumAttrs(Attrs.size()) { - memcpy(getAttrArrayPtr(), Attrs.data(), Attrs.size() * sizeof(Attr *)); + std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr()); } explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { - memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *)); + std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr); } - Attr *const *getAttrArrayPtr() const { - return reinterpret_cast<Attr *const *>(this + 1); + const Attr *const *getAttrArrayPtr() const { + return reinterpret_cast<const Attr *const *>(this + 1); + } + const Attr **getAttrArrayPtr() { + return reinterpret_cast<const Attr **>(this + 1); } - Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); } public: static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, @@ -1239,7 +1226,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// IndirectGotoStmt - This represents an indirect goto. @@ -1307,7 +1296,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// BreakStmt - This represents a break. @@ -1335,7 +1326,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; @@ -1390,7 +1383,7 @@ public: // Iterators child_range children() { if (RetExpr) return child_range(&RetExpr, &RetExpr+1); - return child_range(); + return child_range(child_iterator(), child_iterator()); } }; @@ -1974,7 +1967,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief This captures a statement into a function. For example, the following @@ -1993,6 +1988,7 @@ public: enum VariableCaptureKind { VCK_This, VCK_ByRef, + VCK_ByCopy, VCK_VLAType, }; @@ -2012,24 +2008,10 @@ public: /// \param Var The variable being captured, or null if capturing this. /// Capture(SourceLocation Loc, VariableCaptureKind Kind, - VarDecl *Var = nullptr) - : VarAndKind(Var, Kind), Loc(Loc) { - switch (Kind) { - case VCK_This: - assert(!Var && "'this' capture cannot have a variable!"); - break; - case VCK_ByRef: - assert(Var && "capturing by reference must have a variable!"); - break; - case VCK_VLAType: - assert(!Var && - "Variable-length array type capture cannot have a variable!"); - break; - } - } + VarDecl *Var = nullptr); /// \brief Determine the kind of capture. - VariableCaptureKind getCaptureKind() const { return VarAndKind.getInt(); } + VariableCaptureKind getCaptureKind() const; /// \brief Retrieve the source location at which the variable or 'this' was /// first used. @@ -2038,9 +2020,14 @@ public: /// \brief Determine whether this capture handles the C++ 'this' pointer. bool capturesThis() const { return getCaptureKind() == VCK_This; } - /// \brief Determine whether this capture handles a variable. + /// \brief Determine whether this capture handles a variable (by reference). bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; } + /// \brief Determine whether this capture handles a variable by copy. + bool capturesVariableByCopy() const { + return getCaptureKind() == VCK_ByCopy; + } + /// \brief Determine whether this capture handles a variable-length array /// type. bool capturesVariableArrayType() const { @@ -2050,11 +2037,8 @@ public: /// \brief Retrieve the declaration of the variable being captured. /// /// This operation is only valid if this capture captures a variable. - VarDecl *getCapturedVar() const { - assert(capturesVariable() && - "No variable available for 'this' or VAT capture"); - return VarAndKind.getPointer(); - } + VarDecl *getCapturedVar() const; + friend class ASTStmtReader; }; @@ -2076,8 +2060,10 @@ private: /// \brief Construct an empty captured statement. CapturedStmt(EmptyShell Empty, unsigned NumCaptures); - Stmt **getStoredStmts() const { - return reinterpret_cast<Stmt **>(const_cast<CapturedStmt *>(this) + 1); + Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); } + + Stmt *const *getStoredStmts() const { + return reinterpret_cast<Stmt *const *>(this + 1); } Capture *getStoredCaptures() const; @@ -2096,31 +2082,20 @@ public: /// \brief Retrieve the statement being captured. Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; } - const Stmt *getCapturedStmt() const { - return const_cast<CapturedStmt *>(this)->getCapturedStmt(); - } + const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; } /// \brief Retrieve the outlined function declaration. - CapturedDecl *getCapturedDecl() { return CapDeclAndKind.getPointer(); } - const CapturedDecl *getCapturedDecl() const { - return const_cast<CapturedStmt *>(this)->getCapturedDecl(); - } + CapturedDecl *getCapturedDecl(); + const CapturedDecl *getCapturedDecl() const; /// \brief Set the outlined function declaration. - void setCapturedDecl(CapturedDecl *D) { - assert(D && "null CapturedDecl"); - CapDeclAndKind.setPointer(D); - } + void setCapturedDecl(CapturedDecl *D); /// \brief Retrieve the captured region kind. - CapturedRegionKind getCapturedRegionKind() const { - return CapDeclAndKind.getInt(); - } + CapturedRegionKind getCapturedRegionKind() const; /// \brief Set the captured region kind. - void setCapturedRegionKind(CapturedRegionKind Kind) { - CapDeclAndKind.setInt(Kind); - } + void setCapturedRegionKind(CapturedRegionKind Kind); /// \brief Retrieve the record declaration for captured variables. const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; } @@ -2164,18 +2139,36 @@ public: typedef Expr **capture_init_iterator; typedef llvm::iterator_range<capture_init_iterator> capture_init_range; - capture_init_range capture_inits() const { + /// \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; + + capture_init_range capture_inits() { return capture_init_range(capture_init_begin(), capture_init_end()); } + const_capture_init_range capture_inits() const { + return const_capture_init_range(capture_init_begin(), capture_init_end()); + } + /// \brief Retrieve the first initialization argument. - capture_init_iterator capture_init_begin() const { + capture_init_iterator capture_init_begin() { return reinterpret_cast<Expr **>(getStoredStmts()); } + const_capture_init_iterator capture_init_begin() const { + return reinterpret_cast<Expr *const *>(getStoredStmts()); + } + /// \brief Retrieve the iterator pointing one past the last initialization /// argument. - capture_init_iterator capture_init_end() const { + capture_init_iterator capture_init_end() { + return capture_init_begin() + NumCaptures; + } + + const_capture_init_iterator capture_init_end() const { return capture_init_begin() + NumCaptures; } diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 567a772..1ca73e2 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -131,12 +131,16 @@ class CXXForRangeStmt : public Stmt { // SubExprs[RANGE] is an expression or declstmt. // SubExprs[COND] and SubExprs[INC] are expressions. Stmt *SubExprs[END]; + SourceLocation CoawaitLoc; SourceLocation ColonLoc; SourceLocation RParenLoc; + + friend class ASTStmtReader; public: CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, - SourceLocation FL, SourceLocation CL, SourceLocation RPL); + SourceLocation FL, SourceLocation CAL, SourceLocation CL, + SourceLocation RPL); CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } @@ -181,13 +185,10 @@ public: void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } void setBody(Stmt *S) { SubExprs[BODY] = S; } - SourceLocation getForLoc() const { return ForLoc; } - void setForLoc(SourceLocation Loc) { ForLoc = Loc; } + SourceLocation getCoawaitLoc() const { return CoawaitLoc; } SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } SourceLocation getLocEnd() const LLVM_READONLY { @@ -287,6 +288,130 @@ public: } }; +/// \brief Represents the body of a coroutine. This wraps the normal function +/// body and holds the additional semantic context required to set up and tear +/// down the coroutine frame. +class CoroutineBodyStmt : public Stmt { + enum SubStmt { + Body, ///< The body of the coroutine. + Promise, ///< The promise statement. + InitSuspend, ///< The initial suspend statement, run before the body. + FinalSuspend, ///< The final suspend statement, run after the body. + OnException, ///< Handler for exceptions thrown in the body. + OnFallthrough, ///< Handler for control flow falling off the body. + ReturnValue, ///< Return value for thunk function. + FirstParamMove ///< First offset for move construction of parameter copies. + }; + Stmt *SubStmts[SubStmt::FirstParamMove]; + + friend class ASTStmtReader; +public: + CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend, + Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough, + Expr *ReturnValue, ArrayRef<Expr *> ParamMoves) + : Stmt(CoroutineBodyStmtClass) { + SubStmts[CoroutineBodyStmt::Body] = Body; + SubStmts[CoroutineBodyStmt::Promise] = Promise; + SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend; + SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend; + SubStmts[CoroutineBodyStmt::OnException] = OnException; + SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough; + SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue; + // FIXME: Tail-allocate space for parameter move expressions and store them. + assert(ParamMoves.empty() && "not implemented yet"); + } + + /// \brief Retrieve the body of the coroutine as written. This will be either + /// a CompoundStmt or a TryStmt. + Stmt *getBody() const { + return SubStmts[SubStmt::Body]; + } + + Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; } + VarDecl *getPromiseDecl() const { + return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl()); + } + + Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; } + Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; } + + Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; } + Stmt *getFallthroughHandler() const { + return SubStmts[SubStmt::OnFallthrough]; + } + + Expr *getReturnValueInit() const { + return cast<Expr>(SubStmts[SubStmt::ReturnValue]); + } + + SourceLocation getLocStart() const LLVM_READONLY { + return getBody()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getBody()->getLocEnd(); + } + + child_range children() { + return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoroutineBodyStmtClass; + } +}; + +/// \brief Represents a 'co_return' statement in the C++ Coroutines TS. +/// +/// This statament models the initialization of the coroutine promise +/// (encapsulating the eventual notional return value) from an expression +/// (or braced-init-list), followed by termination of the coroutine. +/// +/// This initialization is modeled by the evaluation of the operand +/// followed by a call to one of: +/// <promise>.return_value(<operand>) +/// <promise>.return_void() +/// which we name the "promise call". +class CoreturnStmt : public Stmt { + SourceLocation CoreturnLoc; + + enum SubStmt { Operand, PromiseCall, Count }; + Stmt *SubStmts[SubStmt::Count]; + + friend class ASTStmtReader; +public: + CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall) + : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) { + SubStmts[SubStmt::Operand] = Operand; + SubStmts[SubStmt::PromiseCall] = PromiseCall; + } + + SourceLocation getKeywordLoc() const { return CoreturnLoc; } + + /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr + /// if none was specified. + Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); } + + /// \brief Retrieve the promise call that results from this 'co_return' + /// statement. Will be nullptr if either the coroutine has not yet been + /// finalized or the coroutine has no eventual return type. + Expr *getPromiseCall() const { + return static_cast<Expr*>(SubStmts[PromiseCall]); + } + + SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return getOperand()->getLocEnd(); + } + + child_range children() { + return child_range(SubStmts, SubStmts + SubStmt::Count); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoreturnStmtClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index a5a57af..81f8ad43 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -139,86 +139,6 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {} }; -/// A range of statement iterators. -/// -/// This class provides some extra functionality beyond std::pair -/// in order to allow the following idiom: -/// for (StmtRange range = stmt->children(); range; ++range) -struct StmtRange : std::pair<StmtIterator,StmtIterator> { - StmtRange() {} - StmtRange(const StmtIterator &begin, const StmtIterator &end) - : std::pair<StmtIterator,StmtIterator>(begin, end) {} - - bool empty() const { return first == second; } - explicit operator bool() const { return !empty(); } - - Stmt *operator->() const { return first.operator->(); } - Stmt *&operator*() const { return first.operator*(); } - - StmtRange &operator++() { - assert(!empty() && "incrementing on empty range"); - ++first; - return *this; - } - - StmtRange operator++(int) { - assert(!empty() && "incrementing on empty range"); - StmtRange copy = *this; - ++first; - return copy; - } - - friend const StmtIterator &begin(const StmtRange &range) { - return range.first; - } - friend const StmtIterator &end(const StmtRange &range) { - return range.second; - } -}; - -/// A range of const statement iterators. -/// -/// This class provides some extra functionality beyond std::pair -/// in order to allow the following idiom: -/// for (ConstStmtRange range = stmt->children(); range; ++range) -struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> { - ConstStmtRange() {} - ConstStmtRange(const ConstStmtIterator &begin, - const ConstStmtIterator &end) - : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {} - ConstStmtRange(const StmtRange &range) - : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second) - {} - ConstStmtRange(const StmtIterator &begin, const StmtIterator &end) - : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {} - - bool empty() const { return first == second; } - explicit operator bool() const { return !empty(); } - - const Stmt *operator->() const { return first.operator->(); } - const Stmt *operator*() const { return first.operator*(); } - - ConstStmtRange &operator++() { - assert(!empty() && "incrementing on empty range"); - ++first; - return *this; - } - - ConstStmtRange operator++(int) { - assert(!empty() && "incrementing on empty range"); - ConstStmtRange copy = *this; - ++first; - return copy; - } - - friend const ConstStmtIterator &begin(const ConstStmtRange &range) { - return range.first; - } - friend const ConstStmtIterator &end(const ConstStmtRange &range) { - return range.second; - } -}; - } // end namespace clang #endif diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 708b866..1ba859c 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -92,65 +92,78 @@ public: /// \brief Iterates over a filtered subrange of clauses applied to a /// directive. /// - /// This iterator visits only those declarations that meet some run-time - /// criteria. - template <class FilterPredicate> class filtered_clause_iterator { - protected: - ArrayRef<OMPClause *>::const_iterator Current; + /// This iterator visits only clauses of type SpecificClause. + template <typename SpecificClause> + class specific_clause_iterator + : public llvm::iterator_adaptor_base< + specific_clause_iterator<SpecificClause>, + ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag, + const SpecificClause *, ptrdiff_t, const SpecificClause *, + const SpecificClause *> { ArrayRef<OMPClause *>::const_iterator End; - FilterPredicate Pred; + void SkipToNextClause() { - while (Current != End && !Pred(*Current)) - ++Current; + while (this->I != End && !isa<SpecificClause>(*this->I)) + ++this->I; } public: - typedef const OMPClause *value_type; - filtered_clause_iterator() : Current(), End() {} - filtered_clause_iterator(ArrayRef<OMPClause *> Arr, FilterPredicate Pred) - : Current(Arr.begin()), End(Arr.end()), Pred(std::move(Pred)) { + explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses) + : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()), + End(Clauses.end()) { SkipToNextClause(); } - value_type operator*() const { return *Current; } - value_type operator->() const { return *Current; } - filtered_clause_iterator &operator++() { - ++Current; - SkipToNextClause(); - return *this; - } - filtered_clause_iterator operator++(int) { - filtered_clause_iterator tmp(*this); - ++(*this); - return tmp; + const SpecificClause *operator*() const { + return cast<SpecificClause>(*this->I); } + const SpecificClause *operator->() const { return **this; } - bool operator!() { return Current == End; } - explicit operator bool() { return Current != End; } - bool empty() const { return Current == End; } + specific_clause_iterator &operator++() { + ++this->I; + SkipToNextClause(); + return *this; + } }; - template <typename Fn> - filtered_clause_iterator<Fn> getFilteredClauses(Fn &&fn) const { - return filtered_clause_iterator<Fn>(clauses(), std::move(fn)); + template <typename SpecificClause> + static llvm::iterator_range<specific_clause_iterator<SpecificClause>> + getClausesOfKind(ArrayRef<OMPClause *> Clauses) { + return {specific_clause_iterator<SpecificClause>(Clauses), + specific_clause_iterator<SpecificClause>( + llvm::makeArrayRef(Clauses.end(), 0))}; } - struct ClauseKindFilter { - OpenMPClauseKind Kind; - bool operator()(const OMPClause *clause) const { - return clause->getClauseKind() == Kind; - } - }; - filtered_clause_iterator<ClauseKindFilter> - getClausesOfKind(OpenMPClauseKind Kind) const { - return getFilteredClauses(ClauseKindFilter{Kind}); + + template <typename SpecificClause> + llvm::iterator_range<specific_clause_iterator<SpecificClause>> + getClausesOfKind() const { + return getClausesOfKind<SpecificClause>(clauses()); } - /// \brief Gets a single clause of the specified kind \a K associated with the + /// Gets a single clause of the specified kind associated with the /// current directive iff there is only one clause of this kind (and assertion /// is fired if there is more than one clause is associated with the - /// directive). Returns nullptr if no clause of kind \a K is associated with + /// directive). Returns nullptr if no clause of this kind is associated with /// the directive. - const OMPClause *getSingleClause(OpenMPClauseKind K) const; + template <typename SpecificClause> + const SpecificClause *getSingleClause() const { + auto Clauses = getClausesOfKind<SpecificClause>(); + + if (Clauses.begin() != Clauses.end()) { + assert(std::next(Clauses.begin()) == Clauses.end() && + "There are at least 2 clauses of the specified kind"); + return *Clauses.begin(); + } + return nullptr; + } + + /// Returns true if the current directive has one or more clauses of a + /// specific kind. + template <typename SpecificClause> + bool hasClausesOfKind() const { + auto Clauses = getClausesOfKind<SpecificClause>(); + return Clauses.begin() != Clauses.end(); + } /// \brief Returns starting location of directive kind. SourceLocation getLocStart() const { return StartLoc; } @@ -195,7 +208,7 @@ public: child_range children() { if (!hasAssociatedStmt()) - return child_range(); + return child_range(child_iterator(), child_iterator()); Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end()); return child_range(ChildStorage, ChildStorage + NumChildren); } @@ -217,6 +230,10 @@ public: /// variables 'c' and 'd'. /// class OMPParallelDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief true if the construct has inner cancel directive. + bool HasCancel; + /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive (directive keyword). @@ -225,7 +242,8 @@ class OMPParallelDirective : public OMPExecutableDirective { OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned NumClauses) : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, - StartLoc, EndLoc, NumClauses, 1) {} + StartLoc, EndLoc, NumClauses, 1), + HasCancel(false) {} /// \brief Build an empty directive. /// @@ -234,7 +252,11 @@ class OMPParallelDirective : public OMPExecutableDirective { explicit OMPParallelDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, SourceLocation(), SourceLocation(), NumClauses, - 1) {} + 1), + HasCancel(false) {} + + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// \brief Creates directive with a list of \a Clauses. @@ -244,10 +266,11 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement associated with the directive. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); /// \brief Creates an empty directive with the place for \a N clauses. /// @@ -257,6 +280,9 @@ public: static OMPParallelDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelDirectiveClass; } @@ -311,11 +337,18 @@ class OMPLoopDirective : public OMPExecutableDirective { return MutableArrayRef<Expr *>(Storage, CollapsedNum); } + /// \brief Get the private counters storage. + MutableArrayRef<Expr *> getPrivateCounters() { + Expr **Storage = reinterpret_cast<Expr **>(&*std::next( + child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + /// \brief Get the updates storage. MutableArrayRef<Expr *> getInits() { Expr **Storage = reinterpret_cast<Expr **>( &*std::next(child_begin(), - getArraysOffset(getDirectiveKind()) + CollapsedNum)); + getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum)); return MutableArrayRef<Expr *>(Storage, CollapsedNum); } @@ -323,7 +356,7 @@ class OMPLoopDirective : public OMPExecutableDirective { MutableArrayRef<Expr *> getUpdates() { Expr **Storage = reinterpret_cast<Expr **>( &*std::next(child_begin(), - getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum)); + getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum)); return MutableArrayRef<Expr *>(Storage, CollapsedNum); } @@ -331,7 +364,7 @@ class OMPLoopDirective : public OMPExecutableDirective { MutableArrayRef<Expr *> getFinals() { Expr **Storage = reinterpret_cast<Expr **>( &*std::next(child_begin(), - getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum)); + getArraysOffset(getDirectiveKind()) + 4 * CollapsedNum)); return MutableArrayRef<Expr *>(Storage, CollapsedNum); } @@ -358,15 +391,19 @@ protected: /// \brief Offset to the start of children expression arrays. static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { - return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd - : DefaultEnd; + return (isOpenMPWorksharingDirective(Kind) || + isOpenMPTaskLoopDirective(Kind) || + isOpenMPDistributeDirective(Kind)) + ? WorksharingEnd + : DefaultEnd; } /// \brief Children number. static unsigned numLoopChildren(unsigned CollapsedNum, OpenMPDirectiveKind Kind) { - return getArraysOffset(Kind) + - 4 * CollapsedNum; // Counters, Inits, Updates and Finals + return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters, + // PrivateCounters, Inits, + // Updates and Finals } void setIterationVariable(Expr *IV) { @@ -387,41 +424,56 @@ protected: void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; } void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; } void setIsLastIterVariable(Expr *IL) { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); *std::next(child_begin(), IsLastIterVariableOffset) = IL; } void setLowerBoundVariable(Expr *LB) { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); *std::next(child_begin(), LowerBoundVariableOffset) = LB; } void setUpperBoundVariable(Expr *UB) { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); *std::next(child_begin(), UpperBoundVariableOffset) = UB; } void setStrideVariable(Expr *ST) { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); *std::next(child_begin(), StrideVariableOffset) = ST; } void setEnsureUpperBound(Expr *EUB) { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); *std::next(child_begin(), EnsureUpperBoundOffset) = EUB; } void setNextLowerBound(Expr *NLB) { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); *std::next(child_begin(), NextLowerBoundOffset) = NLB; } void setNextUpperBound(Expr *NUB) { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); *std::next(child_begin(), NextUpperBoundOffset) = NUB; } void setCounters(ArrayRef<Expr *> A); + void setPrivateCounters(ArrayRef<Expr *> A); void setInits(ArrayRef<Expr *> A); void setUpdates(ArrayRef<Expr *> A); void setFinals(ArrayRef<Expr *> A); @@ -462,6 +514,8 @@ public: Expr *NUB; /// \brief Counters Loop counters. SmallVector<Expr *, 4> Counters; + /// \brief PrivateCounters Loop counters. + SmallVector<Expr *, 4> PrivateCounters; /// \brief Expressions for loop counters inits for CodeGen. SmallVector<Expr *, 4> Inits; /// \brief Expressions for loop counters update for CodeGen. @@ -495,11 +549,13 @@ public: NLB = nullptr; NUB = nullptr; Counters.resize(Size); + PrivateCounters.resize(Size); Inits.resize(Size); Updates.resize(Size); Finals.resize(Size); for (unsigned i = 0; i < Size; ++i) { Counters[i] = nullptr; + PrivateCounters[i] = nullptr; Inits[i] = nullptr; Updates[i] = nullptr; Finals[i] = nullptr; @@ -539,43 +595,50 @@ public: reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset))); } Expr *getIsLastIterVariable() const { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), IsLastIterVariableOffset))); } Expr *getLowerBoundVariable() const { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), LowerBoundVariableOffset))); } Expr *getUpperBoundVariable() const { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), UpperBoundVariableOffset))); } Expr *getStrideVariable() const { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), StrideVariableOffset))); } Expr *getEnsureUpperBound() const { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), EnsureUpperBoundOffset))); } Expr *getNextLowerBound() const { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), NextLowerBoundOffset))); } Expr *getNextUpperBound() const { - assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast<Expr *>(reinterpret_cast<const Expr *>( *std::next(child_begin(), NextUpperBoundOffset))); @@ -597,6 +660,12 @@ public: return const_cast<OMPLoopDirective *>(this)->getCounters(); } + ArrayRef<Expr *> private_counters() { return getPrivateCounters(); } + + ArrayRef<Expr *> private_counters() const { + return const_cast<OMPLoopDirective *>(this)->getPrivateCounters(); + } + ArrayRef<Expr *> inits() { return getInits(); } ArrayRef<Expr *> inits() const { @@ -620,7 +689,10 @@ public: T->getStmtClass() == OMPForDirectiveClass || T->getStmtClass() == OMPForSimdDirectiveClass || T->getStmtClass() == OMPParallelForDirectiveClass || - T->getStmtClass() == OMPParallelForSimdDirectiveClass; + T->getStmtClass() == OMPParallelForSimdDirectiveClass || + T->getStmtClass() == OMPTaskLoopDirectiveClass || + T->getStmtClass() == OMPTaskLoopSimdDirectiveClass || + T->getStmtClass() == OMPDistributeDirectiveClass; } }; @@ -700,6 +772,10 @@ public: /// class OMPForDirective : public OMPLoopDirective { friend class ASTStmtReader; + + /// \brief true if current directive has inner cancel directive. + bool HasCancel; + /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -710,7 +786,8 @@ class OMPForDirective : public OMPLoopDirective { OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc, - CollapsedNum, NumClauses) {} + CollapsedNum, NumClauses), + HasCancel(false) {} /// \brief Build an empty directive. /// @@ -719,7 +796,11 @@ class OMPForDirective : public OMPLoopDirective { /// explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses) {} + SourceLocation(), CollapsedNum, NumClauses), + HasCancel(false) {} + + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// \brief Creates directive with a list of \a Clauses. @@ -731,12 +812,13 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if current directive has inner cancel directive. /// static OMPForDirective *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. @@ -748,6 +830,9 @@ public: static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPForDirectiveClass; } @@ -829,6 +914,10 @@ public: /// class OMPSectionsDirective : public OMPExecutableDirective { friend class ASTStmtReader; + + /// \brief true if current directive has inner cancel directive. + bool HasCancel; + /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -838,7 +927,8 @@ class OMPSectionsDirective : public OMPExecutableDirective { OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned NumClauses) : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections, - StartLoc, EndLoc, NumClauses, 1) {} + StartLoc, EndLoc, NumClauses, 1), + HasCancel(false) {} /// \brief Build an empty directive. /// @@ -847,7 +937,11 @@ class OMPSectionsDirective : public OMPExecutableDirective { explicit OMPSectionsDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections, SourceLocation(), SourceLocation(), NumClauses, - 1) {} + 1), + HasCancel(false) {} + + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// \brief Creates directive with a list of \a Clauses. @@ -857,10 +951,11 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param HasCancel true if current directive has inner directive. /// static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); /// \brief Creates an empty directive with the place for \a NumClauses /// clauses. @@ -871,6 +966,9 @@ public: static OMPSectionsDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPSectionsDirectiveClass; } @@ -884,6 +982,10 @@ public: /// class OMPSectionDirective : public OMPExecutableDirective { friend class ASTStmtReader; + + /// \brief true if current directive has inner cancel directive. + bool HasCancel; + /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -891,13 +993,15 @@ class OMPSectionDirective : public OMPExecutableDirective { /// OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc) : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section, - StartLoc, EndLoc, 0, 1) {} + StartLoc, EndLoc, 0, 1), + HasCancel(false) {} /// \brief Build an empty directive. /// explicit OMPSectionDirective() : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section, - SourceLocation(), SourceLocation(), 0, 1) {} + SourceLocation(), SourceLocation(), 0, 1), + HasCancel(false) {} public: /// \brief Creates directive. @@ -906,11 +1010,12 @@ public: /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. /// \param AssociatedStmt Statement, associated with the directive. + /// \param HasCancel true if current directive has inner directive. /// static OMPSectionDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, bool HasCancel); /// \brief Creates an empty directive. /// @@ -918,6 +1023,12 @@ public: /// static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell); + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } + + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPSectionDirectiveClass; } @@ -1042,18 +1153,22 @@ class OMPCriticalDirective : public OMPExecutableDirective { /// \param Name Name of the directive. /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. /// OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc, - SourceLocation EndLoc) + SourceLocation EndLoc, unsigned NumClauses) : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, - StartLoc, EndLoc, 0, 1), + StartLoc, EndLoc, NumClauses, 1), DirName(Name) {} /// \brief Build an empty directive. /// - explicit OMPCriticalDirective() + /// \param NumClauses Number of clauses. + /// + explicit OMPCriticalDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, - SourceLocation(), SourceLocation(), 0, 1), + SourceLocation(), SourceLocation(), NumClauses, + 1), DirName() {} /// \brief Set name of the directive. @@ -1069,17 +1184,21 @@ public: /// \param Name Name of the directive. /// \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 OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, - SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt); + SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); /// \brief Creates an empty directive. /// /// \param C AST context. + /// \param NumClauses Number of clauses. /// - static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell); + static OMPCriticalDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); /// \brief Return name of the directive. /// @@ -1101,6 +1220,10 @@ public: /// class OMPParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; + + /// \brief true if current region has inner cancel directive. + bool HasCancel; + /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -1111,7 +1234,8 @@ class OMPParallelForDirective : public OMPLoopDirective { OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, - StartLoc, EndLoc, CollapsedNum, NumClauses) {} + StartLoc, EndLoc, CollapsedNum, NumClauses), + HasCancel(false) {} /// \brief Build an empty directive. /// @@ -1121,7 +1245,11 @@ class OMPParallelForDirective : public OMPLoopDirective { explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, SourceLocation(), SourceLocation(), CollapsedNum, - NumClauses) {} + NumClauses), + HasCancel(false) {} + + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// \brief Creates directive with a list of \a Clauses. @@ -1133,11 +1261,12 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if current directive has inner cancel directive. /// static OMPParallelForDirective * 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. @@ -1151,6 +1280,9 @@ public: unsigned CollapsedNum, EmptyShell); + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelForDirectiveClass; } @@ -1236,6 +1368,10 @@ public: /// class OMPParallelSectionsDirective : public OMPExecutableDirective { friend class ASTStmtReader; + + /// \brief true if current directive has inner cancel directive. + bool HasCancel; + /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -1246,7 +1382,8 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective { unsigned NumClauses) : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass, OMPD_parallel_sections, StartLoc, EndLoc, - NumClauses, 1) {} + NumClauses, 1), + HasCancel(false) {} /// \brief Build an empty directive. /// @@ -1255,7 +1392,11 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective { explicit OMPParallelSectionsDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass, OMPD_parallel_sections, SourceLocation(), - SourceLocation(), NumClauses, 1) {} + SourceLocation(), NumClauses, 1), + HasCancel(false) {} + + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// \brief Creates directive with a list of \a Clauses. @@ -1265,10 +1406,11 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param HasCancel true if current directive has inner cancel directive. /// static OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); /// \brief Creates an empty directive with the place for \a NumClauses /// clauses. @@ -1279,6 +1421,9 @@ public: static OMPParallelSectionsDirective * CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelSectionsDirectiveClass; } @@ -1294,6 +1439,9 @@ public: /// class OMPTaskDirective : public OMPExecutableDirective { friend class ASTStmtReader; + /// \brief true if this directive has inner cancel directive. + bool HasCancel; + /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -1303,7 +1451,8 @@ class OMPTaskDirective : public OMPExecutableDirective { OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned NumClauses) : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc, - EndLoc, NumClauses, 1) {} + EndLoc, NumClauses, 1), + HasCancel(false) {} /// \brief Build an empty directive. /// @@ -1312,7 +1461,11 @@ class OMPTaskDirective : public OMPExecutableDirective { explicit OMPTaskDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, SourceLocation(), SourceLocation(), NumClauses, - 1) {} + 1), + HasCancel(false) {} + + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// \brief Creates directive with a list of \a Clauses. @@ -1322,11 +1475,12 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param HasCancel true, if current directive has inner cancel directive. /// static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, bool HasCancel); /// \brief Creates an empty directive with the place for \a NumClauses /// clauses. @@ -1337,6 +1491,9 @@ public: static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPTaskDirectiveClass; } @@ -1592,16 +1749,21 @@ class OMPOrderedDirective : public OMPExecutableDirective { /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. /// - OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc) + OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, - StartLoc, EndLoc, 0, 1) {} + StartLoc, EndLoc, NumClauses, 1) {} /// \brief Build an empty directive. /// - explicit OMPOrderedDirective() + /// \param NumClauses Number of clauses. + /// + explicit OMPOrderedDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, - SourceLocation(), SourceLocation(), 0, 1) {} + SourceLocation(), SourceLocation(), NumClauses, + 1) {} public: /// \brief Creates directive. @@ -1609,18 +1771,20 @@ public: /// \param C AST context. /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// - static OMPOrderedDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AssociatedStmt); + static OMPOrderedDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); /// \brief Creates an empty directive. /// /// \param C AST context. + /// \param NumClauses Number of clauses. /// - static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell); + static OMPOrderedDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); static bool classof(const Stmt *T) { return T->getStmtClass() == OMPOrderedDirectiveClass; @@ -1817,6 +1981,64 @@ public: } }; +/// \brief This represents '#pragma omp target data' directive. +/// +/// \code +/// #pragma omp target data device(0) if(a) map(b[:]) +/// \endcode +/// In this example directive '#pragma omp target data' has clauses 'device' +/// with the value '0', 'if' with condition 'a' and 'map' with array +/// section 'b[:]'. +/// +class OMPTargetDataDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param NumClauses The number of clauses. + /// + OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDataDirectiveClass, + OMPD_target_data, StartLoc, EndLoc, NumClauses, + 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetDataDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDataDirectiveClass, + OMPD_target_data, SourceLocation(), + SourceLocation(), NumClauses, 1) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTargetDataDirective * + 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. + /// + /// \param C AST context. + /// \param N The number of clauses. + /// + static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetDataDirectiveClass; + } +}; + /// \brief This represents '#pragma omp teams' directive. /// /// \code @@ -1947,17 +2169,21 @@ class OMPCancelDirective : public OMPExecutableDirective { /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. /// - OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc) + OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel, - StartLoc, EndLoc, 0, 0), + StartLoc, EndLoc, NumClauses, 0), CancelRegion(OMPD_unknown) {} /// \brief Build an empty directive. /// - explicit OMPCancelDirective() + /// \param NumClauses Number of clauses. + explicit OMPCancelDirective(unsigned NumClauses) : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel, - SourceLocation(), SourceLocation(), 0, 0), + SourceLocation(), SourceLocation(), NumClauses, + 0), CancelRegion(OMPD_unknown) {} /// \brief Set cancel region for current cancellation point. @@ -1970,17 +2196,19 @@ public: /// \param C AST context. /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. /// - static OMPCancelDirective *Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation EndLoc, - OpenMPDirectiveKind CancelRegion); + static OMPCancelDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion); /// \brief Creates an empty directive. /// /// \param C AST context. + /// \param NumClauses Number of clauses. /// - static OMPCancelDirective *CreateEmpty(const ASTContext &C, EmptyShell); + static OMPCancelDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); /// \brief Get cancellation region for the current cancellation point. OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; } @@ -1990,6 +2218,205 @@ public: } }; +/// \brief This represents '#pragma omp taskloop' directive. +/// +/// \code +/// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp taskloop' has clauses 'private' +/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and +/// 'num_tasks' with expression 'num'. +/// +class OMPTaskLoopDirective : public OMPLoopDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop, + StartLoc, EndLoc, CollapsedNum, NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPTaskLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskLoopDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp taskloop simd' directive. +/// +/// \code +/// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp taskloop simd' has clauses 'private' +/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and +/// 'num_tasks' with expression 'num'. +/// +class OMPTaskLoopSimdDirective : public OMPLoopDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass, + OMPD_taskloop_simd, StartLoc, EndLoc, CollapsedNum, + NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass, + OMPD_taskloop_simd, SourceLocation(), SourceLocation(), + CollapsedNum, NumClauses) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPTaskLoopSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp distribute' directive. +/// +/// \code +/// #pragma omp distribute private(a,b) +/// \endcode +/// In this example directive '#pragma omp distribute' has clauses 'private' +/// with the variables 'a' and 'b' +/// +class OMPDistributeDirective : public OMPLoopDirective { + friend class ASTStmtReader; + + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute, + StartLoc, EndLoc, CollapsedNum, NumClauses) + {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPDistributeDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) + {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPDistributeDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPDistributeDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPDistributeDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index c71af38..df4a2d8 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -16,6 +16,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenMP.h" @@ -93,6 +94,7 @@ public: case UO_Real: DISPATCH(UnaryReal, UnaryOperator); case UO_Imag: DISPATCH(UnaryImag, UnaryOperator); case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator); + case UO_Coawait: DISPATCH(UnaryCoawait, UnaryOperator); } } @@ -157,7 +159,7 @@ public: UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) - UNARYOP_FALLBACK(Extension) + UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(Coawait) #undef UNARYOP_FALLBACK // Base case, ignore it. :) diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 1d01753..f87171a 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -22,6 +22,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TrailingObjects.h" namespace llvm { class FoldingSetNodeID; @@ -198,22 +199,19 @@ public: /// /// We assume that storage for the template arguments provided /// outlives the TemplateArgument itself. - TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) { + explicit TemplateArgument(ArrayRef<TemplateArgument> Args) { this->Args.Kind = Pack; - this->Args.Args = Args; - this->Args.NumArgs = NumArgs; + this->Args.Args = Args.data(); + this->Args.NumArgs = Args.size(); } - static TemplateArgument getEmptyPack() { - return TemplateArgument((TemplateArgument*)nullptr, 0); - } + static TemplateArgument getEmptyPack() { return TemplateArgument(None); } /// \brief Create a new template argument pack by copying the given set of /// template arguments. static TemplateArgument CreatePackCopy(ASTContext &Context, - const TemplateArgument *Args, - unsigned NumArgs); - + ArrayRef<TemplateArgument> Args); + /// \brief Return the kind of stored template argument. ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } @@ -523,7 +521,7 @@ class TemplateArgumentListInfo { // This can leak if used in an AST node, use ASTTemplateArgumentListInfo // instead. - void* operator new(size_t bytes, ASTContext& C); + void *operator new(size_t bytes, ASTContext &C) = delete; public: TemplateArgumentListInfo() {} @@ -544,6 +542,10 @@ public: return Arguments.data(); } + llvm::ArrayRef<TemplateArgumentLoc> arguments() const { + return Arguments; + } + const TemplateArgumentLoc &operator[](unsigned I) const { return Arguments[I]; } @@ -561,84 +563,72 @@ public: /// the "<int>" in "sort<int>". /// This is safe to be used inside an AST node, in contrast with /// TemplateArgumentListInfo. -struct ASTTemplateArgumentListInfo { +struct ASTTemplateArgumentListInfo final + : private llvm::TrailingObjects<ASTTemplateArgumentListInfo, + TemplateArgumentLoc> { +private: + friend TrailingObjects; + + ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); + +public: /// \brief The source location of the left angle bracket ('<'). SourceLocation LAngleLoc; - + /// \brief The source location of the right angle bracket ('>'). SourceLocation RAngleLoc; - - union { - /// \brief The number of template arguments in TemplateArgs. - /// The actual template arguments (if any) are stored after the - /// ExplicitTemplateArgumentList structure. - unsigned NumTemplateArgs; - - /// Force ASTTemplateArgumentListInfo to the right alignment - /// for the following array of TemplateArgumentLocs. - llvm::AlignedCharArray< - llvm::AlignOf<TemplateArgumentLoc>::Alignment, 1> Aligner; - }; - /// \brief Retrieve the template arguments - TemplateArgumentLoc *getTemplateArgs() { - return reinterpret_cast<TemplateArgumentLoc *> (this + 1); - } - + /// \brief The number of template arguments in TemplateArgs. + unsigned NumTemplateArgs; + /// \brief Retrieve the template arguments const TemplateArgumentLoc *getTemplateArgs() const { - return reinterpret_cast<const TemplateArgumentLoc *> (this + 1); + return getTrailingObjects<TemplateArgumentLoc>(); } const TemplateArgumentLoc &operator[](unsigned I) const { return getTemplateArgs()[I]; } - static const ASTTemplateArgumentListInfo *Create(ASTContext &C, - const TemplateArgumentListInfo &List); - - void initializeFrom(const TemplateArgumentListInfo &List); - void initializeFrom(const TemplateArgumentListInfo &List, - bool &Dependent, bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack); - void copyInto(TemplateArgumentListInfo &List) const; - static std::size_t sizeFor(unsigned NumTemplateArgs); + static const ASTTemplateArgumentListInfo * + Create(ASTContext &C, const TemplateArgumentListInfo &List); }; -/// \brief Extends ASTTemplateArgumentListInfo with the source location -/// information for the template keyword; this is used as part of the -/// representation of qualified identifiers, such as S<T>::template apply<T>. -struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo { - typedef ASTTemplateArgumentListInfo Base; - - // NOTE: the source location of the (optional) template keyword is - // stored after all template arguments. +/// \brief Represents an explicit template argument list in C++, e.g., +/// the "<int>" in "sort<int>". +/// +/// It is intended to be used as a trailing object on AST nodes, and +/// as such, doesn't contain the array of TemplateArgumentLoc itself, +/// but expects the containing object to also provide storage for +/// that. +struct LLVM_ALIGNAS(LLVM_PTR_SIZE) ASTTemplateKWAndArgsInfo { + /// \brief The source location of the left angle bracket ('<'). + SourceLocation LAngleLoc; - /// \brief Get the source location of the template keyword. - SourceLocation getTemplateKeywordLoc() const { - return *reinterpret_cast<const SourceLocation*> - (getTemplateArgs() + NumTemplateArgs); - } + /// \brief The source location of the right angle bracket ('>'). + SourceLocation RAngleLoc; - /// \brief Sets the source location of the template keyword. - void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) { - *reinterpret_cast<SourceLocation*> - (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc; - } + /// \brief The source location of the template keyword; this is used + /// as part of the representation of qualified identifiers, such as + /// S<T>::template apply<T>. Will be empty if this expression does + /// not have a template keyword. + SourceLocation TemplateKWLoc; - static const ASTTemplateKWAndArgsInfo* - Create(ASTContext &C, SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo &List); + /// \brief The number of template arguments in TemplateArgs. + unsigned NumTemplateArgs; void initializeFrom(SourceLocation TemplateKWLoc, - const TemplateArgumentListInfo &List); + const TemplateArgumentListInfo &List, + TemplateArgumentLoc *OutArgArray); void initializeFrom(SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &List, - bool &Dependent, bool &InstantiationDependent, + TemplateArgumentLoc *OutArgArray, bool &Dependent, + bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack); void initializeFrom(SourceLocation TemplateKWLoc); - static std::size_t sizeFor(unsigned NumTemplateArgs); + void copyInto(const TemplateArgumentLoc *ArgArray, + TemplateArgumentListInfo &List) const; }; const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index f3d23b9..3e10d2f 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -180,9 +180,7 @@ class TemplateName { StorageType Storage; - explicit TemplateName(void *Ptr) { - Storage = StorageType::getFromOpaqueValue(Ptr); - } + explicit TemplateName(void *Ptr); public: // \brief Kind of name that is actually stored. @@ -207,17 +205,15 @@ public: }; TemplateName() : Storage() { } - explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } - explicit TemplateName(OverloadedTemplateStorage *Storage) - : Storage(Storage) { } + explicit TemplateName(TemplateDecl *Template); + explicit TemplateName(OverloadedTemplateStorage *Storage); explicit TemplateName(SubstTemplateTemplateParmStorage *Storage); - explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage) - : Storage(Storage) { } - explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } - explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } + explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage); + explicit TemplateName(QualifiedTemplateName *Qual); + explicit TemplateName(DependentTemplateName *Dep); /// \brief Determine whether this template name is NULL. - bool isNull() const { return Storage.isNull(); } + bool isNull() const; // \brief Get the kind of name that is actually stored. NameKind getKind() const; @@ -238,26 +234,14 @@ public: /// name refers to, if known. If the template name does not refer to a /// specific set of function templates because it is a dependent name or /// refers to a single template, returns NULL. - OverloadedTemplateStorage *getAsOverloadedTemplate() const { - if (UncommonTemplateNameStorage *Uncommon = - Storage.dyn_cast<UncommonTemplateNameStorage *>()) - return Uncommon->getAsOverloadedStorage(); - - return nullptr; - } + OverloadedTemplateStorage *getAsOverloadedTemplate() const; /// \brief Retrieve the substituted template template parameter, if /// known. /// /// \returns The storage for the substituted template template parameter, /// if known. Otherwise, returns NULL. - SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const { - if (UncommonTemplateNameStorage *uncommon = - Storage.dyn_cast<UncommonTemplateNameStorage *>()) - return uncommon->getAsSubstTemplateTemplateParm(); - - return nullptr; - } + SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const; /// \brief Retrieve the substituted template template parameter pack, if /// known. @@ -265,25 +249,15 @@ public: /// \returns The storage for the substituted template template parameter pack, /// if known. Otherwise, returns NULL. SubstTemplateTemplateParmPackStorage * - getAsSubstTemplateTemplateParmPack() const { - if (UncommonTemplateNameStorage *Uncommon = - Storage.dyn_cast<UncommonTemplateNameStorage *>()) - return Uncommon->getAsSubstTemplateTemplateParmPack(); - - return nullptr; - } + getAsSubstTemplateTemplateParmPack() const; /// \brief Retrieve the underlying qualified template name /// structure, if any. - QualifiedTemplateName *getAsQualifiedTemplateName() const { - return Storage.dyn_cast<QualifiedTemplateName *>(); - } + QualifiedTemplateName *getAsQualifiedTemplateName() const; /// \brief Retrieve the underlying dependent template name /// structure, if any. - DependentTemplateName *getAsDependentTemplateName() const { - return Storage.dyn_cast<DependentTemplateName *>(); - } + DependentTemplateName *getAsDependentTemplateName() const; TemplateName getUnderlying() const; @@ -359,9 +333,6 @@ public: TemplateName replacement); }; -inline TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) - : Storage(Storage) { } - inline TemplateName TemplateName::getUnderlying() const { if (SubstTemplateTemplateParmStorage *subst = getAsSubstTemplateTemplateParm()) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 632d4b9..0c08130 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -6,9 +6,12 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Type interface and subclasses. -// +/// \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 @@ -105,7 +108,7 @@ namespace clang { #define TYPE(Class, Base) class Class##Type; #include "clang/AST/TypeNodes.def" -/// Qualifiers - The collection of all-type qualifiers we support. +/// The collection of all-type qualifiers we support. /// Clang supports five independent qualifiers: /// * C99: const, volatile, and restrict /// * Embedded C (TR18037): address spaces @@ -161,7 +164,7 @@ public: Qualifiers() : Mask(0) {} - /// \brief Returns the common set of qualifiers while removing them from + /// Returns the common set of qualifiers while removing them from /// the given sets. static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { // If both are only CVR-qualified, bit operations are sufficient. @@ -342,8 +345,8 @@ public: Mask |= mask; } - /// hasNonFastQualifiers - Return true if the set contains any - /// qualifiers which require an ExtQuals node to be allocated. + /// Return true if the set contains any qualifiers which require an ExtQuals + /// node to be allocated. bool hasNonFastQualifiers() const { return Mask & ~FastMask; } Qualifiers getNonFastQualifiers() const { Qualifiers Quals = *this; @@ -351,11 +354,11 @@ public: return Quals; } - /// hasQualifiers - Return true if the set contains any qualifiers. + /// Return true if the set contains any qualifiers. bool hasQualifiers() const { return Mask; } bool empty() const { return !Mask; } - /// \brief Add the qualifiers from the given set to this set. + /// Add the qualifiers from the given set to this set. void addQualifiers(Qualifiers Q) { // If the other set doesn't have any non-boolean qualifiers, just // bit-or it in. @@ -389,7 +392,7 @@ public: } } - /// \brief Add the qualifiers from the given set to this set, given that + /// Add the qualifiers from the given set to this set, given that /// they don't conflict. void addConsistentQualifiers(Qualifiers qs) { assert(getAddressSpace() == qs.getAddressSpace() || @@ -401,7 +404,7 @@ public: Mask |= qs.Mask; } - /// \brief Returns true if this address space is a superset of the other one. + /// Returns true if this address space is a superset of the other one. /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of /// overlapping address spaces. /// CL1.1 or CL1.2: @@ -418,7 +421,7 @@ public: other.getAddressSpace() != LangAS::opencl_constant); } - /// \brief Determines if these qualifiers compatibly include another set. + /// Determines if these qualifiers compatibly include another set. /// Generally this answers the question of whether an object with the other /// qualifiers can be safely used as an object with these qualifiers. bool compatiblyIncludes(Qualifiers other) const { @@ -438,7 +441,8 @@ public: /// /// One set of Objective-C lifetime qualifiers compatibly includes the other /// if the lifetime qualifiers match, or if both are non-__weak and the - /// including set also contains the 'const' qualifier. + /// including set also contains the 'const' qualifier, or both are non-__weak + /// and one is None (which can only happen in non-ARC modes). bool compatiblyIncludesObjCLifetime(Qualifiers other) const { if (getObjCLifetime() == other.getObjCLifetime()) return true; @@ -446,6 +450,9 @@ public: if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak) return false; + if (getObjCLifetime() == OCL_None || other.getObjCLifetime() == OCL_None) + return true; + return hasConst(); } @@ -551,8 +558,10 @@ enum class ObjCSubstitutionContext { Superclass, }; -/// QualType - For efficiency, we don't store CV-qualified types as nodes on -/// their own: instead each reference to a type stores the qualifiers. This +/// A (possibly-)qualified type. +/// +/// For efficiency, we don't store CV-qualified types as nodes on their +/// own: instead each reference to a type stores the qualifiers. This /// greatly reduces the number of nodes we need to allocate for types (for /// example we only need one for 'int', 'const int', 'volatile int', /// 'const volatile int', etc). @@ -629,7 +638,7 @@ public: bool isCanonical() const; bool isCanonicalAsParam() const; - /// isNull - Return true if this QualType doesn't point to a type yet. + /// Return true if this QualType doesn't point to a type yet. bool isNull() const { return Value.getPointer().isNull(); } @@ -707,29 +716,25 @@ public: /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). bool isPODType(ASTContext &Context) const; - /// isCXX98PODType() - Return true if this is a POD type according to the - /// rules of the C++98 standard, regardless of the current compilation's - /// language. + /// Return true if this is a POD type according to the rules of the C++98 + /// standard, regardless of the current compilation's language. bool isCXX98PODType(ASTContext &Context) const; - /// isCXX11PODType() - Return true if this is a POD type according to the - /// more relaxed rules of the C++11 standard, regardless of the current - /// compilation's language. + /// Return true if this is a POD type according to the more relaxed rules + /// of the C++11 standard, regardless of the current compilation's language. /// (C++0x [basic.types]p9) bool isCXX11PODType(ASTContext &Context) const; - /// isTrivialType - Return true if this is a trivial type - /// (C++0x [basic.types]p9) + /// Return true if this is a trivial type per (C++0x [basic.types]p9) bool isTrivialType(ASTContext &Context) const; - /// isTriviallyCopyableType - Return true if this is a trivially - /// copyable type (C++0x [basic.types]p9) + /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(ASTContext &Context) const; // Don't promise in the API that anything besides 'const' can be // easily added. - /// addConst - add the specified type qualifier to this QualType. + /// Add the `const` type qualifier to this QualType. void addConst() { addFastQualifiers(Qualifiers::Const); } @@ -737,15 +742,15 @@ public: return withFastQualifiers(Qualifiers::Const); } - /// addVolatile - add the specified type qualifier to this QualType. + /// Add the `volatile` type qualifier to this QualType. void addVolatile() { addFastQualifiers(Qualifiers::Volatile); } QualType withVolatile() const { return withFastQualifiers(Qualifiers::Volatile); } - - /// Add the restrict qualifier to this QualType. + + /// Add the `restrict` qualifier to this QualType. void addRestrict() { addFastQualifiers(Qualifiers::Restrict); } @@ -822,8 +827,8 @@ public: /// ASTContext::getUnqualifiedArrayType. inline QualType getUnqualifiedType() const; - /// getSplitUnqualifiedType - Retrieve the unqualified variant of the - /// given type, removing as little sugar as possible. + /// Retrieve the unqualified variant of the given type, removing as little + /// sugar as possible. /// /// Like getUnqualifiedType(), but also returns the set of /// qualifiers that were built up. @@ -853,7 +858,7 @@ public: /// from non-class types (in C++) or all types (in C). QualType getNonLValueExprType(const ASTContext &Context) const; - /// getDesugaredType - Return the specified type with any "sugar" removed from + /// Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar /// to getting the canonical type, but it doesn't remove *all* typedefs. For @@ -878,7 +883,7 @@ public: return getSingleStepDesugaredTypeImpl(*this, Context); } - /// IgnoreParens - Returns the specified type after dropping any + /// Returns the specified type after dropping any /// outer-level parentheses. QualType IgnoreParens() const { if (isa<ParenType>(*this)) @@ -886,8 +891,7 @@ public: return *this; } - /// operator==/!= - Indicate whether the specified types and qualifiers are - /// identical. + /// Indicate whether the specified types and qualifiers are identical. friend bool operator==(const QualType &LHS, const QualType &RHS) { return LHS.Value == RHS.Value; } @@ -956,23 +960,23 @@ public: ID.AddPointer(getAsOpaquePtr()); } - /// getAddressSpace - Return the address space of this type. + /// Return the address space of this type. inline unsigned getAddressSpace() const; - /// getObjCGCAttr - Returns gc attribute of this type. + /// Returns gc attribute of this type. inline Qualifiers::GC getObjCGCAttr() const; - /// isObjCGCWeak true when Type is objc's weak. + /// true when Type is objc's weak. bool isObjCGCWeak() const { return getObjCGCAttr() == Qualifiers::Weak; } - /// isObjCGCStrong true when Type is objc's strong. + /// true when Type is objc's strong. bool isObjCGCStrong() const { return getObjCGCAttr() == Qualifiers::Strong; } - /// getObjCLifetime - Returns lifetime attribute of this type. + /// Returns lifetime attribute of this type. Qualifiers::ObjCLifetime getObjCLifetime() const { return getQualifiers().getObjCLifetime(); } @@ -992,7 +996,7 @@ public: DK_objc_weak_lifetime }; - /// isDestructedType - nonzero if objects of this type require + /// Returns a nonzero value if objects of this type require /// non-trivial work to clean up after. Non-zero because it's /// conceivable that qualifiers (objc_gc(weak)?) could make /// something require destruction. @@ -1000,7 +1004,7 @@ public: return isDestructedTypeImpl(*this); } - /// \brief Determine whether expressions of the given type are forbidden + /// Determine whether expressions of the given type are forbidden /// from being lvalues in C. /// /// The expression types that are forbidden to be lvalues are: @@ -1124,7 +1128,7 @@ class ExtQualsTypeCommonBase { friend class ExtQuals; }; -/// ExtQuals - We can encode up to four bits in the low bits of a +/// We can encode up to four bits in the low bits of a /// type pointer, but there are many more type qualifiers that we want /// to be able to apply to an arbitrary type. Therefore we have this /// struct, intended to be heap-allocated and used by QualType to @@ -1148,8 +1152,8 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode { // 3. ASTContext: // a) Update get{Volatile,Restrict}Type. - /// Quals - the immutable set of qualifiers applied by this - /// node; always contains extended qualifiers. + /// The immutable set of qualifiers applied by this node. Always contains + /// extended qualifiers. Qualifiers Quals; ExtQuals *this_() { return this; } @@ -1194,8 +1198,8 @@ public: } }; -/// \brief The kind of C++0x ref-qualifier associated with a function type, -/// which determines whether a member function's "this" object can be an +/// The kind of C++11 ref-qualifier associated with a function type. +/// This determines whether a member function's "this" object can be an /// lvalue, rvalue, or neither. enum RefQualifierKind { /// \brief No ref-qualifier was provided. @@ -1206,17 +1210,28 @@ enum RefQualifierKind { RQ_RValue }; -/// Type - This is the base class of the type hierarchy. A central concept -/// with types is that each type always has a canonical type. A canonical type -/// is the type with any typedef names stripped out of it or the types it -/// references. For example, consider: +/// Which keyword(s) were used to create an AutoType. +enum class AutoTypeKeyword { + /// \brief auto + Auto, + /// \brief decltype(auto) + DecltypeAuto, + /// \brief __auto_type (GNU extension) + GNUAutoType +}; + +/// The base class of the type hierarchy. +/// +/// A central concept with types is that each type always has a canonical +/// type. A canonical type is the type with any typedef names stripped out +/// of it or the types it references. For example, consider: /// /// typedef int foo; /// typedef foo* bar; /// 'int *' 'foo *' 'bar' /// /// There will be a Type object created for 'int'. Since int is canonical, its -/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a +/// CanonicalType pointer points to itself. There is also a Type for 'foo' (a /// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next /// there is a PointerType that represents 'int*', which, like 'int', is /// canonical. Finally, there is a PointerType type for 'foo*' whose canonical @@ -1253,18 +1268,18 @@ private: /// TypeClass bitfield - Enum that specifies what subclass this belongs to. unsigned TC : 8; - /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). + /// Whether this type is a dependent type (C++ [temp.dep.type]). unsigned Dependent : 1; - /// \brief Whether this type somehow involves a template parameter, even + /// Whether this type somehow involves a template parameter, even /// if the resolution of the type does not depend on a template parameter. unsigned InstantiationDependent : 1; - /// \brief Whether this type is a variably-modified type (C99 6.7.5). + /// Whether this type is a variably-modified type (C99 6.7.5). unsigned VariablyModified : 1; /// \brief Whether this type contains an unexpanded parameter pack - /// (for C++0x variadic templates). + /// (for C++11 variadic templates). unsigned ContainsUnexpandedParameterPack : 1; /// \brief True if the cache (i.e. the bitfields here starting with @@ -1277,7 +1292,7 @@ private: /// \brief Whether this type involves and local or unnamed types. mutable unsigned CachedLocalOrUnnamed : 1; - /// \brief FromAST - Whether this type comes from an AST file. + /// \brief Whether this type comes from an AST file. mutable unsigned FromAST : 1; bool isCacheValid() const { @@ -1303,11 +1318,11 @@ protected: unsigned : NumTypeBits; - /// IndexTypeQuals - CVR qualifiers from declarations like + /// CVR qualifiers from declarations like /// 'int X[static restrict 4]'. For function parameters only. unsigned IndexTypeQuals : 3; - /// SizeModifier - storage class qualifiers from declarations like + /// Storage class qualifiers from declarations like /// 'int X[static restrict 4]'. For function parameters only. /// Actually an ArrayType::ArraySizeModifier. unsigned SizeModifier : 3; @@ -1332,7 +1347,7 @@ protected: /// regparm and the calling convention. unsigned ExtInfo : 9; - /// TypeQuals - Used only by FunctionProtoType, put here to pack with the + /// Used only by FunctionProtoType, put here to pack with the /// other bitfields. /// The qualifiers are part of FunctionProtoType because... /// @@ -1354,8 +1369,7 @@ protected: /// The number of type arguments stored directly on this object type. unsigned NumTypeArgs : 7; - /// NumProtocols - The number of protocols stored directly on this - /// object type. + /// The number of protocols stored directly on this object type. unsigned NumProtocols : 6; /// Whether this is a "kindof" type. @@ -1400,11 +1414,11 @@ protected: unsigned : NumTypeBits; - /// VecKind - The kind of vector, either a generic vector type or some + /// The kind of vector, either a generic vector type or some /// target-specific vector type such as for AltiVec or Neon. unsigned VecKind : 3; - /// NumElements - The number of elements in the vector. + /// The number of elements in the vector. unsigned NumElements : 29 - NumTypeBits; enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 }; @@ -1415,7 +1429,7 @@ protected: unsigned : NumTypeBits; - /// AttrKind - an AttributedType::Kind + /// An AttributedType::Kind unsigned AttrKind : 32 - NumTypeBits; }; @@ -1424,8 +1438,9 @@ protected: unsigned : NumTypeBits; - /// Was this placeholder type spelled as 'decltype(auto)'? - unsigned IsDecltypeAuto : 1; + /// Was this placeholder type spelled as 'auto', 'decltype(auto)', + /// or '__auto_type'? AutoTypeKeyword value. + unsigned Keyword : 2; }; union { @@ -1521,17 +1536,17 @@ public: /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. - /// isIncompleteType - Return true if this is an incomplete type. + /// Return true if this is an incomplete type. /// A type that can describe objects, but which lacks information needed to /// determine its size (e.g. void, or a fwd declared struct). Clients of this /// routine will need to determine if the size is actually required. /// - /// \brief Def If non-NULL, and the type refers to some kind of declaration + /// \brief Def If non-null, and the type refers to some kind of declaration /// that can be completed (such as a C struct, C++ class, or Objective-C /// class), will be set to the declaration. bool isIncompleteType(NamedDecl **Def = nullptr) const; - /// isIncompleteOrObjectType - Return true if this is an incomplete or object + /// Return true if this is an incomplete or object /// type, in other words, not a function type. bool isIncompleteOrObjectType() const { return !isFunctionType(); @@ -1545,35 +1560,34 @@ public: return !isReferenceType() && !isFunctionType() && !isVoidType(); } - /// isLiteralType - Return true if this is a literal type + /// Return true if this is a literal type /// (C++11 [basic.types]p10) bool isLiteralType(const ASTContext &Ctx) const; - /// \brief Test if this type is a standard-layout type. + /// Test if this type is a standard-layout type. /// (C++0x [basic.type]p9) bool isStandardLayoutType() const; /// Helper methods to distinguish type categories. All type predicates /// operate on the canonical type, ignoring typedefs and qualifiers. - /// isBuiltinType - returns true if the type is a builtin type. + /// Returns true if the type is a builtin type. bool isBuiltinType() const; - /// isSpecificBuiltinType - Test for a particular builtin type. + /// Test for a particular builtin type. bool isSpecificBuiltinType(unsigned K) const; - /// isPlaceholderType - Test for a type which does not represent an - /// actual type-system type but is instead used as a placeholder for - /// various convenient purposes within Clang. All such types are - /// BuiltinTypes. + /// Test for a type which does not represent an actual type-system type but + /// is instead used as a placeholder for various convenient purposes within + /// Clang. All such types are BuiltinTypes. bool isPlaceholderType() const; const BuiltinType *getAsPlaceholderType() const; - /// isSpecificPlaceholderType - Test for a specific placeholder type. + /// Test for a specific placeholder type. bool isSpecificPlaceholderType(unsigned K) const; - /// isNonOverloadPlaceholderType - Test for a placeholder type - /// other than Overload; see BuiltinType::isNonOverloadPlaceholderType. + /// Test for a placeholder type other than Overload; see + /// BuiltinType::isNonOverloadPlaceholderType. bool isNonOverloadPlaceholderType() const; /// isIntegerType() does *not* include complex integers (a GCC extension). @@ -1588,10 +1602,9 @@ public: bool isAnyCharacterType() const; bool isIntegralType(ASTContext &Ctx) const; - /// \brief Determine whether this type is an integral or enumeration type. + /// Determine whether this type is an integral or enumeration type. bool isIntegralOrEnumerationType() const; - /// \brief Determine whether this type is an integral or unscoped enumeration - /// type. + /// Determine whether this type is an integral or unscoped enumeration type. bool isIntegralOrUnscopedEnumerationType() const; /// Floating point categories. @@ -1655,6 +1668,7 @@ public: bool isObjCQualifiedClassType() const; // Class<foo> bool isObjCObjectOrInterfaceType() const; bool isObjCIdType() const; // id + bool isObjCInertUnsafeUnretainedType() const; /// Whether the type is Objective-C 'id' or a __kindof type of an /// object type, e.g., __kindof NSView * or __kindof id @@ -1685,17 +1699,27 @@ public: bool isNullPtrType() const; // C++0x nullptr_t bool isAtomicType() const; // C11 _Atomic() - bool isImage1dT() const; // OpenCL image1d_t - bool isImage1dArrayT() const; // OpenCL image1d_array_t - bool isImage1dBufferT() const; // OpenCL image1d_buffer_t - bool isImage2dT() const; // OpenCL image2d_t - bool isImage2dArrayT() const; // OpenCL image2d_array_t - bool isImage3dT() const; // OpenCL image3d_t + bool isImage1dT() const; // OpenCL image1d_t + bool isImage1dArrayT() const; // OpenCL image1d_array_t + bool isImage1dBufferT() const; // OpenCL image1d_buffer_t + bool isImage2dT() const; // OpenCL image2d_t + bool isImage2dArrayT() const; // OpenCL image2d_array_t + bool isImage2dDepthT() const; // OpenCL image_2d_depth_t + bool isImage2dArrayDepthT() const; // OpenCL image_2d_array_depth_t + bool isImage2dMSAAT() const; // OpenCL image_2d_msaa_t + bool isImage2dArrayMSAAT() const; // OpenCL image_2d_array_msaa_t + bool isImage2dMSAATDepth() const; // OpenCL image_2d_msaa_depth_t + bool isImage2dArrayMSAATDepth() const; // OpenCL image_2d_array_msaa_depth_t + bool isImage3dT() const; // OpenCL image3d_t bool isImageType() const; // Any OpenCL image type bool isSamplerT() const; // OpenCL sampler_t bool isEventT() const; // OpenCL event_t + bool isClkEventT() const; // OpenCL clk_event_t + bool isQueueT() const; // OpenCL queue_t + bool isNDRangeT() const; // OpenCL ndrange_t + bool isReserveIDT() const; // OpenCL reserve_id_t bool isOpenCLSpecificType() const; // Any OpenCL specific type @@ -1718,12 +1742,11 @@ public: STK_IntegralComplex, STK_FloatingComplex }; - /// getScalarTypeKind - Given that this is a scalar type, classify it. + /// Given that this is a scalar type, classify it. ScalarTypeKind getScalarTypeKind() const; - /// isDependentType - Whether this type is a dependent type, meaning - /// that its definition somehow depends on a template parameter - /// (C++ [temp.dep.type]). + /// Whether this type is a dependent type, meaning that its definition + /// somehow depends on a template parameter (C++ [temp.dep.type]). bool isDependentType() const { return TypeBits.Dependent; } /// \brief Determine whether this type is an instantiation-dependent type, @@ -1755,14 +1778,13 @@ public: bool canDecayToPointerType() const; - /// hasPointerRepresentation - Whether this type is represented - /// natively as a pointer; this includes pointers, references, block - /// pointers, and Objective-C interface, qualified id, and qualified - /// interface types, as well as nullptr_t. + /// Whether this type is represented natively as a pointer. This includes + /// pointers, references, block pointers, and Objective-C interface, + /// qualified id, and qualified interface types, as well as nullptr_t. bool hasPointerRepresentation() const; - /// hasObjCPointerRepresentation - Whether this type can represent - /// an objective pointer type for the purpose of GC'ability + /// Whether this type can represent an objective pointer type for the + /// purpose of GC'ability bool hasObjCPointerRepresentation() const; /// \brief Determine whether this type has an integer representation @@ -1813,7 +1835,7 @@ public: /// not refer to a CXXRecordDecl, returns NULL. const CXXRecordDecl *getPointeeCXXRecordDecl() const; - /// \brief Get the AutoType whose type will be deduced for a variable with + /// Get the AutoType whose type will be deduced for a variable with /// an initializer of this type. This looks through declarators like pointer /// types, but not through decltype or typedefs. AutoType *getContainedAutoType() const; @@ -1842,34 +1864,33 @@ public: /// qualifiers from the outermost type. const ArrayType *castAsArrayTypeUnsafe() const; - /// getBaseElementTypeUnsafe - Get the base element type of this - /// type, potentially discarding type qualifiers. This method - /// should never be used when type qualifiers are meaningful. + /// Get the base element type of this type, potentially discarding type + /// qualifiers. This should never be used when type qualifiers + /// are meaningful. const Type *getBaseElementTypeUnsafe() const; - /// getArrayElementTypeNoTypeQual - If this is an array type, return the - /// element type of the array, potentially with type qualifiers missing. - /// This method should never be used when type qualifiers are meaningful. + /// If this is an array type, return the element type of the array, + /// potentially with type qualifiers missing. + /// This should never be used when type qualifiers are meaningful. const Type *getArrayElementTypeNoTypeQual() const; - /// getPointeeType - If this is a pointer, ObjC object pointer, or block + /// If this is a pointer, ObjC object pointer, or block /// pointer, this returns the respective pointee. QualType getPointeeType() const; - /// getUnqualifiedDesugaredType() - Return the specified type with - /// any "sugar" removed from the type, removing any typedefs, - /// typeofs, etc., as well as any qualifiers. + /// Return the specified type with any "sugar" removed from the type, + /// removing any typedefs, typeofs, etc., as well as any qualifiers. const Type *getUnqualifiedDesugaredType() const; /// More type predicates useful for type checking/promotion bool isPromotableIntegerType() const; // C99 6.3.1.1p2 - /// isSignedIntegerType - Return true if this is an integer type that is + /// Return true if this is an integer type that is /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], /// or an enum decl which has a signed representation. bool isSignedIntegerType() const; - /// isUnsignedIntegerType - Return true if this is an integer type that is + /// Return true if this is an integer type that is /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], /// or an enum decl which has an unsigned representation. bool isUnsignedIntegerType() const; @@ -1882,32 +1903,32 @@ public: /// enumeration types whose underlying type is a unsigned integer type. bool isUnsignedIntegerOrEnumerationType() const; - /// isConstantSizeType - Return true if this is not a variable sized type, + /// Return true if this is not a variable sized type, /// according to the rules of C99 6.7.5p3. It is not legal to call this on /// incomplete types. bool isConstantSizeType() const; - /// isSpecifierType - Returns true if this type can be represented by some + /// Returns true if this type can be represented by some /// set of type specifiers. bool isSpecifierType() const; - /// \brief Determine the linkage of this type. + /// Determine the linkage of this type. Linkage getLinkage() const; - /// \brief Determine the visibility of this type. + /// Determine the visibility of this type. Visibility getVisibility() const { return getLinkageAndVisibility().getVisibility(); } - /// \brief Return true if the visibility was explicitly set is the code. + /// Return true if the visibility was explicitly set is the code. bool isVisibilityExplicit() const { return getLinkageAndVisibility().isVisibilityExplicit(); } - /// \brief Determine the linkage and visibility of this type. + /// Determine the linkage and visibility of this type. LinkageInfo getLinkageAndVisibility() const; - /// \brief True if the computed linkage is valid. Used for consistency + /// True if the computed linkage is valid. Used for consistency /// checking. Should always return true. bool isLinkageValid() const; @@ -1984,7 +2005,7 @@ template <> inline const Class##Type *Type::castAs() const { \ #include "clang/AST/TypeNodes.def" -/// BuiltinType - This class is used for builtin types like 'int'. Builtin +/// This class is used for builtin types like 'int'. Builtin /// types are always canonical and have a literal name field. class BuiltinType : public Type { public: @@ -2059,7 +2080,7 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } }; -/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex +/// 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 { @@ -2089,7 +2110,7 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Complex; } }; -/// ParenType - Sugar for parentheses used when specifying types. +/// Sugar for parentheses used when specifying types. /// class ParenType : public Type, public llvm::FoldingSetNode { QualType Inner; @@ -2138,7 +2159,7 @@ public: QualType getPointeeType() const { return PointeeType; } - /// \brief Returns true if address spaces of pointers overlap. + /// Returns true if address spaces of pointers overlap. /// OpenCL v2.0 defines conversion rules for pointers to different /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping /// address spaces. @@ -2167,7 +2188,7 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } }; -/// \brief Represents a type which was implicitly adjusted by the semantic +/// Represents a type which was implicitly adjusted by the semantic /// engine for arbitrary reasons. For example, array and function types can /// decay, and function types can have their calling conventions adjusted. class AdjustedType : public Type, public llvm::FoldingSetNode { @@ -2205,7 +2226,7 @@ public: } }; -/// \brief Represents a pointer type decayed from an array or function type. +/// Represents a pointer type decayed from an array or function type. class DecayedType : public AdjustedType { DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr) @@ -2225,7 +2246,7 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Decayed; } }; -/// BlockPointerType - pointer to a block type. +/// 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. /// @@ -2260,7 +2281,7 @@ public: } }; -/// ReferenceType - Base for LValueReferenceType and RValueReferenceType +/// Base for LValueReferenceType and RValueReferenceType /// class ReferenceType : public Type, public llvm::FoldingSetNode { QualType PointeeType; @@ -2307,7 +2328,7 @@ public: } }; -/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference +/// An lvalue reference type, per C++11 [dcl.ref]. /// class LValueReferenceType : public ReferenceType { LValueReferenceType(QualType Referencee, QualType CanonicalRef, @@ -2324,7 +2345,7 @@ public: } }; -/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference +/// An rvalue reference type, per C++11 [dcl.ref]. /// class RValueReferenceType : public ReferenceType { RValueReferenceType(QualType Referencee, QualType CanonicalRef) : @@ -2340,7 +2361,9 @@ public: } }; -/// MemberPointerType - C++ 8.3.3 - Pointers to members +/// 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 { QualType PointeeType; @@ -2395,11 +2418,11 @@ public: } }; -/// ArrayType - C99 6.7.5.2 - Array Declarators. +/// Represents an array type, per C99 6.7.5.2 - Array Declarators. /// class ArrayType : public Type, public llvm::FoldingSetNode { public: - /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4]) + /// Capture whether this is a normal array (e.g. int X[4]) /// an array with a static size (e.g. int X[static 4]), or an array /// with a star size (e.g. int X[*]). /// 'static' is only allowed on function parameters. @@ -2407,7 +2430,7 @@ public: Normal, Static, Star }; private: - /// ElementType - The element type of the array. + /// The element type of the array. QualType ElementType; protected: @@ -2450,10 +2473,9 @@ public: } }; -/// ConstantArrayType - This class represents the canonical version of -/// C arrays with a specified constant size. For example, the canonical -/// type for 'int A[4 + 4*100]' is a ConstantArrayType where the element -/// type is 'int' and the size is 404. +/// Represents the canonical version of C arrays with a specified constant size. +/// For example, the canonical type for 'int A[4 + 4*100]' is a +/// ConstantArrayType where the element type is 'int' and the size is 404. class ConstantArrayType : public ArrayType { llvm::APInt Size; // Allows us to unique the type. @@ -2501,9 +2523,9 @@ public: } }; -/// IncompleteArrayType - This class represents C arrays with an unspecified -/// size. For example 'int A[]' has an IncompleteArrayType where the element -/// type is 'int' and the size is unspecified. +/// Represents a C array with an unspecified size. For example 'int A[]' has +/// an IncompleteArrayType where the element type is 'int' and the size is +/// unspecified. class IncompleteArrayType : public ArrayType { IncompleteArrayType(QualType et, QualType can, @@ -2534,8 +2556,8 @@ public: } }; -/// VariableArrayType - This class represents C arrays with a specified size -/// which is not an integer-constant-expression. For example, 'int s[x+foo()]'. +/// Represents a C array with a specified size that is not an +/// integer-constant-expression. For example, 'int s[x+foo()]'. /// Since the size expression is an arbitrary expression, we store it as such. /// /// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and @@ -2550,10 +2572,10 @@ public: /// } /// class VariableArrayType : public ArrayType { - /// SizeExpr - An assignment expression. VLA's are only permitted within + /// An assignment-expression. VLA's are only permitted within /// a function block. Stmt *SizeExpr; - /// Brackets - The left and right array brackets. + /// The range spanned by the left and right array brackets. SourceRange Brackets; VariableArrayType(QualType et, QualType can, Expr *e, @@ -2588,9 +2610,9 @@ public: } }; -/// DependentSizedArrayType - This type represents an array type in -/// C++ whose size is a value-dependent expression. For example: +/// Represents an array type in C++ whose size is a value-dependent expression. /// +/// For example: /// \code /// template<typename T, int Size> /// class array { @@ -2607,11 +2629,11 @@ class DependentSizedArrayType : public ArrayType { /// \brief An assignment expression that will instantiate to the /// size of the array. /// - /// The expression itself might be NULL, in which case the array + /// The expression itself might be null, in which case the array /// type will have its size deduced from an initializer. Stmt *SizeExpr; - /// Brackets - The left and right array brackets. + /// The range spanned by the left and right array brackets. SourceRange Brackets; DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can, @@ -2650,18 +2672,20 @@ public: unsigned TypeQuals, Expr *E); }; -/// DependentSizedExtVectorType - This type represent an extended vector type -/// where either the type or size is dependent. For example: -/// @code +/// Represents an extended vector type where either the type or size is +/// dependent. +/// +/// For example: +/// \code /// template<typename T, int Size> /// class vector { /// typedef T __attribute__((ext_vector_type(Size))) type; /// } -/// @endcode +/// \endcode class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode { const ASTContext &Context; Expr *SizeExpr; - /// ElementType - The element type of the array. + /// The element type of the array. QualType ElementType; SourceLocation loc; @@ -2691,7 +2715,7 @@ public: }; -/// VectorType - GCC generic vector type. This type is created using +/// Represents a GCC generic vector type. This type is created using /// __attribute__((vector_size(n)), where "n" specifies the vector size in /// bytes; or from an Altivec __vector or vector declaration. /// Since the constructor takes the number of vector elements, the @@ -2699,15 +2723,15 @@ 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 + 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 }; protected: - /// ElementType - The element type of the vector. + /// The element type of the vector. QualType ElementType; VectorType(QualType vecType, unsigned nElements, QualType canonType, @@ -2824,7 +2848,7 @@ class FunctionType : public Type { QualType ResultType; public: - /// ExtInfo - A class which abstracts out some details necessary for + /// A class which abstracts out some details necessary for /// making a call. /// /// It is not actually used directly for storing this information in @@ -2878,7 +2902,7 @@ class FunctionType : public Type { } // Constructor with all defaults. Use when for example creating a - // function know to use defaults. + // function known to use defaults. ExtInfo() : Bits(CC_C) { } // Constructor with just the calling convention, which is an important part @@ -2953,7 +2977,7 @@ public: bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } - /// \brief Determine whether this function type includes the GNU noreturn + /// 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(); } @@ -2977,7 +3001,7 @@ public: } }; -/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has +/// 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) @@ -3008,7 +3032,7 @@ public: } }; -/// FunctionProtoType - Represents a prototype with parameter type info, e.g. +/// Represents a prototype with parameter type info, e.g. /// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no /// parameters, not as having a single void parameter. Such a type can have an /// exception specification, but this specification is not part of the canonical @@ -3038,7 +3062,7 @@ public: FunctionDecl *SourceTemplate; }; - /// ExtProtoInfo - Extra information about a function prototype. + /// Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : Variadic(false), HasTrailingReturn(false), TypeQuals(0), @@ -3081,19 +3105,19 @@ private: /// The number of parameters this function has, not counting '...'. unsigned NumParams : 15; - /// NumExceptions - The number of types in the exception spec, if any. + /// The number of types in the exception spec, if any. unsigned NumExceptions : 9; - /// ExceptionSpecType - The type of exception specification this function has. + /// The type of exception specification this function has. unsigned ExceptionSpecType : 4; - /// HasAnyConsumedParams - Whether this function has any consumed parameters. + /// Whether this function has any consumed parameters. unsigned HasAnyConsumedParams : 1; - /// Variadic - Whether the function is variadic. + /// Whether the function is variadic. unsigned Variadic : 1; - /// HasTrailingReturn - Whether this function has a trailing return type. + /// Whether this function has a trailing return type. unsigned HasTrailingReturn : 1; // ParamInfo - There is an variable size array after the class in memory that @@ -3120,11 +3144,13 @@ private: assert(hasAnyConsumedParams()); // Find the end of the exceptions. - Expr *const *eh_end = reinterpret_cast<Expr *const *>(param_type_end()); - if (getExceptionSpecType() != EST_ComputedNoexcept) - eh_end += NumExceptions; - else + Expr *const *eh_end = reinterpret_cast<Expr *const *>(exception_end()); + if (getExceptionSpecType() == EST_ComputedNoexcept) eh_end += 1; // NoexceptExpr + // The memory layout of these types isn't handled here, so + // hopefully this is never called for them? + assert(getExceptionSpecType() != EST_Uninstantiated && + getExceptionSpecType() != EST_Unevaluated); return reinterpret_cast<const bool*>(eh_end); } @@ -3162,25 +3188,25 @@ public: return EPI; } - /// \brief Get the kind of exception specification on this function. + /// Get the kind of exception specification on this function. ExceptionSpecificationType getExceptionSpecType() const { return static_cast<ExceptionSpecificationType>(ExceptionSpecType); } - /// \brief Return whether this function has any kind of exception spec. + /// Return whether this function has any kind of exception spec. bool hasExceptionSpec() const { return getExceptionSpecType() != EST_None; } - /// \brief Return whether this function has a dynamic (throw) exception spec. + /// Return whether this function has a dynamic (throw) exception spec. bool hasDynamicExceptionSpec() const { return isDynamicExceptionSpec(getExceptionSpecType()); } - /// \brief Return whether this function has a noexcept exception spec. + /// Return whether this function has a noexcept exception spec. bool hasNoexceptExceptionSpec() const { return isNoexceptExceptionSpec(getExceptionSpecType()); } - /// \brief Return whether this function has a dependent exception spec. + /// Return whether this function has a dependent exception spec. bool hasDependentExceptionSpec() const; - /// \brief Result type of getNoexceptSpec(). + /// Result type of getNoexceptSpec(). enum NoexceptResult { NR_NoNoexcept, ///< There is no noexcept specifier. NR_BadNoexcept, ///< The noexcept specifier has a bad expression. @@ -3188,7 +3214,7 @@ public: NR_Throw, ///< The noexcept specifier evaluates to false. NR_Nothrow ///< The noexcept specifier evaluates to true. }; - /// \brief Get the meaning of the noexcept spec on this function, if any. + /// Get the meaning of the noexcept spec on this function, if any. NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const; unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { @@ -3220,14 +3246,14 @@ public: return nullptr; return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1]; } - /// \brief Determine whether this function type has a non-throwing exception + /// Determine whether this function type has a non-throwing exception /// specification. If this depends on template arguments, returns /// \c ResultIfDependent. bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const; bool isVariadic() const { return Variadic; } - /// \brief Determines whether this function prototype contains a + /// Determines whether this function prototype contains a /// parameter pack at the end. /// /// A function template whose last parameter is a parameter pack can be @@ -3240,7 +3266,7 @@ public: unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); } - /// \brief Retrieve the ref-qualifier associated with this function type. + /// Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); } @@ -3284,7 +3310,7 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - void printExceptionSpecification(raw_ostream &OS, + void printExceptionSpecification(raw_ostream &OS, const PrintingPolicy &Policy) const; static bool classof(const Type *T) { @@ -3297,10 +3323,10 @@ public: const ExtProtoInfo &EPI, const ASTContext &Context); }; - /// \brief Represents the dependent type named by a dependently-scoped /// typename using declaration, e.g. /// using typename Base<T>::foo; +/// /// Template instantiation turns these into the underlying type. class UnresolvedUsingType : public Type { UnresolvedUsingTypenameDecl *Decl; @@ -3353,7 +3379,7 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } }; -/// TypeOfExprType (GCC extension). +/// Represents a `typeof` (or __typeof__) expression (a GCC extension). class TypeOfExprType : public Type { Expr *TOExpr; @@ -3373,7 +3399,7 @@ public: }; /// \brief Internal representation of canonical, dependent -/// typeof(expr) types. +/// `typeof(expr)` types. /// /// This class is used internally by the ASTContext to manage /// canonical, dependent types, only. Clients will only see instances @@ -3394,7 +3420,7 @@ public: Expr *E); }; -/// TypeOfType (GCC extension). +/// Represents `typeof(type)`, a GCC extension. class TypeOfType : public Type { QualType TOType; TypeOfType(QualType T, QualType can) @@ -3418,7 +3444,7 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } }; -/// DecltypeType (C++0x) +/// Represents the type `decltype(expr)` (C++11). class DecltypeType : public Type { Expr *E; QualType UnderlyingType; @@ -3459,7 +3485,7 @@ public: Expr *E); }; -/// \brief A unary type transform, which is a type constructed from another +/// A unary type transform, which is a type constructed from another. class UnaryTransformType : public Type { public: enum UTTKind { @@ -3497,15 +3523,14 @@ class TagType : public Type { TagDecl * decl; friend class ASTReader; - + protected: TagType(TypeClass TC, const TagDecl *D, QualType can); public: TagDecl *getDecl() const; - /// @brief Determines whether this type is in the process of being - /// defined. + /// Determines whether this type is in the process of being defined. bool isBeingDefined() const; static bool classof(const Type *T) { @@ -3513,7 +3538,7 @@ public: } }; -/// RecordType - This is a helper class that allows the use of isa/cast/dyncast +/// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of structs/unions/classes. class RecordType : public TagType { protected: @@ -3539,7 +3564,7 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Record; } }; -/// EnumType - This is a helper class that allows the use of isa/cast/dyncast +/// A helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of enums. class EnumType : public TagType { explicit EnumType(const EnumDecl *D) @@ -3557,12 +3582,12 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Enum; } }; -/// AttributedType - An attributed type is a type to which a type -/// attribute has been applied. The "modified type" is the -/// fully-sugared type to which the attributed type was applied; -/// generally it is not canonically equivalent to the attributed type. -/// The "equivalent type" is the minimally-desugared type which the -/// type is canonically equivalent to. +/// An attributed type is a type to which a type attribute has been applied. +/// +/// The "modified type" is the fully-sugared type to which the attributed +/// type was applied; generally it is not canonically equivalent to the +/// attributed type. The "equivalent type" is the minimally-desugared type +/// which the type is canonically equivalent to. /// /// For example, in the following attributed type: /// int32_t __attribute__((vector_size(16))) @@ -3612,6 +3637,7 @@ public: attr_nullable, attr_null_unspecified, attr_objc_kindof, + attr_objc_inert_unsafe_unretained, }; private: @@ -3641,6 +3667,23 @@ public: bool isSugared() const { return true; } QualType desugar() const { return getEquivalentType(); } + /// Does this attribute behave like a type qualifier? + /// + /// A type qualifier adjusts a type to provide specialized rules for + /// a specific object, like the standard const and volatile qualifiers. + /// This includes attributes controlling things like nullability, + /// address spaces, and ARC ownership. The value of the object is still + /// largely described by the modified type. + /// + /// In contrast, many type attributes "rewrite" their modified type to + /// produce a fundamentally different type, not necessarily related in any + /// formalizable way to the original type. For example, calling convention + /// and vector attributes are not simple type qualifiers. + /// + /// Type qualifiers are often, but not always, reflected in the canonical + /// type. + bool isQualifier() const; + bool isMSTypeSpec() const; bool isCallingConv() const; @@ -3653,7 +3696,7 @@ public: switch (kind) { case NullabilityKind::NonNull: return attr_nonnull; - + case NullabilityKind::Nullable: return attr_nullable; @@ -3865,29 +3908,33 @@ public: } }; -/// \brief Represents a C++11 auto or C++1y decltype(auto) type. +/// \brief Represents a C++11 auto or C++14 decltype(auto) type. /// /// These types are usually a placeholder for a deduced type. However, before /// the initializer is attached, or if the initializer is type-dependent, there /// is no deduced type and an auto type is canonical. In the latter case, it is /// also a dependent type. class AutoType : public Type, public llvm::FoldingSetNode { - AutoType(QualType DeducedType, bool IsDecltypeAuto, - bool IsDependent) + AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent) : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent, - /*VariablyModified=*/false, - /*ContainsParameterPack=*/DeducedType.isNull() + /*VariablyModified=*/false, + /*ContainsParameterPack=*/DeducedType.isNull() ? false : DeducedType->containsUnexpandedParameterPack()) { assert((DeducedType.isNull() || !IsDependent) && "auto deduced to dependent type"); - AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto; + AutoTypeBits.Keyword = (unsigned)Keyword; } friend class ASTContext; // ASTContext creates these public: - bool isDecltypeAuto() const { return AutoTypeBits.IsDecltypeAuto; } + bool isDecltypeAuto() const { + return getKeyword() == AutoTypeKeyword::DecltypeAuto; + } + AutoTypeKeyword getKeyword() const { + return (AutoTypeKeyword)AutoTypeBits.Keyword; + } bool isSugared() const { return !isCanonicalUnqualified(); } QualType desugar() const { return getCanonicalTypeInternal(); } @@ -3902,14 +3949,13 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDeducedType(), isDecltypeAuto(), - isDependentType()); + Profile(ID, getDeducedType(), getKeyword(), isDependentType()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced, - bool IsDecltypeAuto, bool IsDependent) { + AutoTypeKeyword Keyword, bool IsDependent) { ID.AddPointer(Deduced.getAsOpaquePtr()); - ID.AddBoolean(IsDecltypeAuto); + ID.AddInteger((unsigned)Keyword); ID.AddBoolean(IsDependent); } @@ -3926,9 +3972,9 @@ public: /// @c DependentTemplateSpecializationType. /// /// A non-dependent template specialization type is always "sugar", -/// typically for a @c RecordType. For example, a class template -/// specialization type of @c vector<int> will refer to a tag type for -/// the instantiation @c std::vector<int, std::allocator<int>> +/// typically for a \c RecordType. For example, a class template +/// specialization type of \c vector<int> will refer to a tag type for +/// the instantiation \c std::vector<int, std::allocator<int>> /// /// Template specializations are dependent if either the template or /// any of the template arguments are dependent, in which case the @@ -3938,9 +3984,10 @@ public: /// TemplateArguments, followed by a QualType representing the /// non-canonical aliased type when the template is a type alias /// template. -class TemplateSpecializationType - : public Type, public llvm::FoldingSetNode { - /// \brief The name of the template being specialized. This is +class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType + : public Type, + public llvm::FoldingSetNode { + /// The name of the template being specialized. This is /// either a TemplateName::Template (in which case it is a /// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a /// TypeAliasTemplateDecl*), a @@ -3949,14 +3996,13 @@ class TemplateSpecializationType /// replacement must, recursively, be one of these). TemplateName Template; - /// \brief - The number of template arguments named in this class - /// template specialization. + /// The number of template arguments named in this class template + /// specialization. unsigned NumArgs : 31; - /// \brief Whether this template specialization type is a substituted - /// type alias. + /// Whether this template specialization type is a substituted type alias. bool TypeAlias : 1; - + TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, QualType Canon, @@ -3965,8 +4011,7 @@ class TemplateSpecializationType friend class ASTContext; // ASTContext creates these public: - /// \brief Determine whether any of the given template arguments are - /// dependent. + /// Determine whether any of the given template arguments are dependent. static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs, bool &InstantiationDependent); @@ -4013,7 +4058,7 @@ public: /// }; /// \endcode bool isTypeAlias() const { return TypeAlias; } - + /// Get the aliased type, if this is a specialization of a type alias /// template. QualType getAliasedType() const { @@ -4026,19 +4071,19 @@ public: iterator begin() const { return getArgs(); } iterator end() const; // defined inline in TemplateBase.h - /// \brief Retrieve the name of the template that we are specializing. + /// Retrieve the name of the template that we are specializing. TemplateName getTemplateName() const { return Template; } - /// \brief Retrieve the template arguments. + /// Retrieve the template arguments. const TemplateArgument *getArgs() const { return reinterpret_cast<const TemplateArgument *>(this + 1); } - /// \brief Retrieve the number of template arguments. + /// Retrieve the number of template arguments. unsigned getNumArgs() const { return NumArgs; } - /// \brief Retrieve a specific template argument as a type. - /// \pre @c isArgType(Arg) + /// Retrieve a specific template argument as a type. + /// \pre \c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h bool isSugared() const { @@ -4062,7 +4107,7 @@ public: } }; -/// \brief The injected class name of a C++ class template or class +/// 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 /// equivalent for non-templated classes is just RecordType. @@ -4178,21 +4223,18 @@ public: return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword); } - /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST) - /// into an elaborated type keyword. + /// Converts a type specifier (DeclSpec::TST) into an elaborated type keyword. static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec); - /// getTagTypeKindForTypeSpec - Converts a type specifier (DeclSpec::TST) - /// into a tag type kind. It is an error to provide a type specifier - /// which *isn't* a tag kind here. + /// Converts a type specifier (DeclSpec::TST) into a tag type kind. + /// It is an error to provide a type specifier which *isn't* a tag kind here. static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec); - /// getKeywordForTagDeclKind - Converts a TagTypeKind into an - /// elaborated type keyword. + /// Converts a TagTypeKind into an elaborated type keyword. static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag); - /// getTagTypeKindForKeyword - Converts an elaborated type keyword into - // a TagTypeKind. It is an error to provide an elaborated type keyword + /// Converts an elaborated type keyword into a TagTypeKind. + /// It is an error to provide an elaborated type keyword /// which *isn't* a tag kind here. static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword); @@ -4218,10 +4260,10 @@ public: /// in the source code but containing no additional semantic information. class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { - /// \brief The nested name specifier containing the qualifier. + /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; - /// \brief The type that this qualified name refers to. + /// The type that this qualified name refers to. QualType NamedType; ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, @@ -4242,16 +4284,16 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { public: ~ElaboratedType(); - /// \brief Retrieve the qualification on this type. + /// Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } - /// \brief Retrieve the type named by the qualified-id. + /// Retrieve the type named by the qualified-id. QualType getNamedType() const { return NamedType; } - /// \brief Remove a single level of sugar. + /// Remove a single level of sugar. QualType desugar() const { return getNamedType(); } - /// \brief Returns whether this type directly provides sugar. + /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } void Profile(llvm::FoldingSetNodeID &ID) { @@ -4301,11 +4343,10 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: - /// \brief Retrieve the qualification on this type. + /// Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } - /// \brief Retrieve the type named by the typename specifier as an - /// identifier. + /// Retrieve the type named by the typename specifier as an identifier. /// /// This routine will return a non-NULL identifier pointer when the /// form of the original typename was terminated by an identifier, @@ -4333,20 +4374,21 @@ public: } }; -/// DependentTemplateSpecializationType - Represents a template -/// specialization type whose template cannot be resolved, e.g. +/// Represents a template specialization type whose template cannot be +/// resolved, e.g. /// A<T>::template B<T> -class DependentTemplateSpecializationType : - public TypeWithKeyword, public llvm::FoldingSetNode { +class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType + : public TypeWithKeyword, + public llvm::FoldingSetNode { - /// \brief The nested name specifier containing the qualifier. + /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; - /// \brief The identifier of the template. + /// The identifier of the template. const IdentifierInfo *Name; - /// \brief - The number of template arguments named in this class - /// template specialization. + /// \brief The number of template arguments named in this class template + /// specialization. unsigned NumArgs; const TemplateArgument *getArgBuffer() const { @@ -4405,7 +4447,7 @@ public: /// \brief Represents a pack expansion of types. /// -/// Pack expansions are part of C++0x variadic templates. A pack +/// Pack expansions are part of C++11 variadic templates. A pack /// expansion contains a pattern, which itself contains one or more /// "unexpanded" parameter packs. When instantiated, a pack expansion /// produces a series of types, each instantiated from the pattern of @@ -4483,7 +4525,7 @@ public: } }; -/// ObjCObjectType - Represents a class type in Objective C. +/// Represents a class type in Objective C. /// /// Every Objective C type is a combination of a base type, a set of /// type arguments (optional, for parameterized classes) and a list of @@ -4560,8 +4602,8 @@ protected: void computeSuperClassTypeSlow() const; public: - /// getBaseType - Gets the base type of this object type. This is - /// always (possibly sugar for) one of: + /// Gets the base type of this object type. This is always (possibly + /// sugar for) one of: /// - the 'id' builtin type (as opposed to the 'id' type visible to the /// user, which is a typedef for an ObjCObjectPointerType) /// - the 'Class' builtin type (same caveat) @@ -4595,8 +4637,8 @@ public: bool isSpecialized() const; /// Determine whether this object type was written with type arguments. - bool isSpecializedAsWritten() const { - return ObjCObjectTypeBits.NumTypeArgs > 0; + bool isSpecializedAsWritten() const { + return ObjCObjectTypeBits.NumTypeArgs > 0; } /// Determine whether this object type is "unspecialized", meaning @@ -4612,8 +4654,8 @@ public: /// Retrieve the type arguments of this object type as they were /// written. - ArrayRef<QualType> getTypeArgsAsWritten() const { - return ArrayRef<QualType>(getTypeArgStorage(), + ArrayRef<QualType> getTypeArgsAsWritten() const { + return llvm::makeArrayRef(getTypeArgStorage(), ObjCObjectTypeBits.NumTypeArgs); } @@ -4626,11 +4668,11 @@ public: bool qual_empty() const { return getNumProtocols() == 0; } - /// getNumProtocols - Return the number of qualifying protocols in this - /// interface type, or 0 if there are none. + /// Return the number of qualifying protocols in this interface type, + /// or 0 if there are none. unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; } - /// \brief Fetch a protocol by index. + /// Fetch a protocol by index. ObjCProtocolDecl *getProtocol(unsigned I) const { assert(I < getNumProtocols() && "Out-of-range protocol access"); return qual_begin()[I]; @@ -4674,7 +4716,7 @@ public: } }; -/// ObjCObjectTypeImpl - A class providing a concrete implementation +/// A class providing a concrete implementation /// of ObjCObjectType, so as to not increase the footprint of /// ObjCInterfaceType. Code outside of ASTContext and the core type /// system should not reference this type. @@ -4708,11 +4750,10 @@ inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() { getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs); } -/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for -/// object oriented design. They basically correspond to C++ classes. There -/// are two kinds of interface types, normal interfaces like "NSString" and -/// qualified interfaces, which are qualified with a protocol list like -/// "NSString<NSCopyable, NSAmazing>". +/// Interfaces are the core concept in Objective-C for object oriented design. +/// They basically correspond to C++ classes. There are two kinds of interface +/// types: normal interfaces like `NSString`, and qualified interfaces, which +/// are qualified with a protocol list like `NSString<NSCopyable, NSAmazing>`. /// /// ObjCInterfaceType guarantees the following properties when considered /// as a subtype of its superclass, ObjCObjectType: @@ -4732,7 +4773,7 @@ class ObjCInterfaceType : public ObjCObjectType { friend class ObjCInterfaceDecl; public: - /// getDecl - Get the declaration of this interface. + /// Get the declaration of this interface. ObjCInterfaceDecl *getDecl() const { return Decl; } bool isSugared() const { return false; } @@ -4767,12 +4808,12 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { return nullptr; } -/// ObjCObjectPointerType - Used to represent a pointer to an -/// Objective C object. These are constructed from pointer -/// declarators when the pointee type is an ObjCObjectType (or sugar -/// for one). In addition, the 'id' and 'Class' types are typedefs -/// for these, and the protocol-qualified types 'id<P>' and 'Class<P>' -/// are translated into these. +/// Represents a pointer to an Objective C object. +/// +/// These are constructed from pointer declarators when the pointee type is +/// an ObjCObjectType (or sugar for one). In addition, the 'id' and 'Class' +/// types are typedefs for these, and the protocol-qualified types 'id<P>' +/// and 'Class<P>' are translated into these. /// /// Pointers to pointers to Objective C objects are still PointerTypes; /// only the first level of pointer gets it own type implementation. @@ -4789,12 +4830,11 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these. public: - /// getPointeeType - Gets the type pointed to by this ObjC pointer. + /// Gets the type pointed to by this ObjC pointer. /// The result will always be an ObjCObjectType or sugar thereof. QualType getPointeeType() const { return PointeeType; } - /// getObjCObjectType - Gets the type pointed to by this ObjC - /// pointer. This method always returns non-null. + /// Gets the type pointed to by this ObjC pointer. Always returns non-null. /// /// This method is equivalent to getPointeeType() except that /// it discards any typedefs (or other sugar) between this @@ -4821,14 +4861,14 @@ public: return PointeeType->castAs<ObjCObjectType>(); } - /// getInterfaceType - If this pointer points to an Objective C + /// If this pointer points to an Objective C /// \@interface type, gets the type for that interface. Any protocol /// qualifiers on the interface are ignored. /// /// \return null if the base type for this pointer is 'id' or 'Class' const ObjCInterfaceType *getInterfaceType() const; - /// getInterfaceDecl - If this pointer points to an Objective \@interface + /// If this pointer points to an Objective \@interface /// type, gets the declaration for that interface. /// /// \return null if the base type for this pointer is 'id' or 'Class' @@ -4836,32 +4876,31 @@ public: return getObjectType()->getInterface(); } - /// isObjCIdType - True if this is equivalent to the 'id' type, i.e. if + /// True if this is equivalent to the 'id' type, i.e. if /// its object type is the primitive 'id' type with no protocols. bool isObjCIdType() const { return getObjectType()->isObjCUnqualifiedId(); } - /// isObjCClassType - True if this is equivalent to the 'Class' type, + /// True if this is equivalent to the 'Class' type, /// i.e. if its object tive is the primitive 'Class' type with no protocols. bool isObjCClassType() const { return getObjectType()->isObjCUnqualifiedClass(); } - /// isObjCIdOrClassType - True if this is equivalent to the 'id' or - /// 'Class' type, + /// True if this is equivalent to the 'id' or 'Class' type, bool isObjCIdOrClassType() const { return getObjectType()->isObjCUnqualifiedIdOrClass(); } - /// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some - /// non-empty set of protocols. + /// True if this is equivalent to 'id<P>' for some non-empty set of + /// protocols. bool isObjCQualifiedIdType() const { return getObjectType()->isObjCQualifiedId(); } - /// isObjCQualifiedClassType - True if this is equivalent to 'Class<P>' for - /// some non-empty set of protocols. + /// True if this is equivalent to 'Class<P>' for some non-empty set of + /// protocols. bool isObjCQualifiedClassType() const { return getObjectType()->isObjCQualifiedClass(); } @@ -4873,10 +4912,10 @@ public: bool isSpecialized() const { return getObjectType()->isSpecialized(); } /// Whether this type is specialized, meaning that it has type arguments. - bool isSpecializedAsWritten() const { - return getObjectType()->isSpecializedAsWritten(); + bool isSpecializedAsWritten() const { + return getObjectType()->isSpecializedAsWritten(); } - + /// Whether this type is unspecialized, meaning that is has no type arguments. bool isUnspecialized() const { return getObjectType()->isUnspecialized(); } @@ -4885,13 +4924,13 @@ public: bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); } /// Retrieve the type arguments for this type. - ArrayRef<QualType> getTypeArgs() const { - return getObjectType()->getTypeArgs(); + ArrayRef<QualType> getTypeArgs() const { + return getObjectType()->getTypeArgs(); } /// Retrieve the type arguments for this type. - ArrayRef<QualType> getTypeArgsAsWritten() const { - return getObjectType()->getTypeArgsAsWritten(); + ArrayRef<QualType> getTypeArgsAsWritten() const { + return getObjectType()->getTypeArgsAsWritten(); } /// An iterator over the qualifiers on the object type. Provided @@ -4909,14 +4948,12 @@ public: } bool qual_empty() const { return getObjectType()->qual_empty(); } - /// getNumProtocols - Return the number of qualifying protocols on - /// the object type. + /// Return the number of qualifying protocols on the object type. unsigned getNumProtocols() const { return getObjectType()->getNumProtocols(); } - /// \brief Retrieve a qualifying protocol by index on the object - /// type. + /// Retrieve a qualifying protocol by index on the object type. ObjCProtocolDecl *getProtocol(unsigned I) const { return getObjectType()->getProtocol(I); } @@ -4960,7 +4997,7 @@ class AtomicType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these. public: - /// getValueType - Gets the type contained by this atomic type, i.e. + /// 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; } @@ -5127,12 +5164,12 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { removeLocalFastQualifiers(Mask); } -/// getAddressSpace - Return the address space of this type. +/// Return the address space of this type. inline unsigned QualType::getAddressSpace() const { return getQualifiers().getAddressSpace(); } - -/// getObjCGCAttr - Return the gc attribute of this type. + +/// Return the gc attribute of this type. inline Qualifiers::GC QualType::getObjCGCAttr() const { return getQualifiers().getObjCGCAttr(); } @@ -5151,7 +5188,7 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { return getFunctionExtInfo(*t); } -/// isMoreQualifiedThan - Determine whether this type is more +/// Determine whether this type is more /// qualified than the Other type. For example, "const volatile int" /// is more qualified than "const int", "volatile int", and /// "int". However, it is not more qualified than "const volatile @@ -5162,7 +5199,7 @@ inline bool QualType::isMoreQualifiedThan(QualType other) const { return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals)); } -/// isAtLeastAsQualifiedAs - Determine whether this type is at last +/// Determine whether this type is at last /// as qualified as the Other type. For example, "const volatile /// int" is at least as qualified as "const int", "volatile int", /// "int", and "const volatile int". @@ -5170,7 +5207,7 @@ inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { return getQualifiers().compatiblyIncludes(other.getQualifiers()); } -/// getNonReferenceType - If Type is a reference type (e.g., const +/// If Type is a reference type (e.g., const /// int&), returns the type that the reference refers to ("const /// int"). Otherwise, returns the type itself. This routine is used /// throughout Sema to implement C++ 5p6: @@ -5191,7 +5228,7 @@ inline bool QualType::isCForbiddenLValueType() const { getTypePtr()->isFunctionType()); } -/// \brief Tests whether the type is categorized as a fundamental type. +/// Tests whether the type is categorized as a fundamental type. /// /// \returns True for types specified in C++0x [basic.fundamental]. inline bool Type::isFundamentalType() const { @@ -5201,7 +5238,7 @@ inline bool Type::isFundamentalType() const { (isArithmeticType() && !isEnumeralType()); } -/// \brief Tests whether the type is categorized as a compound type. +/// Tests whether the type is categorized as a compound type. /// /// \returns True for types specified in C++0x [basic.compound]. inline bool Type::isCompoundType() const { @@ -5364,6 +5401,30 @@ inline bool Type::isImage2dArrayT() const { return isSpecificBuiltinType(BuiltinType::OCLImage2dArray); } +inline bool Type::isImage2dDepthT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2dDepth); +} + +inline bool Type::isImage2dArrayDepthT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayDepth); +} + +inline bool Type::isImage2dMSAAT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAA); +} + +inline bool Type::isImage2dArrayMSAAT() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAA); +} + +inline bool Type::isImage2dMSAATDepth() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAADepth); +} + +inline bool Type::isImage2dArrayMSAATDepth() const { + return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAADepth); +} + inline bool Type::isImage3dT() const { return isSpecificBuiltinType(BuiltinType::OCLImage3d); } @@ -5376,14 +5437,33 @@ inline bool Type::isEventT() const { return isSpecificBuiltinType(BuiltinType::OCLEvent); } +inline bool Type::isClkEventT() const { + return isSpecificBuiltinType(BuiltinType::OCLClkEvent); +} + +inline bool Type::isQueueT() const { + return isSpecificBuiltinType(BuiltinType::OCLQueue); +} + +inline bool Type::isNDRangeT() const { + return isSpecificBuiltinType(BuiltinType::OCLNDRange); +} + +inline bool Type::isReserveIDT() const { + return isSpecificBuiltinType(BuiltinType::OCLReserveID); +} + inline bool Type::isImageType() const { - return isImage3dT() || - isImage2dT() || isImage2dArrayT() || - isImage1dT() || isImage1dArrayT() || isImage1dBufferT(); + return isImage3dT() || isImage2dT() || isImage2dArrayT() || + isImage2dDepthT() || isImage2dArrayDepthT() || isImage2dMSAAT() || + isImage2dArrayMSAAT() || isImage2dMSAATDepth() || + isImage2dArrayMSAATDepth() || isImage1dT() || isImage1dArrayT() || + isImage1dBufferT(); } inline bool Type::isOpenCLSpecificType() const { - return isSamplerT() || isEventT() || isImageType(); + return isSamplerT() || isEventT() || isImageType() || isClkEventT() || + isQueueT() || isNDRangeT() || isReserveIDT(); } inline bool Type::isTemplateTypeParmType() const { diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index f4d20b8..26feda5 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -151,6 +151,14 @@ public: TypeLoc IgnoreParens() const; + /// \brief Find a type with the location of an explicit type qualifier. + /// + /// The result, if non-null, will be one of: + /// QualifiedTypeLoc + /// AtomicTypeLoc + /// AttributedTypeLoc, for those type attributes that behave as qualifiers + TypeLoc findExplicitQualifierLoc() const; + /// \brief Initializes this to state that every location in this /// type is the given location. /// @@ -162,19 +170,18 @@ public: /// \brief Initializes this by copying its information from another /// TypeLoc of the same type. - void initializeFullCopy(TypeLoc Other) const { + void initializeFullCopy(TypeLoc Other) { assert(getType() == Other.getType()); - size_t Size = getFullDataSize(); - memcpy(getOpaqueData(), Other.getOpaqueData(), Size); + copy(Other); } /// \brief Initializes this by copying its information from another /// TypeLoc of the same type. The given size must be the full data /// size. - void initializeFullCopy(TypeLoc Other, unsigned Size) const { + void initializeFullCopy(TypeLoc Other, unsigned Size) { assert(getType() == Other.getType()); assert(getFullDataSize() == Size); - memcpy(getOpaqueData(), Other.getOpaqueData(), Size); + copy(Other); } /// Copies the other type loc into this one. @@ -206,6 +213,7 @@ private: /// \brief Return the TypeLoc for a type source info. inline TypeLoc TypeSourceInfo::getTypeLoc() const { + // TODO: is this alignment already sufficient? return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1))); } @@ -736,6 +744,10 @@ public: return hasAttrExprOperand() || hasAttrEnumOperand(); } + bool isQualifier() const { + return getTypePtr()->isQualifier(); + } + /// The modified type, which is generally canonically different from /// the attribute type. /// int main(int, char**) __attribute__((noreturn)) diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h index ebfbb8a..481fd11 100644 --- a/include/clang/AST/VTableBuilder.h +++ b/include/clang/AST/VTableBuilder.h @@ -51,7 +51,7 @@ public: CK_UnusedFunctionPointer }; - VTableComponent() { } + VTableComponent() = default; static VTableComponent MakeVCallOffset(CharUnits Offset) { return VTableComponent(CK_VCallOffset, Offset); @@ -122,31 +122,56 @@ public: } const CXXRecordDecl *getRTTIDecl() const { - assert(getKind() == CK_RTTI && "Invalid component kind!"); - + assert(isRTTIKind() && "Invalid component kind!"); return reinterpret_cast<CXXRecordDecl *>(getPointer()); } const CXXMethodDecl *getFunctionDecl() const { - assert(getKind() == CK_FunctionPointer); - + assert(isFunctionPointerKind() && "Invalid component kind!"); + if (isDestructorKind()) + return getDestructorDecl(); return reinterpret_cast<CXXMethodDecl *>(getPointer()); } const CXXDestructorDecl *getDestructorDecl() const { - assert((getKind() == CK_CompleteDtorPointer || - getKind() == CK_DeletingDtorPointer) && "Invalid component kind!"); - + assert(isDestructorKind() && "Invalid component kind!"); return reinterpret_cast<CXXDestructorDecl *>(getPointer()); } const CXXMethodDecl *getUnusedFunctionDecl() const { - assert(getKind() == CK_UnusedFunctionPointer); - + assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!"); return reinterpret_cast<CXXMethodDecl *>(getPointer()); } + bool isDestructorKind() const { return isDestructorKind(getKind()); } + + bool isUsedFunctionPointerKind() const { + return isUsedFunctionPointerKind(getKind()); + } + + bool isFunctionPointerKind() const { + return isFunctionPointerKind(getKind()); + } + + bool isRTTIKind() const { return isRTTIKind(getKind()); } + private: + static bool isFunctionPointerKind(Kind ComponentKind) { + return isUsedFunctionPointerKind(ComponentKind) || + ComponentKind == CK_UnusedFunctionPointer; + } + static bool isUsedFunctionPointerKind(Kind ComponentKind) { + return ComponentKind == CK_FunctionPointer || + isDestructorKind(ComponentKind); + } + static bool isDestructorKind(Kind ComponentKind) { + return ComponentKind == CK_CompleteDtorPointer || + ComponentKind == CK_DeletingDtorPointer; + } + static bool isRTTIKind(Kind ComponentKind) { + return ComponentKind == CK_RTTI; + } + VTableComponent(Kind ComponentKind, CharUnits Offset) { assert((ComponentKind == CK_VCallOffset || ComponentKind == CK_VBaseOffset || @@ -158,12 +183,8 @@ private: } VTableComponent(Kind ComponentKind, uintptr_t Ptr) { - assert((ComponentKind == CK_RTTI || - ComponentKind == CK_FunctionPointer || - ComponentKind == CK_CompleteDtorPointer || - ComponentKind == CK_DeletingDtorPointer || - ComponentKind == CK_UnusedFunctionPointer) && - "Invalid component kind!"); + assert((isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) && + "Invalid component kind!"); assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!"); @@ -178,11 +199,7 @@ private: } uintptr_t getPointer() const { - assert((getKind() == CK_RTTI || - getKind() == CK_FunctionPointer || - getKind() == CK_CompleteDtorPointer || - getKind() == CK_DeletingDtorPointer || - getKind() == CK_UnusedFunctionPointer) && + assert((getKind() == CK_RTTI || isFunctionPointerKind()) && "Invalid component kind!"); return static_cast<uintptr_t>(Value & ~7ULL); @@ -205,8 +222,11 @@ public: typedef const VTableComponent *vtable_component_iterator; typedef const VTableThunkTy *vtable_thunk_iterator; + typedef llvm::iterator_range<vtable_component_iterator> + vtable_component_range; typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; + private: uint64_t NumVTableComponents; std::unique_ptr<VTableComponent[]> VTableComponents; @@ -233,6 +253,11 @@ public: return NumVTableComponents; } + vtable_component_range vtable_components() const { + return vtable_component_range(vtable_component_begin(), + vtable_component_end()); + } + vtable_component_iterator vtable_component_begin() const { return VTableComponents.get(); } @@ -376,10 +401,6 @@ struct VPtrInfo { VPtrInfo(const CXXRecordDecl *RD) : ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {} - // Copy constructor. - // FIXME: Uncomment when we've moved to C++11. - // VPtrInfo(const VPtrInfo &) = default; - /// The vtable will hold all of the virtual bases or virtual methods of /// ReusingBase. This may or may not be the same class as VPtrSubobject.Base. /// A derived class will reuse the vptr of the first non-virtual base |