forked from OSchip/llvm-project
Improve diagnostic to tell you a type is incomplete.
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". llvm-svn: 352927
This commit is contained in:
parent
2e719bc428
commit
1147f71fed
|
@ -1828,8 +1828,9 @@ def err_reference_bind_drops_quals : Error<
|
||||||
"'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|"
|
"'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|"
|
||||||
"'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">;
|
"'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">;
|
||||||
def err_reference_bind_failed : Error<
|
def err_reference_bind_failed : Error<
|
||||||
"reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of "
|
"reference %diff{to %select{type|incomplete type}1 $ could not bind to an "
|
||||||
"type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">;
|
"%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<
|
def err_reference_bind_init_list : Error<
|
||||||
"reference to type %0 cannot bind to an initializer list">;
|
"reference to type %0 cannot bind to an initializer list">;
|
||||||
def err_init_list_bad_dest_type : Error<
|
def err_init_list_bad_dest_type : Error<
|
||||||
|
|
|
@ -8450,6 +8450,7 @@ bool InitializationSequence::Diagnose(Sema &S,
|
||||||
case FK_ReferenceInitFailed:
|
case FK_ReferenceInitFailed:
|
||||||
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
|
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
|
||||||
<< DestType.getNonReferenceType()
|
<< DestType.getNonReferenceType()
|
||||||
|
<< DestType.getNonReferenceType()->isIncompleteType()
|
||||||
<< OnlyArg->isLValue()
|
<< OnlyArg->isLValue()
|
||||||
<< OnlyArg->getType()
|
<< OnlyArg->getType()
|
||||||
<< Args[0]->getSourceRange();
|
<< Args[0]->getSourceRange();
|
||||||
|
|
|
@ -327,7 +327,7 @@ namespace update_rbrace_loc_crash {
|
||||||
struct A {};
|
struct A {};
|
||||||
template <typename T, typename F, int... I>
|
template <typename T, typename F, int... I>
|
||||||
std::initializer_list<T> ExplodeImpl(F p1, A<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)...};
|
return {p1(I)...};
|
||||||
}
|
}
|
||||||
template <typename T, int N, typename F>
|
template <typename T, int N, typename F>
|
||||||
|
|
|
@ -36,3 +36,12 @@ namespace PR16502 {
|
||||||
int f();
|
int f();
|
||||||
const A &c = { 10, ++c.temporary };
|
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}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue