diff options
Diffstat (limited to 'clang/include/clang/AST')
58 files changed, 6195 insertions, 1974 deletions
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 63359294ef63..cca92b5f8235 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -372,7 +372,7 @@ public: bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } void dump() const; - void dump(raw_ostream &OS) const; + void dump(raw_ostream &OS, const ASTContext &Context) const; void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const; std::string getAsString(const ASTContext &Ctx, QualType Ty) const; diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h index 896d857d8c96..71bf14a87865 100644 --- a/clang/include/clang/AST/ASTConcept.h +++ b/clang/include/clang/AST/ASTConcept.h @@ -22,10 +22,25 @@ #include <utility> namespace clang { class ConceptDecl; +class ConceptSpecializationExpr; + +/// The result of a constraint satisfaction check, containing the necessary +/// information to diagnose an unsatisfied constraint. +class ConstraintSatisfaction : public llvm::FoldingSetNode { + // The template-like entity that 'owns' the constraint checked here (can be a + // constrained entity or a concept). + const NamedDecl *ConstraintOwner = nullptr; + llvm::SmallVector<TemplateArgument, 4> TemplateArgs; + +public: + + ConstraintSatisfaction() = default; + + ConstraintSatisfaction(const NamedDecl *ConstraintOwner, + ArrayRef<TemplateArgument> TemplateArgs) : + ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(), + TemplateArgs.end()) { } -/// \brief The result of a constraint satisfaction check, containing the -/// necessary information to diagnose an unsatisfied constraint. -struct ConstraintSatisfaction { using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>; @@ -37,9 +52,13 @@ struct ConstraintSatisfaction { /// invalid expression. llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details; - // This can leak if used in an AST node, use ASTConstraintSatisfaction - // instead. - void *operator new(size_t bytes, ASTContext &C) = delete; + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) { + Profile(ID, C, ConstraintOwner, TemplateArgs); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C, + const NamedDecl *ConstraintOwner, + ArrayRef<TemplateArgument> TemplateArgs); }; /// Pairs of unsatisfied atomic constraint expressions along with the @@ -174,4 +193,4 @@ public: } // clang -#endif // LLVM_CLANG_AST_ASTCONCEPT_H
\ No newline at end of file +#endif // LLVM_CLANG_AST_ASTCONCEPT_H diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index fb269cef1ce8..2b988be60da9 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -15,7 +15,7 @@ #define LLVM_CLANG_AST_ASTCONTEXT_H #include "clang/AST/ASTContextAllocate.h" -#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/ComparisonCategories.h" @@ -26,7 +26,6 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/RawCommentList.h" -#include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" @@ -40,7 +39,6 @@ #include "clang/Basic/SanitizerBlacklist.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Basic/XRayLists.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" @@ -75,6 +73,7 @@ namespace llvm { struct fltSemantics; +template <typename T, unsigned N> class SmallPtrSet; } // namespace llvm @@ -88,11 +87,15 @@ class AtomicExpr; class BlockExpr; class BuiltinTemplateDecl; class CharUnits; +class ConceptDecl; class CXXABI; class CXXConstructorDecl; class CXXMethodDecl; class CXXRecordDecl; class DiagnosticsEngine; +class ParentMapContext; +class DynTypedNode; +class DynTypedNodeList; class Expr; class FixedPointSemantics; class GlobalDecl; @@ -101,6 +104,7 @@ class MangleNumberingContext; class MaterializeTemporaryExpr; class MemberSpecializationInfo; class Module; +struct MSGuidDeclParts; class ObjCCategoryDecl; class ObjCCategoryImplDecl; class ObjCContainerDecl; @@ -113,11 +117,13 @@ class ObjCPropertyDecl; class ObjCPropertyImplDecl; class ObjCProtocolDecl; class ObjCTypeParamDecl; +class OMPTraitInfo; struct ParsedTargetAttr; class Preprocessor; class Stmt; class StoredDeclsMap; class TargetAttr; +class TargetInfo; class TemplateDecl; class TemplateParameterList; class TemplateTemplateParmDecl; @@ -135,6 +141,7 @@ class Context; } // namespace Builtin enum BuiltinTemplateKind : int; +enum OpenCLTypeKind : uint8_t; namespace comments { @@ -187,6 +194,8 @@ class ASTContext : public RefCountedBase<ASTContext> { DependentAddressSpaceTypes; mutable llvm::FoldingSet<VectorType> VectorTypes; mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes; + mutable llvm::FoldingSet<ConstantMatrixType> MatrixTypes; + mutable llvm::FoldingSet<DependentSizedMatrixType> DependentSizedMatrixTypes; mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&> FunctionProtoTypes; @@ -211,12 +220,14 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; mutable llvm::FoldingSet<DependentUnaryTransformType> DependentUnaryTransformTypes; - mutable llvm::FoldingSet<AutoType> AutoTypes; + mutable llvm::ContextualFoldingSet<AutoType, ASTContext&> AutoTypes; mutable llvm::FoldingSet<DeducedTemplateSpecializationType> DeducedTemplateSpecializationTypes; mutable llvm::FoldingSet<AtomicType> AtomicTypes; llvm::FoldingSet<AttributedType> AttributedTypes; mutable llvm::FoldingSet<PipeType> PipeTypes; + mutable llvm::FoldingSet<ExtIntType> ExtIntTypes; + mutable llvm::FoldingSet<DependentExtIntType> DependentExtIntTypes; mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames; @@ -263,6 +274,9 @@ class ASTContext : public RefCountedBase<ASTContext> { /// Mapping from __block VarDecls to BlockVarCopyInit. llvm::DenseMap<const VarDecl *, BlockVarCopyInit> BlockVarCopyInits; + /// Mapping from GUIDs to the corresponding MSGuidDecl. + mutable llvm::FoldingSet<MSGuidDecl> MSGuidDecls; + /// Used to cleanups APValues stored in the AST. mutable llvm::SmallVector<APValue *, 0> APValueCleanups; @@ -564,18 +578,9 @@ private: const TargetInfo *AuxTarget = nullptr; clang::PrintingPolicy PrintingPolicy; std::unique_ptr<interp::Context> InterpContext; - - ast_type_traits::TraversalKind Traversal = ast_type_traits::TK_AsIs; + std::unique_ptr<ParentMapContext> ParentMapCtx; public: - ast_type_traits::TraversalKind getTraversalKind() const { return Traversal; } - void setTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; } - - const Expr *traverseIgnored(const Expr *E) const; - Expr *traverseIgnored(Expr *E) const; - ast_type_traits::DynTypedNode - traverseIgnored(const ast_type_traits::DynTypedNode &N) const; - IdentifierTable &Idents; SelectorTable &Selectors; Builtin::Context &BuiltinInfo; @@ -586,46 +591,8 @@ public: /// Returns the clang bytecode interpreter context. interp::Context &getInterpContext(); - /// Container for either a single DynTypedNode or for an ArrayRef to - /// DynTypedNode. For use with ParentMap. - class DynTypedNodeList { - using DynTypedNode = ast_type_traits::DynTypedNode; - - llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode, - ArrayRef<DynTypedNode>> Storage; - bool IsSingleNode; - - public: - DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { - new (Storage.buffer) DynTypedNode(N); - } - - DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) { - new (Storage.buffer) ArrayRef<DynTypedNode>(A); - } - - const ast_type_traits::DynTypedNode *begin() const { - if (!IsSingleNode) - return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) - ->begin(); - return reinterpret_cast<const DynTypedNode *>(Storage.buffer); - } - - const ast_type_traits::DynTypedNode *end() const { - if (!IsSingleNode) - return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) - ->end(); - return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1; - } - - size_t size() const { return end() - begin(); } - bool empty() const { return begin() == end(); } - - const DynTypedNode &operator[](size_t N) const { - assert(N < size() && "Out of bounds!"); - return *(begin() + N); - } - }; + /// Returns the dynamic AST node parent map context. + ParentMapContext &getParentMapContext(); // A traversal scope limits the parts of the AST visible to certain analyses. // RecursiveASTVisitor::TraverseAST will only visit reachable nodes, and @@ -637,35 +604,9 @@ public: std::vector<Decl *> getTraversalScope() const { return TraversalScope; } void setTraversalScope(const std::vector<Decl *> &); - /// Returns the parents of the given node (within the traversal scope). - /// - /// Note that this will lazily compute the parents of all nodes - /// and store them for later retrieval. Thus, the first call is O(n) - /// in the number of AST nodes. - /// - /// Caveats and FIXMEs: - /// Calculating the parent map over all AST nodes will need to load the - /// full AST. This can be undesirable in the case where the full AST is - /// expensive to create (for example, when using precompiled header - /// preambles). Thus, there are good opportunities for optimization here. - /// One idea is to walk the given node downwards, looking for references - /// to declaration contexts - once a declaration context is found, compute - /// the parent map for the declaration context; if that can satisfy the - /// request, loading the whole AST can be avoided. Note that this is made - /// more complex by statements in templates having multiple parents - those - /// problems can be solved by building closure over the templated parts of - /// the AST, which also avoids touching large parts of the AST. - /// Additionally, we will want to add an interface to already give a hint - /// where to search for the parents, for example when looking at a statement - /// inside a certain function. - /// - /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, - /// NestedNameSpecifier or NestedNameSpecifierLoc. - template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) { - return getParents(ast_type_traits::DynTypedNode::create(Node)); - } - - DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node); + /// Forwards to get node parents from the ParentMapContext. New callers should + /// use ParentMapContext::getParents() directly. + template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node); const clang::PrintingPolicy &getPrintingPolicy() const { return PrintingPolicy; @@ -716,7 +657,7 @@ public: /// getRealTypeForBitwidth - /// sets floating point QualTy according to specified bitwidth. /// Returns empty type if there is no appropriate target types. - QualType getRealTypeForBitwidth(unsigned DestWidth) const; + QualType getRealTypeForBitwidth(unsigned DestWidth, bool ExplicitIEEE) const; bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const; @@ -790,15 +731,7 @@ public: RawComment *getRawCommentForDeclNoCache(const Decl *D) const; public: - RawCommentList &getRawCommentList() { - return Comments; - } - - void addComment(const RawComment &RC) { - assert(LangOpts.RetainCommentsFromSystemHeaders || - !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin())); - Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc); - } + void addComment(const RawComment &RC); /// Return the documentation comment attached to a given declaration. /// Returns nullptr if no comment is attached. @@ -958,7 +891,7 @@ public: void addedLocalImportDecl(ImportDecl *Import); static ImportDecl *getNextLocalImport(ImportDecl *Import) { - return Import->NextLocalImport; + return Import->getNextLocalImport(); } using import_range = llvm::iterator_range<import_iterator>; @@ -986,13 +919,7 @@ public: /// Get the additional modules in which the definition \p Def has /// been merged. - ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) { - auto MergedIt = - MergedDefModules.find(cast<NamedDecl>(Def->getCanonicalDecl())); - if (MergedIt == MergedDefModules.end()) - return None; - return MergedIt->second; - } + ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def); /// Add a declaration to the list of declarations that are initialized /// for a module. This will typically be a global variable (with internal @@ -1037,6 +964,7 @@ public: CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy, SatUnsignedLongFractTy; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON + CanQualType BFloat16Ty; CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType Float128ComplexTy; @@ -1051,7 +979,8 @@ public: #include "clang/Basic/OpenCLImageTypes.def" CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy; CanQualType OCLQueueTy, OCLReserveIDTy; - CanQualType OMPArraySectionTy; + CanQualType IncompleteMatrixIdxTy; + CanQualType OMPArraySectionTy, OMPArrayShapingTy, OMPIteratorTy; #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ CanQualType Id##Ty; #include "clang/Basic/OpenCLExtensionTypes.def" @@ -1065,7 +994,10 @@ public: // Decl used to help define __builtin_va_list for some targets. // The decl is built when constructing 'BuiltinVaListDecl'. - mutable Decl *VaListTagDecl; + mutable Decl *VaListTagDecl = nullptr; + + // Implicitly-declared type 'struct _GUID'. + mutable TagDecl *MSGuidTagDecl = nullptr; ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins); @@ -1277,12 +1209,20 @@ public: /// Return a write_only pipe type for the specified type. QualType getWritePipeType(QualType T) const; + /// Return an extended integer type with the specified signedness and bit + /// count. + QualType getExtIntType(bool Unsigned, unsigned NumBits) const; + + /// Return a dependent extended integer type with the specified signedness and + /// bit count. + QualType getDependentExtIntType(bool Unsigned, Expr *BitsExpr) const; + /// Gets the struct used to keep track of the extended descriptor for /// pointer to blocks. QualType getBlockDescriptorExtendedType() const; /// Map an AST Type to an OpenCLTypeKind enum value. - TargetInfo::OpenCLTypeKind getOpenCLTypeKind(const Type *T) const; + OpenCLTypeKind getOpenCLTypeKind(const Type *T) const; /// Get address space for OpenCL type. LangAS getOpenCLTypeAddrSpace(const Type *T) const; @@ -1357,6 +1297,12 @@ public: /// Returns a vla type where known sizes are replaced with [*]. QualType getVariableArrayDecayedType(QualType Ty) const; + /// Return the unique reference to a scalable vector type of the specified + /// element type and scalable number of elements. + /// + /// \pre \p EltTy must be a built-in type. + QualType getScalableVectorType(QualType EltTy, unsigned NumElts) const; + /// Return the unique reference to a vector type of the specified /// element type and size. /// @@ -1384,6 +1330,20 @@ public: Expr *SizeExpr, SourceLocation AttrLoc) const; + /// Return the unique reference to the matrix type of the specified element + /// type and size + /// + /// \pre \p ElementType must be a valid matrix element type (see + /// MatrixType::isValidElementType). + QualType getConstantMatrixType(QualType ElementType, unsigned NumRows, + unsigned NumColumns) const; + + /// Return the unique reference to the matrix type of the specified element + /// type and size + QualType getDependentSizedMatrixType(QualType ElementType, Expr *RowExpr, + Expr *ColumnExpr, + SourceLocation AttrLoc) const; + QualType getDependentAddressSpaceType(QualType PointeeType, Expr *AddrSpaceExpr, SourceLocation AttrLoc) const; @@ -1517,6 +1477,8 @@ public: QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl, ArrayRef<ObjCProtocolDecl *> protocols) const; + void adjustObjCTypeParamBoundType(const ObjCTypeParamDecl *Orig, + ObjCTypeParamDecl *New) const; bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); @@ -1542,7 +1504,9 @@ public: /// C++11 deduced auto type. QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, - bool IsDependent, bool IsPack = false) const; + bool IsDependent, bool IsPack = false, + ConceptDecl *TypeConstraintConcept = nullptr, + ArrayRef<TemplateArgument> TypeConstraintArgs ={}) const; /// C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; @@ -1710,23 +1674,9 @@ public: return NSCopyingName; } - CanQualType getNSUIntegerType() const { - assert(Target && "Expected target to be initialized"); - const llvm::Triple &T = Target->getTriple(); - // Windows is LLP64 rather than LP64 - if (T.isOSWindows() && T.isArch64Bit()) - return UnsignedLongLongTy; - return UnsignedLongTy; - } + CanQualType getNSUIntegerType() const; - CanQualType getNSIntegerType() const { - assert(Target && "Expected target to be initialized"); - const llvm::Triple &T = Target->getTriple(); - // Windows is LLP64 rather than LP64 - if (T.isOSWindows() && T.isArch64Bit()) - return LongLongTy; - return LongTy; - } + CanQualType getNSIntegerType() const; /// Retrieve the identifier 'bool'. IdentifierInfo *getBoolName() const { @@ -1941,6 +1891,15 @@ public: return getTypeDeclType(getBuiltinMSVaListDecl()); } + /// Retrieve the implicitly-predeclared 'struct _GUID' declaration. + TagDecl *getMSGuidTagDecl() const { return MSGuidTagDecl; } + + /// Retrieve the implicitly-predeclared 'struct _GUID' type. + QualType getMSGuidType() const { + assert(MSGuidTagDecl && "asked for GUID type but MS extensions disabled"); + return getTagDeclType(MSGuidTagDecl); + } + /// Return whether a declaration to a builtin is allowed to be /// overloaded/redeclared. bool canBuiltinBeRedeclared(const FunctionDecl *) const; @@ -2204,9 +2163,7 @@ public: /// Return the alignment (in bytes) of the thrown exception object. This is /// only meaningful for targets that allocate C++ exceptions in a system /// runtime, such as those using the Itanium C++ ABI. - CharUnits getExnObjectAlignment() const { - return toCharUnitsFromBits(Target->getExnObjectAlignment()); - } + CharUnits getExnObjectAlignment() const; /// Get or compute information about the layout of the specified /// record (struct/union/class) \p D, which indicates its size and field @@ -2624,7 +2581,7 @@ public: QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false, bool BlockReturnType = false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false); + bool Unqualified = false, bool AllowCXX = false); QualType mergeFunctionParameterTypes(QualType, QualType, bool OfBlockPointer = false, bool Unqualified = false); @@ -2845,6 +2802,10 @@ public: /// PredefinedExpr to cache evaluated results. StringLiteral *getPredefinedStringLiteralFromCache(StringRef Key) const; + /// Return a declaration for the global GUID object representing the given + /// GUID value. + MSGuidDecl *getMSGuidDecl(MSGuidDeclParts Parts) const; + /// Parses the target attributes passed in, and returns only the ones that are /// valid feature names. ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; @@ -3023,8 +2984,6 @@ private: llvm::PointerIntPair<StoredDeclsMap *, 1> LastSDM; std::vector<Decl *> TraversalScope; - class ParentMap; - std::map<ast_type_traits::TraversalKind, std::unique_ptr<ParentMap>> Parents; std::unique_ptr<VTableContextBase> VTContext; @@ -3037,6 +2996,7 @@ public: PSF_Write = 0x2, PSF_Execute = 0x4, PSF_Implicit = 0x8, + PSF_ZeroInit = 0x10, PSF_Invalid = 0x80000000U, }; @@ -3054,8 +3014,20 @@ public: }; llvm::StringMap<SectionInfo> SectionInfos; + + /// Return a new OMPTraitInfo object owned by this context. + OMPTraitInfo &getNewOMPTraitInfo(); + +private: + /// All OMPTraitInfo objects live in this collection, one per + /// `pragma omp [begin] declare variant` directive. + SmallVector<std::unique_ptr<OMPTraitInfo>, 4> OMPTraitInfoVector; }; +/// Insertion operator for diagnostics. +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const ASTContext::SectionInfo &Section); + /// Utility function for constructing a nullary selector. inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); @@ -3068,22 +3040,6 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { return Ctx.Selectors.getSelector(1, &II); } -class TraversalKindScope { - ASTContext &Ctx; - ast_type_traits::TraversalKind TK = ast_type_traits::TK_AsIs; - -public: - TraversalKindScope(ASTContext &Ctx, - llvm::Optional<ast_type_traits::TraversalKind> ScopeTK) - : Ctx(Ctx) { - TK = Ctx.getTraversalKind(); - if (ScopeTK) - Ctx.setTraversalKind(*ScopeTK); - } - - ~TraversalKindScope() { Ctx.setTraversalKind(TK); } -}; - } // namespace clang // operator new and delete aren't allowed inside namespaces. diff --git a/clang/include/clang/AST/ASTDumper.h b/clang/include/clang/AST/ASTDumper.h index 61202f057a80..a154bc2db3a7 100644 --- a/clang/include/clang/AST/ASTDumper.h +++ b/clang/include/clang/AST/ASTDumper.h @@ -11,6 +11,7 @@ #include "clang/AST/ASTNodeTraverser.h" #include "clang/AST/TextNodeDumper.h" +#include "clang/Basic/SourceManager.h" namespace clang { @@ -23,18 +24,11 @@ class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> { const bool ShowColors; public: - ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits, - const SourceManager *SM) - : ASTDumper(OS, Traits, SM, SM && SM->getDiagnostics().getShowColors()) {} - - ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits, - const SourceManager *SM, bool ShowColors) - : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {} - ASTDumper(raw_ostream &OS, const comments::CommandTraits *Traits, - const SourceManager *SM, bool ShowColors, - const PrintingPolicy &PrintPolicy) - : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS), - ShowColors(ShowColors) {} + ASTDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors) + : NodeDumper(OS, Context, ShowColors), OS(OS), ShowColors(ShowColors) {} + + ASTDumper(raw_ostream &OS, bool ShowColors) + : NodeDumper(OS, ShowColors), OS(OS), ShowColors(ShowColors) {} TextNodeDumper &doGetNodeDelegate() { return NodeDumper; } diff --git a/clang/include/clang/AST/ASTDumperUtils.h b/clang/include/clang/AST/ASTDumperUtils.h index 55a085449a9b..1dce913049ad 100644 --- a/clang/include/clang/AST/ASTDumperUtils.h +++ b/clang/include/clang/AST/ASTDumperUtils.h @@ -62,6 +62,8 @@ static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false}; static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false}; // bitfield/objcproperty/objcsubscript/vectorcomponent static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false}; +// contains-errors +static const TerminalColor ErrorsColor = {llvm::raw_ostream::RED, true}; // Null statements static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false}; diff --git a/clang/include/clang/AST/ASTFwd.h b/clang/include/clang/AST/ASTFwd.h index 5a891817b336..65319a19728b 100644 --- a/clang/include/clang/AST/ASTFwd.h +++ b/clang/include/clang/AST/ASTFwd.h @@ -27,8 +27,8 @@ class Type; #include "clang/AST/TypeNodes.inc" class CXXCtorInitializer; class OMPClause; -#define OPENMP_CLAUSE(KIND, CLASSNAME) class CLASSNAME; -#include "clang/Basic/OpenMPKinds.def" +#define OMP_CLAUSE_CLASS(Enum, Str, Class) class Class; +#include "llvm/Frontend/OpenMP/OMPKinds.def" } // end namespace clang diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index 490b34bf95e8..205d7ec67754 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -16,6 +16,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -349,6 +350,10 @@ class TypeSourceInfo; return ToOrErr.takeError(); } + /// Import cleanup objects owned by ExprWithCleanup. + llvm::Expected<ExprWithCleanups::CleanupObject> + Import(ExprWithCleanups::CleanupObject From); + /// Import the given type from the "from" context into the "to" /// context. A null type is imported as a null type (no error). /// diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index e0ebb020e697..26656b7162b6 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -15,16 +15,20 @@ #ifndef LLVM_CLANG_AST_ASTNODETRAVERSER_H #define LLVM_CLANG_AST_ASTNODETRAVERSER_H +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/AttrVisitor.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/LocInfoType.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TemplateArgumentVisitor.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeVisitor.h" namespace clang { +class APValue; + /** ASTNodeTraverser traverses the Clang AST for dumping purposes. @@ -49,6 +53,7 @@ struct { void Visit(const OMPClause *C); void Visit(const BlockDecl::Capture &C); void Visit(const GenericSelectionExpr::ConstAssociation &A); + void Visit(const APValue &Value, QualType Ty); }; */ template <typename Derived, typename NodeDelegateType> @@ -65,8 +70,7 @@ class ASTNodeTraverser /// not already been loaded. bool Deserialize = false; - ast_type_traits::TraversalKind Traversal = - ast_type_traits::TraversalKind::TK_AsIs; + TraversalKind Traversal = TraversalKind::TK_AsIs; NodeDelegateType &getNodeDelegate() { return getDerived().doGetNodeDelegate(); @@ -77,7 +81,7 @@ public: void setDeserialize(bool D) { Deserialize = D; } bool getDeserialize() const { return Deserialize; } - void SetTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; } + void SetTraversalKind(TraversalKind TK) { Traversal = TK; } void Visit(const Decl *D) { getNodeDelegate().AddChild([=] { @@ -108,12 +112,12 @@ public: if (auto *E = dyn_cast_or_null<Expr>(S)) { switch (Traversal) { - case ast_type_traits::TK_AsIs: + case TK_AsIs: break; - case ast_type_traits::TK_IgnoreImplicitCastsAndParentheses: + case TK_IgnoreImplicitCastsAndParentheses: S = E->IgnoreParenImpCasts(); break; - case ast_type_traits::TK_IgnoreUnlessSpelledInSource: + case TK_IgnoreUnlessSpelledInSource: S = E->IgnoreUnlessSpelledInSource(); break; } @@ -131,8 +135,7 @@ public: if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) return; - if (isa<LambdaExpr>(S) && - Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource) + if (isa<LambdaExpr>(S) && Traversal == TK_IgnoreUnlessSpelledInSource) return; for (const Stmt *SubStmt : S->children()) @@ -212,6 +215,10 @@ public: }); } + void Visit(const APValue &Value, QualType Ty) { + getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(Value, Ty); }); + } + void Visit(const comments::Comment *C, const comments::FullComment *FC) { getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(C, FC); @@ -228,7 +235,7 @@ public: }); } - void Visit(const ast_type_traits::DynTypedNode &N) { + void Visit(const DynTypedNode &N) { // FIXME: Improve this with a switch or a visitor pattern. if (const auto *D = N.get<Decl>()) Visit(D); @@ -353,8 +360,6 @@ public: void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { for (const auto &Arg : *T) Visit(Arg); - if (T->isTypeAlias()) - Visit(T->getAliasedType()); } void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { Visit(T->getPointeeType()); @@ -548,8 +553,8 @@ public: } void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { - if (const auto *TC = D->getPlaceholderTypeConstraint()) - Visit(TC->getImmediatelyDeclaredConstraint()); + if (const auto *E = D->getPlaceholderTypeConstraint()) + Visit(E); if (D->hasDefaultArgument()) Visit(D->getDefaultArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), @@ -658,7 +663,7 @@ public: } void VisitLambdaExpr(const LambdaExpr *Node) { - if (Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource) { + if (Traversal == TK_IgnoreUnlessSpelledInSource) { for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { const auto *C = Node->capture_begin() + I; if (!C->isExplicit()) @@ -683,6 +688,15 @@ public: Visit(A); } + void VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { + Visit(E->getParameter()); + } + void VisitSubstNonTypeTemplateParmPackExpr( + const SubstNonTypeTemplateParmPackExpr *E) { + Visit(E->getParameterPack()); + Visit(E->getArgumentPack()); + } + void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { if (const VarDecl *CatchParam = Node->getCatchParamDecl()) Visit(CatchParam); @@ -691,6 +705,11 @@ public: void VisitExpressionTemplateArgument(const TemplateArgument &TA) { Visit(TA.getAsExpr()); } + + void VisitTypeTemplateArgument(const TemplateArgument &TA) { + Visit(TA.getAsType()); + } + void VisitPackTemplateArgument(const TemplateArgument &TA) { for (const auto &TArg : TA.pack_elements()) Visit(TArg); diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h index 1a12281d039d..328b7bce6ba5 100644 --- a/clang/include/clang/AST/ASTTypeTraits.h +++ b/clang/include/clang/AST/ASTTypeTraits.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_AST_ASTTYPETRAITS_H #include "clang/AST/ASTFwd.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" @@ -33,8 +34,6 @@ namespace clang { struct PrintingPolicy; -namespace ast_type_traits { - /// Defines how we descend a level in the AST when we pass /// through expressions. enum TraversalKind { @@ -138,6 +137,7 @@ private: NKI_QualType, NKI_TypeLoc, NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, + NKI_CXXBaseSpecifier, NKI_CXXCtorInitializer, NKI_NestedNameSpecifier, NKI_Decl, @@ -150,8 +150,8 @@ private: #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, #include "clang/AST/TypeNodes.inc" NKI_OMPClause, -#define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class, -#include "clang/Basic/OpenMPKinds.def" +#define OMP_CLAUSE_CLASS(Enum, Str, Class) NKI_##Class, +#include "llvm/Frontend/OpenMP/OMPKinds.def" NKI_NumberOfKinds }; @@ -200,14 +200,15 @@ KIND_TO_KIND_ID(Decl) KIND_TO_KIND_ID(Stmt) KIND_TO_KIND_ID(Type) KIND_TO_KIND_ID(OMPClause) +KIND_TO_KIND_ID(CXXBaseSpecifier) #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) #include "clang/AST/DeclNodes.inc" #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) #include "clang/AST/StmtNodes.inc" #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) #include "clang/AST/TypeNodes.inc" -#define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class) -#include "clang/Basic/OpenMPKinds.def" +#define OMP_CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class) +#include "llvm/Frontend/OpenMP/OMPKinds.def" #undef KIND_TO_KIND_ID inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { @@ -277,7 +278,7 @@ public: void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; /// Dumps the node to the given output stream. - void dump(llvm::raw_ostream &OS, SourceManager &SM) const; + void dump(llvm::raw_ostream &OS, const ASTContext &Context) const; /// For nodes which represent textual entities in the source code, /// return their SourceRange. For all other nodes, return SourceRange(). @@ -465,22 +466,22 @@ private: template <typename T> struct DynTypedNode::BaseConverter< - T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type> + T, std::enable_if_t<std::is_base_of<Decl, T>::value>> : public DynCastPtrConverter<T, Decl> {}; template <typename T> struct DynTypedNode::BaseConverter< - T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> + T, std::enable_if_t<std::is_base_of<Stmt, T>::value>> : public DynCastPtrConverter<T, Stmt> {}; template <typename T> struct DynTypedNode::BaseConverter< - T, typename std::enable_if<std::is_base_of<Type, T>::value>::type> + T, std::enable_if_t<std::is_base_of<Type, T>::value>> : public DynCastPtrConverter<T, Type> {}; template <typename T> struct DynTypedNode::BaseConverter< - T, typename std::enable_if<std::is_base_of<OMPClause, T>::value>::type> + T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>> : public DynCastPtrConverter<T, OMPClause> {}; template <> @@ -512,6 +513,10 @@ template <> struct DynTypedNode::BaseConverter< TypeLoc, void> : public ValueConverter<TypeLoc> {}; +template <> +struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void> + : public PtrConverter<CXXBaseSpecifier> {}; + // The only operation we allow on unsupported types is \c get. // This allows to conveniently use \c DynTypedNode when having an arbitrary // AST node that is not supported, but prevents misuse - a user cannot create @@ -522,18 +527,29 @@ template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { } }; -} // end namespace ast_type_traits +// Previously these types were defined in the clang::ast_type_traits namespace. +// Provide typedefs so that legacy code can be fixed asynchronously. +namespace ast_type_traits { +using DynTypedNode = ::clang::DynTypedNode; +using ASTNodeKind = ::clang::ASTNodeKind; +using TraversalKind = ::clang::TraversalKind; + +constexpr TraversalKind TK_AsIs = ::clang::TK_AsIs; +constexpr TraversalKind TK_IgnoreImplicitCastsAndParentheses = + ::clang::TK_IgnoreImplicitCastsAndParentheses; +constexpr TraversalKind TK_IgnoreUnlessSpelledInSource = + ::clang::TK_IgnoreUnlessSpelledInSource; +} // namespace ast_type_traits + } // end namespace clang namespace llvm { template <> -struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> - : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; +struct DenseMapInfo<clang::ASTNodeKind> : clang::ASTNodeKind::DenseMapInfo {}; template <> -struct DenseMapInfo<clang::ast_type_traits::DynTypedNode> - : clang::ast_type_traits::DynTypedNode::DenseMapInfo {}; +struct DenseMapInfo<clang::DynTypedNode> : clang::DynTypedNode::DenseMapInfo {}; } // end namespace llvm diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index bbaa46363d97..1b457337d658 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -13,13 +13,13 @@ #ifndef LLVM_CLANG_AST_ATTR_H #define LLVM_CLANG_AST_ATTR_H -#include "clang/AST/ASTContextAllocate.h" // For Attrs.inc +#include "clang/AST/ASTFwd.h" #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/AttributeCommonInfo.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Sanitizers.h" @@ -40,6 +40,7 @@ class Expr; class QualType; class FunctionDecl; class TypeSourceInfo; +class OMPTraitInfo; /// Attr - This represents one attribute. class Attr : public AttributeCommonInfo { diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def index 74a45ee4ccc0..039765dfdfea 100644 --- a/clang/include/clang/AST/BuiltinTypes.def +++ b/clang/include/clang/AST/BuiltinTypes.def @@ -212,6 +212,9 @@ FLOATING_TYPE(LongDouble, LongDoubleTy) // '_Float16' FLOATING_TYPE(Float16, HalfTy) +// '__bf16' +FLOATING_TYPE(BFloat16, BFloat16Ty) + // '__float128' FLOATING_TYPE(Float128, Float128Ty) @@ -310,11 +313,20 @@ PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy) // context. PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy) +// A placeholder type for incomplete matrix index expressions. +PLACEHOLDER_TYPE(IncompleteMatrixIdx, IncompleteMatrixIdxTy) + // A placeholder type for OpenMP array sections. PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy) +// A placeholder type for OpenMP array shaping operation. +PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy) + +// A placeholder type for OpenMP iterators. +PLACEHOLDER_TYPE(OMPIterator, OMPIteratorTy) + #ifdef LAST_BUILTIN_TYPE -LAST_BUILTIN_TYPE(OMPArraySection) +LAST_BUILTIN_TYPE(OMPIterator) #undef LAST_BUILTIN_TYPE #endif diff --git a/clang/include/clang/AST/CXXInheritance.h b/clang/include/clang/AST/CXXInheritance.h index f223c1f2f4f0..8b1bcb367b3b 100644 --- a/clang/include/clang/AST/CXXInheritance.h +++ b/clang/include/clang/AST/CXXInheritance.h @@ -119,7 +119,7 @@ class CXXBasePaths { friend class CXXRecordDecl; /// The type from which this search originated. - CXXRecordDecl *Origin = nullptr; + const CXXRecordDecl *Origin = nullptr; /// Paths - The actual set of paths that can be taken from the /// derived class to the same base class. @@ -225,8 +225,8 @@ public: /// Retrieve the type from which this base-paths search /// began - CXXRecordDecl *getOrigin() const { return Origin; } - void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; } + const CXXRecordDecl *getOrigin() const { return Origin; } + void setOrigin(const CXXRecordDecl *Rec) { Origin = Rec; } /// Clear the base-paths results. void clear(); diff --git a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def index bd4d8247aeca..33e65f8ebf44 100644 --- a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def +++ b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def @@ -140,6 +140,7 @@ FIELD(HasInheritedAssignment, 1, NO_MERGE) /// @{ FIELD(NeedOverloadResolutionForCopyConstructor, 1, NO_MERGE) FIELD(NeedOverloadResolutionForMoveConstructor, 1, NO_MERGE) +FIELD(NeedOverloadResolutionForCopyAssignment, 1, NO_MERGE) FIELD(NeedOverloadResolutionForMoveAssignment, 1, NO_MERGE) FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE) /// @} @@ -149,6 +150,7 @@ FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE) /// @{ FIELD(DefaultedCopyConstructorIsDeleted, 1, NO_MERGE) FIELD(DefaultedMoveConstructorIsDeleted, 1, NO_MERGE) +FIELD(DefaultedCopyAssignmentIsDeleted, 1, NO_MERGE) FIELD(DefaultedMoveAssignmentIsDeleted, 1, NO_MERGE) FIELD(DefaultedDestructorIsDeleted, 1, NO_MERGE) /// @} diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index 2e00d344533d..488284713bce 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -74,7 +74,7 @@ public: /// canonical type pointers. template <typename U> CanQual(const CanQual<U> &Other, - typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0); + std::enable_if_t<std::is_base_of<T, U>::value, int> = 0); /// Retrieve the underlying type pointer, which refers to a /// canonical type. @@ -264,6 +264,8 @@ public: // Type predicates LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessBuiltinType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) @@ -384,7 +386,7 @@ struct PointerLikeTypeTraits<clang::CanQual<T>> { } // qualifier information is encoded in the low bits. - enum { NumLowBitsAvailable = 0 }; + static constexpr int NumLowBitsAvailable = 0; }; } // namespace llvm diff --git a/clang/include/clang/AST/Comment.h b/clang/include/clang/AST/Comment.h index cd9c1ce2bce0..54a4b0a9cfe6 100644 --- a/clang/include/clang/AST/Comment.h +++ b/clang/include/clang/AST/Comment.h @@ -209,9 +209,7 @@ public: void dump() const; void dumpColor() const; - void dump(const ASTContext &Context) const; - void dump(raw_ostream &OS, const CommandTraits *Traits, - const SourceManager *SM) const; + void dump(raw_ostream &OS, const ASTContext &Context) const; SourceRange getSourceRange() const LLVM_READONLY { return Range; } diff --git a/clang/include/clang/AST/CommentCommands.td b/clang/include/clang/AST/CommentCommands.td index d387df7ce570..fbbfc9f7e0b7 100644 --- a/clang/include/clang/AST/CommentCommands.td +++ b/clang/include/clang/AST/CommentCommands.td @@ -87,6 +87,7 @@ def P : InlineCommand<"p">; def A : InlineCommand<"a">; def E : InlineCommand<"e">; def Em : InlineCommand<"em">; +def Ref : InlineCommand<"ref">; def Anchor : InlineCommand<"anchor">; //===----------------------------------------------------------------------===// @@ -205,7 +206,6 @@ def Paragraph : VerbatimLineCommand<"paragraph">; def Mainpage : VerbatimLineCommand<"mainpage">; def Subpage : VerbatimLineCommand<"subpage">; -def Ref : VerbatimLineCommand<"ref">; def Relates : VerbatimLineCommand<"relates">; def Related : VerbatimLineCommand<"related">; diff --git a/clang/include/clang/AST/CommentSema.h b/clang/include/clang/AST/CommentSema.h index 307618fa5363..6dfe0f4920d0 100644 --- a/clang/include/clang/AST/CommentSema.h +++ b/clang/include/clang/AST/CommentSema.h @@ -217,6 +217,9 @@ public: bool isTemplateOrSpecialization(); bool isRecordLikeDecl(); bool isClassOrStructDecl(); + /// \return \c true if the declaration that this comment is attached to + /// declares either struct, class or tag typedef. + bool isClassOrStructOrTagTypedefDecl(); bool isUnionDecl(); bool isObjCInterfaceDecl(); bool isObjCProtocolDecl(); diff --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h new file mode 100644 index 000000000000..ac2daf9eb95a --- /dev/null +++ b/clang/include/clang/AST/ComputeDependence.h @@ -0,0 +1,194 @@ +//===--- ComputeDependence.h -------------------------------------- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Calculate various template dependency flags for the AST. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_COMPUTE_DEPENDENCE_H +#define LLVM_CLANG_AST_COMPUTE_DEPENDENCE_H + +#include "clang/AST/DependenceFlags.h" +#include "clang/Basic/ExceptionSpecificationType.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { + +class ASTContext; + +class Expr; +class FullExpr; +class OpaqueValueExpr; +class ParenExpr; +class UnaryOperator; +class UnaryExprOrTypeTraitExpr; +class ArraySubscriptExpr; +class MatrixSubscriptExpr; +class CompoundLiteralExpr; +class CastExpr; +class BinaryOperator; +class ConditionalOperator; +class BinaryConditionalOperator; +class StmtExpr; +class ConvertVectorExpr; +class VAArgExpr; +class ChooseExpr; +class NoInitExpr; +class ArrayInitLoopExpr; +class ImplicitValueInitExpr; +class InitListExpr; +class ExtVectorElementExpr; +class BlockExpr; +class AsTypeExpr; +class DeclRefExpr; +class RecoveryExpr; +class CXXRewrittenBinaryOperator; +class CXXStdInitializerListExpr; +class CXXTypeidExpr; +class MSPropertyRefExpr; +class MSPropertySubscriptExpr; +class CXXUuidofExpr; +class CXXThisExpr; +class CXXThrowExpr; +class CXXBindTemporaryExpr; +class CXXScalarValueInitExpr; +class CXXDeleteExpr; +class ArrayTypeTraitExpr; +class ExpressionTraitExpr; +class CXXNoexceptExpr; +class PackExpansionExpr; +class SubstNonTypeTemplateParmExpr; +class CoroutineSuspendExpr; +class DependentCoawaitExpr; +class CXXNewExpr; +class CXXPseudoDestructorExpr; +class OverloadExpr; +class DependentScopeDeclRefExpr; +class CXXConstructExpr; +class LambdaExpr; +class CXXUnresolvedConstructExpr; +class CXXDependentScopeMemberExpr; +class MaterializeTemporaryExpr; +class CXXFoldExpr; +class TypeTraitExpr; +class ConceptSpecializationExpr; +class PredefinedExpr; +class CallExpr; +class OffsetOfExpr; +class MemberExpr; +class ShuffleVectorExpr; +class GenericSelectionExpr; +class DesignatedInitExpr; +class ParenListExpr; +class PseudoObjectExpr; +class AtomicExpr; +class OMPArraySectionExpr; +class OMPArrayShapingExpr; +class OMPIteratorExpr; +class ObjCArrayLiteral; +class ObjCDictionaryLiteral; +class ObjCBoxedExpr; +class ObjCEncodeExpr; +class ObjCIvarRefExpr; +class ObjCPropertyRefExpr; +class ObjCSubscriptRefExpr; +class ObjCIsaExpr; +class ObjCIndirectCopyRestoreExpr; +class ObjCMessageExpr; + +// The following functions are called from constructors of `Expr`, so they +// should not access anything beyond basic +ExprDependence computeDependence(FullExpr *E); +ExprDependence computeDependence(OpaqueValueExpr *E); +ExprDependence computeDependence(ParenExpr *E); +ExprDependence computeDependence(UnaryOperator *E); +ExprDependence computeDependence(UnaryExprOrTypeTraitExpr *E); +ExprDependence computeDependence(ArraySubscriptExpr *E); +ExprDependence computeDependence(MatrixSubscriptExpr *E); +ExprDependence computeDependence(CompoundLiteralExpr *E); +ExprDependence computeDependence(CastExpr *E); +ExprDependence computeDependence(BinaryOperator *E); +ExprDependence computeDependence(ConditionalOperator *E); +ExprDependence computeDependence(BinaryConditionalOperator *E); +ExprDependence computeDependence(StmtExpr *E, unsigned TemplateDepth); +ExprDependence computeDependence(ConvertVectorExpr *E); +ExprDependence computeDependence(VAArgExpr *E); +ExprDependence computeDependence(ChooseExpr *E); +ExprDependence computeDependence(NoInitExpr *E); +ExprDependence computeDependence(ArrayInitLoopExpr *E); +ExprDependence computeDependence(ImplicitValueInitExpr *E); +ExprDependence computeDependence(InitListExpr *E); +ExprDependence computeDependence(ExtVectorElementExpr *E); +ExprDependence computeDependence(BlockExpr *E); +ExprDependence computeDependence(AsTypeExpr *E); +ExprDependence computeDependence(DeclRefExpr *E, const ASTContext &Ctx); +ExprDependence computeDependence(RecoveryExpr *E); +ExprDependence computeDependence(CXXRewrittenBinaryOperator *E); +ExprDependence computeDependence(CXXStdInitializerListExpr *E); +ExprDependence computeDependence(CXXTypeidExpr *E); +ExprDependence computeDependence(MSPropertyRefExpr *E); +ExprDependence computeDependence(MSPropertySubscriptExpr *E); +ExprDependence computeDependence(CXXUuidofExpr *E); +ExprDependence computeDependence(CXXThisExpr *E); +ExprDependence computeDependence(CXXThrowExpr *E); +ExprDependence computeDependence(CXXBindTemporaryExpr *E); +ExprDependence computeDependence(CXXScalarValueInitExpr *E); +ExprDependence computeDependence(CXXDeleteExpr *E); +ExprDependence computeDependence(ArrayTypeTraitExpr *E); +ExprDependence computeDependence(ExpressionTraitExpr *E); +ExprDependence computeDependence(CXXNoexceptExpr *E, CanThrowResult CT); +ExprDependence computeDependence(PackExpansionExpr *E); +ExprDependence computeDependence(SubstNonTypeTemplateParmExpr *E); +ExprDependence computeDependence(CoroutineSuspendExpr *E); +ExprDependence computeDependence(DependentCoawaitExpr *E); +ExprDependence computeDependence(CXXNewExpr *E); +ExprDependence computeDependence(CXXPseudoDestructorExpr *E); +ExprDependence computeDependence(OverloadExpr *E, bool KnownDependent, + bool KnownInstantiationDependent, + bool KnownContainsUnexpandedParameterPack); +ExprDependence computeDependence(DependentScopeDeclRefExpr *E); +ExprDependence computeDependence(CXXConstructExpr *E); +ExprDependence computeDependence(LambdaExpr *E, + bool ContainsUnexpandedParameterPack); +ExprDependence computeDependence(CXXUnresolvedConstructExpr *E); +ExprDependence computeDependence(CXXDependentScopeMemberExpr *E); +ExprDependence computeDependence(MaterializeTemporaryExpr *E); +ExprDependence computeDependence(CXXFoldExpr *E); +ExprDependence computeDependence(TypeTraitExpr *E); +ExprDependence computeDependence(ConceptSpecializationExpr *E, + bool ValueDependent); + +ExprDependence computeDependence(PredefinedExpr *E); +ExprDependence computeDependence(CallExpr *E, llvm::ArrayRef<Expr *> PreArgs); +ExprDependence computeDependence(OffsetOfExpr *E); +ExprDependence computeDependence(MemberExpr *E); +ExprDependence computeDependence(ShuffleVectorExpr *E); +ExprDependence computeDependence(GenericSelectionExpr *E, + bool ContainsUnexpandedPack); +ExprDependence computeDependence(DesignatedInitExpr *E); +ExprDependence computeDependence(ParenListExpr *E); +ExprDependence computeDependence(PseudoObjectExpr *E); +ExprDependence computeDependence(AtomicExpr *E); + +ExprDependence computeDependence(OMPArraySectionExpr *E); +ExprDependence computeDependence(OMPArrayShapingExpr *E); +ExprDependence computeDependence(OMPIteratorExpr *E); + +ExprDependence computeDependence(ObjCArrayLiteral *E); +ExprDependence computeDependence(ObjCDictionaryLiteral *E); +ExprDependence computeDependence(ObjCBoxedExpr *E); +ExprDependence computeDependence(ObjCEncodeExpr *E); +ExprDependence computeDependence(ObjCIvarRefExpr *E); +ExprDependence computeDependence(ObjCPropertyRefExpr *E); +ExprDependence computeDependence(ObjCSubscriptRefExpr *E); +ExprDependence computeDependence(ObjCIsaExpr *E); +ExprDependence computeDependence(ObjCIndirectCopyRestoreExpr *E); +ExprDependence computeDependence(ObjCMessageExpr *E); + +} // namespace clang +#endif diff --git a/clang/include/clang/AST/DataCollection.h b/clang/include/clang/AST/DataCollection.h index 37f101793ecc..14d1bc188623 100644 --- a/clang/include/clang/AST/DataCollection.h +++ b/clang/include/clang/AST/DataCollection.h @@ -50,10 +50,9 @@ template <class T> void addDataToConsumer(T &DataConsumer, const QualType &QT) { } template <class T, class Type> -typename std::enable_if< - std::is_integral<Type>::value || std::is_enum<Type>::value || - std::is_convertible<Type, size_t>::value // for llvm::hash_code - >::type +std::enable_if_t<std::is_integral<Type>::value || std::is_enum<Type>::value || + std::is_convertible<Type, size_t>::value // for llvm::hash_code + > addDataToConsumer(T &DataConsumer, Type Data) { DataConsumer.update(StringRef(reinterpret_cast<char *>(&Data), sizeof(Data))); } diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 43c6c7b85db4..28faa2c1fc78 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2030,7 +2030,7 @@ public: /// declaration to the declaration that is a definition (if there is one). bool isDefined(const FunctionDecl *&Definition) const; - virtual bool isDefined() const { + bool isDefined() const { const FunctionDecl* Definition; return isDefined(Definition); } @@ -2125,19 +2125,17 @@ public: bool isTrivialForCall() const { return FunctionDeclBits.IsTrivialForCall; } void setTrivialForCall(bool IT) { FunctionDeclBits.IsTrivialForCall = IT; } - /// Whether this function is defaulted per C++0x. Only valid for - /// special member functions. + /// Whether this function is defaulted. Valid for e.g. + /// special member functions, defaulted comparisions (not methods!). bool isDefaulted() const { return FunctionDeclBits.IsDefaulted; } void setDefaulted(bool D = true) { FunctionDeclBits.IsDefaulted = D; } - /// Whether this function is explicitly defaulted per C++0x. Only valid - /// for special member functions. + /// Whether this function is explicitly defaulted. bool isExplicitlyDefaulted() const { return FunctionDeclBits.IsExplicitlyDefaulted; } - /// State that this function is explicitly defaulted per C++0x. Only valid - /// for special member functions. + /// State that this function is explicitly defaulted. void setExplicitlyDefaulted(bool ED = true) { FunctionDeclBits.IsExplicitlyDefaulted = ED; } @@ -2306,8 +2304,13 @@ public: /// allocation function. [...] /// /// If this function is an aligned allocation/deallocation function, return - /// true through IsAligned. - bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const; + /// the parameter number of the requested alignment through AlignmentParam. + /// + /// If this function is an allocation/deallocation function that takes + /// the `std::nothrow_t` tag, return true through IsNothrow, + bool isReplaceableGlobalAllocationFunction( + Optional<unsigned> *AlignmentParam = nullptr, + bool *IsNothrow = nullptr) const; /// Determine if this function provides an inline implementation of a builtin. bool isInlineBuiltinDeclaration() const; @@ -2436,6 +2439,14 @@ public: /// parameters have default arguments (in C++). unsigned getMinRequiredArguments() const; + /// Determine whether this function has a single parameter, or multiple + /// parameters where all but the first have default arguments. + /// + /// This notion is used in the definition of copy/move constructors and + /// initializer list constructors. Note that, unlike getMinRequiredArguments, + /// parameter packs are not treated specially here. + bool hasOneParamOrDefaultArgs() const; + /// Find the source location information for how the type of this function /// was written. May be absent (for example if the function was declared via /// a typedef) and may contain a different type from that of the function @@ -2607,7 +2618,13 @@ public: /// Retrieve the function declaration from which this function could /// be instantiated, if it is an instantiation (rather than a non-template /// or a specialization, for example). - FunctionDecl *getTemplateInstantiationPattern() const; + /// + /// If \p ForDefinition is \c false, explicit specializations will be treated + /// as if they were implicit instantiations. This will then find the pattern + /// corresponding to non-definition portions of the declaration, such as + /// default arguments and the exception specification. + FunctionDecl * + getTemplateInstantiationPattern(bool ForDefinition = true) const; /// Retrieve the primary template that this function template /// specialization either specializes or was instantiated from. @@ -2915,12 +2932,15 @@ public: /// Returns the parent of this field declaration, which /// is the struct in which this field is defined. + /// + /// Returns null if this is not a normal class/struct field declaration, e.g. + /// ObjCAtDefsFieldDecl, ObjCIvarDecl. const RecordDecl *getParent() const { - return cast<RecordDecl>(getDeclContext()); + return dyn_cast<RecordDecl>(getDeclContext()); } RecordDecl *getParent() { - return cast<RecordDecl>(getDeclContext()); + return dyn_cast<RecordDecl>(getDeclContext()); } SourceRange getSourceRange() const override LLVM_READONLY; @@ -3534,6 +3554,7 @@ class EnumDecl : public TagDecl { /// negative enumerators of this enum. (see getNumNegativeBits) void setNumNegativeBits(unsigned Num) { EnumDeclBits.NumNegativeBits = Num; } +public: /// True if this tag declaration is a scoped enumeration. Only /// possible in C++11 mode. void setScoped(bool Scoped = true) { EnumDeclBits.IsScoped = Scoped; } @@ -3550,6 +3571,7 @@ class EnumDecl : public TagDecl { /// Microsoft-style enumeration with a fixed underlying type. void setFixed(bool Fixed = true) { EnumDeclBits.IsFixed = Fixed; } +private: /// True if a valid hash is stored in ODRHash. bool hasODRHash() const { return EnumDeclBits.HasODRHash; } void setHasODRHash(bool Hash = true) { EnumDeclBits.HasODRHash = Hash; } @@ -3954,6 +3976,11 @@ public: return cast_or_null<RecordDecl>(TagDecl::getDefinition()); } + /// Returns whether this record is a union, or contains (at any nesting level) + /// a union member. This is used by CMSE to warn about possible information + /// leaks. + bool isOrContainsUnion() const; + // Iterator access to field members. The field iterator only visits // the non-static data members of this class, ignoring any static // data members, functions, constructors, destructors, etc. @@ -4335,17 +4362,18 @@ class ImportDecl final : public Decl, friend class ASTReader; friend TrailingObjects; - /// The imported module, along with a bit that indicates whether - /// we have source-location information for each identifier in the module - /// name. - /// - /// When the bit is false, we only have a single source location for the - /// end of the import declaration. - llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete; + /// The imported module. + Module *ImportedModule = nullptr; /// The next import in the list of imports local to the translation /// unit being parsed (not loaded from an AST file). - ImportDecl *NextLocalImport = nullptr; + /// + /// Includes a bit that indicates whether we have source-location information + /// for each identifier in the module name. + /// + /// When the bit is false, we only have a single source location for the + /// end of the import declaration. + llvm::PointerIntPair<ImportDecl *, 1, bool> NextLocalImportAndComplete; ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs); @@ -4355,6 +4383,20 @@ class ImportDecl final : public Decl, ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {} + bool isImportComplete() const { return NextLocalImportAndComplete.getInt(); } + + void setImportComplete(bool C) { NextLocalImportAndComplete.setInt(C); } + + /// The next import in the list of imports local to the translation + /// unit being parsed (not loaded from an AST file). + ImportDecl *getNextLocalImport() const { + return NextLocalImportAndComplete.getPointer(); + } + + void setNextLocalImport(ImportDecl *Import) { + NextLocalImportAndComplete.setPointer(Import); + } + public: /// Create a new module import declaration. static ImportDecl *Create(ASTContext &C, DeclContext *DC, @@ -4372,7 +4414,7 @@ public: unsigned NumLocations); /// Retrieve the module that was imported by the import declaration. - Module *getImportedModule() const { return ImportedAndComplete.getPointer(); } + Module *getImportedModule() const { return ImportedModule; } /// Retrieves the locations of each of the identifiers that make up /// the complete module name in the import declaration. @@ -4520,6 +4562,13 @@ inline bool IsEnumDeclScoped(EnumDecl *ED) { return ED->isScoped(); } +/// OpenMP variants are mangled early based on their OpenMP context selector. +/// The new name looks likes this: +/// <name> + OpenMPVariantManglingSeparatorStr + <mangled OpenMP context> +static constexpr StringRef getOpenMPVariantManglingSeparatorStr() { + return "$ompvariant"; +} + } // namespace clang #endif // LLVM_CLANG_AST_DECL_H diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 91c372585b07..4f33ff104ffd 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -66,6 +66,7 @@ class SourceManager; class Stmt; class StoredDeclsMap; class TemplateDecl; +class TemplateParameterList; class TranslationUnitDecl; class UsingDirectiveDecl; @@ -465,6 +466,10 @@ public: ASTContext &getASTContext() const LLVM_READONLY; + /// Helper to get the language options from the ASTContext. + /// Defined out of line to avoid depending on ASTContext.h. + const LangOptions &getLangOpts() const LLVM_READONLY; + void setAccess(AccessSpecifier AS) { Access = AS; assert(AccessDeclContextSanity()); @@ -514,7 +519,7 @@ public: if (!HasAttrs) return; AttrVec &Vec = getAttrs(); - Vec.erase(std::remove_if(Vec.begin(), Vec.end(), isa<T, Attr*>), Vec.end()); + llvm::erase_if(Vec, [](Attr *A) { return isa<T>(A); }); if (Vec.empty()) HasAttrs = false; @@ -626,7 +631,16 @@ protected: setModuleOwnershipKind(ModuleOwnershipKind::ModulePrivate); } - /// Set the owning module ID. +public: + /// Set the FromASTFile flag. This indicates that this declaration + /// was deserialized and not parsed from source code and enables + /// features such as module ownership information. + void setFromASTFile() { + FromASTFile = true; + } + + /// Set the owning module ID. This may only be called for + /// deserialized Decls. void setOwningModuleID(unsigned ID) { assert(isFromASTFile() && "Only works on a deserialized declaration"); *((unsigned*)this - 2) = ID; @@ -767,18 +781,19 @@ public: /// all declarations in a global module fragment are unowned. Module *getOwningModuleForLinkage(bool IgnoreLinkage = false) const; - /// Determine whether this declaration might be hidden from name - /// lookup. Note that the declaration might be visible even if this returns - /// \c false, if the owning module is visible within the query context. - // FIXME: Rename this to make it clearer what it does. - bool isHidden() const { - return (int)getModuleOwnershipKind() > (int)ModuleOwnershipKind::Visible; + /// Determine whether this declaration is definitely visible to name lookup, + /// independent of whether the owning module is visible. + /// Note: The declaration may be visible even if this returns \c false if the + /// owning module is visible within the query context. This is a low-level + /// helper function; most code should be calling Sema::isVisible() instead. + bool isUnconditionallyVisible() const { + return (int)getModuleOwnershipKind() <= (int)ModuleOwnershipKind::Visible; } /// Set that this declaration is globally visible, even if it came from a /// module that is not visible. void setVisibleDespiteOwningModule() { - if (isHidden()) + if (!isUnconditionallyVisible()) setModuleOwnershipKind(ModuleOwnershipKind::Visible); } @@ -848,6 +863,10 @@ public: // within the scope of a template parameter). bool isTemplated() const; + /// Determine the number of levels of template parameter surrounding this + /// declaration. + unsigned getTemplateDepth() const; + /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this /// scoped decl is defined outside the current function or method. This is /// roughly global variables and functions, but also handles enums (which @@ -856,14 +875,19 @@ public: return getParentFunctionOrMethod() == nullptr; } - /// Returns true if this declaration lexically is inside a function. - /// It recognizes non-defining declarations as well as members of local - /// classes: + /// Determine whether a substitution into this declaration would occur as + /// part of a substitution into a dependent local scope. Such a substitution + /// transitively substitutes into all constructs nested within this + /// declaration. + /// + /// This recognizes non-defining declarations as well as members of local + /// classes and lambdas: /// \code - /// void foo() { void bar(); } - /// void foo2() { class ABC { void bar(); }; } + /// template<typename T> void foo() { void bar(); } + /// template<typename T> void foo2() { class ABC { void bar(); }; } + /// template<typename T> inline int x = [](){ return 0; }(); /// \endcode - bool isLexicallyWithinFunctionOrMethod() const; + bool isInLocalScopeForInstantiation() const; /// If this decl is defined inside a function/method/block it returns /// the corresponding DeclContext, otherwise it returns null. @@ -1023,8 +1047,16 @@ public: /// If this is a declaration that describes some template, this /// method returns that template declaration. + /// + /// Note that this returns nullptr for partial specializations, because they + /// are not modeled as TemplateDecls. Use getDescribedTemplateParams to handle + /// those cases. TemplateDecl *getDescribedTemplate() const; + /// If this is a declaration that describes some template or partial + /// specialization, this returns the corresponding template parameter list. + const TemplateParameterList *getDescribedTemplateParams() const; + /// Returns the function itself, or the templated function if this is a /// function template. FunctionDecl *getAsFunction() LLVM_READONLY; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index b716ea453a5a..2b8d7e879a0a 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -15,7 +15,6 @@ #ifndef LLVM_CLANG_AST_DECLCXX_H #define LLVM_CLANG_AST_DECLCXX_H -#include "clang/AST/ASTContext.h" #include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" @@ -40,6 +39,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -53,6 +53,7 @@ namespace clang { +class ASTContext; class ClassTemplateDecl; class ConstructorUsingShadowDecl; class CXXBasePath; @@ -712,6 +713,13 @@ public: } /// \c true if we know for sure that this class has a single, + /// accessible, unambiguous copy assignment operator that is not deleted. + bool hasSimpleCopyAssignment() const { + return !hasUserDeclaredCopyAssignment() && + !data().DefaultedCopyAssignmentIsDeleted; + } + + /// \c true if we know for sure that this class has a single, /// accessible, unambiguous move assignment operator that is not deleted. bool hasSimpleMoveAssignment() const { return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() && @@ -871,6 +879,15 @@ public: return data().UserDeclaredSpecialMembers & SMF_CopyAssignment; } + /// Set that we attempted to declare an implicit copy assignment + /// operator, but overload resolution failed so we deleted it. + void setImplicitCopyAssignmentIsDeleted() { + assert((data().DefaultedCopyAssignmentIsDeleted || + needsOverloadResolutionForCopyAssignment()) && + "copy assignment should not be deleted"); + data().DefaultedCopyAssignmentIsDeleted = true; + } + /// Determine whether this class needs an implicit copy /// assignment operator to be lazily declared. bool needsImplicitCopyAssignment() const { @@ -880,7 +897,16 @@ public: /// Determine whether we need to eagerly declare a defaulted copy /// assignment operator for this class. bool needsOverloadResolutionForCopyAssignment() const { - return data().HasMutableFields; + // C++20 [class.copy.assign]p2: + // If the class definition declares a move constructor or move assignment + // operator, the implicitly declared copy assignment operator is defined + // as deleted. + // In MSVC mode, sometimes a declared move constructor does not delete an + // implicit copy assignment, so defer this choice to Sema. + if (data().UserDeclaredSpecialMembers & + (SMF_MoveConstructor | SMF_MoveAssignment)) + return true; + return data().NeedOverloadResolutionForCopyAssignment; } /// Determine whether an implicit copy assignment operator for this @@ -998,6 +1024,9 @@ public: return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault); } + /// Set the captures for this lambda closure type. + void setCaptures(ArrayRef<LambdaCapture> Captures); + /// For a closure type, retrieve the mapping from captured /// variables and \c this to the non-static data members that store the /// values or references of the captures. @@ -1029,6 +1058,8 @@ public: : nullptr; } + unsigned capture_size() const { return getLambdaData().NumCaptures; } + using conversion_iterator = UnresolvedSetIterator; conversion_iterator conversion_begin() const { @@ -1166,7 +1197,7 @@ public: bool defaultedDefaultConstructorIsConstexpr() const { return data().DefaultedDefaultConstructorIsConstexpr && (!isUnion() || hasInClassInitializer() || !hasVariantMembers() || - getASTContext().getLangOpts().CPlusPlus2a); + getLangOpts().CPlusPlus20); } /// Determine whether this class has a constexpr default constructor. @@ -1258,7 +1289,7 @@ public: /// would be constexpr. bool defaultedDestructorIsConstexpr() const { return data().DefaultedDestructorIsConstexpr && - getASTContext().getLangOpts().CPlusPlus2a; + getLangOpts().CPlusPlus20; } /// Determine whether this class has a constexpr destructor. @@ -1355,10 +1386,10 @@ public: /// /// Only in C++17 and beyond, are lambdas literal types. bool isLiteral() const { - ASTContext &Ctx = getASTContext(); - return (Ctx.getLangOpts().CPlusPlus2a ? hasConstexprDestructor() + const LangOptions &LangOpts = getLangOpts(); + return (LangOpts.CPlusPlus20 ? hasConstexprDestructor() : hasTrivialDestructor()) && - (!isLambda() || Ctx.getLangOpts().CPlusPlus17) && + (!isLambda() || LangOpts.CPlusPlus17) && !hasNonLiteralTypeFieldsOrBases() && (isAggregate() || isLambda() || hasConstexprNonCopyMoveConstructor() || @@ -1517,14 +1548,8 @@ public: /// returns false if the class has non-computable base classes. /// /// \param BaseMatches Callback invoked for each (direct or indirect) base - /// class of this type, or if \p AllowShortCircuit is true then until a call - /// returns false. - /// - /// \param AllowShortCircuit if false, forces the callback to be called - /// for every base class, even if a dependent or non-matching base was - /// found. - bool forallBases(ForallBasesCallback BaseMatches, - bool AllowShortCircuit = true) const; + /// class of this type until a call returns false. + bool forallBases(ForallBasesCallback BaseMatches) const; /// Function type used by lookupInBases() to determine whether a /// specific base class subobject matches the lookup criteria. @@ -1696,6 +1721,10 @@ public: /// actually abstract. bool mayBeAbstract() const; + /// Determine whether it's impossible for a class to be derived from this + /// class. This is best-effort, and may conservatively return false. + bool isEffectivelyFinal() const; + /// If this is the closure type of a lambda expression, retrieve the /// number to be used for name mangling in the Itanium C++ ABI. /// @@ -1893,6 +1922,37 @@ public: static bool classofKind(Kind K) { return K == CXXDeductionGuide; } }; +/// \brief Represents the body of a requires-expression. +/// +/// This decl exists merely to serve as the DeclContext for the local +/// parameters of the requires expression as well as other declarations inside +/// it. +/// +/// \code +/// template<typename T> requires requires (T t) { {t++} -> regular; } +/// \endcode +/// +/// In this example, a RequiresExpr object will be generated for the expression, +/// and a RequiresExprBodyDecl will be created to hold the parameter t and the +/// template argument list imposed by the compound requirement. +class RequiresExprBodyDecl : public Decl, public DeclContext { + RequiresExprBodyDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc) + : Decl(RequiresExprBody, DC, StartLoc), DeclContext(RequiresExprBody) {} + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc); + + static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == RequiresExprBody; } +}; + /// Represents a static or instance method of a struct/union/class. /// /// In the terminology of the C++ Standard, these are the (static and @@ -2006,7 +2066,8 @@ public: method_iterator end_overridden_methods() const; unsigned size_overridden_methods() const; - using overridden_method_range= ASTContext::overridden_method_range; + using overridden_method_range = llvm::iterator_range< + llvm::TinyPtrVector<const CXXMethodDecl *>::const_iterator>; overridden_method_range overridden_methods() const; @@ -2386,17 +2447,6 @@ class CXXConstructorDecl final : ExplicitSpecKind::ResolvedFalse); } - void setExplicitSpecifier(ExplicitSpecifier ES) { - assert((!ES.getExpr() || - CXXConstructorDeclBits.HasTrailingExplicitSpecifier) && - "cannot set this explicit specifier. no trail-allocated space for " - "explicit"); - if (ES.getExpr()) - *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES; - else - CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit(); - } - enum TraillingAllocKind { TAKInheritsConstructor = 1, TAKHasTailExplicit = 1 << 1, @@ -2422,6 +2472,17 @@ public: InheritedConstructor Inherited = InheritedConstructor(), Expr *TrailingRequiresClause = nullptr); + void setExplicitSpecifier(ExplicitSpecifier ES) { + assert((!ES.getExpr() || + CXXConstructorDeclBits.HasTrailingExplicitSpecifier) && + "cannot set this explicit specifier. no trail-allocated space for " + "explicit"); + if (ES.getExpr()) + *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>() = ES; + else + CXXConstructorDeclBits.IsSimpleExplicit = ES.isExplicit(); + } + ExplicitSpecifier getExplicitSpecifier() { return getCanonicalDecl()->getExplicitSpecifierInternal(); } @@ -2693,8 +2754,6 @@ class CXXConversionDecl : public CXXMethodDecl { ExplicitSpecifier ExplicitSpec; - void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } - public: friend class ASTDeclReader; friend class ASTDeclWriter; @@ -2716,6 +2775,7 @@ public: /// Return true if the declartion is already resolved to be explicit. bool isExplicit() const { return getExplicitSpecifier().isExplicit(); } + void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } /// Returns the type that this conversion function is converting to. QualType getConversionType() const { @@ -3933,6 +3993,81 @@ public: IdentifierInfo* getSetterId() const { return SetterId; } }; +/// Parts of a decomposed MSGuidDecl. Factored out to avoid unnecessary +/// dependencies on DeclCXX.h. +struct MSGuidDeclParts { + /// {01234567-... + uint32_t Part1; + /// ...-89ab-... + uint16_t Part2; + /// ...-cdef-... + uint16_t Part3; + /// ...-0123-456789abcdef} + uint8_t Part4And5[8]; + + uint64_t getPart4And5AsUint64() const { + uint64_t Val; + memcpy(&Val, &Part4And5, sizeof(Part4And5)); + return Val; + } +}; + +/// A global _GUID constant. These are implicitly created by UuidAttrs. +/// +/// struct _declspec(uuid("01234567-89ab-cdef-0123-456789abcdef")) X{}; +/// +/// X is a CXXRecordDecl that contains a UuidAttr that references the (unique) +/// MSGuidDecl for the specified UUID. +class MSGuidDecl : public ValueDecl, + public Mergeable<MSGuidDecl>, + public llvm::FoldingSetNode { +public: + using Parts = MSGuidDeclParts; + +private: + /// The decomposed form of the UUID. + Parts PartVal; + + /// The resolved value of the UUID as an APValue. Computed on demand and + /// cached. + mutable APValue APVal; + + void anchor() override; + + MSGuidDecl(DeclContext *DC, QualType T, Parts P); + + static MSGuidDecl *Create(const ASTContext &C, QualType T, Parts P); + static MSGuidDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + // Only ASTContext::getMSGuidDecl and deserialization create these. + friend class ASTContext; + friend class ASTReader; + friend class ASTDeclReader; + +public: + /// Print this UUID in a human-readable format. + void printName(llvm::raw_ostream &OS) const override; + + /// Get the decomposed parts of this declaration. + Parts getParts() const { return PartVal; } + + /// Get the value of this MSGuidDecl as an APValue. This may fail and return + /// an absent APValue if the type of the declaration is not of the expected + /// shape. + APValue &getAsAPValue() const; + + static void Profile(llvm::FoldingSetNodeID &ID, Parts P) { + ID.AddInteger(P.Part1); + ID.AddInteger(P.Part2); + ID.AddInteger(P.Part3); + ID.AddInteger(P.getPart4And5AsUint64()); + } + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, PartVal); } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::MSGuid; } +}; + /// Insertion operator for diagnostics. This allows sending an AccessSpecifier /// into a diagnostic with <<. const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/clang/include/clang/AST/DeclGroup.h b/clang/include/clang/AST/DeclGroup.h index 2be9dae9431e..672b7b0a9fe2 100644 --- a/clang/include/clang/AST/DeclGroup.h +++ b/clang/include/clang/AST/DeclGroup.h @@ -147,7 +147,7 @@ namespace llvm { return clang::DeclGroupRef::getFromOpaquePtr(P); } - enum { NumLowBitsAvailable = 0 }; + static constexpr int NumLowBitsAvailable = 0; }; } // namespace llvm diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index b98aef6b499d..5613ed8370c0 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -15,6 +15,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclObjCCommon.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/SelectorLocationsKind.h" @@ -402,7 +403,7 @@ public: } /// createImplicitParams - Used to lazily create the self and cmd - /// implict parameters. This must be called prior to using getSelfDecl() + /// implicit parameters. This must be called prior to using getSelfDecl() /// or getCmdDecl(). The call is ignored if the implicit parameters /// have already been created. void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID); @@ -742,34 +743,6 @@ class ObjCPropertyDecl : public NamedDecl { void anchor() override; public: - enum PropertyAttributeKind { - OBJC_PR_noattr = 0x00, - OBJC_PR_readonly = 0x01, - OBJC_PR_getter = 0x02, - OBJC_PR_assign = 0x04, - OBJC_PR_readwrite = 0x08, - OBJC_PR_retain = 0x10, - OBJC_PR_copy = 0x20, - OBJC_PR_nonatomic = 0x40, - OBJC_PR_setter = 0x80, - OBJC_PR_atomic = 0x100, - OBJC_PR_weak = 0x200, - OBJC_PR_strong = 0x400, - OBJC_PR_unsafe_unretained = 0x800, - /// Indicates that the nullability of the type was spelled with a - /// property attribute rather than a type qualifier. - OBJC_PR_nullability = 0x1000, - OBJC_PR_null_resettable = 0x2000, - OBJC_PR_class = 0x4000, - OBJC_PR_direct = 0x8000 - // Adding a property should change NumPropertyAttrsBits - }; - - enum { - /// Number of bits fitting all the property attributes. - NumPropertyAttrsBits = 16 - }; - enum SetterKind { Assign, Retain, Copy, Weak }; enum PropertyControl { None, Required, Optional }; @@ -782,8 +755,8 @@ private: QualType DeclType; TypeSourceInfo *DeclTypeSourceInfo; - unsigned PropertyAttributes : NumPropertyAttrsBits; - unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; + unsigned PropertyAttributes : NumObjCPropertyAttrsBits; + unsigned PropertyAttributesAsWritten : NumObjCPropertyAttrsBits; // \@required/\@optional unsigned PropertyImplementation : 2; @@ -810,15 +783,14 @@ private: ObjCIvarDecl *PropertyIvarDecl = nullptr; ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - SourceLocation AtLocation, SourceLocation LParenLocation, - QualType T, TypeSourceInfo *TSI, - PropertyControl propControl) - : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), - LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), - PropertyAttributes(OBJC_PR_noattr), - PropertyAttributesAsWritten(OBJC_PR_noattr), - PropertyImplementation(propControl), GetterName(Selector()), - SetterName(Selector()) {} + SourceLocation AtLocation, SourceLocation LParenLocation, + QualType T, TypeSourceInfo *TSI, PropertyControl propControl) + : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), + LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), + PropertyAttributes(ObjCPropertyAttribute::kind_noattr), + PropertyAttributesAsWritten(ObjCPropertyAttribute::kind_noattr), + PropertyImplementation(propControl), GetterName(Selector()), + SetterName(Selector()) {} public: static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, @@ -850,11 +822,11 @@ public: /// type. QualType getUsageType(QualType objectType) const; - PropertyAttributeKind getPropertyAttributes() const { - return PropertyAttributeKind(PropertyAttributes); + ObjCPropertyAttribute::Kind getPropertyAttributes() const { + return ObjCPropertyAttribute::Kind(PropertyAttributes); } - void setPropertyAttributes(PropertyAttributeKind PRVal) { + void setPropertyAttributes(ObjCPropertyAttribute::Kind PRVal) { PropertyAttributes |= PRVal; } @@ -862,11 +834,11 @@ public: PropertyAttributes = PRVal; } - PropertyAttributeKind getPropertyAttributesAsWritten() const { - return PropertyAttributeKind(PropertyAttributesAsWritten); + ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const { + return ObjCPropertyAttribute::Kind(PropertyAttributesAsWritten); } - void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { + void setPropertyAttributesAsWritten(ObjCPropertyAttribute::Kind PRVal) { PropertyAttributesAsWritten = PRVal; } @@ -874,23 +846,28 @@ public: /// isReadOnly - Return true iff the property has a setter. bool isReadOnly() const { - return (PropertyAttributes & OBJC_PR_readonly); + return (PropertyAttributes & ObjCPropertyAttribute::kind_readonly); } /// isAtomic - Return true if the property is atomic. bool isAtomic() const { - return (PropertyAttributes & OBJC_PR_atomic); + return (PropertyAttributes & ObjCPropertyAttribute::kind_atomic); } /// isRetaining - Return true if the property retains its value. bool isRetaining() const { - return (PropertyAttributes & - (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy)); + return (PropertyAttributes & (ObjCPropertyAttribute::kind_retain | + ObjCPropertyAttribute::kind_strong | + ObjCPropertyAttribute::kind_copy)); } bool isInstanceProperty() const { return !isClassProperty(); } - bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; } - bool isDirectProperty() const { return PropertyAttributes & OBJC_PR_direct; } + bool isClassProperty() const { + return PropertyAttributes & ObjCPropertyAttribute::kind_class; + } + bool isDirectProperty() const { + return PropertyAttributes & ObjCPropertyAttribute::kind_direct; + } ObjCPropertyQueryKind getQueryKind() const { return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class : @@ -906,13 +883,13 @@ public: /// the property setter. This is only valid if the property has been /// defined to have a setter. SetterKind getSetterKind() const { - if (PropertyAttributes & OBJC_PR_strong) + if (PropertyAttributes & ObjCPropertyAttribute::kind_strong) return getType()->isBlockPointerType() ? Copy : Retain; - if (PropertyAttributes & OBJC_PR_retain) + if (PropertyAttributes & ObjCPropertyAttribute::kind_retain) return Retain; - if (PropertyAttributes & OBJC_PR_copy) + if (PropertyAttributes & ObjCPropertyAttribute::kind_copy) return Copy; - if (PropertyAttributes & OBJC_PR_weak) + if (PropertyAttributes & ObjCPropertyAttribute::kind_weak) return Weak; return Assign; } @@ -2692,9 +2669,7 @@ public: /// Get the name of the class associated with this interface. // // FIXME: Move to StringRef API. - std::string getNameAsString() const { - return getName(); - } + std::string getNameAsString() const { return std::string(getName()); } /// Produce a name to be used for class's metadata. It comes either via /// class's objc_runtime_name attribute or class name. @@ -2908,11 +2883,11 @@ ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() { } inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) { - return !Cat->isHidden(); + return Cat->isUnconditionallyVisible(); } inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) { - return Cat->IsClassExtension() && !Cat->isHidden(); + return Cat->IsClassExtension() && Cat->isUnconditionallyVisible(); } inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) { diff --git a/clang/include/clang/AST/DeclObjCCommon.h b/clang/include/clang/AST/DeclObjCCommon.h new file mode 100644 index 000000000000..5f03bce6e9a8 --- /dev/null +++ b/clang/include/clang/AST/DeclObjCCommon.h @@ -0,0 +1,55 @@ +//===- DeclObjCCommon.h - Classes for representing declarations -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains common ObjC enums and classes used in AST and +// Sema. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLOBJC_COMMON_H +#define LLVM_CLANG_AST_DECLOBJC_COMMON_H + +namespace clang { + +/// ObjCPropertyAttribute::Kind - list of property attributes. +/// Keep this list in sync with LLVM's Dwarf.h ApplePropertyAttributes.s +namespace ObjCPropertyAttribute { +enum Kind { + kind_noattr = 0x00, + kind_readonly = 0x01, + kind_getter = 0x02, + kind_assign = 0x04, + kind_readwrite = 0x08, + kind_retain = 0x10, + kind_copy = 0x20, + kind_nonatomic = 0x40, + kind_setter = 0x80, + kind_atomic = 0x100, + kind_weak = 0x200, + kind_strong = 0x400, + kind_unsafe_unretained = 0x800, + /// Indicates that the nullability of the type was spelled with a + /// property attribute rather than a type qualifier. + kind_nullability = 0x1000, + kind_null_resettable = 0x2000, + kind_class = 0x4000, + kind_direct = 0x8000, + // Adding a property should change NumObjCPropertyAttrsBits + // Also, don't forget to update the Clang C API at CXObjCPropertyAttrKind and + // clang_Cursor_getObjCPropertyAttributes. +}; +} // namespace ObjCPropertyAttribute::Kind + +enum { + /// Number of bits fitting all the property attributes. + NumObjCPropertyAttrsBits = 16 +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_DECLOBJC_COMMON_H diff --git a/clang/include/clang/AST/DeclOpenMP.h b/clang/include/clang/AST/DeclOpenMP.h index 437feaba28fb..154ecb977692 100644 --- a/clang/include/clang/AST/DeclOpenMP.h +++ b/clang/include/clang/AST/DeclOpenMP.h @@ -129,7 +129,7 @@ private: /// the declare reduction construct is declared inside compound statement. LazyDeclPtr PrevDeclInScope; - virtual void anchor(); + void anchor() override; OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType Ty, @@ -228,7 +228,7 @@ class OMPDeclareMapperDecl final : public ValueDecl, public DeclContext { LazyDeclPtr PrevDeclInScope; - virtual void anchor(); + void anchor() override; OMPDeclareMapperDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType Ty, diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 7a55d04a0f35..e9c4879b41e8 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1102,6 +1102,17 @@ public: /// template. ArrayRef<TemplateArgument> getInjectedTemplateArgs(); + /// Return whether this function template is an abbreviated function template, + /// e.g. `void foo(auto x)` or `template<typename T> void foo(auto x)` + bool isAbbreviated() const { + // Since the invented template parameters generated from 'auto' parameters + // are either appended to the end of the explicit template parameter list or + // form a new template paramter list, we can simply observe the last + // parameter to determine if such a thing happened. + const TemplateParameterList *TPL = getTemplateParameters(); + return TPL->getParam(TPL->size() - 1)->isImplicit(); + } + /// Merge \p Prev with our RedeclarableTemplateDecl::Common. void mergePrevDecl(FunctionTemplateDecl *Prev); @@ -1215,7 +1226,6 @@ public: bool ParameterPack, bool HasTypeConstraint = false, Optional<unsigned> NumExpanded = None); - static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, unsigned ID); static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, @@ -1374,7 +1384,8 @@ class NonTypeTemplateParmDecl final : public DeclaratorDecl, protected TemplateParmPosition, private llvm::TrailingObjects<NonTypeTemplateParmDecl, - std::pair<QualType, TypeSourceInfo *>> { + std::pair<QualType, TypeSourceInfo *>, + Expr *> { friend class ASTDeclReader; friend TrailingObjects; @@ -1429,10 +1440,12 @@ public: ArrayRef<TypeSourceInfo *> ExpandedTInfos); static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, - unsigned ID); + unsigned ID, + bool HasTypeConstraint); static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, unsigned ID, - unsigned NumExpandedTypes); + unsigned NumExpandedTypes, + bool HasTypeConstraint); using TemplateParmPosition::getDepth; using TemplateParmPosition::setDepth; @@ -1543,20 +1556,22 @@ public: return TypesAndInfos[I].second; } - /// Return the type-constraint in the placeholder type of this non-type + /// Return the constraint introduced by the placeholder type of this non-type /// template parameter (if any). - TypeConstraint *getPlaceholderTypeConstraint() const { - // TODO: Concepts: Implement once we have actual placeholders with type - // constraints. - return nullptr; + Expr *getPlaceholderTypeConstraint() const { + return hasPlaceholderTypeConstraint() ? *getTrailingObjects<Expr *>() : + nullptr; + } + + void setPlaceholderTypeConstraint(Expr *E) { + *getTrailingObjects<Expr *>() = E; } /// Determine whether this non-type template parameter's type has a /// placeholder with a type-constraint. bool hasPlaceholderTypeConstraint() const { - // TODO: Concepts: Implement once we have actual placeholders with type - // constraints. - return false; + auto *AT = getType()->getContainedAutoType(); + return AT && AT->isConstrained(); } /// \brief Get the associated-constraints of this template parameter. @@ -1566,8 +1581,8 @@ public: /// Use this instead of getPlaceholderImmediatelyDeclaredConstraint for /// concepts APIs that accept an ArrayRef of constraint expressions. void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { - if (TypeConstraint *TC = getPlaceholderTypeConstraint()) - AC.push_back(TC->getImmediatelyDeclaredConstraint()); + if (Expr *E = getPlaceholderTypeConstraint()) + AC.push_back(E); } // Implement isa/cast/dyncast/etc. @@ -1876,6 +1891,10 @@ public: return *TemplateArgs; } + void setTemplateArgs(TemplateArgumentList *Args) { + TemplateArgs = Args; + } + /// Determine the kind of specialization that this /// declaration represents. TemplateSpecializationKind getSpecializationKind() const { @@ -1908,6 +1927,10 @@ public: getTemplateSpecializationKind()); } + void setSpecializedTemplate(ClassTemplateDecl *Specialized) { + SpecializedTemplate = Specialized; + } + void setSpecializationKind(TemplateSpecializationKind TSK) { SpecializationKind = TSK; } diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h new file mode 100644 index 000000000000..14a7ffaecb2b --- /dev/null +++ b/clang/include/clang/AST/DependenceFlags.h @@ -0,0 +1,284 @@ +//===--- DependenceFlags.h ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_DEPENDENCEFLAGS_H +#define LLVM_CLANG_AST_DEPENDENCEFLAGS_H + +#include "clang/Basic/BitmaskEnum.h" +#include "llvm/ADT/BitmaskEnum.h" +#include <cstdint> + +namespace clang { +struct ExprDependenceScope { + enum ExprDependence : uint8_t { + UnexpandedPack = 1, + // This expr depends in any way on + // - a template parameter, it implies that the resolution of this expr may + // cause instantiation to fail + // - or an error (often in a non-template context) + // + // Note that C++ standard doesn't define the instantiation-dependent term, + // we follow the formal definition coming from the Itanium C++ ABI, and + // extend it to errors. + Instantiation = 2, + // The type of this expr depends on a template parameter, or an error. + Type = 4, + // The value of this expr depends on a template parameter, or an error. + Value = 8, + + // clang extension: this expr contains or references an error, and is + // considered dependent on how that error is resolved. + Error = 16, + + None = 0, + All = 31, + + TypeValue = Type | Value, + TypeInstantiation = Type | Instantiation, + ValueInstantiation = Value | Instantiation, + TypeValueInstantiation = Type | Value | Instantiation, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) + }; +}; +using ExprDependence = ExprDependenceScope::ExprDependence; + +struct TypeDependenceScope { + enum TypeDependence : uint8_t { + /// Whether this type contains an unexpanded parameter pack + /// (for C++11 variadic templates) + UnexpandedPack = 1, + /// Whether this type somehow involves + /// - a template parameter, even if the resolution of the type does not + /// depend on a template parameter. + /// - or an error. + Instantiation = 2, + /// Whether this type + /// - is a dependent type (C++ [temp.dep.type]) + /// - or it somehow involves an error, e.g. decltype(recovery-expr) + Dependent = 4, + /// Whether this type is a variably-modified type (C99 6.7.5). + VariablyModified = 8, + + /// Whether this type references an error, e.g. decltype(err-expression) + /// yields an error type. + Error = 16, + + None = 0, + All = 31, + + DependentInstantiation = Dependent | Instantiation, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) + }; +}; +using TypeDependence = TypeDependenceScope::TypeDependence; + +#define LLVM_COMMON_DEPENDENCE(NAME) \ + struct NAME##Scope { \ + enum NAME : uint8_t { \ + UnexpandedPack = 1, \ + Instantiation = 2, \ + Dependent = 4, \ + Error = 8, \ + \ + None = 0, \ + DependentInstantiation = Dependent | Instantiation, \ + All = 15, \ + \ + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) \ + }; \ + }; \ + using NAME = NAME##Scope::NAME; + +LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence) +LLVM_COMMON_DEPENDENCE(TemplateNameDependence) +LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence) +#undef LLVM_COMMON_DEPENDENCE + +// A combined space of all dependence concepts for all node types. +// Used when aggregating dependence of nodes of different types. +class Dependence { +public: + enum Bits : uint8_t { + None = 0, + + // Contains a template parameter pack that wasn't expanded. + UnexpandedPack = 1, + // Depends on a template parameter or an error in some way. + // Validity depends on how the template is instantiated or the error is + // resolved. + Instantiation = 2, + // Expression type depends on template context, or an error. + // Value and Instantiation should also be set. + Type = 4, + // Expression value depends on template context, or an error. + // Instantiation should also be set. + Value = 8, + // Depends on template context, or an error. + // The type/value distinction is only meaningful for expressions. + Dependent = Type | Value, + // Includes an error, and depends on how it is resolved. + Error = 16, + // Type depends on a runtime value (variable-length array). + VariablyModified = 32, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified) + }; + + Dependence() : V(None) {} + + Dependence(TypeDependence D) + : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) | + translate(D, TypeDependence::Instantiation, Instantiation) | + translate(D, TypeDependence::Dependent, Dependent) | + translate(D, TypeDependence::Error, Error) | + translate(D, TypeDependence::VariablyModified, VariablyModified)) {} + + Dependence(ExprDependence D) + : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) | + translate(D, ExprDependence::Instantiation, Instantiation) | + translate(D, ExprDependence::Type, Type) | + translate(D, ExprDependence::Value, Value) | + translate(D, ExprDependence::Error, Error)) {} + + Dependence(NestedNameSpecifierDependence D) : + V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) | + translate(D, NNSDependence::Instantiation, Instantiation) | + translate(D, NNSDependence::Dependent, Dependent) | + translate(D, NNSDependence::Error, Error)) {} + + Dependence(TemplateArgumentDependence D) + : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) | + translate(D, TADependence::Instantiation, Instantiation) | + translate(D, TADependence::Dependent, Dependent) | + translate(D, TADependence::Error, Error)) {} + + Dependence(TemplateNameDependence D) + : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) | + translate(D, TNDependence::Instantiation, Instantiation) | + translate(D, TNDependence::Dependent, Dependent) | + translate(D, TNDependence::Error, Error)) {} + + TypeDependence type() const { + return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) | + translate(V, Instantiation, TypeDependence::Instantiation) | + translate(V, Dependent, TypeDependence::Dependent) | + translate(V, Error, TypeDependence::Error) | + translate(V, VariablyModified, TypeDependence::VariablyModified); + } + + ExprDependence expr() const { + return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) | + translate(V, Instantiation, ExprDependence::Instantiation) | + translate(V, Type, ExprDependence::Type) | + translate(V, Value, ExprDependence::Value) | + translate(V, Error, ExprDependence::Error); + } + + NestedNameSpecifierDependence nestedNameSpecifier() const { + return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) | + translate(V, Instantiation, NNSDependence::Instantiation) | + translate(V, Dependent, NNSDependence::Dependent) | + translate(V, Error, NNSDependence::Error); + } + + TemplateArgumentDependence templateArgument() const { + return translate(V, UnexpandedPack, TADependence::UnexpandedPack) | + translate(V, Instantiation, TADependence::Instantiation) | + translate(V, Dependent, TADependence::Dependent) | + translate(V, Error, TADependence::Error); + } + + TemplateNameDependence templateName() const { + return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) | + translate(V, Instantiation, TNDependence::Instantiation) | + translate(V, Dependent, TNDependence::Dependent) | + translate(V, Error, TNDependence::Error); + } + +private: + Bits V; + + template <typename T, typename U> + static U translate(T Bits, T FromBit, U ToBit) { + return (Bits & FromBit) ? ToBit : static_cast<U>(0); + } + + // Abbreviations to make conversions more readable. + using NNSDependence = NestedNameSpecifierDependence; + using TADependence = TemplateArgumentDependence; + using TNDependence = TemplateNameDependence; +}; + +/// Computes dependencies of a reference with the name having template arguments +/// with \p TA dependencies. +inline ExprDependence toExprDependence(TemplateArgumentDependence TA) { + return Dependence(TA).expr(); +} +inline ExprDependence toExprDependence(TypeDependence D) { + return Dependence(D).expr(); +} +// Note: it's often necessary to strip `Dependent` from qualifiers. +// If V<T>:: refers to the current instantiation, NNS is considered dependent +// but the containing V<T>::foo likely isn't. +inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) { + return Dependence(D).expr(); +} +inline ExprDependence turnTypeToValueDependence(ExprDependence D) { + // Type-dependent expressions are always be value-dependent, so we simply drop + // type dependency. + return D & ~ExprDependence::Type; +} +inline ExprDependence turnValueToTypeDependence(ExprDependence D) { + // Type-dependent expressions are always be value-dependent. + if (D & ExprDependence::Value) + D |= ExprDependence::Type; + return D; +} + +// Returned type-dependence will never have VariablyModified set. +inline TypeDependence toTypeDependence(ExprDependence D) { + return Dependence(D).type(); +} +inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) { + return Dependence(D).type(); +} +inline TypeDependence toTypeDependence(TemplateNameDependence D) { + return Dependence(D).type(); +} +inline TypeDependence toTypeDependence(TemplateArgumentDependence D) { + return Dependence(D).type(); +} + +inline NestedNameSpecifierDependence +toNestedNameSpecifierDependendence(TypeDependence D) { + return Dependence(D).nestedNameSpecifier(); +} + +inline TemplateArgumentDependence +toTemplateArgumentDependence(TypeDependence D) { + return Dependence(D).templateArgument(); +} +inline TemplateArgumentDependence +toTemplateArgumentDependence(TemplateNameDependence D) { + return Dependence(D).templateArgument(); +} +inline TemplateArgumentDependence +toTemplateArgumentDependence(ExprDependence D) { + return Dependence(D).templateArgument(); +} + +inline TemplateNameDependence +toTemplateNameDependence(NestedNameSpecifierDependence D) { + return Dependence(D).templateName(); +} + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +} // namespace clang +#endif diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 16956c27a114..c13b97119285 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -15,8 +15,10 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTVector.h" +#include "clang/AST/ComputeDependence.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclAccessPair.h" +#include "clang/AST/DependenceFlags.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" @@ -28,10 +30,10 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" @@ -116,23 +118,26 @@ public: Expr &operator=(Expr&&) = delete; protected: - Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, - bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) - : ValueStmt(SC) - { - ExprBits.TypeDependent = TD; - ExprBits.ValueDependent = VD; - ExprBits.InstantiationDependent = ID; + Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK) + : ValueStmt(SC) { + ExprBits.Dependent = 0; ExprBits.ValueKind = VK; ExprBits.ObjectKind = OK; assert(ExprBits.ObjectKind == OK && "truncated kind"); - ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; setType(T); } /// Construct an empty expression. explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(SC) { } + /// Each concrete expr subclass is expected to compute its dependence and call + /// this in the constructor. + void setDependence(ExprDependence Deps) { + ExprBits.Dependent = static_cast<unsigned>(Deps); + } + friend class ASTImporter; // Sets dependence dircetly. + friend class ASTStmtReader; // Sets dependence dircetly. + public: QualType getType() const { return TR; } void setType(QualType t) { @@ -148,24 +153,29 @@ public: TR = t; } - /// isValueDependent - Determines whether this expression is - /// value-dependent (C++ [temp.dep.constexpr]). For example, the - /// array bound of "Chars" in the following example is + ExprDependence getDependence() const { + return static_cast<ExprDependence>(ExprBits.Dependent); + } + + /// Determines whether the value of this expression depends on + /// - a template parameter (C++ [temp.dep.constexpr]) + /// - or an error, whose resolution is unknown + /// + /// For example, the array bound of "Chars" in the following example is /// value-dependent. /// @code /// template<int Size, char (&Chars)[Size]> struct meta_string; /// @endcode - bool isValueDependent() const { return ExprBits.ValueDependent; } - - /// Set whether this expression is value-dependent or not. - void setValueDependent(bool VD) { - ExprBits.ValueDependent = VD; + bool isValueDependent() const { + return static_cast<bool>(getDependence() & ExprDependence::Value); } - /// isTypeDependent - Determines whether this expression is - /// type-dependent (C++ [temp.dep.expr]), which means that its type - /// could change from one template instantiation to the next. For - /// example, the expressions "x" and "x + y" are type-dependent in + /// Determines whether the type of this expression depends on + /// - a template paramter (C++ [temp.dep.expr], which means that its type + /// could change from one template instantiation to the next) + /// - or an error + /// + /// For example, the expressions "x" and "x + y" are type-dependent in /// the following code, but "y" is not type-dependent: /// @code /// template<typename T> @@ -173,16 +183,15 @@ public: /// x + y; /// } /// @endcode - bool isTypeDependent() const { return ExprBits.TypeDependent; } - - /// Set whether this expression is type-dependent or not. - void setTypeDependent(bool TD) { - ExprBits.TypeDependent = TD; + bool isTypeDependent() const { + return static_cast<bool>(getDependence() & ExprDependence::Type); } /// Whether this expression is instantiation-dependent, meaning that - /// it depends in some way on a template parameter, even if neither its type - /// nor (constant) value can change due to the template instantiation. + /// it depends in some way on + /// - a template parameter (even if neither its type nor (constant) value + /// can change due to the template instantiation) + /// - or an error /// /// In the following example, the expression \c sizeof(sizeof(T() + T())) is /// instantiation-dependent (since it involves a template parameter \c T), but @@ -197,13 +206,14 @@ public: /// } /// \endcode /// + /// \code + /// void func(int) { + /// func(); // the expression is instantiation-dependent, because it depends + /// // on an error. + /// } + /// \endcode bool isInstantiationDependent() const { - return ExprBits.InstantiationDependent; - } - - /// Set whether this expression is instantiation-dependent or not. - void setInstantiationDependent(bool ID) { - ExprBits.InstantiationDependent = ID; + return static_cast<bool>(getDependence() & ExprDependence::Instantiation); } /// Whether this expression contains an unexpanded parameter @@ -221,19 +231,24 @@ public: /// The expressions \c args and \c static_cast<Types&&>(args) both /// contain parameter packs. bool containsUnexpandedParameterPack() const { - return ExprBits.ContainsUnexpandedParameterPack; + return static_cast<bool>(getDependence() & ExprDependence::UnexpandedPack); } - /// Set the bit that describes whether this expression - /// contains an unexpanded parameter pack. - void setContainsUnexpandedParameterPack(bool PP = true) { - ExprBits.ContainsUnexpandedParameterPack = PP; + /// Whether this expression contains subexpressions which had errors, e.g. a + /// TypoExpr. + bool containsErrors() const { + return static_cast<bool>(getDependence() & ExprDependence::Error); } /// getExprLoc - Return the preferred location for the arrow when diagnosing /// a problem with a generic expression. SourceLocation getExprLoc() const LLVM_READONLY; + /// Determine whether an lvalue-to-rvalue conversion should implicitly be + /// applied to this expression if it appears as a discarded-value expression + /// in C++11 onwards. This applies to certain forms of volatile glvalues. + bool isReadIfDiscardedInCPlusPlus11() const; + /// isUnusedResultAWarning - Return true if this immediate expression should /// be warned about if the result is unused. If so, fill in expr, location, /// and ranges with expr to warn on and source locations/ranges appropriate @@ -473,6 +488,11 @@ public: /// Returns whether this expression refers to a vector element. bool refersToVectorElement() const; + /// Returns whether this expression refers to a matrix element. + bool refersToMatrixElement() const { + return getObjectKind() == OK_MatrixComponent; + } + /// Returns whether this expression refers to a global register /// variable. bool refersToGlobalRegisterVar() const; @@ -693,7 +713,8 @@ public: /// Evaluate an expression that is required to be a constant expression. bool EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, - const ASTContext &Ctx) const; + const ASTContext &Ctx, + bool InPlace = false) const; /// If the current Expr is a pointer, this will try to statically /// determine the number of bytes available where the pointer is pointing. @@ -952,11 +973,11 @@ protected: Stmt *SubExpr; FullExpr(StmtClass SC, Expr *subexpr) - : Expr(SC, subexpr->getType(), - subexpr->getValueKind(), subexpr->getObjectKind(), - subexpr->isTypeDependent(), subexpr->isValueDependent(), - subexpr->isInstantiationDependent(), - subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) {} + : Expr(SC, subexpr->getType(), subexpr->getValueKind(), + subexpr->getObjectKind()), + SubExpr(subexpr) { + setDependence(computeDependence(this)); + } FullExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {} public: @@ -979,11 +1000,14 @@ class ConstantExpr final : public FullExpr, private llvm::TrailingObjects<ConstantExpr, APValue, uint64_t> { static_assert(std::is_same<uint64_t, llvm::APInt::WordType>::value, - "this class assumes llvm::APInt::WordType is uint64_t for " - "trail-allocated storage"); + "ConstantExpr assumes that llvm::APInt::WordType is uint64_t " + "for tail-allocated storage"); + friend TrailingObjects; + friend class ASTStmtReader; + friend class ASTStmtWriter; public: - /// Describes the kind of result that can be trail-allocated. + /// Describes the kind of result that can be tail-allocated. enum ResultStorageKind { RSK_None, RSK_Int64, RSK_APValue }; private: @@ -994,7 +1018,6 @@ private: return ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64; } - void DefaultInit(ResultStorageKind StorageKind); uint64_t &Int64Result() { assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64 && "invalid accessor"); @@ -1008,24 +1031,22 @@ private: "invalid accessor"); return *getTrailingObjects<APValue>(); } - const APValue &APValueResult() const { + APValue &APValueResult() const { return const_cast<ConstantExpr *>(this)->APValueResult(); } - ConstantExpr(Expr *subexpr, ResultStorageKind StorageKind); - ConstantExpr(ResultStorageKind StorageKind, EmptyShell Empty); + ConstantExpr(Expr *SubExpr, ResultStorageKind StorageKind, + bool IsImmediateInvocation); + ConstantExpr(EmptyShell Empty, ResultStorageKind StorageKind); public: - friend TrailingObjects; - friend class ASTStmtReader; - friend class ASTStmtWriter; static ConstantExpr *Create(const ASTContext &Context, Expr *E, const APValue &Result); static ConstantExpr *Create(const ASTContext &Context, Expr *E, - ResultStorageKind Storage = RSK_None); + ResultStorageKind Storage = RSK_None, + bool IsImmediateInvocation = false); static ConstantExpr *CreateEmpty(const ASTContext &Context, - ResultStorageKind StorageKind, - EmptyShell Empty); + ResultStorageKind StorageKind); static ResultStorageKind getStorageKind(const APValue &Value); static ResultStorageKind getStorageKind(const Type *T, @@ -1053,8 +1074,14 @@ public: ResultStorageKind getResultStorageKind() const { return static_cast<ResultStorageKind>(ConstantExprBits.ResultKind); } + bool isImmediateInvocation() const { + return ConstantExprBits.IsImmediateInvocation; + } + bool hasAPValueResult() const { + return ConstantExprBits.APValueKind != APValue::None; + } APValue getAPValueResult() const; - const APValue &getResultAsAPValue() const { return APValueResult(); } + APValue &getResultAsAPValue() const { return APValueResult(); } llvm::APSInt getResultAsAPSInt() const; // Iterators child_range children() { return child_range(&SubExpr, &SubExpr+1); } @@ -1078,19 +1105,11 @@ class OpaqueValueExpr : public Expr { public: OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, - ExprObjectKind OK = OK_Ordinary, - Expr *SourceExpr = nullptr) - : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType() || - (SourceExpr && SourceExpr->isTypeDependent()), - T->isDependentType() || - (SourceExpr && SourceExpr->isValueDependent()), - T->isInstantiationDependentType() || - (SourceExpr && SourceExpr->isInstantiationDependent()), - false), - SourceExpr(SourceExpr) { + ExprObjectKind OK = OK_Ordinary, Expr *SourceExpr = nullptr) + : Expr(OpaqueValueExprClass, T, VK, OK), SourceExpr(SourceExpr) { setIsUnique(false); OpaqueValueExprBits.Loc = Loc; + setDependence(computeDependence(this)); } /// Given an expression which invokes a copy constructor --- i.e. a @@ -1210,10 +1229,6 @@ class DeclRefExpr final /// Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {} - /// Computes the type- and value-dependence flags for this - /// declaration reference expression. - void computeDependence(const ASTContext &Ctx); - public: DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, @@ -1490,7 +1505,7 @@ class FixedPointLiteral : public Expr, public APIntStorage { SourceLocation Loc; unsigned Scale; - /// \brief Construct an empty integer literal. + /// \brief Construct an empty fixed-point literal. explicit FixedPointLiteral(EmptyShell Empty) : Expr(FixedPointLiteralClass, Empty) {} @@ -1504,6 +1519,9 @@ class FixedPointLiteral : public Expr, public APIntStorage { QualType type, SourceLocation l, unsigned Scale); + /// Returns an empty fixed-point literal. + static FixedPointLiteral *Create(const ASTContext &C, EmptyShell Empty); + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } @@ -1512,6 +1530,9 @@ class FixedPointLiteral : public Expr, public APIntStorage { void setLocation(SourceLocation Location) { Loc = Location; } + unsigned getScale() const { return Scale; } + void setScale(unsigned S) { Scale = S; } + static bool classof(const Stmt *T) { return T->getStmtClass() == FixedPointLiteralClass; } @@ -1544,10 +1565,10 @@ public: // type should be IntTy CharacterLiteral(unsigned value, CharacterKind kind, QualType type, SourceLocation l) - : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false, - false, false), - Value(value), Loc(l) { + : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary), Value(value), + Loc(l) { CharacterLiteralBits.Kind = kind; + setDependence(ExprDependence::None); } /// Construct an empty character literal. @@ -1663,9 +1684,9 @@ class ImaginaryLiteral : public Expr { Stmt *Val; public: ImaginaryLiteral(Expr *val, QualType Ty) - : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Val(val) {} + : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary), Val(val) { + setDependence(ExprDependence::None); + } /// Build an empty imaginary literal. explicit ImaginaryLiteral(EmptyShell Empty) @@ -1902,13 +1923,17 @@ public: /// [C99 6.4.2.2] - A predefined identifier such as __func__. class PredefinedExpr final : public Expr, - private llvm::TrailingObjects<PredefinedExpr, Stmt *> { + private llvm::TrailingObjects<PredefinedExpr, Stmt *, Expr *, + TypeSourceInfo *> { friend class ASTStmtReader; friend TrailingObjects; // PredefinedExpr is optionally followed by a single trailing // "Stmt *" for the predefined identifier. It is present if and only if // hasFunctionName() is true and is always a "StringLiteral *". + // It can also be followed by a Expr* in the case of a + // __builtin_unique_stable_name with an expression, or TypeSourceInfo * if + // __builtin_unique_stable_name with a type. public: enum IdentKind { @@ -1921,12 +1946,18 @@ public: PrettyFunction, /// The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. - PrettyFunctionNoVirtual + PrettyFunctionNoVirtual, + UniqueStableNameType, + UniqueStableNameExpr, }; private: PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, StringLiteral *SL); + PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, + TypeSourceInfo *Info); + PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, + Expr *E); explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName); @@ -1939,10 +1970,39 @@ private: *getTrailingObjects<Stmt *>() = SL; } + void setTypeSourceInfo(TypeSourceInfo *Info) { + assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType && + "TypeSourceInfo only valid for UniqueStableName of a Type"); + *getTrailingObjects<TypeSourceInfo *>() = Info; + } + + void setExpr(Expr *E) { + assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr && + "TypeSourceInfo only valid for UniqueStableName of n Expression."); + *getTrailingObjects<Expr *>() = E; + } + + size_t numTrailingObjects(OverloadToken<Stmt *>) const { + return hasFunctionName(); + } + + size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const { + return getIdentKind() == UniqueStableNameType && !hasFunctionName(); + } + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return getIdentKind() == UniqueStableNameExpr && !hasFunctionName(); + } + public: /// Create a PredefinedExpr. static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, QualType FNTy, IdentKind IK, StringLiteral *SL); + static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, StringLiteral *SL, + TypeSourceInfo *Info); + static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, StringLiteral *SL, + Expr *E); /// Create an empty PredefinedExpr. static PredefinedExpr *CreateEmpty(const ASTContext &Ctx, @@ -1967,8 +2027,34 @@ public: : nullptr; } + TypeSourceInfo *getTypeSourceInfo() { + assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType && + "TypeSourceInfo only valid for UniqueStableName of a Type"); + return *getTrailingObjects<TypeSourceInfo *>(); + } + + const TypeSourceInfo *getTypeSourceInfo() const { + assert(!hasFunctionName() && getIdentKind() == UniqueStableNameType && + "TypeSourceInfo only valid for UniqueStableName of a Type"); + return *getTrailingObjects<TypeSourceInfo *>(); + } + + Expr *getExpr() { + assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr && + "TypeSourceInfo only valid for UniqueStableName of n Expression."); + return *getTrailingObjects<Expr *>(); + } + + const Expr *getExpr() const { + assert(!hasFunctionName() && getIdentKind() == UniqueStableNameExpr && + "TypeSourceInfo only valid for UniqueStableName of n Expression."); + return *getTrailingObjects<Expr *>(); + } + static StringRef getIdentKindName(IdentKind IK); static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl); + static std::string ComputeName(ASTContext &Context, IdentKind IK, + const QualType Ty); SourceLocation getBeginLoc() const { return getLocation(); } SourceLocation getEndLoc() const { return getLocation(); } @@ -1996,12 +2082,11 @@ class ParenExpr : public Expr { Stmt *Val; public: ParenExpr(SourceLocation l, SourceLocation r, Expr *val) - : Expr(ParenExprClass, val->getType(), - val->getValueKind(), val->getObjectKind(), - val->isTypeDependent(), val->isValueDependent(), - val->isInstantiationDependent(), - val->containsUnexpandedParameterPack()), - L(l), R(r), Val(val) {} + : Expr(ParenExprClass, val->getType(), val->getValueKind(), + val->getObjectKind()), + L(l), R(r), Val(val) { + setDependence(computeDependence(this)); + } /// Construct an empty parenthesized expression. explicit ParenExpr(EmptyShell Empty) @@ -2043,31 +2128,48 @@ public: /// applied to a non-complex value, the former returns its operand and the /// later returns zero in the type of the operand. /// -class UnaryOperator : public Expr { +class UnaryOperator final + : public Expr, + private llvm::TrailingObjects<UnaryOperator, FPOptionsOverride> { Stmt *Val; + size_t numTrailingObjects(OverloadToken<FPOptionsOverride>) const { + return UnaryOperatorBits.HasFPFeatures ? 1 : 0; + } + + FPOptionsOverride &getTrailingFPFeatures() { + assert(UnaryOperatorBits.HasFPFeatures); + return *getTrailingObjects<FPOptionsOverride>(); + } + + const FPOptionsOverride &getTrailingFPFeatures() const { + assert(UnaryOperatorBits.HasFPFeatures); + return *getTrailingObjects<FPOptionsOverride>(); + } + public: typedef UnaryOperatorKind Opcode; - UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK, - ExprObjectKind OK, SourceLocation l, bool CanOverflow) - : Expr(UnaryOperatorClass, type, VK, OK, - input->isTypeDependent() || type->isDependentType(), - input->isValueDependent(), - (input->isInstantiationDependent() || - type->isInstantiationDependentType()), - input->containsUnexpandedParameterPack()), - Val(input) { - UnaryOperatorBits.Opc = opc; - UnaryOperatorBits.CanOverflow = CanOverflow; - UnaryOperatorBits.Loc = l; - } +protected: + UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc, QualType type, + ExprValueKind VK, ExprObjectKind OK, SourceLocation l, + bool CanOverflow, FPOptionsOverride FPFeatures); /// Build an empty unary operator. - explicit UnaryOperator(EmptyShell Empty) : Expr(UnaryOperatorClass, Empty) { + explicit UnaryOperator(bool HasFPFeatures, EmptyShell Empty) + : Expr(UnaryOperatorClass, Empty) { UnaryOperatorBits.Opc = UO_AddrOf; + UnaryOperatorBits.HasFPFeatures = HasFPFeatures; } +public: + static UnaryOperator *CreateEmpty(const ASTContext &C, bool hasFPFeatures); + + static UnaryOperator *Create(const ASTContext &C, Expr *input, Opcode opc, + QualType type, ExprValueKind VK, + ExprObjectKind OK, SourceLocation l, + bool CanOverflow, FPOptionsOverride FPFeatures); + Opcode getOpcode() const { return static_cast<Opcode>(UnaryOperatorBits.Opc); } @@ -2089,6 +2191,18 @@ public: bool canOverflow() const { return UnaryOperatorBits.CanOverflow; } void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; } + // Get the FP contractability status of this operator. Only meaningful for + // operations on floating point types. + bool isFPContractableWithinStatement(const LangOptions &LO) const { + return getFPFeaturesInEffect(LO).allowFPContractWithinStatement(); + } + + // Get the FENV_ACCESS status of this operator. Only meaningful for + // operations on floating point types. + bool isFEnvAccessOn(const LangOptions &LO) const { + return getFPFeaturesInEffect(LO).getAllowFEnvAccess(); + } + /// isPostfix - Return true if this is a postfix operation, like x++. static bool isPostfix(Opcode Op) { return Op == UO_PostInc || Op == UO_PostDec; @@ -2155,6 +2269,37 @@ public: const_child_range children() const { return const_child_range(&Val, &Val + 1); } + + /// Is FPFeatures in Trailing Storage? + bool hasStoredFPFeatures() const { return UnaryOperatorBits.HasFPFeatures; } + +protected: + /// Get FPFeatures from trailing storage + FPOptionsOverride getStoredFPFeatures() const { + return getTrailingFPFeatures(); + } + + /// Set FPFeatures in trailing storage, used only by Serialization + void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; } + +public: + // Get the FP features status of this operator. Only meaningful for + // operations on floating point types. + FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { + if (UnaryOperatorBits.HasFPFeatures) + return getStoredFPFeatures().applyOverrides(LO); + return FPOptions::defaultWithoutTrailingStorage(LO); + } + FPOptionsOverride getFPOptionsOverride() const { + if (UnaryOperatorBits.HasFPFeatures) + return getStoredFPFeatures(); + return FPOptionsOverride(); + } + + friend TrailingObjects; + friend class ASTReader; + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// Helper class for OffsetOfExpr. @@ -2379,17 +2524,17 @@ class UnaryExprOrTypeTraitExpr : public Expr { public: UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo, QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, - false, // Never type-dependent (C++ [temp.dep.expr]p3). - // Value-dependent if the argument is type-dependent. - TInfo->getType()->isDependentType(), - TInfo->getType()->isInstantiationDependentType(), - TInfo->getType()->containsUnexpandedParameterPack()), - OpLoc(op), RParenLoc(rp) { + SourceLocation rp) + : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary), + OpLoc(op), RParenLoc(rp) { + assert(ExprKind <= UETT_Last && "invalid enum value!"); UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + assert(static_cast<unsigned>(ExprKind) == + UnaryExprOrTypeTraitExprBits.Kind && + "UnaryExprOrTypeTraitExprBits.Kind overflow!"); UnaryExprOrTypeTraitExprBits.IsType = true; Argument.Ty = TInfo; + setDependence(computeDependence(this)); } UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E, @@ -2403,7 +2548,12 @@ public: UnaryExprOrTypeTrait getKind() const { return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind); } - void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;} + void setKind(UnaryExprOrTypeTrait K) { + assert(K <= UETT_Last && "invalid enum value!"); + UnaryExprOrTypeTraitExprBits.Kind = K; + assert(static_cast<unsigned>(K) == UnaryExprOrTypeTraitExprBits.Kind && + "UnaryExprOrTypeTraitExprBits.Kind overflow!"); + } bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; } QualType getArgumentType() const { @@ -2466,19 +2616,13 @@ class ArraySubscriptExpr : public Expr { bool lhsIsBase() const { return getRHS()->getType()->isIntegerType(); } public: - ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation rbracketloc) - : Expr(ArraySubscriptExprClass, t, VK, OK, - lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent(), - (lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())) { + ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, ExprValueKind VK, + ExprObjectKind OK, SourceLocation rbracketloc) + : Expr(ArraySubscriptExprClass, t, VK, OK) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - ArraySubscriptExprBits.RBracketLoc = rbracketloc; + ArrayOrMatrixSubscriptExprBits.RBracketLoc = rbracketloc; + setDependence(computeDependence(this)); } /// Create an empty array subscript expression. @@ -2514,10 +2658,10 @@ public: SourceLocation getEndLoc() const { return getRBracketLoc(); } SourceLocation getRBracketLoc() const { - return ArraySubscriptExprBits.RBracketLoc; + return ArrayOrMatrixSubscriptExprBits.RBracketLoc; } void setRBracketLoc(SourceLocation L) { - ArraySubscriptExprBits.RBracketLoc = L; + ArrayOrMatrixSubscriptExprBits.RBracketLoc = L; } SourceLocation getExprLoc() const LLVM_READONLY { @@ -2537,6 +2681,84 @@ public: } }; +/// MatrixSubscriptExpr - Matrix subscript expression for the MatrixType +/// extension. +/// MatrixSubscriptExpr can be either incomplete (only Base and RowIdx are set +/// so far, the type is IncompleteMatrixIdx) or complete (Base, RowIdx and +/// ColumnIdx refer to valid expressions). Incomplete matrix expressions only +/// exist during the initial construction of the AST. +class MatrixSubscriptExpr : public Expr { + enum { BASE, ROW_IDX, COLUMN_IDX, END_EXPR }; + Stmt *SubExprs[END_EXPR]; + +public: + MatrixSubscriptExpr(Expr *Base, Expr *RowIdx, Expr *ColumnIdx, QualType T, + SourceLocation RBracketLoc) + : Expr(MatrixSubscriptExprClass, T, Base->getValueKind(), + OK_MatrixComponent) { + SubExprs[BASE] = Base; + SubExprs[ROW_IDX] = RowIdx; + SubExprs[COLUMN_IDX] = ColumnIdx; + ArrayOrMatrixSubscriptExprBits.RBracketLoc = RBracketLoc; + setDependence(computeDependence(this)); + } + + /// Create an empty matrix subscript expression. + explicit MatrixSubscriptExpr(EmptyShell Shell) + : Expr(MatrixSubscriptExprClass, Shell) {} + + bool isIncomplete() const { + bool IsIncomplete = hasPlaceholderType(BuiltinType::IncompleteMatrixIdx); + assert((SubExprs[COLUMN_IDX] || IsIncomplete) && + "expressions without column index must be marked as incomplete"); + return IsIncomplete; + } + Expr *getBase() { return cast<Expr>(SubExprs[BASE]); } + const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); } + void setBase(Expr *E) { SubExprs[BASE] = E; } + + Expr *getRowIdx() { return cast<Expr>(SubExprs[ROW_IDX]); } + const Expr *getRowIdx() const { return cast<Expr>(SubExprs[ROW_IDX]); } + void setRowIdx(Expr *E) { SubExprs[ROW_IDX] = E; } + + Expr *getColumnIdx() { return cast_or_null<Expr>(SubExprs[COLUMN_IDX]); } + const Expr *getColumnIdx() const { + assert(!isIncomplete() && + "cannot get the column index of an incomplete expression"); + return cast<Expr>(SubExprs[COLUMN_IDX]); + } + void setColumnIdx(Expr *E) { SubExprs[COLUMN_IDX] = E; } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return getBase()->getBeginLoc(); + } + + SourceLocation getEndLoc() const { return getRBracketLoc(); } + + SourceLocation getExprLoc() const LLVM_READONLY { + return getBase()->getExprLoc(); + } + + SourceLocation getRBracketLoc() const { + return ArrayOrMatrixSubscriptExprBits.RBracketLoc; + } + void setRBracketLoc(SourceLocation L) { + ArrayOrMatrixSubscriptExprBits.RBracketLoc = L; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MatrixSubscriptExprClass; + } + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } +}; + /// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). /// CallExpr itself represents a normal function call, e.g., "f(x, 2)", /// while its subclasses may represent alternative syntax that (semantically) @@ -2553,8 +2775,6 @@ class CallExpr : public Expr { /// the derived classes of CallExpr. SourceLocation RParenLoc; - void updateDependenciesFromArg(Expr *Arg); - // CallExpr store some data in trailing objects. However since CallExpr // is used a base of other expression classes we cannot use // llvm::TrailingObjects. Instead we manually perform the pointer arithmetic @@ -2796,6 +3016,12 @@ public: /// a non-value-dependent constant parameter evaluating as false. bool isBuiltinAssumeFalse(const ASTContext &Ctx) const; + /// Used by Sema to implement MSVC-compatible delayed name lookup. + /// (Usually Exprs themselves should set dependence). + void markDependentForPostponedNameLookup() { + setDependence(getDependence() | ExprDependence::TypeValueInstantiation); + } + bool isCallToStdMove() const { const FunctionDecl *FD = getDirectCallee(); return getNumArgs() == 1 && FD && FD->isInStdNamespace() && @@ -3088,13 +3314,10 @@ class CompoundLiteralExpr : public Expr { public: CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, QualType T, ExprValueKind VK, Expr *init, bool fileScope) - : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, - tinfo->getType()->isDependentType(), - init->isValueDependent(), - (init->isInstantiationDependent() || - tinfo->getType()->isInstantiationDependentType()), - init->containsUnexpandedParameterPack()), - LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {} + : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary), + LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) { + setDependence(computeDependence(this)); + } /// Construct an empty compound literal. explicit CompoundLiteralExpr(EmptyShell Empty) @@ -3160,26 +3383,13 @@ class CastExpr : public Expr { 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())), - // 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) { + : Expr(SC, ty, VK, OK_Ordinary), Op(op) { CastExprBits.Kind = kind; CastExprBits.PartOfExplicitCast = false; CastExprBits.BasePathSize = BasePathSize; assert((CastExprBits.BasePathSize == BasePathSize) && "BasePathSize overflow!"); + setDependence(computeDependence(this)); assert(CastConsistency()); } @@ -3438,30 +3648,39 @@ class BinaryOperator : public Expr { public: typedef BinaryOperatorKind Opcode; - BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, FPOptions FPFeatures) - : Expr(BinaryOperatorClass, ResTy, VK, OK, - lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent(), - (lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())) { - BinaryOperatorBits.Opc = opc; - BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); - BinaryOperatorBits.OpLoc = opLoc; - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - assert(!isCompoundAssignmentOp() && - "Use CompoundAssignOperator for compound assignments"); +protected: + size_t offsetOfTrailingStorage() const; + + /// Return a pointer to the trailing FPOptions + FPOptionsOverride *getTrailingFPFeatures() { + assert(BinaryOperatorBits.HasFPFeatures); + return reinterpret_cast<FPOptionsOverride *>( + reinterpret_cast<char *>(this) + offsetOfTrailingStorage()); + } + const FPOptionsOverride *getTrailingFPFeatures() const { + assert(BinaryOperatorBits.HasFPFeatures); + return reinterpret_cast<const FPOptionsOverride *>( + reinterpret_cast<const char *>(this) + offsetOfTrailingStorage()); } + /// Build a binary operator, assuming that appropriate storage has been + /// allocated for the trailing objects when needed. + BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc, + QualType ResTy, ExprValueKind VK, ExprObjectKind OK, + SourceLocation opLoc, FPOptionsOverride FPFeatures); + /// Construct an empty binary operator. explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) { BinaryOperatorBits.Opc = BO_Comma; } +public: + static BinaryOperator *CreateEmpty(const ASTContext &C, bool hasFPFeatures); + + static BinaryOperator *Create(const ASTContext &C, Expr *lhs, Expr *rhs, + Opcode opc, QualType ResTy, ExprValueKind VK, + ExprObjectKind OK, SourceLocation opLoc, + FPOptionsOverride FPFeatures); SourceLocation getExprLoc() const { return getOperatorLoc(); } SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; } void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; } @@ -3602,47 +3821,65 @@ public: return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); } - // Set the FP contractability status of this operator. Only meaningful for + /// Set and fetch the bit that shows whether FPFeatures needs to be + /// allocated in Trailing Storage + void setHasStoredFPFeatures(bool B) { BinaryOperatorBits.HasFPFeatures = B; } + bool hasStoredFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; } + + /// Get FPFeatures from trailing storage + FPOptionsOverride getStoredFPFeatures() const { + assert(hasStoredFPFeatures()); + return *getTrailingFPFeatures(); + } + /// Set FPFeatures in trailing storage, used only by Serialization + void setStoredFPFeatures(FPOptionsOverride F) { + assert(BinaryOperatorBits.HasFPFeatures); + *getTrailingFPFeatures() = F; + } + + // Get the FP features status of this operator. Only meaningful for // operations on floating point types. - void setFPFeatures(FPOptions F) { - BinaryOperatorBits.FPFeatures = F.getInt(); + FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { + if (BinaryOperatorBits.HasFPFeatures) + return getStoredFPFeatures().applyOverrides(LO); + return FPOptions::defaultWithoutTrailingStorage(LO); } - FPOptions getFPFeatures() const { - return FPOptions(BinaryOperatorBits.FPFeatures); + // This is used in ASTImporter + FPOptionsOverride getFPFeatures(const LangOptions &LO) const { + if (BinaryOperatorBits.HasFPFeatures) + return getStoredFPFeatures(); + return FPOptionsOverride(); } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. - bool isFPContractableWithinStatement() const { - return getFPFeatures().allowFPContractWithinStatement(); + bool isFPContractableWithinStatement(const LangOptions &LO) const { + return getFPFeaturesInEffect(LO).allowFPContractWithinStatement(); } // Get the FENV_ACCESS status of this operator. Only meaningful for // operations on floating point types. - bool isFEnvAccessOn() const { return getFPFeatures().allowFEnvAccess(); } + bool isFEnvAccessOn(const LangOptions &LO) const { + return getFPFeaturesInEffect(LO).getAllowFEnvAccess(); + } protected: - BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation opLoc, FPOptions FPFeatures, bool dead2) - : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, - lhs->isTypeDependent() || rhs->isTypeDependent(), - lhs->isValueDependent() || rhs->isValueDependent(), - (lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())) { - BinaryOperatorBits.Opc = opc; - BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); - BinaryOperatorBits.OpLoc = opLoc; - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - } + BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc, + QualType ResTy, ExprValueKind VK, ExprObjectKind OK, + SourceLocation opLoc, FPOptionsOverride FPFeatures, + bool dead2); + /// Construct an empty BinaryOperator, SC is CompoundAssignOperator. BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { BinaryOperatorBits.Opc = BO_MulAssign; } + + /// Return the size in bytes needed for the trailing objects. + /// Used to allocate the right amount of storage. + static unsigned sizeOfTrailingObjects(bool HasFPFeatures) { + return HasFPFeatures * sizeof(FPOptionsOverride); + } }; /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep @@ -3654,22 +3891,33 @@ protected: class CompoundAssignOperator : public BinaryOperator { QualType ComputationLHSType; QualType ComputationResultType; -public: - CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, - ExprValueKind VK, ExprObjectKind OK, - QualType CompLHSType, QualType CompResultType, - SourceLocation OpLoc, FPOptions FPFeatures) - : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures, - true), - ComputationLHSType(CompLHSType), - ComputationResultType(CompResultType) { + + /// Construct an empty CompoundAssignOperator. + explicit CompoundAssignOperator(const ASTContext &C, EmptyShell Empty, + bool hasFPFeatures) + : BinaryOperator(CompoundAssignOperatorClass, Empty) {} + +protected: + CompoundAssignOperator(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, + QualType ResType, ExprValueKind VK, ExprObjectKind OK, + SourceLocation OpLoc, FPOptionsOverride FPFeatures, + QualType CompLHSType, QualType CompResultType) + : BinaryOperator(C, lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures, + true), + ComputationLHSType(CompLHSType), ComputationResultType(CompResultType) { assert(isCompoundAssignmentOp() && "Only should be used for compound assignments"); } - /// Build an empty compound assignment operator expression. - explicit CompoundAssignOperator(EmptyShell Empty) - : BinaryOperator(CompoundAssignOperatorClass, Empty) { } +public: + static CompoundAssignOperator *CreateEmpty(const ASTContext &C, + bool hasFPFeatures); + + static CompoundAssignOperator * + Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, + ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, + FPOptionsOverride FPFeatures, QualType CompLHSType = QualType(), + QualType CompResultType = QualType()); // The two computation types are the type the LHS is converted // to for the computation and the type of the result; the two are @@ -3685,6 +3933,12 @@ public: } }; +inline size_t BinaryOperator::offsetOfTrailingStorage() const { + assert(BinaryOperatorBits.HasFPFeatures); + return isa<CompoundAssignOperator>(this) ? sizeof(CompoundAssignOperator) + : sizeof(BinaryOperator); +} + /// AbstractConditionalOperator - An abstract base class for /// ConditionalOperator and BinaryConditionalOperator. class AbstractConditionalOperator : public Expr { @@ -3692,14 +3946,10 @@ class AbstractConditionalOperator : public Expr { friend class ASTStmtReader; protected: - AbstractConditionalOperator(StmtClass SC, QualType T, - ExprValueKind VK, ExprObjectKind OK, - bool TD, bool VD, bool ID, - bool ContainsUnexpandedParameterPack, - SourceLocation qloc, + AbstractConditionalOperator(StmtClass SC, QualType T, ExprValueKind VK, + ExprObjectKind OK, SourceLocation qloc, SourceLocation cloc) - : Expr(SC, T, VK, OK, TD, VD, ID, ContainsUnexpandedParameterPack), - QuestionLoc(qloc), ColonLoc(cloc) {} + : Expr(SC, T, VK, OK), QuestionLoc(qloc), ColonLoc(cloc) {} AbstractConditionalOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { } @@ -3738,26 +3988,12 @@ public: ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, SourceLocation CLoc, Expr *rhs, QualType t, ExprValueKind VK, ExprObjectKind OK) - : AbstractConditionalOperator( - ConditionalOperatorClass, t, VK, OK, - // The type of the conditional operator depends on the type - // of the conditional to support the GCC vector conditional - // extension. Additionally, [temp.dep.expr] does specify state that - // this should be dependent on ALL sub expressions. - (cond->isTypeDependent() || lhs->isTypeDependent() || - rhs->isTypeDependent()), - (cond->isValueDependent() || lhs->isValueDependent() || - rhs->isValueDependent()), - (cond->isInstantiationDependent() || - lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (cond->containsUnexpandedParameterPack() || - lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack()), - QLoc, CLoc) { + : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, QLoc, + CLoc) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; + setDependence(computeDependence(this)); } /// Build an empty conditional operator. @@ -3822,20 +4058,15 @@ public: Expr *cond, Expr *lhs, Expr *rhs, SourceLocation qloc, SourceLocation cloc, QualType t, ExprValueKind VK, ExprObjectKind OK) - : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK, - (common->isTypeDependent() || rhs->isTypeDependent()), - (common->isValueDependent() || rhs->isValueDependent()), - (common->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (common->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack()), - qloc, cloc), - OpaqueValue(opaqueValue) { + : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK, + qloc, cloc), + OpaqueValue(opaqueValue) { SubExprs[COMMON] = common; SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value"); + setDependence(computeDependence(this)); } /// Build an empty conditional operator. @@ -3913,9 +4144,10 @@ class AddrLabelExpr : public Expr { public: AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L, QualType t) - : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false, - false), - AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} + : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary), AmpAmpLoc(AALoc), + LabelLoc(LLoc), Label(L) { + setDependence(ExprDependence::None); + } /// Build an empty address of a label expression. explicit AddrLabelExpr(EmptyShell Empty) @@ -3955,14 +4187,15 @@ class StmtExpr : public Expr { Stmt *SubStmt; SourceLocation LParenLoc, RParenLoc; public: - // FIXME: Does type-dependence need to be computed differently? - // FIXME: Do we need to compute instantiation instantiation-dependence for - // statements? (ugh!) - StmtExpr(CompoundStmt *substmt, QualType T, - SourceLocation lp, SourceLocation rp) : - Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, - T->isDependentType(), false, false, false), - SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } + StmtExpr(CompoundStmt *SubStmt, QualType T, SourceLocation LParenLoc, + SourceLocation RParenLoc, unsigned TemplateDepth) + : Expr(StmtExprClass, T, VK_RValue, OK_Ordinary), SubStmt(SubStmt), + LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + setDependence(computeDependence(this, TemplateDepth)); + // FIXME: A templated statement expression should have an associated + // DeclContext so that nested declarations always have a dependent context. + StmtExprBits.TemplateDepth = TemplateDepth; + } /// Build an empty statement expression. explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } @@ -3979,6 +4212,8 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } + unsigned getTemplateDepth() const { return StmtExprBits.TemplateDepth; } + static bool classof(const Stmt *T) { return T->getStmtClass() == StmtExprClass; } @@ -4075,17 +4310,13 @@ private: explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {} public: - ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation BuiltinLoc, SourceLocation RParenLoc) - : Expr(ConvertVectorExprClass, DstType, VK, OK, - DstType->isDependentType(), - DstType->isDependentType() || SrcExpr->isValueDependent(), - (DstType->isInstantiationDependentType() || - SrcExpr->isInstantiationDependent()), - (DstType->containsUnexpandedParameterPack() || - SrcExpr->containsUnexpandedParameterPack())), - SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} + ConvertVectorExpr(Expr *SrcExpr, TypeSourceInfo *TI, QualType DstType, + ExprValueKind VK, ExprObjectKind OK, + SourceLocation BuiltinLoc, SourceLocation RParenLoc) + : Expr(ConvertVectorExprClass, DstType, VK, OK), SrcExpr(SrcExpr), + TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) { + setDependence(computeDependence(this)); + } /// getSrcExpr - Return the Expr to be converted. Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } @@ -4133,22 +4364,17 @@ class ChooseExpr : public Expr { SourceLocation BuiltinLoc, RParenLoc; bool CondIsTrue; public: - ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, - QualType t, ExprValueKind VK, ExprObjectKind OK, - SourceLocation RP, bool condIsTrue, - bool TypeDependent, bool ValueDependent) - : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent, - (cond->isInstantiationDependent() || - lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (cond->containsUnexpandedParameterPack() || - lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack())), - BuiltinLoc(BLoc), RParenLoc(RP), CondIsTrue(condIsTrue) { - SubExprs[COND] = cond; - SubExprs[LHS] = lhs; - SubExprs[RHS] = rhs; - } + ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t, + ExprValueKind VK, ExprObjectKind OK, SourceLocation RP, + bool condIsTrue) + : Expr(ChooseExprClass, t, VK, OK), BuiltinLoc(BLoc), RParenLoc(RP), + CondIsTrue(condIsTrue) { + SubExprs[COND] = cond; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + + setDependence(computeDependence(this)); + } /// Build an empty __builtin_choose_expr. explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { } @@ -4213,9 +4439,9 @@ class GNUNullExpr : public Expr { public: GNUNullExpr(QualType Ty, SourceLocation Loc) - : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false, - false), - TokenLoc(Loc) { } + : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary), TokenLoc(Loc) { + setDependence(ExprDependence::None); + } /// Build an empty GNU __null expression. explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } @@ -4248,12 +4474,10 @@ class VAArgExpr : public Expr { public: VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo, SourceLocation RPLoc, QualType t, bool IsMS) - : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(), - false, (TInfo->getType()->isInstantiationDependentType() || - e->isInstantiationDependent()), - (TInfo->getType()->containsUnexpandedParameterPack() || - e->containsUnexpandedParameterPack())), - Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {} + : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary), Val(e), + TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) { + setDependence(computeDependence(this)); + } /// Create an empty __builtin_va_arg expression. explicit VAArgExpr(EmptyShell Empty) @@ -4462,13 +4686,8 @@ public: assert(Init < getNumInits() && "Initializer access out of range!"); InitExprs[Init] = expr; - if (expr) { - ExprBits.TypeDependent |= expr->isTypeDependent(); - ExprBits.ValueDependent |= expr->isValueDependent(); - ExprBits.InstantiationDependent |= expr->isInstantiationDependent(); - ExprBits.ContainsUnexpandedParameterPack |= - expr->containsUnexpandedParameterPack(); - } + if (expr) + setDependence(getDependence() | expr->getDependence()); } /// Reserve space for some number of initializers. @@ -4937,8 +5156,9 @@ public: class NoInitExpr : public Expr { public: explicit NoInitExpr(QualType ty) - : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary, - false, false, ty->isInstantiationDependentType(), false) { } + : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary) { + setDependence(computeDependence(this)); + } explicit NoInitExpr(EmptyShell Empty) : Expr(NoInitExprClass, Empty) { } @@ -5032,12 +5252,10 @@ class ArrayInitLoopExpr : public Expr { public: explicit ArrayInitLoopExpr(QualType T, Expr *CommonInit, Expr *ElementInit) - : Expr(ArrayInitLoopExprClass, T, VK_RValue, OK_Ordinary, false, - CommonInit->isValueDependent() || ElementInit->isValueDependent(), - T->isInstantiationDependentType(), - CommonInit->containsUnexpandedParameterPack() || - ElementInit->containsUnexpandedParameterPack()), - SubExprs{CommonInit, ElementInit} {} + : Expr(ArrayInitLoopExprClass, T, VK_RValue, OK_Ordinary), + SubExprs{CommonInit, ElementInit} { + setDependence(computeDependence(this)); + } /// Get the common subexpression shared by all initializations (the source /// array). @@ -5085,8 +5303,9 @@ class ArrayInitIndexExpr : public Expr { public: explicit ArrayInitIndexExpr(QualType T) - : Expr(ArrayInitIndexExprClass, T, VK_RValue, OK_Ordinary, - false, false, false, false) {} + : Expr(ArrayInitIndexExprClass, T, VK_RValue, OK_Ordinary) { + setDependence(ExprDependence::None); + } static bool classof(const Stmt *S) { return S->getStmtClass() == ArrayInitIndexExprClass; @@ -5117,8 +5336,9 @@ public: class ImplicitValueInitExpr : public Expr { public: explicit ImplicitValueInitExpr(QualType ty) - : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary, - false, false, ty->isInstantiationDependentType(), false) { } + : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary) { + setDependence(computeDependence(this)); + } /// Construct an empty implicit value initialization. explicit ImplicitValueInitExpr(EmptyShell Empty) @@ -5277,10 +5497,9 @@ class GenericSelectionExpr final template <bool Const> class AssociationTy { friend class GenericSelectionExpr; template <bool OtherConst> friend class AssociationIteratorTy; - using ExprPtrTy = - typename std::conditional<Const, const Expr *, Expr *>::type; - using TSIPtrTy = typename std::conditional<Const, const TypeSourceInfo *, - TypeSourceInfo *>::type; + using ExprPtrTy = std::conditional_t<Const, const Expr *, Expr *>; + using TSIPtrTy = + std::conditional_t<Const, const TypeSourceInfo *, TypeSourceInfo *>; ExprPtrTy E; TSIPtrTy TSI; bool Selected; @@ -5322,10 +5541,9 @@ class GenericSelectionExpr final // const Association &Assoc = *It++; // Oops, Assoc is dangling. using BaseTy = typename AssociationIteratorTy::iterator_facade_base; using StmtPtrPtrTy = - typename std::conditional<Const, const Stmt *const *, Stmt **>::type; - using TSIPtrPtrTy = - typename std::conditional<Const, const TypeSourceInfo *const *, - TypeSourceInfo **>::type; + std::conditional_t<Const, const Stmt *const *, Stmt **>; + using TSIPtrPtrTy = std::conditional_t<Const, const TypeSourceInfo *const *, + TypeSourceInfo **>; StmtPtrPtrTy E; // = nullptr; FIXME: Once support for gcc 4.8 is dropped. TSIPtrPtrTy TSI; // Kept in sync with E. unsigned Offset = 0, SelectedOffset = 0; @@ -5522,12 +5740,11 @@ class ExtVectorElementExpr : public Expr { public: ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base, IdentifierInfo &accessor, SourceLocation loc) - : Expr(ExtVectorElementExprClass, ty, VK, - (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent), - base->isTypeDependent(), base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - Base(base), Accessor(&accessor), AccessorLoc(loc) {} + : Expr(ExtVectorElementExprClass, ty, VK, + (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent)), + Base(base), Accessor(&accessor), AccessorLoc(loc) { + setDependence(computeDependence(this)); + } /// Build an empty vector element expression. explicit ExtVectorElementExpr(EmptyShell Empty) @@ -5581,11 +5798,9 @@ protected: BlockDecl *TheBlock; public: BlockExpr(BlockDecl *BD, QualType ty) - : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, - ty->isDependentType(), ty->isDependentType(), - ty->isInstantiationDependentType() || BD->isDependentContext(), - false), - TheBlock(BD) {} + : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary), TheBlock(BD) { + setDependence(computeDependence(this)); + } /// Build an empty block expression. explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { } @@ -5649,17 +5864,13 @@ private: explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {} public: - AsTypeExpr(Expr* SrcExpr, QualType DstType, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation BuiltinLoc, SourceLocation RParenLoc) - : Expr(AsTypeExprClass, DstType, VK, OK, - DstType->isDependentType(), - DstType->isDependentType() || SrcExpr->isValueDependent(), - (DstType->isInstantiationDependentType() || - SrcExpr->isInstantiationDependent()), - (DstType->containsUnexpandedParameterPack() || - SrcExpr->containsUnexpandedParameterPack())), - SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} + AsTypeExpr(Expr *SrcExpr, QualType DstType, ExprValueKind VK, + ExprObjectKind OK, SourceLocation BuiltinLoc, + SourceLocation RParenLoc) + : Expr(AsTypeExprClass, DstType, VK, OK), SrcExpr(SrcExpr), + BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) { + setDependence(computeDependence(this)); + } /// getSrcExpr - Return the Expr to be converted. Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } @@ -5976,14 +6187,15 @@ public: /// TypoExpr - Internal placeholder for expressions where typo correction /// still needs to be performed and/or an error diagnostic emitted. class TypoExpr : public Expr { + // The location for the typo name. + SourceLocation TypoLoc; + public: - TypoExpr(QualType T) - : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary, - /*isTypeDependent*/ true, - /*isValueDependent*/ true, - /*isInstantiationDependent*/ true, - /*containsUnexpandedParameterPack*/ false) { + TypoExpr(QualType T, SourceLocation TypoLoc) + : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary), TypoLoc(TypoLoc) { assert(T->isDependentType() && "TypoExpr given a non-dependent type"); + setDependence(ExprDependence::TypeValueInstantiation | + ExprDependence::Error); } child_range children() { @@ -5993,14 +6205,88 @@ public: return const_child_range(const_child_iterator(), const_child_iterator()); } - SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return TypoLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return TypoLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == TypoExprClass; } }; + +/// Frontend produces RecoveryExprs on semantic errors that prevent creating +/// other well-formed expressions. E.g. when type-checking of a binary operator +/// fails, we cannot produce a BinaryOperator expression. Instead, we can choose +/// to produce a recovery expression storing left and right operands. +/// +/// RecoveryExpr does not have any semantic meaning in C++, it is only useful to +/// preserve expressions in AST that would otherwise be dropped. It captures +/// subexpressions of some expression that we could not construct and source +/// range covered by the expression. +/// +/// By default, RecoveryExpr uses dependence-bits to take advantage of existing +/// machinery to deal with dependent code in C++, e.g. RecoveryExpr is preserved +/// in `decltype(<broken-expr>)` as part of the `DependentDecltypeType`. In +/// addition to that, clang does not report most errors on dependent +/// expressions, so we get rid of bogus errors for free. However, note that +/// unlike other dependent expressions, RecoveryExpr can be produced in +/// non-template contexts. +/// +/// We will preserve the type in RecoveryExpr when the type is known, e.g. +/// preserving the return type for a broken non-overloaded function call, a +/// overloaded call where all candidates have the same return type. In this +/// case, the expression is not type-dependent (unless the known type is itself +/// dependent) +/// +/// One can also reliably suppress all bogus errors on expressions containing +/// recovery expressions by examining results of Expr::containsErrors(). +/// +/// FIXME: RecoveryExpr is currently generated by default in C++ mode only, as +/// dependence isn't handled properly on several C-only codepaths. +class RecoveryExpr final : public Expr, + private llvm::TrailingObjects<RecoveryExpr, Expr *> { +public: + static RecoveryExpr *Create(ASTContext &Ctx, QualType T, + SourceLocation BeginLoc, SourceLocation EndLoc, + ArrayRef<Expr *> SubExprs); + static RecoveryExpr *CreateEmpty(ASTContext &Ctx, unsigned NumSubExprs); + + ArrayRef<Expr *> subExpressions() { + auto *B = getTrailingObjects<Expr *>(); + return llvm::makeArrayRef(B, B + NumExprs); + } + + ArrayRef<const Expr *> subExpressions() const { + return const_cast<RecoveryExpr *>(this)->subExpressions(); + } + + child_range children() { + Stmt **B = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); + return child_range(B, B + NumExprs); + } + + SourceLocation getBeginLoc() const { return BeginLoc; } + SourceLocation getEndLoc() const { return EndLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == RecoveryExprClass; + } + +private: + RecoveryExpr(ASTContext &Ctx, QualType T, SourceLocation BeginLoc, + SourceLocation EndLoc, ArrayRef<Expr *> SubExprs); + RecoveryExpr(EmptyShell Empty, unsigned NumSubExprs) + : Expr(RecoveryExprClass, Empty), NumExprs(NumSubExprs) {} + + size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumExprs; } + + SourceLocation BeginLoc, EndLoc; + unsigned NumExprs; + friend TrailingObjects; + friend class ASTStmtReader; + friend class ASTStmtWriter; +}; + } // end namespace clang #endif // LLVM_CLANG_AST_EXPR_H diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 2c29409e0ca5..6f0b68479b9d 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -15,15 +15,18 @@ #define LLVM_CLANG_AST_EXPRCXX_H #include "clang/AST/ASTConcept.h" +#include "clang/AST/ComputeDependence.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/DependenceFlags.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/AST/UnresolvedSet.h" @@ -81,6 +84,7 @@ class CXXOperatorCallExpr final : public CallExpr { friend class ASTStmtWriter; SourceRange Range; + FPOptionsOverride Overrides; // CXXOperatorCallExpr has some trailing objects belonging // to CallExpr. See CallExpr for the details. @@ -89,7 +93,7 @@ class CXXOperatorCallExpr final : public CallExpr { CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, - SourceLocation OperatorLoc, FPOptions FPFeatures, + SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, ADLCallKind UsesADL); CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty); @@ -98,7 +102,7 @@ public: static CXXOperatorCallExpr * Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, - SourceLocation OperatorLoc, FPOptions FPFeatures, + SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, ADLCallKind UsesADL = NotADL); static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx, @@ -119,6 +123,22 @@ public: } bool isAssignmentOp() const { return isAssignmentOp(getOperator()); } + static bool isComparisonOp(OverloadedOperatorKind Opc) { + switch (Opc) { + case OO_EqualEqual: + case OO_ExclaimEqual: + case OO_Greater: + case OO_GreaterEqual: + case OO_Less: + case OO_LessEqual: + case OO_Spaceship: + return true; + default: + return false; + } + } + bool isComparisonOp() const { return isComparisonOp(getOperator()); } + /// Is this written as an infix binary operator? bool isInfixBinaryOp() const; @@ -145,20 +165,10 @@ public: return T->getStmtClass() == CXXOperatorCallExprClass; } - // Set the FP contractability status of this operator. Only meaningful for + // Set the FPFeatures status of this operator. Only meaningful for // operations on floating point types. - void setFPFeatures(FPOptions F) { - CXXOperatorCallExprBits.FPFeatures = F.getInt(); - } - FPOptions getFPFeatures() const { - return FPOptions(CXXOperatorCallExprBits.FPFeatures); - } - - // Get the FP contractability status of this operator. Only meaningful for - // operations on floating point types. - bool isFPContractableWithinStatement() const { - return getFPFeatures().allowFPContractWithinStatement(); - } + void setFPFeatures(FPOptionsOverride F) { Overrides = F; } + FPOptionsOverride getFPFeatures() const { return Overrides; } }; /// Represents a call to a member function that @@ -280,12 +290,10 @@ class CXXRewrittenBinaryOperator : public Expr { public: CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed) : Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(), - SemanticForm->getValueKind(), SemanticForm->getObjectKind(), - SemanticForm->isTypeDependent(), SemanticForm->isValueDependent(), - SemanticForm->isInstantiationDependent(), - SemanticForm->containsUnexpandedParameterPack()), + SemanticForm->getValueKind(), SemanticForm->getObjectKind()), SemanticForm(SemanticForm) { CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed; + setDependence(computeDependence(this)); } CXXRewrittenBinaryOperator(EmptyShell Empty) : Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {} @@ -350,7 +358,8 @@ public: /// This abstract class is inherited by all of the classes /// representing "named" casts: CXXStaticCastExpr for \c static_cast, /// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for -/// reinterpret_cast, and CXXConstCastExpr for \c const_cast. +/// reinterpret_cast, CXXConstCastExpr for \c const_cast and +/// CXXAddrspaceCastExpr for addrspace_cast (in OpenCL). class CXXNamedCastExpr : public ExplicitCastExpr { private: // the location of the casting op @@ -396,6 +405,7 @@ public: case CXXDynamicCastExprClass: case CXXReinterpretCastExprClass: case CXXConstCastExprClass: + case CXXAddrspaceCastExprClass: return true; default: return false; @@ -553,6 +563,41 @@ public: } }; +/// A C++ addrspace_cast expression (currently only enabled for OpenCL). +/// +/// This expression node represents a cast between pointers to objects in +/// different address spaces e.g., +/// \c addrspace_cast<global int*>(PtrToGenericInt). +/// +/// A addrspace_cast can cast address space type qualifiers but does not change +/// the underlying value. +class CXXAddrspaceCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXAddrspaceCastExpr, CXXBaseSpecifier *> { + CXXAddrspaceCastExpr(QualType ty, ExprValueKind VK, CastKind Kind, Expr *op, + TypeSourceInfo *writtenTy, SourceLocation l, + SourceLocation RParenLoc, SourceRange AngleBrackets) + : CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK, Kind, op, 0, + writtenTy, l, RParenLoc, AngleBrackets) {} + + explicit CXXAddrspaceCastExpr(EmptyShell Empty) + : CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0) {} + +public: + friend class CastExpr; + friend TrailingObjects; + + static CXXAddrspaceCastExpr * + Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, + Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation RParenLoc, SourceRange AngleBrackets); + static CXXAddrspaceCastExpr *CreateEmpty(const ASTContext &Context); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXAddrspaceCastExprClass; + } +}; + /// A call to a literal operator (C++11 [over.literal]) /// written as a user-defined literal (C++11 [lit.ext]). /// @@ -646,10 +691,10 @@ public: class CXXBoolLiteralExpr : public Expr { public: CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc) - : Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false) { + : Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary) { CXXBoolLiteralExprBits.Value = Val; CXXBoolLiteralExprBits.Loc = Loc; + setDependence(ExprDependence::None); } explicit CXXBoolLiteralExpr(EmptyShell Empty) @@ -684,9 +729,9 @@ public: class CXXNullPtrLiteralExpr : public Expr { public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc) - : Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, - false, false, false) { + : Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary) { CXXNullPtrLiteralExprBits.Loc = Loc; + setDependence(ExprDependence::None); } explicit CXXNullPtrLiteralExpr(EmptyShell Empty) @@ -724,11 +769,10 @@ public: friend class ASTStmtReader; CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) - : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary, - Ty->isDependentType(), SubExpr->isValueDependent(), - SubExpr->isInstantiationDependent(), - SubExpr->containsUnexpandedParameterPack()), - SubExpr(SubExpr) {} + : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary), + SubExpr(SubExpr) { + setDependence(computeDependence(this)); + } Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); } const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); } @@ -763,32 +807,24 @@ public: /// /// This represents code like \c typeid(int) or \c typeid(*objPtr) class CXXTypeidExpr : public Expr { + friend class ASTStmtReader; + private: llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; SourceRange Range; public: CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) - : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, - // typeid is never type-dependent (C++ [temp.dep.expr]p4) - false, - // typeid is value-dependent if the type or expression are - // dependent - Operand->getType()->isDependentType(), - Operand->getType()->isInstantiationDependentType(), - Operand->getType()->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) {} + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Range(R) { + setDependence(computeDependence(this)); + } CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) - : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, - // typeid is never type-dependent (C++ [temp.dep.expr]p4) - false, - // typeid is value-dependent if the type or expression are - // dependent - Operand->isTypeDependent() || Operand->isValueDependent(), - Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) {} + : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Range(R) { + setDependence(computeDependence(this)); + } CXXTypeidExpr(EmptyShell Empty, bool isExpr) : Expr(CXXTypeidExprClass, Empty) { @@ -813,22 +849,11 @@ public: assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); return Operand.get<TypeSourceInfo *>(); } - - void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { - assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); - Operand = TSI; - } - Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); return static_cast<Expr*>(Operand.get<Stmt *>()); } - void setExprOperand(Expr *E) { - assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); - Operand = E; - } - SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } @@ -873,15 +898,12 @@ public: MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow, QualType ty, ExprValueKind VK, - NestedNameSpecifierLoc qualifierLoc, - SourceLocation nameLoc) - : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary, - /*type-dependent*/ false, baseExpr->isValueDependent(), - baseExpr->isInstantiationDependent(), - baseExpr->containsUnexpandedParameterPack()), - BaseExpr(baseExpr), TheDecl(decl), - MemberLoc(nameLoc), IsArrow(isArrow), - QualifierLoc(qualifierLoc) {} + NestedNameSpecifierLoc qualifierLoc, SourceLocation nameLoc) + : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary), BaseExpr(baseExpr), + TheDecl(decl), MemberLoc(nameLoc), IsArrow(isArrow), + QualifierLoc(qualifierLoc) { + setDependence(computeDependence(this)); + } MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} @@ -949,12 +971,11 @@ class MSPropertySubscriptExpr : public Expr { public: MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK, ExprObjectKind OK, SourceLocation RBracketLoc) - : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(), - Idx->isValueDependent(), Idx->isInstantiationDependent(), - Idx->containsUnexpandedParameterPack()), + : Expr(MSPropertySubscriptExprClass, Ty, VK, OK), RBracketLoc(RBracketLoc) { SubExprs[BASE_EXPR] = Base; SubExprs[IDX_EXPR] = Idx; + setDependence(computeDependence(this)); } /// Create an empty array subscript expression. @@ -999,25 +1020,26 @@ public: /// /// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr) class CXXUuidofExpr : public Expr { + friend class ASTStmtReader; + private: llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; - StringRef UuidStr; + MSGuidDecl *Guid; SourceRange Range; public: - CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, StringRef UuidStr, + CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, MSGuidDecl *Guid, SourceRange R) - : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, - Operand->getType()->isDependentType(), - Operand->getType()->isInstantiationDependentType(), - Operand->getType()->containsUnexpandedParameterPack()), - Operand(Operand), UuidStr(UuidStr), Range(R) {} - - CXXUuidofExpr(QualType Ty, Expr *Operand, StringRef UuidStr, SourceRange R) - : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, - Operand->isTypeDependent(), Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Operand(Operand), UuidStr(UuidStr), Range(R) {} + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Guid(Guid), Range(R) { + setDependence(computeDependence(this)); + } + + CXXUuidofExpr(QualType Ty, Expr *Operand, MSGuidDecl *Guid, SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), + Guid(Guid), Range(R) { + setDependence(computeDependence(this)); + } CXXUuidofExpr(EmptyShell Empty, bool isExpr) : Expr(CXXUuidofExprClass, Empty) { @@ -1038,24 +1060,12 @@ public: assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); return Operand.get<TypeSourceInfo *>(); } - - void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { - assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); - Operand = TSI; - } - Expr *getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); return static_cast<Expr*>(Operand.get<Stmt *>()); } - void setExprOperand(Expr *E) { - assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); - Operand = E; - } - - void setUuidStr(StringRef US) { UuidStr = US; } - StringRef getUuidStr() const { return UuidStr; } + MSGuidDecl *getGuidDecl() const { return Guid; } SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } @@ -1098,14 +1108,10 @@ public: class CXXThisExpr : public Expr { public: CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit) - : Expr(CXXThisExprClass, Ty, VK_RValue, OK_Ordinary, - // 'this' is type-dependent if the class type of the enclosing - // member function is dependent (C++ [temp.dep.expr]p2) - Ty->isDependentType(), Ty->isDependentType(), - Ty->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false) { + : Expr(CXXThisExprClass, Ty, VK_RValue, OK_Ordinary) { CXXThisExprBits.IsImplicit = IsImplicit; CXXThisExprBits.Loc = L; + setDependence(computeDependence(this)); } CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} @@ -1151,12 +1157,10 @@ public: // null if not present. CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc, bool IsThrownVariableInScope) - : Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - Operand && Operand->isInstantiationDependent(), - Operand && Operand->containsUnexpandedParameterPack()), - Operand(Operand) { + : Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary), Operand(Operand) { CXXThrowExprBits.ThrowLoc = Loc; CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope; + setDependence(computeDependence(this)); } CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} @@ -1210,16 +1214,16 @@ class CXXDefaultArgExpr final : public Expr { DeclContext *UsedContext; CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param, - DeclContext *UsedContext) + DeclContext *UsedContext) : Expr(SC, Param->hasUnparsedDefaultArg() ? Param->getType().getNonReferenceType() : Param->getDefaultArg()->getType(), Param->getDefaultArg()->getValueKind(), - Param->getDefaultArg()->getObjectKind(), false, false, false, - false), + Param->getDefaultArg()->getObjectKind()), Param(Param), UsedContext(UsedContext) { CXXDefaultArgExprBits.Loc = Loc; + setDependence(ExprDependence::None); } public: @@ -1375,13 +1379,12 @@ class CXXBindTemporaryExpr : public Expr { CXXTemporary *Temp = nullptr; Stmt *SubExpr = nullptr; - CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr) - : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), - VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), - SubExpr->isValueDependent(), - SubExpr->isInstantiationDependent(), - SubExpr->containsUnexpandedParameterPack()), - Temp(temp), SubExpr(SubExpr) {} + CXXBindTemporaryExpr(CXXTemporary *temp, Expr *SubExpr) + : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), VK_RValue, + OK_Ordinary), + Temp(temp), SubExpr(SubExpr) { + setDependence(computeDependence(this)); + } public: CXXBindTemporaryExpr(EmptyShell Empty) @@ -1632,12 +1635,12 @@ public: CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T, CXXConstructorDecl *Ctor, bool ConstructsVirtualBase, bool InheritedFromVirtualBase) - : Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary, false, - false, false, false), + : Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary), Constructor(Ctor), Loc(Loc), ConstructsVirtualBase(ConstructsVirtualBase), InheritedFromVirtualBase(InheritedFromVirtualBase) { assert(!T->isDependentType()); + setDependence(ExprDependence::None); } /// Construct an empty C++ inheriting construction expression. @@ -1818,26 +1821,14 @@ Stmt **CXXConstructExpr::getTrailingArgs() { /// and which can never occur implicitly. class LambdaExpr final : public Expr, private llvm::TrailingObjects<LambdaExpr, Stmt *> { + // LambdaExpr has some data stored in LambdaExprBits. + /// The source range that covers the lambda introducer ([...]). SourceRange IntroducerRange; /// The source location of this lambda's capture-default ('=' or '&'). SourceLocation CaptureDefaultLoc; - /// The number of captures. - unsigned NumCaptures : 16; - - /// The default capture kind, which is a value of type - /// LambdaCaptureDefault. - unsigned CaptureDefault : 2; - - /// Whether this lambda had an explicit parameter list vs. an - /// implicit (and empty) parameter list. - unsigned ExplicitParams : 1; - - /// Whether this lambda had the result type explicitly specified. - unsigned ExplicitResultType : 1; - /// The location of the closing brace ('}') that completes /// the lambda. /// @@ -1851,23 +1842,18 @@ class LambdaExpr final : public Expr, /// Construct a lambda expression. LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, - SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, - bool ExplicitParams, bool ExplicitResultType, - ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace, - bool ContainsUnexpandedParameterPack); + SourceLocation CaptureDefaultLoc, bool ExplicitParams, + bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, + SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); /// Construct an empty lambda expression. - LambdaExpr(EmptyShell Empty, unsigned NumCaptures) - : Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures), - CaptureDefault(LCD_None), ExplicitParams(false), - ExplicitResultType(false) { - getStoredStmts()[NumCaptures] = nullptr; - } + LambdaExpr(EmptyShell Empty, unsigned NumCaptures); Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } - Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } + void initBodyIfNeeded() const; + public: friend class ASTStmtReader; friend class ASTStmtWriter; @@ -1877,9 +1863,9 @@ public: static LambdaExpr * Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, - ArrayRef<LambdaCapture> Captures, bool ExplicitParams, - bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, - SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); + bool ExplicitParams, bool ExplicitResultType, + ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace, + bool ContainsUnexpandedParameterPack); /// Construct a new lambda expression that will be deserialized from /// an external source. @@ -1888,13 +1874,11 @@ public: /// Determine the default capture kind for this lambda. LambdaCaptureDefault getCaptureDefault() const { - return static_cast<LambdaCaptureDefault>(CaptureDefault); + return static_cast<LambdaCaptureDefault>(LambdaExprBits.CaptureDefault); } /// Retrieve the location of this lambda's capture-default, if any. - SourceLocation getCaptureDefaultLoc() const { - return CaptureDefaultLoc; - } + SourceLocation getCaptureDefaultLoc() const { return CaptureDefaultLoc; } /// Determine whether one of this lambda's captures is an init-capture. bool isInitCapture(const LambdaCapture *Capture) const; @@ -1917,7 +1901,7 @@ public: capture_iterator capture_end() const; /// Determine the number of captures in this lambda. - unsigned capture_size() const { return NumCaptures; } + unsigned capture_size() const { return LambdaExprBits.NumCaptures; } /// Retrieve this lambda's explicit captures. capture_range explicit_captures() const; @@ -1947,6 +1931,7 @@ public: /// Const iterator that walks over the capture initialization /// arguments. + /// FIXME: This interface is prone to being used incorrectly. using const_capture_init_iterator = Expr *const *; /// Retrieve the initialization expressions for this lambda's captures. @@ -1974,13 +1959,13 @@ public: /// Retrieve the iterator pointing one past the last /// initialization argument for this lambda expression. capture_init_iterator capture_init_end() { - return capture_init_begin() + NumCaptures; + return capture_init_begin() + capture_size(); } /// Retrieve the iterator pointing one past the last /// initialization argument for this lambda expression. const_capture_init_iterator capture_init_end() const { - return capture_init_begin() + NumCaptures; + return capture_init_begin() + capture_size(); } /// Retrieve the source range covering the lambda introducer, @@ -2014,8 +1999,20 @@ public: /// Whether this is a generic lambda. bool isGenericLambda() const { return getTemplateParameterList(); } - /// Retrieve the body of the lambda. - CompoundStmt *getBody() const; + /// Retrieve the body of the lambda. This will be most of the time + /// a \p CompoundStmt, but can also be \p CoroutineBodyStmt wrapping + /// a \p CompoundStmt. Note that unlike functions, lambda-expressions + /// cannot have a function-try-block. + Stmt *getBody() const; + + /// Retrieve the \p CompoundStmt representing the body of the lambda. + /// This is a convenience function for callers who do not need + /// to handle node(s) which may wrap a \p CompoundStmt. + const CompoundStmt *getCompoundStmtBody() const; + CompoundStmt *getCompoundStmtBody() { + const auto *ConstThis = this; + return const_cast<CompoundStmt *>(ConstThis->getCompoundStmtBody()); + } /// Determine whether the lambda is mutable, meaning that any /// captures values can be modified. @@ -2023,10 +2020,12 @@ public: /// Determine whether this lambda has an explicit parameter /// list vs. an implicit (empty) parameter list. - bool hasExplicitParameters() const { return ExplicitParams; } + bool hasExplicitParameters() const { return LambdaExprBits.ExplicitParams; } /// Whether this lambda had its result type explicitly specified. - bool hasExplicitResultType() const { return ExplicitResultType; } + bool hasExplicitResultType() const { + return LambdaExprBits.ExplicitResultType; + } static bool classof(const Stmt *T) { return T->getStmtClass() == LambdaExprClass; @@ -2038,15 +2037,9 @@ public: SourceLocation getEndLoc() const LLVM_READONLY { return ClosingBrace; } - child_range children() { - // Includes initialization exprs plus body stmt - return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1); - } - - const_child_range children() const { - return const_child_range(getStoredStmts(), - getStoredStmts() + NumCaptures + 1); - } + /// Includes the captures and the body of the lambda. + child_range children(); + const_child_range children() const; }; /// An expression "T()" which creates a value-initialized rvalue of type @@ -2061,11 +2054,10 @@ public: /// expression. CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, SourceLocation RParenLoc) - : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, false, - false, Type->isInstantiationDependentType(), - Type->containsUnexpandedParameterPack()), + : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary), TypeInfo(TypeInfo) { CXXScalarValueInitExprBits.RParenLoc = RParenLoc; + setDependence(computeDependence(this)); } explicit CXXScalarValueInitExpr(EmptyShell Shell) @@ -2370,15 +2362,14 @@ public: CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm, bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize, FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc) - : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false, - Arg->isValueDependent(), Arg->isInstantiationDependent(), - Arg->containsUnexpandedParameterPack()), + : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary), OperatorDelete(OperatorDelete), Argument(Arg) { CXXDeleteExprBits.GlobalDelete = GlobalDelete; CXXDeleteExprBits.ArrayForm = ArrayForm; CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten; CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; CXXDeleteExprBits.Loc = Loc; + setDependence(computeDependence(this)); } explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {} @@ -2736,15 +2727,15 @@ public: friend class ASTStmtReader; ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, - TypeSourceInfo *queried, uint64_t value, - Expr *dimension, SourceLocation rparen, QualType ty) - : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, - false, queried->getType()->isDependentType(), - (queried->getType()->isInstantiationDependentType() || - (dimension && dimension->isInstantiationDependent())), - queried->getType()->containsUnexpandedParameterPack()), - ATT(att), Value(value), Dimension(dimension), - Loc(loc), RParen(rparen), QueriedType(queried) {} + TypeSourceInfo *queried, uint64_t value, Expr *dimension, + SourceLocation rparen, QualType ty) + : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary), ATT(att), + Value(value), Dimension(dimension), Loc(loc), RParen(rparen), + QueriedType(queried) { + assert(att <= ATT_Last && "invalid enum value!"); + assert(static_cast<unsigned>(att) == ATT && "ATT overflow!"); + setDependence(computeDependence(this)); + } explicit ArrayTypeTraitExpr(EmptyShell Empty) : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {} @@ -2802,17 +2793,15 @@ class ExpressionTraitExpr : public Expr { public: friend class ASTStmtReader; - ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, - Expr *queried, bool value, - SourceLocation rparen, QualType resultType) - : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, - false, // Not type-dependent - // Value-dependent if the argument is type-dependent. - queried->isTypeDependent(), - queried->isInstantiationDependent(), - queried->containsUnexpandedParameterPack()), + ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried, + bool value, SourceLocation rparen, QualType resultType) + : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary), ET(et), Value(value), Loc(loc), RParen(rparen), - QueriedExpression(queried) {} + QueriedExpression(queried) { + assert(et <= ET_Last && "invalid enum value!"); + assert(static_cast<unsigned>(et) == ET && "ET overflow!"); + setDependence(computeDependence(this)); + } explicit ExpressionTraitExpr(EmptyShell Empty) : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {} @@ -3306,13 +3295,15 @@ public: /// literal is the extent of the enclosing scope. class ExprWithCleanups final : public FullExpr, - private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> { + private llvm::TrailingObjects< + ExprWithCleanups, + llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>> { public: /// The type of objects that are kept in the cleanup. - /// It's useful to remember the set of blocks; we could also - /// remember the set of temporaries, but there's currently - /// no need. - using CleanupObject = BlockDecl *; + /// It's useful to remember the set of blocks and block-scoped compound + /// literals; we could also remember the set of temporaries, but there's + /// currently no need. + using CleanupObject = llvm::PointerUnion<BlockDecl *, CompoundLiteralExpr *>; private: friend class ASTStmtReader; @@ -3965,13 +3956,10 @@ class CXXNoexceptExpr : public Expr { public: CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val, SourceLocation Keyword, SourceLocation RParen) - : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary, - /*TypeDependent*/ false, - /*ValueDependent*/ Val == CT_Dependent, - Val == CT_Dependent || Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), + : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary), Operand(Operand), Range(Keyword, RParen) { CXXNoexceptExprBits.Value = Val == CT_Cannot; + setDependence(computeDependence(this, Val)); } CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {} @@ -4032,12 +4020,12 @@ public: PackExpansionExpr(QualType T, Expr *Pattern, SourceLocation EllipsisLoc, Optional<unsigned> NumExpansions) : Expr(PackExpansionExprClass, T, Pattern->getValueKind(), - Pattern->getObjectKind(), /*TypeDependent=*/true, - /*ValueDependent=*/true, /*InstantiationDependent=*/true, - /*ContainsUnexpandedParameterPack=*/false), + Pattern->getObjectKind()), EllipsisLoc(EllipsisLoc), NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), - Pattern(Pattern) {} + Pattern(Pattern) { + setDependence(computeDependence(this)); + } PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {} @@ -4124,17 +4112,17 @@ class SizeOfPackExpr final /// the given parameter pack. SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, - Optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs) - : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/!Length, - /*InstantiationDependent=*/!Length, - /*ContainsUnexpandedParameterPack=*/false), + Optional<unsigned> Length, + ArrayRef<TemplateArgument> PartialArgs) + : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary), OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), Length(Length ? *Length : PartialArgs.size()), Pack(Pack) { assert((!Length || PartialArgs.empty()) && "have partial args for non-dependent sizeof... expression"); auto *Args = getTrailingObjects<TemplateArgument>(); std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args); + setDependence(Length ? ExprDependence::None + : ExprDependence::ValueInstantiation); } /// Create an empty expression. @@ -4225,12 +4213,10 @@ public: SourceLocation Loc, NonTypeTemplateParmDecl *Param, Expr *Replacement) - : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary, - Replacement->isTypeDependent(), Replacement->isValueDependent(), - Replacement->isInstantiationDependent(), - Replacement->containsUnexpandedParameterPack()), + : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary), Param(Param), Replacement(Replacement) { SubstNonTypeTemplateParmExprBits.NameLoc = Loc; + setDependence(computeDependence(this)); } SourceLocation getNameLoc() const { @@ -4544,13 +4530,12 @@ public: CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc, Optional<unsigned> NumExpansions) - : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary, - /*Dependent*/ true, true, true, - /*ContainsUnexpandedParameterPack*/ false), - LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), + : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary), LParenLoc(LParenLoc), + EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) { SubExprs[0] = LHS; SubExprs[1] = RHS; + setDependence(computeDependence(this)); } CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} @@ -4625,27 +4610,25 @@ public: Expr *Ready, Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue) : Expr(SC, Resume->getType(), Resume->getValueKind(), - Resume->getObjectKind(), Resume->isTypeDependent(), - Resume->isValueDependent(), Common->isInstantiationDependent(), - Common->containsUnexpandedParameterPack()), + Resume->getObjectKind()), KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) { SubExprs[SubExpr::Common] = Common; SubExprs[SubExpr::Ready] = Ready; SubExprs[SubExpr::Suspend] = Suspend; SubExprs[SubExpr::Resume] = Resume; + setDependence(computeDependence(this)); } CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty, Expr *Common) - : Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true, - Common->containsUnexpandedParameterPack()), - KeywordLoc(KeywordLoc) { + : Expr(SC, Ty, VK_RValue, OK_Ordinary), KeywordLoc(KeywordLoc) { assert(Common->isTypeDependent() && Ty->isDependentType() && "wrong constructor for non-dependent co_await/co_yield expression"); SubExprs[SubExpr::Common] = Common; SubExprs[SubExpr::Ready] = nullptr; SubExprs[SubExpr::Suspend] = nullptr; SubExprs[SubExpr::Resume] = nullptr; + setDependence(computeDependence(this)); } CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { @@ -4742,10 +4725,7 @@ class DependentCoawaitExpr : public Expr { public: DependentCoawaitExpr(SourceLocation KeywordLoc, QualType Ty, Expr *Op, UnresolvedLookupExpr *OpCoawait) - : Expr(DependentCoawaitExprClass, Ty, VK_RValue, OK_Ordinary, - /*TypeDependent*/ true, /*ValueDependent*/ true, - /*InstantiationDependent*/ true, - Op->containsUnexpandedParameterPack()), + : Expr(DependentCoawaitExprClass, Ty, VK_RValue, OK_Ordinary), KeywordLoc(KeywordLoc) { // NOTE: A co_await expression is dependent on the coroutines promise // type and may be dependent even when the `Op` expression is not. @@ -4753,6 +4733,7 @@ public: "wrong constructor for non-dependent co_await/co_yield expression"); SubExprs[0] = Op; SubExprs[1] = OpCoawait; + setDependence(computeDependence(this)); } DependentCoawaitExpr(EmptyShell Empty) @@ -4827,6 +4808,8 @@ public: : ExplicitCastExpr(BuiltinBitCastExprClass, T, VK, CK, SrcExpr, 0, DstType), KWLoc(KWLoc), RParenLoc(RParenLoc) {} + BuiltinBitCastExpr(EmptyShell Empty) + : ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0) {} SourceLocation getBeginLoc() const LLVM_READONLY { return KWLoc; } SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } @@ -4836,99 +4819,6 @@ public: } }; -/// \brief Represents the specialization of a concept - evaluates to a prvalue -/// of type bool. -/// -/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the -/// specialization of a concept results in a prvalue of type bool. -class ConceptSpecializationExpr final : public Expr, public ConceptReference, - private llvm::TrailingObjects<ConceptSpecializationExpr, - TemplateArgument> { - friend class ASTStmtReader; - friend TrailingObjects; -public: - using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>; - -protected: - /// \brief The number of template arguments in the tail-allocated list of - /// converted template arguments. - unsigned NumTemplateArgs; - - /// \brief Information about the satisfaction of the named concept with the - /// given arguments. If this expression is value dependent, this is to be - /// ignored. - ASTConstraintSatisfaction *Satisfaction; - - ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, - DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef<TemplateArgument> ConvertedArgs, - const ConstraintSatisfaction *Satisfaction); - - ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); - -public: - - static ConceptSpecializationExpr * - Create(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef<TemplateArgument> ConvertedArgs, - const ConstraintSatisfaction *Satisfaction); - - static ConceptSpecializationExpr * - Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); - - ArrayRef<TemplateArgument> getTemplateArguments() const { - return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(), - NumTemplateArgs); - } - - /// \brief Set new template arguments for this concept specialization. - void setTemplateArguments(ArrayRef<TemplateArgument> Converted); - - /// \brief Whether or not the concept with the given arguments was satisfied - /// when the expression was created. - /// The expression must not be dependent. - bool isSatisfied() const { - assert(!isValueDependent() - && "isSatisfied called on a dependent ConceptSpecializationExpr"); - return Satisfaction->IsSatisfied; - } - - /// \brief Get elaborated satisfaction info about the template arguments' - /// satisfaction of the named concept. - /// The expression must not be dependent. - const ASTConstraintSatisfaction &getSatisfaction() const { - assert(!isValueDependent() - && "getSatisfaction called on dependent ConceptSpecializationExpr"); - return *Satisfaction; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ConceptSpecializationExprClass; - } - - SourceLocation getBeginLoc() const LLVM_READONLY { - return ConceptName.getBeginLoc(); - } - - SourceLocation getEndLoc() const LLVM_READONLY { - return ArgsAsWritten->RAngleLoc; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } -}; - } // namespace clang #endif // LLVM_CLANG_AST_EXPRCXX_H diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h new file mode 100644 index 000000000000..2a88ed5175d2 --- /dev/null +++ b/clang/include/clang/AST/ExprConcepts.h @@ -0,0 +1,554 @@ +//===- ExprConcepts.h - C++2a Concepts expressions --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Defines Expressions and AST nodes for C++2a concepts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPRCONCEPTS_H +#define LLVM_CLANG_AST_EXPRCONCEPTS_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTConcept.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/Support/TrailingObjects.h" +#include <utility> +#include <string> + +namespace clang { +class ASTStmtReader; +class ASTStmtWriter; + +/// \brief Represents the specialization of a concept - evaluates to a prvalue +/// of type bool. +/// +/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the +/// specialization of a concept results in a prvalue of type bool. +class ConceptSpecializationExpr final : public Expr, public ConceptReference, + private llvm::TrailingObjects<ConceptSpecializationExpr, + TemplateArgument> { + friend class ASTStmtReader; + friend TrailingObjects; +public: + using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>; + +protected: + /// \brief The number of template arguments in the tail-allocated list of + /// converted template arguments. + unsigned NumTemplateArgs; + + /// \brief Information about the satisfaction of the named concept with the + /// given arguments. If this expression is value dependent, this is to be + /// ignored. + ASTConstraintSatisfaction *Satisfaction; + + ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, + DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef<TemplateArgument> ConvertedArgs, + const ConstraintSatisfaction *Satisfaction); + + ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept, + ArrayRef<TemplateArgument> ConvertedArgs, + const ConstraintSatisfaction *Satisfaction, + bool Dependent, + bool ContainsUnexpandedParameterPack); + + ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); + +public: + + static ConceptSpecializationExpr * + Create(const ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef<TemplateArgument> ConvertedArgs, + const ConstraintSatisfaction *Satisfaction); + + static ConceptSpecializationExpr * + Create(const ASTContext &C, ConceptDecl *NamedConcept, + ArrayRef<TemplateArgument> ConvertedArgs, + const ConstraintSatisfaction *Satisfaction, + bool Dependent, + bool ContainsUnexpandedParameterPack); + + static ConceptSpecializationExpr * + Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); + + ArrayRef<TemplateArgument> getTemplateArguments() const { + return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(), + NumTemplateArgs); + } + + /// \brief Set new template arguments for this concept specialization. + void setTemplateArguments(ArrayRef<TemplateArgument> Converted); + + /// \brief Whether or not the concept with the given arguments was satisfied + /// when the expression was created. + /// The expression must not be dependent. + bool isSatisfied() const { + assert(!isValueDependent() + && "isSatisfied called on a dependent ConceptSpecializationExpr"); + return Satisfaction->IsSatisfied; + } + + /// \brief Get elaborated satisfaction info about the template arguments' + /// satisfaction of the named concept. + /// The expression must not be dependent. + const ASTConstraintSatisfaction &getSatisfaction() const { + assert(!isValueDependent() + && "getSatisfaction called on dependent ConceptSpecializationExpr"); + return *Satisfaction; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConceptSpecializationExprClass; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return ConceptName.getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + return ArgsAsWritten->RAngleLoc; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +namespace concepts { + +/// \brief A static requirement that can be used in a requires-expression to +/// check properties of types and expression. +class Requirement { +public: + // Note - simple and compound requirements are both represented by the same + // class (ExprRequirement). + enum RequirementKind { RK_Type, RK_Simple, RK_Compound, RK_Nested }; +private: + const RequirementKind Kind; + // FIXME: use RequirementDependence to model dependence? + bool Dependent : 1; + bool ContainsUnexpandedParameterPack : 1; + bool Satisfied : 1; +public: + struct SubstitutionDiagnostic { + StringRef SubstitutedEntity; + // FIXME: Store diagnostics semantically and not as prerendered strings. + // Fixing this probably requires serialization of PartialDiagnostic + // objects. + SourceLocation DiagLoc; + StringRef DiagMessage; + }; + + Requirement(RequirementKind Kind, bool IsDependent, + bool ContainsUnexpandedParameterPack, bool IsSatisfied = true) : + Kind(Kind), Dependent(IsDependent), + ContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack), + Satisfied(IsSatisfied) {} + + RequirementKind getKind() const { return Kind; } + + bool isSatisfied() const { + assert(!Dependent && + "isSatisfied can only be called on non-dependent requirements."); + return Satisfied; + } + + void setSatisfied(bool IsSatisfied) { + assert(!Dependent && + "setSatisfied can only be called on non-dependent requirements."); + Satisfied = IsSatisfied; + } + + void setDependent(bool IsDependent) { Dependent = IsDependent; } + bool isDependent() const { return Dependent; } + + void setContainsUnexpandedParameterPack(bool Contains) { + ContainsUnexpandedParameterPack = Contains; + } + bool containsUnexpandedParameterPack() const { + return ContainsUnexpandedParameterPack; + } +}; + +/// \brief A requires-expression requirement which queries the existence of a +/// type name or type template specialization ('type' requirements). +class TypeRequirement : public Requirement { +public: + enum SatisfactionStatus { + SS_Dependent, + SS_SubstitutionFailure, + SS_Satisfied + }; +private: + llvm::PointerUnion<SubstitutionDiagnostic *, TypeSourceInfo *> Value; + SatisfactionStatus Status; +public: + friend ASTStmtReader; + friend ASTStmtWriter; + + /// \brief Construct a type requirement from a type. If the given type is not + /// dependent, this indicates that the type exists and the requirement will be + /// satisfied. Otherwise, the SubstitutionDiagnostic constructor is to be + /// used. + TypeRequirement(TypeSourceInfo *T); + + /// \brief Construct a type requirement when the nested name specifier is + /// invalid due to a bad substitution. The requirement is unsatisfied. + TypeRequirement(SubstitutionDiagnostic *Diagnostic) : + Requirement(RK_Type, false, false, false), Value(Diagnostic), + Status(SS_SubstitutionFailure) {} + + SatisfactionStatus getSatisfactionStatus() const { return Status; } + void setSatisfactionStatus(SatisfactionStatus Status) { + this->Status = Status; + } + + bool isSubstitutionFailure() const { + return Status == SS_SubstitutionFailure; + } + + SubstitutionDiagnostic *getSubstitutionDiagnostic() const { + assert(Status == SS_SubstitutionFailure && + "Attempted to get substitution diagnostic when there has been no " + "substitution failure."); + return Value.get<SubstitutionDiagnostic *>(); + } + + TypeSourceInfo *getType() const { + assert(!isSubstitutionFailure() && + "Attempted to get type when there has been a substitution failure."); + return Value.get<TypeSourceInfo *>(); + } + + static bool classof(const Requirement *R) { + return R->getKind() == RK_Type; + } +}; + +/// \brief A requires-expression requirement which queries the validity and +/// properties of an expression ('simple' and 'compound' requirements). +class ExprRequirement : public Requirement { +public: + enum SatisfactionStatus { + SS_Dependent, + SS_ExprSubstitutionFailure, + SS_NoexceptNotMet, + SS_TypeRequirementSubstitutionFailure, + SS_ConstraintsNotSatisfied, + SS_Satisfied + }; + class ReturnTypeRequirement { + llvm::PointerIntPair< + llvm::PointerUnion<TemplateParameterList *, SubstitutionDiagnostic *>, + 1, bool> + TypeConstraintInfo; + public: + friend ASTStmtReader; + friend ASTStmtWriter; + + /// \brief No return type requirement was specified. + ReturnTypeRequirement() : TypeConstraintInfo(nullptr, 0) {} + + /// \brief A return type requirement was specified but it was a + /// substitution failure. + ReturnTypeRequirement(SubstitutionDiagnostic *SubstDiag) : + TypeConstraintInfo(SubstDiag, 0) {} + + /// \brief A 'type constraint' style return type requirement. + /// \param TPL an invented template parameter list containing a single + /// type parameter with a type-constraint. + // TODO: Can we maybe not save the whole template parameter list and just + // the type constraint? Saving the whole TPL makes it easier to handle in + // serialization but is less elegant. + ReturnTypeRequirement(TemplateParameterList *TPL); + + bool isDependent() const { + return TypeConstraintInfo.getInt(); + } + + bool containsUnexpandedParameterPack() const { + if (!isTypeConstraint()) + return false; + return getTypeConstraintTemplateParameterList() + ->containsUnexpandedParameterPack(); + } + + bool isEmpty() const { + return TypeConstraintInfo.getPointer().isNull(); + } + + bool isSubstitutionFailure() const { + return !isEmpty() && + TypeConstraintInfo.getPointer().is<SubstitutionDiagnostic *>(); + } + + bool isTypeConstraint() const { + return !isEmpty() && + TypeConstraintInfo.getPointer().is<TemplateParameterList *>(); + } + + SubstitutionDiagnostic *getSubstitutionDiagnostic() const { + assert(isSubstitutionFailure()); + return TypeConstraintInfo.getPointer().get<SubstitutionDiagnostic *>(); + } + + const TypeConstraint *getTypeConstraint() const; + + TemplateParameterList *getTypeConstraintTemplateParameterList() const { + assert(isTypeConstraint()); + return TypeConstraintInfo.getPointer().get<TemplateParameterList *>(); + } + }; +private: + llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value; + SourceLocation NoexceptLoc; // May be empty if noexcept wasn't specified. + ReturnTypeRequirement TypeReq; + ConceptSpecializationExpr *SubstitutedConstraintExpr; + SatisfactionStatus Status; +public: + friend ASTStmtReader; + friend ASTStmtWriter; + + /// \brief Construct a compound requirement. + /// \param E the expression which is checked by this requirement. + /// \param IsSimple whether this was a simple requirement in source. + /// \param NoexceptLoc the location of the noexcept keyword, if it was + /// specified, otherwise an empty location. + /// \param Req the requirement for the type of the checked expression. + /// \param Status the satisfaction status of this requirement. + ExprRequirement( + Expr *E, bool IsSimple, SourceLocation NoexceptLoc, + ReturnTypeRequirement Req, SatisfactionStatus Status, + ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr); + + /// \brief Construct a compound requirement whose expression was a + /// substitution failure. The requirement is not satisfied. + /// \param E the diagnostic emitted while instantiating the original + /// expression. + /// \param IsSimple whether this was a simple requirement in source. + /// \param NoexceptLoc the location of the noexcept keyword, if it was + /// specified, otherwise an empty location. + /// \param Req the requirement for the type of the checked expression (omit + /// if no requirement was specified). + ExprRequirement(SubstitutionDiagnostic *E, bool IsSimple, + SourceLocation NoexceptLoc, ReturnTypeRequirement Req = {}); + + bool isSimple() const { return getKind() == RK_Simple; } + bool isCompound() const { return getKind() == RK_Compound; } + + bool hasNoexceptRequirement() const { return NoexceptLoc.isValid(); } + SourceLocation getNoexceptLoc() const { return NoexceptLoc; } + + SatisfactionStatus getSatisfactionStatus() const { return Status; } + + bool isExprSubstitutionFailure() const { + return Status == SS_ExprSubstitutionFailure; + } + + const ReturnTypeRequirement &getReturnTypeRequirement() const { + return TypeReq; + } + + ConceptSpecializationExpr * + getReturnTypeRequirementSubstitutedConstraintExpr() const { + assert(Status >= SS_TypeRequirementSubstitutionFailure); + return SubstitutedConstraintExpr; + } + + SubstitutionDiagnostic *getExprSubstitutionDiagnostic() const { + assert(isExprSubstitutionFailure() && + "Attempted to get expression substitution diagnostic when there has " + "been no expression substitution failure"); + return Value.get<SubstitutionDiagnostic *>(); + } + + Expr *getExpr() const { + assert(!isExprSubstitutionFailure() && + "ExprRequirement has no expression because there has been a " + "substitution failure."); + return Value.get<Expr *>(); + } + + static bool classof(const Requirement *R) { + return R->getKind() == RK_Compound || R->getKind() == RK_Simple; + } +}; + +/// \brief A requires-expression requirement which is satisfied when a general +/// constraint expression is satisfied ('nested' requirements). +class NestedRequirement : public Requirement { + llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value; + const ASTConstraintSatisfaction *Satisfaction = nullptr; + +public: + friend ASTStmtReader; + friend ASTStmtWriter; + + NestedRequirement(SubstitutionDiagnostic *SubstDiag) : + Requirement(RK_Nested, /*Dependent=*/false, + /*ContainsUnexpandedParameterPack*/false, + /*Satisfied=*/false), Value(SubstDiag) {} + + NestedRequirement(Expr *Constraint) : + Requirement(RK_Nested, /*Dependent=*/true, + Constraint->containsUnexpandedParameterPack()), + Value(Constraint) { + assert(Constraint->isInstantiationDependent() && + "Nested requirement with non-dependent constraint must be " + "constructed with a ConstraintSatisfaction object"); + } + + NestedRequirement(ASTContext &C, Expr *Constraint, + const ConstraintSatisfaction &Satisfaction) : + Requirement(RK_Nested, Constraint->isInstantiationDependent(), + Constraint->containsUnexpandedParameterPack(), + Satisfaction.IsSatisfied), + Value(Constraint), + Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {} + + bool isSubstitutionFailure() const { + return Value.is<SubstitutionDiagnostic *>(); + } + + SubstitutionDiagnostic *getSubstitutionDiagnostic() const { + assert(isSubstitutionFailure() && + "getSubstitutionDiagnostic() may not be called when there was no " + "substitution failure."); + return Value.get<SubstitutionDiagnostic *>(); + } + + Expr *getConstraintExpr() const { + assert(!isSubstitutionFailure() && "getConstraintExpr() may not be called " + "on nested requirements with " + "substitution failures."); + return Value.get<Expr *>(); + } + + const ASTConstraintSatisfaction &getConstraintSatisfaction() const { + assert(!isSubstitutionFailure() && "getConstraintSatisfaction() may not be " + "called on nested requirements with " + "substitution failures."); + return *Satisfaction; + } + + static bool classof(const Requirement *R) { + return R->getKind() == RK_Nested; + } +}; + +} // namespace concepts + +/// C++2a [expr.prim.req]: +/// A requires-expression provides a concise way to express requirements on +/// template arguments. A requirement is one that can be checked by name +/// lookup (6.4) or by checking properties of types and expressions. +/// [...] +/// A requires-expression is a prvalue of type bool [...] +class RequiresExpr final : public Expr, + llvm::TrailingObjects<RequiresExpr, ParmVarDecl *, + concepts::Requirement *> { + friend TrailingObjects; + friend class ASTStmtReader; + + unsigned NumLocalParameters; + unsigned NumRequirements; + RequiresExprBodyDecl *Body; + SourceLocation RBraceLoc; + + unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const { + return NumLocalParameters; + } + + unsigned numTrailingObjects(OverloadToken<concepts::Requirement *>) const { + return NumRequirements; + } + + RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, + RequiresExprBodyDecl *Body, + ArrayRef<ParmVarDecl *> LocalParameters, + ArrayRef<concepts::Requirement *> Requirements, + SourceLocation RBraceLoc); + RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, + unsigned NumRequirements); + +public: + static RequiresExpr * + Create(ASTContext &C, SourceLocation RequiresKWLoc, + RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> LocalParameters, + ArrayRef<concepts::Requirement *> Requirements, + SourceLocation RBraceLoc); + static RequiresExpr * + Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, + unsigned NumRequirements); + + ArrayRef<ParmVarDecl *> getLocalParameters() const { + return {getTrailingObjects<ParmVarDecl *>(), NumLocalParameters}; + } + + RequiresExprBodyDecl *getBody() const { return Body; } + + ArrayRef<concepts::Requirement *> getRequirements() const { + return {getTrailingObjects<concepts::Requirement *>(), NumRequirements}; + } + + /// \brief Whether or not the requires clause is satisfied. + /// The expression must not be dependent. + bool isSatisfied() const { + assert(!isValueDependent() + && "isSatisfied called on a dependent RequiresExpr"); + return RequiresExprBits.IsSatisfied; + } + + SourceLocation getRequiresKWLoc() const { + return RequiresExprBits.RequiresKWLoc; + } + + SourceLocation getRBraceLoc() const { return RBraceLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == RequiresExprClass; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return RequiresExprBits.RequiresKWLoc; + } + SourceLocation getEndLoc() const LLVM_READONLY { + return RBraceLoc; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_EXPRCONCEPTS_H diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index d76b3a26b1f9..4b39d9ab96a6 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -13,8 +13,10 @@ #ifndef LLVM_CLANG_AST_EXPROBJC_H #define LLVM_CLANG_AST_EXPROBJC_H +#include "clang/AST/ComputeDependence.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DependenceFlags.h" #include "clang/AST/Expr.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/SelectorLocationsKind.h" @@ -53,9 +55,10 @@ class ObjCStringLiteral : public Expr { public: ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) - : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - String(SL), AtLoc(L) {} + : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary), String(SL), + AtLoc(L) { + setDependence(ExprDependence::None); + } explicit ObjCStringLiteral(EmptyShell Empty) : Expr(ObjCStringLiteralClass, Empty) {} @@ -88,9 +91,10 @@ class ObjCBoolLiteralExpr : public Expr { public: ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) - : Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Value(val), Loc(l) {} + : Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary), Value(val), + Loc(l) { + setDependence(ExprDependence::None); + } explicit ObjCBoolLiteralExpr(EmptyShell Empty) : Expr(ObjCBoolLiteralExprClass, Empty) {} @@ -129,13 +133,11 @@ class ObjCBoxedExpr : public Expr { public: friend class ASTStmtReader; - ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, - SourceRange R) - : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary, - E->isTypeDependent(), E->isValueDependent(), - E->isInstantiationDependent(), - E->containsUnexpandedParameterPack()), - SubExpr(E), BoxingMethod(method), Range(R) {} + ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, SourceRange R) + : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary), SubExpr(E), + BoxingMethod(method), Range(R) { + setDependence(computeDependence(this)); + } explicit ObjCBoxedExpr(EmptyShell Empty) : Expr(ObjCBoxedExprClass, Empty) {} @@ -409,14 +411,12 @@ class ObjCEncodeExpr : public Expr { SourceLocation AtLoc, RParenLoc; public: - ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, - SourceLocation at, SourceLocation rp) - : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary, - EncodedType->getType()->isDependentType(), - EncodedType->getType()->isDependentType(), - EncodedType->getType()->isInstantiationDependentType(), - EncodedType->getType()->containsUnexpandedParameterPack()), - EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} + ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at, + SourceLocation rp) + : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary), + EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) { + setDependence(computeDependence(this)); + } explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} @@ -456,11 +456,12 @@ class ObjCSelectorExpr : public Expr { SourceLocation AtLoc, RParenLoc; public: - ObjCSelectorExpr(QualType T, Selector selInfo, - SourceLocation at, SourceLocation rp) - : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - SelName(selInfo), AtLoc(at), RParenLoc(rp) {} + ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, + SourceLocation rp) + : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary), + SelName(selInfo), AtLoc(at), RParenLoc(rp) { + setDependence(ExprDependence::None); + } explicit ObjCSelectorExpr(EmptyShell Empty) : Expr(ObjCSelectorExprClass, Empty) {} @@ -508,11 +509,12 @@ public: friend class ASTStmtReader; friend class ASTStmtWriter; - ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, - SourceLocation at, SourceLocation protoLoc, SourceLocation rp) - : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, - false, false), - TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {} + ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, + SourceLocation protoLoc, SourceLocation rp) + : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary), + TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) { + setDependence(ExprDependence::None); + } explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} @@ -558,17 +560,15 @@ class ObjCIvarRefExpr : public Expr { bool IsFreeIvar : 1; public: - ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, - SourceLocation l, SourceLocation oploc, - Expr *base, - bool arrow = false, bool freeIvar = false) + ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, + SourceLocation oploc, Expr *base, bool arrow = false, + bool freeIvar = false) : Expr(ObjCIvarRefExprClass, t, VK_LValue, - d->isBitField() ? OK_BitField : OK_Ordinary, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), + d->isBitField() ? OK_BitField : OK_Ordinary), D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow), - IsFreeIvar(freeIvar) {} + IsFreeIvar(freeIvar) { + setDependence(computeDependence(this)); + } explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} @@ -645,57 +645,53 @@ private: llvm::PointerUnion<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver; public: - ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation l, Expr *base) - : Expr(ObjCPropertyRefExprClass, t, VK, OK, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - base->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), IdLoc(l), Receiver(base) { + ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, + ExprObjectKind OK, SourceLocation l, Expr *base) + : Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false), + IdLoc(l), Receiver(base) { assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); } - ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation l, SourceLocation sl, QualType st) - : Expr(ObjCPropertyRefExprClass, t, VK, OK, - /*TypeDependent=*/false, false, st->isInstantiationDependentType(), - st->containsUnexpandedParameterPack()), - PropertyOrGetter(PD, false), IdLoc(l), ReceiverLoc(sl), - Receiver(st.getTypePtr()) { + ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, + ExprObjectKind OK, SourceLocation l, SourceLocation sl, + QualType st) + : Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false), + IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, QualType T, ExprValueKind VK, ExprObjectKind OK, SourceLocation IdLoc, Expr *Base) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, - Base->isValueDependent(), Base->isInstantiationDependent(), - Base->containsUnexpandedParameterPack()), + : Expr(ObjCPropertyRefExprClass, T, VK, OK), PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), Receiver(Base) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, QualType T, ExprValueKind VK, ExprObjectKind OK, - SourceLocation IdLoc, - SourceLocation SuperLoc, QualType SuperTy) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), + SourceLocation IdLoc, SourceLocation SuperLoc, + QualType SuperTy) + : Expr(ObjCPropertyRefExprClass, T, VK, OK), PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); } ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, QualType T, ExprValueKind VK, ExprObjectKind OK, - SourceLocation IdLoc, - SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver) - : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false), + SourceLocation IdLoc, SourceLocation ReceiverLoc, + ObjCInterfaceDecl *Receiver) + : Expr(ObjCPropertyRefExprClass, T, VK, OK), PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); } explicit ObjCPropertyRefExpr(EmptyShell Empty) @@ -859,20 +855,14 @@ class ObjCSubscriptRefExpr : public Expr { ObjCMethodDecl *SetAtIndexMethodDecl; public: - ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T, - ExprValueKind VK, ExprObjectKind OK, - ObjCMethodDecl *getMethod, + ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T, ExprValueKind VK, + ExprObjectKind OK, ObjCMethodDecl *getMethod, ObjCMethodDecl *setMethod, SourceLocation RB) - : Expr(ObjCSubscriptRefExprClass, T, VK, OK, - base->isTypeDependent() || key->isTypeDependent(), - base->isValueDependent() || key->isValueDependent(), - (base->isInstantiationDependent() || - key->isInstantiationDependent()), - (base->containsUnexpandedParameterPack() || - key->containsUnexpandedParameterPack())), - RBracket(RB), GetAtIndexMethodDecl(getMethod), - SetAtIndexMethodDecl(setMethod) { - SubExprs[BASE] = base; SubExprs[KEY] = key; + : Expr(ObjCSubscriptRefExprClass, T, VK, OK), RBracket(RB), + GetAtIndexMethodDecl(getMethod), SetAtIndexMethodDecl(setMethod) { + SubExprs[BASE] = base; + SubExprs[KEY] = key; + setDependence(computeDependence(this)); } explicit ObjCSubscriptRefExpr(EmptyShell Empty) @@ -1505,11 +1495,10 @@ class ObjCIsaExpr : public Expr { public: ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc, QualType ty) - : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary, - /*TypeDependent=*/false, base->isValueDependent(), - base->isInstantiationDependent(), - /*ContainsUnexpandedParameterPack=*/false), - Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {} + : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary), Base(base), + IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) { + setDependence(computeDependence(this)); + } /// Build an empty expression. explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {} @@ -1591,12 +1580,10 @@ class ObjCIndirectCopyRestoreExpr : public Expr { public: ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy) - : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary, - operand->isTypeDependent(), operand->isValueDependent(), - operand->isInstantiationDependent(), - operand->containsUnexpandedParameterPack()), + : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary), Operand(operand) { setShouldCopy(shouldCopy); + setDependence(computeDependence(this)); } Expr *getSubExpr() { return cast<Expr>(Operand); } @@ -1705,9 +1692,10 @@ class ObjCAvailabilityCheckExpr : public Expr { public: ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc, SourceLocation RParen, QualType Ty) - : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_RValue, OK_Ordinary, false, - false, false, false), - VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) {} + : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_RValue, OK_Ordinary), + VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) { + setDependence(ExprDependence::None); + } explicit ObjCAvailabilityCheckExpr(EmptyShell Shell) : Expr(ObjCAvailabilityCheckExprClass, Shell) {} diff --git a/clang/include/clang/AST/ExprOpenMP.h b/clang/include/clang/AST/ExprOpenMP.h index 5607d2d1dc58..be5dda992334 100644 --- a/clang/include/clang/AST/ExprOpenMP.h +++ b/clang/include/clang/AST/ExprOpenMP.h @@ -13,62 +13,66 @@ #ifndef LLVM_CLANG_AST_EXPROPENMP_H #define LLVM_CLANG_AST_EXPROPENMP_H +#include "clang/AST/ComputeDependence.h" #include "clang/AST/Expr.h" namespace clang { -/// OpenMP 4.0 [2.4, Array Sections]. +/// OpenMP 5.0 [2.1.5, Array Sections]. /// To specify an array section in an OpenMP construct, array subscript /// expressions are extended with the following syntax: /// \code +/// [ lower-bound : length : stride ] +/// [ lower-bound : length : ] /// [ lower-bound : length ] +/// [ lower-bound : : stride ] +/// [ lower-bound : : ] /// [ lower-bound : ] +/// [ : length : stride ] +/// [ : length : ] /// [ : length ] +/// [ : : stride ] +/// [ : : ] /// [ : ] /// \endcode /// The array section must be a subset of the original array. /// Array sections are allowed on multidimensional arrays. Base language array /// subscript expressions can be used to specify length-one dimensions of /// multidimensional array sections. -/// The lower-bound and length are integral type expressions. When evaluated +/// Each of the lower-bound, length, and stride expressions if specified must be +/// an integral type expressions of the base language. When evaluated /// they represent a set of integer values as follows: /// \code -/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length - -/// 1 } +/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... , +/// lower-bound + ((length - 1) * stride) } /// \endcode /// The lower-bound and length must evaluate to non-negative integers. +/// The stride must evaluate to a positive integer. /// When the size of the array dimension is not known, the length must be /// specified explicitly. -/// When the length is absent, it defaults to the size of the array dimension -/// minus the lower-bound. -/// When the lower-bound is absent it defaults to 0. +/// When the stride is absent it defaults to 1. +/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉, +/// where size is the size of the array dimension. When the lower-bound is +/// absent it defaults to 0. class OMPArraySectionExpr : public Expr { - enum { BASE, LOWER_BOUND, LENGTH, END_EXPR }; + enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR }; Stmt *SubExprs[END_EXPR]; - SourceLocation ColonLoc; + SourceLocation ColonLocFirst; + SourceLocation ColonLocSecond; SourceLocation RBracketLoc; public: - OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type, - ExprValueKind VK, ExprObjectKind OK, - SourceLocation ColonLoc, SourceLocation RBracketLoc) - : Expr( - OMPArraySectionExprClass, Type, VK, OK, - Base->isTypeDependent() || - (LowerBound && LowerBound->isTypeDependent()) || - (Length && Length->isTypeDependent()), - Base->isValueDependent() || - (LowerBound && LowerBound->isValueDependent()) || - (Length && Length->isValueDependent()), - Base->isInstantiationDependent() || - (LowerBound && LowerBound->isInstantiationDependent()) || - (Length && Length->isInstantiationDependent()), - Base->containsUnexpandedParameterPack() || - (LowerBound && LowerBound->containsUnexpandedParameterPack()) || - (Length && Length->containsUnexpandedParameterPack())), - ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) { + OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride, + QualType Type, ExprValueKind VK, ExprObjectKind OK, + SourceLocation ColonLocFirst, + SourceLocation ColonLocSecond, SourceLocation RBracketLoc) + : Expr(OMPArraySectionExprClass, Type, VK, OK), + ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond), + RBracketLoc(RBracketLoc) { SubExprs[BASE] = Base; SubExprs[LOWER_BOUND] = LowerBound; SubExprs[LENGTH] = Length; + SubExprs[STRIDE] = Stride; + setDependence(computeDependence(this)); } /// Create an empty array section expression. @@ -100,13 +104,22 @@ public: /// Set length of the array section. void setLength(Expr *E) { SubExprs[LENGTH] = E; } + /// Get stride of array section. + Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); } + const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); } + /// Set length of the array section. + void setStride(Expr *E) { SubExprs[STRIDE] = E; } + SourceLocation getBeginLoc() const LLVM_READONLY { return getBase()->getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; } - SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation L) { ColonLoc = L; } + SourceLocation getColonLocFirst() const { return ColonLocFirst; } + void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; } + + SourceLocation getColonLocSecond() const { return ColonLocSecond; } + void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; } SourceLocation getRBracketLoc() const { return RBracketLoc; } void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } @@ -127,6 +140,286 @@ public: return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]); } }; + +/// An explicit cast in C or a C-style cast in C++, which uses the syntax +/// ([s1][s2]...[sn])expr. For example: @c ([3][3])f. +class OMPArrayShapingExpr final + : public Expr, + private llvm::TrailingObjects<OMPArrayShapingExpr, Expr *, SourceRange> { + friend TrailingObjects; + friend class ASTStmtReader; + friend class ASTStmtWriter; + /// Base node. + SourceLocation LPLoc; /// The location of the left paren + SourceLocation RPLoc; /// The location of the right paren + unsigned NumDims = 0; /// Number of dimensions in the shaping expression. + + /// Construct full expression. + OMPArrayShapingExpr(QualType ExprTy, Expr *Op, SourceLocation L, + SourceLocation R, ArrayRef<Expr *> Dims); + + /// Construct an empty expression. + explicit OMPArrayShapingExpr(EmptyShell Shell, unsigned NumDims) + : Expr(OMPArrayShapingExprClass, Shell), NumDims(NumDims) {} + + /// Sets the dimensions for the array shaping. + void setDimensions(ArrayRef<Expr *> Dims); + + /// Sets the base expression for array shaping operation. + void setBase(Expr *Op) { getTrailingObjects<Expr *>()[NumDims] = Op; } + + /// Sets source ranges for the brackets in the array shaping operation. + void setBracketsRanges(ArrayRef<SourceRange> BR); + + unsigned numTrailingObjects(OverloadToken<Expr *>) const { + // Add an extra one for the base expression. + return NumDims + 1; + } + + unsigned numTrailingObjects(OverloadToken<SourceRange>) const { + return NumDims; + } + +public: + static OMPArrayShapingExpr *Create(const ASTContext &Context, QualType T, + Expr *Op, SourceLocation L, + SourceLocation R, ArrayRef<Expr *> Dims, + ArrayRef<SourceRange> BracketRanges); + + static OMPArrayShapingExpr *CreateEmpty(const ASTContext &Context, + unsigned NumDims); + + SourceLocation getLParenLoc() const { return LPLoc; } + void setLParenLoc(SourceLocation L) { LPLoc = L; } + + SourceLocation getRParenLoc() const { return RPLoc; } + void setRParenLoc(SourceLocation L) { RPLoc = L; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { + return getBase()->getEndLoc(); + } + + /// Fetches the dimensions for array shaping expression. + ArrayRef<Expr *> getDimensions() const { + return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumDims); + } + + /// Fetches source ranges for the brackets os the array shaping expression. + ArrayRef<SourceRange> getBracketsRanges() const { + return llvm::makeArrayRef(getTrailingObjects<SourceRange>(), NumDims); + } + + /// Fetches base expression of array shaping expression. + Expr *getBase() { return getTrailingObjects<Expr *>()[NumDims]; } + const Expr *getBase() const { return getTrailingObjects<Expr *>()[NumDims]; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPArrayShapingExprClass; + } + + // Iterators + child_range children() { + Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); + return child_range(Begin, Begin + NumDims + 1); + } + const_child_range children() const { + Stmt *const *Begin = + reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); + return const_child_range(Begin, Begin + NumDims + 1); + } +}; + +/// Helper expressions and declaration for OMPIteratorExpr class for each +/// iteration space. +struct OMPIteratorHelperData { + /// Internal normalized counter. + VarDecl *CounterVD = nullptr; + /// Normalized upper bound. Normalized loop iterates from 0 to Upper with + /// step 1. + Expr *Upper = nullptr; + /// Update expression for the originally specified iteration variable, + /// calculated as VD = Begin + CounterVD * Step; + Expr *Update = nullptr; + /// Updater for the internal counter: ++CounterVD; + Expr *CounterUpdate = nullptr; +}; + +/// OpenMP 5.0 [2.1.6 Iterators] +/// Iterators are identifiers that expand to multiple values in the clause on +/// which they appear. +/// The syntax of the iterator modifier is as follows: +/// \code +/// iterator(iterators-definition) +/// \endcode +/// where iterators-definition is one of the following: +/// \code +/// iterator-specifier [, iterators-definition ] +/// \endcode +/// where iterator-specifier is one of the following: +/// \code +/// [ iterator-type ] identifier = range-specification +/// \endcode +/// where identifier is a base language identifier. +/// iterator-type is a type name. +/// range-specification is of the form begin:end[:step], where begin and end are +/// expressions for which their types can be converted to iterator-type and step +/// is an integral expression. +/// In an iterator-specifier, if the iterator-type is not specified then the +/// type of that iterator is of int type. +/// The iterator-type must be an integral or pointer type. +/// The iterator-type must not be const qualified. +class OMPIteratorExpr final + : public Expr, + private llvm::TrailingObjects<OMPIteratorExpr, Decl *, Expr *, + SourceLocation, OMPIteratorHelperData> { +public: + /// Iterator range representation begin:end[:step]. + struct IteratorRange { + Expr *Begin = nullptr; + Expr *End = nullptr; + Expr *Step = nullptr; + }; + /// Iterator definition representation. + struct IteratorDefinition { + Decl *IteratorDecl = nullptr; + IteratorRange Range; + SourceLocation AssignmentLoc; + SourceLocation ColonLoc, SecondColonLoc; + }; + +private: + friend TrailingObjects; + friend class ASTStmtReader; + friend class ASTStmtWriter; + + /// Offset in the list of expressions for subelements of the ranges. + enum class RangeExprOffset { + Begin = 0, + End = 1, + Step = 2, + Total = 3, + }; + /// Offset in the list of locations for subelements of colon symbols + /// locations. + enum class RangeLocOffset { + AssignLoc = 0, + FirstColonLoc = 1, + SecondColonLoc = 2, + Total = 3, + }; + /// Location of 'iterator' keyword. + SourceLocation IteratorKwLoc; + /// Location of '('. + SourceLocation LPLoc; + /// Location of ')'. + SourceLocation RPLoc; + /// Number of iterator definitions. + unsigned NumIterators = 0; + + OMPIteratorExpr(QualType ExprTy, SourceLocation IteratorKwLoc, + SourceLocation L, SourceLocation R, + ArrayRef<IteratorDefinition> Data, + ArrayRef<OMPIteratorHelperData> Helpers); + + /// Construct an empty expression. + explicit OMPIteratorExpr(EmptyShell Shell, unsigned NumIterators) + : Expr(OMPIteratorExprClass, Shell), NumIterators(NumIterators) {} + + /// Sets basic declaration for the specified iterator definition. + void setIteratorDeclaration(unsigned I, Decl *D); + + /// Sets the location of the assignment symbol for the specified iterator + /// definition. + void setAssignmentLoc(unsigned I, SourceLocation Loc); + + /// Sets begin, end and optional step expressions for specified iterator + /// definition. + void setIteratorRange(unsigned I, Expr *Begin, SourceLocation ColonLoc, + Expr *End, SourceLocation SecondColonLoc, Expr *Step); + + /// Sets helpers for the specified iteration space. + void setHelper(unsigned I, const OMPIteratorHelperData &D); + + unsigned numTrailingObjects(OverloadToken<Decl *>) const { + return NumIterators; + } + + unsigned numTrailingObjects(OverloadToken<Expr *>) const { + return NumIterators * static_cast<int>(RangeExprOffset::Total); + } + + unsigned numTrailingObjects(OverloadToken<SourceLocation>) const { + return NumIterators * static_cast<int>(RangeLocOffset::Total); + } + +public: + static OMPIteratorExpr *Create(const ASTContext &Context, QualType T, + SourceLocation IteratorKwLoc, SourceLocation L, + SourceLocation R, + ArrayRef<IteratorDefinition> Data, + ArrayRef<OMPIteratorHelperData> Helpers); + + static OMPIteratorExpr *CreateEmpty(const ASTContext &Context, + unsigned NumIterators); + + SourceLocation getLParenLoc() const { return LPLoc; } + void setLParenLoc(SourceLocation L) { LPLoc = L; } + + SourceLocation getRParenLoc() const { return RPLoc; } + void setRParenLoc(SourceLocation L) { RPLoc = L; } + + SourceLocation getIteratorKwLoc() const { return IteratorKwLoc; } + void setIteratorKwLoc(SourceLocation L) { IteratorKwLoc = L; } + SourceLocation getBeginLoc() const LLVM_READONLY { return IteratorKwLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RPLoc; } + + /// Gets the iterator declaration for the given iterator. + Decl *getIteratorDecl(unsigned I); + const Decl *getIteratorDecl(unsigned I) const { + return const_cast<OMPIteratorExpr *>(this)->getIteratorDecl(I); + } + + /// Gets the iterator range for the given iterator. + IteratorRange getIteratorRange(unsigned I); + const IteratorRange getIteratorRange(unsigned I) const { + return const_cast<OMPIteratorExpr *>(this)->getIteratorRange(I); + } + + /// Gets the location of '=' for the given iterator definition. + SourceLocation getAssignLoc(unsigned I) const; + /// Gets the location of the first ':' in the range for the given iterator + /// definition. + SourceLocation getColonLoc(unsigned I) const; + /// Gets the location of the second ':' (if any) in the range for the given + /// iteratori definition. + SourceLocation getSecondColonLoc(unsigned I) const; + + /// Returns number of iterator definitions. + unsigned numOfIterators() const { return NumIterators; } + + /// Fetches helper data for the specified iteration space. + OMPIteratorHelperData &getHelper(unsigned I); + const OMPIteratorHelperData &getHelper(unsigned I) const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPIteratorExprClass; + } + + // Iterators + child_range children() { + Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); + return child_range( + Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total)); + } + const_child_range children() const { + Stmt *const *Begin = + reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); + return const_child_range( + Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total)); + } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 899ac3f66937..def877b91816 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -17,7 +17,6 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/DeclBase.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/Module.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -39,6 +38,7 @@ namespace clang { class ASTConsumer; class ASTContext; +class ASTSourceDescriptor; class CXXBaseSpecifier; class CXXCtorInitializer; class CXXRecordDecl; @@ -165,31 +165,6 @@ public: /// object file. virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; } - /// Abstracts clang modules and precompiled header files and holds - /// everything needed to generate debug info for an imported module - /// or PCH. - class ASTSourceDescriptor { - StringRef PCHModuleName; - StringRef Path; - StringRef ASTFile; - ASTFileSignature Signature; - const Module *ClangModule = nullptr; - - public: - ASTSourceDescriptor() = default; - ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile, - ASTFileSignature Signature) - : PCHModuleName(std::move(Name)), Path(std::move(Path)), - ASTFile(std::move(ASTFile)), Signature(Signature) {} - ASTSourceDescriptor(const Module &M); - - std::string getModuleName() const; - StringRef getPath() const { return Path; } - StringRef getASTFile() const { return ASTFile; } - ASTFileSignature getSignature() const { return Signature; } - const Module *getModuleOrNull() const { return ClangModule; } - }; - /// Return a descriptor for the corresponding module, if one exists. virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID); @@ -504,9 +479,8 @@ struct PointerLikeTypeTraits< static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); } static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); } - enum { - NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1 - }; + static constexpr int NumLowBitsAvailable = + PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1; }; } // namespace llvm diff --git a/clang/include/clang/AST/GlobalDecl.h b/clang/include/clang/AST/GlobalDecl.h index 145e961a23a3..d8ac498be54f 100644 --- a/clang/include/clang/AST/GlobalDecl.h +++ b/clang/include/clang/AST/GlobalDecl.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_GLOBALDECL_H #define LLVM_CLANG_AST_GLOBALDECL_H +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" @@ -33,17 +34,31 @@ enum class DynamicInitKind : unsigned { AtExit, }; +enum class KernelReferenceKind : unsigned { + Kernel = 0, + Stub = 1, +}; + /// GlobalDecl - represents a global declaration. This can either be a /// CXXConstructorDecl and the constructor type (Base, Complete). -/// a CXXDestructorDecl and the destructor type (Base, Complete) or +/// a CXXDestructorDecl and the destructor type (Base, Complete), +/// a FunctionDecl and the kernel reference type (Kernel, Stub), or /// a VarDecl, a FunctionDecl or a BlockDecl. +/// +/// When a new type of GlobalDecl is added, the following places should +/// be updated to convert a Decl* to a GlobalDecl: +/// PredefinedExpr::ComputeName() in lib/AST/Expr.cpp. +/// getParentOfLocalEntity() in lib/AST/ItaniumMangle.cpp +/// ASTNameGenerator::Implementation::writeFuncOrVarName in lib/AST/Mangle.cpp +/// class GlobalDecl { - llvm::PointerIntPair<const Decl *, 2> Value; + llvm::PointerIntPair<const Decl *, 3> Value; unsigned MultiVersionIndex = 0; void Init(const Decl *D) { assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!"); assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!"); + assert(!D->hasAttr<CUDAGlobalAttr>() && "Use other ctor with GPU kernels!"); Value.setPointer(D); } @@ -53,8 +68,17 @@ public: GlobalDecl(const VarDecl *D) { Init(D);} GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0) : MultiVersionIndex(MVIndex) { - Init(D); + if (!D->hasAttr<CUDAGlobalAttr>()) { + Init(D); + return; + } + Value.setPointerAndInt(D, unsigned(getDefaultKernelReference(D))); + } + GlobalDecl(const FunctionDecl *D, KernelReferenceKind Kind) + : Value(D, unsigned(Kind)) { + assert(D->hasAttr<CUDAGlobalAttr>() && "Decl is not a GPU kernel!"); } + GlobalDecl(const NamedDecl *D) { Init(D); } GlobalDecl(const BlockDecl *D) { Init(D); } GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl *D) { Init(D); } @@ -94,13 +118,22 @@ public: } unsigned getMultiVersionIndex() const { - assert(isa<FunctionDecl>(getDecl()) && + assert(isa<FunctionDecl>( + getDecl()) && + !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && !isa<CXXConstructorDecl>(getDecl()) && !isa<CXXDestructorDecl>(getDecl()) && "Decl is not a plain FunctionDecl!"); return MultiVersionIndex; } + KernelReferenceKind getKernelReferenceKind() const { + assert(isa<FunctionDecl>(getDecl()) && + cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && + "Decl is not a GPU kernel!"); + return static_cast<KernelReferenceKind>(Value.getInt()); + } + friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) { return LHS.Value == RHS.Value && LHS.MultiVersionIndex == RHS.MultiVersionIndex; @@ -108,12 +141,19 @@ public: void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } + explicit operator bool() const { return getAsOpaquePtr(); } + static GlobalDecl getFromOpaquePtr(void *P) { GlobalDecl GD; GD.Value.setFromOpaqueValue(P); return GD; } + static KernelReferenceKind getDefaultKernelReference(const FunctionDecl *D) { + return D->getLangOpts().CUDAIsDevice ? KernelReferenceKind::Kernel + : KernelReferenceKind::Stub; + } + GlobalDecl getWithDecl(const Decl *D) { GlobalDecl Result(*this); Result.Value.setPointer(D); @@ -136,6 +176,7 @@ public: GlobalDecl getWithMultiVersionIndex(unsigned Index) { assert(isa<FunctionDecl>(getDecl()) && + !cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && !isa<CXXConstructorDecl>(getDecl()) && !isa<CXXDestructorDecl>(getDecl()) && "Decl is not a plain FunctionDecl!"); @@ -143,6 +184,15 @@ public: Result.MultiVersionIndex = Index; return Result; } + + GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind) { + assert(isa<FunctionDecl>(getDecl()) && + cast<FunctionDecl>(getDecl())->hasAttr<CUDAGlobalAttr>() && + "Decl is not a GPU kernel!"); + GlobalDecl Result(*this); + Result.Value.setInt(unsigned(Kind)); + return Result; + } }; } // namespace clang diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h index 4023e023e9d5..4e7162992418 100644 --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -23,10 +23,13 @@ #include "clang/AST/CommentVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" +#include "clang/AST/Type.h" #include "llvm/Support/JSON.h" namespace clang { +class APValue; + class NodeStreamer { bool FirstChild = true; bool TopLevel = true; @@ -64,7 +67,7 @@ public: // We need to capture an owning-string in the lambda because the lambda // is invoked in a deferred manner. - std::string LabelStr = !Label.empty() ? Label : "inner"; + std::string LabelStr(!Label.empty() ? Label : "inner"); bool WasFirstChild = FirstChild; auto DumpWithIndent = [=](bool IsLastChild) { if (WasFirstChild) { @@ -201,6 +204,7 @@ public: void Visit(const OMPClause *C); void Visit(const BlockDecl::Capture &C); void Visit(const GenericSelectionExpr::ConstAssociation &A); + void Visit(const APValue &Value, QualType Ty); void VisitTypedefType(const TypedefType *TT); void VisitFunctionType(const FunctionType *T); diff --git a/clang/include/clang/AST/LocInfoType.h b/clang/include/clang/AST/LocInfoType.h index 1073174bcf91..7e845ad03587 100644 --- a/clang/include/clang/AST/LocInfoType.h +++ b/clang/include/clang/AST/LocInfoType.h @@ -35,10 +35,7 @@ class LocInfoType : public Type { TypeSourceInfo *DeclInfo; LocInfoType(QualType ty, TypeSourceInfo *TInfo) - : Type((TypeClass)LocInfo, ty, ty->isDependentType(), - ty->isInstantiationDependentType(), ty->isVariablyModifiedType(), - ty->containsUnexpandedParameterPack()), - DeclInfo(TInfo) { + : Type((TypeClass)LocInfo, ty, ty->getDependence()), DeclInfo(TInfo) { assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?"); } friend class Sema; diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h index 5db5c5b977da..011d1faab8ea 100644 --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_MANGLE_H #include "clang/AST/Decl.h" +#include "clang/AST/GlobalDecl.h" #include "clang/AST/Type.h" #include "clang/Basic/ABI.h" #include "llvm/ADT/DenseMap.h" @@ -96,8 +97,8 @@ public: virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0; // FIXME: consider replacing raw_ostream & with something like SmallString &. - void mangleName(const NamedDecl *D, raw_ostream &); - virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0; + void mangleName(GlobalDecl GD, raw_ostream &); + virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0; virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &) = 0; @@ -109,11 +110,8 @@ public: raw_ostream &) = 0; virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0; virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0; - virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - raw_ostream &) = 0; - virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - raw_ostream &) = 0; virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0; + virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&); void mangleGlobalBlock(const BlockDecl *BD, const NamedDecl *ID, @@ -151,9 +149,14 @@ public: }; class ItaniumMangleContext : public MangleContext { + bool IsUniqueNameMangler = false; public: explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D) : MangleContext(C, D, MK_Itanium) {} + explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D, + bool IsUniqueNameMangler) + : MangleContext(C, D, MK_Itanium), + IsUniqueNameMangler(IsUniqueNameMangler) {} virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0; virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0; @@ -172,12 +175,17 @@ public: virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0; + virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0; + + bool isUniqueNameMangler() { return IsUniqueNameMangler; } + static bool classof(const MangleContext *C) { return C->getKind() == MK_Itanium; } static ItaniumMangleContext *create(ASTContext &Context, - DiagnosticsEngine &Diags); + DiagnosticsEngine &Diags, + bool IsUniqueNameMangler = false); }; class MicrosoftMangleContext : public MangleContext { diff --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h index c6fae6f465ff..540ac3df48fe 100644 --- a/clang/include/clang/AST/NestedNameSpecifier.h +++ b/clang/include/clang/AST/NestedNameSpecifier.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H +#include "clang/AST/DependenceFlags.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/FoldingSet.h" @@ -199,6 +200,8 @@ public: return nullptr; } + NestedNameSpecifierDependence getDependence() const; + /// Whether this nested name specifier refers to a dependent /// type or not. bool isDependent() const; @@ -211,6 +214,9 @@ public: /// parameter pack (for C++11 variadic templates). bool containsUnexpandedParameterPack() const; + /// Whether this nested name specifier contains an error. + bool containsErrors() const; + /// Print this nested name specifier to the given output stream. If /// `ResolveTemplateArguments` is true, we'll print actual types, e.g. /// `ns::SomeTemplate<int, MyClass>` instead of diff --git a/clang/include/clang/AST/NonTrivialTypeVisitor.h b/clang/include/clang/AST/NonTrivialTypeVisitor.h index aafcedb9d10b..c95516538ad1 100644 --- a/clang/include/clang/AST/NonTrivialTypeVisitor.h +++ b/clang/include/clang/AST/NonTrivialTypeVisitor.h @@ -1,4 +1,4 @@ -//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types *- C++ --*-===// +//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types -*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index cd4a6f37f5db..2e8593e0b835 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -89,7 +89,7 @@ public: // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); - static bool isWhitelistedDecl(const Decl* D, const DeclContext *Parent); + static bool isDeclToBeProcessed(const Decl* D, const DeclContext *Parent); private: void AddDeclarationNameImpl(DeclarationName Name); diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 26f8389f9cfa..6de7b6deb514 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -31,6 +31,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" +#include "llvm/Frontend/OpenMP/OMPContext.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" @@ -284,12 +285,13 @@ public: /// \param EndLoc Ending location of the clause. OMPAllocatorClause(Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_allocator, StartLoc, EndLoc), LParenLoc(LParenLoc), - Allocator(A) {} + : OMPClause(llvm::omp::OMPC_allocator, StartLoc, EndLoc), + LParenLoc(LParenLoc), Allocator(A) {} /// Build an empty clause. OMPAllocatorClause() - : OMPClause(OMPC_allocator, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_allocator, SourceLocation(), + SourceLocation()) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -314,7 +316,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_allocator; + return T->getClauseKind() == llvm::omp::OMPC_allocator; } }; @@ -349,17 +351,17 @@ class OMPAllocateClause final OMPAllocateClause(SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPAllocateClause>(OMPC_allocate, StartLoc, LParenLoc, - EndLoc, N), + : OMPVarListClause<OMPAllocateClause>(llvm::omp::OMPC_allocate, StartLoc, + LParenLoc, EndLoc, N), Allocator(Allocator), ColonLoc(ColonLoc) {} /// Build an empty clause. /// /// \param N Number of variables. explicit OMPAllocateClause(unsigned N) - : OMPVarListClause<OMPAllocateClause>(OMPC_allocate, SourceLocation(), + : OMPVarListClause<OMPAllocateClause>(llvm::omp::OMPC_allocate, SourceLocation(), SourceLocation(), - N) {} + SourceLocation(), N) {} /// Sets location of ':' symbol in clause. void setColonLoc(SourceLocation CL) { ColonLoc = CL; } @@ -411,7 +413,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_allocate; + return T->getClauseKind() == llvm::omp::OMPC_allocate; } }; @@ -469,15 +471,16 @@ public: OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc) - : OMPClause(OMPC_if, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), Condition(Cond), ColonLoc(ColonLoc), - NameModifier(NameModifier), NameModifierLoc(NameModifierLoc) { + : OMPClause(llvm::omp::OMPC_if, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Condition(Cond), + ColonLoc(ColonLoc), NameModifier(NameModifier), + NameModifierLoc(NameModifierLoc) { setPreInitStmt(HelperCond, CaptureRegion); } /// Build an empty clause. OMPIfClause() - : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_if, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -511,7 +514,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_if; + return T->getClauseKind() == llvm::omp::OMPC_if; } }; @@ -547,14 +550,14 @@ public: OMPFinalClause(Expr *Cond, Stmt *HelperCond, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_final, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), Condition(Cond) { + : OMPClause(llvm::omp::OMPC_final, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Condition(Cond) { setPreInitStmt(HelperCond, CaptureRegion); } /// Build an empty clause. OMPFinalClause() - : OMPClause(OMPC_final, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_final, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -579,7 +582,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_final; + return T->getClauseKind() == llvm::omp::OMPC_final; } }; @@ -617,7 +620,7 @@ public: OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_threads, StartLoc, EndLoc), + : OMPClause(llvm::omp::OMPC_num_threads, StartLoc, EndLoc), OMPClauseWithPreInit(this), LParenLoc(LParenLoc), NumThreads(NumThreads) { setPreInitStmt(HelperNumThreads, CaptureRegion); @@ -625,7 +628,8 @@ public: /// Build an empty clause. OMPNumThreadsClause() - : OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_num_threads, SourceLocation(), + SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -651,7 +655,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_num_threads; + return T->getClauseKind() == llvm::omp::OMPC_num_threads; } }; @@ -687,12 +691,13 @@ public: /// \param EndLoc Ending location of the clause. OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc), - Safelen(Len) {} + : OMPClause(llvm::omp::OMPC_safelen, StartLoc, EndLoc), + LParenLoc(LParenLoc), Safelen(Len) {} /// Build an empty clause. explicit OMPSafelenClause() - : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_safelen, SourceLocation(), SourceLocation()) { + } /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -717,7 +722,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_safelen; + return T->getClauseKind() == llvm::omp::OMPC_safelen; } }; @@ -752,12 +757,13 @@ public: /// \param EndLoc Ending location of the clause. OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc), - Simdlen(Len) {} + : OMPClause(llvm::omp::OMPC_simdlen, StartLoc, EndLoc), + LParenLoc(LParenLoc), Simdlen(Len) {} /// Build an empty clause. explicit OMPSimdlenClause() - : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_simdlen, SourceLocation(), SourceLocation()) { + } /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -782,7 +788,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_simdlen; + return T->getClauseKind() == llvm::omp::OMPC_simdlen; } }; @@ -818,12 +824,13 @@ public: /// \param EndLoc Ending location of the clause. OMPCollapseClause(Expr *Num, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumForLoops(Num) {} + : OMPClause(llvm::omp::OMPC_collapse, StartLoc, EndLoc), + LParenLoc(LParenLoc), NumForLoops(Num) {} /// Build an empty clause. explicit OMPCollapseClause() - : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_collapse, SourceLocation(), + SourceLocation()) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -848,7 +855,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_collapse; + return T->getClauseKind() == llvm::omp::OMPC_collapse; } }; @@ -866,7 +873,7 @@ class OMPDefaultClause : public OMPClause { SourceLocation LParenLoc; /// A kind of the 'default' clause. - OpenMPDefaultClauseKind Kind = OMPC_DEFAULT_unknown; + llvm::omp::DefaultKind Kind = llvm::omp::OMP_DEFAULT_unknown; /// Start location of the kind in source code. SourceLocation KindKwLoc; @@ -874,7 +881,7 @@ class OMPDefaultClause : public OMPClause { /// Set kind of the clauses. /// /// \param K Argument of clause. - void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; } + void setDefaultKind(llvm::omp::DefaultKind K) { Kind = K; } /// Set argument location. /// @@ -889,15 +896,16 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc, + OMPDefaultClause(llvm::omp::DefaultKind A, SourceLocation ALoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc), - Kind(A), KindKwLoc(ALoc) {} + : OMPClause(llvm::omp::OMPC_default, StartLoc, EndLoc), + LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} /// Build an empty clause. OMPDefaultClause() - : OMPClause(OMPC_default, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_default, SourceLocation(), SourceLocation()) { + } /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -906,7 +914,7 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } /// Returns kind of the clause. - OpenMPDefaultClauseKind getDefaultKind() const { return Kind; } + llvm::omp::DefaultKind getDefaultKind() const { return Kind; } /// Returns location of clause kind. SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } @@ -927,7 +935,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_default; + return T->getClauseKind() == llvm::omp::OMPC_default; } }; @@ -973,12 +981,13 @@ public: OMPProcBindClause(llvm::omp::ProcBindKind A, SourceLocation ALoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc), - Kind(A), KindKwLoc(ALoc) {} + : OMPClause(llvm::omp::OMPC_proc_bind, StartLoc, EndLoc), + LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} /// Build an empty clause. OMPProcBindClause() - : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_proc_bind, SourceLocation(), + SourceLocation()) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -1008,7 +1017,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_proc_bind; + return T->getClauseKind() == llvm::omp::OMPC_proc_bind; } }; @@ -1028,11 +1037,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_unified_address, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_unified_address, StartLoc, EndLoc) {} /// Build an empty clause. OMPUnifiedAddressClause() - : OMPClause(OMPC_unified_address, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_unified_address, SourceLocation(), + SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1050,7 +1060,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_unified_address; + return T->getClauseKind() == llvm::omp::OMPC_unified_address; } }; @@ -1070,11 +1080,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_unified_shared_memory, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_unified_shared_memory, StartLoc, EndLoc) {} /// Build an empty clause. OMPUnifiedSharedMemoryClause() - : OMPClause(OMPC_unified_shared_memory, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_unified_shared_memory, SourceLocation(), + SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1092,7 +1103,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_unified_shared_memory; + return T->getClauseKind() == llvm::omp::OMPC_unified_shared_memory; } }; @@ -1112,11 +1123,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_reverse_offload, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_reverse_offload, StartLoc, EndLoc) {} /// Build an empty clause. OMPReverseOffloadClause() - : OMPClause(OMPC_reverse_offload, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_reverse_offload, SourceLocation(), + SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1134,7 +1146,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_reverse_offload; + return T->getClauseKind() == llvm::omp::OMPC_reverse_offload; } }; @@ -1154,12 +1166,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_dynamic_allocators, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_dynamic_allocators, StartLoc, EndLoc) {} /// Build an empty clause. OMPDynamicAllocatorsClause() - : OMPClause(OMPC_dynamic_allocators, SourceLocation(), SourceLocation()) { - } + : OMPClause(llvm::omp::OMPC_dynamic_allocators, SourceLocation(), + SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1177,7 +1189,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_dynamic_allocators; + return T->getClauseKind() == llvm::omp::OMPC_dynamic_allocators; } }; @@ -1229,12 +1241,12 @@ public: SourceLocation ALoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_atomic_default_mem_order, StartLoc, EndLoc), + : OMPClause(llvm::omp::OMPC_atomic_default_mem_order, StartLoc, EndLoc), LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} /// Build an empty clause. OMPAtomicDefaultMemOrderClause() - : OMPClause(OMPC_atomic_default_mem_order, SourceLocation(), + : OMPClause(llvm::omp::OMPC_atomic_default_mem_order, SourceLocation(), SourceLocation()) {} /// Sets the location of '('. @@ -1267,7 +1279,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_atomic_default_mem_order; + return T->getClauseKind() == llvm::omp::OMPC_atomic_default_mem_order; } }; @@ -1386,9 +1398,9 @@ public: Expr *ChunkSize, Stmt *HelperChunkSize, OpenMPScheduleClauseModifier M1, SourceLocation M1Loc, OpenMPScheduleClauseModifier M2, SourceLocation M2Loc) - : OMPClause(OMPC_schedule, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc), - ChunkSize(ChunkSize) { + : OMPClause(llvm::omp::OMPC_schedule, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Kind(Kind), + KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) { setPreInitStmt(HelperChunkSize); Modifiers[FIRST] = M1; Modifiers[SECOND] = M2; @@ -1398,7 +1410,7 @@ public: /// Build an empty clause. explicit OMPScheduleClause() - : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_schedule, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) { Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown; Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown; @@ -1460,7 +1472,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_schedule; + return T->getClauseKind() == llvm::omp::OMPC_schedule; } }; @@ -1495,12 +1507,12 @@ class OMPOrderedClause final /// \param EndLoc Ending location of the clause. OMPOrderedClause(Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumForLoops(Num), NumberOfLoops(NumLoops) {} + : OMPClause(llvm::omp::OMPC_ordered, StartLoc, EndLoc), + LParenLoc(LParenLoc), NumForLoops(Num), NumberOfLoops(NumLoops) {} /// Build an empty clause. explicit OMPOrderedClause(unsigned NumLoops) - : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_ordered, SourceLocation(), SourceLocation()), NumberOfLoops(NumLoops) {} /// Set the number of associated for-loops. @@ -1556,7 +1568,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_ordered; + return T->getClauseKind() == llvm::omp::OMPC_ordered; } }; @@ -1573,11 +1585,11 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_nowait, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_nowait, StartLoc, EndLoc) {} /// Build an empty clause. OMPNowaitClause() - : OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_nowait, SourceLocation(), SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1595,7 +1607,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_nowait; + return T->getClauseKind() == llvm::omp::OMPC_nowait; } }; @@ -1612,11 +1624,11 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_untied, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_untied, StartLoc, EndLoc) {} /// Build an empty clause. OMPUntiedClause() - : OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_untied, SourceLocation(), SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1634,7 +1646,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_untied; + return T->getClauseKind() == llvm::omp::OMPC_untied; } }; @@ -1652,11 +1664,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_mergeable, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_mergeable, StartLoc, EndLoc) {} /// Build an empty clause. OMPMergeableClause() - : OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_mergeable, SourceLocation(), + SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1674,7 +1687,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_mergeable; + return T->getClauseKind() == llvm::omp::OMPC_mergeable; } }; @@ -1691,10 +1704,11 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_read, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_read, StartLoc, EndLoc) {} /// Build an empty clause. - OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {} + OMPReadClause() + : OMPClause(llvm::omp::OMPC_read, SourceLocation(), SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1712,7 +1726,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_read; + return T->getClauseKind() == llvm::omp::OMPC_read; } }; @@ -1729,11 +1743,11 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_write, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_write, StartLoc, EndLoc) {} /// Build an empty clause. OMPWriteClause() - : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_write, SourceLocation(), SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1751,7 +1765,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_write; + return T->getClauseKind() == llvm::omp::OMPC_write; } }; @@ -1762,18 +1776,95 @@ public: /// #pragma omp atomic update /// \endcode /// In this example directive '#pragma omp atomic' has 'update' clause. -class OMPUpdateClause : public OMPClause { -public: +/// Also, this class represents 'update' clause in '#pragma omp depobj' +/// directive. +/// +/// \code +/// #pragma omp depobj(a) update(in) +/// \endcode +/// In this example directive '#pragma omp depobj' has 'update' clause with 'in' +/// dependence kind. +class OMPUpdateClause final + : public OMPClause, + private llvm::TrailingObjects<OMPUpdateClause, SourceLocation, + OpenMPDependClauseKind> { + friend class OMPClauseReader; + friend TrailingObjects; + + /// true if extended version of the clause for 'depobj' directive. + bool IsExtended = false; + + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<SourceLocation>) const { + // 2 locations: for '(' and argument location. + return IsExtended ? 2 : 0; + } + + /// Sets the the location of '(' in clause for 'depobj' directive. + void setLParenLoc(SourceLocation Loc) { + assert(IsExtended && "Expected extended clause."); + *getTrailingObjects<SourceLocation>() = Loc; + } + + /// Sets the the location of '(' in clause for 'depobj' directive. + void setArgumentLoc(SourceLocation Loc) { + assert(IsExtended && "Expected extended clause."); + *std::next(getTrailingObjects<SourceLocation>(), 1) = Loc; + } + + /// Sets the dependence kind for the clause for 'depobj' directive. + void setDependencyKind(OpenMPDependClauseKind DK) { + assert(IsExtended && "Expected extended clause."); + *getTrailingObjects<OpenMPDependClauseKind>() = DK; + } + /// 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) {} + OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc, + bool IsExtended) + : OMPClause(llvm::omp::OMPC_update, StartLoc, EndLoc), + IsExtended(IsExtended) {} /// Build an empty clause. - OMPUpdateClause() - : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {} + OMPUpdateClause(bool IsExtended) + : OMPClause(llvm::omp::OMPC_update, SourceLocation(), SourceLocation()), + IsExtended(IsExtended) {} + +public: + /// Creates clause for 'atomic' directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + static OMPUpdateClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc); + + /// Creates clause for 'depobj' directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ArgumentLoc Location of the argument. + /// \param DK Dependence kind. + /// \param EndLoc Ending location of the clause. + static OMPUpdateClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ArgumentLoc, + OpenMPDependClauseKind DK, + SourceLocation EndLoc); + + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param IsExtended true if extended clause for 'depobj' directive must be + /// created. + static OMPUpdateClause *CreateEmpty(const ASTContext &C, bool IsExtended); + + /// Checks if the clause is the extended clauses for 'depobj' directive. + bool isExtended() const { return IsExtended; } child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1790,8 +1881,26 @@ public: return const_child_range(const_child_iterator(), const_child_iterator()); } + /// Gets the the location of '(' in clause for 'depobj' directive. + SourceLocation getLParenLoc() const { + assert(IsExtended && "Expected extended clause."); + return *getTrailingObjects<SourceLocation>(); + } + + /// Gets the the location of argument in clause for 'depobj' directive. + SourceLocation getArgumentLoc() const { + assert(IsExtended && "Expected extended clause."); + return *std::next(getTrailingObjects<SourceLocation>(), 1); + } + + /// Gets the dependence kind in clause for 'depobj' directive. + OpenMPDependClauseKind getDependencyKind() const { + assert(IsExtended && "Expected extended clause."); + return *getTrailingObjects<OpenMPDependClauseKind>(); + } + static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_update; + return T->getClauseKind() == llvm::omp::OMPC_update; } }; @@ -1809,11 +1918,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_capture, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_capture, StartLoc, EndLoc) {} /// Build an empty clause. OMPCaptureClause() - : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_capture, SourceLocation(), SourceLocation()) { + } child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1831,7 +1941,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_capture; + return T->getClauseKind() == llvm::omp::OMPC_capture; } }; @@ -1849,11 +1959,12 @@ public: /// \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) {} + : OMPClause(llvm::omp::OMPC_seq_cst, StartLoc, EndLoc) {} /// Build an empty clause. OMPSeqCstClause() - : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_seq_cst, SourceLocation(), SourceLocation()) { + } child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1871,7 +1982,171 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_seq_cst; + return T->getClauseKind() == llvm::omp::OMPC_seq_cst; + } +}; + +/// This represents 'acq_rel' clause in the '#pragma omp atomic|flush' +/// directives. +/// +/// \code +/// #pragma omp flush acq_rel +/// \endcode +/// In this example directive '#pragma omp flush' has 'acq_rel' clause. +class OMPAcqRelClause final : public OMPClause { +public: + /// Build 'ack_rel' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_acq_rel, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPAcqRelClause() + : OMPClause(llvm::omp::OMPC_acq_rel, SourceLocation(), SourceLocation()) { + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_acq_rel; + } +}; + +/// This represents 'acquire' clause in the '#pragma omp atomic|flush' +/// directives. +/// +/// \code +/// #pragma omp flush acquire +/// \endcode +/// In this example directive '#pragma omp flush' has 'acquire' clause. +class OMPAcquireClause final : public OMPClause { +public: + /// Build 'acquire' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_acquire, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPAcquireClause() + : OMPClause(llvm::omp::OMPC_acquire, SourceLocation(), SourceLocation()) { + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_acquire; + } +}; + +/// This represents 'release' clause in the '#pragma omp atomic|flush' +/// directives. +/// +/// \code +/// #pragma omp flush release +/// \endcode +/// In this example directive '#pragma omp flush' has 'release' clause. +class OMPReleaseClause final : public OMPClause { +public: + /// Build 'release' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_release, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPReleaseClause() + : OMPClause(llvm::omp::OMPC_release, SourceLocation(), SourceLocation()) { + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_release; + } +}; + +/// This represents 'relaxed' clause in the '#pragma omp atomic' +/// directives. +/// +/// \code +/// #pragma omp atomic relaxed +/// \endcode +/// In this example directive '#pragma omp atomic' has 'relaxed' clause. +class OMPRelaxedClause final : public OMPClause { +public: + /// Build 'relaxed' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_relaxed, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPRelaxedClause() + : OMPClause(llvm::omp::OMPC_relaxed, SourceLocation(), SourceLocation()) { + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_relaxed; } }; @@ -1897,16 +2172,16 @@ class OMPPrivateClause final /// \param N Number of the variables in the clause. OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc, - EndLoc, N) {} + : OMPVarListClause<OMPPrivateClause>(llvm::omp::OMPC_private, StartLoc, + LParenLoc, EndLoc, N) {} /// Build an empty clause. /// /// \param N Number of variables. explicit OMPPrivateClause(unsigned N) - : OMPVarListClause<OMPPrivateClause>(OMPC_private, SourceLocation(), + : OMPVarListClause<OMPPrivateClause>(llvm::omp::OMPC_private, SourceLocation(), SourceLocation(), - N) {} + SourceLocation(), N) {} /// Sets the list of references to private copies with initializers for /// new private variables. @@ -1976,7 +2251,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_private; + return T->getClauseKind() == llvm::omp::OMPC_private; } }; @@ -2004,8 +2279,8 @@ class OMPFirstprivateClause final /// \param N Number of the variables in the clause. OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPFirstprivateClause>(OMPC_firstprivate, StartLoc, - LParenLoc, EndLoc, N), + : OMPVarListClause<OMPFirstprivateClause>(llvm::omp::OMPC_firstprivate, + StartLoc, LParenLoc, EndLoc, N), OMPClauseWithPreInit(this) {} /// Build an empty clause. @@ -2013,7 +2288,7 @@ class OMPFirstprivateClause final /// \param N Number of variables. explicit OMPFirstprivateClause(unsigned N) : OMPVarListClause<OMPFirstprivateClause>( - OMPC_firstprivate, SourceLocation(), SourceLocation(), + llvm::omp::OMPC_firstprivate, SourceLocation(), SourceLocation(), SourceLocation(), N), OMPClauseWithPreInit(this) {} @@ -2117,7 +2392,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_firstprivate; + return T->getClauseKind() == llvm::omp::OMPC_firstprivate; } }; @@ -2170,8 +2445,8 @@ class OMPLastprivateClause final SourceLocation EndLoc, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, unsigned N) - : OMPVarListClause<OMPLastprivateClause>(OMPC_lastprivate, StartLoc, - LParenLoc, EndLoc, N), + : OMPVarListClause<OMPLastprivateClause>(llvm::omp::OMPC_lastprivate, + StartLoc, LParenLoc, EndLoc, N), OMPClauseWithPostUpdate(this), LPKind(LPKind), LPKindLoc(LPKindLoc), ColonLoc(ColonLoc) {} @@ -2180,7 +2455,7 @@ class OMPLastprivateClause final /// \param N Number of variables. explicit OMPLastprivateClause(unsigned N) : OMPVarListClause<OMPLastprivateClause>( - OMPC_lastprivate, SourceLocation(), SourceLocation(), + llvm::omp::OMPC_lastprivate, SourceLocation(), SourceLocation(), SourceLocation(), N), OMPClauseWithPostUpdate(this) {} @@ -2356,7 +2631,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_lastprivate; + return T->getClauseKind() == llvm::omp::OMPC_lastprivate; } }; @@ -2381,16 +2656,16 @@ class OMPSharedClause final /// \param N Number of the variables in the clause. OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc, - EndLoc, N) {} + : OMPVarListClause<OMPSharedClause>(llvm::omp::OMPC_shared, StartLoc, + LParenLoc, EndLoc, N) {} /// Build an empty clause. /// /// \param N Number of variables. explicit OMPSharedClause(unsigned N) - : OMPVarListClause<OMPSharedClause>(OMPC_shared, SourceLocation(), + : OMPVarListClause<OMPSharedClause>(llvm::omp::OMPC_shared, SourceLocation(), SourceLocation(), - N) {} + SourceLocation(), N) {} public: /// Creates clause with a list of variables \a VL. @@ -2428,7 +2703,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_shared; + return T->getClauseKind() == llvm::omp::OMPC_shared; } }; @@ -2448,6 +2723,12 @@ class OMPReductionClause final friend OMPVarListClause; friend TrailingObjects; + /// Reduction modifier. + OpenMPReductionClauseModifier Modifier = OMPC_REDUCTION_unknown; + + /// Reduction modifier location. + SourceLocation ModifierLoc; + /// Location of ':'. SourceLocation ColonLoc; @@ -2461,29 +2742,39 @@ class OMPReductionClause final /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. - /// \param EndLoc Ending location of the clause. + /// \param ModifierLoc Modifier location. /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. /// \param QualifierLoc The nested-name qualifier with location information /// \param NameInfo The full name info for reduction identifier. OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N, + SourceLocation ModifierLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, + OpenMPReductionClauseModifier Modifier, unsigned N, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) - : OMPVarListClause<OMPReductionClause>(OMPC_reduction, StartLoc, - LParenLoc, EndLoc, N), - OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc), + : OMPVarListClause<OMPReductionClause>(llvm::omp::OMPC_reduction, + StartLoc, LParenLoc, EndLoc, N), + OMPClauseWithPostUpdate(this), Modifier(Modifier), + ModifierLoc(ModifierLoc), ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} /// Build an empty clause. /// /// \param N Number of variables. explicit OMPReductionClause(unsigned N) - : OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(), + : OMPVarListClause<OMPReductionClause>(llvm::omp::OMPC_reduction, SourceLocation(), SourceLocation(), - N), + SourceLocation(), N), OMPClauseWithPostUpdate(this) {} + /// Sets reduction modifier. + void setModifier(OpenMPReductionClauseModifier M) { Modifier = M; } + + /// Sets location of the modifier. + void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } + /// Sets location of ':' symbol in clause. void setColonLoc(SourceLocation CL) { ColonLoc = CL; } @@ -2548,11 +2839,47 @@ class OMPReductionClause final return llvm::makeArrayRef(getRHSExprs().end(), varlist_size()); } + /// Set list of helper copy operations for inscan reductions. + /// The form is: Temps[i] = LHS[i]; + void setInscanCopyOps(ArrayRef<Expr *> Ops); + + /// Get the list of helper inscan copy operations. + MutableArrayRef<Expr *> getInscanCopyOps() { + return MutableArrayRef<Expr *>(getReductionOps().end(), varlist_size()); + } + ArrayRef<const Expr *> getInscanCopyOps() const { + return llvm::makeArrayRef(getReductionOps().end(), varlist_size()); + } + + /// Set list of helper temp vars for inscan copy array operations. + void setInscanCopyArrayTemps(ArrayRef<Expr *> CopyArrayTemps); + + /// Get the list of helper inscan copy temps. + MutableArrayRef<Expr *> getInscanCopyArrayTemps() { + return MutableArrayRef<Expr *>(getInscanCopyOps().end(), varlist_size()); + } + ArrayRef<const Expr *> getInscanCopyArrayTemps() const { + return llvm::makeArrayRef(getInscanCopyOps().end(), varlist_size()); + } + + /// Set list of helper temp elements vars for inscan copy array operations. + void setInscanCopyArrayElems(ArrayRef<Expr *> CopyArrayElems); + + /// Get the list of helper inscan copy temps. + MutableArrayRef<Expr *> getInscanCopyArrayElems() { + return MutableArrayRef<Expr *>(getInscanCopyArrayTemps().end(), + varlist_size()); + } + ArrayRef<const Expr *> getInscanCopyArrayElems() const { + return llvm::makeArrayRef(getInscanCopyArrayTemps().end(), varlist_size()); + } + public: /// Creates clause with a list of variables \a VL. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. + /// \param ModifierLoc Modifier location. /// \param ColonLoc Location of ':'. /// \param EndLoc Ending location of the clause. /// \param VL The variables in the clause. @@ -2577,23 +2904,41 @@ public: /// \endcode /// Required for proper codegen of final reduction operation performed by the /// reduction clause. + /// \param CopyOps List of copy operations for inscan reductions: + /// \code + /// TempExprs = LHSExprs; + /// \endcode + /// \param CopyArrayTemps Temp arrays for prefix sums. + /// \param CopyArrayElems Temp arrays for prefix sums. /// \param PreInit Statement that must be executed before entering the OpenMP /// region with this clause. /// \param PostUpdate Expression that must be executed after exit from the /// OpenMP region with this clause. static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL, - NestedNameSpecifierLoc QualifierLoc, + SourceLocation ModifierLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, + ArrayRef<Expr *> VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, - ArrayRef<Expr *> ReductionOps, Stmt *PreInit, Expr *PostUpdate); + ArrayRef<Expr *> ReductionOps, ArrayRef<Expr *> CopyOps, + ArrayRef<Expr *> CopyArrayTemps, ArrayRef<Expr *> CopyArrayElems, + Stmt *PreInit, Expr *PostUpdate); /// Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. - static OMPReductionClause *CreateEmpty(const ASTContext &C, unsigned N); + /// \param Modifier Reduction modifier. + static OMPReductionClause * + CreateEmpty(const ASTContext &C, unsigned N, + OpenMPReductionClauseModifier Modifier); + + /// Returns modifier. + OpenMPReductionClauseModifier getModifier() const { return Modifier; } + + /// Returns modifier location. + SourceLocation getModifierLoc() const { return ModifierLoc; } /// Gets location of ':' symbol in clause. SourceLocation getColonLoc() const { return ColonLoc; } @@ -2644,6 +2989,36 @@ public: getReductionOps().end()); } + helper_expr_const_range copy_ops() const { + return helper_expr_const_range(getInscanCopyOps().begin(), + getInscanCopyOps().end()); + } + + helper_expr_range copy_ops() { + return helper_expr_range(getInscanCopyOps().begin(), + getInscanCopyOps().end()); + } + + helper_expr_const_range copy_array_temps() const { + return helper_expr_const_range(getInscanCopyArrayTemps().begin(), + getInscanCopyArrayTemps().end()); + } + + helper_expr_range copy_array_temps() { + return helper_expr_range(getInscanCopyArrayTemps().begin(), + getInscanCopyArrayTemps().end()); + } + + helper_expr_const_range copy_array_elems() const { + return helper_expr_const_range(getInscanCopyArrayElems().begin(), + getInscanCopyArrayElems().end()); + } + + helper_expr_range copy_array_elems() { + return helper_expr_range(getInscanCopyArrayElems().begin(), + getInscanCopyArrayElems().end()); + } + child_range children() { return child_range(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); @@ -2664,7 +3039,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_reduction; + return T->getClauseKind() == llvm::omp::OMPC_reduction; } }; @@ -2706,8 +3081,8 @@ class OMPTaskReductionClause final SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) - : OMPVarListClause<OMPTaskReductionClause>(OMPC_task_reduction, StartLoc, - LParenLoc, EndLoc, N), + : OMPVarListClause<OMPTaskReductionClause>( + llvm::omp::OMPC_task_reduction, StartLoc, LParenLoc, EndLoc, N), OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} @@ -2716,7 +3091,7 @@ class OMPTaskReductionClause final /// \param N Number of variables. explicit OMPTaskReductionClause(unsigned N) : OMPVarListClause<OMPTaskReductionClause>( - OMPC_task_reduction, SourceLocation(), SourceLocation(), + llvm::omp::OMPC_task_reduction, SourceLocation(), SourceLocation(), SourceLocation(), N), OMPClauseWithPostUpdate(this) {} @@ -2896,7 +3271,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_task_reduction; + return T->getClauseKind() == llvm::omp::OMPC_task_reduction; } }; @@ -2937,8 +3312,8 @@ class OMPInReductionClause final SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) - : OMPVarListClause<OMPInReductionClause>(OMPC_in_reduction, StartLoc, - LParenLoc, EndLoc, N), + : OMPVarListClause<OMPInReductionClause>(llvm::omp::OMPC_in_reduction, + StartLoc, LParenLoc, EndLoc, N), OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} @@ -2947,7 +3322,7 @@ class OMPInReductionClause final /// \param N Number of variables. explicit OMPInReductionClause(unsigned N) : OMPVarListClause<OMPInReductionClause>( - OMPC_in_reduction, SourceLocation(), SourceLocation(), + llvm::omp::OMPC_in_reduction, SourceLocation(), SourceLocation(), SourceLocation(), N), OMPClauseWithPostUpdate(this) {} @@ -3151,7 +3526,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_in_reduction; + return T->getClauseKind() == llvm::omp::OMPC_in_reduction; } }; @@ -3197,8 +3572,8 @@ class OMPLinearClause final OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned NumVars) - : OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc, - EndLoc, NumVars), + : OMPVarListClause<OMPLinearClause>(llvm::omp::OMPC_linear, StartLoc, + LParenLoc, EndLoc, NumVars), OMPClauseWithPostUpdate(this), Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {} @@ -3206,9 +3581,9 @@ class OMPLinearClause final /// /// \param NumVars Number of variables. explicit OMPLinearClause(unsigned NumVars) - : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(), + : OMPVarListClause<OMPLinearClause>(llvm::omp::OMPC_linear, SourceLocation(), SourceLocation(), - NumVars), + SourceLocation(), NumVars), OMPClauseWithPostUpdate(this) {} /// Gets the list of initial values for linear variables. @@ -3428,7 +3803,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_linear; + return T->getClauseKind() == llvm::omp::OMPC_linear; } }; @@ -3463,17 +3838,17 @@ class OMPAlignedClause final OMPAlignedClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, unsigned NumVars) - : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, StartLoc, LParenLoc, - EndLoc, NumVars), + : OMPVarListClause<OMPAlignedClause>(llvm::omp::OMPC_aligned, StartLoc, + LParenLoc, EndLoc, NumVars), ColonLoc(ColonLoc) {} /// Build an empty clause. /// /// \param NumVars Number of variables. explicit OMPAlignedClause(unsigned NumVars) - : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, SourceLocation(), + : OMPVarListClause<OMPAlignedClause>(llvm::omp::OMPC_aligned, SourceLocation(), SourceLocation(), - NumVars) {} + SourceLocation(), NumVars) {} public: /// Creates clause with a list of variables \a VL and alignment \a A. @@ -3527,7 +3902,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_aligned; + return T->getClauseKind() == llvm::omp::OMPC_aligned; } }; @@ -3566,16 +3941,16 @@ class OMPCopyinClause final /// \param N Number of the variables in the clause. OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc, - EndLoc, N) {} + : OMPVarListClause<OMPCopyinClause>(llvm::omp::OMPC_copyin, StartLoc, + LParenLoc, EndLoc, N) {} /// Build an empty clause. /// /// \param N Number of variables. explicit OMPCopyinClause(unsigned N) - : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, SourceLocation(), + : OMPVarListClause<OMPCopyinClause>(llvm::omp::OMPC_copyin, SourceLocation(), SourceLocation(), - N) {} + SourceLocation(), N) {} /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent source expression in the final @@ -3703,7 +4078,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_copyin; + return T->getClauseKind() == llvm::omp::OMPC_copyin; } }; @@ -3730,15 +4105,16 @@ class OMPCopyprivateClause final /// \param N Number of the variables in the clause. OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc, - LParenLoc, EndLoc, N) {} + : OMPVarListClause<OMPCopyprivateClause>(llvm::omp::OMPC_copyprivate, + StartLoc, LParenLoc, EndLoc, N) { + } /// Build an empty clause. /// /// \param N Number of variables. explicit OMPCopyprivateClause(unsigned N) : OMPVarListClause<OMPCopyprivateClause>( - OMPC_copyprivate, SourceLocation(), SourceLocation(), + llvm::omp::OMPC_copyprivate, SourceLocation(), SourceLocation(), SourceLocation(), N) {} /// Set list of helper expressions, required for proper codegen of the @@ -3866,7 +4242,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_copyprivate; + return T->getClauseKind() == llvm::omp::OMPC_copyprivate; } }; @@ -3896,16 +4272,16 @@ class OMPFlushClause final /// \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) {} + : OMPVarListClause<OMPFlushClause>(llvm::omp::OMPC_flush, StartLoc, + LParenLoc, EndLoc, N) {} /// Build an empty clause. /// /// \param N Number of variables. explicit OMPFlushClause(unsigned N) - : OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(), + : OMPVarListClause<OMPFlushClause>(llvm::omp::OMPC_flush, SourceLocation(), SourceLocation(), - N) {} + SourceLocation(), N) {} public: /// Creates clause with a list of variables \a VL. @@ -3943,7 +4319,94 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_flush; + return T->getClauseKind() == llvm::omp::OMPC_flush; + } +}; + +/// This represents implicit clause 'depobj' for the '#pragma omp depobj' +/// directive. +/// This clause does not exist by itself, it can be only as a part of 'omp +/// depobj' 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 depobj(a) destroy +/// \endcode +/// In this example directive '#pragma omp depobj' has implicit clause 'depobj' +/// with the depobj 'a'. +class OMPDepobjClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// Chunk size. + Expr *Depobj = nullptr; + + /// 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. + OMPDepobjClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_depobj, StartLoc, EndLoc), + LParenLoc(LParenLoc) {} + + /// Build an empty clause. + /// + explicit OMPDepobjClause() + : OMPClause(llvm::omp::OMPC_depobj, SourceLocation(), SourceLocation()) {} + + void setDepobj(Expr *E) { Depobj = E; } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + +public: + /// Creates clause. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param Depobj depobj expression associated with the 'depobj' directive. + static OMPDepobjClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, Expr *Depobj); + + /// Creates an empty clause. + /// + /// \param C AST context. + static OMPDepobjClause *CreateEmpty(const ASTContext &C); + + /// Returns depobj expression associated with the clause. + Expr *getDepobj() { return Depobj; } + const Expr *getDepobj() const { return Depobj; } + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(&Depobj), + reinterpret_cast<Stmt **>(&Depobj) + 1); + } + + const_child_range children() const { + auto Children = const_cast<OMPDepobjClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_depobj; } }; @@ -3984,8 +4447,9 @@ class OMPDependClause final /// clause. OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N, unsigned NumLoops) - : OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc, - EndLoc, N), NumLoops(NumLoops) {} + : OMPVarListClause<OMPDependClause>(llvm::omp::OMPC_depend, StartLoc, + LParenLoc, EndLoc, N), + NumLoops(NumLoops) {} /// Build an empty clause. /// @@ -3993,9 +4457,9 @@ class OMPDependClause final /// \param NumLoops Number of loops that is associated with this depend /// clause. explicit OMPDependClause(unsigned N, unsigned NumLoops) - : OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(), + : OMPVarListClause<OMPDependClause>(llvm::omp::OMPC_depend, SourceLocation(), SourceLocation(), - N), + SourceLocation(), N), NumLoops(NumLoops) {} /// Set dependency kind. @@ -4007,6 +4471,9 @@ class OMPDependClause final /// Set colon location. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + /// Sets optional dependency modifier. + void setModifier(Expr *DepModifier); + public: /// Creates clause with a list of variables \a VL. /// @@ -4022,7 +4489,7 @@ public: /// clause. static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, + SourceLocation EndLoc, Expr *DepModifier, OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL, unsigned NumLoops); @@ -4039,6 +4506,12 @@ public: /// Get dependency type. OpenMPDependClauseKind getDependencyKind() const { return DepKind; } + /// Return optional depend modifier. + Expr *getModifier(); + const Expr *getModifier() const { + return const_cast<OMPDependClause *>(this)->getModifier(); + } + /// Get dependency type location. SourceLocation getDependencyLoc() const { return DepLoc; } @@ -4074,7 +4547,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_depend; + return T->getClauseKind() == llvm::omp::OMPC_depend; } }; @@ -4092,6 +4565,12 @@ class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit { /// Location of '('. SourceLocation LParenLoc; + /// Device clause modifier. + OpenMPDeviceClauseModifier Modifier = OMPC_DEVICE_unknown; + + /// Location of the modifier. + SourceLocation ModifierLoc; + /// Device number. Stmt *Device = nullptr; @@ -4100,26 +4579,36 @@ class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit { /// \param E Device number. void setDevice(Expr *E) { Device = E; } + /// Sets modifier. + void setModifier(OpenMPDeviceClauseModifier M) { Modifier = M; } + + /// Setst modifier location. + void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } + public: /// Build 'device' clause. /// + /// \param Modifier Clause modifier. /// \param E Expression associated with this clause. /// \param CaptureRegion Innermost OpenMP region where expressions in this /// clause must be captured. /// \param StartLoc Starting location of the clause. + /// \param ModifierLoc Modifier location. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - OMPDeviceClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, - SourceLocation StartLoc, SourceLocation LParenLoc, + OMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *E, Stmt *HelperE, + OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc) - : OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), Device(E) { + : OMPClause(llvm::omp::OMPC_device, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Modifier(Modifier), + ModifierLoc(ModifierLoc), Device(E) { setPreInitStmt(HelperE, CaptureRegion); } /// Build an empty clause. OMPDeviceClause() - : OMPClause(OMPC_device, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_device, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -4134,6 +4623,12 @@ public: /// Return device number. Expr *getDevice() const { return cast<Expr>(Device); } + /// Gets modifier. + OpenMPDeviceClauseModifier getModifier() const { return Modifier; } + + /// Gets modifier location. + SourceLocation getModifierLoc() const { return ModifierLoc; } + child_range children() { return child_range(&Device, &Device + 1); } const_child_range children() const { @@ -4148,7 +4643,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_device; + return T->getClauseKind() == llvm::omp::OMPC_device; } }; @@ -4165,11 +4660,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_threads, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_threads, StartLoc, EndLoc) {} /// Build an empty clause. OMPThreadsClause() - : OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_threads, SourceLocation(), SourceLocation()) { + } child_range children() { return child_range(child_iterator(), child_iterator()); @@ -4187,7 +4683,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_threads; + return T->getClauseKind() == llvm::omp::OMPC_threads; } }; @@ -4204,10 +4700,11 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_simd, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_simd, StartLoc, EndLoc) {} /// Build an empty clause. - OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {} + OMPSIMDClause() + : OMPClause(llvm::omp::OMPC_simd, SourceLocation(), SourceLocation()) {} child_range children() { return child_range(child_iterator(), child_iterator()); @@ -4225,7 +4722,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_simd; + return T->getClauseKind() == llvm::omp::OMPC_simd; } }; @@ -4853,19 +5350,14 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, return getUniqueDeclarationsNum() + getTotalComponentListNum(); } -public: - /// Number of allowed map-type-modifiers. - static constexpr unsigned NumberOfModifiers = - OMPC_MAP_MODIFIER_last - OMPC_MAP_MODIFIER_unknown - 1; - private: /// Map-type-modifiers for the 'map' clause. - OpenMPMapModifierKind MapTypeModifiers[NumberOfModifiers] = { + OpenMPMapModifierKind MapTypeModifiers[NumberOfOMPMapClauseModifiers] = { OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; /// Location of map-type-modifiers for the 'map' clause. - SourceLocation MapTypeModifiersLoc[NumberOfModifiers]; + SourceLocation MapTypeModifiersLoc[NumberOfOMPMapClauseModifiers]; /// Map type for the 'map' clause. OpenMPMapClauseKind MapType = OMPC_MAP_unknown; @@ -4906,8 +5398,8 @@ private: OpenMPMapClauseKind MapType, bool MapTypeIsImplicit, SourceLocation MapLoc, const OMPVarListLocTy &Locs, const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_map, Locs, Sizes, &MapperQualifierLoc, - &MapperIdInfo), + : OMPMappableExprListClause(llvm::omp::OMPC_map, Locs, Sizes, + &MapperQualifierLoc, &MapperIdInfo), MapType(MapType), MapTypeIsImplicit(MapTypeIsImplicit), MapLoc(MapLoc) { assert(llvm::array_lengthof(MapTypeModifiers) == MapModifiers.size() && "Unexpected number of map type modifiers."); @@ -4927,14 +5419,15 @@ private: /// 3) NumComponentLists: number of component lists in this clause; and 4) /// NumComponents: total number of expression components in the clause. explicit OMPMapClause(const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_map, OMPVarListLocTy(), Sizes) {} + : OMPMappableExprListClause(llvm::omp::OMPC_map, OMPVarListLocTy(), + Sizes) {} /// Set map-type-modifier for the clause. /// /// \param I index for map-type-modifier. /// \param T map-type-modifier for the clause. void setMapTypeModifier(unsigned I, OpenMPMapModifierKind T) { - assert(I < NumberOfModifiers && + assert(I < NumberOfOMPMapClauseModifiers && "Unexpected index to store map type modifier, exceeds array size."); MapTypeModifiers[I] = T; } @@ -4944,7 +5437,7 @@ private: /// \param I index for map-type-modifier location. /// \param TLoc map-type-modifier location. void setMapTypeModifierLoc(unsigned I, SourceLocation TLoc) { - assert(I < NumberOfModifiers && + assert(I < NumberOfOMPMapClauseModifiers && "Index to store map type modifier location exceeds array size."); MapTypeModifiersLoc[I] = TLoc; } @@ -5019,7 +5512,7 @@ public: /// /// \param Cnt index for map-type-modifier. OpenMPMapModifierKind getMapTypeModifier(unsigned Cnt) const LLVM_READONLY { - assert(Cnt < NumberOfModifiers && + assert(Cnt < NumberOfOMPMapClauseModifiers && "Requested modifier exceeds the total number of modifiers."); return MapTypeModifiers[Cnt]; } @@ -5029,7 +5522,7 @@ public: /// /// \param Cnt index for map-type-modifier location. SourceLocation getMapTypeModifierLoc(unsigned Cnt) const LLVM_READONLY { - assert(Cnt < NumberOfModifiers && + assert(Cnt < NumberOfOMPMapClauseModifiers && "Requested modifier location exceeds total number of modifiers."); return MapTypeModifiersLoc[Cnt]; } @@ -5074,7 +5567,7 @@ public: static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_map; + return T->getClauseKind() == llvm::omp::OMPC_map; } }; @@ -5113,14 +5606,15 @@ public: OMPNumTeamsClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_teams, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), NumTeams(E) { + : OMPClause(llvm::omp::OMPC_num_teams, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), NumTeams(E) { setPreInitStmt(HelperE, CaptureRegion); } /// Build an empty clause. OMPNumTeamsClause() - : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_num_teams, SourceLocation(), + SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -5149,7 +5643,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_num_teams; + return T->getClauseKind() == llvm::omp::OMPC_num_teams; } }; @@ -5189,14 +5683,15 @@ public: OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), + : OMPClause(llvm::omp::OMPC_thread_limit, StartLoc, EndLoc), OMPClauseWithPreInit(this), LParenLoc(LParenLoc), ThreadLimit(E) { setPreInitStmt(HelperE, CaptureRegion); } /// Build an empty clause. OMPThreadLimitClause() - : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_thread_limit, SourceLocation(), + SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -5225,7 +5720,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_thread_limit; + return T->getClauseKind() == llvm::omp::OMPC_thread_limit; } }; @@ -5264,14 +5759,14 @@ public: OMPPriorityClause(Expr *Priority, Stmt *HelperPriority, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_priority, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), Priority(Priority) { + : OMPClause(llvm::omp::OMPC_priority, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Priority(Priority) { setPreInitStmt(HelperPriority, CaptureRegion); } /// Build an empty clause. OMPPriorityClause() - : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_priority, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -5299,7 +5794,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_priority; + return T->getClauseKind() == llvm::omp::OMPC_priority; } }; @@ -5335,14 +5830,15 @@ public: OMPGrainsizeClause(Expr *Size, Stmt *HelperSize, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_grainsize, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), Grainsize(Size) { + : OMPClause(llvm::omp::OMPC_grainsize, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Grainsize(Size) { setPreInitStmt(HelperSize, CaptureRegion); } /// Build an empty clause. explicit OMPGrainsizeClause() - : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_grainsize, SourceLocation(), + SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -5367,7 +5863,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_grainsize; + return T->getClauseKind() == llvm::omp::OMPC_grainsize; } }; @@ -5384,11 +5880,12 @@ public: /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_nogroup, StartLoc, EndLoc) {} + : OMPClause(llvm::omp::OMPC_nogroup, StartLoc, EndLoc) {} /// Build an empty clause. OMPNogroupClause() - : OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_nogroup, SourceLocation(), SourceLocation()) { + } child_range children() { return child_range(child_iterator(), child_iterator()); @@ -5406,7 +5903,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_nogroup; + return T->getClauseKind() == llvm::omp::OMPC_nogroup; } }; @@ -5442,14 +5939,15 @@ public: OMPNumTasksClause(Expr *Size, Stmt *HelperSize, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), OMPClauseWithPreInit(this), - LParenLoc(LParenLoc), NumTasks(Size) { + : OMPClause(llvm::omp::OMPC_num_tasks, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), NumTasks(Size) { setPreInitStmt(HelperSize, CaptureRegion); } /// Build an empty clause. explicit OMPNumTasksClause() - : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_num_tasks, SourceLocation(), + SourceLocation()), OMPClauseWithPreInit(this) {} /// Sets the location of '('. @@ -5474,7 +5972,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_num_tasks; + return T->getClauseKind() == llvm::omp::OMPC_num_tasks; } }; @@ -5506,11 +6004,12 @@ public: /// \param EndLoc Ending location of the clause. OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc), + : OMPClause(llvm::omp::OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc), Hint(Hint) {} /// Build an empty clause. - OMPHintClause() : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()) {} + OMPHintClause() + : OMPClause(llvm::omp::OMPC_hint, SourceLocation(), SourceLocation()) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -5535,7 +6034,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_hint; + return T->getClauseKind() == llvm::omp::OMPC_hint; } }; @@ -5607,7 +6106,7 @@ public: SourceLocation EndLoc, OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, Stmt *HelperChunkSize) - : OMPClause(OMPC_dist_schedule, StartLoc, EndLoc), + : OMPClause(llvm::omp::OMPC_dist_schedule, StartLoc, EndLoc), OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) { setPreInitStmt(HelperChunkSize); @@ -5615,7 +6114,8 @@ public: /// Build an empty clause. explicit OMPDistScheduleClause() - : OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()), + : OMPClause(llvm::omp::OMPC_dist_schedule, SourceLocation(), + SourceLocation()), OMPClauseWithPreInit(this) {} /// Get kind of the clause. @@ -5654,7 +6154,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_dist_schedule; + return T->getClauseKind() == llvm::omp::OMPC_dist_schedule; } }; @@ -5724,12 +6224,14 @@ public: SourceLocation MLoc, SourceLocation KLoc, SourceLocation EndLoc, OpenMPDefaultmapClauseKind Kind, OpenMPDefaultmapClauseModifier M) - : OMPClause(OMPC_defaultmap, StartLoc, EndLoc), LParenLoc(LParenLoc), - Modifier(M), ModifierLoc(MLoc), Kind(Kind), KindLoc(KLoc) {} + : OMPClause(llvm::omp::OMPC_defaultmap, StartLoc, EndLoc), + LParenLoc(LParenLoc), Modifier(M), ModifierLoc(MLoc), Kind(Kind), + KindLoc(KLoc) {} /// Build an empty clause. explicit OMPDefaultmapClause() - : OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()) {} + : OMPClause(llvm::omp::OMPC_defaultmap, SourceLocation(), + SourceLocation()) {} /// Get kind of the clause. OpenMPDefaultmapClauseKind getDefaultmapKind() const { return Kind; } @@ -5766,7 +6268,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_defaultmap; + return T->getClauseKind() == llvm::omp::OMPC_defaultmap; } }; @@ -5804,8 +6306,8 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, DeclarationNameInfo MapperIdInfo, const OMPVarListLocTy &Locs, const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_to, Locs, Sizes, &MapperQualifierLoc, - &MapperIdInfo) {} + : OMPMappableExprListClause(llvm::omp::OMPC_to, Locs, Sizes, + &MapperQualifierLoc, &MapperIdInfo) {} /// Build an empty clause. /// @@ -5815,7 +6317,8 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, /// 3) NumComponentLists: number of component lists in this clause; and 4) /// NumComponents: total number of expression components in the clause. explicit OMPToClause(const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_to, OMPVarListLocTy(), Sizes) {} + : OMPMappableExprListClause(llvm::omp::OMPC_to, OMPVarListLocTy(), + Sizes) {} /// Define the sizes of each trailing object array except the last one. This /// is required for TrailingObjects to work properly. @@ -5883,7 +6386,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_to; + return T->getClauseKind() == llvm::omp::OMPC_to; } }; @@ -5922,8 +6425,8 @@ class OMPFromClause final DeclarationNameInfo MapperIdInfo, const OMPVarListLocTy &Locs, const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_from, Locs, Sizes, &MapperQualifierLoc, - &MapperIdInfo) {} + : OMPMappableExprListClause(llvm::omp::OMPC_from, Locs, Sizes, + &MapperQualifierLoc, &MapperIdInfo) {} /// Build an empty clause. /// @@ -5933,7 +6436,8 @@ class OMPFromClause final /// 3) NumComponentLists: number of component lists in this clause; and 4) /// NumComponents: total number of expression components in the clause. explicit OMPFromClause(const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_from, OMPVarListLocTy(), Sizes) {} + : OMPMappableExprListClause(llvm::omp::OMPC_from, OMPVarListLocTy(), + Sizes) {} /// Define the sizes of each trailing object array except the last one. This /// is required for TrailingObjects to work properly. @@ -6001,7 +6505,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_from; + return T->getClauseKind() == llvm::omp::OMPC_from; } }; @@ -6035,7 +6539,8 @@ class OMPUseDevicePtrClause final /// NumComponents: total number of expression components in the clause. explicit OMPUseDevicePtrClause(const OMPVarListLocTy &Locs, const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_use_device_ptr, Locs, Sizes) {} + : OMPMappableExprListClause(llvm::omp::OMPC_use_device_ptr, Locs, Sizes) { + } /// Build an empty clause. /// @@ -6045,8 +6550,8 @@ class OMPUseDevicePtrClause final /// 3) NumComponentLists: number of component lists in this clause; and 4) /// NumComponents: total number of expression components in the clause. explicit OMPUseDevicePtrClause(const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_use_device_ptr, OMPVarListLocTy(), - Sizes) {} + : OMPMappableExprListClause(llvm::omp::OMPC_use_device_ptr, + OMPVarListLocTy(), Sizes) {} /// Define the sizes of each trailing object array except the last one. This /// is required for TrailingObjects to work properly. @@ -6164,7 +6669,111 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_use_device_ptr; + return T->getClauseKind() == llvm::omp::OMPC_use_device_ptr; + } +}; + +/// This represents clause 'use_device_addr' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target data use_device_addr(a,b) +/// \endcode +/// In this example directive '#pragma omp target data' has clause +/// 'use_device_addr' with the variables 'a' and 'b'. +class OMPUseDeviceAddrClause final + : public OMPMappableExprListClause<OMPUseDeviceAddrClause>, + private llvm::TrailingObjects< + OMPUseDeviceAddrClause, Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent> { + friend class OMPClauseReader; + friend OMPMappableExprListClause; + friend OMPVarListClause; + friend TrailingObjects; + + /// Build clause with number of variables \a NumVars. + /// + /// \param Locs Locations needed to build a mappable clause. It includes 1) + /// StartLoc: starting location of the clause (the clause keyword); 2) + /// LParenLoc: location of '('; 3) EndLoc: ending location of the clause. + /// \param Sizes All required sizes to build a mappable clause. It includes 1) + /// NumVars: number of expressions listed in this clause; 2) + /// NumUniqueDeclarations: number of unique base declarations in this clause; + /// 3) NumComponentLists: number of component lists in this clause; and 4) + /// NumComponents: total number of expression components in the clause. + explicit OMPUseDeviceAddrClause(const OMPVarListLocTy &Locs, + const OMPMappableExprListSizeTy &Sizes) + : OMPMappableExprListClause(llvm::omp::OMPC_use_device_addr, Locs, + Sizes) {} + + /// Build an empty clause. + /// + /// \param Sizes All required sizes to build a mappable clause. It includes 1) + /// NumVars: number of expressions listed in this clause; 2) + /// NumUniqueDeclarations: number of unique base declarations in this clause; + /// 3) NumComponentLists: number of component lists in this clause; and 4) + /// NumComponents: total number of expression components in the clause. + explicit OMPUseDeviceAddrClause(const OMPMappableExprListSizeTy &Sizes) + : OMPMappableExprListClause(llvm::omp::OMPC_use_device_addr, + OMPVarListLocTy(), Sizes) {} + + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<Expr *>) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken<ValueDecl *>) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken<unsigned>) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + +public: + /// Creates clause with a list of variables \a Vars. + /// + /// \param C AST context. + /// \param Locs Locations needed to build a mappable clause. It includes 1) + /// StartLoc: starting location of the clause (the clause keyword); 2) + /// LParenLoc: location of '('; 3) EndLoc: ending location of the clause. + /// \param Vars The original expression used in the clause. + /// \param Declarations Declarations used in the clause. + /// \param ComponentLists Component lists used in the clause. + static OMPUseDeviceAddrClause * + Create(const ASTContext &C, const OMPVarListLocTy &Locs, + ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists); + + /// Creates an empty clause with the place for \a NumVars variables. + /// + /// \param C AST context. + /// \param Sizes All required sizes to build a mappable clause. It includes 1) + /// NumVars: number of expressions listed in this clause; 2) + /// NumUniqueDeclarations: number of unique base declarations in this clause; + /// 3) NumComponentLists: number of component lists in this clause; and 4) + /// NumComponents: total number of expression components in the clause. + static OMPUseDeviceAddrClause * + CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes); + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast<OMPUseDeviceAddrClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_use_device_addr; } }; @@ -6198,7 +6807,7 @@ class OMPIsDevicePtrClause final /// NumComponents: total number of expression components in the clause. explicit OMPIsDevicePtrClause(const OMPVarListLocTy &Locs, const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_is_device_ptr, Locs, Sizes) {} + : OMPMappableExprListClause(llvm::omp::OMPC_is_device_ptr, Locs, Sizes) {} /// Build an empty clause. /// @@ -6208,8 +6817,8 @@ class OMPIsDevicePtrClause final /// 3) NumComponentLists: number of component lists in this clause; and 4) /// NumComponents: total number of expression components in the clause. explicit OMPIsDevicePtrClause(const OMPMappableExprListSizeTy &Sizes) - : OMPMappableExprListClause(OMPC_is_device_ptr, OMPVarListLocTy(), - Sizes) {} + : OMPMappableExprListClause(llvm::omp::OMPC_is_device_ptr, + OMPVarListLocTy(), Sizes) {} /// Define the sizes of each trailing object array except the last one. This /// is required for TrailingObjects to work properly. @@ -6267,7 +6876,7 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_is_device_ptr; + return T->getClauseKind() == llvm::omp::OMPC_is_device_ptr; } }; @@ -6293,15 +6902,16 @@ class OMPNontemporalClause final /// \param N Number of the variables in the clause. OMPNontemporalClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) - : OMPVarListClause<OMPNontemporalClause>(OMPC_nontemporal, StartLoc, - LParenLoc, EndLoc, N) {} + : OMPVarListClause<OMPNontemporalClause>(llvm::omp::OMPC_nontemporal, + StartLoc, LParenLoc, EndLoc, N) { + } /// Build an empty clause. /// /// \param N Number of variables. explicit OMPNontemporalClause(unsigned N) : OMPVarListClause<OMPNontemporalClause>( - OMPC_nontemporal, SourceLocation(), SourceLocation(), + llvm::omp::OMPC_nontemporal, SourceLocation(), SourceLocation(), SourceLocation(), N) {} /// Get the list of privatied copies if the member expression was captured by @@ -6363,7 +6973,563 @@ public: } static bool classof(const OMPClause *T) { - return T->getClauseKind() == OMPC_nontemporal; + return T->getClauseKind() == llvm::omp::OMPC_nontemporal; + } +}; + +/// This represents 'order' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp simd order(concurrent) +/// \endcode +/// In this example directive '#pragma omp parallel' has simple 'order' +/// clause with kind 'concurrent'. +class OMPOrderClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// A kind of the 'default' clause. + OpenMPOrderClauseKind Kind = OMPC_ORDER_unknown; + + /// Start location of the kind in source code. + SourceLocation KindKwLoc; + + /// Set kind of the clause. + /// + /// \param K Argument of clause. + void setKind(OpenMPOrderClauseKind K) { Kind = K; } + + /// Set argument location. + /// + /// \param KLoc Argument location. + void setKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + +public: + /// Build 'order' clause with argument \p A ('concurrent'). + /// + /// \param A Argument of the clause ('concurrent'). + /// \param ALoc Starting location of the argument. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPOrderClause(OpenMPOrderClauseKind A, SourceLocation ALoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_order, StartLoc, EndLoc), + LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} + + /// Build an empty clause. + OMPOrderClause() + : OMPClause(llvm::omp::OMPC_order, SourceLocation(), SourceLocation()) {} + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns kind of the clause. + OpenMPOrderClauseKind getKind() const { return Kind; } + + /// Returns location of clause kind. + SourceLocation getKindKwLoc() const { return KindKwLoc; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_order; + } +}; + +/// This represents 'destroy' clause in the '#pragma omp depobj' +/// directive. +/// +/// \code +/// #pragma omp depobj(a) destroy +/// \endcode +/// In this example directive '#pragma omp depobj' has 'destroy' clause. +class OMPDestroyClause final : public OMPClause { +public: + /// Build 'destroy' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPDestroyClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_destroy, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPDestroyClause() + : OMPClause(llvm::omp::OMPC_destroy, SourceLocation(), SourceLocation()) { + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_destroy; + } +}; + +/// This represents 'detach' clause in the '#pragma omp task' directive. +/// +/// \code +/// #pragma omp task detach(evt) +/// \endcode +/// In this example directive '#pragma omp detach' has simple 'detach' clause +/// with the variable 'evt'. +class OMPDetachClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '('. + SourceLocation LParenLoc; + + /// Expression of the 'detach' clause. + Stmt *Evt = nullptr; + + /// Set condition. + void setEventHandler(Expr *E) { Evt = E; } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + +public: + /// Build 'detach' clause with event-handler \a Evt. + /// + /// \param Evt Event handler expression. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_detach, StartLoc, EndLoc), + LParenLoc(LParenLoc), Evt(Evt) {} + + /// Build an empty clause. + OMPDetachClause() + : OMPClause(llvm::omp::OMPC_detach, SourceLocation(), SourceLocation()) {} + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns event-handler expression. + Expr *getEventHandler() const { return cast_or_null<Expr>(Evt); } + + child_range children() { return child_range(&Evt, &Evt + 1); } + + const_child_range children() const { + return const_child_range(&Evt, &Evt + 1); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_detach; + } +}; + +/// This represents clause 'inclusive' in the '#pragma omp scan' directive. +/// +/// \code +/// #pragma omp scan inclusive(a,b) +/// \endcode +/// In this example directive '#pragma omp scan' has clause 'inclusive' +/// with the variables 'a' and 'b'. +class OMPInclusiveClause final + : public OMPVarListClause<OMPInclusiveClause>, + private llvm::TrailingObjects<OMPInclusiveClause, Expr *> { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// 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. + OMPInclusiveClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPInclusiveClause>(llvm::omp::OMPC_inclusive, + StartLoc, LParenLoc, EndLoc, N) {} + + /// Build an empty clause. + /// + /// \param N Number of variables. + explicit OMPInclusiveClause(unsigned N) + : OMPVarListClause<OMPInclusiveClause>(llvm::omp::OMPC_inclusive, + SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + +public: + /// 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 original variables. + static OMPInclusiveClause *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + static OMPInclusiveClause *CreateEmpty(const ASTContext &C, unsigned N); + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast<OMPInclusiveClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_inclusive; + } +}; + +/// This represents clause 'exclusive' in the '#pragma omp scan' directive. +/// +/// \code +/// #pragma omp scan exclusive(a,b) +/// \endcode +/// In this example directive '#pragma omp scan' has clause 'exclusive' +/// with the variables 'a' and 'b'. +class OMPExclusiveClause final + : public OMPVarListClause<OMPExclusiveClause>, + private llvm::TrailingObjects<OMPExclusiveClause, Expr *> { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// 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. + OMPExclusiveClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPExclusiveClause>(llvm::omp::OMPC_exclusive, + StartLoc, LParenLoc, EndLoc, N) {} + + /// Build an empty clause. + /// + /// \param N Number of variables. + explicit OMPExclusiveClause(unsigned N) + : OMPVarListClause<OMPExclusiveClause>(llvm::omp::OMPC_exclusive, + SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + +public: + /// 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 original variables. + static OMPExclusiveClause *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<Expr *> VL); + + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + static OMPExclusiveClause *CreateEmpty(const ASTContext &C, unsigned N); + + child_range children() { + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast<OMPExclusiveClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_exclusive; + } +}; + +/// This represents clause 'uses_allocators' in the '#pragma omp target'-based +/// directives. +/// +/// \code +/// #pragma omp target uses_allocators(default_allocator, my_allocator(traits)) +/// \endcode +/// In this example directive '#pragma omp target' has clause 'uses_allocators' +/// with the allocators 'default_allocator' and user-defined 'my_allocator'. +class OMPUsesAllocatorsClause final + : public OMPClause, + private llvm::TrailingObjects<OMPUsesAllocatorsClause, Expr *, + SourceLocation> { +public: + /// Data for list of allocators. + struct Data { + /// Allocator. + Expr *Allocator = nullptr; + /// Allocator traits. + Expr *AllocatorTraits = nullptr; + /// Locations of '(' and ')' symbols. + SourceLocation LParenLoc, RParenLoc; + }; + +private: + friend class OMPClauseReader; + friend TrailingObjects; + + enum class ExprOffsets { + Allocator, + AllocatorTraits, + Total, + }; + + enum class ParenLocsOffsets { + LParen, + RParen, + Total, + }; + + /// Location of '('. + SourceLocation LParenLoc; + /// Total number of allocators in the clause. + unsigned NumOfAllocators = 0; + + /// Build clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of allocators asssociated with the clause. + OMPUsesAllocatorsClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPClause(llvm::omp::OMPC_uses_allocators, StartLoc, EndLoc), + LParenLoc(LParenLoc), NumOfAllocators(N) {} + + /// Build an empty clause. + /// \param N Number of allocators asssociated with the clause. + /// + explicit OMPUsesAllocatorsClause(unsigned N) + : OMPClause(llvm::omp::OMPC_uses_allocators, SourceLocation(), + SourceLocation()), + NumOfAllocators(N) {} + + unsigned numTrailingObjects(OverloadToken<Expr *>) const { + return NumOfAllocators * static_cast<int>(ExprOffsets::Total); + } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + + /// Sets the allocators data for the clause. + void setAllocatorsData(ArrayRef<OMPUsesAllocatorsClause::Data> Data); + +public: + /// Creates clause with a list of allocators \p Data. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param Data List of allocators. + static OMPUsesAllocatorsClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef<OMPUsesAllocatorsClause::Data> Data); + + /// Creates an empty clause with the place for \p N allocators. + /// + /// \param C AST context. + /// \param N The number of allocators. + static OMPUsesAllocatorsClause *CreateEmpty(const ASTContext &C, unsigned N); + + /// Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns number of allocators associated with the clause. + unsigned getNumberOfAllocators() const { return NumOfAllocators; } + + /// Returns data for the specified allocator. + OMPUsesAllocatorsClause::Data getAllocatorData(unsigned I) const; + + // Iterators + child_range children() { + Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); + return child_range(Begin, Begin + NumOfAllocators * + static_cast<int>(ExprOffsets::Total)); + } + const_child_range children() const { + Stmt *const *Begin = + reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); + return const_child_range( + Begin, Begin + NumOfAllocators * static_cast<int>(ExprOffsets::Total)); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_uses_allocators; + } +}; + +/// This represents clause 'affinity' in the '#pragma omp task'-based +/// directives. +/// +/// \code +/// #pragma omp task affinity(iterator(i = 0:n) : ([3][n])a, b[:n], c[i]) +/// \endcode +/// In this example directive '#pragma omp task' has clause 'affinity' with the +/// affinity modifer 'iterator(i = 0:n)' and locator items '([3][n])a', 'b[:n]' +/// and 'c[i]'. +class OMPAffinityClause final + : public OMPVarListClause<OMPAffinityClause>, + private llvm::TrailingObjects<OMPAffinityClause, Expr *> { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// Location of ':' symbol. + SourceLocation ColonLoc; + + /// Build clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param N Number of locators asssociated with the clause. + OMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N) + : OMPVarListClause<OMPAffinityClause>(llvm::omp::OMPC_affinity, StartLoc, + LParenLoc, EndLoc, N) {} + + /// Build an empty clause. + /// \param N Number of locators asssociated with the clause. + /// + explicit OMPAffinityClause(unsigned N) + : OMPVarListClause<OMPAffinityClause>(llvm::omp::OMPC_affinity, + SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + + /// Sets the affinity modifier for the clause, if any. + void setModifier(Expr *E) { + getTrailingObjects<Expr *>()[varlist_size()] = E; + } + + /// Sets the location of ':' symbol. + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + +public: + /// Creates clause with a modifier a list of locator items. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ColonLoc Location of ':'. + /// \param EndLoc Ending location of the clause. + /// \param Locators List of locator items. + static OMPAffinityClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc, Expr *Modifier, + ArrayRef<Expr *> Locators); + + /// Creates an empty clause with the place for \p N locator items. + /// + /// \param C AST context. + /// \param N The number of locator items. + static OMPAffinityClause *CreateEmpty(const ASTContext &C, unsigned N); + + /// Gets affinity modifier. + Expr *getModifier() { return getTrailingObjects<Expr *>()[varlist_size()]; } + Expr *getModifier() const { + return getTrailingObjects<Expr *>()[varlist_size()]; + } + + /// Gets the location of ':' symbol. + SourceLocation getColonLoc() const { return ColonLoc; } + + // Iterators + child_range children() { + int Offset = getModifier() ? 1 : 0; + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end() + Offset)); + } + + const_child_range children() const { + auto Children = const_cast<OMPAffinityClause *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_affinity; } }; @@ -6372,21 +7538,26 @@ public: template<class ImplClass, template <typename> class Ptr, typename RetTy> class OMPClauseVisitorBase { public: -#define PTR(CLASS) typename Ptr<CLASS>::type +#define PTR(CLASS) Ptr<CLASS> #define DISPATCH(CLASS) \ return static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<PTR(CLASS)>(S)) -#define OPENMP_CLAUSE(Name, Class) \ +#define OMP_CLAUSE_CLASS(Enum, Str, Class) \ RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); } -#include "clang/Basic/OpenMPKinds.def" +#include "llvm/Frontend/OpenMP/OMPKinds.def" RetTy Visit(PTR(OMPClause) S) { // Top switch clause: visit each OMPClause. switch (S->getClauseKind()) { - default: llvm_unreachable("Unknown clause kind!"); -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_ ## Name : return Visit ## Class(static_cast<PTR(Class)>(S)); -#include "clang/Basic/OpenMPKinds.def" +#define OMP_CLAUSE_CLASS(Enum, Str, Class) \ + case llvm::omp::Clause::Enum: \ + return Visit##Class(static_cast<PTR(Class)>(S)); +#define OMP_CLAUSE_NO_CLASS(Enum, Str) \ + case llvm::omp::Clause::Enum: \ + break; +#include "llvm/Frontend/OpenMP/OMPKinds.def" + default: + break; } } // Base case, ignore it. :) @@ -6395,12 +7566,11 @@ public: #undef DISPATCH }; -template <typename T> -using const_ptr = typename std::add_pointer<typename std::add_const<T>::type>; +template <typename T> using const_ptr = std::add_pointer_t<std::add_const_t<T>>; -template<class ImplClass, typename RetTy = void> -class OMPClauseVisitor : - public OMPClauseVisitorBase <ImplClass, std::add_pointer, RetTy> {}; +template <class ImplClass, typename RetTy = void> +class OMPClauseVisitor + : public OMPClauseVisitorBase<ImplClass, std::add_pointer_t, RetTy> {}; template<class ImplClass, typename RetTy = void> class ConstOMPClauseVisitor : public OMPClauseVisitorBase <ImplClass, const_ptr, RetTy> {}; @@ -6416,9 +7586,69 @@ public: OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy) : OS(OS), Policy(Policy) {} -#define OPENMP_CLAUSE(Name, Class) void Visit##Class(Class *S); -#include "clang/Basic/OpenMPKinds.def" +#define OMP_CLAUSE_CLASS(Enum, Str, Class) \ + void Visit##Class(Class *S); +#include "llvm/Frontend/OpenMP/OMPKinds.def" +}; + +struct OMPTraitProperty { + llvm::omp::TraitProperty Kind = llvm::omp::TraitProperty::invalid; +}; +struct OMPTraitSelector { + Expr *ScoreOrCondition = nullptr; + llvm::omp::TraitSelector Kind = llvm::omp::TraitSelector::invalid; + llvm::SmallVector<OMPTraitProperty, 1> Properties; +}; +struct OMPTraitSet { + llvm::omp::TraitSet Kind = llvm::omp::TraitSet::invalid; + llvm::SmallVector<OMPTraitSelector, 2> Selectors; +}; + +/// Helper data structure representing the traits in a match clause of an +/// `declare variant` or `metadirective`. The outer level is an ordered +/// collection of selector sets, each with an associated kind and an ordered +/// collection of selectors. A selector has a kind, an optional score/condition, +/// and an ordered collection of properties. +class OMPTraitInfo { + /// Private constructor accesible only by ASTContext. + OMPTraitInfo() {} + friend class ASTContext; + +public: + /// Reconstruct a (partial) OMPTraitInfo object from a mangled name. + OMPTraitInfo(StringRef MangledName); + + /// The outermost level of selector sets. + llvm::SmallVector<OMPTraitSet, 2> Sets; + + bool anyScoreOrCondition( + llvm::function_ref<bool(Expr *&, bool /* IsScore */)> Cond) { + return llvm::any_of(Sets, [&](OMPTraitSet &Set) { + return llvm::any_of( + Set.Selectors, [&](OMPTraitSelector &Selector) { + return Cond(Selector.ScoreOrCondition, + /* IsScore */ Selector.Kind != + llvm::omp::TraitSelector::user_condition); + }); + }); + } + + /// Create a variant match info object from this trait info object. While the + /// former is a flat representation the actual main difference is that the + /// latter uses clang::Expr to store the score/condition while the former is + /// independent of clang. Thus, expressions and conditions are evaluated in + /// this method. + void getAsVariantMatchInfo(ASTContext &ASTCtx, + llvm::omp::VariantMatchInfo &VMI) const; + + /// Return a string representation identifying this context selector. + std::string getMangledName() const; + + /// Print a human readable representation into \p OS. + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI); +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI); } // namespace clang diff --git a/clang/include/clang/AST/ParentMapContext.h b/clang/include/clang/AST/ParentMapContext.h new file mode 100644 index 000000000000..be4d75df7b99 --- /dev/null +++ b/clang/include/clang/AST/ParentMapContext.h @@ -0,0 +1,144 @@ +//===- ParentMapContext.h - Map of parents using DynTypedNode -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Similar to ParentMap.h, but generalizes to non-Stmt nodes, which can have +// multiple parents. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_PARENTMAPCONTEXT_H +#define LLVM_CLANG_AST_PARENTMAPCONTEXT_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" + +namespace clang { +class DynTypedNodeList; + +class ParentMapContext { +public: + ParentMapContext(ASTContext &Ctx); + + ~ParentMapContext(); + + /// Returns the parents of the given node (within the traversal scope). + /// + /// Note that this will lazily compute the parents of all nodes + /// and store them for later retrieval. Thus, the first call is O(n) + /// in the number of AST nodes. + /// + /// Caveats and FIXMEs: + /// Calculating the parent map over all AST nodes will need to load the + /// full AST. This can be undesirable in the case where the full AST is + /// expensive to create (for example, when using precompiled header + /// preambles). Thus, there are good opportunities for optimization here. + /// One idea is to walk the given node downwards, looking for references + /// to declaration contexts - once a declaration context is found, compute + /// the parent map for the declaration context; if that can satisfy the + /// request, loading the whole AST can be avoided. Note that this is made + /// more complex by statements in templates having multiple parents - those + /// problems can be solved by building closure over the templated parts of + /// the AST, which also avoids touching large parts of the AST. + /// Additionally, we will want to add an interface to already give a hint + /// where to search for the parents, for example when looking at a statement + /// inside a certain function. + /// + /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, + /// NestedNameSpecifier or NestedNameSpecifierLoc. + template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node); + + DynTypedNodeList getParents(const DynTypedNode &Node); + + /// Clear parent maps. + void clear(); + + TraversalKind getTraversalKind() const { return Traversal; } + void setTraversalKind(TraversalKind TK) { Traversal = TK; } + + const Expr *traverseIgnored(const Expr *E) const; + Expr *traverseIgnored(Expr *E) const; + DynTypedNode traverseIgnored(const DynTypedNode &N) const; + +private: + ASTContext &ASTCtx; + class ParentMap; + TraversalKind Traversal = TK_AsIs; + std::unique_ptr<ParentMap> Parents; +}; + +class TraversalKindScope { + ParentMapContext &Ctx; + TraversalKind TK = TK_AsIs; + +public: + TraversalKindScope(ASTContext &ASTCtx, llvm::Optional<TraversalKind> ScopeTK) + : Ctx(ASTCtx.getParentMapContext()) { + TK = Ctx.getTraversalKind(); + if (ScopeTK) + Ctx.setTraversalKind(*ScopeTK); + } + + ~TraversalKindScope() { Ctx.setTraversalKind(TK); } +}; + +/// Container for either a single DynTypedNode or for an ArrayRef to +/// DynTypedNode. For use with ParentMap. +class DynTypedNodeList { + llvm::AlignedCharArrayUnion<DynTypedNode, ArrayRef<DynTypedNode>> Storage; + bool IsSingleNode; + +public: + DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { + new (Storage.buffer) DynTypedNode(N); + } + + DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) { + new (Storage.buffer) ArrayRef<DynTypedNode>(A); + } + + const DynTypedNode *begin() const { + if (!IsSingleNode) + return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) + ->begin(); + return reinterpret_cast<const DynTypedNode *>(Storage.buffer); + } + + const DynTypedNode *end() const { + if (!IsSingleNode) + return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer) + ->end(); + return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1; + } + + size_t size() const { return end() - begin(); } + bool empty() const { return begin() == end(); } + + const DynTypedNode &operator[](size_t N) const { + assert(N < size() && "Out of bounds!"); + return *(begin() + N); + } +}; + +template <typename NodeT> +inline DynTypedNodeList ParentMapContext::getParents(const NodeT &Node) { + return getParents(DynTypedNode::create(Node)); +} + +template <typename NodeT> +inline DynTypedNodeList ASTContext::getParents(const NodeT &Node) { + return getParentMapContext().getParents(Node); +} + +template <> +inline DynTypedNodeList ASTContext::getParents(const DynTypedNode &Node) { + return getParentMapContext().getParents(Node); +} + +} // namespace clang + +#endif diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index 80eec6a5a8be..616647f44430 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -36,7 +36,9 @@ protected: public: /// Remap a path to a form suitable for printing. - virtual std::string remapPath(StringRef Path) const { return Path; } + virtual std::string remapPath(StringRef Path) const { + return std::string(Path); + } }; /// Describes how types, statements, expressions, and declarations should be @@ -55,12 +57,13 @@ struct PrintingPolicy { SuppressLifetimeQualifiers(false), SuppressTemplateArgsInCXXConstructors(false), Bool(LO.Bool), Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), - UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false), + UseVoidForZeroParams(!LO.CPlusPlus), + SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), - PrintCanonicalTypes(false) {} + PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true) {} /// Adjust this printing policy for cases where it's known that we're /// printing C++ code (for instance, if AST dumping reaches a C++-only @@ -181,6 +184,10 @@ struct PrintingPolicy { /// with zero parameters. unsigned UseVoidForZeroParams : 1; + /// Whether nested templates must be closed like 'a\<b\<c\> \>' rather than + /// 'a\<b\<c\>\>'. + unsigned SplitTemplateClosers : 1; + /// Provide a 'terse' output. /// /// For example, in this mode we don't print function bodies, class members, @@ -237,6 +244,11 @@ struct PrintingPolicy { /// Whether to print types as written or canonically. unsigned PrintCanonicalTypes : 1; + /// Whether to print an InjectedClassNameType with template arguments or as + /// written. When a template argument is unnamed, printing it results in + /// invalid C++ code. + unsigned PrintInjectedClassNameWithArguments : 1; + /// Callbacks to use to allow the behavior of printing to be customized. const PrintingCallbacks *Callbacks = nullptr; }; diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 9aacdb9fee36..ba0f237a3bc3 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -99,6 +99,8 @@ def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; } SubclassPropertyType<"TagDecl", DeclRef>; def TemplateDeclRef : SubclassPropertyType<"TemplateDecl", DeclRef>; + def ConceptDeclRef : + SubclassPropertyType<"ConceptDecl", DeclRef>; def TemplateTypeParmDeclRef : SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>; def TemplateTemplateParmDeclRef : diff --git a/clang/include/clang/AST/RawCommentList.h b/clang/include/clang/AST/RawCommentList.h index 1eea56dee622..a18432c2b768 100644 --- a/clang/include/clang/AST/RawCommentList.h +++ b/clang/include/clang/AST/RawCommentList.h @@ -11,9 +11,9 @@ #include "clang/Basic/CommentOptions.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" #include <map> namespace clang { @@ -21,7 +21,9 @@ namespace clang { class ASTContext; class ASTReader; class Decl; +class DiagnosticsEngine; class Preprocessor; +class SourceManager; namespace comments { class FullComment; @@ -173,23 +175,6 @@ private: friend class ASTReader; }; -/// Compare comments' source locations. -template<> -class BeforeThanCompare<RawComment> { - const SourceManager &SM; - -public: - explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { } - - bool operator()(const RawComment &LHS, const RawComment &RHS) { - return SM.isBeforeInTranslationUnit(LHS.getBeginLoc(), RHS.getBeginLoc()); - } - - bool operator()(const RawComment *LHS, const RawComment *RHS) { - return operator()(*LHS, *RHS); - } -}; - /// This class represents all comments included in the translation unit, /// sorted in order of appearance in the translation unit. class RawCommentList { diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index f8ab8e451d8c..3dcfc9fee629 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -23,6 +23,7 @@ #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" @@ -47,29 +48,6 @@ #include <cstddef> #include <type_traits> -// The following three macros are used for meta programming. The code -// using them is responsible for defining macro OPERATOR(). - -// All unary operators. -#define UNARYOP_LIST() \ - OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \ - OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \ - OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \ - OPERATOR(Extension) OPERATOR(Coawait) - -// All binary operators (excluding compound assign operators). -#define BINOP_LIST() \ - OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \ - OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \ - OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \ - OPERATOR(NE) OPERATOR(Cmp) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \ - OPERATOR(LAnd) OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) - -// All compound assign operators. -#define CAO_LIST() \ - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ - OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) - namespace clang { // A helper macro to implement short-circuiting when recursing. It @@ -82,6 +60,42 @@ namespace clang { return false; \ } while (false) +namespace detail { + +template <typename T, typename U> +struct has_same_member_pointer_type : std::false_type {}; +template <typename T, typename U, typename R, typename... P> +struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> + : std::true_type {}; + +template <bool has_same_type> struct is_same_method_impl { + template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> + static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr, + SecondMethodPtrTy SecondMethodPtr) { + return false; + } +}; + +template <> struct is_same_method_impl<true> { + template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> + static bool isSameMethod(FirstMethodPtrTy FirstMethodPtr, + SecondMethodPtrTy SecondMethodPtr) { + return FirstMethodPtr == SecondMethodPtr; + } +}; + +/// Returns true if and only if \p FirstMethodPtr and \p SecondMethodPtr +/// are pointers to the same non-static member function. +template <typename FirstMethodPtrTy, typename SecondMethodPtrTy> +bool isSameMethod(FirstMethodPtrTy FirstMethodPtr, + SecondMethodPtrTy SecondMethodPtr) { + return is_same_method_impl<has_same_member_pointer_type< + FirstMethodPtrTy, + SecondMethodPtrTy>::value>::isSameMethod(FirstMethodPtr, SecondMethodPtr); +} + +} // end namespace detail + /// A class that does preorder or postorder /// depth-first traversal on the entire Clang AST and visits each node. /// @@ -324,26 +338,20 @@ public: Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); } private: - template<typename T, typename U> - struct has_same_member_pointer_type : std::false_type {}; - template<typename T, typename U, typename R, typename... P> - struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)> - : std::true_type {}; - // Traverse the given statement. If the most-derived traverse function takes a // data recursion queue, pass it on; otherwise, discard it. Note that the // first branch of this conditional must compile whether or not the derived // class can take a queue, so if we're taking the second arm, make the first // arm call our function rather than the derived class version. #define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \ - (has_same_member_pointer_type<decltype( \ - &RecursiveASTVisitor::Traverse##NAME), \ - decltype(&Derived::Traverse##NAME)>::value \ - ? static_cast<typename std::conditional< \ - has_same_member_pointer_type< \ + (::clang::detail::has_same_member_pointer_type< \ + decltype(&RecursiveASTVisitor::Traverse##NAME), \ + decltype(&Derived::Traverse##NAME)>::value \ + ? static_cast<std::conditional_t< \ + ::clang::detail::has_same_member_pointer_type< \ decltype(&RecursiveASTVisitor::Traverse##NAME), \ decltype(&Derived::Traverse##NAME)>::value, \ - Derived &, RecursiveASTVisitor &>::type>(*this) \ + Derived &, RecursiveASTVisitor &>>(*this) \ .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \ : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))) @@ -376,60 +384,6 @@ public: bool Visit##CLASS(CLASS *S) { return true; } #include "clang/AST/StmtNodes.inc" -// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary -// operator methods. Unary operators are not classes in themselves -// (they're all opcodes in UnaryOperator) but do have visitors. -#define OPERATOR(NAME) \ - bool TraverseUnary##NAME(UnaryOperator *S, \ - DataRecursionQueue *Queue = nullptr) { \ - if (!getDerived().shouldTraversePostOrder()) \ - TRY_TO(WalkUpFromUnary##NAME(S)); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \ - return true; \ - } \ - bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ - TRY_TO(WalkUpFromUnaryOperator(S)); \ - TRY_TO(VisitUnary##NAME(S)); \ - return true; \ - } \ - bool VisitUnary##NAME(UnaryOperator *S) { return true; } - - UNARYOP_LIST() -#undef OPERATOR - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary -// operator methods. Binary operators are not classes in themselves -// (they're all opcodes in BinaryOperator) but do have visitors. -#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ - bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \ - if (!getDerived().shouldTraversePostOrder()) \ - TRY_TO(WalkUpFromBin##NAME(S)); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \ - return true; \ - } \ - bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ - TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ - TRY_TO(VisitBin##NAME(S)); \ - return true; \ - } \ - bool VisitBin##NAME(BINOP_TYPE *S) { return true; } - -#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) - BINOP_LIST() -#undef OPERATOR - -// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound -// assignment methods. Compound assignment operators are not -// classes in themselves (they're all opcodes in -// CompoundAssignOperator) but do have visitors. -#define OPERATOR(NAME) \ - GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) - - CAO_LIST() -#undef OPERATOR -#undef GENERAL_BINOP_FALLBACK - // ---- Methods on Types ---- // FIXME: revamp to take TypeLoc's rather than Types. @@ -533,8 +487,8 @@ private: 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" +#define OMP_CLAUSE_CLASS(Enum, Str, Class) bool Visit##Class(Class *C); +#include "llvm/Frontend/OpenMP/OMPKinds.def" /// Process clauses with list of variables. template <typename T> bool VisitOMPClauseList(T *Node); /// Process clauses with pre-initis. @@ -548,42 +502,6 @@ private: template <typename Derived> bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) { -#define DISPATCH_STMT(NAME, CLASS, VAR) \ - return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue); - - // If we have a binary expr, dispatch to the subcode of the binop. A smart - // optimizer (e.g. LLVM) will fold this comparison into the switch stmt - // below. - if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { - switch (BinOp->getOpcode()) { -#define OPERATOR(NAME) \ - case BO_##NAME: \ - DISPATCH_STMT(Bin##NAME, BinaryOperator, S); - - BINOP_LIST() -#undef OPERATOR -#undef BINOP_LIST - -#define OPERATOR(NAME) \ - case BO_##NAME##Assign: \ - DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S); - - CAO_LIST() -#undef OPERATOR -#undef CAO_LIST - } - } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { - switch (UnOp->getOpcode()) { -#define OPERATOR(NAME) \ - case UO_##NAME: \ - DISPATCH_STMT(Unary##NAME, UnaryOperator, S); - - UNARYOP_LIST() -#undef OPERATOR -#undef UNARYOP_LIST - } - } - // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. switch (S->getStmtClass()) { case Stmt::NoStmtClass: @@ -591,7 +509,7 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, #define ABSTRACT_STMT(STMT) #define STMT(CLASS, PARENT) \ case Stmt::CLASS##Class: \ - DISPATCH_STMT(CLASS, CLASS, S); + return TRAVERSE_STMT_BASE(CLASS, CLASS, S, Queue); #include "clang/AST/StmtNodes.inc" } @@ -602,23 +520,44 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, template <typename Derived> bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) { + // In pre-order traversal mode, each Traverse##STMT method is responsible for + // calling WalkUpFrom. Therefore, if the user overrides Traverse##STMT and + // does not call the default implementation, the WalkUpFrom callback is not + // called. Post-order traversal mode should provide the same behavior + // regarding method overrides. + // + // In post-order traversal mode the Traverse##STMT method, when it receives a + // DataRecursionQueue, can't call WalkUpFrom after traversing children because + // it only enqueues the children and does not traverse them. TraverseStmt + // traverses the enqueued children, and we call WalkUpFrom here. + // + // However, to make pre-order and post-order modes identical with regards to + // whether they call WalkUpFrom at all, we call WalkUpFrom if and only if the + // user did not override the Traverse##STMT method. We implement the override + // check with isSameMethod calls below. + switch (S->getStmtClass()) { case Stmt::NoStmtClass: break; #define ABSTRACT_STMT(STMT) #define STMT(CLASS, PARENT) \ case Stmt::CLASS##Class: \ - TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break; + if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \ + &Derived::Traverse##CLASS)) { \ + TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); \ + } \ + break; #define INITLISTEXPR(CLASS, PARENT) \ case Stmt::CLASS##Class: \ - { \ + if (::clang::detail::isSameMethod(&RecursiveASTVisitor::Traverse##CLASS, \ + &Derived::Traverse##CLASS)) { \ auto ILE = static_cast<CLASS *>(S); \ if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \ TRY_TO(WalkUpFrom##CLASS(Syn)); \ if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \ TRY_TO(WalkUpFrom##CLASS(Sem)); \ - break; \ - } + } \ + break; #include "clang/AST/StmtNodes.inc" } @@ -668,9 +607,6 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S, return true; } -#define DISPATCH(NAME, CLASS, VAR) \ - return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)) - template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { if (T.isNull()) @@ -680,7 +616,8 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { #define ABSTRACT_TYPE(CLASS, BASE) #define TYPE(CLASS, BASE) \ case Type::CLASS: \ - DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr())); + return getDerived().Traverse##CLASS##Type( \ + static_cast<CLASS##Type *>(const_cast<Type *>(T.getTypePtr()))); #include "clang/AST/TypeNodes.inc" } @@ -730,8 +667,6 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { return true; } -#undef DISPATCH - template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( NestedNameSpecifier *NNS) { @@ -1005,6 +940,17 @@ DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); }) DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); }) +DEF_TRAVERSE_TYPE(ConstantMatrixType, + { TRY_TO(TraverseType(T->getElementType())); }) + +DEF_TRAVERSE_TYPE(DependentSizedMatrixType, { + if (T->getRowExpr()) + TRY_TO(TraverseStmt(T->getRowExpr())); + if (T->getColumnExpr()) + TRY_TO(TraverseStmt(T->getColumnExpr())); + TRY_TO(TraverseType(T->getElementType())); +}) + DEF_TRAVERSE_TYPE(FunctionNoProtoType, { TRY_TO(TraverseType(T->getReturnType())); }) @@ -1039,7 +985,13 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, { TRY_TO(TraverseType(T->getUnderlyingType())); }) -DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); }) +DEF_TRAVERSE_TYPE(AutoType, { + TRY_TO(TraverseType(T->getDeducedType())); + if (T->isConstrained()) { + TRY_TO(TraverseDecl(T->getTypeConstraintConcept())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); + } +}) DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, { TRY_TO(TraverseTemplateName(T->getTemplateName())); TRY_TO(TraverseType(T->getDeducedType())); @@ -1108,6 +1060,10 @@ DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); }) DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); }) +DEF_TRAVERSE_TYPE(ExtIntType, {}) +DEF_TRAVERSE_TYPE(DependentExtIntType, + { TRY_TO(TraverseStmt(T->getNumBitsExpr())); }) + #undef DEF_TRAVERSE_TYPE // ----------------- TypeLoc traversal ----------------- @@ -1120,10 +1076,17 @@ DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); }) #define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ template <typename Derived> \ bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ - if (getDerived().shouldWalkTypesOfTypeLocs()) \ - TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ - TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ + if (!getDerived().shouldTraversePostOrder()) { \ + TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ + if (getDerived().shouldWalkTypesOfTypeLocs()) \ + TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ + } \ { CODE; } \ + if (getDerived().shouldTraversePostOrder()) { \ + TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ + if (getDerived().shouldWalkTypesOfTypeLocs()) \ + TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \ + } \ return true; \ } @@ -1192,22 +1155,22 @@ bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { DEF_TRAVERSE_TYPELOC(ConstantArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); + TRY_TO(TraverseArrayTypeLocHelper(TL)); }) DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); + TRY_TO(TraverseArrayTypeLocHelper(TL)); }) DEF_TRAVERSE_TYPELOC(VariableArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); + TRY_TO(TraverseArrayTypeLocHelper(TL)); }) DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); - return TraverseArrayTypeLocHelper(TL); + TRY_TO(TraverseArrayTypeLocHelper(TL)); }) DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, { @@ -1240,6 +1203,18 @@ DEF_TRAVERSE_TYPELOC(ExtVectorType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); }) +DEF_TRAVERSE_TYPELOC(ConstantMatrixType, { + TRY_TO(TraverseStmt(TL.getAttrRowOperand())); + TRY_TO(TraverseStmt(TL.getAttrColumnOperand())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + +DEF_TRAVERSE_TYPELOC(DependentSizedMatrixType, { + TRY_TO(TraverseStmt(TL.getAttrRowOperand())); + TRY_TO(TraverseStmt(TL.getAttrColumnOperand())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); }) @@ -1286,6 +1261,12 @@ DEF_TRAVERSE_TYPELOC(UnaryTransformType, { DEF_TRAVERSE_TYPELOC(AutoType, { TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); + if (TL.isConstrained()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(TL.getConceptNameInfo())); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + } }) DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, { @@ -1365,6 +1346,11 @@ DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) +DEF_TRAVERSE_TYPELOC(ExtIntType, {}) +DEF_TRAVERSE_TYPELOC(DependentExtIntType, { + TRY_TO(TraverseStmt(TL.getTypePtr()->getNumBitsExpr())); +}) + #undef DEF_TRAVERSE_TYPELOC // ----------------- Decl traversal ----------------- @@ -1973,6 +1959,8 @@ DEF_TRAVERSE_DECL(BindingDecl, { DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) +DEF_TRAVERSE_DECL(MSGuidDecl, {}) + DEF_TRAVERSE_DECL(FieldDecl, { TRY_TO(TraverseDeclaratorHelper(D)); if (D->isBitField()) @@ -2049,11 +2037,11 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { } } - bool VisitBody = D->isThisDeclarationADefinition(); - // If a method is set to default outside the class definition the compiler - // generates the method body and adds it to the AST. - if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) - VisitBody &= !MD->isDefaulted() || getDerived().shouldVisitImplicitCode(); + bool VisitBody = + D->isThisDeclarationADefinition() && + // Don't visit the function body if the function definition is generated + // by clang. + (!D->isDefaulted() || getDerived().shouldVisitImplicitCode()); if (VisitBody) { TRY_TO(TraverseStmt(D->getBody())); // Function body. @@ -2138,6 +2126,8 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { TRY_TO(TraverseStmt(D->getDefaultArg())); }) +DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {}) + #undef DEF_TRAVERSE_DECL // ----------------- Stmt traversal ----------------- @@ -2164,8 +2154,13 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \ } \ } \ - if (!Queue && ReturnValue && getDerived().shouldTraversePostOrder()) \ + /* Call WalkUpFrom if TRY_TO_TRAVERSE_OR_ENQUEUE_STMT has traversed the \ + * children already. If TRY_TO_TRAVERSE_OR_ENQUEUE_STMT only enqueued the \ + * children, PostVisitStmt will call WalkUpFrom after we are done visiting \ + * children. */ \ + if (!Queue && ReturnValue && getDerived().shouldTraversePostOrder()) { \ TRY_TO(WalkUpFrom##STMT(S)); \ + } \ return ReturnValue; \ } @@ -2299,6 +2294,10 @@ DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(CXXAddrspaceCastExpr, { + TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); +}) + DEF_TRAVERSE_STMT(CXXConstCastExpr, { TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) @@ -2332,6 +2331,9 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr( for (Stmt *SubStmt : S->children()) { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); } + + if (!Queue && getDerived().shouldTraversePostOrder()) + TRY_TO(WalkUpFromInitListExpr(S)); } return true; } @@ -2528,7 +2530,10 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {}) // over the children. DEF_TRAVERSE_STMT(AddrLabelExpr, {}) DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) +DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {}) DEF_TRAVERSE_STMT(OMPArraySectionExpr, {}) +DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {}) +DEF_TRAVERSE_STMT(OMPIteratorExpr, {}) DEF_TRAVERSE_STMT(BlockExpr, { TRY_TO(TraverseDecl(S->getBlockDecl())); @@ -2646,6 +2651,7 @@ DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, { }) DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) DEF_TRAVERSE_STMT(TypoExpr, {}) +DEF_TRAVERSE_STMT(RecoveryExpr, {}) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) // These operators (all of them) do not need any action except @@ -2709,6 +2715,28 @@ DEF_TRAVERSE_STMT(ConceptSpecializationExpr, { TRY_TO(TraverseConceptReference(*S)); }) +DEF_TRAVERSE_STMT(RequiresExpr, { + TRY_TO(TraverseDecl(S->getBody())); + for (ParmVarDecl *Parm : S->getLocalParameters()) + TRY_TO(TraverseDecl(Parm)); + for (concepts::Requirement *Req : S->getRequirements()) + if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req)) { + if (!TypeReq->isSubstitutionFailure()) + TRY_TO(TraverseTypeLoc(TypeReq->getType()->getTypeLoc())); + } else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req)) { + if (!ExprReq->isExprSubstitutionFailure()) + TRY_TO(TraverseStmt(ExprReq->getExpr())); + auto &RetReq = ExprReq->getReturnTypeRequirement(); + if (RetReq.isTypeConstraint()) + TRY_TO(TraverseTemplateParameterListHelper( + RetReq.getTypeConstraintTemplateParameterList())); + } else { + auto *NestedReq = cast<concepts::NestedRequirement>(Req); + if (!NestedReq->isSubstitutionFailure()) + TRY_TO(TraverseStmt(NestedReq->getConstraintExpr())); + } +}) + // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, {}) DEF_TRAVERSE_STMT(FixedPointLiteral, {}) @@ -2805,6 +2833,12 @@ DEF_TRAVERSE_STMT(OMPCancelDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPDepobjDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPScanDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPOrderedDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2904,16 +2938,15 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { if (!C) return true; switch (C->getClauseKind()) { -#define OPENMP_CLAUSE(Name, Class) \ - case OMPC_##Name: \ +#define OMP_CLAUSE_CLASS(Enum, Str, Class) \ + case llvm::omp::Clause::Enum: \ TRY_TO(Visit##Class(static_cast<Class *>(C))); \ break; -#include "clang/Basic/OpenMPKinds.def" - case OMPC_threadprivate: - case OMPC_uniform: - case OMPC_device_type: - case OMPC_match: - case OMPC_unknown: +#define OMP_CLAUSE_NO_CLASS(Enum, Str) \ + case llvm::omp::Clause::Enum: \ + break; +#include "llvm/Frontend/OpenMP/OMPKinds.def" + default: break; } return true; @@ -3085,6 +3118,26 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPAcqRelClause(OMPAcqRelClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPReleaseClause(OMPReleaseClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPRelaxedClause(OMPRelaxedClause *) { + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) { return true; } @@ -3100,6 +3153,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDestroyClause(OMPDestroyClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -3109,6 +3167,20 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPInclusiveClause( + OMPInclusiveClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPExclusiveClause( + OMPExclusiveClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); for (auto *E : C->private_copies()) { @@ -3235,6 +3307,17 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) { for (auto *E : C->reduction_ops()) { TRY_TO(TraverseStmt(E)); } + if (C->getModifier() == OMPC_REDUCTION_inscan) { + for (auto *E : C->copy_ops()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->copy_array_temps()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->copy_array_elems()) { + TRY_TO(TraverseStmt(E)); + } + } return true; } @@ -3291,6 +3374,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDepobjClause(OMPDepobjClause *C) { + TRY_TO(TraverseStmt(C->getDepobj())); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) { TRY_TO(VisitOMPClauseList(C)); return true; @@ -3389,6 +3478,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPUseDevicePtrClause( } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUseDeviceAddrClause( + OMPUseDeviceAddrClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPIsDevicePtrClause( OMPIsDevicePtrClause *C) { TRY_TO(VisitOMPClauseList(C)); @@ -3405,6 +3501,37 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNontemporalClause( return true; } +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPOrderClause(OMPOrderClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDetachClause(OMPDetachClause *C) { + TRY_TO(TraverseStmt(C->getEventHandler())); + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUsesAllocatorsClause( + OMPUsesAllocatorsClause *C) { + for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { + const OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I); + TRY_TO(TraverseStmt(Data.Allocator)); + TRY_TO(TraverseStmt(Data.AllocatorTraits)); + } + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPAffinityClause( + OMPAffinityClause *C) { + TRY_TO(TraverseStmt(C->getModifier())); + for (Expr *E : C->varlists()) + TRY_TO(TraverseStmt(E)); + 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/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index eaacb1a5b252..d3fad58fcf59 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -14,12 +14,14 @@ #define LLVM_CLANG_AST_STMT_H #include "clang/AST/DeclGroup.h" +#include "clang/AST/DependenceFlags.h" #include "clang/AST/StmtIterator.h" #include "clang/Basic/CapturedStmt.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" @@ -98,14 +100,8 @@ protected: /// The statement class. unsigned sClass : 8; - - /// This bit is set only for the Stmts that are the structured-block of - /// OpenMP executable directives. Directives that have a structured block - /// are called "non-standalone" directives. - /// I.e. those returned by OMPExecutableDirective::getStructuredBlock(). - unsigned IsOMPStructuredBlock : 1; }; - enum { NumStmtBits = 9 }; + enum { NumStmtBits = 8 }; class NullStmtBitfields { friend class ASTStmtReader; @@ -315,12 +311,9 @@ protected: unsigned ValueKind : 2; unsigned ObjectKind : 3; - unsigned TypeDependent : 1; - unsigned ValueDependent : 1; - unsigned InstantiationDependent : 1; - unsigned ContainsUnexpandedParameterPack : 1; + unsigned /*ExprDependence*/ Dependent : llvm::BitWidth<ExprDependence>; }; - enum { NumExprBits = NumStmtBits + 9 }; + enum { NumExprBits = NumStmtBits + 5 + llvm::BitWidth<ExprDependence> }; class ConstantExprBitfields { friend class ASTStmtReader; @@ -329,24 +322,27 @@ protected: unsigned : NumExprBits; - /// The kind of result that is trail-allocated. + /// The kind of result that is tail-allocated. unsigned ResultKind : 2; - /// Kind of Result as defined by APValue::Kind + /// The kind of Result as defined by APValue::Kind. unsigned APValueKind : 4; - /// When ResultKind == RSK_Int64. whether the trail-allocated integer is - /// signed. + /// When ResultKind == RSK_Int64, true if the tail-allocated integer is + /// unsigned. unsigned IsUnsigned : 1; - /// When ResultKind == RSK_Int64. the BitWidth of the trail-allocated - /// integer. 7 bits because it is the minimal number of bit to represent a - /// value from 0 to 64 (the size of the trail-allocated number). + /// When ResultKind == RSK_Int64. the BitWidth of the tail-allocated + /// integer. 7 bits because it is the minimal number of bits to represent a + /// value from 0 to 64 (the size of the tail-allocated integer). unsigned BitWidth : 7; - /// When ResultKind == RSK_APValue. Wether the ASTContext will cleanup the - /// destructor on the trail-allocated APValue. + /// When ResultKind == RSK_APValue, true if the ASTContext will cleanup the + /// tail-allocated APValue. unsigned HasCleanup : 1; + + /// True if this ConstantExpr was created for immediate invocation. + unsigned IsImmediateInvocation : 1; }; class PredefinedExprBitfields { @@ -431,6 +427,11 @@ protected: unsigned Opc : 5; unsigned CanOverflow : 1; + // + /// This is only meaningful for operations on floating point + /// types when additional values need to be in trailing storage. + /// It is 0 otherwise. + unsigned HasFPFeatures : 1; SourceLocation Loc; }; @@ -444,8 +445,9 @@ protected: unsigned IsType : 1; // true if operand is a type, false if an expression. }; - class ArraySubscriptExprBitfields { + class ArrayOrMatrixSubscriptExprBitfields { friend class ArraySubscriptExpr; + friend class MatrixSubscriptExpr; unsigned : NumExprBits; @@ -529,8 +531,9 @@ protected: unsigned Opc : 6; /// This is only meaningful for operations on floating point - /// types and 0 otherwise. - unsigned FPFeatures : 3; + /// types when additional values need to be in trailing storage. + /// It is 0 otherwise. + unsigned HasFPFeatures : 1; SourceLocation OpLoc; }; @@ -588,6 +591,18 @@ protected: unsigned Kind : 2; }; + class StmtExprBitfields { + friend class ASTStmtReader; + friend class StmtExpr; + + unsigned : NumExprBits; + + /// The number of levels of template parameters enclosing this statement + /// expression. Used to determine if a statement expression remains + /// dependent after instantiation. + unsigned TemplateDepth; + }; + //===--- C++ Expression bitfields classes ---===// class CXXOperatorCallExprBitfields { @@ -599,9 +614,6 @@ protected: /// The kind of this overloaded operator. One of the enumerator /// value of OverloadedOperatorKind. unsigned OperatorKind : 6; - - // Only meaningful for floating point types. - unsigned FPFeatures : 3; }; class CXXRewrittenBinaryOperatorBitfields { @@ -760,8 +772,10 @@ protected: /// the trait evaluated true or false. unsigned Value : 1; - /// The number of arguments to this type trait. - unsigned NumArgs : 32 - 8 - 1 - NumExprBits; + /// The number of arguments to this type trait. According to [implimits] + /// 8 bits would be enough, but we require (and test for) at least 16 bits + /// to mirror FunctionType. + unsigned NumArgs; }; class DependentScopeDeclRefExprBitfields { @@ -910,6 +924,39 @@ protected: SourceLocation NameLoc; }; + class LambdaExprBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class LambdaExpr; + + unsigned : NumExprBits; + + /// The default capture kind, which is a value of type + /// LambdaCaptureDefault. + unsigned CaptureDefault : 2; + + /// Whether this lambda had an explicit parameter list vs. an + /// implicit (and empty) parameter list. + unsigned ExplicitParams : 1; + + /// Whether this lambda had the result type explicitly specified. + unsigned ExplicitResultType : 1; + + /// The number of captures. + unsigned NumCaptures : 16; + }; + + class RequiresExprBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class RequiresExpr; + + unsigned : NumExprBits; + + unsigned IsSatisfied : 1; + SourceLocation RequiresKWLoc; + }; + //===--- C++ Coroutines TS bitfields classes ---===// class CoawaitExprBitfields { @@ -974,7 +1021,7 @@ protected: CharacterLiteralBitfields CharacterLiteralBits; UnaryOperatorBitfields UnaryOperatorBits; UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits; - ArraySubscriptExprBitfields ArraySubscriptExprBits; + ArrayOrMatrixSubscriptExprBitfields ArrayOrMatrixSubscriptExprBits; CallExprBitfields CallExprBits; MemberExprBitfields MemberExprBits; CastExprBitfields CastExprBits; @@ -985,6 +1032,9 @@ protected: PseudoObjectExprBitfields PseudoObjectExprBits; SourceLocExprBitfields SourceLocExprBits; + // GNU Extensions. + StmtExprBitfields StmtExprBits; + // C++ Expressions CXXOperatorCallExprBitfields CXXOperatorCallExprBits; CXXRewrittenBinaryOperatorBitfields CXXRewrittenBinaryOperatorBits; @@ -1008,6 +1058,8 @@ protected: UnresolvedMemberExprBitfields UnresolvedMemberExprBits; CXXNoexceptExprBitfields CXXNoexceptExprBits; SubstNonTypeTemplateParmExprBitfields SubstNonTypeTemplateParmExprBits; + LambdaExprBitfields LambdaExprBits; + RequiresExprBitfields RequiresExprBits; // C++ Coroutines TS expressions CoawaitExprBitfields CoawaitBits; @@ -1090,7 +1142,6 @@ public: static_assert(sizeof(*this) % alignof(void *) == 0, "Insufficient alignment!"); StmtBits.sClass = SC; - StmtBits.IsOMPStructuredBlock = false; if (StatisticsEnabled) Stmt::addStmtClass(SC); } @@ -1100,11 +1151,6 @@ public: const char *getStmtClassName() const; - bool isOMPStructuredBlock() const { return StmtBits.IsOMPStructuredBlock; } - void setIsOMPStructuredBlock(bool IsOMPStructuredBlock) { - StmtBits.IsOMPStructuredBlock = IsOMPStructuredBlock; - } - /// SourceLocation tokens are not useful in isolation - they are low level /// value objects created/interpreted by SourceManager. We assume AST /// clients will have a pointer to the respective SourceManager. @@ -1120,9 +1166,7 @@ public: /// Dumps the specified AST fragment and all subtrees to /// \c llvm::errs(). void dump() const; - void dump(SourceManager &SM) const; - void dump(raw_ostream &OS, SourceManager &SM) const; - void dump(raw_ostream &OS) const; + void dump(raw_ostream &OS, const ASTContext &Context) const; /// \return Unique reproducible object identifier int64_t getID(const ASTContext &Context) const; @@ -2233,6 +2277,8 @@ class WhileStmt final : public Stmt, enum { VarOffset = 0, BodyOffsetFromCond = 1 }; enum { NumMandatoryStmtPtr = 2 }; + SourceLocation LParenLoc, RParenLoc; + unsigned varOffset() const { return VarOffset; } unsigned condOffset() const { return VarOffset + hasVarStorage(); } unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; } @@ -2243,7 +2289,8 @@ class WhileStmt final : public Stmt, /// Build a while statement. WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, Stmt *Body, - SourceLocation WL); + SourceLocation WL, SourceLocation LParenLoc, + SourceLocation RParenLoc); /// Build an empty while statement. explicit WhileStmt(EmptyShell Empty, bool HasVar); @@ -2251,7 +2298,8 @@ class WhileStmt final : public Stmt, public: /// Create a while statement. static WhileStmt *Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, - Stmt *Body, SourceLocation WL); + Stmt *Body, SourceLocation WL, + SourceLocation LParenLoc, SourceLocation RParenLoc); /// Create an empty while statement optionally with storage for /// a condition variable. @@ -2315,6 +2363,11 @@ public: SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; } void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; } + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + SourceLocation getBeginLoc() const { return getWhileLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { return getBody()->getEndLoc(); @@ -3017,7 +3070,7 @@ public: } IdentifierInfo *getLabelIdentifier(unsigned i) const { - return Names[i + NumInputs]; + return Names[i + NumOutputs + NumInputs]; } AddrLabelExpr *getLabelExpr(unsigned i) const; @@ -3028,11 +3081,11 @@ public: using labels_const_range = llvm::iterator_range<const_labels_iterator>; labels_iterator begin_labels() { - return &Exprs[0] + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } labels_iterator end_labels() { - return &Exprs[0] + NumInputs + NumLabels; + return &Exprs[0] + NumOutputs + NumInputs + NumLabels; } labels_range labels() { @@ -3040,11 +3093,11 @@ public: } const_labels_iterator begin_labels() const { - return &Exprs[0] + NumInputs; + return &Exprs[0] + NumOutputs + NumInputs; } const_labels_iterator end_labels() const { - return &Exprs[0] + NumInputs + NumLabels; + return &Exprs[0] + NumOutputs + NumInputs + NumLabels; } labels_const_range labels() const { diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index 65f0afece224..bd87eafc9034 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -356,6 +356,9 @@ public: /// class OMPParallelDirective : public OMPExecutableDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if the construct has inner cancel directive. bool HasCancel; @@ -381,6 +384,9 @@ class OMPParallelDirective : public OMPExecutableDirective { SourceLocation(), NumClauses, 1), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -392,11 +398,14 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement associated with the directive. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if this directive has inner cancel directive. /// static OMPParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place for \a N clauses. /// @@ -406,6 +415,10 @@ public: static OMPParallelDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -1258,7 +1271,9 @@ public: /// class OMPForDirective : public OMPLoopDirective { friend class ASTStmtReader; - + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if current directive has inner cancel directive. bool HasCancel; @@ -1286,6 +1301,9 @@ class OMPForDirective : public OMPLoopDirective { NumClauses), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -1299,13 +1317,15 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if current directive has inner cancel directive. /// static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, - bool HasCancel); + Expr *TaskRedRef, bool HasCancel); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -1317,6 +1337,10 @@ public: static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -1403,6 +1427,9 @@ public: class OMPSectionsDirective : public OMPExecutableDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if current directive has inner cancel directive. bool HasCancel; @@ -1429,6 +1456,9 @@ class OMPSectionsDirective : public OMPExecutableDirective { SourceLocation(), NumClauses, 1), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -1440,11 +1470,14 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if current directive has inner directive. /// static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place for \a NumClauses /// clauses. @@ -1455,6 +1488,10 @@ public: static OMPSectionsDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -1715,6 +1752,9 @@ public: class OMPParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if current region has inner cancel directive. bool HasCancel; @@ -1743,6 +1783,9 @@ class OMPParallelForDirective : public OMPLoopDirective { SourceLocation(), CollapsedNum, NumClauses), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -1756,12 +1799,15 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if current directive has inner cancel directive. /// static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -1775,6 +1821,10 @@ public: unsigned CollapsedNum, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -1863,6 +1913,10 @@ public: class OMPParallelMasterDirective : public OMPExecutableDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; + OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned NumClauses) : OMPExecutableDirective(this, OMPParallelMasterDirectiveClass, @@ -1875,6 +1929,9 @@ class OMPParallelMasterDirective : public OMPExecutableDirective { SourceLocation(), SourceLocation(), NumClauses, 1) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + public: /// Creates directive with a list of \a Clauses. /// @@ -1883,10 +1940,12 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// static OMPParallelMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef); /// Creates an empty directive with the place for \a NumClauses /// clauses. @@ -1897,6 +1956,10 @@ public: static OMPParallelMasterDirective * CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelMasterDirectiveClass; } @@ -1914,6 +1977,9 @@ public: class OMPParallelSectionsDirective : public OMPExecutableDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if current directive has inner cancel directive. bool HasCancel; @@ -1941,6 +2007,9 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective { 1), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -1952,11 +2021,14 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if current directive has inner cancel directive. /// static OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place for \a NumClauses /// clauses. @@ -1967,6 +2039,10 @@ public: static OMPParallelSectionsDirective * CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -2314,6 +2390,64 @@ public: } }; +/// This represents '#pragma omp depobj' directive. +/// +/// \code +/// #pragma omp depobj(a) depend(in:x,y) +/// \endcode +/// In this example directive '#pragma omp depobj' initializes a depobj object +/// 'a' with dependence type 'in' and a list with 'x' and 'y' locators. +class OMPDepobjDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + + /// 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. + /// + OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPDepobjDirectiveClass, + llvm::omp::OMPD_depobj, StartLoc, EndLoc, + NumClauses, 0) {} + + /// Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPDepobjDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPDepobjDirectiveClass, + llvm::omp::OMPD_depobj, SourceLocation(), + SourceLocation(), NumClauses, 0) {} + +public: + /// 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. + /// + static OMPDepobjDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses); + + /// Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPDepobjDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPDepobjDirectiveClass; + } +}; + /// This represents '#pragma omp ordered' directive. /// /// \code @@ -2747,6 +2881,12 @@ public: /// class OMPTargetParallelDirective : public OMPExecutableDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; + /// true if the construct has inner cancel directive. + bool HasCancel = false; + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -2769,6 +2909,11 @@ class OMPTargetParallelDirective : public OMPExecutableDirective { SourceLocation(), SourceLocation(), NumClauses, /*NumChildren=*/1) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } + public: /// Creates directive with a list of \a Clauses. /// @@ -2777,10 +2922,14 @@ public: /// \param EndLoc Ending Location of the directive. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, - ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place for \a NumClauses /// clauses. @@ -2791,6 +2940,13 @@ public: static OMPTargetParallelDirective * CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPTargetParallelDirectiveClass; } @@ -2808,6 +2964,9 @@ public: class OMPTargetParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if current region has inner cancel directive. bool HasCancel; @@ -2837,6 +2996,9 @@ class OMPTargetParallelForDirective : public OMPLoopDirective { SourceLocation(), CollapsedNum, NumClauses), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -2850,12 +3012,15 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if current directive has inner cancel directive. /// static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -2869,6 +3034,10 @@ public: unsigned CollapsedNum, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -3070,6 +3239,9 @@ public: /// class OMPTaskLoopDirective : public OMPLoopDirective { friend class ASTStmtReader; + /// true if the construct has inner cancel directive. + bool HasCancel; + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -3081,7 +3253,8 @@ class OMPTaskLoopDirective : public OMPLoopDirective { unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop, StartLoc, EndLoc, - CollapsedNum, NumClauses) {} + CollapsedNum, NumClauses), + HasCancel(false) {} /// Build an empty directive. /// @@ -3091,7 +3264,11 @@ class OMPTaskLoopDirective : public OMPLoopDirective { explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses) {} + SourceLocation(), CollapsedNum, NumClauses), + HasCancel(false) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// Creates directive with a list of \a Clauses. @@ -3103,11 +3280,12 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -3120,6 +3298,9 @@ public: unsigned NumClauses, unsigned CollapsedNum, EmptyShell); + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPTaskLoopDirectiveClass; } @@ -3203,6 +3384,9 @@ public: /// class OMPMasterTaskLoopDirective : public OMPLoopDirective { friend class ASTStmtReader; + /// true if the construct has inner cancel directive. + bool HasCancel; + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -3214,7 +3398,8 @@ class OMPMasterTaskLoopDirective : public OMPLoopDirective { unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass, llvm::omp::OMPD_master_taskloop, StartLoc, EndLoc, - CollapsedNum, NumClauses) {} + CollapsedNum, NumClauses), + HasCancel(false) {} /// Build an empty directive. /// @@ -3225,7 +3410,11 @@ class OMPMasterTaskLoopDirective : public OMPLoopDirective { unsigned NumClauses) : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass, llvm::omp::OMPD_master_taskloop, SourceLocation(), - SourceLocation(), CollapsedNum, NumClauses) {} + SourceLocation(), CollapsedNum, NumClauses), + HasCancel(false) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// Creates directive with a list of \a Clauses. @@ -3237,11 +3426,12 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -3255,6 +3445,9 @@ public: unsigned CollapsedNum, EmptyShell); + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass; } @@ -3339,6 +3532,9 @@ public: /// class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective { friend class ASTStmtReader; + /// true if the construct has inner cancel directive. + bool HasCancel; + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -3351,7 +3547,8 @@ class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective { unsigned CollapsedNum, unsigned NumClauses) : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass, llvm::omp::OMPD_parallel_master_taskloop, StartLoc, - EndLoc, CollapsedNum, NumClauses) {} + EndLoc, CollapsedNum, NumClauses), + HasCancel(false) {} /// Build an empty directive. /// @@ -3363,7 +3560,11 @@ class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective { : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass, llvm::omp::OMPD_parallel_master_taskloop, SourceLocation(), SourceLocation(), CollapsedNum, - NumClauses) {} + NumClauses), + HasCancel(false) {} + + /// Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } public: /// Creates directive with a list of \a Clauses. @@ -3375,11 +3576,12 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if this directive has inner cancel directive. /// static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs); + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -3393,6 +3595,9 @@ public: unsigned CollapsedNum, EmptyShell); + /// Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass; } @@ -3605,6 +3810,9 @@ public: /// class OMPDistributeParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if the construct has inner cancel directive. bool HasCancel = false; @@ -3636,6 +3844,9 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective { NumClauses), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -3649,12 +3860,15 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if this directive has inner cancel directive. /// static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place /// for \a NumClauses clauses. @@ -3668,6 +3882,10 @@ public: unsigned CollapsedNum, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -4170,6 +4388,9 @@ public: /// class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if the construct has inner cancel directive. bool HasCancel = false; @@ -4202,6 +4423,9 @@ class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective { NumClauses), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -4215,12 +4439,15 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if this directive has inner cancel directive. /// static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place for \a NumClauses clauses. /// @@ -4232,6 +4459,10 @@ public: CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -4379,6 +4610,9 @@ public: class OMPTargetTeamsDistributeParallelForDirective final : public OMPLoopDirective { friend class ASTStmtReader; + /// Special reference expression for handling task reduction. Used to store + /// the taskgroup descriptor returned by the runtime functions. + Expr *TaskRedRef = nullptr; /// true if the construct has inner cancel directive. bool HasCancel = false; @@ -4412,6 +4646,9 @@ class OMPTargetTeamsDistributeParallelForDirective final SourceLocation(), SourceLocation(), CollapsedNum, NumClauses), HasCancel(false) {} + /// Sets special task reduction descriptor. + void setTaskReductionRefExpr(Expr *E) { TaskRedRef = E; } + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } @@ -4425,12 +4662,15 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. + /// \param TaskRedRef Task reduction special reference expression to handle + /// taskgroup descriptor. /// \param HasCancel true if this directive has inner cancel directive. /// static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, + bool HasCancel); /// Creates an empty directive with the place for \a NumClauses clauses. /// @@ -4442,6 +4682,10 @@ public: CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); + /// Returns special task reduction reference expression. + Expr *getTaskReductionRefExpr() { return TaskRedRef; } + const Expr *getTaskReductionRefExpr() const { return TaskRedRef; } + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } @@ -4594,6 +4838,63 @@ public: } }; +/// This represents '#pragma omp scan' directive. +/// +/// \code +/// #pragma omp scan inclusive(a) +/// \endcode +/// In this example directive '#pragma omp scan' has clause 'inclusive' with +/// list item 'a'. +class OMPScanDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + /// 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. + /// + OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPScanDirectiveClass, + llvm::omp::OMPD_scan, StartLoc, EndLoc, + NumClauses, 0) {} + + /// Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPScanDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPScanDirectiveClass, + llvm::omp::OMPD_scan, SourceLocation(), + SourceLocation(), NumClauses, 0) {} + +public: + /// 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 OMPScanDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses); + + /// Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPScanDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPScanDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/clang/include/clang/AST/StmtVisitor.h b/clang/include/clang/AST/StmtVisitor.h index d3be93d228cc..3e5155199eac 100644 --- a/clang/include/clang/AST/StmtVisitor.h +++ b/clang/include/clang/AST/StmtVisitor.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_STMTVISITOR_H #define LLVM_CLANG_AST_STMTVISITOR_H +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index 058a5bc0a067..51fd8ba51034 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H #define LLVM_CLANG_AST_TEMPLATEBASE_H +#include "clang/AST/DependenceFlags.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -81,8 +82,7 @@ public: /// The template argument is an expression, and we've not resolved it to one /// of the other forms yet, either because it's dependent or because we're /// representing a non-canonical template argument (for instance, in a - /// TemplateSpecializationType). Also used to represent a non-dependent - /// __uuidof expression (a Microsoft extension). + /// TemplateSpecializationType). Expression, /// The template argument is actually a parameter pack. Arguments are stored @@ -236,6 +236,8 @@ public: /// Determine whether this template argument has no value. bool isNull() const { return getKind() == Null; } + TemplateArgumentDependence getDependence() const; + /// Whether this template argument is dependent on a template /// parameter such that its result can change from one instantiation to /// another. @@ -637,7 +639,7 @@ public: } static const ASTTemplateArgumentListInfo * - Create(ASTContext &C, const TemplateArgumentListInfo &List); + Create(const ASTContext &C, const TemplateArgumentListInfo &List); }; /// Represents an explicit template argument list in C++, e.g., @@ -666,11 +668,13 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo { void initializeFrom(SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &List, TemplateArgumentLoc *OutArgArray); + // FIXME: The parameter Deps is the result populated by this method, the + // caller doesn't need it since it is populated by computeDependence. remove + // it. void initializeFrom(SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &List, - TemplateArgumentLoc *OutArgArray, bool &Dependent, - bool &InstantiationDependent, - bool &ContainsUnexpandedParameterPack); + TemplateArgumentLoc *OutArgArray, + TemplateArgumentDependence &Deps); void initializeFrom(SourceLocation TemplateKWLoc); void copyInto(const TemplateArgumentLoc *ArgArray, @@ -702,6 +706,11 @@ inline const TemplateArgument & return getArgs()[Idx]; } +inline const TemplateArgument &AutoType::getArg(unsigned Idx) const { + assert(Idx < getNumArgs() && "Template argument out of range"); + return getArgs()[Idx]; +} + } // namespace clang #endif // LLVM_CLANG_AST_TEMPLATEBASE_H diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h index cbbcbf6af8ab..9bcf2838dcf1 100644 --- a/clang/include/clang/AST/TemplateName.h +++ b/clang/include/clang/AST/TemplateName.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_TEMPLATENAME_H #define LLVM_CLANG_AST_TEMPLATENAME_H +#include "clang/AST/DependenceFlags.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" @@ -295,6 +296,8 @@ public: /// the template, including any default template arguments. TemplateName getNameToSubstitute() const; + TemplateNameDependence getDependence() const; + /// Determines whether this is a dependent template name. bool isDependent() const; @@ -559,7 +562,7 @@ struct PointerLikeTypeTraits<clang::TemplateName> { } // No bits are available! - enum { NumLowBitsAvailable = 0 }; + static constexpr int NumLowBitsAvailable = 0; }; } // namespace llvm. diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index d293ea190aa4..b4cfb5a380d1 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -22,10 +22,13 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TemplateArgumentVisitor.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeVisitor.h" namespace clang { +class APValue; + class TextTreeStructure { raw_ostream &OS; const bool ShowColors; @@ -68,7 +71,7 @@ public: // We need to capture an owning-string in the lambda because the lambda // is invoked in a deferred manner. - std::string LabelStr = Label; + std::string LabelStr(Label); auto DumpWithIndent = [this, DoAddChild, LabelStr](bool IsLastChild) { // Print out the appropriate tree structure and work out the prefix for // children of this node. For instance: @@ -139,19 +142,29 @@ class TextNodeDumper const char *LastLocFilename = ""; unsigned LastLocLine = ~0U; - const SourceManager *SM; + /// \p Context, \p SM, and \p Traits can be null. This is because we want + /// to be able to call \p dump() in a debugger without having to pass the + /// \p ASTContext to \p dump. Not all parts of the AST dump output will be + /// available without the \p ASTContext. + const ASTContext *Context = nullptr; + const SourceManager *SM = nullptr; /// The policy to use for printing; can be defaulted. - PrintingPolicy PrintPolicy; + PrintingPolicy PrintPolicy = LangOptions(); - const comments::CommandTraits *Traits; + const comments::CommandTraits *Traits = nullptr; const char *getCommandName(unsigned CommandID); + void dumpAPValueChildren(const APValue &Value, QualType Ty, + const APValue &(*IdxToChildFun)(const APValue &, + unsigned), + unsigned NumChildren, StringRef LabelSingular, + StringRef LabelPlurial); + public: - TextNodeDumper(raw_ostream &OS, bool ShowColors, const SourceManager *SM, - const PrintingPolicy &PrintPolicy, - const comments::CommandTraits *Traits); + TextNodeDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors); + TextNodeDumper(raw_ostream &OS, bool ShowColors); void Visit(const comments::Comment *C, const comments::FullComment *FC); @@ -176,6 +189,8 @@ public: void Visit(const GenericSelectionExpr::ConstAssociation &A); + void Visit(const APValue &Value, QualType Ty); + void dumpPointer(const void *Ptr); void dumpLocation(SourceLocation Loc); void dumpSourceRange(SourceRange R); @@ -184,6 +199,7 @@ public: void dumpBareDeclRef(const Decl *D); void dumpName(const NamedDecl *ND); void dumpAccessSpecifier(AccessSpecifier AS); + void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C); void dumpDeclRef(const Decl *D, StringRef Label = {}); @@ -230,6 +246,7 @@ public: void VisitCaseStmt(const CaseStmt *Node); void VisitConstantExpr(const ConstantExpr *Node); void VisitCallExpr(const CallExpr *Node); + void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node); void VisitCastExpr(const CastExpr *Node); void VisitImplicitCastExpr(const ImplicitCastExpr *Node); void VisitDeclRefExpr(const DeclRefExpr *Node); @@ -257,6 +274,9 @@ public: void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); void VisitCXXNewExpr(const CXXNewExpr *Node); void VisitCXXDeleteExpr(const CXXDeleteExpr *Node); + void VisitTypeTraitExpr(const TypeTraitExpr *Node); + void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node); + void VisitExpressionTraitExpr(const ExpressionTraitExpr *Node); void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node); void VisitExprWithCleanups(const ExprWithCleanups *Node); void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); @@ -273,6 +293,7 @@ public: void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node); void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node); void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node); + void VisitOMPIteratorExpr(const OMPIteratorExpr *Node); void VisitRValueReferenceType(const ReferenceType *T); void VisitArrayType(const ArrayType *T); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index f5955c45fafc..0fc50e0e799f 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -17,6 +17,7 @@ #ifndef LLVM_CLANG_AST_TYPE_H #define LLVM_CLANG_AST_TYPE_H +#include "clang/AST/DependenceFlags.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "clang/Basic/AddressSpaces.h" @@ -44,8 +45,8 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/PointerLikeTypeTraits.h" -#include "llvm/Support/type_traits.h" #include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/type_traits.h" #include <cassert> #include <cstddef> #include <cstdint> @@ -58,6 +59,7 @@ namespace clang { class ExtQuals; class QualType; +class ConceptDecl; class TagDecl; class Type; @@ -85,7 +87,7 @@ namespace llvm { return static_cast< ::clang::Type*>(P); } - enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; + static constexpr int NumLowBitsAvailable = clang::TypeAlignmentInBits; }; template<> @@ -96,7 +98,7 @@ namespace llvm { return static_cast< ::clang::ExtQuals*>(P); } - enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; + static constexpr int NumLowBitsAvailable = clang::TypeAlignmentInBits; }; } // namespace llvm @@ -942,6 +944,12 @@ public: /// from non-class types (in C++) or all types (in C). QualType getNonLValueExprType(const ASTContext &Context) const; + /// Remove an outer pack expansion type (if any) from this type. Used as part + /// of converting the type of a declaration to the type of an expression that + /// references that expression. It's meaningless for an expression to have a + /// pack expansion type. + QualType getNonPackExpansionType() const; + /// Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar @@ -1050,7 +1058,7 @@ public: void dump(const char *s) const; void dump() const; - void dump(llvm::raw_ostream &OS) const; + void dump(llvm::raw_ostream &OS, const ASTContext &Context) const; void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(getAsOpaquePtr()); @@ -1062,6 +1070,21 @@ public: /// Return the address space of this type. inline LangAS getAddressSpace() const; + /// Returns true if address space qualifiers overlap with T address space + /// qualifiers. + /// OpenCL C defines conversion rules for pointers to different address spaces + /// and notion of overlapping address spaces. + /// CL1.1 or CL1.2: + /// address spaces overlap iff they are they same. + /// OpenCL C v2.0 s6.5.5 adds: + /// __generic overlaps with any address space except for __constant. + bool isAddressSpaceOverlapping(QualType T) const { + Qualifiers Q = getQualifiers(); + Qualifiers TQ = T.getQualifiers(); + // Address spaces overlap if at least one of them is a superset of another + return Q.isAddressSpaceSupersetOf(TQ) || TQ.isAddressSpaceSupersetOf(Q); + } + /// Returns gc attribute of this type. inline Qualifiers::GC getObjCGCAttr() const; @@ -1295,7 +1318,7 @@ struct PointerLikeTypeTraits<clang::QualType> { } // Various qualifiers go in low bits. - enum { NumLowBitsAvailable = 0 }; + static constexpr int NumLowBitsAvailable = 0; }; } // namespace llvm @@ -1464,19 +1487,8 @@ private: /// TypeClass bitfield - Enum that specifies what subclass this belongs to. unsigned TC : 8; - /// Whether this type is a dependent type (C++ [temp.dep.type]). - unsigned Dependent : 1; - - /// Whether this type somehow involves a template parameter, even - /// if the resolution of the type does not depend on a template parameter. - unsigned InstantiationDependent : 1; - - /// Whether this type is a variably-modified type (C99 6.7.5). - unsigned VariablyModified : 1; - - /// Whether this type contains an unexpanded parameter pack - /// (for C++11 variadic templates). - unsigned ContainsUnexpandedParameterPack : 1; + /// Store information on the type dependency. + unsigned Dependence : llvm::BitWidth<TypeDependence>; /// True if the cache (i.e. the bitfields here starting with /// 'Cache') is valid. @@ -1505,7 +1517,7 @@ private: return CachedLocalOrUnnamed; } }; - enum { NumTypeBits = 18 }; + enum { NumTypeBits = 8 + llvm::BitWidth<TypeDependence> + 6 }; protected: // These classes allow subclasses to somewhat cleanly pack bitfields @@ -1555,7 +1567,7 @@ protected: /// Extra information which affects how the function is called, like /// regparm and the calling convention. - unsigned ExtInfo : 12; + unsigned ExtInfo : 13; /// The ref-qualifier associated with a \c FunctionProtoType. /// @@ -1659,11 +1671,21 @@ protected: /// The kind of vector, either a generic vector type or some /// target-specific vector type such as for AltiVec or Neon. unsigned VecKind : 3; - /// The number of elements in the vector. - unsigned NumElements : 29 - NumTypeBits; + uint32_t NumElements; + }; + + class ConstantMatrixTypeBitfields { + friend class ConstantMatrixType; + + unsigned : NumTypeBits; - enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 }; + /// Number of rows and columns. Using 20 bits allows supporting very large + /// matrixes, while keeping 24 bits to accommodate NumTypeBits. + unsigned NumRows : 20; + unsigned NumColumns : 20; + + static constexpr uint32_t MaxElementsPerDimension = (1 << 20) - 1; }; class AttributedTypeBitfields { @@ -1683,6 +1705,15 @@ protected: /// Was this placeholder type spelled as 'auto', 'decltype(auto)', /// or '__auto_type'? AutoTypeKeyword value. unsigned Keyword : 2; + + /// The number of template arguments in the type-constraints, which is + /// expected to be able to hold at least 1024 according to [implimits]. + /// However as this limit is somewhat easy to hit with template + /// metaprogramming we'd prefer to keep it as large as possible. + /// At the moment it has been left as a non-bitfield since this type + /// safely fits in 64 bits as an unsigned, so there is no reason to + /// introduce the performance impact of a bitfield. + unsigned NumArgs; }; class SubstTemplateTypeParmPackTypeBitfields { @@ -1766,6 +1797,7 @@ protected: TypeWithKeywordBitfields TypeWithKeywordBits; ElaboratedTypeBitfields ElaboratedTypeBits; VectorTypeBitfields VectorTypeBits; + ConstantMatrixTypeBitfields ConstantMatrixTypeBits; SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits; TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits; DependentTemplateSpecializationTypeBitfields @@ -1818,16 +1850,11 @@ private: protected: friend class ASTContext; - Type(TypeClass tc, QualType canon, bool Dependent, - bool InstantiationDependent, bool VariablyModified, - bool ContainsUnexpandedParameterPack) + Type(TypeClass tc, QualType canon, TypeDependence Dependence) : ExtQualsTypeCommonBase(this, canon.isNull() ? QualType(this_(), 0) : canon) { TypeBits.TC = tc; - TypeBits.Dependent = Dependent; - TypeBits.InstantiationDependent = Dependent || InstantiationDependent; - TypeBits.VariablyModified = VariablyModified; - TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; + TypeBits.Dependence = static_cast<unsigned>(Dependence); TypeBits.CacheValid = false; TypeBits.CachedLocalOrUnnamed = false; TypeBits.CachedLinkage = NoLinkage; @@ -1837,20 +1864,11 @@ protected: // silence VC++ warning C4355: 'this' : used in base member initializer list Type *this_() { return this; } - void setDependent(bool D = true) { - TypeBits.Dependent = D; - if (D) - TypeBits.InstantiationDependent = true; + void setDependence(TypeDependence D) { + TypeBits.Dependence = static_cast<unsigned>(D); } - void setInstantiationDependent(bool D = true) { - TypeBits.InstantiationDependent = D; } - - void setVariablyModified(bool VM = true) { TypeBits.VariablyModified = VM; } - - void setContainsUnexpandedParameterPack(bool PP = true) { - TypeBits.ContainsUnexpandedParameterPack = PP; - } + void addDependence(TypeDependence D) { setDependence(getDependence() | D); } public: friend class ASTReader; @@ -1884,7 +1902,7 @@ public: /// /// Note that this routine does not specify which bool containsUnexpandedParameterPack() const { - return TypeBits.ContainsUnexpandedParameterPack; + return getDependence() & TypeDependence::UnexpandedPack; } /// Determines if this type would be canonical if it had no further @@ -1898,6 +1916,15 @@ public: /// or QualType::getSingleStepDesugaredType(const ASTContext&). QualType getLocallyUnqualifiedSingleStepDesugaredType() const; + /// As an extension, we classify types as one of "sized" or "sizeless"; + /// every type is one or the other. Standard types are all sized; + /// sizeless types are purely an extension. + /// + /// Sizeless types contain data with no specified size, alignment, + /// or layout. + bool isSizelessType() const; + bool isSizelessBuiltinType() const; + /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. @@ -1987,6 +2014,7 @@ public: bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 + bool isBFloat16Type() const; bool isFloat128Type() const; bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) @@ -2029,6 +2057,8 @@ public: bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. + bool isMatrixType() const; // Matrix type. + bool isConstantMatrixType() const; // Constant matrix type. bool isDependentAddressSpaceType() const; // value-dependent address space qualifier bool isObjCObjectPointerType() const; // pointer to ObjC object bool isObjCRetainableType() const; // ObjC object or block pointer @@ -2109,6 +2139,7 @@ public: bool isOCLExtOpaqueType() const; // Any OpenCL extension type bool isPipeType() const; // OpenCL pipe type + bool isExtIntType() const; // Extended Int Type bool isOpenCLSpecificType() const; // Any OpenCL specific type /// Determines if this type, which must satisfy @@ -2116,6 +2147,11 @@ public: /// than implicitly __strong. bool isObjCARCImplicitlyUnretainedType() const; + /// Check if the type is the CUDA device builtin surface type. + bool isCUDADeviceBuiltinSurfaceType() const; + /// Check if the type is the CUDA device builtin texture type. + bool isCUDADeviceBuiltinTextureType() const; + /// Return the implicit lifetime for this type, which must not be dependent. Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const; @@ -2135,16 +2171,27 @@ public: /// Given that this is a scalar type, classify it. ScalarTypeKind getScalarTypeKind() const; + TypeDependence getDependence() const { + return static_cast<TypeDependence>(TypeBits.Dependence); + } + + /// Whether this type is an error type. + bool containsErrors() const { + return getDependence() & TypeDependence::Error; + } + /// Whether this type is a dependent type, meaning that its definition /// somehow depends on a template parameter (C++ [temp.dep.type]). - bool isDependentType() const { return TypeBits.Dependent; } + bool isDependentType() const { + return getDependence() & TypeDependence::Dependent; + } /// Determine whether this type is an instantiation-dependent type, /// meaning that the type involves a template parameter (even if the /// definition does not actually depend on the type substituted for that /// template parameter). bool isInstantiationDependentType() const { - return TypeBits.InstantiationDependent; + return getDependence() & TypeDependence::Instantiation; } /// Determine whether this type is an undeduced type, meaning that @@ -2153,7 +2200,9 @@ public: bool isUndeducedType() const; /// Whether this type is a variably-modified type (C99 6.7.5). - bool isVariablyModifiedType() const { return TypeBits.VariablyModified; } + bool isVariablyModifiedType() const { + return getDependence() & TypeDependence::VariablyModified; + } /// Whether this type involves a variable-length array type /// with a definite size. @@ -2422,7 +2471,7 @@ public: CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h void dump() const; - void dump(llvm::raw_ostream &OS) const; + void dump(llvm::raw_ostream &OS, const ASTContext &Context) const; }; /// This will check for a TypedefType by removing any existing sugar @@ -2474,10 +2523,9 @@ private: friend class ASTContext; // ASTContext creates these. BuiltinType(Kind K) - : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), - /*InstantiationDependent=*/(K == Dependent), - /*VariablyModified=*/false, - /*Unexpanded parameter pack=*/false) { + : Type(Builtin, QualType(), + K == Dependent ? TypeDependence::DependentInstantiation + : TypeDependence::None) { BuiltinTypeBits.Kind = K; } @@ -2547,10 +2595,7 @@ class ComplexType : public Type, public llvm::FoldingSetNode { QualType ElementType; ComplexType(QualType Element, QualType CanonicalPtr) - : Type(Complex, CanonicalPtr, Element->isDependentType(), - Element->isInstantiationDependentType(), - Element->isVariablyModifiedType(), - Element->containsUnexpandedParameterPack()), + : Type(Complex, CanonicalPtr, Element->getDependence()), ElementType(Element) {} public: @@ -2577,11 +2622,7 @@ class ParenType : public Type, public llvm::FoldingSetNode { QualType Inner; ParenType(QualType InnerType, QualType CanonType) - : Type(Paren, CanonType, InnerType->isDependentType(), - InnerType->isInstantiationDependentType(), - InnerType->isVariablyModifiedType(), - InnerType->containsUnexpandedParameterPack()), - Inner(InnerType) {} + : Type(Paren, CanonType, InnerType->getDependence()), Inner(InnerType) {} public: QualType getInnerType() const { return Inner; } @@ -2607,31 +2648,12 @@ class PointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; PointerType(QualType Pointee, QualType CanonicalPtr) - : Type(Pointer, CanonicalPtr, Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), + : Type(Pointer, CanonicalPtr, Pointee->getDependence()), PointeeType(Pointee) {} public: QualType getPointeeType() const { return PointeeType; } - /// Returns true if address spaces of pointers overlap. - /// OpenCL v2.0 defines conversion rules for pointers to different - /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping - /// address spaces. - /// CL1.1 or CL1.2: - /// address spaces overlap iff they are they same. - /// CL2.0 adds: - /// __generic overlaps with any address space except for __constant. - bool isAddressSpaceOverlapping(const PointerType &other) const { - Qualifiers thisQuals = PointeeType.getQualifiers(); - Qualifiers otherQuals = other.getPointeeType().getQualifiers(); - // Address spaces overlap if at least one of them is a superset of another - return thisQuals.isAddressSpaceSupersetOf(otherQuals) || - otherQuals.isAddressSpaceSupersetOf(thisQuals); - } - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2658,10 +2680,7 @@ protected: AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy, QualType CanonicalPtr) - : Type(TC, CanonicalPtr, OriginalTy->isDependentType(), - OriginalTy->isInstantiationDependentType(), - OriginalTy->isVariablyModifiedType(), - OriginalTy->containsUnexpandedParameterPack()), + : Type(TC, CanonicalPtr, OriginalTy->getDependence()), OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {} public: @@ -2710,10 +2729,7 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; BlockPointerType(QualType Pointee, QualType CanonicalCls) - : Type(BlockPointer, CanonicalCls, Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), + : Type(BlockPointer, CanonicalCls, Pointee->getDependence()), PointeeType(Pointee) {} public: @@ -2743,10 +2759,7 @@ class ReferenceType : public Type, public llvm::FoldingSetNode { protected: ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, bool SpelledAsLValue) - : Type(tc, CanonicalRef, Referencee->isDependentType(), - Referencee->isInstantiationDependentType(), - Referencee->isVariablyModifiedType(), - Referencee->containsUnexpandedParameterPack()), + : Type(tc, CanonicalRef, Referencee->getDependence()), PointeeType(Referencee) { ReferenceTypeBits.SpelledAsLValue = SpelledAsLValue; ReferenceTypeBits.InnerRef = Referencee->isReferenceType(); @@ -2831,13 +2844,9 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) : Type(MemberPointer, CanonicalPtr, - Cls->isDependentType() || Pointee->isDependentType(), - (Cls->isInstantiationDependentType() || - Pointee->isInstantiationDependentType()), - Pointee->isVariablyModifiedType(), - (Cls->containsUnexpandedParameterPack() || - Pointee->containsUnexpandedParameterPack())), - PointeeType(Pointee), Class(Cls) {} + (Cls->getDependence() & ~TypeDependence::VariablyModified) | + Pointee->getDependence()), + PointeeType(Pointee), Class(Cls) {} public: QualType getPointeeType() const { return PointeeType; } @@ -3260,10 +3269,6 @@ public: QualType getElementType() const { return ElementType; } unsigned getNumElements() const { return VectorTypeBits.NumElements; } - static bool isVectorSizeTooLarge(unsigned NumElements) { - return NumElements > VectorTypeBitfields::MaxNumElements; - } - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -3407,6 +3412,136 @@ public: } }; +/// Represents a matrix type, as defined in the Matrix Types clang extensions. +/// __attribute__((matrix_type(rows, columns))), where "rows" specifies +/// number of rows and "columns" specifies the number of columns. +class MatrixType : public Type, public llvm::FoldingSetNode { +protected: + friend class ASTContext; + + /// The element type of the matrix. + QualType ElementType; + + MatrixType(QualType ElementTy, QualType CanonElementTy); + + MatrixType(TypeClass TypeClass, QualType ElementTy, QualType CanonElementTy, + const Expr *RowExpr = nullptr, const Expr *ColumnExpr = nullptr); + +public: + /// Returns type of the elements being stored in the matrix + QualType getElementType() const { return ElementType; } + + /// Valid elements types are the following: + /// * an integer type (as in C2x 6.2.5p19), but excluding enumerated types + /// and _Bool + /// * the standard floating types float or double + /// * a half-precision floating point type, if one is supported on the target + static bool isValidElementType(QualType T) { + return T->isDependentType() || + (T->isRealType() && !T->isBooleanType() && !T->isEnumeralType()); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantMatrix || + T->getTypeClass() == DependentSizedMatrix; + } +}; + +/// Represents a concrete matrix type with constant number of rows and columns +class ConstantMatrixType final : public MatrixType { +protected: + friend class ASTContext; + + /// The element type of the matrix. + QualType ElementType; + + ConstantMatrixType(QualType MatrixElementType, unsigned NRows, + unsigned NColumns, QualType CanonElementType); + + ConstantMatrixType(TypeClass typeClass, QualType MatrixType, unsigned NRows, + unsigned NColumns, QualType CanonElementType); + +public: + /// Returns the number of rows in the matrix. + unsigned getNumRows() const { return ConstantMatrixTypeBits.NumRows; } + + /// Returns the number of columns in the matrix. + unsigned getNumColumns() const { return ConstantMatrixTypeBits.NumColumns; } + + /// Returns the number of elements required to embed the matrix into a vector. + unsigned getNumElementsFlattened() const { + return ConstantMatrixTypeBits.NumRows * ConstantMatrixTypeBits.NumColumns; + } + + /// Returns true if \p NumElements is a valid matrix dimension. + static bool isDimensionValid(uint64_t NumElements) { + return NumElements > 0 && + NumElements <= ConstantMatrixTypeBitfields::MaxElementsPerDimension; + } + + /// Returns the maximum number of elements per dimension. + static unsigned getMaxElementsPerDimension() { + return ConstantMatrixTypeBitfields::MaxElementsPerDimension; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getElementType(), getNumRows(), getNumColumns(), + getTypeClass()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, + unsigned NumRows, unsigned NumColumns, + TypeClass TypeClass) { + ID.AddPointer(ElementType.getAsOpaquePtr()); + ID.AddInteger(NumRows); + ID.AddInteger(NumColumns); + ID.AddInteger(TypeClass); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == ConstantMatrix; + } +}; + +/// Represents a matrix type where the type and the number of rows and columns +/// is dependent on a template. +class DependentSizedMatrixType final : public MatrixType { + friend class ASTContext; + + const ASTContext &Context; + Expr *RowExpr; + Expr *ColumnExpr; + + SourceLocation loc; + + DependentSizedMatrixType(const ASTContext &Context, QualType ElementType, + QualType CanonicalType, Expr *RowExpr, + Expr *ColumnExpr, SourceLocation loc); + +public: + QualType getElementType() const { return ElementType; } + Expr *getRowExpr() const { return RowExpr; } + Expr *getColumnExpr() const { return ColumnExpr; } + SourceLocation getAttributeLoc() const { return loc; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentSizedMatrix; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), getRowExpr(), getColumnExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType ElementType, Expr *RowExpr, Expr *ColumnExpr); +}; + /// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base /// class of FunctionNoProtoType and FunctionProtoType. class FunctionType : public Type { @@ -3523,39 +3658,41 @@ public: class ExtInfo { friend class FunctionType; - // Feel free to rearrange or add bits, but if you go over 12, - // you'll need to adjust both the Bits field below and - // Type::FunctionTypeBitfields. + // Feel free to rearrange or add bits, but if you go over 16, you'll need to + // adjust the Bits field below, and if you add bits, you'll need to adjust + // Type::FunctionTypeBitfields::ExtInfo as well. - // | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck| - // |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | + // | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck|cmsenscall| + // |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | 12 | // // regparm is either 0 (no regparm attribute) or the regparm value+1. enum { CallConvMask = 0x1F }; enum { NoReturnMask = 0x20 }; enum { ProducesResultMask = 0x40 }; enum { NoCallerSavedRegsMask = 0x80 }; - enum { NoCfCheckMask = 0x800 }; enum { - RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask | - NoCallerSavedRegsMask | NoCfCheckMask), + RegParmMask = 0x700, RegParmOffset = 8 - }; // Assumed to be the last field + }; + enum { NoCfCheckMask = 0x800 }; + enum { CmseNSCallMask = 0x1000 }; uint16_t Bits = CC_C; ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {} - public: - // Constructor with no defaults. Use this when you know that you - // have all the elements (when reading an AST file for example). - ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc, - bool producesResult, bool noCallerSavedRegs, bool NoCfCheck) { - assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); - Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) | - (producesResult ? ProducesResultMask : 0) | - (noCallerSavedRegs ? NoCallerSavedRegsMask : 0) | - (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) | - (NoCfCheck ? NoCfCheckMask : 0); + public: + // Constructor with no defaults. Use this when you know that you + // have all the elements (when reading an AST file for example). + ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc, + bool producesResult, bool noCallerSavedRegs, bool NoCfCheck, + bool cmseNSCall) { + assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); + Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) | + (producesResult ? ProducesResultMask : 0) | + (noCallerSavedRegs ? NoCallerSavedRegsMask : 0) | + (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) | + (NoCfCheck ? NoCfCheckMask : 0) | + (cmseNSCall ? CmseNSCallMask : 0); } // Constructor with all defaults. Use when for example creating a @@ -3568,9 +3705,10 @@ public: bool getNoReturn() const { return Bits & NoReturnMask; } bool getProducesResult() const { return Bits & ProducesResultMask; } + bool getCmseNSCall() const { return Bits & CmseNSCallMask; } bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; } bool getNoCfCheck() const { return Bits & NoCfCheckMask; } - bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } + bool getHasRegParm() const { return ((Bits & RegParmMask) >> RegParmOffset) != 0; } unsigned getRegParm() const { unsigned RegParm = (Bits & RegParmMask) >> RegParmOffset; @@ -3605,6 +3743,13 @@ public: return ExtInfo(Bits & ~ProducesResultMask); } + ExtInfo withCmseNSCall(bool cmseNSCall) const { + if (cmseNSCall) + return ExtInfo(Bits | CmseNSCallMask); + else + return ExtInfo(Bits & ~CmseNSCallMask); + } + ExtInfo withNoCallerSavedRegs(bool noCallerSavedRegs) const { if (noCallerSavedRegs) return ExtInfo(Bits | NoCallerSavedRegsMask); @@ -3651,14 +3796,9 @@ public: }; protected: - FunctionType(TypeClass tc, QualType res, - QualType Canonical, bool Dependent, - bool InstantiationDependent, - bool VariablyModified, bool ContainsUnexpandedParameterPack, - ExtInfo Info) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack), - ResultType(res) { + FunctionType(TypeClass tc, QualType res, QualType Canonical, + TypeDependence Dependence, ExtInfo Info) + : Type(tc, Canonical, Dependence), ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; } @@ -3677,6 +3817,7 @@ public: /// type. bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } + bool getCmseNSCallAttr() const { return getExtInfo().getCmseNSCall(); } CallingConv getCallConv() const { return getExtInfo().getCC(); } ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } @@ -3709,9 +3850,10 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) : FunctionType(FunctionNoProto, Result, Canonical, - /*Dependent=*/false, /*InstantiationDependent=*/false, - Result->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false, Info) {} + Result->getDependence() & + ~(TypeDependence::DependentInstantiation | + TypeDependence::UnexpandedPack), + Info) {} public: // No additional state past what FunctionType provides. @@ -4203,9 +4345,9 @@ class UnresolvedUsingType : public Type { UnresolvedUsingTypenameDecl *Decl; UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D) - : Type(UnresolvedUsing, QualType(), true, true, false, - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {} + : Type(UnresolvedUsing, QualType(), + TypeDependence::DependentInstantiation), + Decl(const_cast<UnresolvedUsingTypenameDecl *>(D)) {} public: UnresolvedUsingTypenameDecl *getDecl() const { return Decl; } @@ -4234,11 +4376,8 @@ protected: friend class ASTContext; // ASTContext creates these. TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) - : Type(tc, can, can->isDependentType(), - can->isInstantiationDependentType(), - can->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<TypedefNameDecl*>(D)) { + : Type(tc, can, can->getDependence() & ~TypeDependence::UnexpandedPack), + Decl(const_cast<TypedefNameDecl *>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } @@ -4261,10 +4400,7 @@ class MacroQualifiedType : public Type { MacroQualifiedType(QualType UnderlyingTy, QualType CanonTy, const IdentifierInfo *MacroII) - : Type(MacroQualified, CanonTy, UnderlyingTy->isDependentType(), - UnderlyingTy->isInstantiationDependentType(), - UnderlyingTy->isVariablyModifiedType(), - UnderlyingTy->containsUnexpandedParameterPack()), + : Type(MacroQualified, CanonTy, UnderlyingTy->getDependence()), UnderlyingTy(UnderlyingTy), MacroII(MacroII) { assert(isa<AttributedType>(UnderlyingTy) && "Expected a macro qualified type to only wrap attributed types."); @@ -4336,11 +4472,7 @@ class TypeOfType : public Type { QualType TOType; TypeOfType(QualType T, QualType can) - : Type(TypeOf, can, T->isDependentType(), - T->isInstantiationDependentType(), - T->isVariablyModifiedType(), - T->containsUnexpandedParameterPack()), - TOType(T) { + : Type(TypeOf, can, T->getDependence()), TOType(T) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } @@ -4549,10 +4681,7 @@ private: AttributedType(QualType canon, attr::Kind attrKind, QualType modified, QualType equivalent) - : Type(Attributed, canon, equivalent->isDependentType(), - equivalent->isInstantiationDependentType(), - equivalent->isVariablyModifiedType(), - equivalent->containsUnexpandedParameterPack()), + : Type(Attributed, canon, equivalent->getDependence()), ModifiedType(modified), EquivalentType(equivalent) { AttributedTypeBits.AttrKind = attrKind; } @@ -4654,18 +4783,16 @@ class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { /// Build a non-canonical type. TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) - : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - Canon->containsUnexpandedParameterPack()), + : Type(TemplateTypeParm, Canon, + TypeDependence::DependentInstantiation | + (Canon->getDependence() & TypeDependence::UnexpandedPack)), TTPDecl(TTPDecl) {} /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) : Type(TemplateTypeParm, QualType(this, 0), - /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, PP) { + TypeDependence::DependentInstantiation | + (PP ? TypeDependence::UnexpandedPack : TypeDependence::None)) { CanTTPTInfo.Depth = D; CanTTPTInfo.Index = I; CanTTPTInfo.ParameterPack = PP; @@ -4722,10 +4849,7 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { const TemplateTypeParmType *Replaced; SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) - : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(), - Canon->isInstantiationDependentType(), - Canon->isVariablyModifiedType(), - Canon->containsUnexpandedParameterPack()), + : Type(SubstTemplateTypeParm, Canon, Canon->getDependence()), Replaced(Param) {} public: @@ -4814,8 +4938,7 @@ public: /// Common base class for placeholders for types that get replaced by /// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced -/// class template types, and (eventually) constrained type names from the C++ -/// Concepts TS. +/// class template types, and constrained type names. /// /// These types are usually a placeholder for a deduced type. However, before /// the initializer is attached, or (usually) if the initializer is @@ -4823,23 +4946,16 @@ public: /// the latter case, it is also a dependent type. class DeducedType : public Type { protected: - DeducedType(TypeClass TC, QualType DeducedAsType, bool IsDependent, - bool IsInstantiationDependent, bool ContainsParameterPack) + DeducedType(TypeClass TC, QualType DeducedAsType, + TypeDependence ExtraDependence) : Type(TC, // FIXME: Retain the sugared deduced type? DeducedAsType.isNull() ? QualType(this, 0) : DeducedAsType.getCanonicalType(), - IsDependent, IsInstantiationDependent, - /*VariablyModified=*/false, ContainsParameterPack) { - if (!DeducedAsType.isNull()) { - if (DeducedAsType->isDependentType()) - setDependent(); - if (DeducedAsType->isInstantiationDependentType()) - setInstantiationDependent(); - if (DeducedAsType->containsUnexpandedParameterPack()) - setContainsUnexpandedParameterPack(); - } - } + ExtraDependence | (DeducedAsType.isNull() + ? TypeDependence::None + : DeducedAsType->getDependence() & + ~TypeDependence::VariablyModified)) {} public: bool isSugared() const { return !isCanonicalUnqualified(); } @@ -4860,18 +4976,50 @@ public: } }; -/// Represents a C++11 auto or C++14 decltype(auto) type. -class AutoType : public DeducedType, public llvm::FoldingSetNode { +/// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained +/// by a type-constraint. +class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these + ConceptDecl *TypeConstraintConcept; + AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword, - bool IsDeducedAsDependent, bool IsDeducedAsPack) - : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent, - IsDeducedAsDependent, IsDeducedAsPack) { - AutoTypeBits.Keyword = (unsigned)Keyword; + TypeDependence ExtraDependence, ConceptDecl *CD, + ArrayRef<TemplateArgument> TypeConstraintArgs); + + const TemplateArgument *getArgBuffer() const { + return reinterpret_cast<const TemplateArgument*>(this+1); + } + + TemplateArgument *getArgBuffer() { + return reinterpret_cast<TemplateArgument*>(this+1); } public: + /// Retrieve the template arguments. + const TemplateArgument *getArgs() const { + return getArgBuffer(); + } + + /// Retrieve the number of template arguments. + unsigned getNumArgs() const { + return AutoTypeBits.NumArgs; + } + + const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h + + ArrayRef<TemplateArgument> getTypeConstraintArguments() const { + return {getArgs(), getNumArgs()}; + } + + ConceptDecl *getTypeConstraintConcept() const { + return TypeConstraintConcept; + } + + bool isConstrained() const { + return TypeConstraintConcept != nullptr; + } + bool isDecltypeAuto() const { return getKeyword() == AutoTypeKeyword::DecltypeAuto; } @@ -4880,18 +5028,15 @@ public: return (AutoTypeKeyword)AutoTypeBits.Keyword; } - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDeducedType(), getKeyword(), isDependentType(), - containsUnexpandedParameterPack()); + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { + Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(), + getTypeConstraintConcept(), getTypeConstraintArguments()); } - static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced, - AutoTypeKeyword Keyword, bool IsDependent, bool IsPack) { - ID.AddPointer(Deduced.getAsOpaquePtr()); - ID.AddInteger((unsigned)Keyword); - ID.AddBoolean(IsDependent); - ID.AddBoolean(IsPack); - } + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType Deduced, AutoTypeKeyword Keyword, + bool IsDependent, ConceptDecl *CD, + ArrayRef<TemplateArgument> Arguments); static bool classof(const Type *T) { return T->getTypeClass() == Auto; @@ -4910,9 +5055,10 @@ class DeducedTemplateSpecializationType : public DeducedType, QualType DeducedAsType, bool IsDeducedAsDependent) : DeducedType(DeducedTemplateSpecialization, DeducedAsType, - IsDeducedAsDependent || Template.isDependent(), - IsDeducedAsDependent || Template.isInstantiationDependent(), - Template.containsUnexpandedParameterPack()), + toTypeDependence(Template.getDependence()) | + (IsDeducedAsDependent + ? TypeDependence::DependentInstantiation + : TypeDependence::None)), Template(Template) {} public: @@ -5114,10 +5260,8 @@ class InjectedClassNameType : public Type { QualType InjectedType; InjectedClassNameType(CXXRecordDecl *D, QualType TST) - : Type(InjectedClassName, QualType(), /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - /*ContainsUnexpandedParameterPack=*/false), + : Type(InjectedClassName, QualType(), + TypeDependence::DependentInstantiation), Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); assert(!TST.hasQualifiers()); @@ -5196,11 +5340,8 @@ enum ElaboratedTypeKeyword { class TypeWithKeyword : public Type { protected: TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc, - QualType Canonical, bool Dependent, - bool InstantiationDependent, bool VariablyModified, - bool ContainsUnexpandedParameterPack) - : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified, - ContainsUnexpandedParameterPack) { + QualType Canonical, TypeDependence Dependence) + : Type(tc, Canonical, Dependence) { TypeWithKeywordBits.Keyword = Keyword; } @@ -5264,10 +5405,7 @@ class ElaboratedType final ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl) : TypeWithKeyword(Keyword, Elaborated, CanonType, - NamedType->isDependentType(), - NamedType->isInstantiationDependentType(), - NamedType->isVariablyModifiedType(), - NamedType->containsUnexpandedParameterPack()), + NamedType->getDependence()), NNS(NNS), NamedType(NamedType) { ElaboratedTypeBits.HasOwnedTagDecl = false; if (OwnedTagDecl) { @@ -5338,10 +5476,9 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) - : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true, - /*InstantiationDependent=*/true, - /*VariablyModified=*/false, - NNS->containsUnexpandedParameterPack()), + : TypeWithKeyword(Keyword, DependentName, CanonType, + TypeDependence::DependentInstantiation | + toTypeDependence(NNS->getDependence())), NNS(NNS), Name(Name) {} public: @@ -5478,10 +5615,9 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { PackExpansionType(QualType Pattern, QualType Canon, Optional<unsigned> NumExpansions) - : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), - /*InstantiationDependent=*/true, - /*VariablyModified=*/Pattern->isVariablyModifiedType(), - /*ContainsUnexpandedParameterPack=*/false), + : Type(PackExpansion, Canon, + (Pattern->getDependence() | TypeDependence::Instantiation) & + ~TypeDependence::UnexpandedPack), Pattern(Pattern) { PackExpansionTypeBits.NumExpansions = NumExpansions ? *NumExpansions + 1 : 0; @@ -5620,6 +5756,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, const ObjCTypeParamDecl *OTPDecl, + QualType CanonicalType, ArrayRef<ObjCProtocolDecl *> protocols); ObjCTypeParamDecl *getDecl() const { return OTPDecl; } @@ -5700,8 +5837,8 @@ protected: bool isKindOf); ObjCObjectType(enum Nonce_ObjCInterface) - : Type(ObjCInterface, QualType(), false, false, false, false), - BaseType(QualType(this_(), 0)) { + : Type(ObjCInterface, QualType(), TypeDependence::None), + BaseType(QualType(this_(), 0)) { ObjCObjectTypeBits.NumProtocols = 0; ObjCObjectTypeBits.NumTypeArgs = 0; ObjCObjectTypeBits.IsKindOf = 0; @@ -5916,11 +6053,7 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { QualType PointeeType; ObjCObjectPointerType(QualType Canonical, QualType Pointee) - : Type(ObjCObjectPointer, Canonical, - Pointee->isDependentType(), - Pointee->isInstantiationDependentType(), - Pointee->isVariablyModifiedType(), - Pointee->containsUnexpandedParameterPack()), + : Type(ObjCObjectPointer, Canonical, Pointee->getDependence()), PointeeType(Pointee) {} public: @@ -6090,11 +6223,7 @@ class AtomicType : public Type, public llvm::FoldingSetNode { QualType ValueType; AtomicType(QualType ValTy, QualType Canonical) - : Type(Atomic, Canonical, ValTy->isDependentType(), - ValTy->isInstantiationDependentType(), - ValTy->isVariablyModifiedType(), - ValTy->containsUnexpandedParameterPack()), - ValueType(ValTy) {} + : Type(Atomic, Canonical, ValTy->getDependence()), ValueType(ValTy) {} public: /// Gets the type contained by this atomic type, i.e. @@ -6125,10 +6254,7 @@ class PipeType : public Type, public llvm::FoldingSetNode { bool isRead; PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) - : Type(Pipe, CanonicalPtr, elemType->isDependentType(), - elemType->isInstantiationDependentType(), - elemType->isVariablyModifiedType(), - elemType->containsUnexpandedParameterPack()), + : Type(Pipe, CanonicalPtr, elemType->getDependence()), ElementType(elemType), isRead(isRead) {} public: @@ -6154,6 +6280,64 @@ public: bool isReadOnly() const { return isRead; } }; +/// A fixed int type of a specified bitwidth. +class ExtIntType final : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + unsigned IsUnsigned : 1; + unsigned NumBits : 24; + +protected: + ExtIntType(bool isUnsigned, unsigned NumBits); + +public: + bool isUnsigned() const { return IsUnsigned; } + bool isSigned() const { return !IsUnsigned; } + unsigned getNumBits() const { return NumBits; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, isUnsigned(), getNumBits()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, bool IsUnsigned, + unsigned NumBits) { + ID.AddBoolean(IsUnsigned); + ID.AddInteger(NumBits); + } + + static bool classof(const Type *T) { return T->getTypeClass() == ExtInt; } +}; + +class DependentExtIntType final : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + const ASTContext &Context; + llvm::PointerIntPair<Expr*, 1, bool> ExprAndUnsigned; + +protected: + DependentExtIntType(const ASTContext &Context, bool IsUnsigned, + Expr *NumBits); + +public: + bool isUnsigned() const; + bool isSigned() const { return !isUnsigned(); } + Expr *getNumBitsExpr() const; + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, isUnsigned(), getNumBitsExpr()); + } + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + bool IsUnsigned, Expr *NumBitsExpr); + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentExtInt; + } +}; + /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { public: @@ -6573,6 +6757,14 @@ inline bool Type::isExtVectorType() const { return isa<ExtVectorType>(CanonicalType); } +inline bool Type::isMatrixType() const { + return isa<MatrixType>(CanonicalType); +} + +inline bool Type::isConstantMatrixType() const { + return isa<ConstantMatrixType>(CanonicalType); +} + inline bool Type::isDependentAddressSpaceType() const { return isa<DependentAddressSpaceType>(CanonicalType); } @@ -6673,6 +6865,10 @@ inline bool Type::isPipeType() const { return isa<PipeType>(CanonicalType); } +inline bool Type::isExtIntType() const { + return isa<ExtIntType>(CanonicalType); +} + #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ inline bool Type::is##Id##Type() const { \ return isSpecificBuiltinType(BuiltinType::Id); \ @@ -6704,9 +6900,9 @@ inline bool Type::isTemplateTypeParmType() const { } inline bool Type::isSpecificBuiltinType(unsigned K) const { - if (const BuiltinType *BT = getAs<BuiltinType>()) - if (BT->getKind() == (BuiltinType::Kind) K) - return true; + if (const BuiltinType *BT = getAs<BuiltinType>()) { + return BT->getKind() == static_cast<BuiltinType::Kind>(K); + } return false; } @@ -6725,9 +6921,7 @@ inline const BuiltinType *Type::getAsPlaceholderType() const { inline bool Type::isSpecificPlaceholderType(unsigned K) const { assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K)); - if (const auto *BT = dyn_cast<BuiltinType>(this)) - return (BT->getKind() == (BuiltinType::Kind) K); - return false; + return isSpecificBuiltinType(K); } inline bool Type::isNonOverloadPlaceholderType() const { @@ -6737,34 +6931,28 @@ inline bool Type::isNonOverloadPlaceholderType() const { } inline bool Type::isVoidType() const { - if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Void; - return false; + return isSpecificBuiltinType(BuiltinType::Void); } inline bool Type::isHalfType() const { - if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Half; // FIXME: Should we allow complex __fp16? Probably not. - return false; + return isSpecificBuiltinType(BuiltinType::Half); } inline bool Type::isFloat16Type() const { - if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Float16; - return false; + return isSpecificBuiltinType(BuiltinType::Float16); +} + +inline bool Type::isBFloat16Type() const { + return isSpecificBuiltinType(BuiltinType::BFloat16); } inline bool Type::isFloat128Type() const { - if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Float128; - return false; + return isSpecificBuiltinType(BuiltinType::Float128); } inline bool Type::isNullPtrType() const { - if (const auto *BT = getAs<BuiltinType>()) - return BT->getKind() == BuiltinType::NullPtr; - return false; + return isSpecificBuiltinType(BuiltinType::NullPtr); } bool IsEnumDeclComplete(EnumDecl *); @@ -6780,7 +6968,7 @@ inline bool Type::isIntegerType() const { return IsEnumDeclComplete(ET->getDecl()) && !IsEnumDeclScoped(ET->getDecl()); } - return false; + return isExtIntType(); } inline bool Type::isFixedPointType() const { @@ -6837,7 +7025,8 @@ inline bool Type::isScalarType() const { isa<BlockPointerType>(CanonicalType) || isa<MemberPointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) || - isa<ObjCObjectPointerType>(CanonicalType); + isa<ObjCObjectPointerType>(CanonicalType) || + isExtIntType(); } inline bool Type::isIntegralOrEnumerationType() const { @@ -6850,7 +7039,7 @@ inline bool Type::isIntegralOrEnumerationType() const { if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) return IsEnumDeclComplete(ET->getDecl()); - return false; + return isExtIntType(); } inline bool Type::isBooleanType() const { diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index c3baaa3e4174..72cc8ef098e7 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_TYPELOC_H #define LLVM_CLANG_AST_TYPELOC_H +#include "clang/AST/DeclarationName.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" @@ -34,6 +35,7 @@ namespace clang { class Attr; class ASTContext; class CXXRecordDecl; +class ConceptDecl; class Expr; class ObjCInterfaceDecl; class ObjCProtocolDecl; @@ -181,6 +183,11 @@ public: /// AttributedTypeLoc, for those type attributes that behave as qualifiers TypeLoc findExplicitQualifierLoc() const; + /// Get the typeloc of an AutoType whose type will be deduced for a variable + /// with an initializer of this type. This looks through declarators like + /// pointer types, but not through decltype or typedefs. + AutoTypeLoc getContainedAutoTypeLoc() const; + /// Initializes this to state that every location in this /// type is the given location. /// @@ -1728,6 +1735,7 @@ public: void initializeLocal(ASTContext &Context, SourceLocation loc) { setAttrNameLoc(loc); + setAttrOperandParensRange(loc); setAttrOperandParensRange(SourceRange(loc)); setAttrExprOperand(getTypePtr()->getAddrSpaceExpr()); } @@ -1767,6 +1775,68 @@ class DependentSizedExtVectorTypeLoc : DependentSizedExtVectorType> { }; +struct MatrixTypeLocInfo { + SourceLocation AttrLoc; + SourceRange OperandParens; + Expr *RowOperand; + Expr *ColumnOperand; +}; + +class MatrixTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, MatrixTypeLoc, + MatrixType, MatrixTypeLocInfo> { +public: + /// The location of the attribute name, i.e. + /// float __attribute__((matrix_type(4, 2))) + /// ^~~~~~~~~~~~~~~~~ + SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; } + void setAttrNameLoc(SourceLocation loc) { getLocalData()->AttrLoc = loc; } + + /// The attribute's row operand, if it has one. + /// float __attribute__((matrix_type(4, 2))) + /// ^ + Expr *getAttrRowOperand() const { return getLocalData()->RowOperand; } + void setAttrRowOperand(Expr *e) { getLocalData()->RowOperand = e; } + + /// The attribute's column operand, if it has one. + /// float __attribute__((matrix_type(4, 2))) + /// ^ + Expr *getAttrColumnOperand() const { return getLocalData()->ColumnOperand; } + void setAttrColumnOperand(Expr *e) { getLocalData()->ColumnOperand = e; } + + /// The location of the parentheses around the operand, if there is + /// an operand. + /// float __attribute__((matrix_type(4, 2))) + /// ^ ^ + SourceRange getAttrOperandParensRange() const { + return getLocalData()->OperandParens; + } + void setAttrOperandParensRange(SourceRange range) { + getLocalData()->OperandParens = range; + } + + SourceRange getLocalSourceRange() const { + SourceRange range(getAttrNameLoc()); + range.setEnd(getAttrOperandParensRange().getEnd()); + return range; + } + + void initializeLocal(ASTContext &Context, SourceLocation loc) { + setAttrNameLoc(loc); + setAttrOperandParensRange(loc); + setAttrRowOperand(nullptr); + setAttrColumnOperand(nullptr); + } +}; + +class ConstantMatrixTypeLoc + : public InheritingConcreteTypeLoc<MatrixTypeLoc, ConstantMatrixTypeLoc, + ConstantMatrixType> {}; + +class DependentSizedMatrixTypeLoc + : public InheritingConcreteTypeLoc<MatrixTypeLoc, + DependentSizedMatrixTypeLoc, + DependentSizedMatrixType> {}; + // FIXME: location of the '_Complex' keyword. class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, ComplexTypeLoc, @@ -1923,8 +1993,137 @@ class DeducedTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc, DeducedType> {}; +struct AutoTypeLocInfo : TypeSpecLocInfo { + NestedNameSpecifierLoc NestedNameSpec; + SourceLocation TemplateKWLoc; + SourceLocation ConceptNameLoc; + NamedDecl *FoundDecl; + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; +}; + class AutoTypeLoc - : public InheritingConcreteTypeLoc<DeducedTypeLoc, AutoTypeLoc, AutoType> { + : public ConcreteTypeLoc<DeducedTypeLoc, + AutoTypeLoc, + AutoType, + AutoTypeLocInfo> { +public: + AutoTypeKeyword getAutoKeyword() const { + return getTypePtr()->getKeyword(); + } + + bool isConstrained() const { + return getTypePtr()->isConstrained(); + } + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return getLocalData()->NestedNameSpec; + } + + void setNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + getLocalData()->NestedNameSpec = NNS; + } + + SourceLocation getTemplateKWLoc() const { + return getLocalData()->TemplateKWLoc; + } + + void setTemplateKWLoc(SourceLocation Loc) { + getLocalData()->TemplateKWLoc = Loc; + } + + SourceLocation getConceptNameLoc() const { + return getLocalData()->ConceptNameLoc; + } + + void setConceptNameLoc(SourceLocation Loc) { + getLocalData()->ConceptNameLoc = Loc; + } + + NamedDecl *getFoundDecl() const { + return getLocalData()->FoundDecl; + } + + void setFoundDecl(NamedDecl *D) { + getLocalData()->FoundDecl = D; + } + + ConceptDecl *getNamedConcept() const { + return getTypePtr()->getTypeConstraintConcept(); + } + + DeclarationNameInfo getConceptNameInfo() const; + + bool hasExplicitTemplateArgs() const { + return getLocalData()->LAngleLoc.isValid(); + } + + SourceLocation getLAngleLoc() const { + return this->getLocalData()->LAngleLoc; + } + + void setLAngleLoc(SourceLocation Loc) { + this->getLocalData()->LAngleLoc = Loc; + } + + SourceLocation getRAngleLoc() const { + return this->getLocalData()->RAngleLoc; + } + + void setRAngleLoc(SourceLocation Loc) { + this->getLocalData()->RAngleLoc = Loc; + } + + unsigned getNumArgs() const { + return getTypePtr()->getNumArgs(); + } + + void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { + getArgInfos()[i] = AI; + } + + TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { + return getArgInfos()[i]; + } + + TemplateArgumentLoc getArgLoc(unsigned i) const { + return TemplateArgumentLoc(getTypePtr()->getTypeConstraintArguments()[i], + getArgLocInfo(i)); + } + + SourceRange getLocalSourceRange() const { + return{ + isConstrained() + ? (getNestedNameSpecifierLoc() + ? getNestedNameSpecifierLoc().getBeginLoc() + : (getTemplateKWLoc().isValid() + ? getTemplateKWLoc() + : getConceptNameLoc())) + : getNameLoc(), + getNameLoc() + }; + } + + void copy(AutoTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc); + + unsigned getExtraLocalDataSize() const { + return getNumArgs() * sizeof(TemplateArgumentLocInfo); + } + + unsigned getExtraLocalDataAlignment() const { + return alignof(TemplateArgumentLocInfo); + } + +private: + TemplateArgumentLocInfo *getArgInfos() const { + return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); + } }; class DeducedTemplateSpecializationTypeLoc @@ -2314,6 +2513,12 @@ inline T TypeLoc::getAsAdjusted() const { } return Cur.getAs<T>(); } +class ExtIntTypeLoc final + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, ExtIntTypeLoc, + ExtIntType> {}; +class DependentExtIntTypeLoc final + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentExtIntTypeLoc, + DependentExtIntType> {}; } // namespace clang diff --git a/clang/include/clang/AST/TypeLocVisitor.h b/clang/include/clang/AST/TypeLocVisitor.h index ec780884e96c..168e9ac532ee 100644 --- a/clang/include/clang/AST/TypeLocVisitor.h +++ b/clang/include/clang/AST/TypeLocVisitor.h @@ -13,7 +13,6 @@ #define LLVM_CLANG_AST_TYPELOCVISITOR_H #include "clang/AST/TypeLoc.h" -#include "clang/AST/TypeVisitor.h" #include "llvm/Support/ErrorHandling.h" namespace clang { diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index 4df2e2f77e2b..4540ea0e1952 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -224,6 +224,41 @@ let Class = DependentSizedExtVectorType in { }]>; } +let Class = MatrixType in { + def : Property<"elementType", QualType> { + let Read = [{ node->getElementType() }]; + } +} + +let Class = ConstantMatrixType in { + def : Property<"numRows", UInt32> { + let Read = [{ node->getNumRows() }]; + } + def : Property<"numColumns", UInt32> { + let Read = [{ node->getNumColumns() }]; + } + + def : Creator<[{ + return ctx.getConstantMatrixType(elementType, numRows, numColumns); + }]>; +} + +let Class = DependentSizedMatrixType in { + def : Property<"rows", ExprRef> { + let Read = [{ node->getRowExpr() }]; + } + def : Property<"columns", ExprRef> { + let Read = [{ node->getColumnExpr() }]; + } + def : Property<"attributeLoc", SourceLocation> { + let Read = [{ node->getAttributeLoc() }]; + } + + def : Creator<[{ + return ctx.getDependentSizedMatrixType(elementType, rows, columns, attributeLoc); + }]>; +} + let Class = FunctionType in { def : Property<"returnType", QualType> { let Read = [{ node->getReturnType() }]; @@ -249,13 +284,17 @@ let Class = FunctionType in { def : Property<"noCfCheck", Bool> { let Read = [{ node->getExtInfo().getNoCfCheck() }]; } + def : Property<"cmseNSCall", Bool> { + let Read = [{ node->getExtInfo().getCmseNSCall() }]; + } } let Class = FunctionNoProtoType in { def : Creator<[{ auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm, callingConvention, producesResult, - noCallerSavedRegs, noCfCheck); + noCallerSavedRegs, noCfCheck, + cmseNSCall); return ctx.getFunctionNoProtoType(returnType, extInfo); }]>; } @@ -288,7 +327,8 @@ let Class = FunctionProtoType in { def : Creator<[{ auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm, callingConvention, producesResult, - noCallerSavedRegs, noCfCheck); + noCallerSavedRegs, noCfCheck, + cmseNSCall); FunctionProtoType::ExtProtoInfo epi; epi.ExtInfo = extInfo; epi.Variadic = variadic; @@ -395,6 +435,13 @@ let Class = AutoType in { def : Property<"keyword", AutoTypeKeyword> { let Read = [{ node->getKeyword() }]; } + def : Property<"typeConstraintConcept", Optional<ConceptDeclRef>> { + let Read = [{ makeOptionalFromPointer( + const_cast<const ConceptDecl*>(node->getTypeConstraintConcept())) }]; + } + def : Property<"typeConstraintArguments", Array<TemplateArgument>> { + let Read = [{ node->getTypeConstraintArguments() }]; + } // FIXME: better enumerated value // Only really required when the deduced type is null def : Property<"dependence", UInt32> { @@ -406,7 +453,9 @@ let Class = AutoType in { def : Creator<[{ return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword, /*isDependentWithoutDeducedType*/ dependence > 0, - /*isPackWithoutDeducedType*/ dependence > 1); + /*isPackWithoutDeducedType*/ dependence > 1, + makePointerFromOptional(typeConstraintConcept), + typeConstraintArguments); }]>; } @@ -444,7 +493,9 @@ let Class = TagType in { let Class = EnumType in { def : Creator<[{ QualType result = ctx.getEnumType(cast<EnumDecl>(declaration)); - const_cast<Type*>(result.getTypePtr())->setDependent(dependent); + if (dependent) + const_cast<Type *>(result.getTypePtr()) + ->addDependence(TypeDependence::DependentInstantiation); return result; }]>; } @@ -453,7 +504,9 @@ let Class = RecordType in { def : Creator<[{ auto record = cast<RecordDecl>(declaration); QualType result = ctx.getRecordType(record); - const_cast<Type*>(result.getTypePtr())->setDependent(dependent); + if (dependent) + const_cast<Type *>(result.getTypePtr()) + ->addDependence(TypeDependence::DependentInstantiation); return result; }]>; } @@ -596,7 +649,9 @@ let Class = TemplateSpecializationType in { templateArguments, *underlyingType); } - const_cast<Type*>(result.getTypePtr())->setDependent(dependent); + if (dependent) + const_cast<Type *>(result.getTypePtr()) + ->addDependence(TypeDependence::DependentInstantiation); return result; }]>; } @@ -813,3 +868,28 @@ let Class = PipeType in { return ctx.getPipeType(elementType, isReadOnly); }]>; } + +let Class = ExtIntType in { + def : Property<"isUnsigned", Bool> { + let Read = [{ node->isUnsigned() }]; + } + def : Property <"numBits", UInt32> { + let Read = [{ node->getNumBits() }]; + } + + def : Creator<[{ + return ctx.getExtIntType(isUnsigned, numBits); + }]>; +} + +let Class = DependentExtIntType in { + def : Property<"isUnsigned", Bool> { + let Read = [{ node->isUnsigned() }]; + } + def : Property <"numBitsExpr", ExprRef> { + let Read = [{ node->getNumBitsExpr() }]; + } + def : Creator<[{ + return ctx.getDependentExtIntType(isUnsigned, numBitsExpr); + }]>; +} diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h index 43c84292c091..241dd13f903e 100644 --- a/clang/include/clang/AST/VTableBuilder.h +++ b/clang/include/clang/AST/VTableBuilder.h @@ -238,6 +238,11 @@ public: typedef llvm::DenseMap<BaseSubobject, AddressPointLocation> AddressPointsMapTy; + // Mapping between the VTable index and address point index. This is useful + // when you don't care about the base subobjects and only want the address + // point for a given vtable index. + typedef llvm::SmallVector<unsigned, 4> AddressPointsIndexMapTy; + private: // Stores the component indices of the first component of each virtual table in // the virtual table group. To save a little memory in the common case where @@ -253,6 +258,9 @@ private: /// Address points for all vtables. AddressPointsMapTy AddressPoints; + /// Address points for all vtable indices. + AddressPointsIndexMapTy AddressPointIndices; + public: VTableLayout(ArrayRef<size_t> VTableIndices, ArrayRef<VTableComponent> VTableComponents, @@ -277,6 +285,10 @@ public: return AddressPoints; } + const AddressPointsIndexMapTy &getAddressPointIndices() const { + return AddressPointIndices; + } + size_t getNumVTables() const { if (VTableIndices.empty()) return 1; @@ -342,6 +354,9 @@ public: } bool IsMicrosoftABI; + + /// Determine whether this function should be assigned a vtable slot. + static bool hasVtableSlot(const CXXMethodDecl *MD); }; class ItaniumVTableContext : public VTableContextBase { @@ -371,7 +386,17 @@ private: void computeVTableRelatedInformation(const CXXRecordDecl *RD) override; public: - ItaniumVTableContext(ASTContext &Context); + enum VTableComponentLayout { + /// Components in the vtable are pointers to other structs/functions. + Pointer, + + /// Components in the vtable are relative offsets between the vtable and the + /// other structs/functions. + Relative, + }; + + ItaniumVTableContext(ASTContext &Context, + VTableComponentLayout ComponentLayout = Pointer); ~ItaniumVTableContext() override; const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { @@ -402,6 +427,16 @@ public: static bool classof(const VTableContextBase *VT) { return !VT->isMicrosoft(); } + + VTableComponentLayout getVTableComponentLayout() const { + return ComponentLayout; + } + + bool isPointerLayout() const { return ComponentLayout == Pointer; } + bool isRelativeLayout() const { return ComponentLayout == Relative; } + +private: + VTableComponentLayout ComponentLayout; }; /// Holds information about the inheritance path to a virtual base or function |