diff options
Diffstat (limited to 'clang/lib/AST/DeclCXX.cpp')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 131 |
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); } |