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,  | 
