]> granicus.if.org Git - clang/commitdiff
Clean up diagnostics for inheriting constructors.
authorEli Friedman <eli.friedman@gmail.com>
Thu, 18 Jul 2013 23:29:14 +0000 (23:29 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Thu, 18 Jul 2013 23:29:14 +0000 (23:29 +0000)
No new diagnostics, just better wording and notes pointing at more
relevant locations.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186629 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
test/CXX/special/class.inhctor/p1.cpp
test/CXX/special/class.inhctor/p4.cpp

index 003930c7bd7af29b57e3e222e3f421d6b0061847..bdcccac34c349e657968a5dbd89c3e119ebd65e9 100644 (file)
@@ -3398,6 +3398,10 @@ def note_unavailable_here : Note<
   "%select{unavailable|deleted|deprecated}1 here">;
 def note_implicitly_deleted : Note<
   "explicitly defaulted function was implicitly deleted here">;
+def note_inherited_deleted_here : Note<
+  "deleted constructor was inherited here">;
+def note_cannot_inherit : Note<
+  "constructor cannot be inherited">;
 def warn_not_enough_argument : Warning<
   "not enough variable arguments in %0 declaration to fit a sentinel">,
   InGroup<Sentinel>;
index d0a80bd346f876cda405c3ad1df1ae9c2bd3cc2c..e331afd4d0ea7a902992a9858221c9d9a234106e 100644 (file)
@@ -9991,9 +9991,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
 }
 
 bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
-  return FD->isDeleted() && 
-         (FD->isDefaulted() || FD->isImplicit()) &&
-         isa<CXXMethodDecl>(FD);
+  return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD);
 }
 
 /// \brief Mark the call operator of the given lambda closure type as "used".
index 0106232bbbc426fbe2b55c366c1fa290c2ad923a..f397c5bb2ef7e337425e69e39dca1f782ab4fc38 100644 (file)
@@ -140,11 +140,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
     return Result;
 }
 
-/// \brief Emit a note explaining that this function is deleted or unavailable.
+/// \brief Emit a note explaining that this function is deleted.
 void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
+  assert(Decl->isDeleted());
+
   CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
 
-  if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) {
+  if (Method && Method->isDeleted() && Method->isDefaulted()) {
     // If the method was explicitly defaulted, point at that declaration.
     if (!Method->isImplicit())
       Diag(Decl->getLocation(), diag::note_implicitly_deleted);
@@ -158,8 +160,23 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
     return;
   }
 
+  if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(Decl)) {
+    if (CXXConstructorDecl *BaseCD =
+            const_cast<CXXConstructorDecl*>(CD->getInheritedConstructor())) {
+      Diag(Decl->getLocation(), diag::note_inherited_deleted_here);
+      if (BaseCD->isDeleted()) {
+        NoteDeletedFunction(BaseCD);
+      } else {
+        // FIXME: An explanation of why exactly it can't be inherited
+        // would be nice.
+        Diag(BaseCD->getLocation(), diag::note_cannot_inherit);
+      }
+      return;
+    }
+  }
+
   Diag(Decl->getLocation(), diag::note_unavailable_here)
-    << 1 << Decl->isDeleted();
+    << 1 << true;
 }
 
 /// \brief Determine whether a FunctionDecl was ever declared with an
index 8721dec1b40597e3a683f874523edf2da046fade..fa0416e11765c8f9eab0f5427577f1cef93e238c 100644 (file)
@@ -2,31 +2,30 @@
 // Per a core issue (no number yet), an ellipsis is always dropped.
 struct A {
   A(...); // expected-note {{here}}
-  A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 9{{here}}
+  A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 9{{here}} expected-note 2{{constructor cannot be inherited}}
   A(int = 0, int = 0, ...); // expected-note {{here}}
 
   template<typename T> A(T, int = 0, ...); // expected-note 5{{here}}
 
-  template<typename T, int N> A(const T (&)[N]); // expected-note 2{{here}}
+  template<typename T, int N> A(const T (&)[N]); // expected-note 2{{here}} expected-note {{constructor cannot be inherited}}
   template<typename T, int N> A(const T (&)[N], int = 0); // expected-note 2{{here}}
 };
 
 struct B : A { // expected-note 6{{candidate}}
-  using A::A; // expected-warning 4{{inheriting constructor does not inherit ellipsis}} expected-note 16{{candidate}} expected-note 3{{deleted}}
+  using A::A; // expected-warning 4{{inheriting constructor does not inherit ellipsis}} expected-note 16{{candidate}} expected-note 3{{deleted constructor was inherited here}}
 };
 
 struct C {} c;
 
 B b0{};
-// expected-error@-1 {{call to implicitly-deleted default constructor}}
+// expected-error@-1 {{call to implicitly-deleted default constructor of 'B'}}
 // expected-note@-8 {{default constructor of 'B' is implicitly deleted because base class 'A' has multiple default constructors}}
 
 B b1{1};
-// FIXME: explain why the inheriting constructor was deleted
-// expected-error@-2 {{call to implicitly-deleted function of 'B'}}
+// expected-error@-1 {{call to deleted constructor of 'B'}}
 
 B b2{1,2};
-// expected-error@-1 {{call to implicitly-deleted function of 'B'}}
+// expected-error@-1 {{call to deleted constructor of 'B'}}
 
 B b3{1,2,3};
 // ok
index 512705e4dd943413873e979cfa7d22368a09ff42..356cdef687fb82afeccd2f83756d1e09ee50e648 100644 (file)
@@ -43,13 +43,13 @@ FA fa2{X<2>{}}; // expected-error {{calling a private constructor}}
 
 // It is deleted if the corresponding constructor [...] is deleted.
 struct G {
-  G(int) = delete;
-  template<typename T> G(T*) = delete;
+  G(int) = delete; // expected-note {{function has been explicitly marked deleted here}}
+  template<typename T> G(T*) = delete; // expected-note {{function has been explicitly marked deleted here}}
 };
 struct H : G {
-  using G::G; // expected-note 2{{marked deleted here}}
+  using G::G; // expected-note 2{{deleted constructor was inherited here}}
 };
-H h1(5); // expected-error {{call to implicitly-deleted function of 'H'}}
+H h1(5); // expected-error {{call to deleted constructor of 'H'}}
 H h2("foo"); // expected-error {{call to deleted constructor of 'H'}}
 
 
@@ -58,15 +58,14 @@ H h2("foo"); // expected-error {{call to deleted constructor of 'H'}}
 namespace DRnnnn {
   struct A {
     constexpr A(int, float = 0) {}
-    explicit A(int, int = 0) {}
+    explicit A(int, int = 0) {} // expected-note {{constructor cannot be inherited}}
 
     A(int, int, int = 0) = delete;
   };
   struct B : A {
-    // FIXME: produce notes indicating why it was deleted
     using A::A; // expected-note {{here}}
   };
 
   constexpr B b0(0, 0.0f); // ok, constexpr
-  B b1(0, 1); // expected-error {{call to implicitly-deleted}}
+  B b1(0, 1); // expected-error {{call to deleted constructor of 'DRnnnn::B'}}
 }