aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/DeclCXX.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/DeclCXX.cpp512
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: