]> granicus.if.org Git - clang/commitdiff
Improve diagnostic to tell you a type is incomplete.
authorEric Fiselier <eric@efcs.ca>
Fri, 1 Feb 2019 22:06:02 +0000 (22:06 +0000)
committerEric Fiselier <eric@efcs.ca>
Fri, 1 Feb 2019 22:06:02 +0000 (22:06 +0000)
I recently ran into this code:
```
\#include <iostream>
void foo(const std::string &s, const std::string& = "");
\#include <string>
void test() { foo(""); }
```

The diagnostic produced said it can't bind char[1] to std::string
const&. It didn't mention std::string is incomplete. The user had to
infer that.

This patch causes the diagnostic to now say "incomplete type".

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaInit.cpp
test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
test/SemaCXX/decl-init-ref.cpp

index 4271833becaa08e99802324c519b4b7efa341ef3..cf4b71a2afb84189bb6cddb229eb8ec9f9f0f72f 100644 (file)
@@ -1828,8 +1828,9 @@ def err_reference_bind_drops_quals : Error<
   "'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|"
   "'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">;
 def err_reference_bind_failed : Error<
-  "reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of "
-  "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">;
+  "reference %diff{to %select{type|incomplete type}1 $ could not bind to an "
+  "%select{rvalue|lvalue}2 of type $|could not bind to %select{rvalue|lvalue}2 of "
+  "incompatible type}0,3">;
 def err_reference_bind_init_list : Error<
   "reference to type %0 cannot bind to an initializer list">;
 def err_init_list_bad_dest_type : Error<
index c1a7d4799741f74c032869c14f9821182002aec2..6b9270a9e4746785df3f2a2d081e8d6dc2eb0b64 100644 (file)
@@ -8450,6 +8450,7 @@ bool InitializationSequence::Diagnose(Sema &S,
   case FK_ReferenceInitFailed:
     S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
       << DestType.getNonReferenceType()
+      << DestType.getNonReferenceType()->isIncompleteType()
       << OnlyArg->isLValue()
       << OnlyArg->getType()
       << Args[0]->getSourceRange();
index f371891e54802ba3c59339ef06f01c1a68c855a6..9a82ec4a7bd902c2cdced0fe14022c1c2d68e546 100644 (file)
@@ -327,7 +327,7 @@ namespace update_rbrace_loc_crash {
   struct A {};
   template <typename T, typename F, int... I>
   std::initializer_list<T> ExplodeImpl(F p1, A<int, I...>) {
-    // expected-error@+1 {{reference to type 'const update_rbrace_loc_crash::Incomplete' could not bind to an rvalue of type 'void'}}
+    // expected-error@+1 {{reference to incomplete type 'const update_rbrace_loc_crash::Incomplete' could not bind to an rvalue of type 'void'}}
     return {p1(I)...};
   }
   template <typename T, int N, typename F>
index 42b9286852c7521fcb83b82c3236df193dc57c0d..fb5ca8c1491f29900074d698304be3a9973ddc85 100644 (file)
@@ -36,3 +36,12 @@ namespace PR16502 {
   int f();
   const A &c = { 10, ++c.temporary };
 }
+
+namespace IncompleteTest {
+  struct String;
+  // expected-error@+1 {{reference to incomplete type 'const IncompleteTest::String' could not bind to an lvalue of type 'const char [1]'}}
+  void takeString(const String& = "") {} // expected-note {{passing argument to parameter here}} expected-note {{candidate function}}
+  void test() {
+        takeString(); // expected-error {{no matching function for call}}
+  }
+}