diff options
Diffstat (limited to 'include/clang/AST')
50 files changed, 2511 insertions, 399 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 0a991cc4ce..ef87fa6dd9 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. @@ -384,6 +393,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 +466,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 +522,10 @@ public: const LangOptions& getLangOpts() const { return LangOpts; } + const SanitizerBlacklist &getSanitizerBlacklist() const { + return *SanitizerBL; + } + DiagnosticsEngine &getDiagnostics() const; FullSourceLoc getFullLoc(SourceLocation Loc) const { @@ -912,6 +930,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 +1395,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 +1606,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 +1639,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 +1664,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 +1679,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. /// @@ -2272,17 +2292,23 @@ 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, QualType T, std::string& S, bool Extended) const; + + /// \brief Returns true if this is an inline-initialized static data member + /// which is treated as a definition for MSVC compatibility. + bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const; private: const ASTRecordLayout & @@ -2308,6 +2334,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. @@ -2345,9 +2396,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. @@ -2382,9 +2433,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 484ca4cb86..27c85e65f2 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 4f3279874b..003d489c1c 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 9af016b13d..69df2d8c01 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 a89bfed53f..48eb629277 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 0e06e26e6d..efeac563db 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" @@ -53,9 +53,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 +79,17 @@ 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); + private: /// \brief Kind ids. /// @@ -184,12 +205,14 @@ public: return BaseConverter<T>::get(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; @@ -241,7 +264,8 @@ private: } 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; } @@ -257,6 +281,7 @@ private: 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; } @@ -272,12 +297,14 @@ private: static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); + Result.MemoizationData = nullptr; new (Result.Storage.buffer) T(Node); return Result; } }; ASTNodeKind NodeKind; + const void *MemoizationData; /// \brief Stores the data of the node. /// @@ -345,20 +372,7 @@ 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 +#endif diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index d92167e959..6ec054582e 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 fc4881619b..787843e64f 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 7cccef69dd..aa3c846829 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 e18fe9ab86..94470cbf30 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 5d50886063..be5b8eeb80 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 dde7a1442f..ec6d83c030 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 312da065ff..f3a209bf6e 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 a6e3ed89b2..d995df9212 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 7e008131d2..2c444f0dc3 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 027c3b929d..4ae6fe0c61 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 e2dcdbe392..c0526e1cfd 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)); }) @@ -2297,12 +2325,50 @@ DEF_TRAVERSE_STMT(OMPSectionDirective, DEF_TRAVERSE_STMT(OMPSingleDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPMasterDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPCriticalDirective, { + TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); + TRY_TO(TraverseOMPExecutableDirective(S)); +}) + DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskyieldDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPBarrierDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskwaitDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(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) { @@ -2328,6 +2394,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { + TRY_TO(TraverseStmt(C->getCondition())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { TRY_TO(TraverseStmt(C->getNumThreads())); @@ -2375,6 +2447,42 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) { + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -2386,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; } @@ -2393,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; } @@ -2445,6 +2562,12 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { return true; } +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ce8b8b7dbc..b946636ebd 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. /// @@ -1423,8 +1438,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 +1663,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 +1893,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 +2167,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. + /// + /// 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 two because in-class initializers are not - /// permitted for bit-fields. + /// 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 +2209,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 +2229,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 +2245,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 +2280,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 +2562,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 +2578,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 +2724,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 +3213,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 +3269,11 @@ 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; + private: /// \brief Deserialize just the fields. void LoadFieldsFromExternalStorage() const; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 607ca4ec27..984ab13df4 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 72fad7c28e..062c1527d7 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 @@ -1371,6 +1377,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 +2119,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 +2651,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 +2670,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 +2747,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 +2860,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 +2984,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 +3006,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 +3063,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 +3089,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 +3135,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/DeclFriend.h b/include/clang/AST/DeclFriend.h index 97741c1c37..12b93b408a 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -135,8 +135,12 @@ public: /// Retrieves the source range for the friend declaration. SourceRange getSourceRange() const override LLVM_READONLY { if (NamedDecl *ND = getFriendDecl()) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) + return FD->getSourceRange(); if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) return FTD->getSourceRange(); + if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND)) + return CTD->getSourceRange(); if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) { if (DD->getOuterLocStart() != DD->getInnerLocStart()) return DD->getSourceRange(); diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 520f523a6d..55d4b0f169 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; @@ -956,6 +957,10 @@ public: unsigned Num, ASTContext &C); + /// Produce a name to be used for class's metadata. It comes either via + /// objc_runtime_name attribute or class name. + StringRef getObjCRuntimeNameAsString() const; + /// Returns the designated initializers for the interface. /// /// If this declaration does not have methods marked as designated @@ -1653,6 +1658,10 @@ public: /// \brief Starts the definition of this Objective-C protocol. void startDefinition(); + /// Produce a name to be used for protocol's metadata. It comes either via + /// objc_runtime_name attribute or protocol name. + StringRef getObjCRuntimeNameAsString() const; + SourceRange getSourceRange() const override LLVM_READONLY { if (isThisDeclarationADefinition()) return ObjCContainerDecl::getSourceRange(); @@ -2100,6 +2109,10 @@ public: std::string getNameAsString() const { return getName(); } + + /// Produce a name to be used for class's metadata. It comes either via + /// class's objc_runtime_name attribute or class name. + StringRef getObjCRuntimeNameAsString() const; const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } ObjCInterfaceDecl *getSuperClass() { return SuperClass; } @@ -2342,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 1b329dcd00..7f0616f1e6 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 980a06e35b..9283d2dc43 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 3076b30cd3..49e51e09b8 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 63047ec4db..63066797b3 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" diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index e208280ccc..d94e225c74 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 @@ -1161,7 +1161,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 +1171,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 +1179,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 +1210,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 +2217,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 +2261,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 +2658,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 +2675,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); @@ -4167,6 +4172,17 @@ public: return Designators + NumDesignators; } + typedef llvm::iterator_range<designators_iterator> designators_range; + designators_range designators() { + return designators_range(designators_begin(), designators_end()); + } + + typedef llvm::iterator_range<const_designators_iterator> + designators_const_range; + designators_const_range designators() const { + return designators_const_range(designators_begin(), designators_end()); + } + typedef std::reverse_iterator<designators_iterator> reverse_designators_iterator; reverse_designators_iterator designators_rbegin() { @@ -4830,6 +4846,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 4403b0858f..040fbe7f92 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -737,8 +737,8 @@ public: /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to /// a single GUID. - static UuidAttr *GetUuidAttrOfType(QualType QT, - bool *HasMultipleGUIDsPtr = nullptr); + static const UuidAttr *GetUuidAttrOfType(QualType QT, + bool *HasMultipleGUIDsPtr = nullptr); // Iterators child_range children() { @@ -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; } @@ -1077,6 +1083,7 @@ private: bool Elidable : 1; bool HadMultipleCandidates : 1; bool ListInitialization : 1; + bool StdInitListInitialization : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; @@ -1088,6 +1095,7 @@ protected: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); @@ -1114,6 +1122,7 @@ public: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); @@ -1137,6 +1146,13 @@ public: bool isListInitialization() const { return ListInitialization; } void setListInitialization(bool V) { ListInitialization = V; } + /// \brief Whether this constructor call was written as list-initialization, + /// but was interpreted as forming a std::initializer_list<T> from the list + /// and passing that as a single constructor argument. + /// See C++11 [over.match.list]p1 bullet 1. + bool isStdInitListInitialization() const { return StdInitListInitialization; } + void setStdInitListInitialization(bool V) { StdInitListInitialization = V; } + /// \brief Whether this construction first requires /// zero-initialization before the initializer is called. bool requiresZeroInitialization() const { return ZeroInitialization; } @@ -1155,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; } @@ -1272,6 +1295,7 @@ public: SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } @@ -1468,6 +1492,12 @@ public: /// arguments. typedef Expr **capture_init_iterator; + /// \brief Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range<capture_init_iterator> capture_inits() const { + return llvm::iterator_range<capture_init_iterator>(capture_init_begin(), + capture_init_end()); + } + /// \brief Retrieve the first initialization argument for this /// lambda expression (which initializes the first capture field). capture_init_iterator capture_init_begin() const { @@ -1552,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) { } @@ -2096,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; @@ -2750,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; } @@ -3794,6 +3824,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/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 1e8eff38d3..ff1d180ee8 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 8633c97965..a7468a0fd5 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 a8d119971b..cbe08a1a76 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 56c995264b..7a818557fd 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 0b21b03348..33fcce2109 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 fc719bdc16..518f1232fe 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 95cb11ce64..0c3002c103 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); } }; @@ -196,6 +196,59 @@ public: StmtRange children() { return StmtRange(&Condition, &Condition + 1); } }; +/// \brief This represents 'final' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp task final(a > 5) +/// \endcode +/// In this example directive '#pragma omp task' has simple 'final' +/// clause with condition 'a > 5'. +/// +class OMPFinalClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Condition of the 'if' clause. + Stmt *Condition; + + /// \brief Set condition. + /// + void setCondition(Expr *Cond) { Condition = Cond; } + +public: + /// \brief Build 'final' clause with condition \a Cond. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param Cond Condition of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc), + Condition(Cond) {} + + /// \brief Build an empty clause. + /// + OMPFinalClause() + : OMPClause(OMPC_final, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Condition(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Returns condition. + Expr *getCondition() const { return cast_or_null<Expr>(Condition); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_final; + } + + StmtRange children() { return StmtRange(&Condition, &Condition + 1); } +}; + /// \brief This represents 'num_threads' clause in the '#pragma omp ...' /// directive. /// @@ -658,6 +711,212 @@ public: StmtRange children() { return StmtRange(); } }; +/// \brief This represents 'untied' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp task untied +/// \endcode +/// In this example directive '#pragma omp task' has 'untied' clause. +/// +class OMPUntiedClause : public OMPClause { +public: + /// \brief Build 'untied' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_untied, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPUntiedClause() + : OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_untied; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'mergeable' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp task mergeable +/// \endcode +/// In this example directive '#pragma omp task' has 'mergeable' clause. +/// +class OMPMergeableClause : public OMPClause { +public: + /// \brief Build 'mergeable' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_mergeable, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPMergeableClause() + : OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_mergeable; + } + + 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 @@ -667,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. @@ -688,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. /// @@ -696,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. @@ -707,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())); @@ -727,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. @@ -747,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. @@ -755,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. @@ -767,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())); @@ -1278,6 +1630,71 @@ public: } }; +/// \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 implicit clause 'flush' +/// with the variables 'a' and 'b'. +/// +class OMPFlushClause : public OMPVarListClause<OMPFlushClause> { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPFlushClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc, + EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPFlushClause(unsigned N) + : OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(), + SourceLocation(), SourceLocation(), + N) {} + +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \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. + /// + static OMPFlushClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL); + /// \brief Creates an empty clause with \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_flush; + } +}; + } // end namespace clang #endif + diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index aba88d6c54..e3f0126677 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 eece8510e9..8945c413d2 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 349f4c44a4..35ceabbd6b 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 8ba85c43f6..2e005ddbd0 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 4befb45062..7b7799884a 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 b4c4fd6ddb..a1d36180d7 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)); }) @@ -2319,12 +2347,50 @@ DEF_TRAVERSE_STMT(OMPSectionDirective, DEF_TRAVERSE_STMT(OMPSingleDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPMasterDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPCriticalDirective, { + TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName())); + TRY_TO(TraverseOMPExecutableDirective(S)); +}) + DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTaskDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskyieldDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPBarrierDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTaskwaitDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(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) { @@ -2350,6 +2416,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { + TRY_TO(TraverseStmt(C->getCondition())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { TRY_TO(TraverseStmt(C->getNumThreads())); @@ -2397,6 +2469,42 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) { + return true; +} + +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -2408,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; } @@ -2415,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; } @@ -2467,6 +2584,12 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { return true; } +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 790c8e3e66..380c3b956e 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -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; } @@ -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]; } @@ -1972,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: @@ -2002,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; } } @@ -2016,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 a3e9e1e093..ab636a5ddc 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 18c55166be..6ffe74f2d7 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 f6fe473f7b..6a2832cdad 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -83,7 +83,10 @@ protected: /// /// /param S Associated statement. /// - void setAssociatedStmt(Stmt *S) { *child_begin() = S; } + void setAssociatedStmt(Stmt *S) { + assert(hasAssociatedStmt() && "no associated statement."); + *child_begin() = S; + } public: /// \brief Iterates over a filtered subrange of clauses applied to a @@ -125,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. @@ -150,8 +160,14 @@ public: /// OMPClause *getClause(unsigned i) const { return clauses()[i]; } + /// \brief Returns true if directive has associated statement. + bool hasAssociatedStmt() const { return NumChildren > 0; } + /// \brief Returns statement associated with the directive. - Stmt *getAssociatedStmt() const { return const_cast<Stmt *>(*child_begin()); } + Stmt *getAssociatedStmt() const { + assert(hasAssociatedStmt() && "no associated statement."); + return const_cast<Stmt *>(*child_begin()); + } OpenMPDirectiveKind getDirectiveKind() const { return Kind; } @@ -161,6 +177,8 @@ public: } child_range children() { + if (!hasAssociatedStmt()) + return child_range(); Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end()); return child_range(ChildStorage, ChildStorage + NumChildren); } @@ -227,6 +245,168 @@ 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. + enum { + AssociatedStmtOffset = 0, + IterationVariableOffset = 1, + LastIterationOffset = 2, + CalcLastIterationOffset = 3, + PreConditionOffset = 4, + CondOffset = 5, + SeparatedCondOffset = 6, + InitOffset = 7, + IncOffset = 8, + ArraysOffset = 9 + }; + + /// \brief Get the counters storage. + MutableArrayRef<Expr *> getCounters() { + Expr **Storage = + reinterpret_cast<Expr **>(&(*(std::next(child_begin(), ArraysOffset)))); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// \brief Get the updates storage. + MutableArrayRef<Expr *> getUpdates() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), ArraysOffset + 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(), ArraysOffset + 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) + + NumSpecialChildren), + CollapsedNum(CollapsedNum) {} + + /// \brief Children number. + static unsigned numLoopChildren(unsigned CollapsedNum) { + return ArraysOffset + 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 setCounters(ArrayRef<Expr *> A); + void setUpdates(ArrayRef<Expr *> A); + void setFinals(ArrayRef<Expr *> A); + +public: + /// \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))); + } + 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 @@ -236,10 +416,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. @@ -249,9 +427,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. /// @@ -259,10 +436,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. @@ -273,11 +449,24 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + /// \param IV Loop iteration variable for CodeGen. + /// \param LastIteration Loop last iteration number for CodeGen. + /// \param CalcLastIteration Calculation of last iteration. + /// \param PreCond Pre-condition. + /// \param Cond Condition. + /// \param SeparatedCond Condition with 1 iteration separated. + /// \param Inc Loop increment. + /// \param Counters Loop counters. + /// \param Updates Expressions for loop counters update for CodeGen. + /// \param Finals Final loop counter values for GodeGen. + /// + static OMPSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Expr *IV, Expr *LastIteration, + Expr *CalcLastIteration, Expr *PreCond, Expr *Cond, + Expr *SeparatedCond, Expr *Init, Expr *Inc, ArrayRef<Expr *> Counters, + ArrayRef<Expr *> Updates, ArrayRef<Expr *> Finals); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -289,8 +478,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; } @@ -305,10 +492,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. @@ -318,9 +503,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. /// @@ -328,10 +512,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. @@ -342,11 +524,24 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. - /// - static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation EndLoc, unsigned CollapsedNum, - ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + /// \param IV Loop iteration variable for CodeGen. + /// \param LastIteration Loop last iteration number for CodeGen. + /// \param CalcLastIteration Calculation of last iteration. + /// \param PreCond Pre-condition. + /// \param Cond Condition. + /// \param SeparatedCond Condition with 1 iteration separated. + /// \param Inc Loop increment. + /// \param Counters Loop counters. + /// \param Updates Expressions for loop counters update for CodeGen. + /// \param Finals Final loop counter values for GodeGen. + /// + static OMPForDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Expr *IV, Expr *LastIteration, + Expr *CalcLastIteration, Expr *PreCond, Expr *Cond, + Expr *SeparatedCond, Expr *Init, Expr *Inc, ArrayRef<Expr *> Counters, + ArrayRef<Expr *> Updates, ArrayRef<Expr *> Finals); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -358,13 +553,88 @@ 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 IV Loop iteration variable for CodeGen. + /// \param LastIteration Loop last iteration number for CodeGen. + /// \param CalcLastIteration Calculation of last iteration. + /// \param PreCond Pre-condition. + /// \param Cond Condition. + /// \param SeparatedCond Condition with 1 iteration separated. + /// \param Inc Loop increment. + /// \param Counters Loop counters. + /// \param Updates Expressions for loop counters update for CodeGen. + /// \param Finals Final loop counter values for GodeGen. + /// + static OMPForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Expr *IV, Expr *LastIteration, + Expr *CalcLastIteration, Expr *PreCond, Expr *Cond, + Expr *SeparatedCond, Expr *Init, Expr *Inc, ArrayRef<Expr *> Counters, + ArrayRef<Expr *> Updates, ArrayRef<Expr *> Finals); + + /// \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 @@ -527,6 +797,116 @@ public: } }; +/// \brief This represents '#pragma omp master' directive. +/// +/// \code +/// #pragma omp master +/// \endcode +/// +class OMPMasterDirective : 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. + /// + OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPMasterDirective() + : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, + 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 OMPMasterDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMasterDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp critical' directive. +/// +/// \code +/// #pragma omp critical +/// \endcode +/// +class OMPCriticalDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Name of the directive. + DeclarationNameInfo DirName; + /// \brief Build directive with the given start and end location. + /// + /// \param Name Name of the directive. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc, + SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, + StartLoc, EndLoc, 0, 1), + DirName(Name) {} + + /// \brief Build an empty directive. + /// + explicit OMPCriticalDirective() + : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical, + SourceLocation(), SourceLocation(), 0, 1), + DirName() {} + + /// \brief Set name of the directive. + /// + /// \param Name Name of the directive. + /// + void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; } + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param Name Name of the directive. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPCriticalDirective * + Create(const ASTContext &C, const DeclarationNameInfo &Name, + SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + /// \brief Return name of the directive. + /// + DeclarationNameInfo getDirectiveName() const { return DirName; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPCriticalDirectiveClass; + } +}; + /// \brief This represents '#pragma omp parallel for' directive. /// /// \code @@ -536,10 +916,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. @@ -549,10 +927,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. /// @@ -560,10 +936,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. @@ -574,11 +949,24 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param IV Loop iteration variable for CodeGen. + /// \param LastIteration Loop last iteration number for CodeGen. + /// \param CalcLastIteration Calculation of last iteration. + /// \param PreCond Pre-condition. + /// \param Cond Condition. + /// \param SeparatedCond Condition with 1 iteration separated. + /// \param Inc Loop increment. + /// \param Counters Loop counters. + /// \param Updates Expressions for loop counters update for CodeGen. + /// \param Finals Final loop counter values for GodeGen. /// static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, Expr *IV, Expr *LastIteration, + Expr *CalcLastIteration, Expr *PreCond, Expr *Cond, + Expr *SeparatedCond, Expr *Init, Expr *Inc, ArrayRef<Expr *> Counters, + ArrayRef<Expr *> Updates, ArrayRef<Expr *> Finals); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -592,13 +980,92 @@ 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 IV Loop iteration variable for CodeGen. + /// \param LastIteration Loop last iteration number for CodeGen. + /// \param CalcLastIteration Calculation of last iteration. + /// \param PreCond Pre-condition. + /// \param Cond Condition. + /// \param SeparatedCond Condition with 1 iteration separated. + /// \param Inc Loop increment. + /// \param Counters Loop counters. + /// \param Updates Expressions for loop counters update for CodeGen. + /// \param Finals Final loop counter values for GodeGen. + /// + static OMPParallelForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, Expr *IV, Expr *LastIteration, + Expr *CalcLastIteration, Expr *PreCond, Expr *Cond, + Expr *SeparatedCond, Expr *Init, Expr *Inc, ArrayRef<Expr *> Counters, + ArrayRef<Expr *> Updates, ArrayRef<Expr *> Finals); + + /// \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 @@ -658,6 +1125,502 @@ public: } }; +/// \brief This represents '#pragma omp task' directive. +/// +/// \code +/// #pragma omp task private(a,b) final(d) +/// \endcode +/// In this example directive '#pragma omp task' has clauses 'private' with the +/// variables 'a' and 'b' and 'final' with condition 'd'. +/// +class OMPTaskDirective : 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. + /// + OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc, + EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTaskDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, + 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 OMPTaskDirective *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 OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp taskyield' directive. +/// +/// \code +/// #pragma omp taskyield +/// \endcode +/// +class OMPTaskyieldDirective : 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. + /// + OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, + StartLoc, EndLoc, 0, 0) {} + + /// \brief Build an empty directive. + /// + explicit OMPTaskyieldDirective() + : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, + SourceLocation(), SourceLocation(), 0, 0) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPTaskyieldDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskyieldDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp barrier' directive. +/// +/// \code +/// #pragma omp barrier +/// \endcode +/// +class OMPBarrierDirective : 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. + /// + OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, + StartLoc, EndLoc, 0, 0) {} + + /// \brief Build an empty directive. + /// + explicit OMPBarrierDirective() + : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, + SourceLocation(), SourceLocation(), 0, 0) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPBarrierDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPBarrierDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp taskwait' directive. +/// +/// \code +/// #pragma omp taskwait +/// \endcode +/// +class OMPTaskwaitDirective : 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. + /// + OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, + StartLoc, EndLoc, 0, 0) {} + + /// \brief Build an empty directive. + /// + explicit OMPTaskwaitDirective() + : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, + SourceLocation(), SourceLocation(), 0, 0) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// + static OMPTaskwaitDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTaskwaitDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp flush' directive. +/// +/// \code +/// #pragma omp flush(a,b) +/// \endcode +/// In this example directive '#pragma omp flush' has 2 arguments- variables 'a' +/// and 'b'. +/// 'omp flush' directive does not have clauses but have an optional list of +/// variables to flush. This list of variables is stored within some fake clause +/// FlushClause. +class OMPFlushDirective : 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. + /// + OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush, + StartLoc, EndLoc, NumClauses, 0) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPFlushDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush, + SourceLocation(), SourceLocation(), NumClauses, + 0) {} + +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 (only single OMPFlushClause clause is + /// allowed). + /// + static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPFlushDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPFlushDirectiveClass; + } +}; + +/// \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 9e4a577c4c..f3c6440f40 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -18,6 +18,7 @@ #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/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -75,7 +76,7 @@ private: struct DA { unsigned Kind; - bool ForRefParam; + void *QT; ValueDecl *D; }; struct I { @@ -131,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 @@ -248,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. @@ -327,6 +326,12 @@ public: return Args.Args + Args.NumArgs; } + /// \brief Iterator range referencing all of the elements of a template + /// argument pack. + llvm::iterator_range<pack_iterator> pack_elements() const { + return llvm::make_range(pack_begin(), pack_end()); + } + /// \brief The number of template arguments in the given template argument /// pack. unsigned pack_size() const { @@ -337,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 a20e43413c..4f194b022d 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1245,6 +1245,7 @@ protected: class FunctionTypeBitfields { friend class FunctionType; + friend class FunctionProtoType; unsigned : NumTypeBits; @@ -1259,6 +1260,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 { @@ -2765,7 +2771,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 +2779,6 @@ protected: ContainsUnexpandedParameterPack), ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; - FunctionTypeBits.TypeQuals = typeQuals; } unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } @@ -2810,7 +2815,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 +2849,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 +2919,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 +2930,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 +2970,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 +2978,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 +3012,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 +3076,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 +3093,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 +3434,7 @@ public: attr_stdcall, attr_thiscall, attr_pascal, + attr_vectorcall, attr_pnaclcall, attr_inteloclbicc, attr_ms_abi, @@ -5231,8 +5250,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 3648d2a5c2..4f3c811ce2 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 9c9f15e953..392e544d90 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 2ef5800c30..a11f22d201 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 |