summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp43
1 files changed, 36 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 25dbd07b410..9b85c10d594 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -3346,7 +3346,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
for (unsigned i = 0; i < Initializers.size(); i++) {
CXXCtorInitializer *Member = Initializers[i];
-
+
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
else
@@ -3367,12 +3367,28 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
if (CXXCtorInitializer *Value
= Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
+ // [class.base.init]p7, per DR257:
+ // A mem-initializer where the mem-initializer-id names a virtual base
+ // class is ignored during execution of a constructor of any class that
+ // is not the most derived class.
+ if (ClassDecl->isAbstract()) {
+ // FIXME: Provide a fixit to remove the base specifier. This requires
+ // tracking the location of the associated comma for a base specifier.
+ Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored)
+ << VBase->getType() << ClassDecl;
+ DiagnoseAbstractType(ClassDecl);
+ }
+
Info.AllToInit.push_back(Value);
- } else if (!AnyErrors) {
+ } else if (!AnyErrors && !ClassDecl->isAbstract()) {
+ // [class.base.init]p8, per DR257:
+ // If a given [...] base class is not named by a mem-initializer-id
+ // [...] and the entity is not a virtual base class of an abstract
+ // class, then [...] the entity is default-initialized.
bool IsInheritedVirtualBase = !DirectVBases.count(VBase);
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
- VBase, IsInheritedVirtualBase,
+ VBase, IsInheritedVirtualBase,
CXXBaseInit)) {
HadError = true;
continue;
@@ -3913,6 +3929,12 @@ void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
return;
+ // If the diagnostic is suppressed, don't emit the notes. We're only
+ // going to emit them once, so try to attach them to a diagnostic we're
+ // actually going to show.
+ if (Diags.isLastDiagnosticIgnored())
+ return;
+
CXXFinalOverriderMap FinalOverriders;
RD->getFinalOverriders(FinalOverriders);
@@ -5055,10 +5077,17 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
SMI.shouldDeleteForBase(BI))
return true;
- for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
- BE = RD->vbases_end(); BI != BE; ++BI)
- if (SMI.shouldDeleteForBase(BI))
- return true;
+ // Defect report (no number yet): do not consider virtual bases of
+ // constructors of abstract classes, since we are not going to construct
+ // them. This is an extension of DR257 into the C++11 behavior for special
+ // members.
+ if (!RD->isAbstract() || !SMI.IsConstructor) {
+ for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
+ BE = RD->vbases_end();
+ BI != BE; ++BI)
+ if (SMI.shouldDeleteForBase(BI))
+ return true;
+ }
for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
FE = RD->field_end(); FI != FE; ++FI)
OpenPOWER on IntegriCloud