diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/AST/DeclCXX.h')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/AST/DeclCXX.h | 462 |
1 files changed, 327 insertions, 135 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h index 0d5ad40fc19e..9cebaff63bb0 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h @@ -64,7 +64,6 @@ class CXXFinalOverriderMap; class CXXIndirectPrimaryBaseSet; class CXXMethodDecl; class DecompositionDecl; -class DiagnosticBuilder; class FriendDecl; class FunctionTemplateDecl; class IdentifierInfo; @@ -155,22 +154,26 @@ class CXXBaseSpecifier { SourceLocation EllipsisLoc; /// Whether this is a virtual base class or not. + LLVM_PREFERRED_TYPE(bool) unsigned Virtual : 1; /// Whether this is the base of a class (true) or of a struct (false). /// /// This determines the mapping from the access specifier as written in the /// source code to the access specifier used for semantic analysis. + LLVM_PREFERRED_TYPE(bool) unsigned BaseOfClass : 1; /// Access specifier as written in the source code (may be AS_none). /// /// The actual type of data stored here is an AccessSpecifier, but we use - /// "unsigned" here to work around a VC++ bug. + /// "unsigned" here to work around Microsoft ABI. + LLVM_PREFERRED_TYPE(AccessSpecifier) unsigned Access : 2; /// Whether the class contains a using declaration /// to inherit the named class's constructors. + LLVM_PREFERRED_TYPE(bool) unsigned InheritConstructors : 1; /// The type of the base class. @@ -261,8 +264,9 @@ class CXXRecordDecl : public RecordDecl { friend class ASTWriter; friend class DeclContext; friend class LambdaExpr; + friend class ODRDiagsEmitter; - friend void FunctionDecl::setPure(bool); + friend void FunctionDecl::setIsPureVirtual(bool); friend void TagDecl::startDefinition(); /// Values used in DefinitionData fields to represent special members. @@ -276,21 +280,33 @@ class CXXRecordDecl : public RecordDecl { SMF_All = 0x3f }; +public: + enum LambdaDependencyKind { + LDK_Unknown = 0, + LDK_AlwaysDependent, + LDK_NeverDependent, + }; + +private: struct DefinitionData { #define FIELD(Name, Width, Merge) \ unsigned Name : Width; #include "CXXRecordDeclDefinitionBits.def" /// Whether this class describes a C++ lambda. + LLVM_PREFERRED_TYPE(bool) unsigned IsLambda : 1; /// Whether we are currently parsing base specifiers. + LLVM_PREFERRED_TYPE(bool) unsigned IsParsingBaseSpecifiers : 1; /// True when visible conversion functions are already computed /// and are available. + LLVM_PREFERRED_TYPE(bool) unsigned ComputedVisibleConversions : 1; + LLVM_PREFERRED_TYPE(bool) unsigned HasODRHash : 1; /// A hash of parts of the class to help in ODR checking. @@ -349,11 +365,11 @@ class CXXRecordDecl : public RecordDecl { } ArrayRef<CXXBaseSpecifier> bases() const { - return llvm::makeArrayRef(getBases(), NumBases); + return llvm::ArrayRef(getBases(), NumBases); } ArrayRef<CXXBaseSpecifier> vbases() const { - return llvm::makeArrayRef(getVBases(), NumVBases); + return llvm::ArrayRef(getVBases(), NumVBases); } private: @@ -375,46 +391,56 @@ class CXXRecordDecl : public RecordDecl { /// lambda will have been created with the enclosing context as its /// declaration context, rather than function. This is an unfortunate /// artifact of having to parse the default arguments before. - unsigned Dependent : 1; + LLVM_PREFERRED_TYPE(LambdaDependencyKind) + unsigned DependencyKind : 2; /// Whether this lambda is a generic lambda. + LLVM_PREFERRED_TYPE(bool) unsigned IsGenericLambda : 1; /// The Default Capture. + LLVM_PREFERRED_TYPE(LambdaCaptureDefault) unsigned CaptureDefault : 2; /// The number of captures in this lambda is limited 2^NumCaptures. unsigned NumCaptures : 15; /// The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 13; + unsigned NumExplicitCaptures : 12; /// Has known `internal` linkage. + LLVM_PREFERRED_TYPE(bool) unsigned HasKnownInternalLinkage : 1; /// The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. unsigned ManglingNumber : 31; + /// The index of this lambda within its context declaration. This is not in + /// general the same as the mangling number. + unsigned IndexInContext; + /// The declaration that provides context for this lambda, if the /// actual DeclContext does not suffice. This is used for lambdas that /// occur within default arguments of function parameters within the class /// or within a data member initializer. LazyDeclPtr ContextDecl; - /// The list of captures, both explicit and implicit, for this - /// lambda. - Capture *Captures = nullptr; + /// The lists of captures, both explicit and implicit, for this + /// lambda. One list is provided for each merged copy of the lambda. + /// The first list corresponds to the canonical definition. + /// The destructor is registered by AddCaptureList when necessary. + llvm::TinyPtrVector<Capture*> Captures; /// The type of the call method. TypeSourceInfo *MethodTyInfo; - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent, + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, unsigned DK, bool IsGeneric, LambdaCaptureDefault CaptureDefault) - : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), + : DefinitionData(D), DependencyKind(DK), IsGenericLambda(IsGeneric), CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0), - MethodTyInfo(Info) { + IndexInContext(0), MethodTyInfo(Info) { IsLambda = true; // C++1z [expr.prim.lambda]p4: @@ -422,6 +448,9 @@ class CXXRecordDecl : public RecordDecl { Aggregate = false; PlainOldData = false; } + + // Add a list of captures. + void AddCaptureList(ASTContext &Ctx, Capture *CaptureList); }; struct DefinitionData *dataPtr() const { @@ -548,7 +577,7 @@ public: bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool DependentLambda, bool IsGeneric, + unsigned DependencyKind, bool IsGeneric, LambdaCaptureDefault CaptureDefault); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); @@ -1035,6 +1064,12 @@ public: return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault); } + bool isCapturelessLambda() const { + if (!isLambda()) + return false; + return getLambdaCaptureDefault() == LCD_None && capture_size() == 0; + } + /// Set the captures for this lambda closure type. void setCaptures(ASTContext &Context, ArrayRef<LambdaCapture> Captures); @@ -1050,8 +1085,14 @@ public: /// /// \note No entries will be added for init-captures, as they do not capture /// variables. - void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, - FieldDecl *&ThisCapture) const; + /// + /// \note If multiple versions of the lambda are merged together, they may + /// have different variable declarations corresponding to the same capture. + /// In that case, all of those variable declarations will be added to the + /// Captures list, so it may have more than one variable listed per field. + void + getCaptureFields(llvm::DenseMap<const ValueDecl *, FieldDecl *> &Captures, + FieldDecl *&ThisCapture) const; using capture_const_iterator = const LambdaCapture *; using capture_const_range = llvm::iterator_range<capture_const_iterator>; @@ -1061,7 +1102,9 @@ public: } capture_const_iterator captures_begin() const { - return isLambda() ? getLambdaData().Captures : nullptr; + if (!isLambda()) return nullptr; + LambdaDefinitionData &LambdaData = getLambdaData(); + return LambdaData.Captures.empty() ? nullptr : LambdaData.Captures.front(); } capture_const_iterator captures_end() const { @@ -1071,6 +1114,11 @@ public: unsigned capture_size() const { return getLambdaData().NumCaptures; } + const LambdaCapture *getCapture(unsigned I) const { + assert(isLambda() && I < capture_size() && "invalid index for capture"); + return captures_begin() + I; + } + using conversion_iterator = UnresolvedSetIterator; conversion_iterator conversion_begin() const { @@ -1139,6 +1187,13 @@ public: /// /// \note This does NOT include a check for union-ness. bool isEmpty() const { return data().Empty; } + /// Marks this record as empty. This is used by DWARFASTParserClang + /// when parsing records with empty fields having [[no_unique_address]] + /// attribute + void markEmpty() { data().Empty = true; } + + void setInitMethod(bool Val) { data().HasInitMethod = Val; } + bool hasInitMethod() const { return data().HasInitMethod; } bool hasPrivateFields() const { return data().HasPrivateFields; @@ -1160,7 +1215,7 @@ public: /// Determine whether this class has a pure virtual function. /// - /// The class is is abstract per (C++ [class.abstract]p2) if it declares + /// The class is abstract per (C++ [class.abstract]p2) if it declares /// a pure virtual function or inherits a pure virtual function that is /// not overridden. bool isAbstract() const { return data().Abstract; } @@ -1370,6 +1425,9 @@ public: /// (C++11 [class]p6). bool isTriviallyCopyable() const; + /// Determine whether this class is considered trivially copyable per + bool isTriviallyCopyConstructible() const; + /// Determine whether this class is considered trivial. /// /// C++11 [class]p6: @@ -1381,37 +1439,39 @@ public: /// Determine whether this class is a literal type. /// - /// C++11 [basic.types]p10: + /// C++20 [basic.types]p10: /// A class type that has all the following properties: - /// - it has a trivial destructor - /// - every constructor call and full-expression in the - /// brace-or-equal-intializers for non-static data members (if any) is - /// a constant expression. - /// - it is an aggregate type or has at least one constexpr constructor - /// or constructor template that is not a copy or move constructor, and - /// - all of its non-static data members and base classes are of literal - /// types - /// - /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by - /// treating types with trivial default constructors as literal types. - /// - /// Only in C++17 and beyond, are lambdas literal types. - bool isLiteral() const { - const LangOptions &LangOpts = getLangOpts(); - return (LangOpts.CPlusPlus20 ? hasConstexprDestructor() - : hasTrivialDestructor()) && - (!isLambda() || LangOpts.CPlusPlus17) && - !hasNonLiteralTypeFieldsOrBases() && - (isAggregate() || isLambda() || - hasConstexprNonCopyMoveConstructor() || - hasTrivialDefaultConstructor()); - } + /// - it has a constexpr destructor + /// - all of its non-static non-variant data members and base classes + /// are of non-volatile literal types, and it: + /// - is a closure type + /// - is an aggregate union type that has either no variant members + /// or at least one variant member of non-volatile literal type + /// - is a non-union aggregate type for which each of its anonymous + /// union members satisfies the above requirements for an aggregate + /// union type, or + /// - has at least one constexpr constructor or constructor template + /// that is not a copy or move constructor. + bool isLiteral() const; /// Determine whether this is a structural type. bool isStructural() const { return isLiteral() && data().StructuralIfLiteral; } + /// Notify the class that this destructor is now selected. + /// + /// Important properties of the class depend on destructor properties. Since + /// C++20, it is possible to have multiple destructor declarations in a class + /// out of which one will be selected at the end. + /// This is called separately from addedMember because it has to be deferred + /// to the completion of the class. + void addedSelectedDestructor(CXXDestructorDecl *DD); + + /// Notify the class that an eligible SMF has been added. + /// This updates triviality and destructor based properties of the class accordingly. + void addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, unsigned SMKind); + /// If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// @@ -1726,18 +1786,31 @@ public: /// the declaration context suffices. Decl *getLambdaContextDecl() const; - /// Set the mangling number and context declaration for a lambda - /// class. - void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl, - bool HasKnownInternalLinkage = false) { + /// Retrieve the index of this lambda within the context declaration returned + /// by getLambdaContextDecl(). + unsigned getLambdaIndexInContext() const { assert(isLambda() && "Not a lambda closure type!"); - getLambdaData().ManglingNumber = ManglingNumber; - getLambdaData().ContextDecl = ContextDecl; - getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage; + return getLambdaData().IndexInContext; } - /// Set the device side mangling number. - void setDeviceLambdaManglingNumber(unsigned Num) const; + /// Information about how a lambda is numbered within its context. + struct LambdaNumbering { + Decl *ContextDecl = nullptr; + unsigned IndexInContext = 0; + unsigned ManglingNumber = 0; + unsigned DeviceManglingNumber = 0; + bool HasKnownInternalLinkage = false; + }; + + /// Set the mangling numbers and context declaration for a lambda class. + void setLambdaNumbering(LambdaNumbering Numbering); + + // Get the mangling numbers and context declaration for a lambda class. + LambdaNumbering getLambdaNumbering() const { + return {getLambdaContextDecl(), getLambdaIndexInContext(), + getLambdaManglingNumber(), getDeviceLambdaManglingNumber(), + hasKnownLambdaInternalLinkage()}; + } /// Retrieve the device side mangling number. unsigned getDeviceLambdaManglingNumber() const; @@ -1772,13 +1845,37 @@ public: /// function declaration itself is dependent. This flag indicates when we /// know that the lambda is dependent despite that. bool isDependentLambda() const { - return isLambda() && getLambdaData().Dependent; + return isLambda() && getLambdaData().DependencyKind == LDK_AlwaysDependent; + } + + bool isNeverDependentLambda() const { + return isLambda() && getLambdaData().DependencyKind == LDK_NeverDependent; + } + + unsigned getLambdaDependencyKind() const { + if (!isLambda()) + return LDK_Unknown; + return getLambdaData().DependencyKind; } TypeSourceInfo *getLambdaTypeInfo() const { return getLambdaData().MethodTyInfo; } + void setLambdaTypeInfo(TypeSourceInfo *TS) { + assert(DefinitionData && DefinitionData->IsLambda && + "setting lambda property of non-lambda class"); + auto &DL = static_cast<LambdaDefinitionData &>(*DefinitionData); + DL.MethodTyInfo = TS; + } + + void setLambdaIsGeneric(bool IsGeneric) { + assert(DefinitionData && DefinitionData->IsLambda && + "setting lambda property of non-lambda class"); + auto &DL = static_cast<LambdaDefinitionData &>(*DefinitionData); + DL.IsGenericLambda = IsGeneric; + } + // Determine whether this type is an Interface Like type for // __interface inheritance purposes. bool isInterfaceLike() const; @@ -1855,13 +1952,13 @@ private: ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor) + CXXConstructorDecl *Ctor, DeductionCandidate Kind) : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, - SC_None, false, ConstexprSpecKind::Unspecified), + SC_None, false, false, ConstexprSpecKind::Unspecified), Ctor(Ctor), ExplicitSpec(ES) { if (EndLocation.isValid()) setRangeEnd(EndLocation); - setIsCopyDeductionCandidate(false); + setDeductionCandidateKind(Kind); } CXXConstructorDecl *Ctor; @@ -1876,14 +1973,15 @@ public: Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor = nullptr); + CXXConstructorDecl *Ctor = nullptr, + DeductionCandidate Kind = DeductionCandidate::Normal); static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, unsigned ID); ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; } const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; } - /// Return true if the declartion is already resolved to be explicit. + /// Return true if the declaration is already resolved to be explicit. bool isExplicit() const { return ExplicitSpec.isExplicit(); } /// Get the template for which this guide performs deduction. @@ -1893,16 +1991,15 @@ public: /// Get the constructor from which this deduction guide was generated, if /// this is an implicit deduction guide. - CXXConstructorDecl *getCorrespondingConstructor() const { - return Ctor; - } + CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; } - void setIsCopyDeductionCandidate(bool isCDC = true) { - FunctionDeclBits.IsCopyDeductionCandidate = isCDC; + void setDeductionCandidateKind(DeductionCandidate K) { + FunctionDeclBits.DeductionCandidateKind = static_cast<unsigned char>(K); } - bool isCopyDeductionCandidate() const { - return FunctionDeclBits.IsCopyDeductionCandidate; + DeductionCandidate getDeductionCandidateKind() const { + return static_cast<DeductionCandidate>( + FunctionDeclBits.DeductionCandidateKind); } // Implement isa/cast/dyncast/etc. @@ -1939,6 +2036,14 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { + return static_cast<DeclContext *>(const_cast<RequiresExprBodyDecl *>(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<RequiresExprBodyDecl *>(const_cast<DeclContext *>(DC)); + } }; /// Represents a static or instance method of a struct/union/class. @@ -1952,29 +2057,39 @@ protected: CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, + bool UsesFPIntrin, bool isInline, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr) - : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, isInline, - ConstexprKind, TrailingRequiresClause) { + : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, + isInline, ConstexprKind, TrailingRequiresClause) { if (EndLocation.isValid()) setRangeEnd(EndLocation); } public: - static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr); + static CXXMethodDecl * + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool UsesFPIntrin, bool isInline, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr); static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); bool isStatic() const; bool isInstance() const { return !isStatic(); } + /// [C++2b][dcl.fct]/p7 + /// An explicit object member function is a non-static + /// member function with an explicit object parameter. e.g., + /// void func(this SomeType); + bool isExplicitObjectMemberFunction() const; + + /// [C++2b][dcl.fct]/p7 + /// An implicit object member function is a non-static + /// member function without an explicit object parameter. + bool isImplicitObjectMemberFunction() const; + /// Returns true if the given operator is implicitly static in a record /// context. static bool isStaticOverloadedOperator(OverloadedOperatorKind OOK) { @@ -1995,7 +2110,7 @@ public: // Member function is virtual if it is marked explicitly so, or if it is // declared in __interface -- then it is automatically pure virtual. - if (CD->isVirtualAsWritten() || CD->isPure()) + if (CD->isVirtualAsWritten() || CD->isPureVirtual()) return true; return CD->size_overridden_methods() != 0; @@ -2083,14 +2198,19 @@ public: /// Return the type of the object pointed by \c this. /// /// See getThisType() for usage restriction. - QualType getThisObjectType() const; + + QualType getFunctionObjectParameterReferenceType() const; + QualType getFunctionObjectParameterType() const { + return getFunctionObjectParameterReferenceType().getNonReferenceType(); + } + + unsigned getNumExplicitParams() const { + return getNumParams() - (isExplicitObjectMemberFunction() ? 1 : 0); + } static QualType getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl); - static QualType getThisObjectType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl); - Qualifiers getMethodQualifiers() const { return getType()->castAs<FunctionProtoType>()->getMethodQuals(); } @@ -2197,14 +2317,17 @@ class CXXCtorInitializer final { /// If the initializee is a type, whether that type makes this /// a delegating initialization. + LLVM_PREFERRED_TYPE(bool) unsigned IsDelegating : 1; /// If the initializer is a base initializer, this keeps track /// of whether the base is virtual or not. + LLVM_PREFERRED_TYPE(bool) unsigned IsVirtual : 1; /// Whether or not the initializer is explicitly written /// in the sources. + LLVM_PREFERRED_TYPE(bool) unsigned IsWritten : 1; /// If IsWritten is true, then this number keeps track of the textual order @@ -2413,7 +2536,8 @@ class CXXConstructorDecl final CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline, + TypeSourceInfo *TInfo, ExplicitSpecifier ES, + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, Expr *TrailingRequiresClause); @@ -2456,8 +2580,8 @@ public: static CXXConstructorDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, + ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited = InheritedConstructor(), Expr *TrailingRequiresClause = nullptr); @@ -2479,7 +2603,7 @@ public: return getCanonicalDecl()->getExplicitSpecifierInternal(); } - /// Return true if the declartion is already resolved to be explicit. + /// Return true if the declaration is already resolved to be explicit. bool isExplicit() const { return getExplicitSpecifier().isExplicit(); } /// Iterates through the member/base initializer list. @@ -2676,25 +2800,24 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, bool isInline, + TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause) { + SC_None, UsesFPIntrin, isInline, ConstexprKind, + SourceLocation(), TrailingRequiresClause) { setImplicit(isImplicitlyDeclared); } void anchor() override; public: - static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause = nullptr); + static CXXDestructorDecl * + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause = nullptr); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); @@ -2732,12 +2855,13 @@ public: class CXXConversionDecl : public CXXMethodDecl { CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES, - ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, + ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, EndLocation, - TrailingRequiresClause), + SC_None, UsesFPIntrin, isInline, ConstexprKind, + EndLocation, TrailingRequiresClause), ExplicitSpec(ES) {} void anchor() override; @@ -2750,8 +2874,9 @@ public: static CXXConversionDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); + bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr); static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); ExplicitSpecifier getExplicitSpecifier() { @@ -2762,7 +2887,7 @@ public: return getCanonicalDecl()->ExplicitSpec; } - /// Return true if the declartion is already resolved to be explicit. + /// Return true if the declaration is already resolved to be explicit. bool isExplicit() const { return getExplicitSpecifier().isExplicit(); } void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } @@ -2787,6 +2912,12 @@ public: static bool classofKind(Kind K) { return K == CXXConversion; } }; +/// Represents the language in a linkage specification. +/// +/// The values are part of the serialization ABI for +/// ASTs and cannot be changed without altering that ABI. +enum class LinkageSpecLanguageIDs { C = 1, CXX = 2 }; + /// Represents a linkage specification. /// /// For example: @@ -2797,14 +2928,7 @@ class LinkageSpecDecl : public Decl, public DeclContext { virtual void anchor(); // This class stores some data in DeclContext::LinkageSpecDeclBits to save // some space. Use the provided accessors to access it. -public: - /// Represents the language in a linkage specification. - /// - /// The values are part of the serialization ABI for - /// ASTs and cannot be changed without altering that ABI. - enum LanguageIDs { lang_c = 1, lang_cxx = 2 }; -private: /// The source location for the extern keyword. SourceLocation ExternLoc; @@ -2812,22 +2936,25 @@ private: SourceLocation RBraceLoc; LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs lang, bool HasBraces); + SourceLocation LangLoc, LinkageSpecLanguageIDs lang, + bool HasBraces); public: static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs Lang, - bool HasBraces); + SourceLocation LangLoc, + LinkageSpecLanguageIDs Lang, bool HasBraces); static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// Return the language specified by this linkage specification. - LanguageIDs getLanguage() const { - return static_cast<LanguageIDs>(LinkageSpecDeclBits.Language); + LinkageSpecLanguageIDs getLanguage() const { + return static_cast<LinkageSpecLanguageIDs>(LinkageSpecDeclBits.Language); } /// Set the language specified by this linkage specification. - void setLanguage(LanguageIDs L) { LinkageSpecDeclBits.Language = L; } + void setLanguage(LinkageSpecLanguageIDs L) { + LinkageSpecDeclBits.Language = llvm::to_underlying(L); + } /// Determines whether this linkage specification had braces in /// its syntactic form. @@ -3290,7 +3417,7 @@ class BaseUsingDecl : public NamedDecl { protected: BaseUsingDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) - : NamedDecl(DK, DC, L, N), FirstUsingShadow(nullptr, 0) {} + : NamedDecl(DK, DC, L, N), FirstUsingShadow(nullptr, false) {} private: void anchor() override; @@ -3476,6 +3603,7 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl { /// \c true if the constructor ultimately named by this using shadow /// declaration is within a virtual base class subobject of the class that /// contains this declaration. + LLVM_PREFERRED_TYPE(bool) unsigned IsVirtual : 1; ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, @@ -3578,17 +3706,15 @@ public: class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> { /// The source location of the 'using' keyword itself. SourceLocation UsingLocation; - - /// Location of the 'enum' keyword. + /// The source location of the 'enum' keyword. SourceLocation EnumLocation; - - /// The enum - EnumDecl *Enum; + /// 'qual::SomeEnum' as an EnumType, possibly with Elaborated/Typedef sugar. + TypeSourceInfo *EnumType; UsingEnumDecl(DeclContext *DC, DeclarationName DN, SourceLocation UL, - SourceLocation EL, SourceLocation NL, EnumDecl *ED) - : BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL), - EnumLocation(EL), Enum(ED) {} + SourceLocation EL, SourceLocation NL, TypeSourceInfo *EnumType) + : BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL), EnumLocation(EL), + EnumType(EnumType){} void anchor() override; @@ -3603,13 +3729,29 @@ public: /// The source location of the 'enum' keyword. SourceLocation getEnumLoc() const { return EnumLocation; } void setEnumLoc(SourceLocation L) { EnumLocation = L; } + NestedNameSpecifier *getQualifier() const { + return getQualifierLoc().getNestedNameSpecifier(); + } + NestedNameSpecifierLoc getQualifierLoc() const { + if (auto ETL = EnumType->getTypeLoc().getAs<ElaboratedTypeLoc>()) + return ETL.getQualifierLoc(); + return NestedNameSpecifierLoc(); + } + // Returns the "qualifier::Name" part as a TypeLoc. + TypeLoc getEnumTypeLoc() const { + return EnumType->getTypeLoc(); + } + TypeSourceInfo *getEnumType() const { + return EnumType; + } + void setEnumType(TypeSourceInfo *TSI) { EnumType = TSI; } public: - EnumDecl *getEnumDecl() const { return Enum; } + EnumDecl *getEnumDecl() const { return cast<EnumDecl>(EnumType->getType()->getAsTagDecl()); } static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation UsingL, SourceLocation EnumL, - SourceLocation NameL, EnumDecl *ED); + SourceLocation NameL, TypeSourceInfo *EnumType); static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -3677,7 +3819,7 @@ public: /// Get the set of using declarations that this pack expanded into. Note that /// some of these may still be unresolved. ArrayRef<NamedDecl *> expansions() const { - return llvm::makeArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions); + return llvm::ArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions); } static UsingPackDecl *Create(ASTContext &C, DeclContext *DC, @@ -3908,12 +4050,12 @@ public: /// Represents a C++11 static_assert declaration. class StaticAssertDecl : public Decl { llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed; - StringLiteral *Message; + Expr *Message; SourceLocation RParenLoc; StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, - SourceLocation RParenLoc, bool Failed) + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, + bool Failed) : Decl(StaticAssert, DC, StaticAssertLoc), AssertExprAndFailed(AssertExpr, Failed), Message(Message), RParenLoc(RParenLoc) {} @@ -3925,15 +4067,15 @@ public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, StringLiteral *Message, + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, bool Failed); static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID); Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); } const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); } - StringLiteral *getMessage() { return Message; } - const StringLiteral *getMessage() const { return Message; } + Expr *getMessage() { return Message; } + const Expr *getMessage() const { return Message; } bool isFailed() const { return AssertExprAndFailed.getInt(); } @@ -4047,10 +4189,10 @@ public: unsigned NumBindings); ArrayRef<BindingDecl *> bindings() const { - return llvm::makeArrayRef(getTrailingObjects<BindingDecl *>(), NumBindings); + return llvm::ArrayRef(getTrailingObjects<BindingDecl *>(), NumBindings); } - void printName(raw_ostream &os) const override; + void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decomposition; } @@ -4163,7 +4305,8 @@ private: public: /// Print this UUID in a human-readable format. - void printName(llvm::raw_ostream &OS) const override; + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; /// Get the decomposed parts of this declaration. Parts getParts() const { return PartVal; } @@ -4185,6 +4328,55 @@ public: static bool classofKind(Kind K) { return K == Decl::MSGuid; } }; +/// An artificial decl, representing a global anonymous constant value which is +/// uniquified by value within a translation unit. +/// +/// These is currently only used to back the LValue returned by +/// __builtin_source_location, but could potentially be used for other similar +/// situations in the future. +class UnnamedGlobalConstantDecl : public ValueDecl, + public Mergeable<UnnamedGlobalConstantDecl>, + public llvm::FoldingSetNode { + + // The constant value of this global. + APValue Value; + + void anchor() override; + + UnnamedGlobalConstantDecl(const ASTContext &C, DeclContext *DC, QualType T, + const APValue &Val); + + static UnnamedGlobalConstantDecl *Create(const ASTContext &C, QualType T, + const APValue &APVal); + static UnnamedGlobalConstantDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + // Only ASTContext::getUnnamedGlobalConstantDecl and deserialization create + // these. + friend class ASTContext; + friend class ASTReader; + friend class ASTDeclReader; + +public: + /// Print this in a human-readable format. + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; + + const APValue &getValue() const { return Value; } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType Ty, + const APValue &APVal) { + Ty.Profile(ID); + APVal.Profile(ID); + } + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getType(), getValue()); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::UnnamedGlobalConstant; } +}; + /// Insertion operator for diagnostics. This allows sending an AccessSpecifier /// into a diagnostic with <<. const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |