diff options
author | dim <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
commit | c86b984ea8ecb3e944dc3de48539f4c1f65851ea (patch) | |
tree | 3eb853da77d46cc77c4b017525a422f9ddb1385b /include/clang/AST | |
parent | c696171ff15f0ee60dea4abfd99a135473c95656 (diff) | |
download | FreeBSD-src-c86b984ea8ecb3e944dc3de48539f4c1f65851ea.zip FreeBSD-src-c86b984ea8ecb3e944dc3de48539f4c1f65851ea.tar.gz |
Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1):
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_360/rc1@226102
Diffstat (limited to 'include/clang/AST')
52 files changed, 2120 insertions, 447 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 8134f6b..195d748 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -30,6 +30,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SanitizerBlacklist.h" #include "clang/Basic/VersionTuple.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -74,6 +75,15 @@ namespace clang { class FullComment; } + struct TypeInfo { + uint64_t Width; + unsigned Align; + bool AlignIsRequired : 1; + TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {} + TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired) + : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {} + }; + /// \brief Holds long-lived AST nodes (such as types and decls) that can be /// referred to throughout the semantic analysis of a file. class ASTContext : public RefCountedBase<ASTContext> { @@ -144,8 +154,7 @@ class ASTContext : public RefCountedBase<ASTContext> { ObjCLayouts; /// \brief A cache from types to size and alignment information. - typedef llvm::DenseMap<const Type*, - std::pair<uint64_t, unsigned> > TypeInfoMap; + typedef llvm::DenseMap<const Type *, struct TypeInfo> TypeInfoMap; mutable TypeInfoMap MemoizedTypeInfo; /// \brief A cache mapping from CXXRecordDecls to key functions. @@ -264,8 +273,6 @@ class ASTContext : public RefCountedBase<ASTContext> { /// \brief Declaration for the CUDA cudaConfigureCall function. FunctionDecl *cudaConfigureCallDecl; - TypeSourceInfo NullTypeSourceInfo; - /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of @@ -384,6 +391,10 @@ private: /// this ASTContext object. LangOptions &LangOpts; + /// \brief Blacklist object that is used by sanitizers to decide which + /// entities should not be instrumented. + std::unique_ptr<SanitizerBlacklist> SanitizerBL; + /// \brief The allocator used to create AST objects. /// /// AST objects are never destructed; rather, all memory associated with the @@ -453,11 +464,12 @@ public: /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, /// NestedNameSpecifier or NestedNameSpecifierLoc. template <typename NodeT> - ParentVector getParents(const NodeT &Node) { + ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) { return getParents(ast_type_traits::DynTypedNode::create(Node)); } - ParentVector getParents(const ast_type_traits::DynTypedNode &Node); + ArrayRef<ast_type_traits::DynTypedNode> + getParents(const ast_type_traits::DynTypedNode &Node); const clang::PrintingPolicy &getPrintingPolicy() const { return PrintingPolicy; @@ -508,6 +520,10 @@ public: const LangOptions& getLangOpts() const { return LangOpts; } + const SanitizerBlacklist &getSanitizerBlacklist() const { + return *SanitizerBL; + } + DiagnosticsEngine &getDiagnostics() const; FullSourceLoc getFullLoc(SourceLocation Loc) const { @@ -912,6 +928,12 @@ public: /// \brief Change the result type of a function type once it is deduced. void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); + /// \brief Change the exception specification on a function once it is + /// delay-parsed, instantiated, or computed. + void adjustExceptionSpec(FunctionDecl *FD, + const FunctionProtoType::ExceptionSpecInfo &ESI, + bool AsWritten = false); + /// \brief Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T) const; @@ -1371,7 +1393,8 @@ public: /// /// If \p Field is specified then record field names are also encoded. void getObjCEncodingForType(QualType T, std::string &S, - const FieldDecl *Field=nullptr) const; + const FieldDecl *Field=nullptr, + QualType *NotEncodedT=nullptr) const; /// \brief Emit the Objective-C property type encoding for the given /// type \p T into \p S. @@ -1581,7 +1604,7 @@ public: private: CanQualType getFromTargetType(unsigned Type) const; - std::pair<uint64_t, unsigned> getTypeInfoImpl(const Type *T) const; + TypeInfo getTypeInfoImpl(const Type *T) const; //===--------------------------------------------------------------------===// // Type Predicates. @@ -1614,18 +1637,12 @@ public: const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const; /// \brief Get the size and alignment of the specified complete type in bits. - std::pair<uint64_t, unsigned> getTypeInfo(const Type *T) const; - std::pair<uint64_t, unsigned> getTypeInfo(QualType T) const { - return getTypeInfo(T.getTypePtr()); - } + TypeInfo getTypeInfo(const Type *T) const; + TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); } /// \brief Return the size of the specified (complete) type \p T, in bits. - uint64_t getTypeSize(QualType T) const { - return getTypeInfo(T).first; - } - uint64_t getTypeSize(const Type *T) const { - return getTypeInfo(T).first; - } + uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; } + uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; } /// \brief Return the size of the character type, in bits. uint64_t getCharWidth() const { @@ -1645,12 +1662,8 @@ public: /// \brief Return the ABI-specified alignment of a (complete) type \p T, in /// bits. - unsigned getTypeAlign(QualType T) const { - return getTypeInfo(T).second; - } - unsigned getTypeAlign(const Type *T) const { - return getTypeInfo(T).second; - } + unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; } + unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; } /// \brief Return the ABI-specified alignment of a (complete) type \p T, in /// characters. @@ -1664,6 +1677,11 @@ public: std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const; std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const; + /// \brief Determine if the alignment the type has was required using an + /// alignment attribute. + bool isAlignmentRequired(const Type *T) const; + bool isAlignmentRequired(QualType T) const; + /// \brief Return the "preferred" alignment of the specified type \p T for /// the current target, in bits. /// @@ -2153,8 +2171,6 @@ public: getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()) const; - TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; } - /// \brief Add a deallocation callback that will be invoked when the /// ASTContext is destroyed. /// @@ -2272,12 +2288,14 @@ private: bool StructField = false, bool EncodeBlockParameters = false, bool EncodeClassNames = false, - bool EncodePointerToObjCTypedef = false) const; + bool EncodePointerToObjCTypedef = false, + QualType *NotEncodedT=nullptr) const; // Adds the encoding of the structure's members. void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, const FieldDecl *Field, - bool includeVBases = true) const; + bool includeVBases = true, + QualType *NotEncodedT=nullptr) const; public: // Adds the encoding of a method parameter or return type. void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, @@ -2312,6 +2330,31 @@ private: std::unique_ptr<ParentMap> AllParents; std::unique_ptr<VTableContextBase> VTContext; + +public: + enum PragmaSectionFlag : unsigned { + PSF_None = 0, + PSF_Read = 0x1, + PSF_Write = 0x2, + PSF_Execute = 0x4, + PSF_Implicit = 0x8, + PSF_Invalid = 0x80000000U, + }; + + struct SectionInfo { + DeclaratorDecl *Decl; + SourceLocation PragmaSectionLocation; + int SectionFlags; + SectionInfo() {} + SectionInfo(DeclaratorDecl *Decl, + SourceLocation PragmaSectionLocation, + int SectionFlags) + : Decl(Decl), + PragmaSectionLocation(PragmaSectionLocation), + SectionFlags(SectionFlags) {} + }; + + llvm::StringMap<SectionInfo> SectionInfos; }; /// \brief Utility function for constructing a nullary selector. @@ -2349,9 +2392,9 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { /// // Specific alignment /// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); /// @endcode -/// Please note that you cannot use delete on the pointer; it must be -/// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// Memory allocated through this placement new operator does not need to be +/// explicitly freed, as ASTContext will free all of this memory when it gets +/// destroyed. Please note that you cannot use delete on the pointer. /// /// @param Bytes The number of bytes to allocate. Calculated by the compiler. /// @param C The ASTContext that provides the allocator. @@ -2386,9 +2429,9 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) { /// // Specific alignment /// char *data = new (Context, 4) char[10]; /// @endcode -/// Please note that you cannot use delete on the pointer; it must be -/// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// Memory allocated through this placement new[] operator does not need to be +/// explicitly freed, as ASTContext will free all of this memory when it gets +/// destroyed. Please note that you cannot use delete on the pointer. /// /// @param Bytes The number of bytes to allocate. Calculated by the compiler. /// @param C The ASTContext that provides the allocator. diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 484ca4c..27c85e6 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTICAST_H -#define LLVM_CLANG_DIAGNOSTICAST_H +#ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H +#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h index 4f32798..003d489 100644 --- a/include/clang/AST/ASTFwd.h +++ b/include/clang/AST/ASTFwd.h @@ -12,6 +12,9 @@ /// //===-------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_ASTFWD_H +#define LLVM_CLANG_AST_ASTFWD_H + namespace clang { class Decl; @@ -26,3 +29,5 @@ class Type; class CXXCtorInitializer; } // end namespace clang + +#endif diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h index 9af016b..69df2d8 100644 --- a/include/clang/AST/ASTLambda.h +++ b/include/clang/AST/ASTLambda.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_LAMBDA_H -#define LLVM_CLANG_AST_LAMBDA_H +#ifndef LLVM_CLANG_AST_ASTLAMBDA_H +#define LLVM_CLANG_AST_ASTLAMBDA_H #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" @@ -77,4 +77,4 @@ inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { } // clang -#endif // LLVM_CLANG_AST_LAMBDA_H +#endif diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index a89bfed..48eb629 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -102,6 +102,12 @@ public: /// \param D the declaration marked used virtual void DeclarationMarkedUsed(const Decl *D) {} + /// \brief A declaration is marked as OpenMP threadprivate which was not + /// previously marked as threadprivate. + /// + /// \param D the declaration marked OpenMP threadprivate. + virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {} + // NOTE: If new methods are added they should also be added to // MultiplexASTMutationListener. }; diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 0e06e26..dc3c34f 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H -#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H +#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H +#define LLVM_CLANG_AST_ASTTYPETRAITS_H #include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" @@ -23,6 +23,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/AlignOf.h" namespace llvm { @@ -53,9 +54,19 @@ public: return ASTNodeKind(KindToKindId<T>::Id); } + /// \{ + /// \brief Construct an identifier for the dynamic type of the node + static ASTNodeKind getFromNode(const Decl &D); + static ASTNodeKind getFromNode(const Stmt &S); + static ASTNodeKind getFromNode(const Type &T); + /// \} + /// \brief Returns \c true if \c this and \c Other represent the same kind. bool isSame(ASTNodeKind Other) const; + /// \brief Returns \c true only for the default \c ASTNodeKind() + bool isNone() const { return KindId == NKI_None; } + /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. /// \param Distance If non-null, used to return the distance between \c this /// and \c Other in the class hierarchy. @@ -69,6 +80,32 @@ public: return KindId < Other.KindId; } + /// \brief Return the most derived type between \p Kind1 and \p Kind2. + /// + /// Return ASTNodeKind() if they are not related. + static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2); + + /// \brief Return the most derived common ancestor between Kind1 and Kind2. + /// + /// Return ASTNodeKind() if they are not related. + static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, + ASTNodeKind Kind2); + + /// \brief Hooks for using ASTNodeKind as a key in a DenseMap. + struct DenseMapInfo { + // ASTNodeKind() is a good empty key because it is represented as a 0. + static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); } + // NKI_NumberOfKinds is not a valid value, so it is good for a + // tombstone key. + static inline ASTNodeKind getTombstoneKey() { + return ASTNodeKind(NKI_NumberOfKinds); + } + static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; } + static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) { + return LHS.KindId == RHS.KindId; + } + }; + private: /// \brief Kind ids. /// @@ -108,6 +145,8 @@ private: template <class T> struct KindToKindId { static const NodeKindId Id = NKI_None; }; + template <class T> + struct KindToKindId<const T> : KindToKindId<T> {}; /// \brief Per kind info. struct KindInfo { @@ -184,12 +223,22 @@ public: return BaseConverter<T>::get(NodeKind, Storage.buffer); } + /// \brief Retrieve the stored node as type \c T. + /// + /// Similar to \c get(), but asserts that the type is what we are expecting. + template <typename T> + const T &getUnchecked() const { + return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer); + } + + ASTNodeKind getNodeKind() const { return NodeKind; } + /// \brief Returns a pointer that identifies the stored AST node. /// /// Note that this is not supported by all AST nodes. For AST nodes /// that don't have a pointer-defined identity inside the AST, this /// method returns NULL. - const void *getMemoizationData() const; + const void *getMemoizationData() const { return MemoizationData; } /// \brief Prints the node to the given output stream. void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; @@ -212,14 +261,15 @@ public: return getMemoizationData() < Other.getMemoizationData(); } bool operator==(const DynTypedNode &Other) const { - if (!NodeKind.isBaseOf(Other.NodeKind) && - !Other.NodeKind.isBaseOf(NodeKind)) + // DynTypedNode::create() stores the exact kind of the node in NodeKind. + // If they contain the same node, their NodeKind must be the same. + if (!NodeKind.isSame(Other.NodeKind)) return false; // FIXME: Implement for other types. - if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) { - return *get<QualType>() == *Other.get<QualType>(); - } + if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) + return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() == Other.getMemoizationData(); } @@ -235,13 +285,18 @@ private: /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. template <typename T, typename BaseT> struct DynCastPtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind)) - return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) + return cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); + return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; - Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); + Result.NodeKind = ASTNodeKind::getFromNode(Node); + Result.MemoizationData = &Node; new (Result.Storage.buffer) const BaseT * (&Node); return Result; } @@ -254,9 +309,14 @@ private: return *reinterpret_cast<T *const *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return **reinterpret_cast<T *const *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); + Result.MemoizationData = &Node; new (Result.Storage.buffer) const T * (&Node); return Result; } @@ -269,15 +329,21 @@ private: return reinterpret_cast<const T *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return *reinterpret_cast<const T *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); + Result.MemoizationData = nullptr; new (Result.Storage.buffer) T(Node); return Result; } }; ASTNodeKind NodeKind; + const void *MemoizationData; /// \brief Stores the data of the node. /// @@ -345,20 +411,15 @@ template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { } }; -inline const void *DynTypedNode::getMemoizationData() const { - if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(NodeKind)) { - return BaseConverter<Decl>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<Stmt>().isBaseOf(NodeKind)) { - return BaseConverter<Stmt>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<Type>().isBaseOf(NodeKind)) { - return BaseConverter<Type>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) { - return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer); - } - return nullptr; -} - } // end namespace ast_type_traits } // end namespace clang -#endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H +namespace llvm { + +template <> +struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> + : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; + +} // end namespace llvm + +#endif diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index d92167e..6ec0545 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -15,8 +15,8 @@ // FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h. // We can refactor this core logic into something common. -#ifndef LLVM_CLANG_AST_VECTOR -#define LLVM_CLANG_AST_VECTOR +#ifndef LLVM_CLANG_AST_ASTVECTOR_H +#define LLVM_CLANG_AST_ASTVECTOR_H #include "clang/AST/AttrIterator.h" #include "llvm/ADT/PointerIntPair.h" @@ -236,14 +236,14 @@ public: iterator insert(const ASTContext &C, iterator I, size_type NumToInsert, const T &Elt) { - if (I == this->end()) { // Important special case for empty vector. - append(C, NumToInsert, Elt); - return this->end()-1; - } - // Convert iterator to elt# to avoid invalidating iterator when we reserve() size_t InsertElt = I - this->begin(); + if (I == this->end()) { // Important special case for empty vector. + append(C, NumToInsert, Elt); + return this->begin() + InsertElt; + } + // Ensure there is enough space. reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); @@ -284,14 +284,15 @@ public: template<typename ItTy> iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) { - if (I == this->end()) { // Important special case for empty vector. + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + if (I == this->end()) { // Important special case for empty vector. append(C, From, To); - return this->end()-1; + return this->begin() + InsertElt; } size_t NumToInsert = std::distance(From, To); - // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I - this->begin(); // Ensure there is enough space. reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index fc48816..787843e 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -16,6 +16,7 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/LLVM.h" diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 7cccef6..aa3c846 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H -#define LLVM_CLANG_AST_CANONICAL_TYPE_H +#ifndef LLVM_CLANG_AST_CANONICALTYPE_H +#define LLVM_CLANG_AST_CANONICALTYPE_H #include "clang/AST/Type.h" #include "llvm/Support/Casting.h" @@ -736,4 +736,4 @@ CanTypeIterator<InputIterator>::operator->() const { } -#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H +#endif diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index e18fe9a..94470cb 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -96,9 +96,10 @@ protected: unsigned : NumInlineContentCommentBits; unsigned RenderKind : 2; - unsigned CommandID : 8; + unsigned CommandID : CommandInfo::NumCommandIDBits; }; - enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 }; + enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + + CommandInfo::NumCommandIDBits }; class HTMLTagCommentBitfields { friend class HTMLTagComment; @@ -139,13 +140,14 @@ protected: unsigned : NumCommentBits; - unsigned CommandID : 8; + unsigned CommandID : CommandInfo::NumCommandIDBits; /// Describes the syntax that was used in a documentation command. /// Contains values from CommandMarkerKind enum. unsigned CommandMarker : 1; }; - enum { NumBlockCommandCommentBits = NumCommentBits + 9 }; + enum { NumBlockCommandCommentBits = NumCommentBits + + CommandInfo::NumCommandIDBits + 1 }; class ParamCommandCommentBitfields { friend class ParamCommandComment; diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h index 5d50886..be5b8ee 100644 --- a/include/clang/AST/CommentBriefParser.h +++ b/include/clang/AST/CommentBriefParser.h @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H -#define LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H +#ifndef LLVM_CLANG_AST_COMMENTBRIEFPARSER_H +#define LLVM_CLANG_AST_COMMENTBRIEFPARSER_H #include "clang/AST/CommentLexer.h" diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index dde7a14..ec6d83c 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H -#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H +#ifndef LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H +#define LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H #include "clang/Basic/CommentOptions.h" #include "clang/Basic/LLVM.h" @@ -40,7 +40,11 @@ struct CommandInfo { /// Name of the command that ends the verbatim block. const char *EndCommandName; - unsigned ID : 8; + /// DRY definition of the number of bits used for a command ID. + enum { NumCommandIDBits = 20 }; + + /// The ID of the command. + unsigned ID : NumCommandIDBits; /// Number of word-like arguments for a given block command, except for /// \\param and \\tparam commands -- these have special argument parsers. diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h index 312da06..f3a209b 100644 --- a/include/clang/AST/CommentDiagnostic.h +++ b/include/clang/AST/CommentDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H -#define LLVM_CLANG_COMMENTDIAGNOSTIC_H +#ifndef LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H +#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index a6e3ed8..d995df9 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H -#define LLVM_CLANG_AST_COMMENT_LEXER_H +#ifndef LLVM_CLANG_AST_COMMENTLEXER_H +#define LLVM_CLANG_AST_COMMENTLEXER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h index 7e00813..2c444f0 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_PARSER_H -#define LLVM_CLANG_AST_COMMENT_PARSER_H +#ifndef LLVM_CLANG_AST_COMMENTPARSER_H +#define LLVM_CLANG_AST_COMMENTPARSER_H #include "clang/AST/Comment.h" #include "clang/AST/CommentLexer.h" diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 027c3b9..4ae6fe0 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_SEMA_H -#define LLVM_CLANG_AST_COMMENT_SEMA_H +#ifndef LLVM_CLANG_AST_COMMENTSEMA_H +#define LLVM_CLANG_AST_COMMENTSEMA_H #include "clang/AST/Comment.h" #include "clang/Basic/Diagnostic.h" @@ -85,7 +85,7 @@ public: std::uninitialized_copy(Source.begin(), Source.end(), Mem); return llvm::makeArrayRef(Mem, Size); } - return ArrayRef<T>(); + return None; } ParagraphComment *actOnParagraphComment( diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 9ef0087..c0526e1 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -424,6 +424,7 @@ private: bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); + bool TraverseOMPLoopDirective(OMPLoopDirective *S); bool TraverseOMPClause(OMPClause *C); #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); #include "clang/Basic/OpenMPKinds.def" @@ -623,6 +624,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -647,6 +649,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -875,6 +878,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) @@ -1083,6 +1089,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) @@ -2122,21 +2131,29 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { TRY_TO(TraverseLambdaCapture(S, C)); } - if (S->hasExplicitParameters() || S->hasExplicitResultType()) { - TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - if (S->hasExplicitParameters() && S->hasExplicitResultType()) { - // Visit the whole type. - TRY_TO(TraverseTypeLoc(TL)); - } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { - if (S->hasExplicitParameters()) { - // Visit parameters. - for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { - TRY_TO(TraverseDecl(Proto.getParam(I))); - } - } else { - TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>(); + + if (S->hasExplicitParameters() && S->hasExplicitResultType()) { + // Visit the whole type. + TRY_TO(TraverseTypeLoc(TL)); + } else { + if (S->hasExplicitParameters()) { + // Visit parameters. + for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { + TRY_TO(TraverseDecl(Proto.getParam(I))); } + } else if (S->hasExplicitResultType()) { + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + } + + auto *T = Proto.getTypePtr(); + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); } TRY_TO(TraverseLambdaBody(S)); @@ -2237,6 +2254,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) +DEF_TRAVERSE_STMT(TypoExpr, {}) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) // These operators (all of them) do not need any action except @@ -2253,6 +2271,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) +DEF_TRAVERSE_STMT(CXXFoldExpr, {}) DEF_TRAVERSE_STMT(AtomicExpr, {}) // These literals (all of them) do not need any action. @@ -2279,6 +2298,12 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( return true; } +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { + return TraverseOMPExecutableDirective(S); +} + DEF_TRAVERSE_STMT(OMPParallelDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2288,6 +2313,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective, DEF_TRAVERSE_STMT(OMPForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2308,6 +2336,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, { DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2326,6 +2357,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPOrderedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPAtomicDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTeamsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { @@ -2415,6 +2458,31 @@ RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -2426,6 +2494,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } return true; } @@ -2433,6 +2504,12 @@ template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( OMPFirstprivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->inits()) { + TRY_TO(TraverseStmt(E)); + } return true; } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ce8b8b7..a39888f 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -43,6 +43,7 @@ class Stmt; class StringLiteral; class TemplateArgumentList; class TemplateParameterList; +class TypeAliasTemplateDecl; class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; @@ -67,6 +68,9 @@ public: /// \brief Return the TypeLoc wrapper for the type source info. TypeLoc getTypeLoc() const; // implemented in TypeLoc.h + + /// \brief Override the type stored in this TypeSourceInfo. Use with caution! + void overrideType(QualType T) { Ty = T; } }; /// TranslationUnitDecl - The top declaration context. @@ -288,6 +292,8 @@ public: return const_cast<NamedDecl*>(this)->getMostRecentDecl(); } + ObjCStringFormatFamily getObjCFStringFormattingFamily() const; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; } }; @@ -305,6 +311,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { class LabelDecl : public NamedDecl { void anchor() override; LabelStmt *TheStmt; + StringRef MSAsmName; + bool MSAsmNameResolved; /// LocStart - For normal labels, this is the same as the main declaration /// label, i.e., the location of the identifier; for GNU local labels, /// this is the location of the __label__ keyword. @@ -312,7 +320,10 @@ class LabelDecl : public NamedDecl { LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, LabelStmt *S, SourceLocation StartL) - : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {} + : NamedDecl(Label, DC, IdentL, II), + TheStmt(S), + MSAsmNameResolved(false), + LocStart(StartL) {} public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, @@ -332,6 +343,12 @@ public: return SourceRange(LocStart, getLocation()); } + bool isMSAsmLabel() const { return MSAsmName.size() != 0; } + bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; } + void setMSAsmLabel(StringRef Name); + StringRef getMSAsmLabel() const { return MSAsmName; } + void setMSAsmLabelResolved() { MSAsmNameResolved = true; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Label; } @@ -648,8 +665,6 @@ struct EvaluatedStmt { /// declaration or definition. class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { public: - typedef clang::StorageClass StorageClass; - /// getStorageClassSpecifierString - Return the string used to /// specify the storage class \p SC. /// @@ -891,6 +906,11 @@ public: return false; } + /// \brief Similar to isLocalVarDecl but also includes parameters. + bool isLocalVarDeclOrParm() const { + return isLocalVarDecl() || getKind() == Decl::ParmVar; + } + /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but /// excludes variables declared in blocks. bool isFunctionOrMethodVarDecl() const { @@ -1423,8 +1443,6 @@ private: class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable<FunctionDecl> { public: - typedef clang::StorageClass StorageClass; - /// \brief The kind of templated function a FunctionDecl can be. enum TemplatedKind { TK_NonTemplate, @@ -1650,7 +1668,7 @@ public: /// unnecessary AST de-serialization of the body. Stmt *getBody(const FunctionDecl *&Definition) const; - Stmt *getBody() const override { + Stmt *getBody() const override { const FunctionDecl* Definition; return getBody(Definition); } @@ -1880,7 +1898,7 @@ public: return llvm::makeArrayRef(ParamInfo, getNumParams()); } - const ArrayRef<NamedDecl *> &getDeclsInPrototypeScope() const { + ArrayRef<NamedDecl *> getDeclsInPrototypeScope() const { return DeclsInPrototypeScope; } void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls); @@ -2154,17 +2172,41 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { bool Mutable : 1; mutable unsigned CachedFieldIndex : 31; - /// \brief An InClassInitStyle value, and either a bit width expression (if - /// the InClassInitStyle value is ICIS_NoInit), or a pointer to the in-class - /// initializer for this field (otherwise). + /// The kinds of value we can store in InitializerOrBitWidth. /// - /// We can safely combine these two because in-class initializers are not - /// permitted for bit-fields. + /// Note that this is compatible with InClassInitStyle except for + /// ISK_CapturedVLAType. + enum InitStorageKind { + /// If the pointer is null, there's nothing special. Otherwise, + /// this is a bitfield and the pointer is the Expr* storing the + /// bit-width. + ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit, + + /// The pointer is an (optional due to delayed parsing) Expr* + /// holding the copy-initializer. + ISK_InClassCopyInit = (unsigned) ICIS_CopyInit, + + /// The pointer is an (optional due to delayed parsing) Expr* + /// holding the list-initializer. + ISK_InClassListInit = (unsigned) ICIS_ListInit, + + /// The pointer is a VariableArrayType* that's been captured; + /// the enclosing context is a lambda or captured statement. + ISK_CapturedVLAType, + }; + + /// \brief Storage for either the bit-width, the in-class + /// initializer, or the captured variable length array bound. + /// + /// We can safely combine these because in-class initializers are + /// not permitted for bit-fields, and both are exclusive with VLA + /// captures. /// - /// If the InClassInitStyle is not ICIS_NoInit and the initializer is null, - /// then this field has an in-class initializer which has not yet been parsed + /// If the storage kind is ISK_InClassCopyInit or + /// ISK_InClassListInit, but the initializer is null, then this + /// field has an in-class initializer which has not yet been parsed /// and attached. - llvm::PointerIntPair<Expr *, 2, unsigned> InitializerOrBitWidth; + llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -2172,7 +2214,7 @@ protected: InClassInitStyle InitStyle) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Mutable(Mutable), CachedFieldIndex(0), - InitializerOrBitWidth(BW, InitStyle) { + InitStorage(BW, (InitStorageKind) InitStyle) { assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield"); } @@ -2192,10 +2234,10 @@ public: /// isMutable - Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } - /// isBitfield - Determines whether this field is a bitfield. + /// \brief Determines whether this field is a bitfield. bool isBitField() const { - return getInClassInitStyle() == ICIS_NoInit && - InitializerOrBitWidth.getPointer(); + return InitStorage.getInt() == ISK_BitWidthOrNothing && + InitStorage.getPointer() != nullptr; } /// @brief Determines whether this is an unnamed bitfield. @@ -2208,24 +2250,34 @@ public: bool isAnonymousStructOrUnion() const; Expr *getBitWidth() const { - return isBitField() ? InitializerOrBitWidth.getPointer() : nullptr; + return isBitField() + ? static_cast<Expr *>(InitStorage.getPointer()) + : nullptr; } unsigned getBitWidthValue(const ASTContext &Ctx) const; /// setBitWidth - Set the bit-field width for this member. // Note: used by some clients (i.e., do not remove it). - void setBitWidth(Expr *Width); + void setBitWidth(Expr *Width) { + assert(InitStorage.getInt() == ISK_BitWidthOrNothing && + InitStorage.getPointer() == nullptr && + "bit width, initializer or captured type already set"); + InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing); + } + /// removeBitWidth - Remove the bit-field width from this member. // Note: used by some clients (i.e., do not remove it). void removeBitWidth() { assert(isBitField() && "no bitfield width to remove"); - InitializerOrBitWidth.setPointer(nullptr); + InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); } /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which /// this field has. InClassInitStyle getInClassInitStyle() const { - return static_cast<InClassInitStyle>(InitializerOrBitWidth.getInt()); + InitStorageKind storageKind = InitStorage.getInt(); + return (storageKind == ISK_CapturedVLAType + ? ICIS_NoInit : (InClassInitStyle) storageKind); } /// hasInClassInitializer - Determine whether this member has a C++11 in-class @@ -2233,24 +2285,47 @@ public: bool hasInClassInitializer() const { return getInClassInitStyle() != ICIS_NoInit; } + /// getInClassInitializer - Get the C++11 in-class initializer for this /// member, or null if one has not been set. If a valid declaration has an /// in-class initializer, but this returns null, then we have not parsed and /// attached it yet. Expr *getInClassInitializer() const { - return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() - : nullptr; + return hasInClassInitializer() + ? static_cast<Expr *>(InitStorage.getPointer()) + : nullptr; } + /// setInClassInitializer - Set the C++11 in-class initializer for this /// member. - void setInClassInitializer(Expr *Init); + void setInClassInitializer(Expr *Init) { + assert(hasInClassInitializer() && + InitStorage.getPointer() == nullptr && + "bit width, initializer or captured type already set"); + InitStorage.setPointer(Init); + } + /// removeInClassInitializer - Remove the C++11 in-class initializer from this /// member. void removeInClassInitializer() { assert(hasInClassInitializer() && "no initializer to remove"); - InitializerOrBitWidth.setPointer(nullptr); - InitializerOrBitWidth.setInt(ICIS_NoInit); + InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); + } + + /// \brief Determine whether this member captures the variable length array + /// type. + bool hasCapturedVLAType() const { + return InitStorage.getInt() == ISK_CapturedVLAType; + } + + /// \brief Get the captured variable length array type. + const VariableArrayType *getCapturedVLAType() const { + return hasCapturedVLAType() ? static_cast<const VariableArrayType *>( + InitStorage.getPointer()) + : nullptr; } + /// \brief Set the captured variable length array type for this field. + void setCapturedVLAType(const VariableArrayType *VLAType); /// getParent - Returns the parent of this field declaration, which /// is the struct in which this method is defined. @@ -2492,9 +2567,13 @@ public: /// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x /// alias-declaration. class TypeAliasDecl : public TypedefNameDecl { + /// The template for which this is the pattern, if any. + TypeAliasTemplateDecl *Template; + TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo) {} + : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo), + Template(nullptr) {} public: static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, @@ -2504,6 +2583,9 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; } + void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TypeAlias; } @@ -2647,7 +2729,7 @@ public: } /// isThisDeclarationADefinition() - Return true if this declaration - /// is a completion definintion of the type. Provided for consistency. + /// is a completion definition of the type. Provided for consistency. bool isThisDeclarationADefinition() const { return isCompleteDefinition(); } @@ -3136,6 +3218,17 @@ public: /// \endcode bool isInjectedClassName() const; + /// \brief Determine whether this record is a class describing a lambda + /// function object. + bool isLambda() const; + + /// \brief Determine whether this record is a record for captured variables in + /// CapturedStmt construct. + bool isCapturedRecord() const; + /// \brief Mark the record as a record for captured variables in CapturedStmt + /// construct. + void setCapturedRecord(); + /// getDefinition - Returns the RecordDecl that actually defines /// this struct/union/class. When determining whether or not a /// struct/union/class is completely defined, one should use this @@ -3181,6 +3274,15 @@ public: /// commandline option. bool isMsStruct(const ASTContext &C) const; + /// \brief Whether we are allowed to insert extra padding between fields. + /// These padding are added to help AddressSanitizer detect + /// intra-object-overflow bugs. + bool mayInsertExtraPadding(bool EmitRemark = false) const; + + /// Finds the first data member which has a name. + /// nullptr is returned if no named data member exists. + const FieldDecl *findFirstNamedDataMember() const; + private: /// \brief Deserialize just the fields. void LoadFieldsFromExternalStorage() const; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 607ca4e..984ab13 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -48,6 +48,7 @@ class ObjCInterfaceDecl; class ObjCMethodDecl; class ObjCProtocolDecl; struct PrintingPolicy; +class RecordDecl; class Stmt; class StoredDeclsMap; class TranslationUnitDecl; @@ -515,9 +516,13 @@ public: /// indicating the declaration is used. void markUsed(ASTContext &C); - /// \brief Whether this declaration was referenced. + /// \brief Whether any declaration of this entity was referenced. bool isReferenced() const; + /// \brief Whether this declaration was referenced. This should not be relied + /// upon for anything other than debugging. + bool isThisDeclarationReferenced() const { return Referenced; } + void setReferenced(bool R = true) { Referenced = R; } /// \brief Whether this declaration is a top-level declaration (function, @@ -675,9 +680,9 @@ public: return const_cast<Decl*>(this)->getLexicalDeclContext(); } - virtual bool isOutOfLine() const { - return getLexicalDeclContext() != getDeclContext(); - } + /// Determine whether this declaration is declared out of line (outside its + /// semantic context). + virtual bool isOutOfLine() const; /// setDeclContext - Set both the semantic and lexical DeclContext /// to DC. @@ -1234,6 +1239,12 @@ public: return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); } + /// \brief Retrieve the outermost lexically enclosing record context. + RecordDecl *getOuterLexicalRecordContext(); + const RecordDecl *getOuterLexicalRecordContext() const { + return const_cast<DeclContext *>(this)->getOuterLexicalRecordContext(); + } + /// \brief Test if this context is part of the enclosing namespace set of /// the context NS, as defined in C++0x [namespace.def]p9. If either context /// isn't a namespace, this is equivalent to Equals(). @@ -1642,7 +1653,7 @@ public: void dumpDeclContext() const; void dumpLookups() const; - void dumpLookups(llvm::raw_ostream &OS) const; + void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const; private: void reconcileExternalVisibleStorage() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 72fad7c..027b41e 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -538,6 +538,12 @@ class CXXRecordDecl : public RecordDecl { ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr), MethodTyInfo(Info) { IsLambda = true; + + // C++11 [expr.prim.lambda]p3: + // This class type is neither an aggregate nor a literal type. + Aggregate = false; + PlainOldData = false; + HasNonLiteralTypeFieldsOrBases = true; } /// \brief Whether this lambda is known to be dependent, even if its @@ -820,7 +826,11 @@ public: /// This value is used for lazy creation of default constructors. bool needsImplicitDefaultConstructor() const { return !data().UserDeclaredConstructor && - !(data().DeclaredSpecialMembers & SMF_DefaultConstructor); + !(data().DeclaredSpecialMembers & SMF_DefaultConstructor) && + // C++14 [expr.prim.lambda]p20: + // The closure type associated with a lambda-expression has no + // default constructor. + !isLambda(); } /// \brief Determine whether this class has any user-declared constructors. @@ -1371,6 +1381,15 @@ public: /// \brief Set the kind of specialization or template instantiation this is. void setTemplateSpecializationKind(TemplateSpecializationKind TSK); + /// \brief Retrieve the record declaration from which this record could be + /// instantiated. Returns null if this class is not a template instantiation. + const CXXRecordDecl *getTemplateInstantiationPattern() const; + + CXXRecordDecl *getTemplateInstantiationPattern() { + return const_cast<CXXRecordDecl *>(const_cast<const CXXRecordDecl *>(this) + ->getTemplateInstantiationPattern()); + } + /// \brief Returns the destructor decl for this class. CXXDestructorDecl *getDestructor() const; @@ -2104,8 +2123,8 @@ public: } ArrayRef<VarDecl *> getArrayIndexes() { assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init"); - return ArrayRef<VarDecl *>(reinterpret_cast<VarDecl **>(this + 1), - getNumArrayIndices()); + return llvm::makeArrayRef(reinterpret_cast<VarDecl **>(this + 1), + getNumArrayIndices()); } /// \brief Get the initializer. @@ -2636,7 +2655,8 @@ public: /// \code /// namespace Foo = Bar; /// \endcode -class NamespaceAliasDecl : public NamedDecl { +class NamespaceAliasDecl : public NamedDecl, + public Redeclarable<NamespaceAliasDecl> { void anchor() override; /// \brief The location of the \c namespace keyword. @@ -2654,17 +2674,47 @@ class NamespaceAliasDecl : public NamedDecl { /// a NamespaceAliasDecl. NamedDecl *Namespace; - NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc, - SourceLocation AliasLoc, IdentifierInfo *Alias, - NestedNameSpecifierLoc QualifierLoc, + NamespaceAliasDecl(ASTContext &C, DeclContext *DC, + SourceLocation NamespaceLoc, SourceLocation AliasLoc, + IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), - NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), - QualifierLoc(QualifierLoc), Namespace(Namespace) { } + : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), redeclarable_base(C), + NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), + QualifierLoc(QualifierLoc), Namespace(Namespace) {} + + typedef Redeclarable<NamespaceAliasDecl> redeclarable_base; + NamespaceAliasDecl *getNextRedeclarationImpl() override; + NamespaceAliasDecl *getPreviousDeclImpl() override; + NamespaceAliasDecl *getMostRecentDeclImpl() override; friend class ASTDeclReader; public: + static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, + IdentifierInfo *Alias, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation IdentLoc, + NamedDecl *Namespace); + + static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + typedef redeclarable_base::redecl_range redecl_range; + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::redecls; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; + + NamespaceAliasDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const NamespaceAliasDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } @@ -2701,16 +2751,6 @@ public: /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } - static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation NamespaceLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Namespace); - - static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(NamespaceLoc, IdentLoc); } @@ -2824,7 +2864,7 @@ public: /// \code /// using someNameSpace::someIdentifier; /// \endcode -class UsingDecl : public NamedDecl { +class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { void anchor() override; /// \brief The source location of the 'using' keyword itself. @@ -2948,6 +2988,10 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + /// Retrieves the canonical declaration of this declaration. + UsingDecl *getCanonicalDecl() override { return getFirstDecl(); } + const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Using; } @@ -2966,7 +3010,8 @@ public: /// using Base<T>::foo; /// }; /// \endcode -class UnresolvedUsingValueDecl : public ValueDecl { +class UnresolvedUsingValueDecl : public ValueDecl, + public Mergeable<UnresolvedUsingValueDecl> { void anchor() override; /// \brief The source location of the 'using' keyword @@ -3022,6 +3067,14 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + /// Retrieves the canonical declaration of this declaration. + UnresolvedUsingValueDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const UnresolvedUsingValueDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } @@ -3040,7 +3093,9 @@ public: /// /// The type associated with an unresolved using typename decl is /// currently always a typename type. -class UnresolvedUsingTypenameDecl : public TypeDecl { +class UnresolvedUsingTypenameDecl + : public TypeDecl, + public Mergeable<UnresolvedUsingTypenameDecl> { void anchor() override; /// \brief The source location of the 'typename' keyword @@ -3084,6 +3139,14 @@ public: static UnresolvedUsingTypenameDecl * CreateDeserialized(ASTContext &C, unsigned ID); + /// Retrieves the canonical declaration of this declaration. + UnresolvedUsingTypenameDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const UnresolvedUsingTypenameDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } }; diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h index d2016af..eba2266 100644 --- a/include/clang/AST/DeclLookups.h +++ b/include/clang/AST/DeclLookups.h @@ -75,7 +75,10 @@ inline DeclContext::lookups_range DeclContext::lookups() const { if (StoredDeclsMap *Map = Primary->buildLookup()) return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), all_lookups_iterator(Map->end(), Map->end())); - return lookups_range(); + + // Synthesize an empty range. This requires that two default constructed + // versions of these iterators form a valid empty range. + return lookups_range(all_lookups_iterator(), all_lookups_iterator()); } inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { @@ -91,7 +94,10 @@ inline DeclContext::lookups_range DeclContext::noload_lookups() const { if (StoredDeclsMap *Map = Primary->getLookupPtr()) return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), all_lookups_iterator(Map->end(), Map->end())); - return lookups_range(); + + // Synthesize an empty range. This requires that two default constructed + // versions of these iterators form a valid empty range. + return lookups_range(all_lookups_iterator(), all_lookups_iterator()); } inline diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index db3b084..55d4b0f 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -329,6 +329,7 @@ public: QualType getReturnType() const { return MethodDeclType; } void setReturnType(QualType T) { MethodDeclType = T; } + SourceRange getReturnTypeSourceRange() const; /// \brief Determine the type of an expression that sends a message to this /// function. @@ -378,8 +379,7 @@ public: /// ignored. void setMethodParams(ASTContext &C, ArrayRef<ParmVarDecl*> Params, - ArrayRef<SourceLocation> SelLocs = - ArrayRef<SourceLocation>()); + ArrayRef<SourceLocation> SelLocs = llvm::None); // Iterator access to parameter types. typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun; @@ -591,7 +591,8 @@ public: bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const; ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; - ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; + ObjCPropertyDecl * + FindPropertyDeclaration(const IdentifierInfo *PropertyId) const; typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap; @@ -2354,7 +2355,7 @@ public: /// Lookup a property by name in the specified DeclContext. static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, - IdentifierInfo *propertyID); + const IdentifierInfo *propertyID); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProperty; } diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h index 1b329dc..7f0616f 100644 --- a/include/clang/AST/DeclOpenMP.h +++ b/include/clang/AST/DeclOpenMP.h @@ -12,13 +12,14 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_OPENMP_H -#define LLVM_CLANG_AST_OPENMP_H +#ifndef LLVM_CLANG_AST_DECLOPENMP_H +#define LLVM_CLANG_AST_DECLOPENMP_H #include "clang/AST/DeclBase.h" #include "llvm/ADT/ArrayRef.h" namespace clang { +class Expr; /// \brief This represents '#pragma omp threadprivate ...' directive. /// For example, in the following, both 'a' and 'A::b' are threadprivate: @@ -42,9 +43,8 @@ class OMPThreadPrivateDecl : public Decl { Decl(DK, DC, L), NumVars(0) { } ArrayRef<const Expr *> getVars() const { - return ArrayRef<const Expr *>( - reinterpret_cast<const Expr * const *>(this + 1), - NumVars); + return llvm::makeArrayRef(reinterpret_cast<const Expr * const *>(this + 1), + NumVars); } MutableArrayRef<Expr *> getVars() { diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 980a06e..9283d2d 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -87,10 +87,10 @@ public: unsigned size() const { return NumParams; } ArrayRef<NamedDecl*> asArray() { - return ArrayRef<NamedDecl*>(begin(), size()); + return llvm::makeArrayRef(begin(), end()); } ArrayRef<const NamedDecl*> asArray() const { - return ArrayRef<const NamedDecl*>(begin(), size()); + return llvm::makeArrayRef(begin(), size()); } NamedDecl* getParam(unsigned Idx) { @@ -204,7 +204,7 @@ public: /// \brief Produce this as an array ref. ArrayRef<TemplateArgument> asArray() const { - return ArrayRef<TemplateArgument>(data(), size()); + return llvm::makeArrayRef(data(), size()); } /// \brief Retrieve the number of template arguments in this @@ -236,7 +236,7 @@ protected: TemplateParams(nullptr) {} // Construct a template decl with the given name and parameters. - // Used when there is not templated element (tt-params, alias?). + // Used when there is not templated element (tt-params). TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 3076b30..49e51e0 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -59,6 +59,7 @@ public: CXXLiteralOperatorName, CXXUsingDirective }; + static const unsigned NumNameKinds = CXXUsingDirective + 1; private: /// StoredNameKind - The kind of name that is actually stored in the diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h index 63047ec..8e038c8 100644 --- a/include/clang/AST/DependentDiagnostic.h +++ b/include/clang/AST/DependentDiagnostic.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H -#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H +#ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H +#define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H #include "clang/AST/DeclBase.h" #include "clang/AST/DeclContextInternals.h" @@ -178,7 +178,8 @@ inline DeclContext::ddiag_range DeclContext::ddiags() const { = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr()); if (!Map) - return ddiag_range(); + // Return an empty range using the always-end default constructor. + return ddiag_range(ddiag_iterator(), ddiag_iterator()); return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator()); } diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index 12c4fcc..59de104 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -56,6 +56,17 @@ public: return this->Visit(E->getChosenSubExpr()); } + void VisitGenericSelectionExpr(GenericSelectionExpr *E) { + // The controlling expression of a generic selection is not evaluated. + + // Don't visit either child expression if the condition is type-dependent. + if (E->isResultDependent()) + return; + // Only the selected subexpression matters; the other subexpressions and the + // controlling expression are not evaluated. + return this->Visit(E->getResultExpr()); + } + void VisitDesignatedInitExpr(DesignatedInitExpr *E) { // Only the actual initializer matters; the designators are all constant // expressions. diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index b4bb0b6..c410f23 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -45,6 +45,7 @@ namespace clang { class ObjCPropertyRefExpr; class OpaqueValueExpr; class ParmVarDecl; + class StringLiteral; class TargetInfo; class ValueDecl; @@ -124,8 +125,7 @@ public: QualType getType() const { return TR; } void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it - // will not have reference type an expression will never have - // reference type (C++ [expr]p6). Use + // will not have reference type (C++ [expr]p6). Use // QualType::getNonReferenceType() to retrieve the non-reference // type. Additionally, inspect Expr::isLvalue to determine whether // an expression that is adjusted in this manner should be @@ -586,8 +586,13 @@ public: /// HasSideEffects - This routine returns true for all those expressions /// which have any effect other than producing a value. Example is a function - /// call, volatile variable read, or throwing an exception. - bool HasSideEffects(const ASTContext &Ctx) const; + /// call, volatile variable read, or throwing an exception. If + /// IncludePossibleEffects is false, this call treats certain expressions with + /// potential side effects (such as function call-like expressions, + /// instantiation-dependent expressions, or invocations from a macro) as not + /// having side effects. + bool HasSideEffects(const ASTContext &Ctx, + bool IncludePossibleEffects = true) const; /// \brief Determine whether this expression involves a call to any function /// that is not trivial. @@ -886,9 +891,9 @@ public: /// DeclRefExprBits.HasTemplateKWAndArgsInfo: /// Specifies when this declaration reference expression has an explicit /// C++ template keyword and/or template argument list. -/// DeclRefExprBits.RefersToEnclosingLocal +/// DeclRefExprBits.RefersToEnclosingVariableOrCapture /// Specifies when this declaration reference expression (validly) -/// refers to a local variable from a different function. +/// refers to an enclosed local or a captured variable. class DeclRefExpr : public Expr { /// \brief The declaration that we are referencing. ValueDecl *D; @@ -933,7 +938,7 @@ class DeclRefExpr : public Expr { DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - ValueDecl *D, bool refersToEnclosingLocal, + ValueDecl *D, bool RefersToEnlosingVariableOrCapture, const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, @@ -948,7 +953,7 @@ class DeclRefExpr : public Expr { void computeDependence(const ASTContext &C); public: - DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T, + DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, ExprValueKind VK, SourceLocation L, const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), @@ -957,20 +962,22 @@ public: DeclRefExprBits.HasTemplateKWAndArgsInfo = 0; DeclRefExprBits.HasFoundDecl = 0; DeclRefExprBits.HadMultipleCandidates = 0; - DeclRefExprBits.RefersToEnclosingLocal = refersToEnclosingLocal; + DeclRefExprBits.RefersToEnclosingVariableOrCapture = + RefersToEnclosingVariableOrCapture; computeDependence(D->getASTContext()); } static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal, - SourceLocation NameLoc, QualType T, ExprValueKind VK, - NamedDecl *FoundD = nullptr, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, + QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr); static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr); @@ -1144,10 +1151,10 @@ public: DeclRefExprBits.HadMultipleCandidates = V; } - /// Does this DeclRefExpr refer to a local declaration from an - /// enclosing function scope? - bool refersToEnclosingLocal() const { - return DeclRefExprBits.RefersToEnclosingLocal; + /// \brief Does this DeclRefExpr refer to an enclosing local or a captured + /// variable? + bool refersToEnclosingVariableOrCapture() const { + return DeclRefExprBits.RefersToEnclosingVariableOrCapture; } static bool classof(const Stmt *T) { @@ -1161,7 +1168,7 @@ public: friend class ASTStmtWriter; }; -/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. +/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__. class PredefinedExpr : public Expr { public: enum IdentType { @@ -1171,7 +1178,7 @@ public: FuncDName, FuncSig, PrettyFunction, - /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the + /// \brief The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. PrettyFunctionNoVirtual }; @@ -1179,24 +1186,27 @@ public: private: SourceLocation Loc; IdentType Type; + Stmt *FnName; + public: - PredefinedExpr(SourceLocation l, QualType type, IdentType IT) - : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary, - type->isDependentType(), type->isDependentType(), - type->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(l), Type(IT) {} + PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, + StringLiteral *SL); /// \brief Construct an empty predefined expression. explicit PredefinedExpr(EmptyShell Empty) - : Expr(PredefinedExprClass, Empty) { } + : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {} IdentType getIdentType() const { return Type; } - void setIdentType(IdentType IT) { Type = IT; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } + StringLiteral *getFunctionName(); + const StringLiteral *getFunctionName() const { + return const_cast<PredefinedExpr *>(this)->getFunctionName(); + } + + static StringRef getIdentTypeName(IdentType IT); static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); SourceLocation getLocStart() const LLVM_READONLY { return Loc; } @@ -1207,7 +1217,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { return child_range(&FnName, &FnName + 1); } + + friend class ASTStmtReader; }; /// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without @@ -2212,11 +2224,11 @@ public: /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]); + return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]); + return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); } /// setArg - Set the specified argument. @@ -2256,8 +2268,8 @@ public: /// interface. This provides efficient reverse iteration of the /// subexpressions. This is currently used for CFG construction. ArrayRef<Stmt*> getRawSubExprs() { - return ArrayRef<Stmt*>(SubExprs, - getNumPreArgs() + PREARGS_START + getNumArgs()); + return llvm::makeArrayRef(SubExprs, + getNumPreArgs() + PREARGS_START + getNumArgs()); } /// getNumCommas - Return the number of commas that must have been present in @@ -2653,9 +2665,6 @@ public: /// representation in the source code (ExplicitCastExpr's derived /// classes). class CastExpr : public Expr { -public: - typedef clang::CastKind CastKind; - private: Stmt *Op; @@ -2673,20 +2682,23 @@ private: } protected: - CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, - const CastKind kind, Expr *op, unsigned BasePathSize) : - Expr(SC, ty, VK, OK_Ordinary, - // Cast expressions are type-dependent if the type is - // dependent (C++ [temp.dep.expr]p3). - ty->isDependentType(), - // Cast expressions are value-dependent if the type is - // dependent or if the subexpression is value-dependent. - ty->isDependentType() || (op && op->isValueDependent()), - (ty->isInstantiationDependentType() || - (op && op->isInstantiationDependent())), - (ty->containsUnexpandedParameterPack() || - (op && op->containsUnexpandedParameterPack()))), - Op(op) { + CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, + Expr *op, unsigned BasePathSize) + : Expr(SC, ty, VK, OK_Ordinary, + // Cast expressions are type-dependent if the type is + // dependent (C++ [temp.dep.expr]p3). + ty->isDependentType(), + // Cast expressions are value-dependent if the type is + // dependent or if the subexpression is value-dependent. + ty->isDependentType() || (op && op->isValueDependent()), + (ty->isInstantiationDependentType() || + (op && op->isInstantiationDependent())), + // An implicit cast expression doesn't (lexically) contain an + // unexpanded pack, even if its target type does. + ((SC != ImplicitCastExprClass && + ty->containsUnexpandedParameterPack()) || + (op && op->containsUnexpandedParameterPack()))), + Op(op) { assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; setBasePathSize(BasePathSize); @@ -4841,6 +4853,24 @@ public: return child_range(SubExprs, SubExprs+NumSubExprs); } }; + +/// TypoExpr - Internal placeholder for expressions where typo correction +/// still needs to be performed and/or an error diagnostic emitted. +class TypoExpr : public Expr { +public: + TypoExpr(QualType T) + : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary, + /*isTypeDependent*/ true, + /*isValueDependent*/ true, + /*isInstantiationDependent*/ true, + /*containsUnexpandedParameterPack*/ false) { + assert(T->isDependentType() && "TypoExpr given a non-dependent type"); + } + + child_range children() { return child_range(); } + SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } +}; } // end namespace clang #endif diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 3a43d6d..1768178 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -17,10 +17,10 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/LambdaCapture.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/ExpressionTraits.h" -#include "clang/AST/LambdaCapture.h" #include "clang/Basic/TypeTraits.h" #include "llvm/Support/Compiler.h" @@ -967,8 +967,14 @@ public: const FieldDecl *getField() const { return Field; } /// \brief Get the initialization expression that will be used. - const Expr *getExpr() const { return Field->getInClassInitializer(); } - Expr *getExpr() { return Field->getInClassInitializer(); } + const Expr *getExpr() const { + assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); + return Field->getInClassInitializer(); + } + Expr *getExpr() { + assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); + return Field->getInClassInitializer(); + } SourceLocation getLocStart() const LLVM_READONLY { return Loc; } SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } @@ -1165,6 +1171,13 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; + typedef llvm::iterator_range<arg_iterator> arg_range; + typedef llvm::iterator_range<const_arg_iterator> arg_const_range; + + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } + arg_const_range arguments() const { + return arg_const_range(arg_begin(), arg_end()); + } arg_iterator arg_begin() { return Args; } arg_iterator arg_end() { return Args + NumArgs; } @@ -1569,12 +1582,12 @@ class CXXScalarValueInitExpr : public Expr { public: /// \brief Create an explicitly-written scalar-value initialization /// expression. - CXXScalarValueInitExpr(QualType Type, - TypeSourceInfo *TypeInfo, - SourceLocation rParenLoc ) : - Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, - false, false, Type->isInstantiationDependentType(), false), - RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} + CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, + SourceLocation rParenLoc) + : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, + false, false, Type->isInstantiationDependentType(), + Type->containsUnexpandedParameterPack()), + RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} explicit CXXScalarValueInitExpr(EmptyShell Shell) : Expr(CXXScalarValueInitExprClass, Shell) { } @@ -2113,7 +2126,7 @@ public: /// \brief Retrieve the argument types. ArrayRef<TypeSourceInfo *> getArgs() const { - return ArrayRef<TypeSourceInfo *>(getTypeSourceInfos(), getNumArgs()); + return llvm::makeArrayRef(getTypeSourceInfos(), getNumArgs()); } typedef TypeSourceInfo **arg_iterator; @@ -2767,7 +2780,7 @@ public: ArrayRef<CleanupObject> objects); ArrayRef<CleanupObject> getObjects() const { - return ArrayRef<CleanupObject>(getObjectsBuffer(), getNumObjects()); + return llvm::makeArrayRef(getObjectsBuffer(), getNumObjects()); } unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; } @@ -2902,8 +2915,9 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY { - assert(RParenLoc.isValid() || NumArgs == 1); - return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd(); + if (!RParenLoc.isValid() && NumArgs > 0) + return getArg(NumArgs - 1)->getLocEnd(); + return RParenLoc; } static bool classof(const Stmt *T) { @@ -3811,6 +3825,69 @@ public: } }; +/// \brief Represents a folding of a pack over an operator. +/// +/// This expression is always dependent and represents a pack expansion of the +/// forms: +/// +/// ( expr op ... ) +/// ( ... op expr ) +/// ( expr op ... op expr ) +class CXXFoldExpr : public Expr { + SourceLocation LParenLoc; + SourceLocation EllipsisLoc; + SourceLocation RParenLoc; + Stmt *SubExprs[2]; + BinaryOperatorKind Opcode; + + friend class ASTStmtReader; + friend class ASTStmtWriter; +public: + CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS, + BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc) + : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary, + /*Dependent*/ true, true, true, + /*ContainsUnexpandedParameterPack*/ false), + LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), + Opcode(Opcode) { + SubExprs[0] = LHS; + SubExprs[1] = RHS; + } + CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} + + Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); } + Expr *getRHS() const { return static_cast<Expr*>(SubExprs[1]); } + + /// Does this produce a right-associated sequence of operators? + bool isRightFold() const { + return getLHS() && getLHS()->containsUnexpandedParameterPack(); + } + /// Does this produce a left-associated sequence of operators? + bool isLeftFold() const { return !isRightFold(); } + /// Get the pattern, that is, the operand that contains an unexpanded pack. + Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); } + /// Get the operand that doesn't contain a pack, for a binary fold. + Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); } + + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + BinaryOperatorKind getOperator() const { return Opcode; } + + SourceLocation getLocStart() const LLVM_READONLY { + return LParenLoc; + } + SourceLocation getLocEnd() const LLVM_READONLY { + return RParenLoc; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXFoldExprClass; + } + + // Iterators + child_range children() { return child_range(SubExprs, SubExprs + 2); } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 817c0cc..f296e8f 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -124,6 +124,15 @@ public: // Iterators child_range children() { return child_range(&SubExpr, &SubExpr+1); } + + typedef ConstExprIterator const_arg_iterator; + + const_arg_iterator arg_begin() const { + return reinterpret_cast<Stmt const * const*>(&SubExpr); + } + const_arg_iterator arg_end() const { + return reinterpret_cast<Stmt const * const*>(&SubExpr + 1); + } friend class ASTStmtReader; }; diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 1e8eff3..ff1d180 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -11,8 +11,8 @@ // construction of AST nodes from some external source. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H -#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H +#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H #include "clang/AST/CharUnits.h" #include "clang/AST/DeclBase.h" @@ -650,4 +650,4 @@ typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, } // end namespace clang -#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#endif diff --git a/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h index 8633c97..a7468a0 100644 --- a/include/clang/AST/LambdaCapture.h +++ b/include/clang/AST/LambdaCapture.h @@ -68,13 +68,23 @@ public: /// \brief Determine whether this capture handles the C++ \c this /// pointer. - bool capturesThis() const { return DeclAndBits.getPointer() == nullptr; } + bool capturesThis() const { + return (DeclAndBits.getPointer() == nullptr) && + !(DeclAndBits.getInt() & Capture_ByCopy); + } /// \brief Determine whether this capture handles a variable. bool capturesVariable() const { return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer()); } + /// \brief Determine whether this captures a variable length array bound + /// expression. + bool capturesVLAType() const { + return (DeclAndBits.getPointer() == nullptr) && + (DeclAndBits.getInt() & Capture_ByCopy); + } + /// \brief Determine whether this is an init-capture. bool isInitCapture() const { return capturesVariable() && getCapturedVar()->isInitCapture(); diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index a8d1199..cbe08a1 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -156,6 +156,11 @@ public: virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &) = 0; + virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D, + raw_ostream &) = 0; + virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D, + raw_ostream &) = 0; + static bool classof(const MangleContext *C) { return C->getKind() == MK_Itanium; } diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h index 56c9952..7a81855 100644 --- a/include/clang/AST/MangleNumberingContext.h +++ b/include/clang/AST/MangleNumberingContext.h @@ -12,8 +12,8 @@ // literals. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H -#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H +#ifndef LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H +#define LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" @@ -30,23 +30,20 @@ class VarDecl; /// \brief Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. -class MangleNumberingContext - : public RefCountedBase<MangleNumberingContext> { - llvm::DenseMap<const Type *, unsigned> ManglingNumbers; - +class MangleNumberingContext : public RefCountedBase<MangleNumberingContext> { public: virtual ~MangleNumberingContext() {} /// \brief Retrieve the mangling number of a new lambda expression with the /// given call operator within this context. - unsigned getManglingNumber(const CXXMethodDecl *CallOperator); + virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0; /// \brief Retrieve the mangling number of a new block literal within this /// context. - unsigned getManglingNumber(const BlockDecl *BD); + virtual unsigned getManglingNumber(const BlockDecl *BD) = 0; /// Static locals are numbered by source order. - unsigned getStaticLocalNumber(const VarDecl *VD); + virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0; /// \brief Retrieve the mangling number of a static local variable within /// this context. @@ -58,6 +55,6 @@ public: virtual unsigned getManglingNumber(const TagDecl *TD, unsigned MSLocalManglingNumber) = 0; }; - + } // end namespace clang #endif diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index 0b21b03..33fcce2 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -42,7 +42,8 @@ public: NSStr_stringWithUTF8String, NSStr_stringWithCStringEncoding, NSStr_stringWithCString, - NSStr_initWithString + NSStr_initWithString, + NSStr_initWithUTF8String }; static const unsigned NumNSStringMethods = 5; @@ -100,8 +101,8 @@ public: NSDict_objectForKey, NSMutableDict_setObjectForKey }; - static const unsigned NumNSDictionaryMethods = 11; - + static const unsigned NumNSDictionaryMethods = 12; + /// \brief The Objective-C NSDictionary selectors. Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; @@ -184,6 +185,9 @@ public: bool isObjCNSIntegerType(QualType T) const; /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. bool isObjCNSUIntegerType(QualType T) const; + /// \brief Returns one of NSIntegral typedef names if \param T is a typedef + /// of that name in objective-c. + StringRef GetNSIntegralKind(QualType T) const; private: bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const; diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index fc719bd..518f123 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -22,6 +22,7 @@ namespace clang { class ASTContext; +class CXXRecordDecl; class NamespaceAliasDecl; class NamespaceDecl; class IdentifierInfo; @@ -45,7 +46,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { /// \brief Enumeration describing enum StoredSpecifierKind { StoredIdentifier = 0, - StoredNamespaceOrAlias = 1, + StoredDecl = 1, StoredTypeSpec = 2, StoredTypeSpecWithTemplate = 3 }; @@ -83,7 +84,10 @@ public: /// stored as a Type*. TypeSpecWithTemplate, /// \brief The global specifier '::'. There is no stored value. - Global + Global, + /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of + /// the class it appeared in. + Super }; private: @@ -143,6 +147,11 @@ public: /// scope. static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); + /// \brief Returns the nested name specifier representing the __super scope + /// for the given CXXRecordDecl. + static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context, + CXXRecordDecl *RD); + /// \brief Return the prefix of this nested name specifier. /// /// The prefix contains all of the parts of the nested name @@ -172,6 +181,10 @@ public: /// specifier. NamespaceAliasDecl *getAsNamespaceAlias() const; + /// \brief Retrieve the record declaration stored in this nested name + /// specifier. + CXXRecordDecl *getAsRecordDecl() const; + /// \brief Retrieve the type stored in this nested name specifier. const Type *getAsType() const { if (Prefix.getInt() == StoredTypeSpec || @@ -421,7 +434,22 @@ public: /// \brief Turn this (empty) nested-name-specifier into the global /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); - + + /// \brief Turns this (empty) nested-name-specifier into '__super' + /// nested-name-specifier. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param RD The declaration of the class in which nested-name-specifier + /// appeared. + /// + /// \param SuperLoc The location of the '__super' keyword. + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, + SourceLocation SuperLoc, SourceLocation ColonColonLoc); /// \brief Make a new nested-name-specifier from incomplete source-location /// information. /// diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 3345959..0c3002c 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -61,7 +61,7 @@ public: ConstStmtRange children() const { return const_cast<OMPClause *>(this)->children(); } - static bool classof(const OMPClause *T) { return true; } + static bool classof(const OMPClause *) { return true; } }; /// \brief This represents clauses with the list of variables like 'private', @@ -135,10 +135,10 @@ public: /// \brief Fetches list of all variables in the clause. ArrayRef<const Expr *> getVarRefs() const { - return ArrayRef<const Expr *>( + return llvm::makeArrayRef( reinterpret_cast<const Expr *const *>( reinterpret_cast<const char *>(this) + - llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())), + llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<const Expr *>())), NumVars); } }; @@ -770,6 +770,153 @@ public: StmtRange children() { return StmtRange(); } }; +/// \brief This represents 'read' clause in the '#pragma omp atomic' directive. +/// +/// \code +/// #pragma omp atomic read +/// \endcode +/// In this example directive '#pragma omp atomic' has 'read' clause. +/// +class OMPReadClause : public OMPClause { +public: + /// \brief Build 'read' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_read, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_read; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'write' clause in the '#pragma omp atomic' directive. +/// +/// \code +/// #pragma omp atomic write +/// \endcode +/// In this example directive '#pragma omp atomic' has 'write' clause. +/// +class OMPWriteClause : public OMPClause { +public: + /// \brief Build 'write' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_write, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPWriteClause() + : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_write; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'update' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic update +/// \endcode +/// In this example directive '#pragma omp atomic' has 'update' clause. +/// +class OMPUpdateClause : public OMPClause { +public: + /// \brief Build 'update' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_update, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPUpdateClause() + : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_update; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'capture' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic capture +/// \endcode +/// In this example directive '#pragma omp atomic' has 'capture' clause. +/// +class OMPCaptureClause : public OMPClause { +public: + /// \brief Build 'capture' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_capture, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPCaptureClause() + : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_capture; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic seq_cst +/// \endcode +/// In this example directive '#pragma omp atomic' has 'seq_cst' clause. +/// +class OMPSeqCstClause : public OMPClause { +public: + /// \brief Build 'seq_cst' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPSeqCstClause() + : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_seq_cst; + } + + StmtRange children() { return StmtRange(); } +}; + /// \brief This represents clause 'private' in the '#pragma omp ...' directives. /// /// \code @@ -779,6 +926,7 @@ public: /// with the variables 'a' and 'b'. /// class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> { + friend class OMPClauseReader; /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -800,6 +948,20 @@ class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> { SourceLocation(), SourceLocation(), N) {} + /// \brief Sets the list of references to private copies with initializers for + /// new private variables. + /// \param VL List of references. + void setPrivateCopies(ArrayRef<Expr *> VL); + + /// \brief Gets the list of references to private copies with initializers for + /// new private variables. + MutableArrayRef<Expr *> getPrivateCopies() { + return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); + } + ArrayRef<const Expr *> getPrivateCopies() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + public: /// \brief Creates clause with a list of variables \a VL. /// @@ -808,10 +970,12 @@ public: /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. + /// \param PrivateVL List of references to private copies with initializers. /// static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL); + SourceLocation EndLoc, ArrayRef<Expr *> VL, + ArrayRef<Expr *> PrivateVL); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -819,6 +983,21 @@ public: /// static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); + typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; + typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; + typedef llvm::iterator_range<private_copies_iterator> private_copies_range; + typedef llvm::iterator_range<private_copies_const_iterator> + private_copies_const_range; + + private_copies_range private_copies() { + return private_copies_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + private_copies_const_range private_copies() const { + return private_copies_const_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + StmtRange children() { return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); @@ -839,6 +1018,8 @@ public: /// with the variables 'a' and 'b'. /// class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> { + friend class OMPClauseReader; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -859,6 +1040,33 @@ class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> { : OMPVarListClause<OMPFirstprivateClause>( OMPC_firstprivate, SourceLocation(), SourceLocation(), SourceLocation(), N) {} + /// \brief Sets the list of references to private copies with initializers for + /// new private variables. + /// \param VL List of references. + void setPrivateCopies(ArrayRef<Expr *> VL); + + /// \brief Gets the list of references to private copies with initializers for + /// new private variables. + MutableArrayRef<Expr *> getPrivateCopies() { + return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); + } + ArrayRef<const Expr *> getPrivateCopies() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + + /// \brief Sets the list of references to initializer variables for new + /// private variables. + /// \param VL List of references. + void setInits(ArrayRef<Expr *> VL); + + /// \brief Gets the list of references to initializer variables for new + /// private variables. + MutableArrayRef<Expr *> getInits() { + return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); + } + ArrayRef<const Expr *> getInits() const { + return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); + } public: /// \brief Creates clause with a list of variables \a VL. @@ -867,11 +1075,16 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. + /// \param VL List of references to the original variables. + /// \param PrivateVL List of references to private copies with initializers. + /// \param InitVL List of references to auto generated variables used for + /// initialization of a single array element. Used if firstprivate variable is + /// of array type. /// static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL); + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, + ArrayRef<Expr *> InitVL); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -879,6 +1092,33 @@ public: /// static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; + typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; + typedef llvm::iterator_range<private_copies_iterator> private_copies_range; + typedef llvm::iterator_range<private_copies_const_iterator> + private_copies_const_range; + + private_copies_range private_copies() { + return private_copies_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + private_copies_const_range private_copies() const { + return private_copies_const_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + + typedef MutableArrayRef<Expr *>::iterator inits_iterator; + typedef ArrayRef<const Expr *>::iterator inits_const_iterator; + typedef llvm::iterator_range<inits_iterator> inits_range; + typedef llvm::iterator_range<inits_const_iterator> inits_const_range; + + inits_range inits() { + return inits_range(getInits().begin(), getInits().end()); + } + inits_const_range inits() const { + return inits_const_range(getInits().begin(), getInits().end()); + } + StmtRange children() { return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); @@ -1390,13 +1630,17 @@ public: } }; -/// \brief This represents pseudo clause 'flush' for the '#pragma omp flush' +/// \brief This represents implicit clause 'flush' for the '#pragma omp flush' /// directive. +/// This clause does not exist by itself, it can be only as a part of 'omp +/// flush' directive. This clause is introduced to keep the original structure +/// of \a OMPExecutableDirective class and its derivatives and to use the +/// existing infrastructure of clauses with the list of variables. /// /// \code /// #pragma omp flush(a,b) /// \endcode -/// In this example directive '#pragma omp flush' has pseudo clause 'flush' +/// In this example directive '#pragma omp flush' has implicit clause 'flush' /// with the variables 'a' and 'b'. /// class OMPFlushClause : public OMPVarListClause<OMPFlushClause> { @@ -1453,3 +1697,4 @@ public: } // end namespace clang #endif + diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index aba88d6..e3f0126 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H -#define LLVM_CLANG_AST_OPERATION_KINDS_H +#ifndef LLVM_CLANG_AST_OPERATIONKINDS_H +#define LLVM_CLANG_AST_OPERATIONKINDS_H namespace clang { diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h index eece851..8945c41 100644 --- a/include/clang/AST/ParentMap.h +++ b/include/clang/AST/ParentMap.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARENTMAP_H -#define LLVM_CLANG_PARENTMAP_H +#ifndef LLVM_CLANG_AST_PARENTMAP_H +#define LLVM_CLANG_AST_PARENTMAP_H namespace clang { class Stmt; diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 349f4c4..35ceabb 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H -#define LLVM_CLANG_AST_PRETTY_PRINTER_H +#ifndef LLVM_CLANG_AST_PRETTYPRINTER_H +#define LLVM_CLANG_AST_PRETTYPRINTER_H #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 8ba85c4..2e005dd 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H -#define LLVM_CLANG_AST_RAW_COMMENT_LIST_H +#ifndef LLVM_CLANG_AST_RAWCOMMENTLIST_H +#define LLVM_CLANG_AST_RAWCOMMENTLIST_H #include "clang/Basic/CommentOptions.h" #include "clang/Basic/SourceManager.h" diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 4befb45..7b77998 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_LAYOUTINFO_H -#define LLVM_CLANG_AST_LAYOUTINFO_H +#ifndef LLVM_CLANG_AST_RECORDLAYOUT_H +#define LLVM_CLANG_AST_RECORDLAYOUT_H #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index ff46ffb..a1d3618 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -429,6 +429,7 @@ private: bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); + bool TraverseOMPLoopDirective(OMPLoopDirective *S); bool TraverseOMPClause(OMPClause *C); #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); #include "clang/Basic/OpenMPKinds.def" @@ -689,6 +690,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -713,6 +715,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -940,6 +943,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) @@ -1148,6 +1154,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) @@ -2144,21 +2153,29 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { TRY_TO(TraverseLambdaCapture(S, C)); } - if (S->hasExplicitParameters() || S->hasExplicitResultType()) { - TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - if (S->hasExplicitParameters() && S->hasExplicitResultType()) { - // Visit the whole type. - TRY_TO(TraverseTypeLoc(TL)); - } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { - if (S->hasExplicitParameters()) { - // Visit parameters. - for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { - TRY_TO(TraverseDecl(Proto.getParam(I))); - } - } else { - TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>(); + + if (S->hasExplicitParameters() && S->hasExplicitResultType()) { + // Visit the whole type. + TRY_TO(TraverseTypeLoc(TL)); + } else { + if (S->hasExplicitParameters()) { + // Visit parameters. + for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { + TRY_TO(TraverseDecl(Proto.getParam(I))); } + } else if (S->hasExplicitResultType()) { + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + } + + auto *T = Proto.getTypePtr(); + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); } TRY_TO(TraverseLambdaBody(S)); @@ -2259,6 +2276,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) +DEF_TRAVERSE_STMT(TypoExpr, {}) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) // These operators (all of them) do not need any action except @@ -2275,6 +2293,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) +DEF_TRAVERSE_STMT(CXXFoldExpr, {}) DEF_TRAVERSE_STMT(AtomicExpr, {}) // These literals (all of them) do not need any action. @@ -2301,6 +2320,12 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( return true; } +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { + return TraverseOMPExecutableDirective(S); +} + DEF_TRAVERSE_STMT(OMPParallelDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2310,6 +2335,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective, DEF_TRAVERSE_STMT(OMPForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2330,6 +2358,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, { DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2348,6 +2379,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPOrderedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPAtomicDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTeamsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { @@ -2437,6 +2480,31 @@ RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -2448,6 +2516,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } return true; } @@ -2455,6 +2526,12 @@ template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( OMPFirstprivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->inits()) { + TRY_TO(TraverseStmt(E)); + } return true; } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index fb94097..eb6836f 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -212,7 +212,7 @@ protected: unsigned HasTemplateKWAndArgsInfo : 1; unsigned HasFoundDecl : 1; unsigned HadMultipleCandidates : 1; - unsigned RefersToEnclosingLocal : 1; + unsigned RefersToEnclosingVariableOrCapture : 1; }; class CastExprBitfields { @@ -393,6 +393,10 @@ public: /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes. Stmt *IgnoreImplicit(); + /// \brief Skip no-op (attributed, compound) container stmts and skip captured + /// stmt at the top, if \a IgnoreCaptured is true. + Stmt *IgnoreContainers(bool IgnoreCaptured = false); + const Stmt *stripLabelLikeStatements() const; Stmt *stripLabelLikeStatements() { return const_cast<Stmt*>( @@ -548,14 +552,17 @@ public: /// class CompoundStmt : public Stmt { Stmt** Body; - SourceLocation LBracLoc, RBracLoc; + SourceLocation LBraceLoc, RBraceLoc; + + friend class ASTStmtReader; + public: CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, SourceLocation LB, SourceLocation RB); // \brief Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), Body(nullptr), LBracLoc(Loc), RBracLoc(Loc) { + : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) { CompoundStmtBits.NumStmts = 0; } @@ -614,13 +621,11 @@ public: return const_reverse_body_iterator(body_begin()); } - SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; } + SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; } - SourceLocation getLBracLoc() const { return LBracLoc; } - void setLBracLoc(SourceLocation L) { LBracLoc = L; } - SourceLocation getRBracLoc() const { return RBracLoc; } - void setRBracLoc(SourceLocation L) { RBracLoc = L; } + SourceLocation getLBracLoc() const { return LBraceLoc; } + SourceLocation getRBracLoc() const { return RBraceLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CompoundStmtClass; @@ -846,7 +851,7 @@ public: SourceLocation getAttrLoc() const { return AttrLoc; } ArrayRef<const Attr*> getAttrs() const { - return ArrayRef<const Attr*>(getAttrArrayPtr(), NumAttrs); + return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs); } Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -1010,7 +1015,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; } SourceLocation getLocEnd() const LLVM_READONLY { - return SubExprs[BODY]->getLocEnd(); + return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd(); } // Iterators @@ -1580,18 +1585,21 @@ public: Kind MyKind; std::string Str; unsigned OperandNo; + + // Source range for operand references. + CharSourceRange Range; public: AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} - AsmStringPiece(unsigned OpNo, char Modifier) - : MyKind(Operand), Str(), OperandNo(OpNo) { - Str += Modifier; + AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin, + SourceLocation End) + : MyKind(Operand), Str(S), OperandNo(OpNo), + Range(CharSourceRange::getCharRange(Begin, End)) { } bool isString() const { return MyKind == String; } bool isOperand() const { return MyKind == Operand; } const std::string &getString() const { - assert(isString()); return Str; } @@ -1600,12 +1608,14 @@ public: return OperandNo; } + CharSourceRange getRange() const { + assert(isOperand() && "Range is currently used only for Operands."); + return Range; + } + /// getModifier - Get the modifier for this operand, if present. This /// returns '\0' if there was no modifier. - char getModifier() const { - assert(isOperand()); - return Str[0]; - } + char getModifier() const; }; /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing @@ -1780,14 +1790,14 @@ public: //===--- Other ---===// ArrayRef<StringRef> getAllConstraints() const { - return ArrayRef<StringRef>(Constraints, NumInputs + NumOutputs); + return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs); } ArrayRef<StringRef> getClobbers() const { - return ArrayRef<StringRef>(Clobbers, NumClobbers); + return llvm::makeArrayRef(Clobbers, NumClobbers); } ArrayRef<Expr*> getAllExprs() const { - return ArrayRef<Expr*>(reinterpret_cast<Expr**>(Exprs), - NumInputs + NumOutputs); + return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs), + NumInputs + NumOutputs); } StringRef getClobber(unsigned i) const { return getClobbers()[i]; } @@ -1892,24 +1902,22 @@ class SEHTryStmt : public Stmt { bool IsCXXTry; SourceLocation TryLoc; Stmt *Children[2]; - int HandlerIndex; - int HandlerParentIndex; enum { TRY = 0, HANDLER = 1 }; SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try' - SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler, - int HandlerIndex, int HandlerParentIndex); + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); friend class ASTReader; friend class ASTStmtReader; explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } public: - static SEHTryStmt *Create(const ASTContext &C, bool isCXXTry, + static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry, SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler, int HandlerIndex, - int HandlerParentIndex); + Stmt *Handler); SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } @@ -1936,9 +1944,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHTryStmtClass; } - - int getHandlerIndex() const { return HandlerIndex; } - int getHandlerParentIndex() const { return HandlerParentIndex; } }; /// Represents a __leave statement. @@ -1977,15 +1982,18 @@ public: /// @endcode class CapturedStmt : public Stmt { public: - /// \brief The different capture forms: by 'this' or by reference, etc. + /// \brief The different capture forms: by 'this', by reference, capture for + /// variable-length array type etc. enum VariableCaptureKind { VCK_This, - VCK_ByRef + VCK_ByRef, + VCK_VLAType, }; - /// \brief Describes the capture of either a variable or 'this'. + /// \brief Describes the capture of either a variable, or 'this', or + /// variable-length array type. class Capture { - llvm::PointerIntPair<VarDecl *, 1, VariableCaptureKind> VarAndKind; + llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind; SourceLocation Loc; public: @@ -2007,6 +2015,10 @@ public: case VCK_ByRef: assert(Var && "capturing by reference must have a variable!"); break; + case VCK_VLAType: + assert(!Var && + "Variable-length array type capture cannot have a variable!"); + break; } } @@ -2021,13 +2033,20 @@ public: bool capturesThis() const { return getCaptureKind() == VCK_This; } /// \brief Determine whether this capture handles a variable. - bool capturesVariable() const { return getCaptureKind() != VCK_This; } + bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; } + + /// \brief Determine whether this capture handles a variable-length array + /// type. + bool capturesVariableArrayType() const { + return getCaptureKind() == VCK_VLAType; + } /// \brief Retrieve the declaration of the variable being captured. /// - /// This operation is only valid if this capture does not capture 'this'. + /// This operation is only valid if this capture captures a variable. VarDecl *getCapturedVar() const { - assert(!capturesThis() && "No variable available for 'this' capture"); + assert(capturesVariable() && + "No variable available for 'this' or VAT capture"); return VarAndKind.getPointer(); } friend class ASTStmtReader; diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h index a3e9e1e..ab636a5 100644 --- a/include/clang/AST/StmtGraphTraits.h +++ b/include/clang/AST/StmtGraphTraits.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H -#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H +#ifndef LLVM_CLANG_AST_STMTGRAPHTRAITS_H +#define LLVM_CLANG_AST_STMTGRAPHTRAITS_H #include "clang/AST/Stmt.h" #include "llvm/ADT/DepthFirstIterator.h" diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 18c5516..6ffe74f 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_STMT_ITR_H -#define LLVM_CLANG_AST_STMT_ITR_H +#ifndef LLVM_CLANG_AST_STMTITERATOR_H +#define LLVM_CLANG_AST_STMTITERATOR_H #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index db02afe0..aed7691 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -128,6 +128,13 @@ public: operator bool() { return Current != End; } }; + /// \brief Gets a single clause of the specified kind \a K associated with the + /// current directive iff there is only one clause of this kind (and assertion + /// is fired if there is more than one clause is associated with the + /// directive). Returns nullptr if no clause of kind \a K is associated with + /// the directive. + const OMPClause *getSingleClause(OpenMPClauseKind K) const; + /// \brief Returns starting location of directive kind. SourceLocation getLocStart() const { return StartLoc; } /// \brief Returns ending location of directive. @@ -238,6 +245,353 @@ public: } }; +/// \brief This is a common base class for loop directives ('omp simd', 'omp +/// for', 'omp for simd' etc.). It is responsible for the loop code generation. +/// +class OMPLoopDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Number of collapsed loops as specified by 'collapse' clause. + unsigned CollapsedNum; + + /// \brief Offsets to the stored exprs. + /// This enumeration contains offsets to all the pointers to children + /// expressions stored in OMPLoopDirective. + /// The first 9 children are nesessary for all the loop directives, and + /// the next 7 are specific to the worksharing ones. + /// After the fixed children, three arrays of length CollapsedNum are + /// allocated: loop counters, their updates and final values. + /// + enum { + AssociatedStmtOffset = 0, + IterationVariableOffset = 1, + LastIterationOffset = 2, + CalcLastIterationOffset = 3, + PreConditionOffset = 4, + CondOffset = 5, + SeparatedCondOffset = 6, + InitOffset = 7, + IncOffset = 8, + // The '...End' enumerators do not correspond to child expressions - they + // specify the offset to the end (and start of the following counters/ + // updates/finals arrays). + DefaultEnd = 9, + // The following 7 exprs are used by worksharing loops only. + IsLastIterVariableOffset = 9, + LowerBoundVariableOffset = 10, + UpperBoundVariableOffset = 11, + StrideVariableOffset = 12, + EnsureUpperBoundOffset = 13, + NextLowerBoundOffset = 14, + NextUpperBoundOffset = 15, + // Offset to the end (and start of the following counters/updates/finals + // arrays) for worksharing loop directives. + WorksharingEnd = 16, + }; + + /// \brief Get the counters storage. + MutableArrayRef<Expr *> getCounters() { + Expr **Storage = reinterpret_cast<Expr **>( + &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind()))))); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// \brief Get the updates storage. + MutableArrayRef<Expr *> getUpdates() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// \brief Get the final counter updates storage. + MutableArrayRef<Expr *> getFinals() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + +protected: + /// \brief Build instance of loop directive of class \a Kind. + /// + /// \param SC Statement class. + /// \param Kind Kind of OpenMP directive. + /// \param StartLoc Starting location of the directive (directive keyword). + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed loops from 'collapse' clause. + /// \param NumClauses Number of clauses. + /// \param NumSpecialChildren Number of additional directive-specific stmts. + /// + template <typename T> + OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind, + SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses, + unsigned NumSpecialChildren = 0) + : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses, + numLoopChildren(CollapsedNum, Kind) + + NumSpecialChildren), + CollapsedNum(CollapsedNum) {} + + /// \brief Offset to the start of children expression arrays. + static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { + return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd + : DefaultEnd; + } + + /// \brief Children number. + static unsigned numLoopChildren(unsigned CollapsedNum, + OpenMPDirectiveKind Kind) { + return getArraysOffset(Kind) + + 3 * CollapsedNum; // Counters, Updates and Finals + } + + void setIterationVariable(Expr *IV) { + *std::next(child_begin(), IterationVariableOffset) = IV; + } + void setLastIteration(Expr *LI) { + *std::next(child_begin(), LastIterationOffset) = LI; + } + void setCalcLastIteration(Expr *CLI) { + *std::next(child_begin(), CalcLastIterationOffset) = CLI; + } + void setPreCond(Expr *PC) { + *std::next(child_begin(), PreConditionOffset) = PC; + } + void setCond(Expr *Cond, Expr *SeparatedCond) { + *std::next(child_begin(), CondOffset) = Cond; + *std::next(child_begin(), SeparatedCondOffset) = SeparatedCond; + } + void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; } + void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; } + void setIsLastIterVariable(Expr *IL) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), IsLastIterVariableOffset) = IL; + } + void setLowerBoundVariable(Expr *LB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), LowerBoundVariableOffset) = LB; + } + void setUpperBoundVariable(Expr *UB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), UpperBoundVariableOffset) = UB; + } + void setStrideVariable(Expr *ST) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), StrideVariableOffset) = ST; + } + void setEnsureUpperBound(Expr *EUB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), EnsureUpperBoundOffset) = EUB; + } + void setNextLowerBound(Expr *NLB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), NextLowerBoundOffset) = NLB; + } + void setNextUpperBound(Expr *NUB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), NextUpperBoundOffset) = NUB; + } + void setCounters(ArrayRef<Expr *> A); + void setUpdates(ArrayRef<Expr *> A); + void setFinals(ArrayRef<Expr *> A); + +public: + /// \brief The expressions built for the OpenMP loop CodeGen for the + /// whole collapsed loop nest. + struct HelperExprs { + /// \brief Loop iteration variable. + Expr *IterationVarRef; + /// \brief Loop last iteration number. + Expr *LastIteration; + /// \brief Calculation of last iteration. + Expr *CalcLastIteration; + /// \brief Loop pre-condition. + Expr *PreCond; + /// \brief Loop condition. + Expr *Cond; + /// \brief A condition with 1 iteration separated. + Expr *SeparatedCond; + /// \brief Loop iteration variable init. + Expr *Init; + /// \brief Loop increment. + Expr *Inc; + /// \brief IsLastIteration - local flag variable passed to runtime. + Expr *IL; + /// \brief LowerBound - local variable passed to runtime. + Expr *LB; + /// \brief UpperBound - local variable passed to runtime. + Expr *UB; + /// \brief Stride - local variable passed to runtime. + Expr *ST; + /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations). + Expr *EUB; + /// \brief Update of LowerBound for statically sheduled 'omp for' loops. + Expr *NLB; + /// \brief Update of UpperBound for statically sheduled 'omp for' loops. + Expr *NUB; + /// \brief Counters Loop counters. + SmallVector<Expr *, 4> Counters; + /// \brief Expressions for loop counters update for CodeGen. + SmallVector<Expr *, 4> Updates; + /// \brief Final loop counter values for GodeGen. + SmallVector<Expr *, 4> Finals; + + /// \brief Check if all the expressions are built (does not check the + /// worksharing ones). + bool builtAll() { + return IterationVarRef != nullptr && LastIteration != nullptr && + PreCond != nullptr && Cond != nullptr && + SeparatedCond != nullptr && Init != nullptr && Inc != nullptr; + } + + /// \brief Initialize all the fields to null. + /// \param Size Number of elements in the counters/finals/updates arrays. + void clear(unsigned Size) { + IterationVarRef = nullptr; + LastIteration = nullptr; + CalcLastIteration = nullptr; + PreCond = nullptr; + Cond = nullptr; + SeparatedCond = nullptr; + Init = nullptr; + Inc = nullptr; + IL = nullptr; + LB = nullptr; + UB = nullptr; + ST = nullptr; + EUB = nullptr; + NLB = nullptr; + NUB = nullptr; + Counters.resize(Size); + Updates.resize(Size); + Finals.resize(Size); + for (unsigned i = 0; i < Size; ++i) { + Counters[i] = nullptr; + Updates[i] = nullptr; + Finals[i] = nullptr; + } + } + }; + + /// \brief Get number of collapsed loops. + unsigned getCollapsedNumber() const { return CollapsedNum; } + + Expr *getIterationVariable() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), IterationVariableOffset))); + } + Expr *getLastIteration() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), LastIterationOffset))); + } + Expr *getCalcLastIteration() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CalcLastIterationOffset))); + } + Expr *getPreCond() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), PreConditionOffset))); + } + Expr *getCond(bool SeparateIter) const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), + (SeparateIter ? SeparatedCondOffset : CondOffset)))); + } + Expr *getInit() const { + return const_cast<Expr *>( + reinterpret_cast<const Expr *>(*std::next(child_begin(), InitOffset))); + } + Expr *getInc() const { + return const_cast<Expr *>( + reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset))); + } + Expr *getIsLastIterVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), IsLastIterVariableOffset))); + } + Expr *getLowerBoundVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), LowerBoundVariableOffset))); + } + Expr *getUpperBoundVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), UpperBoundVariableOffset))); + } + Expr *getStrideVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), StrideVariableOffset))); + } + Expr *getEnsureUpperBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), EnsureUpperBoundOffset))); + } + Expr *getNextLowerBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), NextLowerBoundOffset))); + } + Expr *getNextUpperBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), NextUpperBoundOffset))); + } + const Stmt *getBody() const { + // This relies on the loop form is already checked by Sema. + Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); + Body = cast<ForStmt>(Body)->getBody(); + for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { + Body = Body->IgnoreContainers(); + Body = cast<ForStmt>(Body)->getBody(); + } + return Body; + } + + ArrayRef<Expr *> counters() { return getCounters(); } + + ArrayRef<Expr *> counters() const { + return const_cast<OMPLoopDirective *>(this)->getCounters(); + } + + ArrayRef<Expr *> updates() { return getUpdates(); } + + ArrayRef<Expr *> updates() const { + return const_cast<OMPLoopDirective *>(this)->getUpdates(); + } + + ArrayRef<Expr *> finals() { return getFinals(); } + + ArrayRef<Expr *> finals() const { + return const_cast<OMPLoopDirective *>(this)->getFinals(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPSimdDirectiveClass || + T->getStmtClass() == OMPForDirectiveClass || + T->getStmtClass() == OMPForSimdDirectiveClass || + T->getStmtClass() == OMPParallelForDirectiveClass || + T->getStmtClass() == OMPParallelForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp simd' directive. /// /// \code @@ -247,10 +601,8 @@ public: /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. /// -class OMPSimdDirective : public OMPExecutableDirective { +class OMPSimdDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -260,9 +612,8 @@ class OMPSimdDirective : public OMPExecutableDirective { /// OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, - EndLoc, NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, + EndLoc, CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -270,10 +621,9 @@ class OMPSimdDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, - SourceLocation(), SourceLocation(), NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -284,11 +634,13 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. /// static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, + const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -300,8 +652,6 @@ public: static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPSimdDirectiveClass; } @@ -316,10 +666,8 @@ public: /// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c' /// and 'd'. /// -class OMPForDirective : public OMPExecutableDirective { +class OMPForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -329,9 +677,8 @@ class OMPForDirective : public OMPExecutableDirective { /// OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, - EndLoc, NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -339,10 +686,8 @@ class OMPForDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, - SourceLocation(), SourceLocation(), NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -353,11 +698,13 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. /// static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, + const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -369,13 +716,76 @@ public: static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPForDirectiveClass; } }; +/// \brief This represents '#pragma omp for simd' directive. +/// +/// \code +/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp for simd' has clauses 'private' +/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and +/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. +/// +class OMPForSimdDirective : public OMPLoopDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, + StartLoc, EndLoc, CollapsedNum, NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPForSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp sections' directive. /// /// \code @@ -657,10 +1067,8 @@ public: /// with the variables 'a' and 'b' and 'reduction' with operator '+' and /// variables 'c' and 'd'. /// -class OMPParallelForDirective : public OMPExecutableDirective { +class OMPParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -670,10 +1078,8 @@ class OMPParallelForDirective : public OMPExecutableDirective { /// OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelForDirectiveClass, - OMPD_parallel_for, StartLoc, EndLoc, NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, + StartLoc, EndLoc, CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -681,10 +1087,9 @@ class OMPParallelForDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelForDirectiveClass, - OMPD_parallel_for, SourceLocation(), - SourceLocation(), NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -695,11 +1100,12 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. /// static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -713,13 +1119,80 @@ public: unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelForDirectiveClass; } }; +/// \brief This represents '#pragma omp parallel for simd' directive. +/// +/// \code +/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp parallel for simd' has clauses +/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j' +/// and linear step 's', 'reduction' with operator '+' and variables 'c' and +/// 'd'. +/// +class OMPParallelForSimdDirective : public OMPLoopDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, + OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum, + NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPParallelForSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, + OMPD_parallel_for_simd, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPParallelForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp parallel sections' directive. /// /// \code @@ -1028,6 +1501,253 @@ public: } }; +/// \brief This represents '#pragma omp ordered' directive. +/// +/// \code +/// #pragma omp ordered +/// \endcode +/// +class OMPOrderedDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPOrderedDirective() + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPOrderedDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPOrderedDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp atomic' directive. +/// +/// \code +/// #pragma omp atomic capture +/// \endcode +/// In this example directive '#pragma omp atomic' has clause 'capture'. +/// +class OMPAtomicDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, + StartLoc, EndLoc, NumClauses, 4) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPAtomicDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, + SourceLocation(), SourceLocation(), NumClauses, + 4) {} + + /// \brief Set 'x' part of the associated expression/statement. + void setX(Expr *X) { *std::next(child_begin()) = X; } + /// \brief Set 'v' part of the associated expression/statement. + void setV(Expr *V) { *std::next(child_begin(), 2) = V; } + /// \brief Set 'expr' part of the associated expression/statement. + void setExpr(Expr *E) { *std::next(child_begin(), 3) = E; } + +public: + /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' + /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for + /// detailed description of 'x', 'v' and 'expr'). + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param X 'x' part of the associated expression/statement. + /// \param V 'v' part of the associated expression/statement. + /// \param E 'expr' part of the associated expression/statement. + /// + static OMPAtomicDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, + Expr *E); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPAtomicDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + /// \brief Get 'x' part of the associated expression/statement. + Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); } + const Expr *getX() const { + return cast_or_null<Expr>(*std::next(child_begin())); + } + /// \brief Get 'v' part of the associated expression/statement. + Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 2)); } + const Expr *getV() const { + return cast_or_null<Expr>(*std::next(child_begin(), 2)); + } + /// \brief Get 'expr' part of the associated expression/statement. + Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); } + const Expr *getExpr() const { + return cast_or_null<Expr>(*std::next(child_begin(), 3)); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPAtomicDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp target' directive. +/// +/// \code +/// #pragma omp target if(a) +/// \endcode +/// In this example directive '#pragma omp target' has clause 'if' with +/// condition 'a'. +/// +class OMPTargetDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + StartLoc, EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTargetDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPTargetDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp teams' directive. +/// +/// \code +/// #pragma omp teams if(a) +/// \endcode +/// In this example directive '#pragma omp teams' has clause 'if' with +/// condition 'a'. +/// +class OMPTeamsDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, + StartLoc, EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTeamsDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPTeamsDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTeamsDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 1026a78..80b68bc 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -18,8 +18,8 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -76,7 +76,7 @@ private: struct DA { unsigned Kind; - bool ForRefParam; + void *QT; ValueDecl *D; }; struct I { @@ -132,11 +132,11 @@ public: /// \brief Construct a template argument that refers to a /// declaration, which is either an external declaration or a /// template declaration. - TemplateArgument(ValueDecl *D, bool ForRefParam) { + TemplateArgument(ValueDecl *D, QualType QT) { assert(D && "Expected decl"); DeclArg.Kind = Declaration; + DeclArg.QT = QT.getAsOpaquePtr(); DeclArg.D = D; - DeclArg.ForRefParam = ForRefParam; } /// \brief Construct an integral constant template argument. The memory to @@ -249,11 +249,9 @@ public: return DeclArg.D; } - /// \brief Retrieve whether a declaration is binding to a - /// reference parameter in a declaration non-type template argument. - bool isDeclForReferenceParam() const { + QualType getParamTypeForDecl() const { assert(getKind() == Declaration && "Unexpected kind"); - return DeclArg.ForRefParam; + return QualType::getFromOpaquePtr(DeclArg.QT); } /// \brief Retrieve the type for null non-type template argument. @@ -344,7 +342,7 @@ public: /// \brief Return the array of arguments in this template argument pack. ArrayRef<TemplateArgument> getPackAsArray() const { assert(getKind() == Pack); - return ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs); + return llvm::makeArrayRef(Args.Args, Args.NumArgs); } /// \brief Determines whether two template arguments are superficially the diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 09862e4..1bda01f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -16,6 +16,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/LLVM.h" @@ -25,11 +26,11 @@ #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" namespace clang { @@ -400,21 +401,36 @@ public: Mask |= qs.Mask; } + /// \brief Returns true if this address space is a superset of the other one. + /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of + /// overlapping address spaces. + /// CL1.1 or CL1.2: + /// every address space is a superset of itself. + /// CL2.0 adds: + /// __generic is a superset of any address space except for __constant. + bool isAddressSpaceSupersetOf(Qualifiers other) const { + return + // Address spaces must match exactly. + getAddressSpace() == other.getAddressSpace() || + // Otherwise in OpenCLC v2.0 s6.5.5: every address space except + // for __constant can be used as __generic. + (getAddressSpace() == LangAS::opencl_generic && + other.getAddressSpace() != LangAS::opencl_constant); + } + /// \brief Determines if these qualifiers compatibly include another set. /// Generally this answers the question of whether an object with the other /// qualifiers can be safely used as an object with these qualifiers. bool compatiblyIncludes(Qualifiers other) const { - return - // Address spaces must match exactly. - getAddressSpace() == other.getAddressSpace() && - // ObjC GC qualifiers can match, be added, or be removed, but can't be - // changed. - (getObjCGCAttr() == other.getObjCGCAttr() || - !hasObjCGCAttr() || !other.hasObjCGCAttr()) && - // ObjC lifetime qualifiers must match exactly. - getObjCLifetime() == other.getObjCLifetime() && - // CVR qualifiers may subset. - (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); + return isAddressSpaceSupersetOf(other) && + // ObjC GC qualifiers can match, be added, or be removed, but can't + // be changed. + (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || + !other.hasObjCGCAttr()) && + // ObjC lifetime qualifiers must match exactly. + getObjCLifetime() == other.getObjCLifetime() && + // CVR qualifiers may subset. + (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); } /// \brief Determines if these qualifiers compatibly include another set of @@ -1245,6 +1261,7 @@ protected: class FunctionTypeBitfields { friend class FunctionType; + friend class FunctionProtoType; unsigned : NumTypeBits; @@ -1259,6 +1276,11 @@ protected: /// C++ 8.3.5p4: The return type, the parameter type list and the /// cv-qualifier-seq, [...], are part of the function type. unsigned TypeQuals : 3; + + /// \brief The ref-qualifier associated with a \c FunctionProtoType. + /// + /// This is a value of type \c RefQualifierKind. + unsigned RefQualifier : 2; }; class ObjCObjectTypeBitfields { @@ -1685,6 +1707,11 @@ public: /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; + /// \brief Retrieves the TagDecl that this type refers to, either + /// because the type is a TagType or because it is the injected-class-name + /// type of a class template or class template partial specialization. + TagDecl *getAsTagDecl() const; + /// If this is a pointer or reference to a RecordType, return the /// CXXRecordDecl that that type refers to. /// @@ -1982,6 +2009,22 @@ public: QualType getPointeeType() const { return PointeeType; } + /// \brief Returns true if address spaces of pointers overlap. + /// OpenCL v2.0 defines conversion rules for pointers to different + /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping + /// address spaces. + /// CL1.1 or CL1.2: + /// address spaces overlap iff they are they same. + /// CL2.0 adds: + /// __generic overlaps with any address space except for __constant. + bool isAddressSpaceOverlapping(const PointerType &other) const { + Qualifiers thisQuals = PointeeType.getQualifiers(); + Qualifiers otherQuals = other.getPointeeType().getQualifiers(); + // Address spaces overlap if at least one of them is a superset of another + return thisQuals.isAddressSpaceSupersetOf(otherQuals) || + otherQuals.isAddressSpaceSupersetOf(thisQuals); + } + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2765,7 +2808,7 @@ class FunctionType : public Type { protected: FunctionType(TypeClass tc, QualType res, - unsigned typeQuals, QualType Canonical, bool Dependent, + QualType Canonical, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) @@ -2773,7 +2816,6 @@ protected: ContainsUnexpandedParameterPack), ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; - FunctionTypeBits.TypeQuals = typeQuals; } unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } @@ -2810,7 +2852,7 @@ public: /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) - : FunctionType(FunctionNoProto, Result, 0, Canonical, + : FunctionType(FunctionNoProto, Result, Canonical, /*Dependent=*/false, /*InstantiationDependent=*/false, Result->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false, Info) {} @@ -2844,33 +2886,51 @@ public: /// type. class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { public: + struct ExceptionSpecInfo { + ExceptionSpecInfo() + : Type(EST_None), NoexceptExpr(nullptr), + SourceDecl(nullptr), SourceTemplate(nullptr) {} + + ExceptionSpecInfo(ExceptionSpecificationType EST) + : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr), + SourceTemplate(nullptr) {} + + /// The kind of exception specification this is. + ExceptionSpecificationType Type; + /// Explicitly-specified list of exception types. + ArrayRef<QualType> Exceptions; + /// Noexcept expression, if this is EST_ComputedNoexcept. + Expr *NoexceptExpr; + /// The function whose exception specification this is, for + /// EST_Unevaluated and EST_Uninstantiated. + FunctionDecl *SourceDecl; + /// The function template whose exception specification this is instantiated + /// from, for EST_Uninstantiated. + FunctionDecl *SourceTemplate; + }; + /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(nullptr), NoexceptExpr(nullptr), - ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), - ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ConsumedParameters(nullptr) {} ExtProtoInfo(CallingConv CC) : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(nullptr), NoexceptExpr(nullptr), - ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), - ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ConsumedParameters(nullptr) {} + + ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) { + ExtProtoInfo Result(*this); + Result.ExceptionSpec = O; + return Result; + } FunctionType::ExtInfo ExtInfo; bool Variadic : 1; bool HasTrailingReturn : 1; unsigned char TypeQuals; - ExceptionSpecificationType ExceptionSpecType; RefQualifierKind RefQualifier; - unsigned NumExceptions; - const QualType *Exceptions; - Expr *NoexceptExpr; - FunctionDecl *ExceptionSpecDecl; - FunctionDecl *ExceptionSpecTemplate; + ExceptionSpecInfo ExceptionSpec; const bool *ConsumedParameters; }; @@ -2896,7 +2956,7 @@ private: unsigned NumExceptions : 9; /// ExceptionSpecType - The type of exception specification this function has. - unsigned ExceptionSpecType : 3; + unsigned ExceptionSpecType : 4; /// HasAnyConsumedParams - Whether this function has any consumed parameters. unsigned HasAnyConsumedParams : 1; @@ -2907,11 +2967,6 @@ private: /// HasTrailingReturn - Whether this function has a trailing return type. unsigned HasTrailingReturn : 1; - /// \brief The ref-qualifier associated with a \c FunctionProtoType. - /// - /// This is a value of type \c RefQualifierKind. - unsigned RefQualifier : 2; - // ParamInfo - There is an variable size array after the class in memory that // holds the parameter types. @@ -2952,7 +3007,7 @@ public: return param_type_begin()[i]; } ArrayRef<QualType> getParamTypes() const { - return ArrayRef<QualType>(param_type_begin(), param_type_end()); + return llvm::makeArrayRef(param_type_begin(), param_type_end()); } ExtProtoInfo getExtProtoInfo() const { @@ -2960,19 +3015,18 @@ public: EPI.ExtInfo = getExtInfo(); EPI.Variadic = isVariadic(); EPI.HasTrailingReturn = hasTrailingReturn(); - EPI.ExceptionSpecType = getExceptionSpecType(); + EPI.ExceptionSpec.Type = getExceptionSpecType(); EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); - if (EPI.ExceptionSpecType == EST_Dynamic) { - EPI.NumExceptions = NumExceptions; - EPI.Exceptions = exception_begin(); - } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { - EPI.NoexceptExpr = getNoexceptExpr(); - } else if (EPI.ExceptionSpecType == EST_Uninstantiated) { - EPI.ExceptionSpecDecl = getExceptionSpecDecl(); - EPI.ExceptionSpecTemplate = getExceptionSpecTemplate(); - } else if (EPI.ExceptionSpecType == EST_Unevaluated) { - EPI.ExceptionSpecDecl = getExceptionSpecDecl(); + if (EPI.ExceptionSpec.Type == EST_Dynamic) { + EPI.ExceptionSpec.Exceptions = exceptions(); + } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { + EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr(); + } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { + EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); + EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate(); + } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { + EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); } if (hasAnyConsumedParams()) EPI.ConsumedParameters = getConsumedParamsBuffer(); @@ -2995,6 +3049,8 @@ public: bool hasNoexceptExceptionSpec() const { return isNoexceptExceptionSpec(getExceptionSpecType()); } + /// \brief Return whether this function has a dependent exception spec. + bool hasDependentExceptionSpec() const; /// \brief Result type of getNoexceptSpec(). enum NoexceptResult { NR_NoNoexcept, ///< There is no noexcept specifier. @@ -3057,7 +3113,7 @@ public: /// \brief Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { - return static_cast<RefQualifierKind>(RefQualifier); + return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); } typedef const QualType *param_type_iterator; @@ -3074,10 +3130,9 @@ public: } typedef const QualType *exception_iterator; - typedef llvm::iterator_range<exception_iterator> exception_range; - exception_range exceptions() const { - return exception_range(exception_begin(), exception_end()); + ArrayRef<QualType> exceptions() const { + return llvm::makeArrayRef(exception_begin(), exception_end()); } exception_iterator exception_begin() const { // exceptions begin where arguments end @@ -3416,6 +3471,7 @@ public: attr_stdcall, attr_thiscall, attr_pascal, + attr_vectorcall, attr_pnaclcall, attr_inteloclbicc, attr_ms_abi, @@ -5231,8 +5287,8 @@ template <typename T> const T *Type::castAs() const { ArrayType_cannot_be_used_with_getAs<T> at; (void) at; - assert(isa<T>(CanonicalType)); if (const T *ty = dyn_cast<T>(this)) return ty; + assert(isa<T>(CanonicalType)); return cast<T>(getUnqualifiedDesugaredType()); } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 3648d2a..4f3c811 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1208,7 +1208,7 @@ public: } ArrayRef<ParmVarDecl *> getParams() const { - return ArrayRef<ParmVarDecl *>(getParmArray(), getNumParams()); + return llvm::makeArrayRef(getParmArray(), getNumParams()); } // ParmVarDecls* are stored after Info, one for each parameter. @@ -1567,6 +1567,8 @@ public: void setUnderlyingTInfo(TypeSourceInfo* TI) const { this->getLocalData()->UnderlyingTInfo = TI; } + + void initializeLocal(ASTContext &Context, SourceLocation Loc); }; // FIXME: location of the 'decltype' and parens. diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 9c9f15e..392e544 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -16,8 +16,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TYPE_ORDERING_H -#define LLVM_CLANG_TYPE_ORDERING_H +#ifndef LLVM_CLANG_AST_TYPEORDERING_H +#define LLVM_CLANG_AST_TYPEORDERING_H #include "clang/AST/CanonicalType.h" #include "clang/AST/Type.h" diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 2ef5800..a11f22d 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -98,7 +98,7 @@ class UnresolvedSetImpl { private: template <unsigned N> friend class UnresolvedSet; UnresolvedSetImpl() {} - UnresolvedSetImpl(const UnresolvedSetImpl &) LLVM_DELETED_FUNCTION; + UnresolvedSetImpl(const UnresolvedSetImpl &) {} public: // We don't currently support assignment through this iterator, so we might |