diff options
Diffstat (limited to 'include/clang/AST')
38 files changed, 1618 insertions, 868 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 6943479831ec..63359294ef63 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -53,6 +53,34 @@ public: void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const; }; + +/// Symbolic representation of a dynamic allocation. +class DynamicAllocLValue { + unsigned Index; + +public: + DynamicAllocLValue() : Index(0) {} + explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {} + unsigned getIndex() { return Index - 1; } + + explicit operator bool() const { return Index != 0; } + + void *getOpaqueValue() { + return reinterpret_cast<void *>(static_cast<uintptr_t>(Index) + << NumLowBitsAvailable); + } + static DynamicAllocLValue getFromOpaqueValue(void *Value) { + DynamicAllocLValue V; + V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable; + return V; + } + + static unsigned getMaxIndex() { + return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1; + } + + static constexpr int NumLowBitsAvailable = 3; +}; } namespace llvm { @@ -67,6 +95,17 @@ template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> { // to include Type.h. static constexpr int NumLowBitsAvailable = 3; }; + +template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> { + static void *getAsVoidPointer(clang::DynamicAllocLValue V) { + return V.getOpaqueValue(); + } + static clang::DynamicAllocLValue getFromVoidPointer(void *P) { + return clang::DynamicAllocLValue::getFromOpaqueValue(P); + } + static constexpr int NumLowBitsAvailable = + clang::DynamicAllocLValue::NumLowBitsAvailable; +}; } namespace clang { @@ -97,13 +136,15 @@ public: }; class LValueBase { - typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue> + typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue, + DynamicAllocLValue> PtrTy; public: LValueBase() : Local{} {} LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0); LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0); + static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type); static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); template <class T> @@ -124,6 +165,7 @@ public: unsigned getCallIndex() const; unsigned getVersion() const; QualType getTypeInfoType() const; + QualType getDynamicAllocType() const; friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { @@ -140,6 +182,8 @@ public: LocalState Local; /// The type std::type_info, if this is a TypeInfoLValue. void *TypeInfoType; + /// The QualType, if this is a DynamicAllocLValue. + void *DynamicAllocType; }; }; diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 1d1aaf4fb115..5e2f4031d96c 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -139,6 +139,12 @@ class FullComment; } // namespace comments +namespace interp { + +class Context; + +} // namespace interp + struct TypeInfo { uint64_t Width = 0; unsigned Align = 0; @@ -179,7 +185,8 @@ private: mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes; mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes; mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes; - mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes; + mutable llvm::ContextualFoldingSet<ConstantArrayType, ASTContext &> + ConstantArrayTypes; mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes; mutable std::vector<VariableArrayType*> VariableArrayTypes; mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes; @@ -507,6 +514,8 @@ private: /// need to be consistently numbered for the mangler). llvm::DenseMap<const DeclContext *, std::unique_ptr<MangleNumberingContext>> MangleNumberingContexts; + llvm::DenseMap<const Decl *, std::unique_ptr<MangleNumberingContext>> + ExtraMangleNumberingContexts; /// Side-table of mangling numbers for declarations which rarely /// need them (like static local vars). @@ -564,6 +573,7 @@ private: const TargetInfo *Target = nullptr; const TargetInfo *AuxTarget = nullptr; clang::PrintingPolicy PrintingPolicy; + std::unique_ptr<interp::Context> InterpContext; public: IdentifierTable &Idents; @@ -573,6 +583,9 @@ public: IntrusiveRefCntPtr<ExternalASTSource> ExternalSource; ASTMutationListener *Listener = nullptr; + /// 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 { @@ -729,71 +742,49 @@ public: /// True if comments are already loaded from ExternalASTSource. mutable bool CommentsLoaded = false; - class RawCommentAndCacheFlags { - public: - enum Kind { - /// We searched for a comment attached to the particular declaration, but - /// didn't find any. - /// - /// getRaw() == 0. - NoCommentInDecl = 0, - - /// We have found a comment attached to this particular declaration. - /// - /// getRaw() != 0. - FromDecl, - - /// This declaration does not have an attached comment, and we have - /// searched the redeclaration chain. - /// - /// If getRaw() == 0, the whole redeclaration chain does not have any - /// comments. - /// - /// If getRaw() != 0, it is a comment propagated from other - /// redeclaration. - FromRedecl - }; - - Kind getKind() const LLVM_READONLY { - return Data.getInt(); - } - - void setKind(Kind K) { - Data.setInt(K); - } - - const RawComment *getRaw() const LLVM_READONLY { - return Data.getPointer(); - } - - void setRaw(const RawComment *RC) { - Data.setPointer(RC); - } - - const Decl *getOriginalDecl() const LLVM_READONLY { - return OriginalDecl; - } - - void setOriginalDecl(const Decl *Orig) { - OriginalDecl = Orig; - } - - private: - llvm::PointerIntPair<const RawComment *, 2, Kind> Data; - const Decl *OriginalDecl; - }; + /// Mapping from declaration to directly attached comment. + /// + /// Raw comments are owned by Comments list. This mapping is populated + /// lazily. + mutable llvm::DenseMap<const Decl *, const RawComment *> DeclRawComments; - /// Mapping from declarations to comments attached to any - /// redeclaration. + /// Mapping from canonical declaration to the first redeclaration in chain + /// that has a comment attached. /// /// Raw comments are owned by Comments list. This mapping is populated /// lazily. - mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments; + mutable llvm::DenseMap<const Decl *, const Decl *> RedeclChainComments; + + /// Keeps track of redeclaration chains that don't have any comment attached. + /// Mapping from canonical declaration to redeclaration chain that has no + /// comments attached to any redeclaration. Specifically it's mapping to + /// the last redeclaration we've checked. + /// + /// Shall not contain declarations that have comments attached to any + /// redeclaration in their chain. + mutable llvm::DenseMap<const Decl *, const Decl *> CommentlessRedeclChains; /// Mapping from declarations to parsed comments attached to any /// redeclaration. mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments; + /// Attaches \p Comment to \p OriginalD and to its redeclaration chain + /// and removes the redeclaration chain from the set of commentless chains. + /// + /// Don't do anything if a comment has already been attached to \p OriginalD + /// or its redeclaration chain. + void cacheRawCommentForDecl(const Decl &OriginalD, + const RawComment &Comment) const; + + /// \returns searches \p CommentsInFile for doc comment for \p D. + /// + /// \p RepresentativeLocForDecl is used as a location for searching doc + /// comments. \p CommentsInFile is a mapping offset -> comment of files in the + /// same file where \p RepresentativeLocForDecl is. + RawComment *getRawCommentForDeclNoCacheImpl( + const Decl *D, const SourceLocation RepresentativeLocForDecl, + const std::map<unsigned, RawComment *> &CommentsInFile) const; + /// Return the documentation comment attached to a given declaration, /// without looking into cache. RawComment *getRawCommentForDeclNoCache(const Decl *D) const; @@ -818,6 +809,16 @@ public: getRawCommentForAnyRedecl(const Decl *D, const Decl **OriginalDecl = nullptr) const; + /// Searches existing comments for doc comments that should be attached to \p + /// Decls. If any doc comment is found, it is parsed. + /// + /// Requirement: All \p Decls are in the same file. + /// + /// If the last comment in the file is already attached we assume + /// there are not comments left to be attached to \p Decls. + void attachCommentsToJustParsedDecls(ArrayRef<Decl *> Decls, + const Preprocessor *PP); + /// Return parsed documentation comment attached to a given declaration. /// Returns nullptr if no comment is attached. /// @@ -1054,6 +1055,9 @@ public: #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ CanQualType Id##Ty; #include "clang/Basic/OpenCLExtensionTypes.def" +#define SVE_TYPE(Name, Id, SingletonId) \ + CanQualType SingletonId; +#include "clang/Basic/AArch64SVEACLETypes.def" // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. @@ -1329,6 +1333,7 @@ public: /// Return the unique reference to the type for a constant array of /// the specified element type. QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, + const Expr *SizeExpr, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; @@ -1498,8 +1503,7 @@ public: bool isKindOf) const; QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl, - ArrayRef<ObjCProtocolDecl *> protocols, - QualType Canonical = QualType()) const; + ArrayRef<ObjCProtocolDecl *> protocols) const; bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl); @@ -2054,6 +2058,11 @@ public: /// types. bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec); + /// Return true if the type has been explicitly qualified with ObjC ownership. + /// A type may be implicitly qualified with ownership under ObjC ARC, and in + /// some cases the compiler treats these differently. + bool hasDirectOwnershipQualifier(QualType Ty) const; + /// Return true if this is an \c NSObject object with its \c NSObject /// attribute set. static bool isObjCNSObjectType(QualType Ty) { @@ -2577,10 +2586,12 @@ public: return T == getObjCSelType(); } - bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, + bool ObjCQualifiedIdTypesAreCompatible(const ObjCObjectPointerType *LHS, + const ObjCObjectPointerType *RHS, bool ForCompare); - bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS); + bool ObjCQualifiedClassTypesAreCompatible(const ObjCObjectPointerType *LHS, + const ObjCObjectPointerType *RHS); // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, @@ -2802,6 +2813,9 @@ public: /// Retrieve the context for computing mangling numbers in the given /// DeclContext. MangleNumberingContext &getManglingNumberContext(const DeclContext *DC); + enum NeedExtraManglingDecl_t { NeedExtraManglingDecl }; + MangleNumberingContext &getManglingNumberContext(NeedExtraManglingDecl_t, + const Decl *D); std::unique_ptr<MangleNumberingContext> createMangleNumberingContext() const; diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h index 93919bbdd52f..25c321485443 100644 --- a/include/clang/AST/ASTFwd.h +++ b/include/clang/AST/ASTFwd.h @@ -24,7 +24,7 @@ class Stmt; #include "clang/AST/StmtNodes.inc" class Type; #define TYPE(DERIVED, BASE) class DERIVED##Type; -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" class CXXCtorInitializer; } // end namespace clang diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 4a55c120a457..c82dcab35db5 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -87,6 +87,10 @@ class TypeSourceInfo; using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>; using ImportedCXXBaseSpecifierMap = llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>; + using FileIDImportHandlerType = + std::function<void(FileID /*ToID*/, FileID /*FromID*/)>; + + enum class ODRHandlingType { Conservative, Liberal }; // An ImportPath is the list of the AST nodes which we visit during an // Import call. @@ -210,6 +214,8 @@ class TypeSourceInfo; }; private: + FileIDImportHandlerType FileIDImportHandler; + std::shared_ptr<ASTImporterSharedState> SharedState = nullptr; /// The path which we go through during the import of a given AST node. @@ -232,6 +238,8 @@ class TypeSourceInfo; /// Whether to perform a minimal import. bool Minimal; + ODRHandlingType ODRHandling; + /// Whether the last diagnostic came from the "from" context. bool LastDiagFromFrom = false; @@ -310,10 +318,20 @@ class TypeSourceInfo; virtual ~ASTImporter(); + /// Set a callback function for FileID import handling. + /// The function is invoked when a FileID is imported from the From context. + /// The imported FileID in the To context and the original FileID in the + /// From context is passed to it. + void setFileIDImportHandler(FileIDImportHandlerType H) { + FileIDImportHandler = H; + } + /// Whether the importer will perform a minimal import, creating /// to-be-completed forward declarations when possible. bool isMinimalImport() const { return Minimal; } + void setODRHandling(ODRHandlingType T) { ODRHandling = T; } + /// \brief Import the given object, returns the result. /// /// \param To Import the object into this variable. @@ -366,6 +384,20 @@ class TypeSourceInfo; /// imported. If it does not exist nullptr is returned. TranslationUnitDecl *GetFromTU(Decl *ToD); + /// Return the declaration in the "from" context from which the declaration + /// in the "to" context was imported. If it was not imported or of the wrong + /// type a null value is returned. + template <typename DeclT> + llvm::Optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const { + auto FromI = ImportedFromDecls.find(ToD); + if (FromI == ImportedFromDecls.end()) + return {}; + auto *FromD = dyn_cast<DeclT>(FromI->second); + if (!FromD) + return {}; + return FromD; + } + /// Import the given declaration context from the "from" /// AST context into the "to" AST context. /// @@ -491,12 +523,11 @@ class TypeSourceInfo; /// /// \param NumDecls the number of conflicting declarations in \p Decls. /// - /// \returns the name that the newly-imported declaration should have. - virtual DeclarationName HandleNameConflict(DeclarationName Name, - DeclContext *DC, - unsigned IDNS, - NamedDecl **Decls, - unsigned NumDecls); + /// \returns the name that the newly-imported declaration should have. Or + /// an error if we can't handle the name conflict. + virtual Expected<DeclarationName> + HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, + NamedDecl **Decls, unsigned NumDecls); /// Retrieve the context that AST nodes are being imported into. ASTContext &getToContext() const { return ToContext; } diff --git a/include/clang/AST/ASTImporterSharedState.h b/include/clang/AST/ASTImporterSharedState.h index 3635a62deef0..829eb1c611c3 100644 --- a/include/clang/AST/ASTImporterSharedState.h +++ b/include/clang/AST/ASTImporterSharedState.h @@ -47,7 +47,7 @@ public: ASTImporterSharedState() = default; ASTImporterSharedState(TranslationUnitDecl &ToTU) { - LookupTable = llvm::make_unique<ASTImporterLookupTable>(ToTU); + LookupTable = std::make_unique<ASTImporterLookupTable>(ToTU); } ASTImporterLookupTable *getLookupTable() { return LookupTable.get(); } diff --git a/include/clang/AST/ASTNodeTraverser.h b/include/clang/AST/ASTNodeTraverser.h index e43eacef86c6..0bb2aad553fb 100644 --- a/include/clang/AST/ASTNodeTraverser.h +++ b/include/clang/AST/ASTNodeTraverser.h @@ -237,6 +237,9 @@ public: for (const auto &TP : *TPL) Visit(TP); + + if (const Expr *RC = TPL->getRequiresClause()) + Visit(RC); } void diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h index 70e0daa08a9a..36a42070fd28 100644 --- a/include/clang/AST/ASTStructuralEquivalence.h +++ b/include/clang/AST/ASTStructuralEquivalence.h @@ -18,7 +18,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" -#include <deque> +#include <queue> #include <utility> namespace clang { @@ -42,14 +42,13 @@ struct StructuralEquivalenceContext { /// AST contexts for which we are checking structural equivalence. ASTContext &FromCtx, &ToCtx; - /// The set of "tentative" equivalences between two canonical - /// declarations, mapping from a declaration in the first context to the - /// declaration in the second context that we believe to be equivalent. - llvm::DenseMap<Decl *, Decl *> TentativeEquivalences; + // Queue of from-to Decl pairs that are to be checked to determine the final + // result of equivalence of a starting Decl pair. + std::queue<std::pair<Decl *, Decl *>> DeclsToCheck; - /// Queue of declarations in the first context whose equivalence - /// with a declaration in the second context still needs to be verified. - std::deque<Decl *> DeclsToCheck; + // Set of from-to Decl pairs that are already visited during the check + // (are in or were once in \c DeclsToCheck) of a starting Decl pair. + llvm::DenseSet<std::pair<Decl *, Decl *>> VisitedDecls; /// Declaration (from, to) pairs that are known not to be equivalent /// (which we have already complained about). @@ -88,14 +87,14 @@ struct StructuralEquivalenceContext { /// Implementation functions (all static functions in /// ASTStructuralEquivalence.cpp) must never call this function because that /// will wreak havoc the internal state (\c DeclsToCheck and - /// \c TentativeEquivalences members) and can cause faulty equivalent results. + /// \c VisitedDecls members) and can cause faulty equivalent results. bool IsEquivalent(Decl *D1, Decl *D2); /// Determine whether the two types are structurally equivalent. /// Implementation functions (all static functions in /// ASTStructuralEquivalence.cpp) must never call this function because that /// will wreak havoc the internal state (\c DeclsToCheck and - /// \c TentativeEquivalences members) and can cause faulty equivalent results. + /// \c VisitedDecls members) and can cause faulty equivalent results. bool IsEquivalent(QualType T1, QualType T2); /// Find the index of the given anonymous struct/union within its diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index a29a04e5d242..dd4ead2f0c2b 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -148,7 +148,7 @@ private: #include "clang/AST/StmtNodes.inc" NKI_Type, #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" NKI_OMPClause, #define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class, #include "clang/Basic/OpenMPKinds.def" @@ -205,7 +205,7 @@ KIND_TO_KIND_ID(OMPClause) #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.def" +#include "clang/AST/TypeNodes.inc" #define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class) #include "clang/Basic/OpenMPKinds.def" #undef KIND_TO_KIND_ID diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 1fbed7ceebfa..d315dde6ed45 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -19,6 +19,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/AttrKinds.h" +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Sanitizers.h" @@ -32,6 +33,7 @@ namespace clang { class ASTContext; + class AttributeCommonInfo; class IdentifierInfo; class ObjCInterfaceDecl; class Expr; @@ -40,84 +42,79 @@ namespace clang { class TypeSourceInfo; /// Attr - This represents one attribute. -class Attr { -private: - SourceRange Range; - unsigned AttrKind : 16; - -protected: - /// An index into the spelling list of an - /// attribute defined in Attr.td file. - unsigned SpellingListIndex : 4; - unsigned Inherited : 1; - unsigned IsPackExpansion : 1; - unsigned Implicit : 1; - // FIXME: These are properties of the attribute kind, not state for this - // instance of the attribute. - unsigned IsLateParsed : 1; - unsigned InheritEvenIfAlreadyPresent : 1; - - void *operator new(size_t bytes) noexcept { - llvm_unreachable("Attrs cannot be allocated with regular 'new'."); - } - void operator delete(void *data) noexcept { - llvm_unreachable("Attrs cannot be released with regular 'delete'."); - } - -public: - // Forward so that the regular new and delete do not hide global ones. - void *operator new(size_t Bytes, ASTContext &C, - size_t Alignment = 8) noexcept { - return ::operator new(Bytes, C, Alignment); - } - void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept { - return ::operator delete(Ptr, C, Alignment); - } + class Attr : public AttributeCommonInfo { + private: + unsigned AttrKind : 16; + + protected: + /// An index into the spelling list of an + /// attribute defined in Attr.td file. + unsigned Inherited : 1; + unsigned IsPackExpansion : 1; + unsigned Implicit : 1; + // FIXME: These are properties of the attribute kind, not state for this + // instance of the attribute. + unsigned IsLateParsed : 1; + unsigned InheritEvenIfAlreadyPresent : 1; + + void *operator new(size_t bytes) noexcept { + llvm_unreachable("Attrs cannot be allocated with regular 'new'."); + } + void operator delete(void *data) noexcept { + llvm_unreachable("Attrs cannot be released with regular 'delete'."); + } -protected: - Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed) - : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex), - Inherited(false), IsPackExpansion(false), Implicit(false), - IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {} + public: + // Forward so that the regular new and delete do not hide global ones. + void *operator new(size_t Bytes, ASTContext &C, + size_t Alignment = 8) noexcept { + return ::operator new(Bytes, C, Alignment); + } + void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept { + return ::operator delete(Ptr, C, Alignment); + } -public: + protected: + Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed) + : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false), + IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed), + InheritEvenIfAlreadyPresent(false) {} - attr::Kind getKind() const { - return static_cast<attr::Kind>(AttrKind); - } + public: + attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); } - unsigned getSpellingListIndex() const { return SpellingListIndex; } - const char *getSpelling() const; + unsigned getSpellingListIndex() const { + return getAttributeSpellingListIndex(); + } + const char *getSpelling() const; - SourceLocation getLocation() const { return Range.getBegin(); } - SourceRange getRange() const { return Range; } - void setRange(SourceRange R) { Range = R; } + SourceLocation getLocation() const { return getRange().getBegin(); } - bool isInherited() const { return Inherited; } + bool isInherited() const { return Inherited; } - /// Returns true if the attribute has been implicitly created instead - /// of explicitly written by the user. - bool isImplicit() const { return Implicit; } - void setImplicit(bool I) { Implicit = I; } + /// Returns true if the attribute has been implicitly created instead + /// of explicitly written by the user. + bool isImplicit() const { return Implicit; } + void setImplicit(bool I) { Implicit = I; } - void setPackExpansion(bool PE) { IsPackExpansion = PE; } - bool isPackExpansion() const { return IsPackExpansion; } + void setPackExpansion(bool PE) { IsPackExpansion = PE; } + bool isPackExpansion() const { return IsPackExpansion; } - // Clone this attribute. - Attr *clone(ASTContext &C) const; + // Clone this attribute. + Attr *clone(ASTContext &C) const; - bool isLateParsed() const { return IsLateParsed; } + bool isLateParsed() const { return IsLateParsed; } - // Pretty print this attribute. - void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; -}; + // Pretty print this attribute. + void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; + }; class TypeAttr : public Attr { protected: - TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed) - : Attr(AK, R, SpellingListIndex, IsLateParsed) {} + TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed) + : Attr(Context, CommonInfo, AK, IsLateParsed) {} public: static bool classof(const Attr *A) { @@ -128,9 +125,9 @@ public: class StmtAttr : public Attr { protected: - StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed) - : Attr(AK, R, SpellingListIndex, IsLateParsed) {} + StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed) + : Attr(Context, CommonInfo, AK, IsLateParsed) {} public: static bool classof(const Attr *A) { @@ -141,9 +138,10 @@ public: class InheritableAttr : public Attr { protected: - InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool InheritEvenIfAlreadyPresent) - : Attr(AK, R, SpellingListIndex, IsLateParsed) { + InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed, + bool InheritEvenIfAlreadyPresent) + : Attr(Context, CommonInfo, AK, IsLateParsed) { this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent; } @@ -165,9 +163,10 @@ public: class InheritableParamAttr : public InheritableAttr { protected: - InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, + InheritableParamAttr(ASTContext &Context, + const AttributeCommonInfo &CommonInfo, attr::Kind AK, bool IsLateParsed, bool InheritEvenIfAlreadyPresent) - : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed, + : InheritableAttr(Context, CommonInfo, AK, IsLateParsed, InheritEvenIfAlreadyPresent) {} public: @@ -182,11 +181,11 @@ public: /// for the parameter. class ParameterABIAttr : public InheritableParamAttr { protected: - ParameterABIAttr(attr::Kind AK, SourceRange R, - unsigned SpellingListIndex, bool IsLateParsed, + ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed, bool InheritEvenIfAlreadyPresent) - : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed, - InheritEvenIfAlreadyPresent) {} + : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed, + InheritEvenIfAlreadyPresent) {} public: ParameterABI getABI() const { diff --git a/include/clang/AST/CXXRecordDeclDefinitionBits.def b/include/clang/AST/CXXRecordDeclDefinitionBits.def new file mode 100644 index 000000000000..bd4d8247aeca --- /dev/null +++ b/include/clang/AST/CXXRecordDeclDefinitionBits.def @@ -0,0 +1,236 @@ +//===-- CXXRecordDeclDefinitionBits.def - Class definition bits -*- 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 enumerates the various bitfields that we want to store on C++ class +// definitions. +// +//===----------------------------------------------------------------------===// +// +/// @file CXXRecordDeclDefinitionBits.def +/// +/// In this file, each of the bitfields representing data about a C++ class +/// results in an expansion of the FIELD macro, which should be defined before +/// including this file. +/// +/// The macro have three operands: +/// +/// Name: The name of the field, as a member of CXXRecordDecl::DefinitionData. +/// +/// BitWidth: The width of the field in bits. +/// +/// MergePolicy: How to behave when the value of the field is different in +/// multiple translation units, one of: +/// NO_MERGE: It is an ODR violation if the fields do not match. +/// MERGE_OR: Merge the fields by ORing them together. + +#ifndef FIELD +#error define FIELD before including this file +#endif + +/// True if this class has any user-declared constructors. +FIELD(UserDeclaredConstructor, 1, NO_MERGE) + +/// The user-declared special members which this class has. +FIELD(UserDeclaredSpecialMembers, 6, NO_MERGE) + +/// True when this class is an aggregate. +FIELD(Aggregate, 1, NO_MERGE) + +/// True when this class is a POD-type. +FIELD(PlainOldData, 1, NO_MERGE) + +/// True when this class is empty for traits purposes, that is: +/// * has no data members other than 0-width bit-fields and empty fields +/// marked [[no_unique_address]] +/// * has no virtual function/base, and +/// * doesn't inherit from a non-empty class. +/// Doesn't take union-ness into account. +FIELD(Empty, 1, NO_MERGE) + +/// True when this class is polymorphic, i.e., has at +/// least one virtual member or derives from a polymorphic class. +FIELD(Polymorphic, 1, NO_MERGE) + +/// True when this class is abstract, i.e., has at least +/// one pure virtual function, (that can come from a base class). +FIELD(Abstract, 1, NO_MERGE) + +/// True when this class is standard-layout, per the applicable +/// language rules (including DRs). +FIELD(IsStandardLayout, 1, NO_MERGE) + +/// True when this class was standard-layout under the C++11 +/// definition. +/// +/// C++11 [class]p7. A standard-layout class is a class that: +/// * has no non-static data members of type non-standard-layout class (or +/// array of such types) or reference, +/// * has no virtual functions (10.3) and no virtual base classes (10.1), +/// * has the same access control (Clause 11) for all non-static data +/// members +/// * has no non-standard-layout base classes, +/// * either has no non-static data members in the most derived class and at +/// most one base class with non-static data members, or has no base +/// classes with non-static data members, and +/// * has no base classes of the same type as the first non-static data +/// member. +FIELD(IsCXX11StandardLayout, 1, NO_MERGE) + +/// True when any base class has any declared non-static data +/// members or bit-fields. +/// This is a helper bit of state used to implement IsStandardLayout more +/// efficiently. +FIELD(HasBasesWithFields, 1, NO_MERGE) + +/// True when any base class has any declared non-static data +/// members. +/// This is a helper bit of state used to implement IsCXX11StandardLayout +/// more efficiently. +FIELD(HasBasesWithNonStaticDataMembers, 1, NO_MERGE) + +/// True when there are private non-static data members. +FIELD(HasPrivateFields, 1, NO_MERGE) + +/// True when there are protected non-static data members. +FIELD(HasProtectedFields, 1, NO_MERGE) + +/// True when there are private non-static data members. +FIELD(HasPublicFields, 1, NO_MERGE) + +/// True if this class (or any subobject) has mutable fields. +FIELD(HasMutableFields, 1, NO_MERGE) + +/// True if this class (or any nested anonymous struct or union) +/// has variant members. +FIELD(HasVariantMembers, 1, NO_MERGE) + +/// True if there no non-field members declared by the user. +FIELD(HasOnlyCMembers, 1, NO_MERGE) + +/// True if any field has an in-class initializer, including those +/// within anonymous unions or structs. +FIELD(HasInClassInitializer, 1, NO_MERGE) + +/// True if any field is of reference type, and does not have an +/// in-class initializer. +/// +/// In this case, value-initialization of this class is illegal in C++98 +/// even if the class has a trivial default constructor. +FIELD(HasUninitializedReferenceMember, 1, NO_MERGE) + +/// True if any non-mutable field whose type doesn't have a user- +/// provided default ctor also doesn't have an in-class initializer. +FIELD(HasUninitializedFields, 1, NO_MERGE) + +/// True if there are any member using-declarations that inherit +/// constructors from a base class. +FIELD(HasInheritedConstructor, 1, NO_MERGE) + +/// True if there are any member using-declarations named +/// 'operator='. +FIELD(HasInheritedAssignment, 1, NO_MERGE) + +/// These flags are \c true if a defaulted corresponding special +/// member can't be fully analyzed without performing overload resolution. +/// @{ +FIELD(NeedOverloadResolutionForCopyConstructor, 1, NO_MERGE) +FIELD(NeedOverloadResolutionForMoveConstructor, 1, NO_MERGE) +FIELD(NeedOverloadResolutionForMoveAssignment, 1, NO_MERGE) +FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE) +/// @} + +/// These flags are \c true if an implicit defaulted corresponding +/// special member would be defined as deleted. +/// @{ +FIELD(DefaultedCopyConstructorIsDeleted, 1, NO_MERGE) +FIELD(DefaultedMoveConstructorIsDeleted, 1, NO_MERGE) +FIELD(DefaultedMoveAssignmentIsDeleted, 1, NO_MERGE) +FIELD(DefaultedDestructorIsDeleted, 1, NO_MERGE) +/// @} + +/// The trivial special members which this class has, per +/// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25, +/// C++11 [class.dtor]p5, or would have if the member were not suppressed. +/// +/// This excludes any user-declared but not user-provided special members +/// which have been declared but not yet defined. +FIELD(HasTrivialSpecialMembers, 6, MERGE_OR) + +/// These bits keep track of the triviality of special functions for the +/// purpose of calls. Only the bits corresponding to SMF_CopyConstructor, +/// SMF_MoveConstructor, and SMF_Destructor are meaningful here. +FIELD(HasTrivialSpecialMembersForCall, 6, MERGE_OR) + +/// The declared special members of this class which are known to be +/// non-trivial. +/// +/// This excludes any user-declared but not user-provided special members +/// which have been declared but not yet defined, and any implicit special +/// members which have not yet been declared. +FIELD(DeclaredNonTrivialSpecialMembers, 6, MERGE_OR) + +/// These bits keep track of the declared special members that are +/// non-trivial for the purpose of calls. +/// Only the bits corresponding to SMF_CopyConstructor, +/// SMF_MoveConstructor, and SMF_Destructor are meaningful here. +FIELD(DeclaredNonTrivialSpecialMembersForCall, 6, MERGE_OR) + +/// True when this class has a destructor with no semantic effect. +FIELD(HasIrrelevantDestructor, 1, NO_MERGE) + +/// True when this class has at least one user-declared constexpr +/// constructor which is neither the copy nor move constructor. +FIELD(HasConstexprNonCopyMoveConstructor, 1, MERGE_OR) + +/// True if this class has a (possibly implicit) defaulted default +/// constructor. +FIELD(HasDefaultedDefaultConstructor, 1, MERGE_OR) + +/// True if a defaulted default constructor for this class would +/// be constexpr. +FIELD(DefaultedDefaultConstructorIsConstexpr, 1, NO_MERGE) + +/// True if this class has a constexpr default constructor. +/// +/// This is true for either a user-declared constexpr default constructor +/// or an implicitly declared constexpr default constructor. +FIELD(HasConstexprDefaultConstructor, 1, MERGE_OR) + +/// True if a defaulted destructor for this class would be constexpr. +FIELD(DefaultedDestructorIsConstexpr, 1, NO_MERGE) + +/// True when this class contains at least one non-static data +/// member or base class of non-literal or volatile type. +FIELD(HasNonLiteralTypeFieldsOrBases, 1, NO_MERGE) + +/// Whether we have a C++11 user-provided default constructor (not +/// explicitly deleted or defaulted). +FIELD(UserProvidedDefaultConstructor, 1, NO_MERGE) + +/// The special members which have been declared for this class, +/// either by the user or implicitly. +FIELD(DeclaredSpecialMembers, 6, MERGE_OR) + +/// Whether an implicit copy constructor could have a const-qualified +/// parameter, for initializing virtual bases and for other subobjects. +FIELD(ImplicitCopyConstructorCanHaveConstParamForVBase, 1, NO_MERGE) +FIELD(ImplicitCopyConstructorCanHaveConstParamForNonVBase, 1, NO_MERGE) + +/// Whether an implicit copy assignment operator would have a +/// const-qualified parameter. +FIELD(ImplicitCopyAssignmentHasConstParam, 1, NO_MERGE) + +/// Whether any declared copy constructor has a const-qualified +/// parameter. +FIELD(HasDeclaredCopyConstructorWithConstParam, 1, MERGE_OR) + +/// Whether any declared copy assignment operator has either a +/// const-qualified reference parameter or a non-reference parameter. +FIELD(HasDeclaredCopyAssignmentWithConstParam, 1, MERGE_OR) + +#undef FIELD diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 37f489c7708a..f14d3abf71e5 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_CHARUNITS_H #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/Alignment.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" @@ -177,6 +178,10 @@ namespace clang { /// getQuantity - Get the raw integer representation of this quantity. QuantityType getQuantity() const { return Quantity; } + /// getAsAlign - Returns Quantity as a valid llvm::Align, + /// Beware llvm::Align assumes power of two 8-bit bytes. + llvm::Align getAsAlign() const { return llvm::Align(Quantity); } + /// alignTo - Returns the next integer (mod 2**64) that is /// greater than or equal to this quantity and is a multiple of \p Align. /// Align must be non-zero. diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td index 958ee032e71f..3b0d1603d407 100644 --- a/include/clang/AST/CommentCommands.td +++ b/include/clang/AST/CommentCommands.td @@ -139,6 +139,7 @@ def Post : BlockCommand<"post">; def Pre : BlockCommand<"pre">; def Remark : BlockCommand<"remark">; def Remarks : BlockCommand<"remarks">; +def Retval : BlockCommand<"retval">; def Sa : BlockCommand<"sa">; def See : BlockCommand<"see">; def Since : BlockCommand<"since">; diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index 9ddbb7d31d99..138fdaca0ff6 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -352,8 +352,7 @@ public: void lex(Token &T); - StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr, - bool *Invalid = nullptr) const; + StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr) const; }; } // end namespace comments diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 02742801f37c..ce674e09c44d 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -310,6 +310,14 @@ public: void printQualifiedName(raw_ostream &OS) const; void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const; + /// Print only the nested name specifier part of a fully-qualified name, + /// including the '::' at the end. E.g. + /// when `printQualifiedName(D)` prints "A::B::i", + /// this function prints "A::B::". + void printNestedNameSpecifier(raw_ostream &OS) const; + void printNestedNameSpecifier(raw_ostream &OS, + const PrintingPolicy &Policy) const; + // FIXME: Remove string version. std::string getQualifiedNameAsString() const; @@ -800,12 +808,19 @@ struct EvaluatedStmt { /// valid if CheckedICE is true. bool IsICE : 1; + /// Whether this variable is known to have constant destruction. That is, + /// whether running the destructor on the initial value is a side-effect + /// (and doesn't inspect any state that might have changed during program + /// execution). This is currently only computed if the destructor is + /// non-trivial. + bool HasConstantDestruction : 1; + Stmt *Value; APValue Evaluated; - EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), - CheckingICE(false), IsICE(false) {} - + EvaluatedStmt() + : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), + CheckingICE(false), IsICE(false), HasConstantDestruction(false) {} }; /// Represents a variable declaration or definition. @@ -1226,6 +1241,14 @@ public: void setInit(Expr *I); + /// Get the initializing declaration of this variable, if any. This is + /// usually the definition, except that for a static data member it can be + /// the in-class declaration. + VarDecl *getInitializingDeclaration(); + const VarDecl *getInitializingDeclaration() const { + return const_cast<VarDecl *>(this)->getInitializingDeclaration(); + } + /// Determine whether this variable's value might be usable in a /// constant expression, according to the relevant language standard. /// This only checks properties of the declaration, and does not check @@ -1251,6 +1274,14 @@ public: /// to untyped APValue if the value could not be evaluated. APValue *getEvaluatedValue() const; + /// Evaluate the destruction of this variable to determine if it constitutes + /// constant destruction. + /// + /// \pre isInitICE() + /// \return \c true if this variable has constant destruction, \c false if + /// not. + bool evaluateDestruction(SmallVectorImpl<PartialDiagnosticAt> &Notes) const; + /// Determines whether it is already known whether the /// initializer is an integral constant expression or not. bool isInitKnownICE() const; @@ -1489,9 +1520,14 @@ public: // has no definition within this source file. bool isKnownToBeDefined() const; - /// Do we need to emit an exit-time destructor for this variable? + /// Is destruction of this variable entirely suppressed? If so, the variable + /// need not have a usable destructor at all. bool isNoDestroy(const ASTContext &) const; + /// Do we need to emit an exit-time destructor for this variable, and if so, + /// what kind? + QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; } @@ -4078,13 +4114,9 @@ public: void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures, bool CapturesCXXThis); - unsigned getBlockManglingNumber() const { - return ManglingNumber; - } + unsigned getBlockManglingNumber() const { return ManglingNumber; } - Decl *getBlockManglingContextDecl() const { - return ManglingContextDecl; - } + Decl *getBlockManglingContextDecl() const { return ManglingContextDecl; } void setBlockMangling(unsigned Number, Decl *Ctx) { ManglingNumber = Number; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index d64d0cb425db..01c2f1809771 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -959,7 +959,7 @@ public: /// as this declaration, or NULL if there is no previous declaration. Decl *getPreviousDecl() { return getPreviousDeclImpl(); } - /// Retrieve the most recent declaration that declares the same entity + /// Retrieve the previous declaration that declares the same entity /// as this declaration, or NULL if there is no previous declaration. const Decl *getPreviousDecl() const { return const_cast<Decl *>(this)->getPreviousDeclImpl(); diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 7add83f89624..66212f72b787 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -42,6 +42,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" @@ -73,52 +74,6 @@ class TemplateDecl; class TemplateParameterList; class UsingDecl; -/// Represents any kind of function declaration, whether it is a -/// concrete function or a function template. -class AnyFunctionDecl { - NamedDecl *Function; - - AnyFunctionDecl(NamedDecl *ND) : Function(ND) {} - -public: - AnyFunctionDecl(FunctionDecl *FD) : Function(FD) {} - AnyFunctionDecl(FunctionTemplateDecl *FTD); - - /// Implicily converts any function or function template into a - /// named declaration. - operator NamedDecl *() const { return Function; } - - /// Retrieve the underlying function or function template. - NamedDecl *get() const { return Function; } - - static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { - return AnyFunctionDecl(ND); - } -}; - -} // namespace clang - -namespace llvm { - - // Provide PointerLikeTypeTraits for non-cvr pointers. - template<> - struct PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { - static void *getAsVoidPointer(::clang::AnyFunctionDecl F) { - return F.get(); - } - - static ::clang::AnyFunctionDecl getFromVoidPointer(void *P) { - return ::clang::AnyFunctionDecl::getFromNamedDecl( - static_cast< ::clang::NamedDecl*>(P)); - } - - enum { NumLowBitsAvailable = 2 }; - }; - -} // namespace llvm - -namespace clang { - /// Represents an access specifier followed by colon ':'. /// /// An objects of this class represents sugar for the syntactic occurrence @@ -322,207 +277,9 @@ class CXXRecordDecl : public RecordDecl { }; struct DefinitionData { - /// True if this class has any user-declared constructors. - unsigned UserDeclaredConstructor : 1; - - /// The user-declared special members which this class has. - unsigned UserDeclaredSpecialMembers : 6; - - /// True when this class is an aggregate. - unsigned Aggregate : 1; - - /// True when this class is a POD-type. - unsigned PlainOldData : 1; - - /// True when this class is empty for traits purposes, that is: - /// * has no data members other than 0-width bit-fields and empty fields - /// marked [[no_unique_address]] - /// * has no virtual function/base, and - /// * doesn't inherit from a non-empty class. - /// Doesn't take union-ness into account. - unsigned Empty : 1; - - /// True when this class is polymorphic, i.e., has at - /// least one virtual member or derives from a polymorphic class. - unsigned Polymorphic : 1; - - /// True when this class is abstract, i.e., has at least - /// one pure virtual function, (that can come from a base class). - unsigned Abstract : 1; - - /// True when this class is standard-layout, per the applicable - /// language rules (including DRs). - unsigned IsStandardLayout : 1; - - /// True when this class was standard-layout under the C++11 - /// definition. - /// - /// C++11 [class]p7. A standard-layout class is a class that: - /// * has no non-static data members of type non-standard-layout class (or - /// array of such types) or reference, - /// * has no virtual functions (10.3) and no virtual base classes (10.1), - /// * has the same access control (Clause 11) for all non-static data - /// members - /// * has no non-standard-layout base classes, - /// * either has no non-static data members in the most derived class and at - /// most one base class with non-static data members, or has no base - /// classes with non-static data members, and - /// * has no base classes of the same type as the first non-static data - /// member. - unsigned IsCXX11StandardLayout : 1; - - /// True when any base class has any declared non-static data - /// members or bit-fields. - /// This is a helper bit of state used to implement IsStandardLayout more - /// efficiently. - unsigned HasBasesWithFields : 1; - - /// True when any base class has any declared non-static data - /// members. - /// This is a helper bit of state used to implement IsCXX11StandardLayout - /// more efficiently. - unsigned HasBasesWithNonStaticDataMembers : 1; - - /// True when there are private non-static data members. - unsigned HasPrivateFields : 1; - - /// True when there are protected non-static data members. - unsigned HasProtectedFields : 1; - - /// True when there are private non-static data members. - unsigned HasPublicFields : 1; - - /// True if this class (or any subobject) has mutable fields. - unsigned HasMutableFields : 1; - - /// True if this class (or any nested anonymous struct or union) - /// has variant members. - unsigned HasVariantMembers : 1; - - /// True if there no non-field members declared by the user. - unsigned HasOnlyCMembers : 1; - - /// True if any field has an in-class initializer, including those - /// within anonymous unions or structs. - unsigned HasInClassInitializer : 1; - - /// True if any field is of reference type, and does not have an - /// in-class initializer. - /// - /// In this case, value-initialization of this class is illegal in C++98 - /// even if the class has a trivial default constructor. - unsigned HasUninitializedReferenceMember : 1; - - /// True if any non-mutable field whose type doesn't have a user- - /// provided default ctor also doesn't have an in-class initializer. - unsigned HasUninitializedFields : 1; - - /// True if there are any member using-declarations that inherit - /// constructors from a base class. - unsigned HasInheritedConstructor : 1; - - /// True if there are any member using-declarations named - /// 'operator='. - unsigned HasInheritedAssignment : 1; - - /// These flags are \c true if a defaulted corresponding special - /// member can't be fully analyzed without performing overload resolution. - /// @{ - unsigned NeedOverloadResolutionForCopyConstructor : 1; - unsigned NeedOverloadResolutionForMoveConstructor : 1; - unsigned NeedOverloadResolutionForMoveAssignment : 1; - unsigned NeedOverloadResolutionForDestructor : 1; - /// @} - - /// These flags are \c true if an implicit defaulted corresponding - /// special member would be defined as deleted. - /// @{ - unsigned DefaultedCopyConstructorIsDeleted : 1; - unsigned DefaultedMoveConstructorIsDeleted : 1; - unsigned DefaultedMoveAssignmentIsDeleted : 1; - unsigned DefaultedDestructorIsDeleted : 1; - /// @} - - /// The trivial special members which this class has, per - /// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25, - /// C++11 [class.dtor]p5, or would have if the member were not suppressed. - /// - /// This excludes any user-declared but not user-provided special members - /// which have been declared but not yet defined. - unsigned HasTrivialSpecialMembers : 6; - - /// These bits keep track of the triviality of special functions for the - /// purpose of calls. Only the bits corresponding to SMF_CopyConstructor, - /// SMF_MoveConstructor, and SMF_Destructor are meaningful here. - unsigned HasTrivialSpecialMembersForCall : 6; - - /// The declared special members of this class which are known to be - /// non-trivial. - /// - /// This excludes any user-declared but not user-provided special members - /// which have been declared but not yet defined, and any implicit special - /// members which have not yet been declared. - unsigned DeclaredNonTrivialSpecialMembers : 6; - - /// These bits keep track of the declared special members that are - /// non-trivial for the purpose of calls. - /// Only the bits corresponding to SMF_CopyConstructor, - /// SMF_MoveConstructor, and SMF_Destructor are meaningful here. - unsigned DeclaredNonTrivialSpecialMembersForCall : 6; - - /// True when this class has a destructor with no semantic effect. - unsigned HasIrrelevantDestructor : 1; - - /// True when this class has at least one user-declared constexpr - /// constructor which is neither the copy nor move constructor. - unsigned HasConstexprNonCopyMoveConstructor : 1; - - /// True if this class has a (possibly implicit) defaulted default - /// constructor. - unsigned HasDefaultedDefaultConstructor : 1; - - /// True if a defaulted default constructor for this class would - /// be constexpr. - unsigned DefaultedDefaultConstructorIsConstexpr : 1; - - /// True if this class has a constexpr default constructor. - /// - /// This is true for either a user-declared constexpr default constructor - /// or an implicitly declared constexpr default constructor. - unsigned HasConstexprDefaultConstructor : 1; - - /// True when this class contains at least one non-static data - /// member or base class of non-literal or volatile type. - unsigned HasNonLiteralTypeFieldsOrBases : 1; - - /// True when visible conversion functions are already computed - /// and are available. - unsigned ComputedVisibleConversions : 1; - - /// Whether we have a C++11 user-provided default constructor (not - /// explicitly deleted or defaulted). - unsigned UserProvidedDefaultConstructor : 1; - - /// The special members which have been declared for this class, - /// either by the user or implicitly. - unsigned DeclaredSpecialMembers : 6; - - /// Whether an implicit copy constructor could have a const-qualified - /// parameter, for initializing virtual bases and for other subobjects. - unsigned ImplicitCopyConstructorCanHaveConstParamForVBase : 1; - unsigned ImplicitCopyConstructorCanHaveConstParamForNonVBase : 1; - - /// Whether an implicit copy assignment operator would have a - /// const-qualified parameter. - unsigned ImplicitCopyAssignmentHasConstParam : 1; - - /// Whether any declared copy constructor has a const-qualified - /// parameter. - unsigned HasDeclaredCopyConstructorWithConstParam : 1; - - /// Whether any declared copy assignment operator has either a - /// const-qualified reference parameter or a non-reference parameter. - unsigned HasDeclaredCopyAssignmentWithConstParam : 1; + #define FIELD(Name, Width, Merge) \ + unsigned Name : Width; + #include "CXXRecordDeclDefinitionBits.def" /// Whether this class describes a C++ lambda. unsigned IsLambda : 1; @@ -530,6 +287,10 @@ class CXXRecordDecl : public RecordDecl { /// Whether we are currently parsing base specifiers. unsigned IsParsingBaseSpecifiers : 1; + /// True when visible conversion functions are already computed + /// and are available. + unsigned ComputedVisibleConversions : 1; + unsigned HasODRHash : 1; /// A hash of parts of the class to help in ODR checking. @@ -628,9 +389,12 @@ class CXXRecordDecl : public RecordDecl { /// The number of explicit captures in this lambda. unsigned NumExplicitCaptures : 13; + /// Has known `internal` linkage. + unsigned HasKnownInternalLinkage : 1; + /// The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. - unsigned ManglingNumber = 0; + unsigned ManglingNumber : 31; /// The declaration that provides context for this lambda, if the /// actual DeclContext does not suffice. This is used for lambdas that @@ -645,12 +409,12 @@ class CXXRecordDecl : public RecordDecl { /// The type of the call method. TypeSourceInfo *MethodTyInfo; - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, - bool Dependent, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) - : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), - CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), - MethodTyInfo(Info) { + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent, + bool IsGeneric, LambdaCaptureDefault CaptureDefault) + : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), + CaptureDefault(CaptureDefault), NumCaptures(0), + NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0), + MethodTyInfo(Info) { IsLambda = true; // C++1z [expr.prim.lambda]p4: @@ -1214,6 +978,10 @@ public: /// if this is a closure type. CXXMethodDecl *getLambdaCallOperator() const; + /// Retrieve the dependent lambda call operator of the closure type + /// if this is a templated closure type. + FunctionTemplateDecl *getDependentLambdaCallOperator() const; + /// Retrieve the lambda static invoker, the address of which /// is returned by the conversion operator, and the body of which /// is forwarded to the lambda call operator. @@ -1398,7 +1166,8 @@ public: /// would be constexpr. bool defaultedDefaultConstructorIsConstexpr() const { return data().DefaultedDefaultConstructorIsConstexpr && - (!isUnion() || hasInClassInitializer() || !hasVariantMembers()); + (!isUnion() || hasInClassInitializer() || !hasVariantMembers() || + getASTContext().getLangOpts().CPlusPlus2a); } /// Determine whether this class has a constexpr default constructor. @@ -1486,6 +1255,16 @@ public: !(data().HasTrivialSpecialMembers & SMF_MoveAssignment)); } + /// Determine whether a defaulted default constructor for this class + /// would be constexpr. + bool defaultedDestructorIsConstexpr() const { + return data().DefaultedDestructorIsConstexpr && + getASTContext().getLangOpts().CPlusPlus2a; + } + + /// Determine whether this class has a constexpr destructor. + bool hasConstexprDestructor() const; + /// Determine whether this class has a trivial destructor /// (C++ [class.dtor]p3) bool hasTrivialDestructor() const { @@ -1577,8 +1356,10 @@ public: /// /// Only in C++17 and beyond, are lambdas literal types. bool isLiteral() const { - return hasTrivialDestructor() && - (!isLambda() || getASTContext().getLangOpts().CPlusPlus17) && + ASTContext &Ctx = getASTContext(); + return (Ctx.getLangOpts().CPlusPlus2a ? hasConstexprDestructor() + : hasTrivialDestructor()) && + (!isLambda() || Ctx.getLangOpts().CPlusPlus17) && !hasNonLiteralTypeFieldsOrBases() && (isAggregate() || isLambda() || hasConstexprNonCopyMoveConstructor() || @@ -1927,6 +1708,13 @@ public: return getLambdaData().ManglingNumber; } + /// The lambda is known to has internal linkage no matter whether it has name + /// mangling number. + bool hasKnownLambdaInternalLinkage() const { + assert(isLambda() && "Not a lambda closure type!"); + return getLambdaData().HasKnownInternalLinkage; + } + /// Retrieve the declaration that provides additional context for a /// lambda, when the normal declaration context is not specific enough. /// @@ -1940,9 +1728,12 @@ public: /// Set the mangling number and context declaration for a lambda /// class. - void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) { + void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl, + bool HasKnownInternalLinkage = false) { + assert(isLambda() && "Not a lambda closure type!"); getLambdaData().ManglingNumber = ManglingNumber; getLambdaData().ContextDecl = ContextDecl; + getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage; } /// Returns the inheritance model used for this record. @@ -2265,7 +2056,7 @@ public: const CXXRecordDecl *Decl); Qualifiers getMethodQualifiers() const { - return getType()->getAs<FunctionProtoType>()->getMethodQuals(); + return getType()->castAs<FunctionProtoType>()->getMethodQuals(); } /// Retrieve the ref-qualifier associated with this method. @@ -2280,7 +2071,7 @@ public: /// }; /// @endcode RefQualifierKind getRefQualifier() const { - return getType()->getAs<FunctionProtoType>()->getRefQualifier(); + return getType()->castAs<FunctionProtoType>()->getRefQualifier(); } bool hasInlineBody() const; @@ -2600,9 +2391,9 @@ class CXXConstructorDecl final ExplicitSpecifier getExplicitSpecifierInternal() const { if (CXXConstructorDeclBits.HasTrailingExplicitSpecifier) - return *getCanonicalDecl()->getTrailingObjects<ExplicitSpecifier>(); + return *getTrailingObjects<ExplicitSpecifier>(); return ExplicitSpecifier( - nullptr, getCanonicalDecl()->CXXConstructorDeclBits.IsSimpleExplicit + nullptr, CXXConstructorDeclBits.IsSimpleExplicit ? ExplicitSpecKind::ResolvedTrue : ExplicitSpecKind::ResolvedFalse); } @@ -2643,10 +2434,10 @@ public: InheritedConstructor Inherited = InheritedConstructor()); ExplicitSpecifier getExplicitSpecifier() { - return getExplicitSpecifierInternal(); + return getCanonicalDecl()->getExplicitSpecifierInternal(); } const ExplicitSpecifier getExplicitSpecifier() const { - return getExplicitSpecifierInternal(); + return getCanonicalDecl()->getExplicitSpecifierInternal(); } /// Return true if the declartion is already resolved to be explicit. @@ -2847,9 +2638,9 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, - bool isImplicitlyDeclared) + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, CSK_unspecified, SourceLocation()) { + SC_None, isInline, ConstexprKind, SourceLocation()) { setImplicit(isImplicitlyDeclared); } @@ -2859,9 +2650,9 @@ public: static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo* TInfo, - bool isInline, - bool isImplicitlyDeclared); + QualType T, TypeSourceInfo *TInfo, + bool isInline, bool isImplicitlyDeclared, + ConstexprSpecKind ConstexprKind); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); @@ -2934,7 +2725,7 @@ public: /// Returns the type that this conversion function is converting to. QualType getConversionType() const { - return getType()->getAs<FunctionType>()->getReturnType(); + return getType()->castAs<FunctionType>()->getReturnType(); } /// Determine whether this conversion function is a conversion from @@ -2971,8 +2762,10 @@ public: /// ensure a stable ABI for this, we choose the DW_LANG_ encodings /// from the dwarf standard. enum LanguageIDs { - lang_c = /* DW_LANG_C */ 0x0002, - lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 + lang_c = llvm::dwarf::DW_LANG_C, + lang_cxx = llvm::dwarf::DW_LANG_C_plus_plus, + lang_cxx_11 = llvm::dwarf::DW_LANG_C_plus_plus_11, + lang_cxx_14 = llvm::dwarf::DW_LANG_C_plus_plus_14 }; private: @@ -3469,12 +3262,6 @@ public: return IsVirtual; } - /// Get the constructor or constructor template in the derived class - /// correspnding to this using shadow declaration, if it has been implicitly - /// declared already. - CXXConstructorDecl *getConstructor() const; - void setConstructor(NamedDecl *Ctor); - static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ConstructorUsingShadow; } }; diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 235b31c1c312..ec14adc7de97 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -168,6 +168,16 @@ public: return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr; } + /// \brief All associated constraints derived from this template parameter + /// list, including the requires clause and any constraints derived from + /// constrained-parameters. + /// + /// The constraints in the resulting list are to be treated as if in a + /// conjunction ("and"). + void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const; + + bool hasAssociatedConstraints() const; + SourceLocation getTemplateLoc() const { return TemplateLoc; } SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } @@ -369,33 +379,7 @@ public: // Kinds of Templates //===----------------------------------------------------------------------===// -/// Stores the template parameter list and associated constraints for -/// \c TemplateDecl objects that track associated constraints. -class ConstrainedTemplateDeclInfo { - friend TemplateDecl; - -public: - ConstrainedTemplateDeclInfo() = default; - - TemplateParameterList *getTemplateParameters() const { - return TemplateParams; - } - - Expr *getAssociatedConstraints() const { return AssociatedConstraints; } - -protected: - void setTemplateParameters(TemplateParameterList *TParams) { - TemplateParams = TParams; - } - - void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; } - - TemplateParameterList *TemplateParams = nullptr; - Expr *AssociatedConstraints = nullptr; -}; - - -/// The base class of all kinds of template declarations (e.g., +/// \brief The base class of all kinds of template declarations (e.g., /// class, function, etc.). /// /// The TemplateDecl class stores the list of template parameters and a @@ -404,54 +388,32 @@ class TemplateDecl : public NamedDecl { void anchor() override; protected: + // Construct a template decl with name, parameters, and templated element. + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl); + // Construct a template decl with the given name and parameters. // Used when there is no templated element (e.g., for tt-params). - TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), - TemplateParams(CTDI) { - this->setTemplateParameters(Params); - } - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) - : TemplateDecl(nullptr, DK, DC, L, Name, Params) {} - - // Construct a template decl with name, parameters, and templated element. - TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), - TemplateParams(CTDI) { - this->setTemplateParameters(Params); - } - - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {} + : TemplateDecl(DK, DC, L, Name, Params, nullptr) {} public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { - const auto *const CTDI = - TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>(); - return CTDI ? CTDI->getTemplateParameters() - : TemplateParams.get<TemplateParameterList *>(); + return TemplateParams; } - /// Get the constraint-expression from the associated requires-clause (if any) - const Expr *getRequiresClause() const { - const TemplateParameterList *const TP = getTemplateParameters(); - return TP ? TP->getRequiresClause() : nullptr; - } + /// \brief Get the total constraint-expression associated with this template, + /// including constraint-expressions derived from the requires-clause, + /// trailing requires-clause (for functions and methods) and constrained + /// template parameters. + void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const; - Expr *getAssociatedConstraints() const { - const auto *const C = cast<TemplateDecl>(getCanonicalDecl()); - const auto *const CTDI = - C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>(); - return CTDI ? CTDI->getAssociatedConstraints() : nullptr; - } + bool hasAssociatedConstraints() const; /// Get the underlying, templated declaration. NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } @@ -470,29 +432,10 @@ public: protected: NamedDecl *TemplatedDecl; - - /// The template parameter list and optional requires-clause - /// associated with this declaration; alternatively, a - /// \c ConstrainedTemplateDeclInfo if the associated constraints of the - /// template are being tracked by this particular declaration. - llvm::PointerUnion<TemplateParameterList *, - ConstrainedTemplateDeclInfo *> - TemplateParams; + TemplateParameterList *TemplateParams; void setTemplateParameters(TemplateParameterList *TParams) { - if (auto *const CTDI = - TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) { - CTDI->setTemplateParameters(TParams); - } else { - TemplateParams = TParams; - } - } - - void setAssociatedConstraints(Expr *AC) { - assert(isCanonicalDecl() && - "Attaching associated constraints to non-canonical Decl"); - TemplateParams.get<ConstrainedTemplateDeclInfo *>() - ->setAssociatedConstraints(AC); + TemplateParams = TParams; } public: @@ -889,17 +832,10 @@ protected: virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. - RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, - ASTContext &C, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C) - {} - RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {} + : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C) {} public: friend class ASTDeclReader; @@ -2026,6 +1962,20 @@ public: return TemplateParams; } + /// \brief All associated constraints of this partial specialization, + /// including the requires clause and any constraints derived from + /// constrained-parameters. + /// + /// The constraints in the resulting list are to be treated as if in a + /// conjunction ("and"). + void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { + TemplateParams->getAssociatedConstraints(AC); + } + + bool hasAssociatedConstraints() const { + return TemplateParams->hasAssociatedConstraints(); + } + /// Get the template arguments as written. const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { return ArgsAsWritten; @@ -2145,16 +2095,10 @@ protected: llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> & getPartialSpecializations(); - ClassTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, ASTContext &C, - DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : RedeclarableTemplateDecl(CTDI, ClassTemplate, C, DC, L, Name, Params, - Decl) {} - ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {} + : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {} CommonBase *newCommon(ASTContext &C) const override; @@ -2180,14 +2124,12 @@ public: return getTemplatedDecl()->isThisDeclarationADefinition(); } - // FIXME: remove default argument for AssociatedConstraints - /// Create a class template node. + /// \brief Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl, - Expr *AssociatedConstraints = nullptr); + NamedDecl *Decl); /// Create an empty class template node. static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2527,10 +2469,6 @@ public: } }; -/// Implementation of inline functions that require the template declarations -inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) - : Function(FTD) {} - /// Represents a variable template specialization, which refers to /// a variable template with a given set of template arguments. /// @@ -2866,7 +2804,21 @@ public: return ArgsAsWritten; } - /// Retrieve the member variable template partial specialization from + /// \brief All associated constraints of this partial specialization, + /// including the requires clause and any constraints derived from + /// constrained-parameters. + /// + /// The constraints in the resulting list are to be treated as if in a + /// conjunction ("and"). + void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { + TemplateParams->getAssociatedConstraints(AC); + } + + bool hasAssociatedConstraints() const { + return TemplateParams->hasAssociatedConstraints(); + } + + /// \brief Retrieve the member variable template partial specialization from /// which this particular variable template partial specialization was /// instantiated. /// @@ -3095,11 +3047,9 @@ class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> { protected: Expr *ConstraintExpr; - ConceptDecl(DeclContext *DC, - SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, - Expr *ConstraintExpr) - : TemplateDecl(nullptr, Concept, DC, L, Name, Params), + ConceptDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, Expr *ConstraintExpr) + : TemplateDecl(Concept, DC, L, Name, Params), ConstraintExpr(ConstraintExpr) {}; public: static ConceptDecl *Create(ASTContext &C, DeclContext *DC, diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d44a815c8699..ffa7d4db96a4 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -906,6 +906,11 @@ public: return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); } + /// Checks that the two Expr's will refer to the same value as a comparison + /// operand. The caller must ensure that the values referenced by the Expr's + /// are not modified between E1 and E2 or the result my be invalid. + static bool isSameComparisonOperand(const Expr* E1, const Expr* E2); + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && T->getStmtClass() <= lastExprConstant; @@ -2619,9 +2624,8 @@ public: /// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr): /// /// \code{.cpp} - /// llvm::AlignedCharArray<alignof(CallExpr), - /// sizeof(CallExpr) + sizeof(Stmt *)> Buffer; - /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.buffer, etc); + /// alignas(CallExpr) char Buffer[sizeof(CallExpr) + sizeof(Stmt *)]; + /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer, etc); /// \endcode static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, @@ -4496,6 +4500,8 @@ public: // Explicit InitListExpr's originate from source code (and have valid source // locations). Implicit InitListExpr's are created by the semantic analyzer. + // FIXME: This is wrong; InitListExprs created by semantic analysis have + // valid source locations too! bool isExplicit() const { return LBraceLoc.isValid() && RBraceLoc.isValid(); } @@ -4830,6 +4836,10 @@ public: SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; } + /// Whether this designated initializer should result in direct-initialization + /// of the designated subobject (eg, '{.foo{1, 2, 3}}'). + bool isDirectInit() const { return EqualOrColonLoc.isInvalid(); } + /// Determines whether this designated initializer used the /// deprecated GNU syntax for designated initializers. bool usesGNUSyntax() const { return GNUSyntax; } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 28ed6cdfde14..2152e108c7cb 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -17,6 +17,7 @@ #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/Expr.h" #include "clang/AST/NestedNameSpecifier.h" @@ -185,15 +186,20 @@ public: static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, EmptyShell Empty); - /// Retrieves the implicit object argument for the member call. + /// Retrieve the implicit object argument for the member call. /// /// For example, in "x.f(5)", this returns the sub-expression "x". Expr *getImplicitObjectArgument() const; - /// Retrieves the declaration of the called method. + /// Retrieve the type of the object argument. + /// + /// Note that this always returns a non-pointer type. + QualType getObjectType() const; + + /// Retrieve the declaration of the called method. CXXMethodDecl *getMethodDecl() const; - /// Retrieves the CXXRecordDecl for the underlying type of + /// Retrieve the CXXRecordDecl for the underlying type of /// the implicit object argument. /// /// Note that this is may not be the same declaration as that of the class @@ -248,6 +254,96 @@ public: } }; +/// A rewritten comparison expression that was originally written using +/// operator syntax. +/// +/// In C++20, the following rewrites are performed: +/// - <tt>a == b</tt> -> <tt>b == a</tt> +/// - <tt>a != b</tt> -> <tt>!(a == b)</tt> +/// - <tt>a != b</tt> -> <tt>!(b == a)</tt> +/// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>: +/// - <tt>a @ b</tt> -> <tt>(a <=> b) @ 0</tt> +/// - <tt>a @ b</tt> -> <tt>0 @ (b <=> a)</tt> +/// +/// This expression provides access to both the original syntax and the +/// rewritten expression. +/// +/// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically +/// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators. +class CXXRewrittenBinaryOperator : public Expr { + friend class ASTStmtReader; + + /// The rewritten semantic form. + Stmt *SemanticForm; + +public: + CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed) + : Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(), + SemanticForm->getValueKind(), SemanticForm->getObjectKind(), + SemanticForm->isTypeDependent(), SemanticForm->isValueDependent(), + SemanticForm->isInstantiationDependent(), + SemanticForm->containsUnexpandedParameterPack()), + SemanticForm(SemanticForm) { + CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed; + } + CXXRewrittenBinaryOperator(EmptyShell Empty) + : Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {} + + /// Get an equivalent semantic form for this expression. + Expr *getSemanticForm() { return cast<Expr>(SemanticForm); } + const Expr *getSemanticForm() const { return cast<Expr>(SemanticForm); } + + struct DecomposedForm { + /// The original opcode, prior to rewriting. + BinaryOperatorKind Opcode; + /// The original left-hand side. + const Expr *LHS; + /// The original right-hand side. + const Expr *RHS; + /// The inner \c == or \c <=> operator expression. + const Expr *InnerBinOp; + }; + + /// Decompose this operator into its syntactic form. + DecomposedForm getDecomposedForm() const LLVM_READONLY; + + /// Determine whether this expression was rewritten in reverse form. + bool isReversed() const { return CXXRewrittenBinaryOperatorBits.IsReversed; } + + BinaryOperatorKind getOperator() const { return getDecomposedForm().Opcode; } + const Expr *getLHS() const { return getDecomposedForm().LHS; } + const Expr *getRHS() const { return getDecomposedForm().RHS; } + + SourceLocation getOperatorLoc() const LLVM_READONLY { + return getDecomposedForm().InnerBinOp->getExprLoc(); + } + SourceLocation getExprLoc() const LLVM_READONLY { return getOperatorLoc(); } + + /// Compute the begin and end locations from the decomposed form. + /// The locations of the semantic form are not reliable if this is + /// a reversed expression. + //@{ + SourceLocation getBeginLoc() const LLVM_READONLY { + return getDecomposedForm().LHS->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { + return getDecomposedForm().RHS->getEndLoc(); + } + SourceRange getSourceRange() const LLVM_READONLY { + DecomposedForm DF = getDecomposedForm(); + return SourceRange(DF.LHS->getBeginLoc(), DF.RHS->getEndLoc()); + } + //@} + + child_range children() { + return child_range(&SemanticForm, &SemanticForm + 1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXRewrittenBinaryOperatorClass; + } +}; + /// Abstract class common to all of the C++ "named"/"keyword" casts. /// /// This abstract class is inherited by all of the classes @@ -1902,6 +1998,10 @@ public: /// lambda expression. CXXMethodDecl *getCallOperator() const; + /// Retrieve the function template call operator associated with this + /// lambda expression. + FunctionTemplateDecl *getDependentCallOperator() const; + /// If this is a generic lambda expression, retrieve the template /// parameter list associated with it, or else return null. TemplateParameterList *getTemplateParameterList() const; @@ -2091,8 +2191,7 @@ public: bool IsParenTypeId); QualType getAllocatedType() const { - assert(getType()->isPointerType()); - return getType()->getAs<PointerType>()->getPointeeType(); + return getType()->castAs<PointerType>()->getPointeeType(); } TypeSourceInfo *getAllocatedTypeSourceInfo() const { @@ -2270,8 +2369,8 @@ 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, false, - Arg->isInstantiationDependent(), + : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false, + Arg->isValueDependent(), Arg->isInstantiationDependent(), Arg->containsUnexpandedParameterPack()), OperatorDelete(OperatorDelete), Argument(Arg) { CXXDeleteExprBits.GlobalDelete = GlobalDelete; @@ -4335,9 +4434,6 @@ private: }; llvm::PointerUnion<Stmt *, ExtraState *> State; - void initializeExtraState(const ValueDecl *ExtendedBy, - unsigned ManglingNumber); - public: MaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference) @@ -4745,6 +4841,125 @@ 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, + private llvm::TrailingObjects<ConceptSpecializationExpr, + TemplateArgument> { + friend class ASTStmtReader; + friend TrailingObjects; + + // \brief The optional nested name specifier used when naming the concept. + NestedNameSpecifierLoc NestedNameSpec; + + /// \brief The location of the template keyword, if specified when naming the + /// concept. + SourceLocation TemplateKWLoc; + + /// \brief The location of the concept name in the expression. + SourceLocation ConceptNameLoc; + + /// \brief The declaration found by name lookup when the expression was + /// created. + /// Can differ from NamedConcept when, for example, the concept was found + /// through a UsingShadowDecl. + NamedDecl *FoundDecl; + + /// \brief The concept named, and whether or not the concept with the given + /// arguments was satisfied when the expression was created. + /// If any of the template arguments are dependent (this expr would then be + /// isValueDependent()), this bit is to be ignored. + llvm::PointerIntPair<ConceptDecl *, 1, bool> NamedConcept; + + /// \brief The template argument list source info used to specialize the + /// concept. + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; + + /// \brief The number of template arguments in the tail-allocated list of + /// converted template arguments. + unsigned NumTemplateArgs; + + ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, + SourceLocation ConceptNameLoc, NamedDecl *FoundDecl, + ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef<TemplateArgument> ConvertedArgs, + Optional<bool> IsSatisfied); + + ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); + +public: + + static ConceptSpecializationExpr * + Create(ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied); + + static ConceptSpecializationExpr * + Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return NestedNameSpec; + } + + NamedDecl *getFoundDecl() const { + return FoundDecl; + } + + ConceptDecl *getNamedConcept() const { + return NamedConcept.getPointer(); + } + + ArrayRef<TemplateArgument> getTemplateArguments() const { + return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(), + NumTemplateArgs); + } + + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ArgsAsWritten; + } + + /// \brief Set new template arguments for this concept specialization. + void setTemplateArguments(const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef<TemplateArgument> Converted); + + /// \brief Whether or not the concept with the given arguments was satisfied + /// when the expression was created. This method assumes that the expression + /// is not dependent! + bool isSatisfied() const { + assert(!isValueDependent() + && "isSatisfied called on a dependent ConceptSpecializationExpr"); + return NamedConcept.getInt(); + } + + SourceLocation getConceptNameLoc() const { return ConceptNameLoc; } + + SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConceptSpecializationExprClass; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return ConceptNameLoc; } + 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/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h index d89189da04f0..0230495a5ef3 100644 --- a/include/clang/AST/ExternalASTMerger.h +++ b/include/clang/AST/ExternalASTMerger.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_EXTERNALASTMERGER_H #include "clang/AST/ASTImporter.h" +#include "clang/AST/ASTImporterSharedState.h" #include "clang/AST/ExternalASTSource.h" #include "llvm/Support/raw_ostream.h" @@ -22,7 +23,7 @@ namespace clang { /// ExternalASTSource implementation that merges information from several /// ASTContexts. /// -/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import +/// ExternalASTMerger maintains a vector of ASTImporters that it uses to import /// (potentially incomplete) Decls and DeclContexts from the source ASTContexts /// in response to ExternalASTSource API calls. /// @@ -36,7 +37,7 @@ namespace clang { /// lookup. In this case, Origins contains an entry overriding lookup and /// specifying the correct pair of DeclContext/ASTContext. /// -/// - The DeclContext of origin was determined by another ExterenalASTMerger. +/// - The DeclContext of origin was determined by another ExternalASTMerger. /// (This is possible when the source ASTContext for one of the Importers has /// its own ExternalASTMerger). The origin must be properly forwarded in this /// case. @@ -79,20 +80,47 @@ public: /// import SourceLocations properly. Additionally, when import occurs for /// a DeclContext whose origin has been overridden, then this /// ExternalASTMerger must be able to determine that. - struct ImporterSource { + class ImporterSource { ASTContext &AST; FileManager &FM; const OriginMap &OM; + /// True iff the source only exists temporary, i.e., it will be removed from + /// the ExternalASTMerger during the life time of the ExternalASTMerger. + bool Temporary; + /// If the ASTContext of this source has an ExternalASTMerger that imports + /// into this source, then this will point to that other ExternalASTMerger. + ExternalASTMerger *Merger; + + public: + ImporterSource(ASTContext &AST, FileManager &FM, const OriginMap &OM, + bool Temporary = false, ExternalASTMerger *Merger = nullptr) + : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {} + ASTContext &getASTContext() const { return AST; } + FileManager &getFileManager() const { return FM; } + const OriginMap &getOriginMap() const { return OM; } + bool isTemporary() const { return Temporary; } + ExternalASTMerger *getMerger() const { return Merger; } }; private: - /// The target for this ExtenralASTMerger. + /// The target for this ExternalASTMerger. ImporterTarget Target; + /// ExternalASTMerger has multiple ASTImporters that import into the same + /// TU. This is the shared state for all ASTImporters of this + /// ExternalASTMerger. + /// See also the CrossTranslationUnitContext that has a similar setup. + std::shared_ptr<ASTImporterSharedState> SharedState; public: ExternalASTMerger(const ImporterTarget &Target, llvm::ArrayRef<ImporterSource> Sources); + /// Asks all connected ASTImporters if any of them imported the given + /// declaration. If any ASTImporter did import the given declaration, + /// then this function returns the declaration that D was imported from. + /// Returns nullptr if no ASTImporter did import import D. + Decl *FindOriginalDecl(Decl *D); + /// Add a set of ASTContexts as possible origins. /// /// Usually the set will be initialized in the constructor, but long-lived @@ -145,7 +173,7 @@ public: /// OriginContext. bool HasImporterForOrigin(ASTContext &OriginContext); - /// Returns a reference to the ASTRImporter from Importers whose origin + /// Returns a reference to the ASTImporter from Importers whose origin /// is OriginContext. This allows manual import of ASTs while preserving the /// OriginMap correctly. ASTImporter &ImporterForOrigin(ASTContext &OriginContext); diff --git a/include/clang/AST/FormatString.h b/include/clang/AST/FormatString.h index 643fb822f7f4..8c944451f796 100644 --- a/include/clang/AST/FormatString.h +++ b/include/clang/AST/FormatString.h @@ -251,7 +251,21 @@ public: enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, AnyCharTy, CStrTy, WCStrTy, WIntTy }; - enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic }; + /// How well a given conversion specifier matches its argument. + enum MatchKind { + /// The conversion specifier and the argument types are incompatible. For + /// instance, "%d" and float. + NoMatch = 0, + /// The conversion specifier and the argument type are compatible. For + /// instance, "%d" and _Bool. + Match = 1, + /// The conversion specifier and the argument type are disallowed by the C + /// standard, but are in practice harmless. For instance, "%p" and int*. + NoMatchPedantic, + /// The conversion specifier and the argument type are compatible, but still + /// seems likely to be an error. For instance, "%hd" and _Bool. + NoMatchTypeConfusion, + }; private: const Kind K; @@ -748,6 +762,12 @@ bool ParseScanfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target); +/// Return true if the given string has at least one formatting specifier. +bool parseFormatStringHasFormattingSpecifiers(const char *Begin, + const char *End, + const LangOptions &LO, + const TargetInfo &Target); + } // end analyze_format_string namespace } // end clang namespace #endif diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h index 86fd0f6aa907..145e961a23a3 100644 --- a/include/clang/AST/GlobalDecl.h +++ b/include/clang/AST/GlobalDecl.h @@ -59,6 +59,7 @@ public: GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl *D) { Init(D); } GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } + GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); } GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} GlobalDecl(const VarDecl *D, DynamicInitKind StubKind) diff --git a/include/clang/AST/JSONNodeDumper.h b/include/clang/AST/JSONNodeDumper.h index 238e43aad78b..5f34440b8b56 100644 --- a/include/clang/AST/JSONNodeDumper.h +++ b/include/clang/AST/JSONNodeDumper.h @@ -141,6 +141,8 @@ class JSONNodeDumper JOS.attribute(Key, Value); } + void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false); + // Writes the attributes of a SourceLocation object without. void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling); diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index b1fbe936136a..5db5c5b977da 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -56,7 +56,7 @@ private: llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds; llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds; - llvm::DenseMap<const TagDecl*, uint64_t> AnonStructIds; + llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds; public: ManglerKind getKind() const { return Kind; } @@ -82,9 +82,9 @@ public: return Result.first->second; } - uint64_t getAnonymousStructId(const TagDecl *TD) { - std::pair<llvm::DenseMap<const TagDecl *, uint64_t>::iterator, bool> - Result = AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); + uint64_t getAnonymousStructId(const NamedDecl *D) { + std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool> + Result = AnonStructIds.insert(std::make_pair(D, AnonStructIds.size())); return Result.first->second; } @@ -170,6 +170,8 @@ public: virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) = 0; + virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0; + static bool classof(const MangleContext *C) { return C->getKind() == MK_Itanium; } @@ -248,8 +250,16 @@ class ASTNameGenerator { public: explicit ASTNameGenerator(ASTContext &Ctx); ~ASTNameGenerator(); + + /// Writes name for \p D to \p OS. + /// \returns true on failure, false on success. bool writeName(const Decl *D, raw_ostream &OS); + + /// \returns name for \p D std::string getName(const Decl *D); + + /// \returns all applicable mangled names. + /// For example C++ constructors/destructors can have multiple. std::vector<std::string> getAllManglings(const Decl *D); private: diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index 21f0c5458d81..a8bd2d0f17e6 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -55,9 +55,6 @@ public: /// The Objective-C NSString selectors. Selector getNSStringSelector(NSStringMethodKind MK) const; - /// Return NSStringMethodKind if \param Sel is such a selector. - Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const; - /// Returns true if the expression \param E is a reference of /// "NSUTF8StringEncoding" enum constant. bool isNSUTF8StringEncodingConstant(const Expr *E) const { diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index eadcc62a3457..b2a2035dcb3c 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -519,7 +519,7 @@ public: /// \endcode /// In this example directive '#pragma omp task' has simple 'final' /// clause with condition 'a > 5'. -class OMPFinalClause : public OMPClause { +class OMPFinalClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// Location of '('. @@ -534,18 +534,25 @@ class OMPFinalClause : public OMPClause { public: /// Build 'final' clause with condition \a Cond. /// + /// \param Cond Condition of the clause. + /// \param HelperCond Helper condition for the construct. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. - /// \param Cond Condition of the clause. /// \param EndLoc Ending location of the clause. - OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc), - Condition(Cond) {} + OMPFinalClause(Expr *Cond, Stmt *HelperCond, + OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_final, StartLoc, EndLoc), OMPClauseWithPreInit(this), + LParenLoc(LParenLoc), Condition(Cond) { + setPreInitStmt(HelperCond, CaptureRegion); + } /// Build an empty clause. OMPFinalClause() - : OMPClause(OMPC_final, SourceLocation(), SourceLocation()) {} + : OMPClause(OMPC_final, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -562,11 +569,10 @@ public: return const_child_range(&Condition, &Condition + 1); } - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } + child_range used_children(); const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPFinalClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { @@ -2099,10 +2105,12 @@ public: } child_range used_children() { - return child_range(child_iterator(), child_iterator()); + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPFirstprivateClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { @@ -2616,10 +2624,12 @@ public: } child_range used_children() { - return child_range(child_iterator(), child_iterator()); + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); } const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPReductionClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { @@ -3212,6 +3222,14 @@ class OMPLinearClause final return llvm::makeArrayRef(getUpdates().end(), varlist_size()); } + /// Gets the list of used expressions for linear variables. + MutableArrayRef<Expr *> getUsedExprs() { + return MutableArrayRef<Expr *>(getFinals().end() + 2, varlist_size() + 1); + } + ArrayRef<const Expr *> getUsedExprs() const { + return llvm::makeArrayRef(getFinals().end() + 2, varlist_size() + 1); + } + /// Sets the list of the copies of original linear variables. /// \param PL List of expressions. void setPrivates(ArrayRef<Expr *> PL); @@ -3291,6 +3309,9 @@ public: /// \param FL List of expressions. void setFinals(ArrayRef<Expr *> FL); + /// Sets the list of used expressions for the linear clause. + void setUsedExprs(ArrayRef<Expr *> UE); + using privates_iterator = MutableArrayRef<Expr *>::iterator; using privates_const_iterator = ArrayRef<const Expr *>::iterator; using privates_range = llvm::iterator_range<privates_iterator>; @@ -3343,6 +3364,21 @@ public: return finals_const_range(getFinals().begin(), getFinals().end()); } + using used_expressions_iterator = MutableArrayRef<Expr *>::iterator; + using used_expressions_const_iterator = ArrayRef<const Expr *>::iterator; + using used_expressions_range = + llvm::iterator_range<used_expressions_iterator>; + using used_expressions_const_range = + llvm::iterator_range<used_expressions_const_iterator>; + + used_expressions_range used_expressions() { + return finals_range(getUsedExprs().begin(), getUsedExprs().end()); + } + + used_expressions_const_range used_expressions() const { + return finals_const_range(getUsedExprs().begin(), getUsedExprs().end()); + } + child_range children() { return child_range(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); @@ -3353,11 +3389,11 @@ public: return const_child_range(Children.begin(), Children.end()); } - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } + child_range used_children(); + const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPLinearClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { @@ -4995,12 +5031,17 @@ public: } child_range used_children() { + if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_tofrom) + return child_range(reinterpret_cast<Stmt **>(varlist_begin()), + reinterpret_cast<Stmt **>(varlist_end())); return child_range(child_iterator(), child_iterator()); } const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPMapClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_map; } @@ -5165,7 +5206,7 @@ public: /// \endcode /// In this example directive '#pragma omp teams' has clause 'priority' with /// single expression 'n'. -class OMPPriorityClause : public OMPClause { +class OMPPriorityClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// Location of '('. @@ -5182,18 +5223,25 @@ class OMPPriorityClause : public OMPClause { public: /// Build 'priority' clause. /// - /// \param E Expression associated with this clause. + /// \param Priority Expression associated with this clause. + /// \param HelperPriority Helper priority for the construct. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc) - : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc), - Priority(E) {} + OMPPriorityClause(Expr *Priority, Stmt *HelperPriority, + OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_priority, StartLoc, EndLoc), OMPClauseWithPreInit(this), + LParenLoc(LParenLoc), Priority(Priority) { + setPreInitStmt(HelperPriority, CaptureRegion); + } /// Build an empty clause. OMPPriorityClause() - : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()) {} + : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -5213,11 +5261,10 @@ public: return const_child_range(&Priority, &Priority + 1); } - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } + child_range used_children(); const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPPriorityClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { @@ -5233,7 +5280,7 @@ public: /// \endcode /// In this example directive '#pragma omp taskloop' has clause 'grainsize' /// with single expression '4'. -class OMPGrainsizeClause : public OMPClause { +class OMPGrainsizeClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// Location of '('. @@ -5249,16 +5296,23 @@ public: /// Build 'grainsize' clause. /// /// \param Size Expression associated with this clause. + /// \param HelperSize Helper grainsize for the construct. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc, + OMPGrainsizeClause(Expr *Size, Stmt *HelperSize, + OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc), - Grainsize(Size) {} + : OMPClause(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(OMPC_grainsize, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -5275,11 +5329,10 @@ public: return const_child_range(&Grainsize, &Grainsize + 1); } - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } + child_range used_children(); const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPGrainsizeClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { @@ -5334,7 +5387,7 @@ public: /// \endcode /// In this example directive '#pragma omp taskloop' has clause 'num_tasks' /// with single expression '4'. -class OMPNumTasksClause : public OMPClause { +class OMPNumTasksClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// Location of '('. @@ -5350,16 +5403,23 @@ public: /// Build 'num_tasks' clause. /// /// \param Size Expression associated with this clause. + /// \param HelperSize Helper grainsize for the construct. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - OMPNumTasksClause(Expr *Size, SourceLocation StartLoc, + OMPNumTasksClause(Expr *Size, Stmt *HelperSize, + OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) - : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc), - NumTasks(Size) {} + : OMPClause(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(OMPC_num_tasks, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this) {} /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } @@ -5376,11 +5436,10 @@ public: return const_child_range(&NumTasks, &NumTasks + 1); } - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } + child_range used_children(); const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast<OMPNumTasksClause *>(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { diff --git a/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def index 9af92c1ae7ff..f29664e8eb33 100644 --- a/include/clang/AST/OperationKinds.def +++ b/include/clang/AST/OperationKinds.def @@ -66,8 +66,9 @@ CAST_OPERATION(BitCast) /// bool b; reinterpret_cast<char&>(b) = 'a'; CAST_OPERATION(LValueBitCast) -/// CK_LValueToRValueBitCast - A conversion that causes us to reinterpret an -/// lvalue as an rvalue of a different type. Created by __builtin_bit_cast. +/// CK_LValueToRValueBitCast - A conversion that causes us to reinterpret the +/// object representation of an lvalue as an rvalue. Created by +/// __builtin_bit_cast. CAST_OPERATION(LValueToRValueBitCast) /// CK_LValueToRValue - A conversion which causes the extraction of diff --git a/include/clang/AST/OptionalDiagnostic.h b/include/clang/AST/OptionalDiagnostic.h new file mode 100644 index 000000000000..c57199f0fdf1 --- /dev/null +++ b/include/clang/AST/OptionalDiagnostic.h @@ -0,0 +1,78 @@ +//===- OptionalDiagnostic.h - An optional diagnostic ------------*- 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 +/// Implements a partial diagnostic which may not be emitted. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H +#define LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H + +#include "clang/AST/APValue.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { + +/// A partial diagnostic which we might know in advance that we are not going +/// to emit. +class OptionalDiagnostic { + PartialDiagnostic *Diag; + +public: + explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) : Diag(Diag) {} + + template <typename T> OptionalDiagnostic &operator<<(const T &v) { + if (Diag) + *Diag << v; + return *this; + } + + OptionalDiagnostic &operator<<(const llvm::APSInt &I) { + if (Diag) { + SmallVector<char, 32> Buffer; + I.toString(Buffer); + *Diag << StringRef(Buffer.data(), Buffer.size()); + } + return *this; + } + + OptionalDiagnostic &operator<<(const llvm::APFloat &F) { + if (Diag) { + // FIXME: Force the precision of the source value down so we don't + // print digits which are usually useless (we don't really care here if + // we truncate a digit by accident in edge cases). Ideally, + // APFloat::toString would automatically print the shortest + // representation which rounds to the correct value, but it's a bit + // tricky to implement. Could use std::to_chars. + unsigned precision = llvm::APFloat::semanticsPrecision(F.getSemantics()); + precision = (precision * 59 + 195) / 196; + SmallVector<char, 32> Buffer; + F.toString(Buffer, precision); + *Diag << StringRef(Buffer.data(), Buffer.size()); + } + return *this; + } + + OptionalDiagnostic &operator<<(const APFixedPoint &FX) { + if (Diag) { + SmallVector<char, 32> Buffer; + FX.toString(Buffer); + *Diag << StringRef(Buffer.data(), Buffer.size()); + } + return *this; + } +}; + +} // namespace clang + +#endif diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 5dc8694e77e9..1eea56dee622 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -10,8 +10,11 @@ #define LLVM_CLANG_AST_RAWCOMMENTLIST_H #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 <map> namespace clang { @@ -196,17 +199,25 @@ public: void addComment(const RawComment &RC, const CommentOptions &CommentOpts, llvm::BumpPtrAllocator &Allocator); - ArrayRef<RawComment *> getComments() const { - return Comments; - } + /// \returns A mapping from an offset of the start of the comment to the + /// comment itself, or nullptr in case there are no comments in \p File. + const std::map<unsigned, RawComment *> *getCommentsInFile(FileID File) const; + + bool empty() const; + + unsigned getCommentBeginLine(RawComment *C, FileID File, + unsigned Offset) const; + unsigned getCommentEndOffset(RawComment *C) const; private: SourceManager &SourceMgr; - std::vector<RawComment *> Comments; - - void addDeserializedComments(ArrayRef<RawComment *> DeserializedComments); + // mapping: FileId -> comment begin offset -> comment + llvm::DenseMap<FileID, std::map<unsigned, RawComment *>> OrderedComments; + mutable llvm::DenseMap<RawComment *, unsigned> CommentBeginLine; + mutable llvm::DenseMap<RawComment *, unsigned> CommentEndOffset; friend class ASTReader; + friend class ASTWriter; }; } // end namespace clang diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 698fba2f4ed1..5b58eab95d60 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -431,7 +431,7 @@ public: // Declare Traverse*() for all concrete Type classes. #define ABSTRACT_TYPE(CLASS, BASE) #define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T); -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. // Define WalkUpFrom*() and empty Visit*() for all Type classes. @@ -444,7 +444,7 @@ public: return true; \ } \ bool Visit##CLASS##Type(CLASS##Type *T) { return true; } -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" // ---- Methods on TypeLocs ---- // FIXME: this currently just calls the matching Type methods @@ -460,7 +460,7 @@ public: bool VisitTypeLoc(TypeLoc TL) { return true; } // QualifiedTypeLoc and UnqualTypeLoc are not declared in - // TypeNodes.def and thus need to be handled specially. + // TypeNodes.inc and thus need to be handled specially. bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); } @@ -478,7 +478,7 @@ public: return true; \ } \ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" // ---- Methods on Decls ---- @@ -676,7 +676,7 @@ bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { #define TYPE(CLASS, BASE) \ case Type::CLASS: \ DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr())); -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" } return true; @@ -722,12 +722,6 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { break; #include "clang/AST/DeclNodes.inc" } - - // Visit any attributes attached to this declaration. - for (auto *I : D->attrs()) { - if (!getDerived().TraverseAttr(I)) - return false; - } return true; } @@ -965,8 +959,11 @@ DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); }) DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); }) -DEF_TRAVERSE_TYPE(ConstantArrayType, - { TRY_TO(TraverseType(T->getElementType())); }) +DEF_TRAVERSE_TYPE(ConstantArrayType, { + TRY_TO(TraverseType(T->getElementType())); + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr()))); +}) DEF_TRAVERSE_TYPE(IncompleteArrayType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -1407,6 +1404,11 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { { CODE; } \ if (ReturnValue && ShouldVisitChildren) \ TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ + if (ReturnValue) { \ + /* Visit any attributes attached to this declaration. */ \ + for (auto *I : D->attrs()) \ + TRY_TO(getDerived().TraverseAttr(I)); \ + } \ if (ReturnValue && getDerived().shouldTraversePostOrder()) \ TRY_TO(WalkUpFrom##DECL(D)); \ return ReturnValue; \ @@ -1631,9 +1633,11 @@ template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( TemplateParameterList *TPL) { if (TPL) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); + for (NamedDecl *D : *TPL) { + TRY_TO(TraverseDecl(D)); + } + if (Expr *RequiresClause = TPL->getRequiresClause()) { + TRY_TO(TraverseStmt(RequiresClause)); } } return true; @@ -2023,11 +2027,18 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { // Constructor initializers. for (auto *I : Ctor->inits()) { - TRY_TO(TraverseConstructorInitializer(I)); + if (I->isWritten() || getDerived().shouldVisitImplicitCode()) + TRY_TO(TraverseConstructorInitializer(I)); } } - if (D->isThisDeclarationADefinition()) { + 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(); + + if (VisitBody) { TRY_TO(TraverseStmt(D->getBody())); // Function body. } return true; @@ -2308,19 +2319,30 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr( return true; } -// This method is called once for each pair of syntactic and semantic -// InitListExpr, and it traverses the subtrees defined by the two forms. This -// may cause some of the children to be visited twice, if they appear both in -// the syntactic and the semantic form. +// If shouldVisitImplicitCode() returns false, this method traverses only the +// syntactic form of InitListExpr. +// If shouldVisitImplicitCode() return true, this method is called once for +// each pair of syntactic and semantic InitListExpr, and it traverses the +// subtrees defined by the two forms. This may cause some of the children to be +// visited twice, if they appear both in the syntactic and the semantic form. // // There is no guarantee about which form \p S takes when this method is called. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseInitListExpr( InitListExpr *S, DataRecursionQueue *Queue) { + if (S->isSemanticForm() && S->isSyntacticForm()) { + // `S` does not have alternative forms, traverse only once. + TRY_TO(TraverseSynOrSemInitListExpr(S, Queue)); + return true; + } TRY_TO(TraverseSynOrSemInitListExpr( S->isSemanticForm() ? S->getSyntacticForm() : S, Queue)); - TRY_TO(TraverseSynOrSemInitListExpr( - S->isSemanticForm() ? S : S->getSemanticForm(), Queue)); + if (getDerived().shouldVisitImplicitCode()) { + // Only visit the semantic form if the clients are interested in implicit + // compiler-generated. + TRY_TO(TraverseSynOrSemInitListExpr( + S->isSemanticForm() ? S : S->getSemanticForm(), Queue)); + } return true; } @@ -2584,6 +2606,15 @@ DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) +DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, { + if (!getDerived().shouldVisitImplicitCode()) { + CXXRewrittenBinaryOperator::DecomposedForm Decomposed = + S->getDecomposedForm(); + TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.LHS))); + TRY_TO(TraverseStmt(const_cast<Expr*>(Decomposed.RHS))); + ShouldVisitChildren = false; + } +}) DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) DEF_TRAVERSE_STMT(TypoExpr, {}) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) @@ -2639,6 +2670,12 @@ DEF_TRAVERSE_STMT(CoyieldExpr, { } }) +DEF_TRAVERSE_STMT(ConceptSpecializationExpr, { + TRY_TO(TraverseTemplateArgumentLocsHelper( + S->getTemplateArgsAsWritten()->getTemplateArgs(), + S->getTemplateArgsAsWritten()->NumTemplateArgs)); +}) + // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, {}) DEF_TRAVERSE_STMT(FixedPointLiteral, {}) @@ -2768,6 +2805,15 @@ DEF_TRAVERSE_STMT(OMPTaskLoopDirective, DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPMasterTaskLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPMasterTaskLoopSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPParallelMasterTaskLoopDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPDistributeDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2826,6 +2872,8 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { #include "clang/Basic/OpenMPKinds.def" case OMPC_threadprivate: case OMPC_uniform: + case OMPC_device_type: + case OMPC_match: case OMPC_unknown: break; } @@ -2870,6 +2918,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getCondition())); return true; } @@ -3240,6 +3289,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause( template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause( OMPPriorityClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getPriority())); return true; } @@ -3247,6 +3297,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause( template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause( OMPGrainsizeClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getGrainsize())); return true; } @@ -3254,6 +3305,7 @@ bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause( template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause( OMPNumTasksClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getNumTasks())); return true; } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 403b88ac3a3c..7aebbf2cb6a3 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -604,6 +604,15 @@ protected: unsigned FPFeatures : 3; }; + class CXXRewrittenBinaryOperatorBitfields { + friend class ASTStmtReader; + friend class CXXRewrittenBinaryOperator; + + unsigned : NumCallExprBits; + + unsigned IsReversed : 1; + }; + class CXXBoolLiteralExprBitfields { friend class CXXBoolLiteralExpr; @@ -978,6 +987,7 @@ protected: // C++ Expressions CXXOperatorCallExprBitfields CXXOperatorCallExprBits; + CXXRewrittenBinaryOperatorBitfields CXXRewrittenBinaryOperatorBits; CXXBoolLiteralExprBitfields CXXBoolLiteralExprBits; CXXNullPtrLiteralExprBitfields CXXNullPtrLiteralExprBits; CXXThisExprBitfields CXXThisExprBits; diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index e37f5b1e0004..ddfb3060b158 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -17,6 +17,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/SourceLocation.h" @@ -448,7 +449,8 @@ class OMPLoopDirective : public OMPExecutableDirective { PreInitsOffset = 8, // The '...End' enumerators do not correspond to child expressions - they // specify the offset to the end (and start of the following counters/ - // updates/finals arrays). + // updates/finals/dependent_counters/dependent_inits/finals_conditions + // arrays). DefaultEnd = 9, // The following 8 exprs are used by worksharing and distribute loops only. IsLastIterVariableOffset = 9, @@ -474,7 +476,8 @@ class OMPLoopDirective : public OMPExecutableDirective { CombinedNextUpperBoundOffset = 27, CombinedDistConditionOffset = 28, CombinedParForInDistConditionOffset = 29, - // Offset to the end (and start of the following counters/updates/finals + // Offset to the end (and start of the following + // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions // arrays) for combined distribute loop directives. CombinedDistributeEnd = 30, }; @@ -517,6 +520,30 @@ class OMPLoopDirective : public OMPExecutableDirective { return MutableArrayRef<Expr *>(Storage, CollapsedNum); } + /// Get the dependent counters storage. + MutableArrayRef<Expr *> getDependentCounters() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + 5 * CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// Get the dependent inits storage. + MutableArrayRef<Expr *> getDependentInits() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + 6 * CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// Get the finals conditions storage. + MutableArrayRef<Expr *> getFinalsConditions() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + 7 * CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + protected: /// Build instance of loop directive of class \a Kind. /// @@ -551,9 +578,10 @@ protected: /// Children number. static unsigned numLoopChildren(unsigned CollapsedNum, OpenMPDirectiveKind Kind) { - return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters, - // PrivateCounters, Inits, - // Updates and Finals + return getArraysOffset(Kind) + + 8 * CollapsedNum; // Counters, PrivateCounters, Inits, + // Updates, Finals, DependentCounters, + // DependentInits, FinalsConditions. } void setIterationVariable(Expr *IV) { @@ -703,6 +731,9 @@ protected: void setInits(ArrayRef<Expr *> A); void setUpdates(ArrayRef<Expr *> A); void setFinals(ArrayRef<Expr *> A); + void setDependentCounters(ArrayRef<Expr *> A); + void setDependentInits(ArrayRef<Expr *> A); + void setFinalsConditions(ArrayRef<Expr *> A); public: /// The expressions built to support OpenMP loops in combined/composite @@ -798,6 +829,15 @@ public: SmallVector<Expr *, 4> Updates; /// Final loop counter values for GodeGen. SmallVector<Expr *, 4> Finals; + /// List of counters required for the generation of the non-rectangular + /// loops. + SmallVector<Expr *, 4> DependentCounters; + /// List of initializers required for the generation of the non-rectangular + /// loops. + SmallVector<Expr *, 4> DependentInits; + /// List of final conditions required for the generation of the + /// non-rectangular loops. + SmallVector<Expr *, 4> FinalsConditions; /// Init statement for all captured expressions. Stmt *PreInits; @@ -813,7 +853,9 @@ public: } /// Initialize all the fields to null. - /// \param Size Number of elements in the counters/finals/updates arrays. + /// \param Size Number of elements in the + /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions + /// arrays. void clear(unsigned Size) { IterationVarRef = nullptr; LastIteration = nullptr; @@ -839,12 +881,18 @@ public: Inits.resize(Size); Updates.resize(Size); Finals.resize(Size); + DependentCounters.resize(Size); + DependentInits.resize(Size); + FinalsConditions.resize(Size); for (unsigned i = 0; i < Size; ++i) { Counters[i] = nullptr; PrivateCounters[i] = nullptr; Inits[i] = nullptr; Updates[i] = nullptr; Finals[i] = nullptr; + DependentCounters[i] = nullptr; + DependentInits[i] = nullptr; + FinalsConditions[i] = nullptr; } PreInits = nullptr; DistCombinedFields.LB = nullptr; @@ -1040,10 +1088,22 @@ public: // This relies on the loop form is already checked by Sema. const Stmt *Body = getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(); - Body = cast<ForStmt>(Body)->getBody(); + if (auto *For = dyn_cast<ForStmt>(Body)) { + Body = For->getBody(); + } else { + assert(isa<CXXForRangeStmt>(Body) && + "Expected canonical for loop or range-based for loop."); + Body = cast<CXXForRangeStmt>(Body)->getBody(); + } for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { Body = Body->IgnoreContainers(); - Body = cast<ForStmt>(Body)->getBody(); + if (auto *For = dyn_cast<ForStmt>(Body)) { + Body = For->getBody(); + } else { + assert(isa<CXXForRangeStmt>(Body) && + "Expected canonical for loop or range-based for loop."); + Body = cast<CXXForRangeStmt>(Body)->getBody(); + } } return Body; } @@ -1078,6 +1138,24 @@ public: return const_cast<OMPLoopDirective *>(this)->getFinals(); } + ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); } + + ArrayRef<Expr *> dependent_counters() const { + return const_cast<OMPLoopDirective *>(this)->getDependentCounters(); + } + + ArrayRef<Expr *> dependent_inits() { return getDependentInits(); } + + ArrayRef<Expr *> dependent_inits() const { + return const_cast<OMPLoopDirective *>(this)->getDependentInits(); + } + + ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); } + + ArrayRef<Expr *> finals_conditions() const { + return const_cast<OMPLoopDirective *>(this)->getFinalsConditions(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == OMPSimdDirectiveClass || T->getStmtClass() == OMPForDirectiveClass || @@ -1086,6 +1164,9 @@ public: T->getStmtClass() == OMPParallelForSimdDirectiveClass || T->getStmtClass() == OMPTaskLoopDirectiveClass || T->getStmtClass() == OMPTaskLoopSimdDirectiveClass || + T->getStmtClass() == OMPMasterTaskLoopDirectiveClass || + T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass || + T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass || T->getStmtClass() == OMPDistributeDirectiveClass || T->getStmtClass() == OMPTargetParallelForDirectiveClass || T->getStmtClass() == OMPDistributeParallelForDirectiveClass || @@ -3041,6 +3122,211 @@ public: } }; +/// This represents '#pragma omp master taskloop' directive. +/// +/// \code +/// #pragma omp master taskloop private(a,b) grainsize(val) num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp master taskloop' has clauses +/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val' +/// and 'num_tasks' with expression 'num'. +/// +class OMPMasterTaskLoopDirective : public OMPLoopDirective { + 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 CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass, + OMPD_master_taskloop, StartLoc, EndLoc, CollapsedNum, + NumClauses) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPMasterTaskLoopDirectiveClass, + OMPD_master_taskloop, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +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 CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPMasterTaskLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPMasterTaskLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass; + } +}; + +/// This represents '#pragma omp master taskloop simd' directive. +/// +/// \code +/// #pragma omp master taskloop simd private(a,b) grainsize(val) num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp master taskloop simd' has clauses +/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val' +/// and 'num_tasks' with expression 'num'. +/// +class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective { + 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 CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass, + OMPD_master_taskloop_simd, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPMasterTaskLoopSimdDirectiveClass, + OMPD_master_taskloop_simd, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +public: + /// Creates directive with a list of \p Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPMasterTaskLoopSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place for \p NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPMasterTaskLoopSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass; + } +}; + +/// This represents '#pragma omp parallel master taskloop' directive. +/// +/// \code +/// #pragma omp parallel master taskloop private(a,b) grainsize(val) +/// num_tasks(num) +/// \endcode +/// In this example directive '#pragma omp parallel master taskloop' has clauses +/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val' +/// and 'num_tasks' with expression 'num'. +/// +class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective { + 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 CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass, + OMPD_parallel_master_taskloop, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelMasterTaskLoopDirectiveClass, + OMPD_parallel_master_taskloop, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +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 CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPParallelMasterTaskLoopDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPParallelMasterTaskLoopDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass; + } +}; + /// This represents '#pragma omp distribute' directive. /// /// \code diff --git a/include/clang/AST/TextNodeDumper.h b/include/clang/AST/TextNodeDumper.h index 4c2d0710963b..0ff5a614a864 100644 --- a/include/clang/AST/TextNodeDumper.h +++ b/include/clang/AST/TextNodeDumper.h @@ -146,8 +146,6 @@ class TextNodeDumper const comments::CommandTraits *Traits; - const ASTContext *Context; - const char *getCommandName(unsigned CommandID); public: diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 584655fe789e..c9238e952101 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -126,7 +126,7 @@ using CanQualType = CanQual<Type>; // Provide forward declarations for all of the *Type classes. #define TYPE(Class, Base) class Class##Type; -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" /// The collection of all-type qualifiers we support. /// Clang supports five independent qualifiers: @@ -972,6 +972,9 @@ public: friend bool operator!=(const QualType &LHS, const QualType &RHS) { return LHS.Value != RHS.Value; } + friend bool operator<(const QualType &LHS, const QualType &RHS) { + return LHS.Value < RHS.Value; + } static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy) { @@ -1434,10 +1437,9 @@ class alignas(8) Type : public ExtQualsTypeCommonBase { public: enum TypeClass { #define TYPE(Class, Base) Class, -#define LAST_TYPE(Class) TypeLast = Class, +#define LAST_TYPE(Class) TypeLast = Class #define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - TagFirst = Record, TagLast = Enum +#include "clang/AST/TypeNodes.inc" }; private: @@ -1511,6 +1513,15 @@ protected: unsigned SizeModifier : 3; }; + class ConstantArrayTypeBitfields { + friend class ConstantArrayType; + + unsigned : NumTypeBits + 3 + 3; + + /// Whether we have a stored size expression. + unsigned HasStoredSizeExpr : 1; + }; + class BuiltinTypeBitfields { friend class BuiltinType; @@ -1732,6 +1743,7 @@ protected: union { TypeBitfields TypeBits; ArrayTypeBitfields ArrayTypeBits; + ConstantArrayTypeBitfields ConstantArrayTypeBits; AttributedTypeBitfields AttributedTypeBits; AutoTypeBitfields AutoTypeBits; BuiltinTypeBitfields BuiltinTypeBits; @@ -2053,6 +2065,7 @@ public: bool isCARCBridgableType() const; bool isTemplateTypeParmType() const; // C++ template type parameter bool isNullPtrType() const; // C++11 std::nullptr_t + bool isNothrowT() const; // C++ std::nothrow_t bool isAlignValT() const; // C++17 std::align_val_t bool isStdByteType() const; // C++17 std::byte bool isAtomicType() const; // C11 _Atomic() @@ -2416,7 +2429,7 @@ template <> inline const Class##Type *Type::getAs() const { \ template <> inline const Class##Type *Type::castAs() const { \ return cast<Class##Type>(CanonicalType); \ } -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" /// This class is used for builtin types like 'int'. Builtin /// types are always canonical and have a literal name field. @@ -2429,6 +2442,9 @@ public: // OpenCL extension types #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) Id, #include "clang/Basic/OpenCLExtensionTypes.def" +// SVE Types +#define SVE_TYPE(Name, Id, SingletonId) Id, +#include "clang/Basic/AArch64SVEACLETypes.def" // All other builtin types #define BUILTIN_TYPE(Id, SingletonId) Id, #define LAST_BUILTIN_TYPE(Id) LastKind = Id @@ -2858,22 +2874,8 @@ private: protected: friend class ASTContext; // ASTContext creates these. - // C++ [temp.dep.type]p1: - // A type is dependent if it is... - // - an array type constructed from any dependent type or whose - // size is specified by a constant expression that is - // value-dependent, - ArrayType(TypeClass tc, QualType et, QualType can, - ArraySizeModifier sm, unsigned tq, - bool ContainsUnexpandedParameterPack) - : Type(tc, can, et->isDependentType() || tc == DependentSizedArray, - et->isInstantiationDependentType() || tc == DependentSizedArray, - (tc == VariableArray || et->isVariablyModifiedType()), - ContainsUnexpandedParameterPack), - ElementType(et) { - ArrayTypeBits.IndexTypeQuals = tq; - ArrayTypeBits.SizeModifier = sm; - } + ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm, + unsigned tq, const Expr *sz = nullptr); public: QualType getElementType() const { return ElementType; } @@ -2901,25 +2903,35 @@ public: /// Represents the canonical version of C arrays with a specified constant size. /// For example, the canonical type for 'int A[4 + 4*100]' is a /// ConstantArrayType where the element type is 'int' and the size is 404. -class ConstantArrayType : public ArrayType { +class ConstantArrayType final + : public ArrayType, + private llvm::TrailingObjects<ConstantArrayType, const Expr *> { + friend class ASTContext; // ASTContext creates these. + friend TrailingObjects; + llvm::APInt Size; // Allows us to unique the type. ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, - ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), - Size(size) {} - -protected: - friend class ASTContext; // ASTContext creates these. + const Expr *sz, ArraySizeModifier sm, unsigned tq) + : ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) { + ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr; + if (ConstantArrayTypeBits.HasStoredSizeExpr) { + assert(!can.isNull() && "canonical constant array should not have size"); + *getTrailingObjects<const Expr*>() = sz; + } + } - ConstantArrayType(TypeClass tc, QualType et, QualType can, - const llvm::APInt &size, ArraySizeModifier sm, unsigned tq) - : ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()), - Size(size) {} + unsigned numTrailingObjects(OverloadToken<const Expr*>) const { + return ConstantArrayTypeBits.HasStoredSizeExpr; + } public: const llvm::APInt &getSize() const { return Size; } + const Expr *getSizeExpr() const { + return ConstantArrayTypeBits.HasStoredSizeExpr + ? *getTrailingObjects<const Expr *>() + : nullptr; + } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2933,19 +2945,15 @@ public: /// can require, which limits the maximum size of the array. static unsigned getMaxSizeBits(const ASTContext &Context); - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getSize(), + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { + Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(), getSizeModifier(), getIndexTypeCVRQualifiers()); } - static void Profile(llvm::FoldingSetNodeID &ID, QualType ET, - const llvm::APInt &ArraySize, ArraySizeModifier SizeMod, - unsigned TypeQuals) { - ID.AddPointer(ET.getAsOpaquePtr()); - ID.AddInteger(ArraySize.getZExtValue()); - ID.AddInteger(SizeMod); - ID.AddInteger(TypeQuals); - } + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx, + QualType ET, const llvm::APInt &ArraySize, + const Expr *SizeExpr, ArraySizeModifier SizeMod, + unsigned TypeQuals); static bool classof(const Type *T) { return T->getTypeClass() == ConstantArray; @@ -2960,8 +2968,7 @@ class IncompleteArrayType : public ArrayType { IncompleteArrayType(QualType et, QualType can, ArraySizeModifier sm, unsigned tq) - : ArrayType(IncompleteArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()) {} + : ArrayType(IncompleteArray, et, can, sm, tq) {} public: friend class StmtIteratorBase; @@ -3013,8 +3020,7 @@ class VariableArrayType : public ArrayType { VariableArrayType(QualType et, QualType can, Expr *e, ArraySizeModifier sm, unsigned tq, SourceRange brackets) - : ArrayType(VariableArray, et, can, sm, tq, - et->containsUnexpandedParameterPack()), + : ArrayType(VariableArray, et, can, sm, tq, e), SizeExpr((Stmt*) e), Brackets(brackets) {} public: @@ -4429,7 +4435,7 @@ public: bool isBeingDefined() const; static bool classof(const Type *T) { - return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; + return T->getTypeClass() == Enum || T->getTypeClass() == Record; } }; @@ -5563,7 +5569,7 @@ class ObjCTypeParamType : public Type, public: bool isSugared() const { return true; } - QualType desugar() const { return getCanonicalTypeInternal(); } + QualType desugar() const; static bool classof(const Type *T) { return T->getTypeClass() == ObjCTypeParam; @@ -6347,6 +6353,7 @@ inline bool QualType::isCForbiddenLValueType() const { /// \returns True for types specified in C++0x [basic.fundamental]. inline bool Type::isFundamentalType() const { return isVoidType() || + isNullPtrType() || // FIXME: It's really annoying that we don't have an // 'isArithmeticType()' which agrees with the standard definition. (isArithmeticType() && !isEnumeralType()); diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 40d17f991f1f..f305680d775c 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -106,7 +106,7 @@ public: #define ABSTRACT_TYPE(Class, Base) #define TYPE(Class, Base) \ Class = Type::Class, -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" Qualified }; diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def index c0dfe150d6cc..81448c7e7ce5 100644 --- a/include/clang/AST/TypeLocNodes.def +++ b/include/clang/AST/TypeLocNodes.def @@ -31,7 +31,7 @@ TYPELOC(Qualified, TypeLoc) #define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc) #define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc) -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" #undef DECLARATOR_TYPELOC #undef TYPESPEC_TYPELOC diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def deleted file mode 100644 index 58a5f880cbe6..000000000000 --- a/include/clang/AST/TypeNodes.def +++ /dev/null @@ -1,135 +0,0 @@ -//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- 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 defines the AST type info database. Each type node is -// enumerated by providing its name (e.g., "Builtin" or "Enum") and -// base class (e.g., "Type" or "TagType"). Depending on where in the -// abstract syntax tree the type will show up, the enumeration uses -// one of five different macros: -// -// TYPE(Class, Base) - A type that can show up anywhere in the AST, -// and might be dependent, canonical, or non-canonical. All clients -// will need to understand these types. -// -// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in -// the type hierarchy but has no concrete instances. -// -// NON_CANONICAL_TYPE(Class, Base) - A type that can show up -// anywhere in the AST but will never be a part of a canonical -// type. Clients that only need to deal with canonical types -// (ignoring, e.g., typedefs and other type aliases used for -// pretty-printing) can ignore these types. -// -// DEPENDENT_TYPE(Class, Base) - A type that will only show up -// within a C++ template that has not been instantiated, e.g., a -// type that is always dependent. Clients that do not need to deal -// with uninstantiated C++ templates can ignore these types. -// -// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that -// is non-canonical unless it is dependent. Defaults to TYPE because -// it is neither reliably dependent nor reliably non-canonical. -// -// There is a sixth macro, independent of the others. Most clients -// will not need to use it. -// -// LEAF_TYPE(Class) - A type that never has inner types. Clients -// which can operate on such types more efficiently may wish to do so. -// -//===----------------------------------------------------------------------===// - -#ifndef ABSTRACT_TYPE -# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base) -#endif - -#ifndef NON_CANONICAL_TYPE -# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base) -#endif - -#ifndef DEPENDENT_TYPE -# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) -#endif - -#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE -# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) -#endif - -TYPE(Builtin, Type) -TYPE(Complex, Type) -TYPE(Pointer, Type) -TYPE(BlockPointer, Type) -ABSTRACT_TYPE(Reference, Type) -TYPE(LValueReference, ReferenceType) -TYPE(RValueReference, ReferenceType) -TYPE(MemberPointer, Type) -ABSTRACT_TYPE(Array, Type) -TYPE(ConstantArray, ArrayType) -TYPE(IncompleteArray, ArrayType) -TYPE(VariableArray, ArrayType) -DEPENDENT_TYPE(DependentSizedArray, ArrayType) -DEPENDENT_TYPE(DependentSizedExtVector, Type) -DEPENDENT_TYPE(DependentAddressSpace, Type) -TYPE(Vector, Type) -DEPENDENT_TYPE(DependentVector, Type) -TYPE(ExtVector, VectorType) -ABSTRACT_TYPE(Function, Type) -TYPE(FunctionProto, FunctionType) -TYPE(FunctionNoProto, FunctionType) -DEPENDENT_TYPE(UnresolvedUsing, Type) -NON_CANONICAL_TYPE(Paren, Type) -NON_CANONICAL_TYPE(Typedef, Type) -NON_CANONICAL_TYPE(MacroQualified, Type) -NON_CANONICAL_TYPE(Adjusted, Type) -NON_CANONICAL_TYPE(Decayed, AdjustedType) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type) -ABSTRACT_TYPE(Tag, Type) -TYPE(Record, TagType) -TYPE(Enum, TagType) -NON_CANONICAL_TYPE(Elaborated, Type) -NON_CANONICAL_TYPE(Attributed, Type) -DEPENDENT_TYPE(TemplateTypeParm, Type) -NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) -DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) -ABSTRACT_TYPE(Deduced, Type) -TYPE(Auto, DeducedType) -TYPE(DeducedTemplateSpecialization, DeducedType) -DEPENDENT_TYPE(InjectedClassName, Type) -DEPENDENT_TYPE(DependentName, Type) -DEPENDENT_TYPE(DependentTemplateSpecialization, Type) -NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type) -NON_CANONICAL_TYPE(ObjCTypeParam, Type) -TYPE(ObjCObject, Type) -TYPE(ObjCInterface, ObjCObjectType) -TYPE(ObjCObjectPointer, Type) -TYPE(Pipe, Type) -TYPE(Atomic, Type) - -#ifdef LAST_TYPE -LAST_TYPE(Atomic) -#undef LAST_TYPE -#endif - -// These types are always leaves in the type hierarchy. -#ifdef LEAF_TYPE -LEAF_TYPE(Enum) -LEAF_TYPE(Builtin) -LEAF_TYPE(Record) -LEAF_TYPE(InjectedClassName) -LEAF_TYPE(ObjCInterface) -LEAF_TYPE(TemplateTypeParm) -#undef LEAF_TYPE -#endif - -#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE -#undef DEPENDENT_TYPE -#undef NON_CANONICAL_TYPE -#undef ABSTRACT_TYPE -#undef TYPE diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h index 8930ec853949..17301835fb18 100644 --- a/include/clang/AST/TypeVisitor.h +++ b/include/clang/AST/TypeVisitor.h @@ -70,7 +70,7 @@ public: switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type); -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" } llvm_unreachable("Unknown type class!"); } @@ -80,7 +80,7 @@ public: #define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \ DISPATCH(PARENT); \ } -#include "clang/AST/TypeNodes.def" +#include "clang/AST/TypeNodes.inc" /// Method called if \c ImpClass doesn't provide specific handler /// for some type class. |