summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp150
1 files changed, 125 insertions, 25 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 28a88d5bb8b..45adbe3a16e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5780,20 +5780,20 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
if (D->needsImplicitCopyConstructor() &&
!D->defaultedCopyConstructorIsDeleted()) {
- if (!D->hasTrivialCopyConstructor())
+ if (!D->hasTrivialCopyConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
!D->defaultedMoveConstructorIsDeleted()) {
- if (!D->hasTrivialMoveConstructor())
+ if (!D->hasTrivialMoveConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
- !D->hasTrivialDestructor())
+ !D->hasTrivialDestructorForCall())
return false;
for (const CXXMethodDecl *MD : D->methods()) {
@@ -5806,7 +5806,7 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {
else if (!isa<CXXDestructorDecl>(MD))
continue;
- if (!MD->isTrivial())
+ if (!MD->isTrivialForCall())
return false;
}
@@ -5890,6 +5890,13 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
+ // Set HasTrivialSpecialMemberForCall if the record has attribute
+ // "trivial_abi".
+ bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>();
+
+ if (HasTrivialABI)
+ Record->setHasTrivialSpecialMemberForCall();
+
bool HasMethodWithOverrideControl = false,
HasOverridingMethodWithoutOverrideControl = false;
if (!Record->isDependentType()) {
@@ -5912,12 +5919,23 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (!M->isImplicit() && !M->isUserProvided()) {
if (CSM != CXXInvalid) {
M->setTrivial(SpecialMemberIsTrivial(M, CSM));
-
// Inform the class that we've finished declaring this member.
Record->finishedDefaultedOrDeletedMember(M);
+ M->setTrivialForCall(
+ HasTrivialABI ||
+ SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI));
+ Record->setTrivialForCallFlags(M);
}
}
+ // Set triviality for the purpose of calls if this is a user-provided
+ // copy/move constructor or destructor.
+ if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
+ CSM == CXXDestructor) && M->isUserProvided()) {
+ M->setTrivialForCall(HasTrivialABI);
+ Record->setTrivialForCallFlags(M);
+ }
+
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() &&
M->hasAttr<DLLExportAttr>()) {
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
@@ -7029,9 +7047,14 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
///
/// If \p Selected is not \c NULL, \c *Selected will be filled in with the
/// member that was most likely to be intended to be trivial, if any.
+///
+/// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to
+/// determine whether the special member is trivial.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM, unsigned Quals,
- bool ConstRHS, CXXMethodDecl **Selected) {
+ bool ConstRHS,
+ Sema::TrivialABIHandling TAH,
+ CXXMethodDecl **Selected) {
if (Selected)
*Selected = nullptr;
@@ -7072,7 +7095,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.dtor]p5:
// A destructor is trivial if:
// - all the direct [subobjects] have trivial destructors
- if (RD->hasTrivialDestructor())
+ if (RD->hasTrivialDestructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialDestructorForCall()))
return true;
if (Selected) {
@@ -7087,7 +7112,9 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// C++11 [class.copy]p12:
// A copy constructor is trivial if:
// - the constructor selected to copy each direct [subobject] is trivial
- if (RD->hasTrivialCopyConstructor()) {
+ if (RD->hasTrivialCopyConstructor() ||
+ (TAH == Sema::TAH_ConsiderTrivialABI &&
+ RD->hasTrivialCopyConstructorForCall())) {
if (Quals == Qualifiers::Const)
// We must either select the trivial copy constructor or reach an
// ambiguity; no need to actually perform overload resolution.
@@ -7140,6 +7167,10 @@ static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
// not supposed to!
if (Selected)
*Selected = SMOR.getMethod();
+
+ if (TAH == Sema::TAH_ConsiderTrivialABI &&
+ (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor))
+ return SMOR.getMethod()->isTrivialForCall();
return SMOR.getMethod()->isTrivial();
}
@@ -7178,14 +7209,14 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
QualType SubType, bool ConstRHS,
Sema::CXXSpecialMember CSM,
TrivialSubobjectKind Kind,
- bool Diagnose) {
+ Sema::TrivialABIHandling TAH, bool Diagnose) {
CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
if (!SubRD)
return true;
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
- ConstRHS, Diagnose ? &Selected : nullptr))
+ ConstRHS, TAH, Diagnose ? &Selected : nullptr))
return true;
if (Diagnose) {
@@ -7215,7 +7246,8 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
<< Kind << SubType.getUnqualifiedType() << CSM;
// Explain why the defaulted or deleted special member isn't trivial.
- S.SpecialMemberIsTrivial(Selected, CSM, Diagnose);
+ S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI,
+ Diagnose);
}
}
@@ -7226,7 +7258,9 @@ static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
/// trivial.
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM,
- bool ConstArg, bool Diagnose) {
+ bool ConstArg,
+ Sema::TrivialABIHandling TAH,
+ bool Diagnose) {
for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
continue;
@@ -7236,7 +7270,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
// Pretend anonymous struct or union members are members of this class.
if (FI->isAnonymousStructOrUnion()) {
if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(),
- CSM, ConstArg, Diagnose))
+ CSM, ConstArg, TAH, Diagnose))
return false;
continue;
}
@@ -7264,7 +7298,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
bool ConstRHS = ConstArg && !FI->isMutable();
if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
- CSM, TSK_Field, Diagnose))
+ CSM, TSK_Field, TAH, Diagnose))
return false;
}
@@ -7278,14 +7312,15 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
- TSK_CompleteObject, /*Diagnose*/true);
+ TSK_CompleteObject, TAH_IgnoreTrivialABI,
+ /*Diagnose*/true);
}
/// Determine whether a defaulted or deleted special member function is trivial,
/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12,
/// C++11 [class.copy]p25, and C++11 [class.dtor]p5.
bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
- bool Diagnose) {
+ TrivialABIHandling TAH, bool Diagnose) {
assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough");
CXXRecordDecl *RD = MD->getParent();
@@ -7362,7 +7397,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// destructors]
for (const auto &BI : RD->bases())
if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(),
- ConstArg, CSM, TSK_BaseClass, Diagnose))
+ ConstArg, CSM, TSK_BaseClass, TAH, Diagnose))
return false;
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
@@ -7377,7 +7412,7 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
// -- for all of the non-static data members of its class that are of class
// type (or array thereof), each such class has a trivial [default
// constructor or destructor]
- if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose))
+ if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose))
return false;
// C++11 [class.dtor]p5:
@@ -7559,6 +7594,50 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
}
}
+void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
+ auto PrintDiagAndRemoveAttr = [&]() {
+ // No diagnostics if this is a template instantiation.
+ if (!isTemplateInstantiation(RD.getTemplateSpecializationKind()))
+ Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
+ diag::ext_cannot_use_trivial_abi) << &RD;
+ RD.dropAttr<TrivialABIAttr>();
+ };
+
+ // Ill-formed if the struct has virtual functions.
+ if (RD.isPolymorphic()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ for (const auto &B : RD.bases()) {
+ // Ill-formed if the base class is non-trivial for the purpose of calls or a
+ // virtual base.
+ if ((!B.getType()->isDependentType() &&
+ !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) ||
+ B.isVirtual()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+
+ for (const auto *FD : RD.fields()) {
+ // Ill-formed if the field is an ObjectiveC pointer or of a type that is
+ // non-trivial for the purpose of calls.
+ QualType FT = FD->getType();
+ if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+
+ if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
+ if (!RT->isDependentType() &&
+ !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
+ PrintDiagAndRemoveAttr();
+ return;
+ }
+ }
+}
+
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
Decl *TagDecl,
SourceLocation LBrac,
@@ -7577,12 +7656,17 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
l->getName();
}
+ // See if trivial_abi has to be dropped.
+ auto *RD = dyn_cast<CXXRecordDecl>(TagDecl);
+ if (RD && RD->hasAttr<TrivialABIAttr>())
+ checkIllFormedTrivialABIStruct(*RD);
+
ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
// strict aliasing violation!
reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
- CheckCompletedCXXClass(dyn_cast_or_null<CXXRecordDecl>(TagDecl));
+ CheckCompletedCXXClass(RD);
}
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
@@ -10732,6 +10816,8 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
// We don't need to use SpecialMemberIsTrivial here; triviality for
// destructors is easy to compute.
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+ Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() ||
+ ClassDecl->hasTrivialDestructorForCall());
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
@@ -12035,9 +12121,16 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForCopyConstructor()
- ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
- : ClassDecl->hasTrivialCopyConstructor());
+ ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
+ : ClassDecl->hasTrivialCopyConstructor());
+
+ CopyConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForCopyConstructor()
+ ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialCopyConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitCopyConstructorsDeclared;
@@ -12158,9 +12251,16 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
MoveConstructor->setParams(FromParam);
MoveConstructor->setTrivial(
- ClassDecl->needsOverloadResolutionForMoveConstructor()
- ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
- : ClassDecl->hasTrivialMoveConstructor());
+ ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
+ : ClassDecl->hasTrivialMoveConstructor());
+
+ MoveConstructor->setTrivialForCall(
+ ClassDecl->hasAttr<TrivialABIAttr>() ||
+ (ClassDecl->needsOverloadResolutionForMoveConstructor()
+ ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
+ TAH_ConsiderTrivialABI)
+ : ClassDecl->hasTrivialMoveConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitMoveConstructorsDeclared;
OpenPOWER on IntegriCloud