r274088 - Mark inheriting constructors as deleted if the corresponding defaulted default
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 28 18:10:28 PDT 2016
Author: rsmith
Date: Tue Jun 28 20:10:27 2016
New Revision: 274088
URL: http://llvm.org/viewvc/llvm-project?rev=274088&view=rev
Log:
Mark inheriting constructors as deleted if the corresponding defaulted default
constructor would be; this is effectively required by P0136R1. This has the
effect of exposing the validity of the base class initialization steps to
SFINAE checks.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/CXX/drs/dr15xx.cpp
cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp
cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 28 20:10:27 2016
@@ -4295,20 +4295,25 @@ def err_new_abi_tag_on_redeclaration : E
def note_deleted_dtor_no_operator_delete : Note<
"virtual destructor requires an unambiguous, accessible 'operator delete'">;
def note_deleted_special_member_class_subobject : Note<
- "%select{default constructor|copy constructor|move constructor|"
- "copy assignment operator|move assignment operator|destructor}0 of "
+ "%select{default constructor of|copy constructor of|move constructor of|"
+ "copy assignment operator of|move assignment operator of|destructor of|"
+ "constructor inherited by}0 "
"%1 is implicitly deleted because "
"%select{base class %3|%select{||||variant }4field %3}2 has "
"%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 "
"%select{%select{default constructor|copy constructor|move constructor|copy "
- "assignment operator|move assignment operator|destructor}0|destructor}5"
+ "assignment operator|move assignment operator|destructor|"
+ "%select{default|corresponding|default|default|default}4 constructor}0|"
+ "destructor}5"
"%select{||s||}4">;
def note_deleted_default_ctor_uninit_field : Note<
- "default constructor of %0 is implicitly deleted because field %1 of "
- "%select{reference|const-qualified}3 type %2 would not be initialized">;
+ "%select{default constructor of|constructor inherited by}0 "
+ "%1 is implicitly deleted because field %2 of "
+ "%select{reference|const-qualified}4 type %3 would not be initialized">;
def note_deleted_default_ctor_all_const : Note<
- "default constructor of %0 is implicitly deleted because all "
- "%select{data members|data members of an anonymous union member}1"
+ "%select{default constructor of|constructor inherited by}0 "
+ "%1 is implicitly deleted because all "
+ "%select{data members|data members of an anonymous union member}2"
" are const-qualified">;
def note_deleted_copy_ctor_rvalue_reference : Note<
"copy constructor of %0 is implicitly deleted because field %1 is of "
@@ -6567,6 +6572,8 @@ def err_nontemporal_builtin_must_be_poin
"pointer, or a vector of such types (%0 invalid)">;
def err_deleted_function_use : Error<"attempt to use a deleted function">;
+def err_deleted_inherited_ctor_use : Error<
+ "constructor inherited by %0 from base class %1 is implicitly deleted">;
def err_kern_type_not_void_return : Error<
"kernel function type %0 must have void return type">;
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 28 20:10:27 2016
@@ -3634,6 +3634,7 @@ public:
const ObjCInterfaceDecl *UnknownObjCClass=nullptr,
bool ObjCPropertyAccess=false);
void NoteDeletedFunction(FunctionDecl *FD);
+ void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD);
std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
ObjCMethodDecl *Getter,
@@ -4460,9 +4461,12 @@ public:
ArrayRef<SourceRange> DynamicExceptionRanges,
Expr *NoexceptExpr);
+ class InheritedConstructorInfo;
+
/// \brief Determine if a special member function should have a deleted
/// definition when it is defaulted.
bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ InheritedConstructorInfo *ICI = nullptr,
bool Diagnose = false);
/// \brief Declare the implicit default constructor for the given class.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jun 28 20:10:27 2016
@@ -5071,11 +5071,9 @@ static Sema::SpecialMemberOverloadResult
LHSQuals & Qualifiers::Volatile);
}
-namespace {
-struct InheritedConstructorInfo {
+class Sema::InheritedConstructorInfo {
Sema &S;
SourceLocation UseLoc;
- ConstructorUsingShadowDecl *Shadow;
/// A mapping from the base classes through which the constructor was
/// inherited to the using shadow declaration in that base class (or a null
@@ -5083,9 +5081,10 @@ struct InheritedConstructorInfo {
llvm::DenseMap<CXXRecordDecl *, ConstructorUsingShadowDecl *>
InheritedFromBases;
+public:
InheritedConstructorInfo(Sema &S, SourceLocation UseLoc,
ConstructorUsingShadowDecl *Shadow)
- : S(S), UseLoc(UseLoc), Shadow(Shadow) {
+ : S(S), UseLoc(UseLoc) {
bool DiagnosedMultipleConstructedBases = false;
CXXRecordDecl *ConstructedBase = nullptr;
UsingDecl *ConstructedBaseUsing = nullptr;
@@ -5152,7 +5151,6 @@ struct InheritedConstructorInfo {
return std::make_pair(Ctor, false);
}
};
-}
/// Is the special member function which would be selected to perform the
/// specified operation on the specified class type a constexpr constructor?
@@ -5161,7 +5159,7 @@ specialMemberIsConstexpr(Sema &S, CXXRec
Sema::CXXSpecialMember CSM, unsigned Quals,
bool ConstRHS,
CXXConstructorDecl *InheritedCtor = nullptr,
- InheritedConstructorInfo *Inherited = nullptr) {
+ Sema::InheritedConstructorInfo *Inherited = nullptr) {
// If we're inheriting a constructor, see if we need to call it for this base
// class.
if (InheritedCtor) {
@@ -5189,7 +5187,7 @@ specialMemberIsConstexpr(Sema &S, CXXRec
static bool defaultedSpecialMemberIsConstexpr(
Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM,
bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr,
- InheritedConstructorInfo *Inherited = nullptr) {
+ Sema::InheritedConstructorInfo *Inherited = nullptr) {
if (!S.getLangOpts().CPlusPlus11)
return false;
@@ -5508,7 +5506,7 @@ void Sema::CheckExplicitlyDefaultedSpeci
// [For a] user-provided explicitly-defaulted function [...] if such a
// function is implicitly defined as deleted, the program is ill-formed.
Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
- ShouldDeleteSpecialMember(MD, CSM, /*Diagnose*/true);
+ ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
HadError = true;
}
}
@@ -5569,6 +5567,7 @@ struct SpecialMemberDeletionInfo {
Sema &S;
CXXMethodDecl *MD;
Sema::CXXSpecialMember CSM;
+ Sema::InheritedConstructorInfo *ICI;
bool Diagnose;
// Properties of the special member, computed for convenience.
@@ -5578,11 +5577,11 @@ struct SpecialMemberDeletionInfo {
bool AllFieldsAreConst;
SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD,
- Sema::CXXSpecialMember CSM, bool Diagnose)
- : S(S), MD(MD), CSM(CSM), Diagnose(Diagnose),
- IsConstructor(false), IsAssignment(false), IsMove(false),
- ConstArg(false), Loc(MD->getLocation()),
- AllFieldsAreConst(true) {
+ Sema::CXXSpecialMember CSM,
+ Sema::InheritedConstructorInfo *ICI, bool Diagnose)
+ : S(S), MD(MD), CSM(CSM), ICI(ICI), Diagnose(Diagnose),
+ IsConstructor(false), IsAssignment(false), IsMove(false),
+ ConstArg(false), Loc(MD->getLocation()), AllFieldsAreConst(true) {
switch (CSM) {
case Sema::CXXDefaultConstructor:
case Sema::CXXCopyConstructor:
@@ -5614,6 +5613,10 @@ struct SpecialMemberDeletionInfo {
bool inUnion() const { return MD->getParent()->isUnion(); }
+ Sema::CXXSpecialMember getEffectiveCSM() {
+ return ICI ? Sema::CXXInvalid : CSM;
+ }
+
/// Look up the corresponding special member in the given class.
Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class,
unsigned Quals, bool IsMutable) {
@@ -5690,13 +5693,13 @@ bool SpecialMemberDeletionInfo::shouldDe
if (Field) {
S.Diag(Field->getLocation(),
diag::note_deleted_special_member_class_subobject)
- << CSM << MD->getParent() << /*IsField*/true
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/true
<< Field << DiagKind << IsDtorCallInCtor;
} else {
CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
S.Diag(Base->getLocStart(),
diag::note_deleted_special_member_class_subobject)
- << CSM << MD->getParent() << /*IsField*/false
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/false
<< Base->getType() << DiagKind << IsDtorCallInCtor;
}
@@ -5755,7 +5758,29 @@ bool SpecialMemberDeletionInfo::shouldDe
CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
// If program is correct, BaseClass cannot be null, but if it is, the error
// must be reported elsewhere.
- return BaseClass && shouldDeleteForClassSubobject(BaseClass, Base, 0);
+ if (!BaseClass)
+ return false;
+ // If we have an inheriting constructor, check whether we're calling an
+ // inherited constructor instead of a default constructor.
+ if (ICI) {
+ assert(CSM == Sema::CXXDefaultConstructor);
+ auto *BaseCtor =
+ ICI->findConstructorForBase(BaseClass, cast<CXXConstructorDecl>(MD)
+ ->getInheritedConstructor()
+ .getConstructor())
+ .first;
+ if (BaseCtor) {
+ if (BaseCtor->isDeleted() && Diagnose) {
+ S.Diag(Base->getLocStart(),
+ diag::note_deleted_special_member_class_subobject)
+ << getEffectiveCSM() << MD->getParent() << /*IsField*/false
+ << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/false;
+ S.NoteDeletedFunction(BaseCtor);
+ }
+ return BaseCtor->isDeleted();
+ }
+ }
+ return shouldDeleteForClassSubobject(BaseClass, Base, 0);
}
/// Check whether we should delete a special member function due to the class
@@ -5770,7 +5795,7 @@ bool SpecialMemberDeletionInfo::shouldDe
if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
- << MD->getParent() << FD << FieldType << /*Reference*/0;
+ << !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0;
return true;
}
// C++11 [class.ctor]p5: any non-variant non-static data member of
@@ -5782,7 +5807,7 @@ bool SpecialMemberDeletionInfo::shouldDe
(!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
- << MD->getParent() << FD << FD->getType() << /*Const*/1;
+ << !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1;
return true;
}
@@ -5841,7 +5866,7 @@ bool SpecialMemberDeletionInfo::shouldDe
if (Diagnose)
S.Diag(FieldRecord->getLocation(),
diag::note_deleted_default_ctor_all_const)
- << MD->getParent() << /*anonymous union*/1;
+ << !!ICI << MD->getParent() << /*anonymous union*/1;
return true;
}
@@ -5869,7 +5894,7 @@ bool SpecialMemberDeletionInfo::shouldDe
if (Diagnose)
S.Diag(MD->getParent()->getLocation(),
diag::note_deleted_default_ctor_all_const)
- << MD->getParent() << /*not anonymous union*/0;
+ << !!ICI << MD->getParent() << /*not anonymous union*/0;
return true;
}
return false;
@@ -5879,6 +5904,7 @@ bool SpecialMemberDeletionInfo::shouldDe
/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11,
/// C++11 [class.copy]p23, and C++11 [class.dtor]p5.
bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ InheritedConstructorInfo *ICI,
bool Diagnose) {
if (MD->isInvalidDecl())
return false;
@@ -5968,7 +5994,7 @@ bool Sema::ShouldDeleteSpecialMember(CXX
}
}
- SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose);
+ SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose);
for (auto &BI : RD->bases())
if (!BI.isVirtual() &&
@@ -9288,9 +9314,20 @@ Sema::findInheritingConstructor(SourceLo
DerivedCtor->setAccess(BaseCtor->getAccess());
DerivedCtor->setParams(ParamDecls);
Derived->addDecl(DerivedCtor);
+
+ if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI))
+ SetDeclDeleted(DerivedCtor, UsingLoc);
+
return DerivedCtor;
}
+void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) {
+ InheritedConstructorInfo ICI(*this, Ctor->getLocation(),
+ Ctor->getInheritedConstructor().getShadowDecl());
+ ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI,
+ /*Diagnose*/true);
+}
+
void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor) {
CXXRecordDecl *ClassDecl = Constructor->getParent();
@@ -11441,8 +11478,11 @@ Sema::BuildCXXConstructExpr(SourceLocati
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
- if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl))
+ if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl)) {
Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow);
+ if (DiagnoseUseOfDecl(Constructor, ConstructLoc))
+ return ExprError();
+ }
return BuildCXXConstructExpr(
ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 28 20:10:27 2016
@@ -216,11 +216,15 @@ void Sema::NoteDeletedFunction(FunctionD
// deleted. This might fail, if that reason no longer applies.
CXXSpecialMember CSM = getSpecialMember(Method);
if (CSM != CXXInvalid)
- ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true);
+ ShouldDeleteSpecialMember(Method, CSM, nullptr, /*Diagnose=*/true);
return;
}
+ auto *Ctor = dyn_cast<CXXConstructorDecl>(Decl);
+ if (Ctor && Ctor->isInheritingConstructor())
+ return NoteDeletedInheritingConstructor(Ctor);
+
Diag(Decl->getLocation(), diag::note_availability_specified_here)
<< Decl << true;
}
@@ -346,7 +350,13 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted()) {
- Diag(Loc, diag::err_deleted_function_use);
+ auto *Ctor = dyn_cast<CXXConstructorDecl>(FD);
+ if (Ctor && Ctor->isInheritingConstructor())
+ Diag(Loc, diag::err_deleted_inherited_ctor_use)
+ << Ctor->getParent()
+ << Ctor->getInheritedConstructor().getConstructor()->getParent();
+ else
+ Diag(Loc, diag::err_deleted_function_use);
NoteDeletedFunction(FD);
return true;
}
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jun 28 20:10:27 2016
@@ -5741,8 +5741,11 @@ PerformConstructorInitialization(Sema &S
: Kind.getParenRange();
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
- Step.Function.FoundDecl.getDecl()))
+ Step.Function.FoundDecl.getDecl())) {
Constructor = S.findInheritingConstructor(Loc, Constructor, Shadow);
+ if (S.DiagnoseUseOfDecl(Constructor, Loc))
+ return ExprError();
+ }
S.MarkFunctionReferenced(Loc, Constructor);
CurInit = new (S.Context) CXXTemporaryObjectExpr(
Modified: cfe/trunk/test/CXX/drs/dr15xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr15xx.cpp?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr15xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr15xx.cpp Tue Jun 28 20:10:27 2016
@@ -41,9 +41,9 @@ namespace dr1573 { // dr1573: 3.9
constexpr F f = F(0); // expected-error {{constant expression}} expected-note {{constructor inherited from base class 'C'}}
// inherited constructor is effectively deleted if the user-written constructor would be
- struct G { G(int); }; // expected-note {{declared here}}
- struct H : G { using G::G; G g; }; // expected-error {{cannot use constructor inherited from base class 'G'; member 'g' of 'dr1573::H' does not have a default constructor}} expected-note {{declared here}}
- H h(0); // expected-note {{first required here}}
+ struct G { G(int); };
+ struct H : G { using G::G; G g; }; // expected-note {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}}
+ H h(0); // expected-error {{constructor inherited by 'H' from base class 'G' is implicitly deleted}}
#endif
}
Modified: cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp (original)
+++ cfe/trunk/test/CXX/special/class.init/class.inhctor.init/p1.cpp Tue Jun 28 20:10:27 2016
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
namespace std_example {
- struct B1 { // expected-note {{declared here}}
+ struct B1 {
B1(int, ...) {}
};
@@ -25,11 +25,11 @@ namespace std_example {
}
struct D2 : B2 {
- using B2::B2; // expected-error {{cannot use constructor inherited from base class 'B2'; member 'b' of 'std_example::D2' does not have a default constructor}}
- B1 b; // expected-note {{member}}
+ using B2::B2;
+ B1 b; // expected-note {{constructor inherited by 'D2' is implicitly deleted because field 'b' has no default constructor}}
};
- D2 f(1.0); // expected-note {{inherited constructor for 'D2' first required here}}
+ D2 f(1.0); // expected-error {{constructor inherited by 'D2' from base class 'B2' is implicitly deleted}}
struct W {
W(int);
@@ -53,7 +53,7 @@ namespace std_example {
}
namespace vbase {
- struct V { // expected-note 2{{declared here}}
+ struct V {
V(int);
};
@@ -61,17 +61,17 @@ namespace vbase {
A() = delete; // expected-note 2{{deleted here}} expected-note {{deleted}}
using V::V;
};
- struct B : virtual V {
+ struct B : virtual V { // expected-note {{no default constructor}}
B() = delete; // expected-note 2{{deleted here}}
B(int, int);
using V::V;
};
struct C : B { // expected-note {{deleted default constructor}}
- using B::B; // expected-error {{cannot use constructor inherited from base class 'B'; base class 'vbase::V' of 'vbase::C' does not have a default constructor}}
+ using B::B;
};
- struct D : A, C { // expected-note {{deleted default constructor}}
+ struct D : A, C { // expected-note {{deleted default constructor}} expected-note {{deleted corresponding constructor}}
using A::A;
- using C::C; // expected-error {{cannot use constructor inherited from base class 'C'; base class 'vbase::V' of 'vbase::D' does not have a default constructor}} expected-error {{call to deleted constructor of 'vbase::A'}}
+ using C::C;
};
A a0; // expected-error {{deleted}}
@@ -81,10 +81,10 @@ namespace vbase {
B b2(0, 0);
C c0; // expected-error {{deleted}}
C c1(0);
- C c2(0, 0); // expected-note {{first required here}}
- D d0; // expected-error {{implicitly-deleted}}
+ C c2(0, 0); // expected-error {{deleted}}
+ D d0; // expected-error {{deleted}}
D d1(0);
- D d2(0, 0); // expected-note {{first required here}}
+ D d2(0, 0); // expected-error {{deleted}}
}
namespace constexpr_init_order {
Modified: cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp?rev=274088&r1=274087&r2=274088&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp Tue Jun 28 20:10:27 2016
@@ -44,3 +44,15 @@ namespace DefaultCtorConflict {
B b;
} c;
}
+
+namespace InvalidConstruction {
+ struct A { A(int); };
+ struct B { B() = delete; };
+ struct C : A, B { using A::A; };
+ // Initialization here is performed as if by a defaulted default constructor,
+ // which would be ill-formed (in the immediate context) in this case because
+ // it would be defined as deleted.
+ template<typename T> void f(decltype(T(0))*);
+ template<typename T> int &f(...);
+ int &r = f<C>(0);
+}
More information about the cfe-commits
mailing list