for (unsigned i = 0; i < Initializers.size(); i++) {
CXXCtorInitializer *Member = Initializers[i];
-
+
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
else
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;
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);
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)
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wabstract-vbase-init
#ifndef __GXX_EXPERIMENTAL_CXX0X__
#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y)
foo(C(99)); // expected-error {{allocating an object of abstract class type 'pr12658::C'}}\r
}
}
+
+namespace pr16659 {
+ struct A {
+ A(int);
+ virtual void x() = 0; // expected-note {{unimplemented pure virtual method 'x' in 'RedundantInit'}}
+ };
+ struct B : virtual A {};
+ struct C : B {
+ C() : A(37) {}
+ void x() override {}
+ };
+
+ struct X {
+ friend class Z;
+ private:
+ X &operator=(const X&);
+ };
+ struct Y : virtual X { // expected-note {{::X' has an inaccessible copy assignment}}
+ virtual ~Y() = 0;
+ };
+ struct Z : Y {}; // expected-note {{::Y' has a deleted copy assignment}}
+ void f(Z &a, const Z &b) { a = b; } // expected-error {{copy assignment operator is implicitly deleted}}
+
+ struct RedundantInit : virtual A {
+ RedundantInit() : A(0) {} // expected-warning {{initializer for virtual base class 'pr16659::A' of abstract class 'RedundantInit' will never be used}}
+ };
+}