diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/DeclCXX.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/DeclCXX.cpp | 621 |
1 files changed, 388 insertions, 233 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp b/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp index aeee35d9c74f..117e802dae2d 100644 --- a/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp @@ -36,7 +36,7 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" -#include "llvm/ADT/None.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" @@ -79,10 +79,9 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasBasesWithFields(false), HasBasesWithNonStaticDataMembers(false), HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false), - HasOnlyCMembers(true), HasInClassInitializer(false), + HasOnlyCMembers(true), HasInitMethod(false), HasInClassInitializer(false), HasUninitializedReferenceMember(false), HasUninitializedFields(false), - HasInheritedConstructor(false), - HasInheritedDefaultConstructor(false), + HasInheritedConstructor(false), HasInheritedDefaultConstructor(false), HasInheritedAssignment(false), NeedOverloadResolutionForCopyConstructor(false), NeedOverloadResolutionForMoveConstructor(false), @@ -147,25 +146,25 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, CXXRecordDecl * CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool Dependent, bool IsGeneric, + unsigned DependencyKind, bool IsGeneric, LambdaCaptureDefault CaptureDefault) { - auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc, - nullptr, nullptr); + auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TagTypeKind::Class, C, DC, Loc, + Loc, nullptr, nullptr); R->setBeingDefined(true); - R->DefinitionData = - new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric, - CaptureDefault); + R->DefinitionData = new (C) struct LambdaDefinitionData( + R, Info, DependencyKind, IsGeneric, CaptureDefault); R->setMayHaveOutOfDateDef(false); R->setImplicit(true); + C.getTypeDeclType(R, /*PrevDecl=*/nullptr); return R; } CXXRecordDecl * CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - auto *R = new (C, ID) CXXRecordDecl( - CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(), - nullptr, nullptr); + auto *R = new (C, ID) + CXXRecordDecl(CXXRecord, TagTypeKind::Struct, C, nullptr, + SourceLocation(), SourceLocation(), nullptr, nullptr); R->setMayHaveOutOfDateDef(false); return R; } @@ -178,6 +177,8 @@ static bool hasRepeatedBaseClass(const CXXRecordDecl *StartRD) { SmallVector<const CXXRecordDecl*, 8> WorkList = {StartRD}; while (!WorkList.empty()) { const CXXRecordDecl *RD = WorkList.pop_back_val(); + if (RD->getTypeForDecl()->isDependentType()) + continue; for (const CXXBaseSpecifier &BaseSpec : RD->bases()) { if (const CXXRecordDecl *B = BaseSpec.getType()->getAsCXXRecordDecl()) { if (!SeenBaseTypes.insert(B).second) @@ -445,8 +446,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, setHasVolatileMember(true); if (BaseClassDecl->getArgPassingRestrictions() == - RecordDecl::APK_CanNeverPassInRegs) - setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs); + RecordArgPassingKind::CanNeverPassInRegs) + setArgPassingRestrictions(RecordArgPassingKind::CanNeverPassInRegs); // Keep track of the presence of mutable fields. if (BaseClassDecl->hasMutableFields()) @@ -586,6 +587,19 @@ bool CXXRecordDecl::isTriviallyCopyable() const { return true; } +bool CXXRecordDecl::isTriviallyCopyConstructible() const { + + // A trivially copy constructible class is a class that: + // -- has no non-trivial copy constructors, + if (hasNonTrivialCopyConstructor()) + return false; + // -- has a trivial destructor. + if (!hasTrivialDestructor()) + return false; + + return true; +} + void CXXRecordDecl::markedVirtualFunctionPure() { // C++ [class.abstract]p2: // A class is abstract if it has at least one pure virtual function. @@ -685,17 +699,16 @@ bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const { // C++17 [expr.prim.lambda]p21: // The closure type associated with a lambda-expression has no default // constructor and a deleted copy assignment operator. - if (getLambdaCaptureDefault() != LCD_None || capture_size() != 0) + if (!isCapturelessLambda()) return false; return getASTContext().getLangOpts().CPlusPlus20; } void CXXRecordDecl::addedMember(Decl *D) { - if (!D->isImplicit() && - !isa<FieldDecl>(D) && - !isa<IndirectFieldDecl>(D) && - (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class || - cast<TagDecl>(D)->getTagKind() == TTK_Interface)) + if (!D->isImplicit() && !isa<FieldDecl>(D) && !isa<IndirectFieldDecl>(D) && + (!isa<TagDecl>(D) || + cast<TagDecl>(D)->getTagKind() == TagTypeKind::Class || + cast<TagDecl>(D)->getTagKind() == TagTypeKind::Interface)) data().HasOnlyCMembers = false; // Ignore friends and invalid declarations. @@ -767,12 +780,16 @@ void CXXRecordDecl::addedMember(Decl *D) { // Note that we have a user-declared constructor. data().UserDeclaredConstructor = true; - // C++ [class]p4: - // A POD-struct is an aggregate class [...] - // Since the POD bit is meant to be C++03 POD-ness, clear it even if - // the type is technically an aggregate in C++0x since it wouldn't be - // in 03. - data().PlainOldData = false; + const TargetInfo &TI = getASTContext().getTargetInfo(); + if ((!Constructor->isDeleted() && !Constructor->isDefaulted()) || + !TI.areDefaultedSMFStillPOD(getLangOpts())) { + // C++ [class]p4: + // A POD-struct is an aggregate class [...] + // Since the POD bit is meant to be C++03 POD-ness, clear it even if + // the type is technically an aggregate in C++0x since it wouldn't be + // in 03. + data().PlainOldData = false; + } } if (Constructor->isDefaultConstructor()) { @@ -824,34 +841,16 @@ void CXXRecordDecl::addedMember(Decl *D) { data().HasInheritedDefaultConstructor = true; } - // Handle destructors. - if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) { - SMKind |= SMF_Destructor; - - if (DD->isUserProvided()) - data().HasIrrelevantDestructor = false; - // If the destructor is explicitly defaulted and not trivial or not public - // or if the destructor is deleted, we clear HasIrrelevantDestructor in - // finishedDefaultedOrDeletedMember. - - // C++11 [class.dtor]p5: - // A destructor is trivial if [...] the destructor is not virtual. - if (DD->isVirtual()) { - data().HasTrivialSpecialMembers &= ~SMF_Destructor; - data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor; - } - - if (DD->isNoReturn()) - data().IsAnyDestructorNoReturn = true; - } - // Handle member functions. if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) { + if (isa<CXXDestructorDecl>(D)) + SMKind |= SMF_Destructor; + if (Method->isCopyAssignmentOperator()) { SMKind |= SMF_CopyAssignment; const auto *ParamTy = - Method->getParamDecl(0)->getType()->getAs<ReferenceType>(); + Method->getNonObjectParameter(0)->getType()->getAs<ReferenceType>(); if (!ParamTy || ParamTy->getPointeeType().isConstQualified()) data().HasDeclaredCopyAssignmentWithConstParam = true; } @@ -892,46 +891,38 @@ void CXXRecordDecl::addedMember(Decl *D) { data().HasTrivialSpecialMembersForCall &= data().DeclaredSpecialMembers | ~SMKind; - if (!Method->isImplicit() && !Method->isUserProvided()) { - // This method is user-declared but not user-provided. We can't work out - // whether it's trivial yet (not until we get to the end of the class). - // We'll handle this method in finishedDefaultedOrDeletedMember. - } else if (Method->isTrivial()) { - data().HasTrivialSpecialMembers |= SMKind; - data().HasTrivialSpecialMembersForCall |= SMKind; - } else if (Method->isTrivialForCall()) { - data().HasTrivialSpecialMembersForCall |= SMKind; - data().DeclaredNonTrivialSpecialMembers |= SMKind; - } else { - data().DeclaredNonTrivialSpecialMembers |= SMKind; - // If this is a user-provided function, do not set - // DeclaredNonTrivialSpecialMembersForCall here since we don't know - // yet whether the method would be considered non-trivial for the - // purpose of calls (attribute "trivial_abi" can be dropped from the - // class later, which can change the special method's triviality). - if (!Method->isUserProvided()) - data().DeclaredNonTrivialSpecialMembersForCall |= SMKind; - } - // Note when we have declared a declared special member, and suppress the // implicit declaration of this special member. data().DeclaredSpecialMembers |= SMKind; - if (!Method->isImplicit()) { data().UserDeclaredSpecialMembers |= SMKind; - // C++03 [class]p4: - // A POD-struct is an aggregate class that has [...] no user-defined - // copy assignment operator and no user-defined destructor. - // - // Since the POD bit is meant to be C++03 POD-ness, and in C++03, - // aggregates could not have any constructors, clear it even for an - // explicitly defaulted or deleted constructor. - // type is technically an aggregate in C++0x since it wouldn't be in 03. - // - // Also, a user-declared move assignment operator makes a class non-POD. - // This is an extension in C++03. - data().PlainOldData = false; + const TargetInfo &TI = getASTContext().getTargetInfo(); + if ((!Method->isDeleted() && !Method->isDefaulted() && + SMKind != SMF_MoveAssignment) || + !TI.areDefaultedSMFStillPOD(getLangOpts())) { + // C++03 [class]p4: + // A POD-struct is an aggregate class that has [...] no user-defined + // copy assignment operator and no user-defined destructor. + // + // Since the POD bit is meant to be C++03 POD-ness, and in C++03, + // aggregates could not have any constructors, clear it even for an + // explicitly defaulted or deleted constructor. + // type is technically an aggregate in C++0x since it wouldn't be in + // 03. + // + // Also, a user-declared move assignment operator makes a class + // non-POD. This is an extension in C++03. + data().PlainOldData = false; + } + } + // When instantiating a class, we delay updating the destructor and + // triviality properties of the class until selecting a destructor and + // computing the eligibility of its special member functions. This is + // because there might be function constraints that we need to evaluate + // and compare later in the instantiation. + if (!Method->isIneligibleOrNotSelected()) { + addedEligibleSpecialMemberFunction(Method, SMKind); } } @@ -1053,7 +1044,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // Structs with __weak fields should never be passed directly. if (LT == Qualifiers::OCL_Weak) - setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs); + setArgPassingRestrictions(RecordArgPassingKind::CanNeverPassInRegs); Data.HasIrrelevantDestructor = false; @@ -1247,8 +1238,8 @@ void CXXRecordDecl::addedMember(Decl *D) { if (FieldRec->hasVolatileMember()) setHasVolatileMember(true); if (FieldRec->getArgPassingRestrictions() == - RecordDecl::APK_CanNeverPassInRegs) - setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs); + RecordArgPassingKind::CanNeverPassInRegs) + setArgPassingRestrictions(RecordArgPassingKind::CanNeverPassInRegs); // C++0x [class]p7: // A standard-layout class is a class that: @@ -1392,6 +1383,83 @@ void CXXRecordDecl::addedMember(Decl *D) { } } +bool CXXRecordDecl::isLiteral() const { + const LangOptions &LangOpts = getLangOpts(); + if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor() + : hasTrivialDestructor())) + return false; + + if (hasNonLiteralTypeFieldsOrBases()) { + // CWG2598 + // is an aggregate union type that has either no variant + // members or at least one variant member of non-volatile literal type, + if (!isUnion()) + return false; + bool HasAtLeastOneLiteralMember = + fields().empty() || any_of(fields(), [this](const FieldDecl *D) { + return !D->getType().isVolatileQualified() && + D->getType()->isLiteralType(getASTContext()); + }); + if (!HasAtLeastOneLiteralMember) + return false; + } + + return isAggregate() || (isLambda() && LangOpts.CPlusPlus17) || + hasConstexprNonCopyMoveConstructor() || hasTrivialDefaultConstructor(); +} + +void CXXRecordDecl::addedSelectedDestructor(CXXDestructorDecl *DD) { + DD->setIneligibleOrNotSelected(false); + addedEligibleSpecialMemberFunction(DD, SMF_Destructor); +} + +void CXXRecordDecl::addedEligibleSpecialMemberFunction(const CXXMethodDecl *MD, + unsigned SMKind) { + // FIXME: We shouldn't change DeclaredNonTrivialSpecialMembers if `MD` is + // a function template, but this needs CWG attention before we break ABI. + // See https://github.com/llvm/llvm-project/issues/59206 + + if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) { + if (DD->isUserProvided()) + data().HasIrrelevantDestructor = false; + // If the destructor is explicitly defaulted and not trivial or not public + // or if the destructor is deleted, we clear HasIrrelevantDestructor in + // finishedDefaultedOrDeletedMember. + + // C++11 [class.dtor]p5: + // A destructor is trivial if [...] the destructor is not virtual. + if (DD->isVirtual()) { + data().HasTrivialSpecialMembers &= ~SMF_Destructor; + data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor; + } + + if (DD->isNoReturn()) + data().IsAnyDestructorNoReturn = true; + } + + if (!MD->isImplicit() && !MD->isUserProvided()) { + // This method is user-declared but not user-provided. We can't work + // out whether it's trivial yet (not until we get to the end of the + // class). We'll handle this method in + // finishedDefaultedOrDeletedMember. + } else if (MD->isTrivial()) { + data().HasTrivialSpecialMembers |= SMKind; + data().HasTrivialSpecialMembersForCall |= SMKind; + } else if (MD->isTrivialForCall()) { + data().HasTrivialSpecialMembersForCall |= SMKind; + data().DeclaredNonTrivialSpecialMembers |= SMKind; + } else { + data().DeclaredNonTrivialSpecialMembers |= SMKind; + // If this is a user-provided function, do not set + // DeclaredNonTrivialSpecialMembersForCall here since we don't know + // yet whether the method would be considered non-trivial for the + // purpose of calls (attribute "trivial_abi" can be dropped from the + // class later, which can change the special method's triviality). + if (!MD->isUserProvided()) + data().DeclaredNonTrivialSpecialMembersForCall |= SMKind; + } +} + void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { assert(!D->isImplicit() && !D->isUserProvided()); @@ -1422,10 +1490,21 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { // Update which trivial / non-trivial special members we have. // addedMember will have skipped this step for this member. - if (D->isTrivial()) - data().HasTrivialSpecialMembers |= SMKind; - else - data().DeclaredNonTrivialSpecialMembers |= SMKind; + if (!D->isIneligibleOrNotSelected()) { + if (D->isTrivial()) + data().HasTrivialSpecialMembers |= SMKind; + else + data().DeclaredNonTrivialSpecialMembers |= SMKind; + } +} + +void CXXRecordDecl::LambdaDefinitionData::AddCaptureList(ASTContext &Ctx, + Capture *CaptureList) { + Captures.push_back(CaptureList); + if (Captures.size() == 2) { + // The TinyPtrVector member now needs destruction. + Ctx.addDestruction(&Captures); + } } void CXXRecordDecl::setCaptures(ASTContext &Context, @@ -1435,14 +1514,15 @@ void CXXRecordDecl::setCaptures(ASTContext &Context, // Copy captures. Data.NumCaptures = Captures.size(); Data.NumExplicitCaptures = 0; - Data.Captures = (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * - Captures.size()); - LambdaCapture *ToCapture = Data.Captures; + auto *ToCapture = (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * + Captures.size()); + Data.AddCaptureList(Context, ToCapture); for (unsigned I = 0, N = Captures.size(); I != N; ++I) { if (Captures[I].isExplicit()) ++Data.NumExplicitCaptures; - *ToCapture++ = Captures[I]; + new (ToCapture) LambdaCapture(Captures[I]); + ToCapture++; } if (!lambdaIsDefaultConstructibleAndAssignable()) @@ -1467,7 +1547,8 @@ void CXXRecordDecl::setTrivialForCallFlags(CXXMethodDecl *D) { } bool CXXRecordDecl::isCLike() const { - if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface || + if (getTagKind() == TagTypeKind::Class || + getTagKind() == TagTypeKind::Interface || !TemplateOrInstantiation.isNull()) return false; if (!hasDefinition()) @@ -1555,21 +1636,23 @@ CXXMethodDecl *CXXRecordDecl::getLambdaStaticInvoker(CallingConv CC) const { } void CXXRecordDecl::getCaptureFields( - llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, - FieldDecl *&ThisCapture) const { + llvm::DenseMap<const ValueDecl *, FieldDecl *> &Captures, + FieldDecl *&ThisCapture) const { Captures.clear(); ThisCapture = nullptr; LambdaDefinitionData &Lambda = getLambdaData(); - RecordDecl::field_iterator Field = field_begin(); - for (const LambdaCapture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures; - C != CEnd; ++C, ++Field) { - if (C->capturesThis()) - ThisCapture = *Field; - else if (C->capturesVariable()) - Captures[C->getCapturedVar()] = *Field; + for (const LambdaCapture *List : Lambda.Captures) { + RecordDecl::field_iterator Field = field_begin(); + for (const LambdaCapture *C = List, *CEnd = C + Lambda.NumCaptures; + C != CEnd; ++C, ++Field) { + if (C->capturesThis()) + ThisCapture = *Field; + else if (C->capturesVariable()) + Captures[C->getCapturedVar()] = *Field; + } + assert(Field == field_end()); } - assert(Field == field_end()); } TemplateParameterList * @@ -1593,7 +1676,7 @@ CXXRecordDecl::getLambdaExplicitTemplateParameters() const { const auto ExplicitEnd = llvm::partition_point( *List, [](const NamedDecl *D) { return !D->isImplicit(); }); - return llvm::makeArrayRef(List->begin(), ExplicitEnd); + return llvm::ArrayRef(List->begin(), ExplicitEnd); } Decl *CXXRecordDecl::getLambdaContextDecl() const { @@ -1602,18 +1685,20 @@ Decl *CXXRecordDecl::getLambdaContextDecl() const { return getLambdaData().ContextDecl.get(Source); } -void CXXRecordDecl::setDeviceLambdaManglingNumber(unsigned Num) const { +void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) { assert(isLambda() && "Not a lambda closure type!"); - if (Num) - getASTContext().DeviceLambdaManglingNumbers[this] = Num; + getLambdaData().ManglingNumber = Numbering.ManglingNumber; + if (Numbering.DeviceManglingNumber) + getASTContext().DeviceLambdaManglingNumbers[this] = + Numbering.DeviceManglingNumber; + getLambdaData().IndexInContext = Numbering.IndexInContext; + getLambdaData().ContextDecl = Numbering.ContextDecl; + getLambdaData().HasKnownInternalLinkage = Numbering.HasKnownInternalLinkage; } unsigned CXXRecordDecl::getDeviceLambdaManglingNumber() const { assert(isLambda() && "Not a lambda closure type!"); - auto I = getASTContext().DeviceLambdaManglingNumbers.find(this); - if (I != getASTContext().DeviceLambdaManglingNumbers.end()) - return I->second; - return 0; + return getASTContext().DeviceLambdaManglingNumbers.lookup(this); } static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { @@ -1776,7 +1861,7 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { for (unsigned I = 0, E = Convs.size(); I != E; ++I) { if (Convs[I].getDecl() == ConvDecl) { Convs.erase(I); - assert(llvm::find(Convs, ConvDecl) == Convs.end() && + assert(!llvm::is_contained(Convs, ConvDecl) && "conversion was found multiple times in unresolved set"); return; } @@ -1894,7 +1979,14 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { DeclContext::lookup_result R = lookup(Name); - return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front()); + // If a destructor was marked as not selected, we skip it. We don't always + // have a selected destructor: dependent types, unnamed structs. + for (auto *Decl : R) { + auto* DD = dyn_cast<CXXDestructorDecl>(Decl); + if (DD && !DD->isIneligibleOrNotSelected()) + return DD; + } + return nullptr; } static bool isDeclContextInNamespace(const DeclContext *DC) { @@ -1987,7 +2079,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { // A class is abstract if it contains or inherits at least one // pure virtual function for which the final overrider is pure // virtual. - if (SO->second.front().Method->isPure()) { + if (SO->second.front().Method->isPureVirtual()) { data().Abstract = true; Done = true; break; @@ -2059,21 +2151,21 @@ ExplicitSpecifier ExplicitSpecifier::getFromDecl(FunctionDecl *Function) { } } -CXXDeductionGuideDecl * -CXXDeductionGuideDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, ExplicitSpecifier ES, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, SourceLocation EndLocation, - CXXConstructorDecl *Ctor) { +CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( + ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor, + DeductionCandidate Kind) { return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T, - TInfo, EndLocation, Ctor); + TInfo, EndLocation, Ctor, Kind); } CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXDeductionGuideDecl( C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(), - QualType(), nullptr, SourceLocation(), nullptr); + QualType(), nullptr, SourceLocation(), nullptr, + DeductionCandidate::Normal); } RequiresExprBodyDecl *RequiresExprBodyDecl::Create( @@ -2156,12 +2248,9 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, } // Other candidate final overriders might be overridden by this function. - FinalOverriders.erase( - std::remove_if(FinalOverriders.begin(), FinalOverriders.end(), - [&](CXXMethodDecl *OtherD) { - return recursivelyOverrides(D, OtherD); - }), - FinalOverriders.end()); + llvm::erase_if(FinalOverriders, [&](CXXMethodDecl *OtherD) { + return recursivelyOverrides(D, OtherD); + }); FinalOverriders.push_back(D); }; @@ -2178,25 +2267,23 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, return FinalOverriders.size() == 1 ? FinalOverriders.front() : nullptr; } -CXXMethodDecl *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) { - return new (C, RD) - CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, - isInline, ConstexprKind, EndLocation, - TrailingRequiresClause); +CXXMethodDecl * +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) { + return new (C, RD) CXXMethodDecl( + CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, + isInline, ConstexprKind, EndLocation, TrailingRequiresClause); } CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) - CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(), - DeclarationNameInfo(), QualType(), nullptr, SC_None, false, - ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); + return new (C, ID) CXXMethodDecl( + CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(), + QualType(), nullptr, SC_None, false, false, + ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); } CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, @@ -2211,7 +2298,7 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, // If the member function is marked 'final', we know that it can't be // overridden and can therefore devirtualize it unless it's pure virtual. if (hasAttr<FinalAttr>()) - return isPure() ? nullptr : this; + return isPureVirtual() ? nullptr : this; // If Base is unknown, we cannot devirtualize. if (!Base) @@ -2240,7 +2327,7 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, // If that method is pure virtual, we can't devirtualize. If this code is // reached, the result would be UB, not a direct call to the derived class // function, and we can't assume the derived class function is defined. - if (DevirtualizedMethod->isPure()) + if (DevirtualizedMethod->isPureVirtual()) return nullptr; // If that method is marked final, we can devirtualize it. @@ -2339,7 +2426,7 @@ bool CXXMethodDecl::isUsualDeallocationFunction( // In C++17 onwards, all potential usual deallocation functions are actual // usual deallocation functions. Honor this behavior when post-C++14 // deallocation functions are offered as extensions too. - // FIXME(EricWF): Destrying Delete should be a language option. How do we + // FIXME(EricWF): Destroying Delete should be a language option. How do we // handle when destroying delete is used prior to C++17? if (Context.getLangOpts().CPlusPlus17 || Context.getLangOpts().AlignedAllocation || @@ -2361,6 +2448,17 @@ bool CXXMethodDecl::isUsualDeallocationFunction( return Result; } +bool CXXMethodDecl::isExplicitObjectMemberFunction() const { + // C++2b [dcl.fct]p6: + // An explicit object member function is a non-static member + // function with an explicit object parameter + return !isStatic() && hasCXXExplicitFunctionObjectParameter(); +} + +bool CXXMethodDecl::isImplicitObjectMemberFunction() const { + return !isStatic() && !hasCXXExplicitFunctionObjectParameter(); +} + bool CXXMethodDecl::isCopyAssignmentOperator() const { // C++0x [class.copy]p17: // A user-declared copy assignment operator X::operator= is a non-static @@ -2368,11 +2466,12 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const { // type X, X&, const X&, volatile X& or const volatile X&. if (/*operator=*/getOverloadedOperator() != OO_Equal || /*non-static*/ isStatic() || - /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() || - getNumParams() != 1) + + /*non-template*/ getPrimaryTemplate() || getDescribedFunctionTemplate() || + getNumExplicitParams() != 1) return false; - QualType ParamType = getParamDecl(0)->getType(); + QualType ParamType = getNonObjectParameter(0)->getType(); if (const auto *Ref = ParamType->getAs<LValueReferenceType>()) ParamType = Ref->getPointeeType(); @@ -2389,11 +2488,11 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const { // X&&, const X&&, volatile X&&, or const volatile X&&. if (getOverloadedOperator() != OO_Equal || isStatic() || getPrimaryTemplate() || getDescribedFunctionTemplate() || - getNumParams() != 1) + getNumExplicitParams() != 1) return false; - QualType ParamType = getParamDecl(0)->getType(); - if (!isa<RValueReferenceType>(ParamType)) + QualType ParamType = getNonObjectParameter(0)->getType(); + if (!ParamType->isRValueReferenceType()) return false; ParamType = ParamType->getPointeeType(); @@ -2444,13 +2543,8 @@ QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl) { ASTContext &C = Decl->getASTContext(); QualType ObjectTy = ::getThisObjectType(C, FPT, Decl); - return C.getPointerType(ObjectTy); -} - -QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl) { - ASTContext &C = Decl->getASTContext(); - return ::getThisObjectType(C, FPT, Decl); + return C.getLangOpts().HLSL ? C.getLValueReferenceType(ObjectTy) + : C.getPointerType(ObjectTy); } QualType CXXMethodDecl::getThisType() const { @@ -2464,11 +2558,17 @@ QualType CXXMethodDecl::getThisType() const { getParent()); } -QualType CXXMethodDecl::getThisObjectType() const { - // Ditto getThisType. - assert(isInstance() && "No 'this' for static methods!"); - return CXXMethodDecl::getThisObjectType( - getType()->castAs<FunctionProtoType>(), getParent()); +QualType CXXMethodDecl::getFunctionObjectParameterReferenceType() const { + if (isExplicitObjectMemberFunction()) + return parameters()[0]->getType(); + + ASTContext &C = getParentASTContext(); + const FunctionProtoType *FPT = getType()->castAs<FunctionProtoType>(); + QualType Type = ::getThisObjectType(C, FPT, getParent()); + RefQualifierKind RK = FPT->getRefQualifier(); + if (RK == RefQualifierKind::RQ_RValue) + return C.getRValueReferenceType(Type); + return C.getLValueReferenceType(Type); } bool CXXMethodDecl::hasInlineBody() const { @@ -2549,7 +2649,7 @@ SourceLocation CXXCtorInitializer::getSourceLocation() const { return getMemberLocation(); if (const auto *TSInfo = Initializee.get<TypeSourceInfo *>()) - return TSInfo->getTypeLoc().getLocalSourceRange().getBegin(); + return TSInfo->getTypeLoc().getBeginLoc(); return {}; } @@ -2568,12 +2668,12 @@ SourceRange CXXCtorInitializer::getSourceRange() const { CXXConstructorDecl::CXXConstructorDecl( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, - Expr *TrailingRequiresClause) + ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, + InheritedConstructor Inherited, Expr *TrailingRequiresClause) : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause) { + SC_None, UsesFPIntrin, isInline, ConstexprKind, + SourceLocation(), TrailingRequiresClause) { setNumCtorInitializers(0); setInheritingConstructor(static_cast<bool>(Inherited)); setImplicit(isImplicitlyDeclared); @@ -2596,7 +2696,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, isInheritingConstructor, hasTrailingExplicit); auto *Result = new (C, ID, Extra) CXXConstructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - ExplicitSpecifier(), false, false, ConstexprSpecKind::Unspecified, + ExplicitSpecifier(), false, false, false, ConstexprSpecKind::Unspecified, InheritedConstructor(), nullptr); Result->setInheritingConstructor(isInheritingConstructor); Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier = @@ -2608,19 +2708,18 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, CXXConstructorDecl *CXXConstructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, - Expr *TrailingRequiresClause) { + ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, + InheritedConstructor Inherited, Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); unsigned Extra = additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>( Inherited ? 1 : 0, ES.getExpr() ? 1 : 0); - return new (C, RD, Extra) - CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline, - isImplicitlyDeclared, ConstexprKind, Inherited, - TrailingRequiresClause); + return new (C, RD, Extra) CXXConstructorDecl( + C, RD, StartLoc, NameInfo, T, TInfo, ES, UsesFPIntrin, isInline, + isImplicitlyDeclared, ConstexprKind, Inherited, TrailingRequiresClause); } CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { @@ -2737,21 +2836,20 @@ CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXDestructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, false, ConstexprSpecKind::Unspecified, nullptr); + false, false, false, ConstexprSpecKind::Unspecified, nullptr); } CXXDestructorDecl *CXXDestructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause) { + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, + ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); - return new (C, RD) - CXXDestructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, - isImplicitlyDeclared, ConstexprKind, - TrailingRequiresClause); + return new (C, RD) CXXDestructorDecl( + C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline, + isImplicitlyDeclared, ConstexprKind, TrailingRequiresClause); } void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { @@ -2770,21 +2868,22 @@ CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXConversionDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, + false, false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); } CXXConversionDecl *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) { + bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); - return new (C, RD) - CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, ES, - ConstexprKind, EndLocation, TrailingRequiresClause); + return new (C, RD) CXXConversionDecl( + C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline, ES, + ConstexprKind, EndLocation, TrailingRequiresClause); } bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { @@ -2793,8 +2892,8 @@ bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { } LinkageSpecDecl::LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, - SourceLocation LangLoc, LanguageIDs lang, - bool HasBraces) + SourceLocation LangLoc, + LinkageSpecLanguageIDs lang, bool HasBraces) : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), ExternLoc(ExternLoc), RBraceLoc(SourceLocation()) { setLanguage(lang); @@ -2803,19 +2902,19 @@ LinkageSpecDecl::LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, void LinkageSpecDecl::anchor() {} -LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, - DeclContext *DC, +LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation ExternLoc, SourceLocation LangLoc, - LanguageIDs Lang, + LinkageSpecLanguageIDs Lang, bool HasBraces) { return new (C, DC) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, HasBraces); } LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) LinkageSpecDecl(nullptr, SourceLocation(), - SourceLocation(), lang_c, false); + return new (C, ID) + LinkageSpecDecl(nullptr, SourceLocation(), SourceLocation(), + LinkageSpecLanguageIDs::C, false); } void UsingDirectiveDecl::anchor() {} @@ -2849,41 +2948,47 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, NamespaceDecl *PrevDecl) + IdentifierInfo *Id, NamespaceDecl *PrevDecl, + bool Nested) : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), - redeclarable_base(C), LocStart(StartLoc), - AnonOrFirstNamespaceAndInline(nullptr, Inline) { + redeclarable_base(C), LocStart(StartLoc) { + unsigned Flags = 0; + if (Inline) + Flags |= F_Inline; + if (Nested) + Flags |= F_Nested; + AnonOrFirstNamespaceAndFlags = {nullptr, Flags}; setPreviousDecl(PrevDecl); if (PrevDecl) - AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace()); + AnonOrFirstNamespaceAndFlags.setPointer(PrevDecl->getOriginalNamespace()); } NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, - NamespaceDecl *PrevDecl) { - return new (C, DC) NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id, - PrevDecl); + NamespaceDecl *PrevDecl, bool Nested) { + return new (C, DC) + NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id, PrevDecl, Nested); } NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(), - SourceLocation(), nullptr, nullptr); + SourceLocation(), nullptr, nullptr, false); } NamespaceDecl *NamespaceDecl::getOriginalNamespace() { if (isFirstDecl()) return this; - return AnonOrFirstNamespaceAndInline.getPointer(); + return AnonOrFirstNamespaceAndFlags.getPointer(); } const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const { if (isFirstDecl()) return this; - return AnonOrFirstNamespaceAndInline.getPointer(); + return AnonOrFirstNamespaceAndFlags.getPointer(); } bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); } @@ -2973,8 +3078,10 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, BaseUsingDecl *Introducer, NamedDecl *Target) : NamedDecl(K, DC, Loc, Name), redeclarable_base(C), UsingOrNextShadow(Introducer) { - if (Target) + if (Target) { + assert(!isa<UsingShadowDecl>(Target)); setTargetDecl(Target); + } setImplicit(); } @@ -3017,8 +3124,7 @@ CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const { void BaseUsingDecl::anchor() {} void BaseUsingDecl::addShadowDecl(UsingShadowDecl *S) { - assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() && - "declaration already in set"); + assert(!llvm::is_contained(shadows(), S) && "declaration already in set"); assert(S->getIntroducer() == this); if (FirstUsingShadow.getPointer()) @@ -3027,8 +3133,7 @@ void BaseUsingDecl::addShadowDecl(UsingShadowDecl *S) { } void BaseUsingDecl::removeShadowDecl(UsingShadowDecl *S) { - assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() && - "declaration not in set"); + assert(llvm::is_contained(shadows(), S) && "declaration not in set"); assert(S->getIntroducer() == this); // Remove S from the shadow decl chain. This is O(n) but hopefully rare. @@ -3071,18 +3176,23 @@ SourceRange UsingDecl::getSourceRange() const { void UsingEnumDecl::anchor() {} UsingEnumDecl *UsingEnumDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation UL, SourceLocation EL, - SourceLocation NL, EnumDecl *Enum) { - return new (C, DC) UsingEnumDecl(DC, Enum->getDeclName(), UL, EL, NL, Enum); + SourceLocation UL, + SourceLocation EL, + SourceLocation NL, + TypeSourceInfo *EnumType) { + assert(isa<EnumDecl>(EnumType->getType()->getAsTagDecl())); + return new (C, DC) + UsingEnumDecl(DC, EnumType->getType()->getAsTagDecl()->getDeclName(), UL, EL, NL, EnumType); } UsingEnumDecl *UsingEnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) UsingEnumDecl(nullptr, DeclarationName(), SourceLocation(), - SourceLocation(), SourceLocation(), nullptr); + return new (C, ID) + UsingEnumDecl(nullptr, DeclarationName(), SourceLocation(), + SourceLocation(), SourceLocation(), nullptr); } SourceRange UsingEnumDecl::getSourceRange() const { - return SourceRange(EnumLocation, getLocation()); + return SourceRange(UsingLocation, EnumType->getTypeLoc().getEndLoc()); } void UsingPackDecl::anchor() {} @@ -3097,7 +3207,8 @@ UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC, UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpansions) { size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions); - auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None); + auto *Result = + new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, std::nullopt); Result->NumExpansions = NumExpansions; auto *Trail = Result->getTrailingObjects<NamedDecl *>(); for (unsigned I = 0; I != NumExpansions; ++I) @@ -3178,8 +3289,7 @@ void StaticAssertDecl::anchor() {} StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *AssertExpr, - StringLiteral *Message, + Expr *AssertExpr, Expr *Message, SourceLocation RParenLoc, bool Failed) { return new (C, DC) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message, @@ -3192,6 +3302,16 @@ StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, nullptr, SourceLocation(), false); } +VarDecl *ValueDecl::getPotentiallyDecomposedVarDecl() { + assert((isa<VarDecl, BindingDecl>(this)) && + "expected a VarDecl or a BindingDecl"); + if (auto *Var = llvm::dyn_cast<VarDecl>(this)) + return Var; + if (auto *BD = llvm::dyn_cast<BindingDecl>(this)) + return llvm::dyn_cast<VarDecl>(BD->getDecomposedDecl()); + return nullptr; +} + void BindingDecl::anchor() {} BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC, @@ -3235,7 +3355,7 @@ DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C, size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings); auto *Result = new (C, ID, Extra) DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(), - QualType(), nullptr, StorageClass(), None); + QualType(), nullptr, StorageClass(), std::nullopt); // Set up and clean out the bindings array. Result->NumBindings = NumBindings; auto *Trail = Result->getTrailingObjects<BindingDecl *>(); @@ -3244,16 +3364,17 @@ DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C, return Result; } -void DecompositionDecl::printName(llvm::raw_ostream &os) const { - os << '['; +void DecompositionDecl::printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const { + OS << '['; bool Comma = false; for (const auto *B : bindings()) { if (Comma) - os << ", "; - B->printName(os); + OS << ", "; + B->printName(OS, Policy); Comma = true; } - os << ']'; + OS << ']'; } void MSPropertyDecl::anchor() {} @@ -3278,7 +3399,7 @@ void MSGuidDecl::anchor() {} MSGuidDecl::MSGuidDecl(DeclContext *DC, QualType T, Parts P) : ValueDecl(Decl::MSGuid, DC, SourceLocation(), DeclarationName(), T), - PartVal(P), APVal() {} + PartVal(P) {} MSGuidDecl *MSGuidDecl::Create(const ASTContext &C, QualType T, Parts P) { DeclContext *DC = C.getTranslationUnitDecl(); @@ -3289,7 +3410,8 @@ MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) MSGuidDecl(nullptr, QualType(), Parts()); } -void MSGuidDecl::printName(llvm::raw_ostream &OS) const { +void MSGuidDecl::printName(llvm::raw_ostream &OS, + const PrintingPolicy &) const { OS << llvm::format("GUID{%08" PRIx32 "-%04" PRIx16 "-%04" PRIx16 "-", PartVal.Part1, PartVal.Part2, PartVal.Part3); unsigned I = 0; @@ -3370,6 +3492,39 @@ APValue &MSGuidDecl::getAsAPValue() const { return APVal; } +void UnnamedGlobalConstantDecl::anchor() {} + +UnnamedGlobalConstantDecl::UnnamedGlobalConstantDecl(const ASTContext &C, + DeclContext *DC, + QualType Ty, + const APValue &Val) + : ValueDecl(Decl::UnnamedGlobalConstant, DC, SourceLocation(), + DeclarationName(), Ty), + Value(Val) { + // Cleanup the embedded APValue if required (note that our destructor is never + // run) + if (Value.needsCleanup()) + C.addDestruction(&Value); +} + +UnnamedGlobalConstantDecl * +UnnamedGlobalConstantDecl::Create(const ASTContext &C, QualType T, + const APValue &Value) { + DeclContext *DC = C.getTranslationUnitDecl(); + return new (C, DC) UnnamedGlobalConstantDecl(C, DC, T, Value); +} + +UnnamedGlobalConstantDecl * +UnnamedGlobalConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) + UnnamedGlobalConstantDecl(C, nullptr, QualType(), APValue()); +} + +void UnnamedGlobalConstantDecl::printName(llvm::raw_ostream &OS, + const PrintingPolicy &) const { + OS << "unnamed-global-constant"; +} + static const char *getAccessName(AccessSpecifier AS) { switch (AS) { case AS_none: |