diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/DeclCXX.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/DeclCXX.cpp | 512 |
1 files changed, 337 insertions, 175 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp b/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp index 0cf6e60b2a6c..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" @@ -146,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; } @@ -446,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()) @@ -587,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. @@ -686,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. @@ -768,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()) { @@ -825,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; } @@ -893,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); } } @@ -1054,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; @@ -1248,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: @@ -1393,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()); @@ -1423,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, @@ -1436,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()) @@ -1468,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()) @@ -1556,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 * @@ -1594,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 { @@ -1603,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) { @@ -1895,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) { @@ -1988,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; @@ -2060,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( @@ -2207,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) @@ -2236,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. @@ -2357,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 @@ -2364,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(); @@ -2385,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(); @@ -2440,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 { @@ -2460,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 { @@ -2545,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 {}; } @@ -2788,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); @@ -2798,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() {} @@ -2844,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(); } @@ -2968,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(); } @@ -3064,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() {} @@ -3090,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) @@ -3171,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, @@ -3185,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, @@ -3228,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 *>(); @@ -3237,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() {} @@ -3282,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; @@ -3363,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: |