aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/DeclCXX.cpp')
-rw-r--r--clang/lib/AST/DeclCXX.cpp131
1 files changed, 88 insertions, 43 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 6f1fd2f14ede..0368ada0b81c 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -81,7 +81,9 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false),
HasOnlyCMembers(true), HasInClassInitializer(false),
HasUninitializedReferenceMember(false), HasUninitializedFields(false),
- HasInheritedConstructor(false), HasInheritedAssignment(false),
+ HasInheritedConstructor(false),
+ HasInheritedDefaultConstructor(false),
+ HasInheritedAssignment(false),
NeedOverloadResolutionForCopyConstructor(false),
NeedOverloadResolutionForMoveConstructor(false),
NeedOverloadResolutionForCopyAssignment(false),
@@ -100,7 +102,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
DefaultedDefaultConstructorIsConstexpr(true),
HasConstexprDefaultConstructor(false),
DefaultedDestructorIsConstexpr(true),
- HasNonLiteralTypeFieldsOrBases(false),
+ HasNonLiteralTypeFieldsOrBases(false), StructuralIfLiteral(true),
UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
ImplicitCopyConstructorCanHaveConstParamForVBase(true),
ImplicitCopyConstructorCanHaveConstParamForNonVBase(true),
@@ -258,9 +260,15 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// C++1z [dcl.init.agg]p1:
// An aggregate is a class with [...] no private or protected base classes
- if (Base->getAccessSpecifier() != AS_public)
+ if (Base->getAccessSpecifier() != AS_public) {
data().Aggregate = false;
+ // C++20 [temp.param]p7:
+ // A structural type is [...] a literal class type with [...] all base
+ // classes [...] public
+ data().StructuralIfLiteral = false;
+ }
+
// C++ [class.virtual]p1:
// A class that declares or inherits a virtual function is called a
// polymorphic class.
@@ -536,6 +544,13 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
// array thereof, that class type shall have a constexpr destructor
if (!Subobj->hasConstexprDestructor())
data().DefaultedDestructorIsConstexpr = false;
+
+ // C++20 [temp.param]p7:
+ // A structural type is [...] a literal class type [for which] the types
+ // of all base classes and non-static data members are structural types or
+ // (possibly multi-dimensional) array thereof
+ if (!Subobj->data().StructuralIfLiteral)
+ data().StructuralIfLiteral = false;
}
bool CXXRecordDecl::hasConstexprDestructor() const {
@@ -801,6 +816,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
// constructor [...]
if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor())
data().HasConstexprNonCopyMoveConstructor = true;
+ if (!isa<CXXConstructorDecl>(D) && Constructor->isDefaultConstructor())
+ data().HasInheritedDefaultConstructor = true;
}
// Handle destructors.
@@ -956,6 +973,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (D->getAccess() == AS_private || D->getAccess() == AS_protected) {
data().Aggregate = false;
data().PlainOldData = false;
+
+ // C++20 [temp.param]p7:
+ // A structural type is [...] a literal class type [for which] all
+ // non-static data members are public
+ data().StructuralIfLiteral = false;
}
// Track whether this is the first field. We use this when checking
@@ -980,9 +1002,15 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Keep track of the presence of mutable fields.
- if (Field->isMutable())
+ if (Field->isMutable()) {
data().HasMutableFields = true;
+ // C++20 [temp.param]p7:
+ // A structural type is [...] a literal class type [for which] all
+ // non-static data members are public
+ data().StructuralIfLiteral = false;
+ }
+
// C++11 [class.union]p8, DR1460:
// If X is a union, a non-static data member of X that is not an anonymous
// union is a variant member of X.
@@ -1315,6 +1343,14 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().DefaultedCopyAssignmentIsDeleted = true;
data().DefaultedMoveAssignmentIsDeleted = true;
}
+
+ // C++20 [temp.param]p7:
+ // A structural type is [...] a literal class type [for which] the
+ // types of all non-static data members are structural types or
+ // (possibly multidimensional) array thereof
+ // We deal with class types elsewhere.
+ if (!T->isStructuralType())
+ data().StructuralIfLiteral = false;
}
// C++14 [meta.unary.prop]p4:
@@ -1383,8 +1419,8 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
data().DeclaredNonTrivialSpecialMembers |= SMKind;
}
-void CXXRecordDecl::setCaptures(ArrayRef<LambdaCapture> Captures) {
- ASTContext &Context = getASTContext();
+void CXXRecordDecl::setCaptures(ASTContext &Context,
+ ArrayRef<LambdaCapture> Captures) {
CXXRecordDecl::LambdaDefinitionData &Data = getLambdaData();
// Copy captures.
@@ -1475,18 +1511,38 @@ CXXMethodDecl *CXXRecordDecl::getLambdaCallOperator() const {
}
CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
- if (!isLambda()) return nullptr;
+ CXXMethodDecl *CallOp = getLambdaCallOperator();
+ CallingConv CC = CallOp->getType()->castAs<FunctionType>()->getCallConv();
+ return getLambdaStaticInvoker(CC);
+}
+
+static DeclContext::lookup_result
+getLambdaStaticInvokers(const CXXRecordDecl &RD) {
+ assert(RD.isLambda() && "Must be a lambda");
DeclarationName Name =
- &getASTContext().Idents.get(getLambdaStaticInvokerName());
- DeclContext::lookup_result Invoker = lookup(Name);
- if (Invoker.empty()) return nullptr;
- assert(allLookupResultsAreTheSame(Invoker) &&
- "More than one static invoker operator!");
- NamedDecl *InvokerFun = Invoker.front();
- if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun))
+ &RD.getASTContext().Idents.get(getLambdaStaticInvokerName());
+ return RD.lookup(Name);
+}
+
+static CXXMethodDecl *getInvokerAsMethod(NamedDecl *ND) {
+ if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(ND))
return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl());
+ return cast<CXXMethodDecl>(ND);
+}
+
+CXXMethodDecl *CXXRecordDecl::getLambdaStaticInvoker(CallingConv CC) const {
+ if (!isLambda())
+ return nullptr;
+ DeclContext::lookup_result Invoker = getLambdaStaticInvokers(*this);
+
+ for (NamedDecl *ND : Invoker) {
+ const auto *FTy =
+ cast<ValueDecl>(ND->getAsFunction())->getType()->castAs<FunctionType>();
+ if (FTy->getCallConv() == CC)
+ return getInvokerAsMethod(ND);
+ }
- return cast<CXXMethodDecl>(InvokerFun);
+ return nullptr;
}
void CXXRecordDecl::getCaptureFields(
@@ -2135,10 +2191,10 @@ CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
}
CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXMethodDecl(
- CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(),
- QualType(), nullptr, SC_None, false, CSK_unspecified, SourceLocation(),
- nullptr);
+ return new (C, ID)
+ CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(),
+ DeclarationNameInfo(), QualType(), nullptr, SC_None, false,
+ ConstexprSpecKind::Unspecified, SourceLocation(), nullptr);
}
CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
@@ -2427,14 +2483,8 @@ bool CXXMethodDecl::hasInlineBody() const {
bool CXXMethodDecl::isLambdaStaticInvoker() const {
const CXXRecordDecl *P = getParent();
- if (P->isLambda()) {
- if (const CXXMethodDecl *StaticInvoker = P->getLambdaStaticInvoker()) {
- if (StaticInvoker == this) return true;
- if (P->isGenericLambda() && this->isFunctionTemplateSpecialization())
- return StaticInvoker == this->getPrimaryTemplate()->getTemplatedDecl();
- }
- }
- return false;
+ return P->isLambda() && getDeclName().isIdentifier() &&
+ getName() == getLambdaStaticInvokerName();
}
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
@@ -2543,10 +2593,10 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
unsigned Extra =
additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
isInheritingConstructor, hasTraillingExplicit);
- auto *Result = new (C, ID, Extra)
- CXXConstructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(),
- QualType(), nullptr, ExplicitSpecifier(), false, false,
- CSK_unspecified, InheritedConstructor(), nullptr);
+ auto *Result = new (C, ID, Extra) CXXConstructorDecl(
+ C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
+ ExplicitSpecifier(), false, false, ConstexprSpecKind::Unspecified,
+ InheritedConstructor(), nullptr);
Result->setInheritingConstructor(isInheritingConstructor);
Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
hasTraillingExplicit;
@@ -2684,10 +2734,9 @@ void CXXDestructorDecl::anchor() {}
CXXDestructorDecl *
CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID)
- CXXDestructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(),
- QualType(), nullptr, false, false, CSK_unspecified,
- nullptr);
+ return new (C, ID) CXXDestructorDecl(
+ C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
+ false, false, ConstexprSpecKind::Unspecified, nullptr);
}
CXXDestructorDecl *CXXDestructorDecl::Create(
@@ -2720,7 +2769,8 @@ CXXConversionDecl *
CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) CXXConversionDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
- false, ExplicitSpecifier(), CSK_unspecified, SourceLocation(), nullptr);
+ false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified,
+ SourceLocation(), nullptr);
}
CXXConversionDecl *CXXConversionDecl::Create(
@@ -3301,12 +3351,7 @@ static const char *getAccessName(AccessSpecifier AS) {
llvm_unreachable("Invalid access specifier!");
}
-const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
- AccessSpecifier AS) {
- return DB << getAccessName(AS);
-}
-
-const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB,
- AccessSpecifier AS) {
+const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
+ AccessSpecifier AS) {
return DB << getAccessName(AS);
}