summaryrefslogtreecommitdiffstats
path: root/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/DeclCXX.cpp')
-rw-r--r--lib/AST/DeclCXX.cpp179
1 files changed, 98 insertions, 81 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 114322b..eec2e9d 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -43,13 +43,11 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
HasMutableFields(false), HasOnlyCMembers(true),
+ HasInClassInitializer(false),
HasTrivialDefaultConstructor(true),
HasConstexprNonCopyMoveConstructor(false),
DefaultedDefaultConstructorIsConstexpr(true),
- DefaultedCopyConstructorIsConstexpr(true),
- DefaultedMoveConstructorIsConstexpr(true),
- HasConstexprDefaultConstructor(false), HasConstexprCopyConstructor(false),
- HasConstexprMoveConstructor(false), HasTrivialCopyConstructor(true),
+ HasConstexprDefaultConstructor(false), HasTrivialCopyConstructor(true),
HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
HasIrrelevantDestructor(true),
@@ -62,6 +60,14 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
NumVBases(0), Bases(), VBases(), Definition(D), FirstFriend(0) {
}
+CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
+ return Bases.get(Definition->getASTContext().getExternalSource());
+}
+
+CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const {
+ return VBases.get(Definition->getASTContext().getExternalSource());
+}
+
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, CXXRecordDecl *PrevDecl)
@@ -219,8 +225,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// In the definition of a constexpr constructor [...]
// -- the class shall not have any virtual base classes
data().DefaultedDefaultConstructorIsConstexpr = false;
- data().DefaultedCopyConstructorIsConstexpr = false;
- data().DefaultedMoveConstructorIsConstexpr = false;
} else {
// C++ [class.ctor]p5:
// A default constructor is trivial [...] if:
@@ -259,25 +263,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// default constructor is constexpr.
if (!BaseClassDecl->hasConstexprDefaultConstructor())
data().DefaultedDefaultConstructorIsConstexpr = false;
-
- // C++11 [class.copy]p13:
- // If the implicitly-defined constructor would satisfy the requirements
- // of a constexpr constructor, the implicitly-defined constructor is
- // constexpr.
- // C++11 [dcl.constexpr]p4:
- // -- every constructor involved in initializing [...] base class
- // sub-objects shall be a constexpr constructor
- if (!BaseClassDecl->hasConstexprCopyConstructor())
- data().DefaultedCopyConstructorIsConstexpr = false;
- if (BaseClassDecl->hasDeclaredMoveConstructor() ||
- BaseClassDecl->needsImplicitMoveConstructor())
- // FIXME: If the implicit move constructor generated for the base class
- // would be ill-formed, the implicit move constructor generated for the
- // derived class calls the base class' copy constructor.
- data().DefaultedMoveConstructorIsConstexpr &=
- BaseClassDecl->hasConstexprMoveConstructor();
- else if (!BaseClassDecl->hasConstexprCopyConstructor())
- data().DefaultedMoveConstructorIsConstexpr = false;
}
// C++ [class.ctor]p3:
@@ -359,8 +344,8 @@ GetBestOverloadCandidateSimple(
if (Cands[Best].second.compatiblyIncludes(Cands[I].second))
Best = I;
- for (unsigned I = 1; I != N; ++I)
- if (Cands[Best].second.compatiblyIncludes(Cands[I].second))
+ for (unsigned I = 0; I != N; ++I)
+ if (I != Best && Cands[Best].second.compatiblyIncludes(Cands[I].second))
return 0;
return Cands[Best].first;
@@ -469,6 +454,14 @@ void CXXRecordDecl::markedVirtualFunctionPure() {
data().Abstract = true;
}
+void CXXRecordDecl::markedConstructorConstexpr(CXXConstructorDecl *CD) {
+ if (!CD->isCopyOrMoveConstructor())
+ data().HasConstexprNonCopyMoveConstructor = true;
+
+ if (CD->isDefaultConstructor())
+ data().HasConstexprDefaultConstructor = true;
+}
+
void CXXRecordDecl::addedMember(Decl *D) {
if (!D->isImplicit() &&
!isa<FieldDecl>(D) &&
@@ -545,12 +538,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
} else if (Constructor->isCopyConstructor()) {
data().DeclaredCopyConstructor = true;
- if (Constructor->isConstexpr())
- data().HasConstexprCopyConstructor = true;
} else if (Constructor->isMoveConstructor()) {
data().DeclaredMoveConstructor = true;
- if (Constructor->isConstexpr())
- data().HasConstexprMoveConstructor = true;
} else
goto NotASpecialMember;
return;
@@ -607,9 +596,6 @@ NotASpecialMember:;
// user-provided [...]
if (UserProvided)
data().HasTrivialCopyConstructor = false;
-
- if (Constructor->isConstexpr())
- data().HasConstexprCopyConstructor = true;
} else if (Constructor->isMoveConstructor()) {
data().UserDeclaredMoveConstructor = true;
data().DeclaredMoveConstructor = true;
@@ -619,9 +605,6 @@ NotASpecialMember:;
// user-provided [...]
if (UserProvided)
data().HasTrivialMoveConstructor = false;
-
- if (Constructor->isConstexpr())
- data().HasConstexprMoveConstructor = true;
}
}
if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) {
@@ -663,19 +646,9 @@ NotASpecialMember:;
// C++11 [class.dtor]p5:
// A destructor is trivial if it is not user-provided and if
// -- the destructor is not virtual.
- if (DD->isUserProvided() || DD->isVirtual()) {
+ if (DD->isUserProvided() || DD->isVirtual())
data().HasTrivialDestructor = false;
- // C++11 [dcl.constexpr]p1:
- // The constexpr specifier shall be applied only to [...] the
- // declaration of a static data member of a literal type.
- // C++11 [basic.types]p10:
- // A type is a literal type if it is [...] a class type that [...] has
- // a trivial destructor.
- data().DefaultedDefaultConstructorIsConstexpr = false;
- data().DefaultedCopyConstructorIsConstexpr = false;
- data().DefaultedMoveConstructorIsConstexpr = false;
- }
-
+
return;
}
@@ -792,7 +765,7 @@ NotASpecialMember:;
// that does not explicitly have no lifetime makes the class a non-POD.
// However, we delay setting PlainOldData to false in this case so that
// Sema has a chance to diagnostic causes where the same class will be
- // non-POD with Automatic Reference Counting but a POD without Instant Objects.
+ // non-POD with Automatic Reference Counting but a POD without ARC.
// In this case, the class will become a non-POD class when we complete
// the definition.
ASTContext &Context = getASTContext();
@@ -818,17 +791,19 @@ NotASpecialMember:;
data().HasNonLiteralTypeFieldsOrBases = true;
if (Field->hasInClassInitializer()) {
- // C++0x [class]p5:
+ data().HasInClassInitializer = true;
+
+ // C++11 [class]p5:
// A default constructor is trivial if [...] no non-static data member
// of its class has a brace-or-equal-initializer.
data().HasTrivialDefaultConstructor = false;
- // C++0x [dcl.init.aggr]p1:
+ // C++11 [dcl.init.aggr]p1:
// An aggregate is a [...] class with [...] no
// brace-or-equal-initializers for non-static data members.
data().Aggregate = false;
- // C++0x [class]p10:
+ // C++11 [class]p10:
// A POD struct is [...] a trivial class.
data().PlainOldData = false;
}
@@ -920,31 +895,15 @@ NotASpecialMember:;
// -- every constructor involved in initializing non-static data
// members [...] shall be a constexpr constructor
if (!Field->hasInClassInitializer() &&
- !FieldRec->hasConstexprDefaultConstructor())
+ !FieldRec->hasConstexprDefaultConstructor() && !isUnion())
// The standard requires any in-class initializer to be a constant
// expression. We consider this to be a defect.
data().DefaultedDefaultConstructorIsConstexpr = false;
-
- if (!FieldRec->hasConstexprCopyConstructor())
- data().DefaultedCopyConstructorIsConstexpr = false;
-
- if (FieldRec->hasDeclaredMoveConstructor() ||
- FieldRec->needsImplicitMoveConstructor())
- // FIXME: If the implicit move constructor generated for the member's
- // class would be ill-formed, the implicit move constructor generated
- // for this class calls the member's copy constructor.
- data().DefaultedMoveConstructorIsConstexpr &=
- FieldRec->hasConstexprMoveConstructor();
- else if (!FieldRec->hasConstexprCopyConstructor())
- data().DefaultedMoveConstructorIsConstexpr = false;
}
} else {
// Base element type of field is a non-class type.
- if (!T->isLiteralType()) {
- data().DefaultedDefaultConstructorIsConstexpr = false;
- data().DefaultedCopyConstructorIsConstexpr = false;
- data().DefaultedMoveConstructorIsConstexpr = false;
- } else if (!Field->hasInClassInitializer())
+ if (!T->isLiteralType() ||
+ (!Field->hasInClassInitializer() && !isUnion()))
data().DefaultedDefaultConstructorIsConstexpr = false;
}
@@ -1018,7 +977,7 @@ static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
/// Collect the visible conversions of a base class.
///
-/// \param Base a base class of the class we're considering
+/// \param Record a base class of the class we're considering
/// \param InVirtual whether this base class is a virtual base (or a base
/// of a virtual base)
/// \param Access the access along the inheritance path to this base
@@ -1050,8 +1009,10 @@ static void CollectVisibleConversions(ASTContext &Context,
HiddenTypes = &HiddenTypesBuffer;
for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I) {
- bool Hidden =
- !HiddenTypesBuffer.insert(GetConversionType(Context, I.getDecl()));
+ CanQualType ConvType(GetConversionType(Context, I.getDecl()));
+ bool Hidden = ParentHiddenTypes.count(ConvType);
+ if (!Hidden)
+ HiddenTypesBuffer.insert(ConvType);
// If this conversion is hidden and we're in a virtual base,
// remember that it's hidden along some inheritance path.
@@ -1247,13 +1208,16 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
// Objective-C Automatic Reference Counting:
// If a class has a non-static data member of Objective-C pointer
// type (or array thereof), it is a non-POD type and its
- // default constructor (if any), copy constructor, copy assignment
- // operator, and destructor are non-trivial.
+ // default constructor (if any), copy constructor, move constructor,
+ // copy assignment operator, move assignment operator, and destructor are
+ // non-trivial.
struct DefinitionData &Data = data();
Data.PlainOldData = false;
Data.HasTrivialDefaultConstructor = false;
Data.HasTrivialCopyConstructor = false;
+ Data.HasTrivialMoveConstructor = false;
Data.HasTrivialCopyAssignment = false;
+ Data.HasTrivialMoveAssignment = false;
Data.HasTrivialDestructor = false;
Data.HasIrrelevantDestructor = false;
}
@@ -1316,6 +1280,55 @@ bool CXXRecordDecl::mayBeAbstract() const {
void CXXMethodDecl::anchor() { }
+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;
+ if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl())
+ return true;
+ if (recursivelyOverrides(MD, BaseMD))
+ return true;
+ }
+ return false;
+}
+
+CXXMethodDecl *
+CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD) {
+ if (this->getParent()->getCanonicalDecl() == RD->getCanonicalDecl())
+ return this;
+
+ // Lookup doesn't work for destructors, so handle them separately.
+ if (isa<CXXDestructorDecl>(this)) {
+ CXXMethodDecl *MD = RD->getDestructor();
+ if (MD && recursivelyOverrides(MD, this))
+ return MD;
+ return NULL;
+ }
+
+ lookup_const_result Candidates = RD->lookup(getDeclName());
+ for (NamedDecl * const * I = Candidates.first; I != Candidates.second; ++I) {
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*I);
+ if (!MD)
+ continue;
+ if (recursivelyOverrides(MD, this))
+ return MD;
+ }
+
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const RecordType *RT = I->getType()->getAs<RecordType>();
+ if (!RT)
+ continue;
+ const CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl());
+ CXXMethodDecl *T = this->getCorrespondingMethodInClass(Base);
+ if (T)
+ return T;
+ }
+
+ return NULL;
+}
+
CXXMethodDecl *
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc,
@@ -1690,7 +1703,9 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
return (getNumParams() == 0 &&
getType()->getAs<FunctionProtoType>()->isVariadic()) ||
(getNumParams() == 1) ||
- (getNumParams() > 1 && getParamDecl(1)->hasDefaultArg());
+ (getNumParams() > 1 &&
+ (getParamDecl(1)->hasDefaultArg() ||
+ getParamDecl(1)->isParameterPack()));
}
bool CXXConstructorDecl::isSpecializationCopyingObject() const {
@@ -1993,15 +2008,17 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StaticAssertLoc,
Expr *AssertExpr,
StringLiteral *Message,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ bool Failed) {
return new (C) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message,
- RParenLoc);
+ RParenLoc, Failed);
}
StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(StaticAssertDecl));
- return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0,SourceLocation());
+ return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0,
+ SourceLocation(), false);
}
static const char *getAccessName(AccessSpecifier AS) {
OpenPOWER on IntegriCloud