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 | 842 |
1 files changed, 587 insertions, 255 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h index 89006b1cfa7f..9cebaff63bb0 100644 --- a/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm-project/clang/include/clang/AST/DeclCXX.h @@ -64,11 +64,11 @@ class CXXFinalOverriderMap; class CXXIndirectPrimaryBaseSet; class CXXMethodDecl; class DecompositionDecl; -class DiagnosticBuilder; class FriendDecl; class FunctionTemplateDecl; class IdentifierInfo; class MemberSpecializationInfo; +class BaseUsingDecl; class TemplateDecl; class TemplateParameterList; class UsingDecl; @@ -154,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. @@ -260,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. @@ -275,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. @@ -348,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: @@ -374,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: @@ -421,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 { @@ -547,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); @@ -1034,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); @@ -1049,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>; @@ -1060,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 { @@ -1070,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 { @@ -1138,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; @@ -1159,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; } @@ -1369,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: @@ -1380,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. /// @@ -1479,7 +1540,7 @@ public: /// Returns true if the class destructor, or any implicitly invoked /// destructors are marked noreturn. - bool isAnyDestructorNoReturn() const; + bool isAnyDestructorNoReturn() const { return data().IsAnyDestructorNoReturn; } /// If the class is a local class [class.local], returns /// the enclosing function declaration. @@ -1725,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; @@ -1771,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; @@ -1786,6 +1884,7 @@ public: static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; } + void markAbstract() { data().Abstract = true; } }; /// Store information needed for an explicit specifier. @@ -1852,15 +1951,17 @@ private: CXXDeductionGuideDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, SourceLocation EndLocation) + TypeSourceInfo *TInfo, SourceLocation EndLocation, + CXXConstructorDecl *Ctor, DeductionCandidate Kind) : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, - SC_None, false, ConstexprSpecKind::Unspecified), - ExplicitSpec(ES) { + SC_None, false, false, ConstexprSpecKind::Unspecified), + Ctor(Ctor), ExplicitSpec(ES) { if (EndLocation.isValid()) setRangeEnd(EndLocation); - setIsCopyDeductionCandidate(false); + setDeductionCandidateKind(Kind); } + CXXConstructorDecl *Ctor; ExplicitSpecifier ExplicitSpec; void setExplicitSpecifier(ExplicitSpecifier ES) { ExplicitSpec = ES; } @@ -1871,14 +1972,16 @@ public: static CXXDeductionGuideDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, SourceLocation EndLocation); + TypeSourceInfo *TInfo, SourceLocation EndLocation, + 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. @@ -1886,12 +1989,17 @@ public: return getDeclName().getCXXDeductionGuideTemplate(); } - void setIsCopyDeductionCandidate(bool isCDC = true) { - FunctionDeclBits.IsCopyDeductionCandidate = isCDC; + /// Get the constructor from which this deduction guide was generated, if + /// this is an implicit deduction guide. + CXXConstructorDecl *getCorrespondingConstructor() const { return Ctor; } + + 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. @@ -1928,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. @@ -1941,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) { @@ -1984,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; @@ -2072,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(); } @@ -2166,6 +2297,10 @@ class CXXCtorInitializer final { llvm::PointerUnion<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> Initializee; + /// The argument used to initialize the base or member, which may + /// end up constructing an object (when multiple arguments are involved). + Stmt *Init; + /// The source location for the field name or, for a base initializer /// pack expansion, the location of the ellipsis. /// @@ -2174,10 +2309,6 @@ class CXXCtorInitializer final { /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; - /// The argument used to initialize the base or member, which may - /// end up constructing an object (when multiple arguments are involved). - Stmt *Init; - /// Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -2186,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 @@ -2267,7 +2401,8 @@ public: // For a pack expansion, returns the location of the ellipsis. SourceLocation getEllipsisLoc() const { - assert(isPackExpansion() && "Initializer is not a pack expansion"); + if (!isPackExpansion()) + return {}; return MemberOrEllipsisLocation; } @@ -2401,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); @@ -2424,12 +2560,12 @@ class CXXConstructorDecl final : ExplicitSpecKind::ResolvedFalse); } - enum TraillingAllocKind { + enum TrailingAllocKind { TAKInheritsConstructor = 1, TAKHasTailExplicit = 1 << 1, }; - uint64_t getTraillingAllocKind() const { + uint64_t getTrailingAllocKind() const { return numTrailingObjects(OverloadToken<InheritedConstructor>()) | (numTrailingObjects(OverloadToken<ExplicitSpecifier>()) << 1); } @@ -2444,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); @@ -2467,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. @@ -2664,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); @@ -2720,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; @@ -2738,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() { @@ -2750,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; } @@ -2775,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: @@ -2785,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; @@ -2800,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. @@ -3152,21 +3291,27 @@ public: } }; -/// Represents a shadow declaration introduced into a scope by a -/// (resolved) using declaration. +/// Represents a shadow declaration implicitly introduced into a scope by a +/// (resolved) using-declaration or using-enum-declaration to achieve +/// the desired lookup semantics. /// -/// For example, +/// For example: /// \code /// namespace A { /// void foo(); +/// void foo(int); +/// struct foo {}; +/// enum bar { bar1, bar2 }; /// } /// namespace B { -/// using A::foo; // <- a UsingDecl -/// // Also creates a UsingShadowDecl for A::foo() in B +/// // add a UsingDecl and three UsingShadowDecls (named foo) to B. +/// using A::foo; +/// // adds UsingEnumDecl and two UsingShadowDecls (named bar1 and bar2) to B. +/// using enum A::bar; /// } /// \endcode class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { - friend class UsingDecl; + friend class BaseUsingDecl; /// The referenced declaration. NamedDecl *Underlying = nullptr; @@ -3193,7 +3338,8 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { protected: UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, SourceLocation Loc, - UsingDecl *Using, NamedDecl *Target); + DeclarationName Name, BaseUsingDecl *Introducer, + NamedDecl *Target); UsingShadowDecl(Kind K, ASTContext &C, EmptyShell); public: @@ -3201,9 +3347,10 @@ public: friend class ASTDeclWriter; static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation Loc, UsingDecl *Using, - NamedDecl *Target) { - return new (C, DC) UsingShadowDecl(UsingShadow, C, DC, Loc, Using, Target); + SourceLocation Loc, DeclarationName Name, + BaseUsingDecl *Introducer, NamedDecl *Target) { + return new (C, DC) + UsingShadowDecl(UsingShadow, C, DC, Loc, Name, Introducer, Target); } static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -3241,8 +3388,9 @@ public: ~(IDNS_OrdinaryFriend | IDNS_TagFriend | IDNS_LocalExtern); } - /// Gets the using declaration to which this declaration is tied. - UsingDecl *getUsingDecl() const; + /// Gets the (written or instantiated) using declaration that introduced this + /// declaration. + BaseUsingDecl *getIntroducer() const; /// The next using shadow declaration contained in the shadow decl /// chain of the using declaration which introduced this decl. @@ -3256,6 +3404,180 @@ public: } }; +/// Represents a C++ declaration that introduces decls from somewhere else. It +/// provides a set of the shadow decls so introduced. + +class BaseUsingDecl : public NamedDecl { + /// The first shadow declaration of the shadow decl chain associated + /// with this using declaration. + /// + /// The bool member of the pair is a bool flag a derived type may use + /// (UsingDecl makes use of it). + llvm::PointerIntPair<UsingShadowDecl *, 1, bool> FirstUsingShadow; + +protected: + BaseUsingDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) + : NamedDecl(DK, DC, L, N), FirstUsingShadow(nullptr, false) {} + +private: + void anchor() override; + +protected: + /// A bool flag for use by a derived type + bool getShadowFlag() const { return FirstUsingShadow.getInt(); } + + /// A bool flag a derived type may set + void setShadowFlag(bool V) { FirstUsingShadow.setInt(V); } + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + /// Iterates through the using shadow declarations associated with + /// this using declaration. + class shadow_iterator { + /// The current using shadow declaration. + UsingShadowDecl *Current = nullptr; + + public: + using value_type = UsingShadowDecl *; + using reference = UsingShadowDecl *; + using pointer = UsingShadowDecl *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + + shadow_iterator() = default; + explicit shadow_iterator(UsingShadowDecl *C) : Current(C) {} + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + shadow_iterator &operator++() { + Current = Current->getNextUsingShadowDecl(); + return *this; + } + + shadow_iterator operator++(int) { + shadow_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(shadow_iterator x, shadow_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(shadow_iterator x, shadow_iterator y) { + return x.Current != y.Current; + } + }; + + using shadow_range = llvm::iterator_range<shadow_iterator>; + + shadow_range shadows() const { + return shadow_range(shadow_begin(), shadow_end()); + } + + shadow_iterator shadow_begin() const { + return shadow_iterator(FirstUsingShadow.getPointer()); + } + + shadow_iterator shadow_end() const { return shadow_iterator(); } + + /// Return the number of shadowed declarations associated with this + /// using declaration. + unsigned shadow_size() const { + return std::distance(shadow_begin(), shadow_end()); + } + + void addShadowDecl(UsingShadowDecl *S); + void removeShadowDecl(UsingShadowDecl *S); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Using || K == UsingEnum; } +}; + +/// Represents a C++ using-declaration. +/// +/// For example: +/// \code +/// using someNameSpace::someIdentifier; +/// \endcode +class UsingDecl : public BaseUsingDecl, public Mergeable<UsingDecl> { + /// The source location of the 'using' keyword itself. + SourceLocation UsingLocation; + + /// The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; + + /// Provides source/type location info for the declaration name + /// embedded in the ValueDecl base class. + DeclarationNameLoc DNLoc; + + UsingDecl(DeclContext *DC, SourceLocation UL, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword) + : BaseUsingDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), + UsingLocation(UL), QualifierLoc(QualifierLoc), + DNLoc(NameInfo.getInfo()) { + setShadowFlag(HasTypenameKeyword); + } + + void anchor() override; + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + /// Return the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } + + /// Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + + /// Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + + /// Return true if it is a C++03 access declaration (no 'using'). + bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } + + /// Return true if the using declaration has 'typename'. + bool hasTypename() const { return getShadowFlag(); } + + /// Sets whether the using declaration has 'typename'. + void setTypename(bool TN) { setShadowFlag(TN); } + + static UsingDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation UsingL, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, + bool HasTypenameKeyword); + + static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const override LLVM_READONLY; + + /// Retrieves the canonical declaration of this declaration. + UsingDecl *getCanonicalDecl() override { + return cast<UsingDecl>(getFirstDecl()); + } + const UsingDecl *getCanonicalDecl() const { + return cast<UsingDecl>(getFirstDecl()); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Using; } +}; + /// Represents a shadow constructor declaration introduced into a /// class by a C++11 using-declaration that names a constructor. /// @@ -3281,12 +3603,14 @@ 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, UsingDecl *Using, NamedDecl *Target, bool TargetInVirtualBase) - : UsingShadowDecl(ConstructorUsingShadow, C, DC, Loc, Using, + : UsingShadowDecl(ConstructorUsingShadow, C, DC, Loc, + Using->getDeclName(), Using, Target->getUnderlyingDecl()), NominatedBaseClassShadowDecl( dyn_cast<ConstructorUsingShadowDecl>(Target)), @@ -3319,6 +3643,12 @@ public: static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// Override the UsingShadowDecl's getIntroducer, returning the UsingDecl that + /// introduced this. + UsingDecl *getIntroducer() const { + return cast<UsingDecl>(UsingShadowDecl::getIntroducer()); + } + /// Returns the parent of this using shadow declaration, which /// is the class in which this is declared. //@{ @@ -3366,37 +3696,25 @@ public: static bool classofKind(Kind K) { return K == ConstructorUsingShadow; } }; -/// Represents a C++ using-declaration. +/// Represents a C++ using-enum-declaration. /// /// For example: /// \code -/// using someNameSpace::someIdentifier; +/// using enum SomeEnumTag ; /// \endcode -class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { + +class UsingEnumDecl : public BaseUsingDecl, public Mergeable<UsingEnumDecl> { /// The source location of the 'using' keyword itself. SourceLocation UsingLocation; + /// The source location of the 'enum' keyword. + SourceLocation EnumLocation; + /// 'qual::SomeEnum' as an EnumType, possibly with Elaborated/Typedef sugar. + TypeSourceInfo *EnumType; - /// The nested-name-specifier that precedes the name. - NestedNameSpecifierLoc QualifierLoc; - - /// Provides source/type location info for the declaration name - /// embedded in the ValueDecl base class. - DeclarationNameLoc DNLoc; - - /// The first shadow declaration of the shadow decl chain associated - /// with this using declaration. - /// - /// The bool member of the pair store whether this decl has the \c typename - /// keyword. - llvm::PointerIntPair<UsingShadowDecl *, 1, bool> FirstUsingShadow; - - UsingDecl(DeclContext *DC, SourceLocation UL, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword) - : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), - UsingLocation(UL), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) { - } + UsingEnumDecl(DeclContext *DC, DeclarationName DN, SourceLocation UL, + SourceLocation EL, SourceLocation NL, TypeSourceInfo *EnumType) + : BaseUsingDecl(UsingEnum, DC, NL, DN), UsingLocation(UL), EnumLocation(EL), + EnumType(EnumType){} void anchor() override; @@ -3404,109 +3722,51 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; - /// Return the source location of the 'using' keyword. + /// The source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } - - /// Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } - /// Retrieve the nested-name-specifier that qualifies the name, - /// with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// Retrieve the nested-name-specifier that qualifies the name. + /// The source location of the 'enum' keyword. + SourceLocation getEnumLoc() const { return EnumLocation; } + void setEnumLoc(SourceLocation L) { EnumLocation = L; } NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - DeclarationNameInfo getNameInfo() const { - return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + return getQualifierLoc().getNestedNameSpecifier(); } - - /// Return true if it is a C++03 access declaration (no 'using'). - bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } - - /// Return true if the using declaration has 'typename'. - bool hasTypename() const { return FirstUsingShadow.getInt(); } - - /// Sets whether the using declaration has 'typename'. - void setTypename(bool TN) { FirstUsingShadow.setInt(TN); } - - /// Iterates through the using shadow declarations associated with - /// this using declaration. - class shadow_iterator { - /// The current using shadow declaration. - UsingShadowDecl *Current = nullptr; - - public: - using value_type = UsingShadowDecl *; - using reference = UsingShadowDecl *; - using pointer = UsingShadowDecl *; - using iterator_category = std::forward_iterator_tag; - using difference_type = std::ptrdiff_t; - - shadow_iterator() = default; - explicit shadow_iterator(UsingShadowDecl *C) : Current(C) {} - - reference operator*() const { return Current; } - pointer operator->() const { return Current; } - - shadow_iterator& operator++() { - Current = Current->getNextUsingShadowDecl(); - return *this; - } - - shadow_iterator operator++(int) { - shadow_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(shadow_iterator x, shadow_iterator y) { - return x.Current == y.Current; - } - friend bool operator!=(shadow_iterator x, shadow_iterator y) { - return x.Current != y.Current; - } - }; - - using shadow_range = llvm::iterator_range<shadow_iterator>; - - shadow_range shadows() const { - return shadow_range(shadow_begin(), shadow_end()); + NestedNameSpecifierLoc getQualifierLoc() const { + if (auto ETL = EnumType->getTypeLoc().getAs<ElaboratedTypeLoc>()) + return ETL.getQualifierLoc(); + return NestedNameSpecifierLoc(); } - - shadow_iterator shadow_begin() const { - return shadow_iterator(FirstUsingShadow.getPointer()); + // Returns the "qualifier::Name" part as a TypeLoc. + TypeLoc getEnumTypeLoc() const { + return EnumType->getTypeLoc(); } - - shadow_iterator shadow_end() const { return shadow_iterator(); } - - /// Return the number of shadowed declarations associated with this - /// using declaration. - unsigned shadow_size() const { - return std::distance(shadow_begin(), shadow_end()); + TypeSourceInfo *getEnumType() const { + return EnumType; } + void setEnumType(TypeSourceInfo *TSI) { EnumType = TSI; } - void addShadowDecl(UsingShadowDecl *S); - void removeShadowDecl(UsingShadowDecl *S); +public: + EnumDecl *getEnumDecl() const { return cast<EnumDecl>(EnumType->getType()->getAsTagDecl()); } - static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation UsingL, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, - bool HasTypenameKeyword); + static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation UsingL, SourceLocation EnumL, + SourceLocation NameL, TypeSourceInfo *EnumType); - static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); + static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); SourceRange getSourceRange() const override LLVM_READONLY; /// Retrieves the canonical declaration of this declaration. - UsingDecl *getCanonicalDecl() override { return getFirstDecl(); } - const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); } + UsingEnumDecl *getCanonicalDecl() override { + return cast<UsingEnumDecl>(getFirstDecl()); + } + const UsingEnumDecl *getCanonicalDecl() const { + return cast<UsingEnumDecl>(getFirstDecl()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Using; } + static bool classofKind(Kind K) { return K == UsingEnum; } }; /// Represents a pack of using declarations that a single @@ -3559,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, @@ -3765,15 +4025,37 @@ public: static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } }; +/// This node is generated when a using-declaration that was annotated with +/// __attribute__((using_if_exists)) failed to resolve to a known declaration. +/// In that case, Sema builds a UsingShadowDecl whose target is an instance of +/// this declaration, adding it to the current scope. Referring to this +/// declaration in any way is an error. +class UnresolvedUsingIfExistsDecl final : public NamedDecl { + UnresolvedUsingIfExistsDecl(DeclContext *DC, SourceLocation Loc, + DeclarationName Name); + + void anchor() override; + +public: + static UnresolvedUsingIfExistsDecl *Create(ASTContext &Ctx, DeclContext *DC, + SourceLocation Loc, + DeclarationName Name); + static UnresolvedUsingIfExistsDecl *CreateDeserialized(ASTContext &Ctx, + unsigned ID); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingIfExists; } +}; + /// 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) {} @@ -3785,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(); } @@ -3817,7 +4099,7 @@ public: /// DecompositionDecl of type 'int (&)[3]'. class BindingDecl : public ValueDecl { /// The declaration that this binding binds to part of. - LazyDeclPtr Decomp; + ValueDecl *Decomp; /// The binding represented by this declaration. References to this /// declaration are effectively equivalent to this expression (except /// that it is only evaluated once at the point of declaration of the @@ -3843,7 +4125,7 @@ public: /// Get the decomposition declaration that this binding represents a /// decomposition of. - ValueDecl *getDecomposedDecl() const; + ValueDecl *getDecomposedDecl() const { return Decomp; } /// Get the variable (if any) that holds the value of evaluating the binding. /// Only present for user-defined bindings for tuple-like types. @@ -3907,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; } @@ -4023,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; } @@ -4045,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, |