summaryrefslogtreecommitdiff
path: root/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/DeclCXX.cpp')
-rw-r--r--lib/AST/DeclCXX.cpp189
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,