diff options
Diffstat (limited to 'lib/AST/DeclCXX.cpp')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 189 |
1 files changed, 136 insertions, 53 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 5782b7b56c96..41f2449a9d6a 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1,4 +1,4 @@ -//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// +//===- DeclCXX.cpp - C++ Declaration AST Node Implementation --------------===// // // The LLVM Compiler Infrastructure // @@ -10,26 +10,51 @@ // This file implements the C++ related Decl classes. // //===----------------------------------------------------------------------===// + #include "clang/AST/DeclCXX.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/LambdaCapture.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/ODRHash.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/STLExtras.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> + using namespace clang; //===----------------------------------------------------------------------===// // Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// -void AccessSpecDecl::anchor() { } +void AccessSpecDecl::anchor() {} AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) AccessSpecDecl(EmptyShell()); @@ -76,9 +101,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false), - IsParsingBaseSpecifiers(false), HasODRHash(false), ODRHash(0), - NumBases(0), NumVBases(0), Bases(), VBases(), Definition(D), - FirstFriend() {} + IsParsingBaseSpecifiers(false), HasODRHash(false), Definition(D) {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); @@ -94,13 +117,12 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, CXXRecordDecl *PrevDecl) : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl), DefinitionData(PrevDecl ? PrevDecl->DefinitionData - : nullptr), - TemplateOrInstantiation() {} + : nullptr) {} CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, - CXXRecordDecl* PrevDecl, + CXXRecordDecl *PrevDecl, bool DelayTypeCreation) { CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl); @@ -148,7 +170,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, C.Deallocate(data().getBases()); if (NumBases) { - if (!C.getLangOpts().CPlusPlus1z) { + if (!C.getLangOpts().CPlusPlus17) { // C++ [dcl.init.aggr]p1: // An aggregate is [...] a class with [...] no base classes [...]. data().Aggregate = false; @@ -403,7 +425,6 @@ unsigned CXXRecordDecl::getODRHash() const { return DefinitionData->ODRHash; } - void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // C++11 [class.copy]p11: // A defaulted copy/move constructor for a class X is defined as @@ -1470,6 +1491,66 @@ bool CXXRecordDecl::isAnyDestructorNoReturn() const { return false; } +static bool isDeclContextInNamespace(const DeclContext *DC) { + while (!DC->isTranslationUnit()) { + if (DC->isNamespace()) + return true; + DC = DC->getParent(); + } + return false; +} + +bool CXXRecordDecl::isInterfaceLike() const { + assert(hasDefinition() && "checking for interface-like without a definition"); + // All __interfaces are inheritently interface-like. + if (isInterface()) + return true; + + // Interface-like types cannot have a user declared constructor, destructor, + // friends, VBases, conversion functions, or fields. Additionally, lambdas + // cannot be interface types. + if (isLambda() || hasUserDeclaredConstructor() || + hasUserDeclaredDestructor() || !field_empty() || hasFriends() || + getNumVBases() > 0 || conversion_end() - conversion_begin() > 0) + return false; + + // No interface-like type can have a method with a definition. + for (const auto *const Method : methods()) + if (Method->isDefined() && !Method->isImplicit()) + return false; + + // Check "Special" types. + const auto *Uuid = getAttr<UuidAttr>(); + // MS SDK declares IUnknown/IDispatch both in the root of a TU, or in an + // extern C++ block directly in the TU. These are only valid if in one + // of these two situations. + if (Uuid && isStruct() && !getDeclContext()->isExternCContext() && + !isDeclContextInNamespace(getDeclContext()) && + ((getName() == "IUnknown" && + Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") || + (getName() == "IDispatch" && + Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) { + if (getNumBases() > 0) + return false; + return true; + } + + // FIXME: Any access specifiers is supposed to make this no longer interface + // like. + + // If this isn't a 'special' type, it must have a single interface-like base. + if (getNumBases() != 1) + return false; + + const auto BaseSpec = *bases_begin(); + if (BaseSpec.isVirtual() || BaseSpec.getAccessSpecifier() != AS_public) + return false; + const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl(); + if (Base->isInterface() || !Base->isInterfaceLike()) + return false; + return true; +} + void CXXRecordDecl::completeDefinition() { completeDefinition(nullptr); } @@ -1530,7 +1611,7 @@ bool CXXRecordDecl::mayBeAbstract() const { return false; } -void CXXDeductionGuideDecl::anchor() { } +void CXXDeductionGuideDecl::anchor() {} CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit, @@ -1547,7 +1628,7 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, nullptr, SourceLocation()); } -void CXXMethodDecl::anchor() { } +void CXXMethodDecl::anchor() {} bool CXXMethodDecl::isStatic() const { const CXXMethodDecl *MD = getCanonicalDecl(); @@ -1561,9 +1642,7 @@ bool CXXMethodDecl::isStatic() const { static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD, const CXXMethodDecl *BaseMD) { - for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(), - E = DerivedMD->end_overridden_methods(); I != E; ++I) { - const CXXMethodDecl *MD = *I; + for (const CXXMethodDecl *MD : DerivedMD->overridden_methods()) { if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl()) return true; if (recursivelyOverrides(MD, BaseMD)) @@ -1728,6 +1807,14 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const { return true; unsigned UsualParams = 1; + // C++ P0722: + // A destroying operator delete is a usual deallocation function if + // removing the std::destroying_delete_t parameter and changing the + // first parameter type from T* to void* results in the signature of + // a usual deallocation function. + if (isDestroyingOperatorDelete()) + ++UsualParams; + // C++ <=14 [basic.stc.dynamic.deallocation]p2: // [...] If class T does not declare such an operator delete but does // declare a member deallocation function named operator delete with @@ -1886,43 +1973,34 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation L, Expr *Init, SourceLocation R, SourceLocation EllipsisLoc) - : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), + IsWritten(false), SourceOrder(0) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), + IsWritten(false), SourceOrder(0) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), + IsWritten(false), SourceOrder(0) {} CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), - LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), - IsWritten(false), SourceOrder(0) -{ -} + : Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R), + IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {} TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) @@ -1962,7 +2040,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const { return SourceRange(getSourceLocation(), getRParenLoc()); } -void CXXConstructorDecl::anchor() { } +void CXXConstructorDecl::anchor() {} CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID, @@ -2105,7 +2183,7 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const { return true; } -void CXXDestructorDecl::anchor() { } +void CXXDestructorDecl::anchor() {} CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -2127,16 +2205,17 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isInline, isImplicitlyDeclared); } -void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD) { +void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { auto *First = cast<CXXDestructorDecl>(getFirstDecl()); if (OD && !First->OperatorDelete) { First->OperatorDelete = OD; + First->OperatorDeleteThisArg = ThisArg; if (auto *L = getASTMutationListener()) - L->ResolvedOperatorDelete(First, OD); + L->ResolvedOperatorDelete(First, OD, ThisArg); } } -void CXXConversionDecl::anchor() { } +void CXXConversionDecl::anchor() {} CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -2166,7 +2245,7 @@ bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { getConversionType()->isBlockPointerType(); } -void LinkageSpecDecl::anchor() { } +void LinkageSpecDecl::anchor() {} LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, @@ -2183,7 +2262,7 @@ LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, SourceLocation(), lang_c, false); } -void UsingDirectiveDecl::anchor() { } +void UsingDirectiveDecl::anchor() {} UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -2217,7 +2296,7 @@ NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, NamespaceDecl *PrevDecl) : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), - redeclarable_base(C), LocStart(StartLoc), RBraceLoc(), + redeclarable_base(C), LocStart(StartLoc), AnonOrFirstNamespaceAndInline(nullptr, Inline) { setPreviousDecl(PrevDecl); @@ -2257,21 +2336,25 @@ bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); } NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() { return getNextRedeclaration(); } + NamespaceDecl *NamespaceDecl::getPreviousDeclImpl() { return getPreviousDecl(); } + NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() { return getMostRecentDecl(); } -void NamespaceAliasDecl::anchor() { } +void NamespaceAliasDecl::anchor() {} NamespaceAliasDecl *NamespaceAliasDecl::getNextRedeclarationImpl() { return getNextRedeclaration(); } + NamespaceAliasDecl *NamespaceAliasDecl::getPreviousDeclImpl() { return getPreviousDecl(); } + NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() { return getMostRecentDecl(); } @@ -2298,7 +2381,7 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr); } -void UsingShadowDecl::anchor() { } +void UsingShadowDecl::anchor() {} UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, @@ -2313,7 +2396,7 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty) : NamedDecl(K, nullptr, SourceLocation(), DeclarationName()), - redeclarable_base(C), Underlying(), UsingOrNextShadow() {} + redeclarable_base(C) {} UsingShadowDecl * UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { @@ -2328,7 +2411,7 @@ UsingDecl *UsingShadowDecl::getUsingDecl() const { return cast<UsingDecl>(Shadow->UsingOrNextShadow); } -void ConstructorUsingShadowDecl::anchor() { } +void ConstructorUsingShadowDecl::anchor() {} ConstructorUsingShadowDecl * ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC, @@ -2347,7 +2430,7 @@ CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const { return getUsingDecl()->getQualifier()->getAsRecordDecl(); } -void UsingDecl::anchor() { } +void UsingDecl::anchor() {} void UsingDecl::addShadowDecl(UsingShadowDecl *S) { assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() && @@ -2399,7 +2482,7 @@ SourceRange UsingDecl::getSourceRange() const { return SourceRange(Begin, getNameInfo().getEndLoc()); } -void UsingPackDecl::anchor() { } +void UsingPackDecl::anchor() {} UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC, NamedDecl *InstantiatedFrom, @@ -2419,7 +2502,7 @@ UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID, return Result; } -void UnresolvedUsingValueDecl::anchor() { } +void UnresolvedUsingValueDecl::anchor() {} UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, @@ -2447,7 +2530,7 @@ SourceRange UnresolvedUsingValueDecl::getSourceRange() const { return SourceRange(Begin, getNameInfo().getEndLoc()); } -void UnresolvedUsingTypenameDecl::anchor() { } +void UnresolvedUsingTypenameDecl::anchor() {} UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, @@ -2469,7 +2552,7 @@ UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { SourceLocation(), nullptr, SourceLocation()); } -void StaticAssertDecl::anchor() { } +void StaticAssertDecl::anchor() {} StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, |