aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:44:14 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:44:14 +0000
commit2b6b257f4e5503a7a2675bdb8735693db769f75c (patch)
treee85e046ae7003fe3bcc8b5454cd0fa3f7407b470 /lib/AST/DeclCXX.cpp
parentb4348ed0b7e90c0831b925fbee00b5f179a99796 (diff)
downloadsrc-2b6b257f4e5503a7a2675bdb8735693db769f75c.tar.gz
src-2b6b257f4e5503a7a2675bdb8735693db769f75c.zip
Vendor import of clang release_39 branch r276489:vendor/clang/clang-release_39-r276489
Notes
Notes: svn path=/vendor/clang/dist/; revision=303233 svn path=/vendor/clang/clang-release_39-r276489/; revision=303234; tag=vendor/clang/clang-release_39-r276489
Diffstat (limited to 'lib/AST/DeclCXX.cpp')
-rw-r--r--lib/AST/DeclCXX.cpp240
1 files changed, 163 insertions, 77 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 4f24fdc28f71..d069bfdc3dc2 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -46,34 +46,33 @@ void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const {
}
CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
- : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0),
- Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
- Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
- HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
- HasMutableFields(false), HasVariantMembers(false), HasOnlyCMembers(true),
- HasInClassInitializer(false), HasUninitializedReferenceMember(false),
- NeedOverloadResolutionForMoveConstructor(false),
- NeedOverloadResolutionForMoveAssignment(false),
- NeedOverloadResolutionForDestructor(false),
- DefaultedMoveConstructorIsDeleted(false),
- DefaultedMoveAssignmentIsDeleted(false),
- DefaultedDestructorIsDeleted(false),
- HasTrivialSpecialMembers(SMF_All),
- DeclaredNonTrivialSpecialMembers(0),
- HasIrrelevantDestructor(true),
- HasConstexprNonCopyMoveConstructor(false),
- DefaultedDefaultConstructorIsConstexpr(true),
- HasConstexprDefaultConstructor(false),
- HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
- UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
- ImplicitCopyConstructorHasConstParam(true),
- ImplicitCopyAssignmentHasConstParam(true),
- HasDeclaredCopyConstructorWithConstParam(false),
- HasDeclaredCopyAssignmentWithConstParam(false),
- IsLambda(false), IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0),
- Bases(), VBases(),
- Definition(D), FirstFriend() {
-}
+ : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0),
+ Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
+ Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
+ HasPrivateFields(false), HasProtectedFields(false),
+ HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false),
+ HasOnlyCMembers(true), HasInClassInitializer(false),
+ HasUninitializedReferenceMember(false), HasUninitializedFields(false),
+ HasInheritedConstructor(false), HasInheritedAssignment(false),
+ NeedOverloadResolutionForMoveConstructor(false),
+ NeedOverloadResolutionForMoveAssignment(false),
+ NeedOverloadResolutionForDestructor(false),
+ DefaultedMoveConstructorIsDeleted(false),
+ DefaultedMoveAssignmentIsDeleted(false),
+ DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
+ DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
+ HasConstexprNonCopyMoveConstructor(false),
+ HasDefaultedDefaultConstructor(false),
+ DefaultedDefaultConstructorIsConstexpr(true),
+ HasConstexprDefaultConstructor(false),
+ HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
+ UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
+ ImplicitCopyConstructorHasConstParam(true),
+ ImplicitCopyAssignmentHasConstParam(true),
+ HasDeclaredCopyConstructorWithConstParam(false),
+ HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false),
+ IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), Bases(),
+ VBases(), Definition(D), FirstFriend() {}
CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
return Bases.get(Definition->getASTContext().getExternalSource());
@@ -89,7 +88,7 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
CXXRecordDecl *PrevDecl)
: RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl),
DefinitionData(PrevDecl ? PrevDecl->DefinitionData
- : DefinitionDataPtr(this)),
+ : nullptr),
TemplateOrInstantiation() {}
CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
@@ -143,9 +142,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
C.Deallocate(data().getBases());
if (NumBases) {
- // C++ [dcl.init.aggr]p1:
- // An aggregate is [...] a class with [...] no base classes [...].
- data().Aggregate = false;
+ if (!C.getLangOpts().CPlusPlus1z) {
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is [...] a class with [...] no base classes [...].
+ data().Aggregate = false;
+ }
// C++ [class]p4:
// A POD-struct is an aggregate class...
@@ -171,8 +172,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- // A class with a non-empty base class is not empty.
- // FIXME: Standard ref?
if (!BaseClassDecl->isEmpty()) {
if (!data().Empty) {
// C++0x [class]p7:
@@ -186,10 +185,18 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
data().IsStandardLayout = false;
}
+ // C++14 [meta.unary.prop]p4:
+ // T is a class type [...] with [...] no base class B for which
+ // is_empty<B>::value is false.
data().Empty = false;
data().HasNoNonEmptyBases = false;
}
+ // C++1z [dcl.init.agg]p1:
+ // An aggregate is a class with [...] no private or protected base classes
+ if (Base->getAccessSpecifier() != AS_public)
+ data().Aggregate = false;
+
// C++ [class.virtual]p1:
// A class that declares or inherits a virtual function is called a
// polymorphic class.
@@ -220,6 +227,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (CXXRecordDecl *VBaseDecl = VBase.getType()->getAsCXXRecordDecl())
if (!VBaseDecl->hasCopyConstructorWithConstParam())
data().ImplicitCopyConstructorHasConstParam = false;
+
+ // C++1z [dcl.init.agg]p1:
+ // An aggregate is a class with [...] no virtual base classes
+ data().Aggregate = false;
}
}
@@ -228,11 +239,15 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)).second)
VBases.push_back(Base);
- // C++0x [meta.unary.prop] is_empty:
- // T is a class type, but not a union type, with ... no virtual base
- // classes
+ // C++14 [meta.unary.prop] is_empty:
+ // T is a class type, but not a union type, with ... no virtual base
+ // classes
data().Empty = false;
+ // C++1z [dcl.init.agg]p1:
+ // An aggregate is a class with [...] no virtual base classes
+ data().Aggregate = false;
+
// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
// A [default constructor, copy/move constructor, or copy/move assignment
// operator for a class X] is trivial [...] if:
@@ -332,6 +347,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (BaseClassDecl->hasUninitializedReferenceMember())
data().HasUninitializedReferenceMember = true;
+ if (!BaseClassDecl->allowConstDefaultInit())
+ data().HasUninitializedFields = true;
+
addedClassSubobject(BaseClassDecl);
}
@@ -430,6 +448,15 @@ void CXXRecordDecl::addedMember(Decl *D) {
FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (FunTmpl)
D = FunTmpl->getTemplatedDecl();
+
+ // FIXME: Pass NamedDecl* to addedMember?
+ Decl *DUnderlying = D;
+ if (auto *ND = dyn_cast<NamedDecl>(DUnderlying)) {
+ DUnderlying = ND->getUnderlyingDecl();
+ if (FunctionTemplateDecl *UnderlyingFunTmpl =
+ dyn_cast<FunctionTemplateDecl>(DUnderlying))
+ DUnderlying = UnderlyingFunTmpl->getTemplatedDecl();
+ }
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isVirtual()) {
@@ -441,8 +468,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
// A POD-struct is an aggregate class...
data().PlainOldData = false;
- // Virtual functions make the class non-empty.
- // FIXME: Standard ref?
+ // C++14 [meta.unary.prop]p4:
+ // T is a class type [...] with [...] no virtual member functions...
data().Empty = false;
// C++ [class.virtual]p1:
@@ -485,18 +512,15 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().PlainOldData = false;
}
- // Technically, "user-provided" is only defined for special member
- // functions, but the intent of the standard is clearly that it should apply
- // to all functions.
- bool UserProvided = Constructor->isUserProvided();
-
if (Constructor->isDefaultConstructor()) {
SMKind |= SMF_DefaultConstructor;
- if (UserProvided)
+ if (Constructor->isUserProvided())
data().UserProvidedDefaultConstructor = true;
if (Constructor->isConstexpr())
data().HasConstexprDefaultConstructor = true;
+ if (Constructor->isDefaulted())
+ data().HasDefaultedDefaultConstructor = true;
}
if (!FunTmpl) {
@@ -509,9 +533,17 @@ void CXXRecordDecl::addedMember(Decl *D) {
} else if (Constructor->isMoveConstructor())
SMKind |= SMF_MoveConstructor;
}
+ }
+ // Handle constructors, including those inherited from base classes.
+ if (CXXConstructorDecl *Constructor =
+ dyn_cast<CXXConstructorDecl>(DUnderlying)) {
// Record if we see any constexpr constructors which are neither copy
// nor move constructors.
+ // C++1z [basic.types]p10:
+ // [...] has at least one constexpr constructor or constructor template
+ // (possibly inherited from a base class) that is not a copy or move
+ // constructor [...]
if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor())
data().HasConstexprNonCopyMoveConstructor = true;
@@ -521,8 +553,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
// C++11 [dcl.init.aggr]p1:
// An aggregate is an array or a class with no user-provided
// constructors [...].
+ // C++11 [dcl.init.aggr]p1:
+ // An aggregate is an array or a class with no user-provided
+ // constructors (including those inherited from a base class) [...].
if (getASTContext().getLangOpts().CPlusPlus11
- ? UserProvided : !Constructor->isImplicit())
+ ? Constructor->isUserProvided()
+ : !Constructor->isImplicit())
data().Aggregate = false;
}
@@ -702,6 +738,15 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().IsStandardLayout = false;
}
+ if (!Field->hasInClassInitializer() && !Field->isMutable()) {
+ if (CXXRecordDecl *FieldType = Field->getType()->getAsCXXRecordDecl()) {
+ if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
+ data().HasUninitializedFields = true;
+ } else {
+ data().HasUninitializedFields = true;
+ }
+ }
+
// Record if this field is the first non-literal or volatile field or base.
if (!T->isLiteralType(Context) || T.isVolatileQualified())
data().HasNonLiteralTypeFieldsOrBases = true;
@@ -720,7 +765,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// An aggregate is a [...] class with [...] no
// brace-or-equal-initializers for non-static data members.
//
- // This rule was removed in C++1y.
+ // This rule was removed in C++14.
if (!getASTContext().getLangOpts().CPlusPlus14)
data().Aggregate = false;
@@ -910,7 +955,9 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (!data().HasNoNonEmptyBases)
data().IsStandardLayout = false;
- // If this is not a zero-length bit-field, then the class is not empty.
+ // C++14 [meta.unary.prop]p4:
+ // T is a class type [...] with [...] no non-static data members other
+ // than bit-fields of length 0...
if (data().Empty) {
if (!Field->isBitField() ||
(!Field->getBitWidth()->isTypeDependent() &&
@@ -928,6 +975,15 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().Conversions.get(Ctx).addDecl(Ctx, Shadow, Shadow->getAccess());
}
}
+
+ if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
+ if (Using->getDeclName().getNameKind() ==
+ DeclarationName::CXXConstructorName)
+ data().HasInheritedConstructor = true;
+
+ if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
+ data().HasInheritedAssignment = true;
+ }
}
void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
@@ -1595,6 +1651,13 @@ unsigned CXXMethodDecl::size_overridden_methods() const {
return getASTContext().overridden_methods_size(this);
}
+CXXMethodDecl::overridden_method_range
+CXXMethodDecl::overridden_methods() const {
+ if (isa<CXXConstructorDecl>(this))
+ return overridden_method_range(nullptr, nullptr);
+ return getASTContext().overridden_methods(this);
+}
+
QualType CXXMethodDecl::getThisType(ASTContext &C) const {
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
// If the member function is declared const, the type of this is const X*,
@@ -1606,7 +1669,7 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
QualType ClassTy = C.getTypeDeclType(getParent());
ClassTy = C.getQualifiedType(ClassTy,
- Qualifiers::fromCVRMask(getTypeQualifiers()));
+ Qualifiers::fromCVRUMask(getTypeQualifiers()));
return C.getPointerType(ClassTy);
}
@@ -1744,11 +1807,15 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
void CXXConstructorDecl::anchor() { }
-CXXConstructorDecl *
-CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) CXXConstructorDecl(C, nullptr, SourceLocation(),
- DeclarationNameInfo(), QualType(),
- nullptr, false, false, false, false);
+CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID,
+ bool Inherited) {
+ unsigned Extra = additionalSizeToAlloc<InheritedConstructor>(Inherited);
+ auto *Result = new (C, ID, Extra) CXXConstructorDecl(
+ C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
+ false, false, false, false, InheritedConstructor());
+ Result->IsInheritingConstructor = Inherited;
+ return Result;
}
CXXConstructorDecl *
@@ -1757,13 +1824,16 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit, bool isInline,
- bool isImplicitlyDeclared, bool isConstexpr) {
+ bool isImplicitlyDeclared, bool isConstexpr,
+ InheritedConstructor Inherited) {
assert(NameInfo.getName().getNameKind()
== DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
- return new (C, RD) CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo,
- isExplicit, isInline,
- isImplicitlyDeclared, isConstexpr);
+ unsigned Extra =
+ additionalSizeToAlloc<InheritedConstructor>(Inherited ? 1 : 0);
+ return new (C, RD, Extra) CXXConstructorDecl(
+ C, RD, StartLoc, NameInfo, T, TInfo, isExplicit, isInline,
+ isImplicitlyDeclared, isConstexpr, Inherited);
}
CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
@@ -1878,23 +1948,6 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
return true;
}
-const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const {
- // Hack: we store the inherited constructor in the overridden method table
- method_iterator It = getASTContext().overridden_methods_begin(this);
- if (It == getASTContext().overridden_methods_end(this))
- return nullptr;
-
- return cast<CXXConstructorDecl>(*It);
-}
-
-void
-CXXConstructorDecl::setInheritedConstructor(const CXXConstructorDecl *BaseCtor){
- // Hack: we store the inherited constructor in the overridden method table
- assert(getASTContext().overridden_methods_size(this) == 0 &&
- "Base ctor already set.");
- getASTContext().addOverriddenMethod(this, BaseCtor);
-}
-
void CXXDestructorDecl::anchor() { }
CXXDestructorDecl *
@@ -2090,10 +2143,24 @@ NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void UsingShadowDecl::anchor() { }
+UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
+ SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target)
+ : NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()),
+ redeclarable_base(C), Underlying(Target),
+ UsingOrNextShadow(cast<NamedDecl>(Using)) {
+ if (Target)
+ IdentifierNamespace = Target->getIdentifierNamespace();
+ setImplicit();
+}
+
+UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty)
+ : NamedDecl(K, nullptr, SourceLocation(), DeclarationName()),
+ redeclarable_base(C), Underlying(), UsingOrNextShadow() {}
+
UsingShadowDecl *
UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
- return new (C, ID) UsingShadowDecl(C, nullptr, SourceLocation(),
- nullptr, nullptr);
+ return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell());
}
UsingDecl *UsingShadowDecl::getUsingDecl() const {
@@ -2104,6 +2171,25 @@ UsingDecl *UsingShadowDecl::getUsingDecl() const {
return cast<UsingDecl>(Shadow->UsingOrNextShadow);
}
+void ConstructorUsingShadowDecl::anchor() { }
+
+ConstructorUsingShadowDecl *
+ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target, bool IsVirtual) {
+ return new (C, DC) ConstructorUsingShadowDecl(C, DC, Loc, Using, Target,
+ IsVirtual);
+}
+
+ConstructorUsingShadowDecl *
+ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell());
+}
+
+CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const {
+ return getUsingDecl()->getQualifier()->getAsRecordDecl();
+}
+
void UsingDecl::anchor() { }
void UsingDecl::addShadowDecl(UsingShadowDecl *S) {