diff options
Diffstat (limited to 'clang/lib/AST/DeclCXX.cpp')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 173 |
1 files changed, 109 insertions, 64 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 12ec44fa0279..2ead1e70ea0d 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/ASTUnresolvedSet.h" +#include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclTemplate.h" @@ -413,7 +414,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().HasIrrelevantDestructor = false; // C++11 [class.copy]p18: - // The implicitly-declared copy assignment oeprator for a class X will + // The implicitly-declared copy assignment operator for a class X will // have the form 'X& X::operator=(const X&)' if each direct base class B // of X has a copy assignment operator whose parameter is of type 'const // B&', 'const volatile B&', or 'B' [...] @@ -737,49 +738,55 @@ void CXXRecordDecl::addedMember(Decl *D) { // Handle constructors. if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - if (!Constructor->isImplicit()) { - // Note that we have a user-declared constructor. - data().UserDeclaredConstructor = true; + if (Constructor->isInheritingConstructor()) { + // Ignore constructor shadow declarations. They are lazily created and + // so shouldn't affect any properties of the class. + } else { + if (!Constructor->isImplicit()) { + // 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; + } - // 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()) { + SMKind |= SMF_DefaultConstructor; - if (Constructor->isDefaultConstructor()) { - SMKind |= SMF_DefaultConstructor; + if (Constructor->isUserProvided()) + data().UserProvidedDefaultConstructor = true; + if (Constructor->isConstexpr()) + data().HasConstexprDefaultConstructor = true; + if (Constructor->isDefaulted()) + data().HasDefaultedDefaultConstructor = true; + } - if (Constructor->isUserProvided()) - data().UserProvidedDefaultConstructor = true; - if (Constructor->isConstexpr()) - data().HasConstexprDefaultConstructor = true; - if (Constructor->isDefaulted()) - data().HasDefaultedDefaultConstructor = true; - } + if (!FunTmpl) { + unsigned Quals; + if (Constructor->isCopyConstructor(Quals)) { + SMKind |= SMF_CopyConstructor; - if (!FunTmpl) { - unsigned Quals; - if (Constructor->isCopyConstructor(Quals)) { - SMKind |= SMF_CopyConstructor; + if (Quals & Qualifiers::Const) + data().HasDeclaredCopyConstructorWithConstParam = true; + } else if (Constructor->isMoveConstructor()) + SMKind |= SMF_MoveConstructor; + } - if (Quals & Qualifiers::Const) - data().HasDeclaredCopyConstructorWithConstParam = true; - } else if (Constructor->isMoveConstructor()) - SMKind |= SMF_MoveConstructor; + // C++11 [dcl.init.aggr]p1: DR1518 + // An aggregate is an array or a class with no user-provided [or] + // explicit [...] constructors + // C++20 [dcl.init.aggr]p1: + // An aggregate is an array or a class with no user-declared [...] + // constructors + if (getASTContext().getLangOpts().CPlusPlus2a + ? !Constructor->isImplicit() + : (Constructor->isUserProvided() || Constructor->isExplicit())) + data().Aggregate = false; } - - // C++11 [dcl.init.aggr]p1: DR1518 - // An aggregate is an array or a class with no user-provided [or] - // explicit [...] constructors - // C++20 [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-declared [...] - // constructors - if (getASTContext().getLangOpts().CPlusPlus2a - ? !Constructor->isImplicit() - : (Constructor->isUserProvided() || Constructor->isExplicit())) - data().Aggregate = false; } // Handle constructors, including those inherited from base classes. @@ -1511,14 +1518,12 @@ static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { /// \param VOutput the set to which to add conversions from virtual bases /// \param HiddenVBaseCs the set of conversions which were hidden in a /// virtual base along some inheritance path -static void CollectVisibleConversions(ASTContext &Context, - CXXRecordDecl *Record, - bool InVirtual, - AccessSpecifier Access, - const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes, - ASTUnresolvedSet &Output, - UnresolvedSetImpl &VOutput, - llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) { +static void CollectVisibleConversions( + ASTContext &Context, const CXXRecordDecl *Record, bool InVirtual, + AccessSpecifier Access, + const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes, + ASTUnresolvedSet &Output, UnresolvedSetImpl &VOutput, + llvm::SmallPtrSet<NamedDecl *, 8> &HiddenVBaseCs) { // The set of types which have conversions in this class or its // subclasses. As an optimization, we don't copy the derived set // unless it might change. @@ -1559,7 +1564,7 @@ static void CollectVisibleConversions(ASTContext &Context, // Collect information recursively from any base classes. for (const auto &I : Record->bases()) { - const RecordType *RT = I.getType()->getAs<RecordType>(); + const auto *RT = I.getType()->getAs<RecordType>(); if (!RT) continue; AccessSpecifier BaseAccess @@ -1577,7 +1582,7 @@ static void CollectVisibleConversions(ASTContext &Context, /// This would be extremely straightforward if it weren't for virtual /// bases. It might be worth special-casing that, really. static void CollectVisibleConversions(ASTContext &Context, - CXXRecordDecl *Record, + const CXXRecordDecl *Record, ASTUnresolvedSet &Output) { // The collection of all conversions in virtual bases that we've // found. These will be added to the output as long as they don't @@ -1601,7 +1606,7 @@ static void CollectVisibleConversions(ASTContext &Context, // Recursively collect conversions from base classes. for (const auto &I : Record->bases()) { - const RecordType *RT = I.getType()->getAs<RecordType>(); + const auto *RT = I.getType()->getAs<RecordType>(); if (!RT) continue; CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()), @@ -1620,7 +1625,7 @@ static void CollectVisibleConversions(ASTContext &Context, /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. llvm::iterator_range<CXXRecordDecl::conversion_iterator> -CXXRecordDecl::getVisibleConversionFunctions() { +CXXRecordDecl::getVisibleConversionFunctions() const { ASTContext &Ctx = getASTContext(); ASTUnresolvedSet *Set; @@ -2042,16 +2047,19 @@ CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation) { + SourceLocation EndLocation, + Expr *TrailingRequiresClause) { return new (C, RD) CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, - isInline, ConstexprKind, EndLocation); + 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, CSK_unspecified, SourceLocation()); + QualType(), nullptr, SC_None, false, CSK_unspecified, SourceLocation(), + nullptr); } CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, @@ -2432,9 +2440,11 @@ 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) + ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, + Expr *TrailingRequiresClause) : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation()) { + SC_None, isInline, ConstexprKind, SourceLocation(), + TrailingRequiresClause) { setNumCtorInitializers(0); setInheritingConstructor(static_cast<bool>(Inherited)); setImplicit(isImplicitlyDeclared); @@ -2458,7 +2468,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, auto *Result = new (C, ID, Extra) CXXConstructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, ExplicitSpecifier(), false, false, - CSK_unspecified, InheritedConstructor()); + CSK_unspecified, InheritedConstructor(), nullptr); Result->setInheritingConstructor(isInheritingConstructor); Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier = hasTraillingExplicit; @@ -2470,7 +2480,8 @@ 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) { + ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, + Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); @@ -2479,7 +2490,8 @@ CXXConstructorDecl *CXXConstructorDecl::Create( Inherited ? 1 : 0, ES.getExpr() ? 1 : 0); return new (C, RD, Extra) CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline, - isImplicitlyDeclared, ConstexprKind, Inherited); + isImplicitlyDeclared, ConstexprKind, Inherited, + TrailingRequiresClause); } CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { @@ -2600,19 +2612,22 @@ CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXDestructorDecl(C, nullptr, SourceLocation(), DeclarationNameInfo(), - QualType(), nullptr, false, false, CSK_unspecified); + QualType(), nullptr, false, false, CSK_unspecified, + nullptr); } CXXDestructorDecl *CXXDestructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind) { + 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); + isImplicitlyDeclared, ConstexprKind, + TrailingRequiresClause); } void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { @@ -2631,20 +2646,20 @@ CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXConversionDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, ExplicitSpecifier(), CSK_unspecified, SourceLocation()); + false, ExplicitSpecifier(), CSK_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) { + 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); + ConstexprKind, EndLocation, TrailingRequiresClause); } bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { @@ -2796,6 +2811,36 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr); } +void LifetimeExtendedTemporaryDecl::anchor() {} + +/// Retrieve the storage duration for the materialized temporary. +StorageDuration LifetimeExtendedTemporaryDecl::getStorageDuration() const { + const ValueDecl *ExtendingDecl = getExtendingDecl(); + if (!ExtendingDecl) + return SD_FullExpression; + // FIXME: This is not necessarily correct for a temporary materialized + // within a default initializer. + if (isa<FieldDecl>(ExtendingDecl)) + return SD_Automatic; + // FIXME: This only works because storage class specifiers are not allowed + // on decomposition declarations. + if (isa<BindingDecl>(ExtendingDecl)) + return ExtendingDecl->getDeclContext()->isFunctionOrMethod() ? SD_Automatic + : SD_Static; + return cast<VarDecl>(ExtendingDecl)->getStorageDuration(); +} + +APValue *LifetimeExtendedTemporaryDecl::getOrCreateValue(bool MayCreate) const { + assert(getStorageDuration() == SD_Static && + "don't need to cache the computed value for this temporary"); + if (MayCreate && !Value) { + Value = (new (getASTContext()) APValue); + getASTContext().addDestruction(Value); + } + assert(Value && "may not be null"); + return Value; +} + void UsingShadowDecl::anchor() {} UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, |