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