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.cpp452
1 files changed, 328 insertions, 124 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 41f2449a9d6a0..076e6376d1578 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -74,7 +74,8 @@ 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),
+ Abstract(false), IsStandardLayout(true), IsCXX11StandardLayout(true),
+ HasBasesWithFields(false), HasBasesWithNonStaticDataMembers(false),
HasPrivateFields(false), HasProtectedFields(false),
HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false),
HasOnlyCMembers(true), HasInClassInitializer(false),
@@ -88,10 +89,11 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
DefaultedMoveConstructorIsDeleted(false),
DefaultedMoveAssignmentIsDeleted(false),
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
- DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
+ HasTrivialSpecialMembersForCall(SMF_All),
+ DeclaredNonTrivialSpecialMembers(0),
+ DeclaredNonTrivialSpecialMembersForCall(0), HasIrrelevantDestructor(true),
HasConstexprNonCopyMoveConstructor(false),
HasDefaultedDefaultConstructor(false),
- CanPassInRegisters(true),
DefaultedDefaultConstructorIsConstexpr(true),
HasConstexprDefaultConstructor(false),
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
@@ -124,8 +126,8 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
SourceLocation IdLoc, IdentifierInfo *Id,
CXXRecordDecl *PrevDecl,
bool DelayTypeCreation) {
- CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc,
- IdLoc, Id, PrevDecl);
+ auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
+ PrevDecl);
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
// FIXME: DelayTypeCreation seems like such a hack
@@ -139,9 +141,8 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
TypeSourceInfo *Info, SourceLocation Loc,
bool Dependent, bool IsGeneric,
LambdaCaptureDefault CaptureDefault) {
- CXXRecordDecl *R =
- new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
- nullptr, nullptr);
+ auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
+ nullptr, nullptr);
R->IsBeingDefined = true;
R->DefinitionData =
new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
@@ -154,13 +155,32 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
CXXRecordDecl *
CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
- CXXRecordDecl *R = new (C, ID) CXXRecordDecl(
+ auto *R = new (C, ID) CXXRecordDecl(
CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
R->MayHaveOutOfDateDef = false;
return R;
}
+/// Determine whether a class has a repeated base class. This is intended for
+/// use when determining if a class is standard-layout, so makes no attempt to
+/// handle virtual bases.
+static bool hasRepeatedBaseClass(const CXXRecordDecl *StartRD) {
+ llvm::SmallPtrSet<const CXXRecordDecl*, 8> SeenBaseTypes;
+ SmallVector<const CXXRecordDecl*, 8> WorkList = {StartRD};
+ while (!WorkList.empty()) {
+ const CXXRecordDecl *RD = WorkList.pop_back_val();
+ for (const CXXBaseSpecifier &BaseSpec : RD->bases()) {
+ if (const CXXRecordDecl *B = BaseSpec.getType()->getAsCXXRecordDecl()) {
+ if (!SeenBaseTypes.insert(B).second)
+ return true;
+ WorkList.push_back(B);
+ }
+ }
+ }
+ return false;
+}
+
void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
unsigned NumBases) {
@@ -197,29 +217,40 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// Skip dependent types; we can't do any checking on them now.
if (BaseType->isDependentType())
continue;
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+ auto *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- if (!BaseClassDecl->isEmpty()) {
- if (!data().Empty) {
- // C++0x [class]p7:
- // A standard-layout class is a class that:
- // [...]
- // -- either has no non-static data members in the most derived
- // class and at most one base class with non-static data members,
- // or has no base classes with non-static data members, and
- // If this is the second non-empty base, then neither of these two
- // clauses can be true.
+ // C++2a [class]p7:
+ // A standard-layout class is a class that:
+ // [...]
+ // -- has all non-static data members and bit-fields in the class and
+ // its base classes first declared in the same class
+ if (BaseClassDecl->data().HasBasesWithFields ||
+ !BaseClassDecl->field_empty()) {
+ if (data().HasBasesWithFields)
+ // Two bases have members or bit-fields: not standard-layout.
data().IsStandardLayout = false;
- }
+ data().HasBasesWithFields = true;
+ }
+
+ // C++11 [class]p7:
+ // A standard-layout class is a class that:
+ // -- [...] has [...] at most one base class with non-static data
+ // members
+ if (BaseClassDecl->data().HasBasesWithNonStaticDataMembers ||
+ BaseClassDecl->hasDirectFields()) {
+ if (data().HasBasesWithNonStaticDataMembers)
+ data().IsCXX11StandardLayout = false;
+ data().HasBasesWithNonStaticDataMembers = true;
+ }
+ if (!BaseClassDecl->isEmpty()) {
// 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)
@@ -228,14 +259,20 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// C++ [class.virtual]p1:
// A class that declares or inherits a virtual function is called a
// polymorphic class.
- if (BaseClassDecl->isPolymorphic())
+ if (BaseClassDecl->isPolymorphic()) {
data().Polymorphic = true;
+ // An aggregate is a class with [...] no virtual functions.
+ data().Aggregate = false;
+ }
+
// C++0x [class]p7:
// A standard-layout class is a class that: [...]
// -- has no non-standard-layout base classes
if (!BaseClassDecl->isStandardLayout())
data().IsStandardLayout = false;
+ if (!BaseClassDecl->isCXX11StandardLayout())
+ data().IsCXX11StandardLayout = false;
// Record if this base is the first non-literal field or base.
if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType(C))
@@ -281,11 +318,13 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// operator for a class X] is trivial [...] if:
// -- class X has [...] no virtual base classes
data().HasTrivialSpecialMembers &= SMF_Destructor;
+ data().HasTrivialSpecialMembersForCall &= SMF_Destructor;
// C++0x [class]p7:
// A standard-layout class is a class that: [...]
// -- has [...] no virtual base classes
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
// C++11 [dcl.constexpr]p4:
// In the definition of a constexpr constructor [...]
@@ -314,6 +353,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// subobject is trivial, and
if (!BaseClassDecl->hasTrivialCopyConstructor())
data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
+
+ if (!BaseClassDecl->hasTrivialCopyConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;
+
// If the base class doesn't have a simple move constructor, we'll eagerly
// declare it and perform overload resolution to determine which function
// it actually calls. If it does have a simple move constructor, this
@@ -321,6 +364,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (!BaseClassDecl->hasTrivialMoveConstructor())
data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
+ if (!BaseClassDecl->hasTrivialMoveConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;
+
// C++0x [class.copy]p27:
// A copy/move assignment operator for class X is trivial if [...]
// [...]
@@ -357,6 +403,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (!BaseClassDecl->hasTrivialDestructor())
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
+ if (!BaseClassDecl->hasTrivialDestructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
+
if (!BaseClassDecl->hasIrrelevantDestructor())
data().HasIrrelevantDestructor = false;
@@ -376,6 +425,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (BaseClassDecl->hasVolatileMember())
setHasVolatileMember(true);
+ if (BaseClassDecl->getArgPassingRestrictions() ==
+ RecordDecl::APK_CanNeverPassInRegs)
+ setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+
// Keep track of the presence of mutable fields.
if (BaseClassDecl->hasMutableFields()) {
data().HasMutableFields = true;
@@ -390,6 +443,16 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
addedClassSubobject(BaseClassDecl);
}
+
+ // C++2a [class]p7:
+ // A class S is a standard-layout class if it:
+ // -- has at most one base class subobject of any given type
+ //
+ // Note that we only need to check this for classes with more than one base
+ // class. If there's only one base class, and it's standard layout, then
+ // we know there are no repeated base classes.
+ if (data().IsStandardLayout && NumBases > 1 && hasRepeatedBaseClass(this))
+ data().IsStandardLayout = false;
if (VBases.empty()) {
data().IsParsingBaseSpecifiers = false;
@@ -490,6 +553,81 @@ void CXXRecordDecl::markedVirtualFunctionPure() {
data().Abstract = true;
}
+bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType(
+ ASTContext &Ctx, const CXXRecordDecl *XFirst) {
+ if (!getNumBases())
+ return false;
+
+ llvm::SmallPtrSet<const CXXRecordDecl*, 8> Bases;
+ llvm::SmallPtrSet<const CXXRecordDecl*, 8> M;
+ SmallVector<const CXXRecordDecl*, 8> WorkList;
+
+ // Visit a type that we have determined is an element of M(S).
+ auto Visit = [&](const CXXRecordDecl *RD) -> bool {
+ RD = RD->getCanonicalDecl();
+
+ // C++2a [class]p8:
+ // A class S is a standard-layout class if it [...] has no element of the
+ // set M(S) of types as a base class.
+ //
+ // If we find a subobject of an empty type, it might also be a base class,
+ // so we'll need to walk the base classes to check.
+ if (!RD->data().HasBasesWithFields) {
+ // Walk the bases the first time, stopping if we find the type. Build a
+ // set of them so we don't need to walk them again.
+ if (Bases.empty()) {
+ bool RDIsBase = !forallBases([&](const CXXRecordDecl *Base) -> bool {
+ Base = Base->getCanonicalDecl();
+ if (RD == Base)
+ return false;
+ Bases.insert(Base);
+ return true;
+ });
+ if (RDIsBase)
+ return true;
+ } else {
+ if (Bases.count(RD))
+ return true;
+ }
+ }
+
+ if (M.insert(RD).second)
+ WorkList.push_back(RD);
+ return false;
+ };
+
+ if (Visit(XFirst))
+ return true;
+
+ while (!WorkList.empty()) {
+ const CXXRecordDecl *X = WorkList.pop_back_val();
+
+ // FIXME: We don't check the bases of X. That matches the standard, but
+ // that sure looks like a wording bug.
+
+ // -- If X is a non-union class type with a non-static data member
+ // [recurse to] the first non-static data member of X
+ // -- If X is a union type, [recurse to union members]
+ for (auto *FD : X->fields()) {
+ // FIXME: Should we really care about the type of the first non-static
+ // data member of a non-union if there are preceding unnamed bit-fields?
+ if (FD->isUnnamedBitfield())
+ continue;
+
+ // -- If X is n array type, [visit the element type]
+ QualType T = Ctx.getBaseElementType(FD->getType());
+ if (auto *RD = T->getAsCXXRecordDecl())
+ if (Visit(RD))
+ return true;
+
+ if (!X->isUnion())
+ break;
+ }
+ }
+
+ return false;
+}
+
void CXXRecordDecl::addedMember(Decl *D) {
if (!D->isImplicit() &&
!isa<FieldDecl>(D) &&
@@ -502,7 +640,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (D->getFriendObjectKind() || D->isInvalidDecl())
return;
- FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (FunTmpl)
D = FunTmpl->getTemplatedDecl();
@@ -510,12 +648,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
Decl *DUnderlying = D;
if (auto *ND = dyn_cast<NamedDecl>(DUnderlying)) {
DUnderlying = ND->getUnderlyingDecl();
- if (FunctionTemplateDecl *UnderlyingFunTmpl =
- dyn_cast<FunctionTemplateDecl>(DUnderlying))
+ if (auto *UnderlyingFunTmpl = dyn_cast<FunctionTemplateDecl>(DUnderlying))
DUnderlying = UnderlyingFunTmpl->getTemplatedDecl();
}
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isVirtual()) {
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class with [...] no virtual functions.
@@ -539,11 +676,13 @@ void CXXRecordDecl::addedMember(Decl *D) {
// assignment operator for a class X] is trivial [...] if:
// -- class X has no virtual functions [...]
data().HasTrivialSpecialMembers &= SMF_Destructor;
+ data().HasTrivialSpecialMembersForCall &= SMF_Destructor;
// C++0x [class]p7:
// A standard-layout class is a class that: [...]
// -- has no virtual functions
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
}
}
@@ -557,7 +696,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
unsigned SMKind = 0;
// Handle constructors.
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
if (!Constructor->isImplicit()) {
// Note that we have a user-declared constructor.
data().UserDeclaredConstructor = true;
@@ -599,8 +738,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Handle constructors, including those inherited from base classes.
- if (CXXConstructorDecl *Constructor =
- dyn_cast<CXXConstructorDecl>(DUnderlying)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(DUnderlying)) {
// Record if we see any constexpr constructors which are neither copy
// nor move constructors.
// C++1z [basic.types]p10:
@@ -612,7 +750,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Handle destructors.
- if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) {
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
SMKind |= SMF_Destructor;
if (DD->isUserProvided())
@@ -623,17 +761,19 @@ void CXXRecordDecl::addedMember(Decl *D) {
// C++11 [class.dtor]p5:
// A destructor is trivial if [...] the destructor is not virtual.
- if (DD->isVirtual())
+ if (DD->isVirtual()) {
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
+ data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
+ }
}
// Handle member functions.
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isCopyAssignmentOperator()) {
SMKind |= SMF_CopyAssignment;
- const ReferenceType *ParamTy =
- Method->getParamDecl(0)->getType()->getAs<ReferenceType>();
+ const auto *ParamTy =
+ Method->getParamDecl(0)->getType()->getAs<ReferenceType>();
if (!ParamTy || ParamTy->getPointeeType().isConstQualified())
data().HasDeclaredCopyAssignmentWithConstParam = true;
}
@@ -642,7 +782,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
SMKind |= SMF_MoveAssignment;
// Keep the list of conversion functions up-to-date.
- if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
+ if (auto *Conversion = dyn_cast<CXXConversionDecl>(D)) {
// FIXME: We use the 'unsafe' accessor for the access specifier here,
// because Sema may not have set it yet. That's really just a misdesign
// in Sema. However, LLDB *will* have set the access specifier correctly,
@@ -670,16 +810,30 @@ void CXXRecordDecl::addedMember(Decl *D) {
// If this is the first declaration of a special member, we no longer have
// an implicit trivial special member.
data().HasTrivialSpecialMembers &=
- data().DeclaredSpecialMembers | ~SMKind;
+ data().DeclaredSpecialMembers | ~SMKind;
+ data().HasTrivialSpecialMembersForCall &=
+ data().DeclaredSpecialMembers | ~SMKind;
if (!Method->isImplicit() && !Method->isUserProvided()) {
// This method is user-declared but not user-provided. We can't work out
// whether it's trivial yet (not until we get to the end of the class).
// We'll handle this method in finishedDefaultedOrDeletedMember.
- } else if (Method->isTrivial())
+ } else if (Method->isTrivial()) {
data().HasTrivialSpecialMembers |= SMKind;
- else
+ data().HasTrivialSpecialMembersForCall |= SMKind;
+ } else if (Method->isTrivialForCall()) {
+ data().HasTrivialSpecialMembersForCall |= SMKind;
data().DeclaredNonTrivialSpecialMembers |= SMKind;
+ } else {
+ data().DeclaredNonTrivialSpecialMembers |= SMKind;
+ // If this is a user-provided function, do not set
+ // DeclaredNonTrivialSpecialMembersForCall here since we don't know
+ // yet whether the method would be considered non-trivial for the
+ // purpose of calls (attribute "trivial_abi" can be dropped from the
+ // class later, which can change the special method's triviality).
+ if (!Method->isUserProvided())
+ data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
+ }
// Note when we have declared a declared special member, and suppress the
// implicit declaration of this special member.
@@ -707,14 +861,39 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// Handle non-static data members.
- if (FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
+ if (const auto *Field = dyn_cast<FieldDecl>(D)) {
+ ASTContext &Context = getASTContext();
+
+ // C++2a [class]p7:
+ // A standard-layout class is a class that:
+ // [...]
+ // -- has all non-static data members and bit-fields in the class and
+ // its base classes first declared in the same class
+ if (data().HasBasesWithFields)
+ data().IsStandardLayout = false;
+
// C++ [class.bit]p2:
// A declaration for a bit-field that omits the identifier declares an
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
// initialized.
- if (Field->isUnnamedBitfield())
+ if (Field->isUnnamedBitfield()) {
+ // C++ [meta.unary.prop]p4: [LWG2358]
+ // T is a class type [...] with [...] no unnamed bit-fields of non-zero
+ // length
+ if (data().Empty && !Field->isZeroLengthBitField(Context) &&
+ Context.getLangOpts().getClangABICompat() >
+ LangOptions::ClangABI::Ver6)
+ data().Empty = false;
return;
+ }
+ // C++11 [class]p7:
+ // A standard-layout class is a class that:
+ // -- either has no non-static data members in the most derived class
+ // [...] or has no base classes with non-static data members
+ if (data().HasBasesWithNonStaticDataMembers)
+ data().IsCXX11StandardLayout = false;
+
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...] no
// private or protected non-static data members (clause 11).
@@ -725,6 +904,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().PlainOldData = false;
}
+ // Track whether this is the first field. We use this when checking
+ // whether the class is standard-layout below.
+ bool IsFirstField = !data().HasPrivateFields &&
+ !data().HasProtectedFields && !data().HasPublicFields;
+
// C++0x [class]p7:
// A standard-layout class is a class that:
// [...]
@@ -736,8 +920,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
case AS_none: llvm_unreachable("Invalid access specifier");
};
if ((data().HasPrivateFields + data().HasProtectedFields +
- data().HasPublicFields) > 1)
+ data().HasPublicFields) > 1) {
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
+ }
// Keep track of the presence of mutable fields.
if (Field->isMutable()) {
@@ -758,7 +944,6 @@ void CXXRecordDecl::addedMember(Decl *D) {
//
// Automatic Reference Counting: the presence of a member of Objective-C pointer type
// that does not explicitly have no lifetime makes the class a non-POD.
- ASTContext &Context = getASTContext();
QualType T = Context.getBaseElementType(Field->getType());
if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
if (T.hasNonTrivialObjCLifetime()) {
@@ -772,6 +957,17 @@ void CXXRecordDecl::addedMember(Decl *D) {
struct DefinitionData &Data = data();
Data.PlainOldData = false;
Data.HasTrivialSpecialMembers = 0;
+
+ // __strong or __weak fields do not make special functions non-trivial
+ // for the purpose of calls.
+ Qualifiers::ObjCLifetime LT = T.getQualifiers().getObjCLifetime();
+ if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak)
+ data().HasTrivialSpecialMembersForCall = 0;
+
+ // Structs with __weak fields should never be passed directly.
+ if (LT == Qualifiers::OCL_Weak)
+ setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
+
Data.HasIrrelevantDestructor = false;
} else if (!Context.getLangOpts().ObjCAutoRefCount) {
setHasObjectMember(true);
@@ -787,6 +983,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// A standard-layout class is a class that:
// -- has no non-static data members of type [...] reference,
data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
// C++1z [class.copy.ctor]p10:
// A defaulted copy constructor for a class X is defined as deleted if X has:
@@ -838,8 +1035,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (T->isReferenceType())
data().DefaultedMoveAssignmentIsDeleted = true;
- if (const RecordType *RecordTy = T->getAs<RecordType>()) {
- CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (const auto *RecordTy = T->getAs<RecordType>()) {
+ auto *FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
if (FieldRec->getDefinition()) {
addedClassSubobject(FieldRec);
@@ -899,12 +1096,19 @@ void CXXRecordDecl::addedMember(Decl *D) {
// member is trivial;
if (!FieldRec->hasTrivialCopyConstructor())
data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;
+
+ if (!FieldRec->hasTrivialCopyConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;
+
// If the field doesn't have a simple move constructor, we'll eagerly
// declare the move constructor for this class and we'll decide whether
// it's trivial then.
if (!FieldRec->hasTrivialMoveConstructor())
data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;
+ if (!FieldRec->hasTrivialMoveConstructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;
+
// C++0x [class.copy]p27:
// A copy/move assignment operator for class X is trivial if [...]
// [...]
@@ -921,12 +1125,17 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (!FieldRec->hasTrivialDestructor())
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
+ if (!FieldRec->hasTrivialDestructorForCall())
+ data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
if (!FieldRec->hasIrrelevantDestructor())
data().HasIrrelevantDestructor = false;
if (FieldRec->hasObjectMember())
setHasObjectMember(true);
if (FieldRec->hasVolatileMember())
setHasVolatileMember(true);
+ if (FieldRec->getArgPassingRestrictions() ==
+ RecordDecl::APK_CanNeverPassInRegs)
+ setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
// C++0x [class]p7:
// A standard-layout class is a class that:
@@ -934,31 +1143,32 @@ void CXXRecordDecl::addedMember(Decl *D) {
// class (or array of such types) [...]
if (!FieldRec->isStandardLayout())
data().IsStandardLayout = false;
+ if (!FieldRec->isCXX11StandardLayout())
+ data().IsCXX11StandardLayout = false;
- // C++0x [class]p7:
+ // C++2a [class]p7:
// A standard-layout class is a class that:
// [...]
+ // -- has no element of the set M(S) of types as a base class.
+ if (data().IsStandardLayout && (isUnion() || IsFirstField) &&
+ hasSubobjectAtOffsetZeroOfEmptyBaseType(Context, FieldRec))
+ data().IsStandardLayout = false;
+
+ // C++11 [class]p7:
+ // A standard-layout class is a class that:
// -- has no base classes of the same type as the first non-static
- // data member.
- // We don't want to expend bits in the state of the record decl
- // tracking whether this is the first non-static data member so we
- // cheat a bit and use some of the existing state: the empty bit.
- // Virtual bases and virtual methods make a class non-empty, but they
- // also make it non-standard-layout so we needn't check here.
- // A non-empty base class may leave the class standard-layout, but not
- // if we have arrived here, and have at least one non-static data
- // member. If IsStandardLayout remains true, then the first non-static
- // data member must come through here with Empty still true, and Empty
- // will subsequently be set to false below.
- if (data().IsStandardLayout && data().Empty) {
+ // data member
+ if (data().IsCXX11StandardLayout && IsFirstField) {
+ // FIXME: We should check all base classes here, not just direct
+ // base classes.
for (const auto &BI : bases()) {
if (Context.hasSameUnqualifiedType(BI.getType(), T)) {
- data().IsStandardLayout = false;
+ data().IsCXX11StandardLayout = false;
break;
}
}
}
-
+
// Keep track of the presence of mutable fields.
if (FieldRec->hasMutableFields()) {
data().HasMutableFields = true;
@@ -1021,31 +1231,13 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().DefaultedMoveAssignmentIsDeleted = true;
}
- // C++0x [class]p7:
- // A standard-layout class is a class that:
- // [...]
- // -- either has no non-static data members in the most derived
- // class and at most one base class with non-static data members,
- // or has no base classes with non-static data members, and
- // At this point we know that we have a non-static data member, so the last
- // clause holds.
- if (!data().HasNoNonEmptyBases)
- data().IsStandardLayout = false;
-
// 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() &&
- !Field->getBitWidth()->isValueDependent() &&
- Field->getBitWidthValue(Context) != 0))
- data().Empty = false;
- }
+ // T is a class type [...] with [...] no non-static data members
+ data().Empty = false;
}
// Handle using declarations of conversion functions.
- if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(D)) {
+ if (auto *Shadow = dyn_cast<UsingShadowDecl>(D)) {
if (Shadow->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName) {
ASTContext &Ctx = getASTContext();
@@ -1053,7 +1245,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
}
- if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
+ if (const auto *Using = dyn_cast<UsingDecl>(D)) {
if (Using->getDeclName().getNameKind() ==
DeclarationName::CXXConstructorName) {
data().HasInheritedConstructor = true;
@@ -1073,7 +1265,7 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
// The kind of special member this declaration is, if any.
unsigned SMKind = 0;
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
if (Constructor->isDefaultConstructor()) {
SMKind |= SMF_DefaultConstructor;
if (Constructor->isConstexpr())
@@ -1103,6 +1295,23 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
data().DeclaredNonTrivialSpecialMembers |= SMKind;
}
+void CXXRecordDecl::setTrivialForCallFlags(CXXMethodDecl *D) {
+ unsigned SMKind = 0;
+
+ if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (Constructor->isCopyConstructor())
+ SMKind = SMF_CopyConstructor;
+ else if (Constructor->isMoveConstructor())
+ SMKind = SMF_MoveConstructor;
+ } else if (isa<CXXDestructorDecl>(D))
+ SMKind = SMF_Destructor;
+
+ if (D->isTrivialForCall())
+ data().HasTrivialSpecialMembersForCall |= SMKind;
+ else
+ data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
+}
+
bool CXXRecordDecl::isCLike() const {
if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
!TemplateOrInstantiation.isNull())
@@ -1128,8 +1337,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
assert(Calls.size() == 1 && "More than one lambda call operator!");
NamedDecl *CallOp = Calls.front();
- if (FunctionTemplateDecl *CallOpTmpl =
- dyn_cast<FunctionTemplateDecl>(CallOp))
+ if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());
return cast<CXXMethodDecl>(CallOp);
@@ -1143,8 +1351,7 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
if (Invoker.empty()) return nullptr;
assert(Invoker.size() == 1 && "More than one static invoker operator!");
NamedDecl *InvokerFun = Invoker.front();
- if (FunctionTemplateDecl *InvokerTemplate =
- dyn_cast<FunctionTemplateDecl>(InvokerFun))
+ if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun))
return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl());
return cast<CXXMethodDecl>(InvokerFun);
@@ -1257,7 +1464,7 @@ static void CollectVisibleConversions(ASTContext &Context,
= CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier());
bool BaseInVirtual = InVirtual || I.isVirtual();
- CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl());
+ auto *Base = cast<CXXRecordDecl>(RT->getDecl());
CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess,
*HiddenTypes, Output, VOutput, HiddenVBaseCs);
}
@@ -1384,8 +1591,7 @@ void CXXRecordDecl::setDescribedClassTemplate(ClassTemplateDecl *Template) {
}
TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
- if (const ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(this))
+ if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this))
return Spec->getSpecializationKind();
if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
@@ -1396,8 +1602,7 @@ TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
void
CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
+ if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
Spec->setSpecializationKind(TSK);
return;
}
@@ -1575,7 +1780,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
SOEnd = M->second.end();
SO != SOEnd && !Done; ++SO) {
assert(SO->second.size() > 0 &&
- "All virtual functions have overridding virtual functions");
+ "All virtual functions have overriding virtual functions");
// C++ [class.abstract]p4:
// A class is abstract if it contains or inherits at least one
@@ -1602,8 +1807,8 @@ bool CXXRecordDecl::mayBeAbstract() const {
return false;
for (const auto &B : bases()) {
- CXXRecordDecl *BaseDecl
- = cast<CXXRecordDecl>(B.getType()->getAs<RecordType>()->getDecl());
+ const auto *BaseDecl =
+ cast<CXXRecordDecl>(B.getType()->getAs<RecordType>()->getDecl());
if (BaseDecl->isAbstract())
return true;
}
@@ -1670,7 +1875,7 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
}
for (auto *ND : RD->lookup(getDeclName())) {
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND);
+ auto *MD = dyn_cast<CXXMethodDecl>(ND);
if (!MD)
continue;
if (recursivelyOverrides(MD, this))
@@ -1683,7 +1888,7 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
const RecordType *RT = I.getType()->getAs<RecordType>();
if (!RT)
continue;
- const CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl());
+ const auto *Base = cast<CXXRecordDecl>(RT->getDecl());
CXXMethodDecl *T = this->getCorrespondingMethodInClass(Base);
if (T)
return T;
@@ -1758,8 +1963,8 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
if (BestDynamicDecl->hasAttr<FinalAttr>())
return DevirtualizedMethod;
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
if (VD->getType()->isRecordType())
// This is a record decl. We know the type and can devirtualize it.
return DevirtualizedMethod;
@@ -1770,9 +1975,10 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
// We can devirtualize calls on an object accessed by a class member access
// expression, since by C++11 [basic.life]p6 we know that it can't refer to
// a derived class object constructed in the same location.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base))
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl()))
- return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr;
+ if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
+ const ValueDecl *VD = ME->getMemberDecl();
+ return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr;
+ }
// Likewise for calls on an object accessed by a (non-reference) pointer to
// member access.
@@ -1848,7 +2054,7 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
I != E; ++I) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I))
+ if (const auto *FD = dyn_cast<FunctionDecl>(*I))
if (FD->getNumParams() == 1)
return false;
}
@@ -1868,7 +2074,7 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const {
return false;
QualType ParamType = getParamDecl(0)->getType();
- if (const LValueReferenceType *Ref = ParamType->getAs<LValueReferenceType>())
+ if (const auto *Ref = ParamType->getAs<LValueReferenceType>())
ParamType = Ref->getPointeeType();
ASTContext &Context = getASTContext();
@@ -2006,7 +2212,7 @@ TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
else
- return TypeLoc();
+ return {};
}
const Type *CXXCtorInitializer::getBaseClass() const {
@@ -2023,10 +2229,10 @@ SourceLocation CXXCtorInitializer::getSourceLocation() const {
if (isAnyMemberInitializer())
return getMemberLocation();
- if (TypeSourceInfo *TSInfo = Initializee.get<TypeSourceInfo*>())
+ if (const auto *TSInfo = Initializee.get<TypeSourceInfo *>())
return TSInfo->getTypeLoc().getLocalSourceRange().getBegin();
- return SourceLocation();
+ return {};
}
SourceRange CXXCtorInitializer::getSourceRange() const {
@@ -2034,7 +2240,7 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
FieldDecl *D = getAnyMember();
if (Expr *I = D->getInClassInitializer())
return I->getSourceRange();
- return SourceRange();
+ return {};
}
return SourceRange(getSourceLocation(), getRParenLoc());
@@ -2078,7 +2284,7 @@ CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
assert(isDelegatingConstructor() && "Not a delegating constructor!");
Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
- if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E))
+ if (const auto *Construct = dyn_cast<CXXConstructExpr>(E))
return Construct->getConstructor();
return nullptr;
@@ -2103,7 +2309,7 @@ bool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const {
getParamDecl(0)->getType()->isRValueReferenceType();
}
-/// \brief Determine whether this is a copy or move constructor.
+/// Determine whether this is a copy or move constructor.
bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
// C++ [class.copy]p2:
// A non-template constructor for class X is a copy constructor
@@ -2124,7 +2330,7 @@ bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
const ParmVarDecl *Param = getParamDecl(0);
// Do we have a reference type?
- const ReferenceType *ParamRefType = Param->getType()->getAs<ReferenceType>();
+ const auto *ParamRefType = Param->getType()->getAs<ReferenceType>();
if (!ParamRefType)
return false;
@@ -2174,7 +2380,7 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
ASTContext &Context = getASTContext();
CanQualType ParamType = Context.getCanonicalType(Param->getType());
- // Is it the same as our our class type?
+ // Is it the same as our class type?
CanQualType ClassTy
= Context.getCanonicalType(Context.getTagDeclType(getParent()));
if (ParamType.getUnqualifiedType() != ClassTy)
@@ -2271,7 +2477,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentLoc,
NamedDecl *Used,
DeclContext *CommonAncestor) {
- if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used))
+ if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Used))
Used = NS->getOriginalNamespace();
return new (C, DC) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
IdentLoc, Used, CommonAncestor);
@@ -2286,8 +2492,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C,
}
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
- if (NamespaceAliasDecl *NA =
- dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
+ if (auto *NA = dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
return NA->getNamespace();
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
@@ -2367,7 +2572,7 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentLoc,
NamedDecl *Namespace) {
// FIXME: Preserve the aliased namespace as written.
- if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
+ if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias,
QualifierLoc, IdentLoc, Namespace);
@@ -2387,10 +2592,9 @@ 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)) {
+ redeclarable_base(C), UsingOrNextShadow(cast<NamedDecl>(Using)) {
if (Target)
- IdentifierNamespace = Target->getIdentifierNamespace();
+ setTargetDecl(Target);
setImplicit();
}
@@ -2405,8 +2609,8 @@ UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
UsingDecl *UsingShadowDecl::getUsingDecl() const {
const UsingShadowDecl *Shadow = this;
- while (const UsingShadowDecl *NextShadow =
- dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
+ while (const auto *NextShadow =
+ dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
Shadow = NextShadow;
return cast<UsingDecl>(Shadow->UsingOrNextShadow);
}
@@ -2625,7 +2829,7 @@ DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
void DecompositionDecl::printName(llvm::raw_ostream &os) const {
os << '[';
bool Comma = false;
- for (auto *B : bindings()) {
+ for (const auto *B : bindings()) {
if (Comma)
os << ", ";
B->printName(os);