diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-09 00:35:39 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-09 00:35:39 +0000 |
commit | d4eea8362605807327735727a9098abe1eb23b19 (patch) | |
tree | ffa33b82edfd313505b5bf83dac9fd6b6e844fa9 | |
parent | 355fa3a65d2bffb2cb230e5c3d8cd14ec5570329 (diff) |
Improve diagnostics when we fail to convert from a source type to a
destination type for initialization, assignment, parameter-passing,
etc. The main issue fixed here is that we used rather confusing
wording for diagnostics such as
t.c:2:9: warning: initializing 'char const [2]' discards qualifiers,
expected 'char *' [-pedantic]
char *name = __func__;
^ ~~~~~~~~
We're not initializing a 'char const [2]', we're initializing a 'char
*' with an expression of type 'char const [2]'. Similar problems
existed for other diagnostics in this area, so I've normalized them all
with more precise descriptive text to say what we're
initializing/converting/assigning/etc. from and to. The warning for
the code above is now:
t.c:2:9: warning: initializing 'char *' from an expression of type
'char const [2]' discards qualifiers [-pedantic]
char *name = __func__;
^ ~~~~~~~~
Fixes <rdar://problem/7447179>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100832 91177308-0d34-0410-b5e6-96231b3b80d8
70 files changed, 254 insertions, 198 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e2d8d6fa77..27632f171f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2229,44 +2229,81 @@ def warn_value_always_zero : Warning< // In most of these diagnostics the %2 is a value from the // Sema::AssignmentAction enumeration def err_typecheck_convert_incompatible : Error< - "incompatible type %select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from incompatible type|to parameter of incompatible type|" + "from a function with incompatible result type|to incompatible type|" + "from an expression of incompatible type|to parameter of incompatible type|" + "to incompatible type}2 %1">; def warn_incompatible_qualified_id : Warning< - "incompatible type %select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from incompatible type|to parameter of incompatible type|" + "from a function with incompatible result type|to incompatible type|" + "from an expression of incompatible type|to parameter of incompatible type|" + "to incompatible type}2 %1">; def ext_typecheck_convert_pointer_int : ExtWarn< "incompatible pointer to integer conversion " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1">; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1">; def ext_typecheck_convert_pointer_void_func : Extension< - "%select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1 converts between void* and function pointer, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1 " + "converts between void pointer and function pointer">; def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn< - "pointer types point to integer types with different sign " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">, + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1 " + "converts between pointers to integer types with different sign">, InGroup<DiagGroup<"pointer-sign">>; def ext_typecheck_convert_incompatible_pointer : ExtWarn< "incompatible pointer types " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1">; def ext_typecheck_convert_discards_qualifiers : ExtWarn< - "%select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1 discards qualifiers, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1 discards " + "qualifiers">; def ext_nested_pointer_qualifier_mismatch : ExtWarn< - "%select{assigning|passing|returning|converting|initializing|sending|casting}2," - " %0 and %1 have different qualifiers in nested pointer types">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1 discards " + "qualifiers in nested pointer types">; def warn_incompatible_vectors : Warning< - "incompatible vector types %select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1, expected %0">, + "incompatible vector types " + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1">, InGroup<VectorConversions>, DefaultIgnore; def err_int_to_block_pointer : Error< - "invalid conversion " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2" - " integer %1, expected block pointer %0">; + "invalid block pointer conversion " + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1">; def err_typecheck_convert_incompatible_block_pointer : Error< "incompatible block pointer types " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "from an expression of type|to parameter of type|to type}2 %1">; def err_typecheck_convert_ambiguous : Error< "ambiguity in initializing value of type %0 with initializer of type %1">; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index da0c0a0499..654b220499 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7201,7 +7201,27 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, break; } - Diag(Loc, DiagKind) << DstType << SrcType << Action + QualType FirstType, SecondType; + switch (Action) { + case AA_Assigning: + case AA_Initializing: + // The destination type comes first. + FirstType = DstType; + SecondType = SrcType; + break; + + case AA_Returning: + case AA_Passing: + case AA_Converting: + case AA_Sending: + case AA_Casting: + // The source type comes first. + FirstType = SrcType; + SecondType = DstType; + break; + } + + Diag(Loc, DiagKind) << FirstType << SecondType << Action << SrcExpr->getSourceRange() << Hint; return isInvalid; } diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index 5376ca0eb3..5a1049c7d7 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -62,8 +62,8 @@ int f4(int *p) { int f4_b() { short array[2]; - uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion initializing}} - short *p = x; // expected-warning{{incompatible integer to pointer conversion initializing}} + uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion}} + short *p = x; // expected-warning{{incompatible integer to pointer conversion}} // The following branch should be infeasible. if (!(p = &array[0])) { diff --git a/test/Analysis/override-werror.c b/test/Analysis/override-werror.c index 522b9dcb94..f4854bb819 100644 --- a/test/Analysis/override-werror.c +++ b/test/Analysis/override-werror.c @@ -6,7 +6,7 @@ // analyzer results. char* f(int *p) { - return p; // expected-warning{{incompatible pointer types returning 'int *', expected 'char *'}} + return p; // expected-warning{{incompatible pointer types}} } void g(int *p) { diff --git a/test/CXX/except/except.handle/p16.cpp b/test/CXX/except/except.handle/p16.cpp index 87972f5985..4950a2f6aa 100644 --- a/test/CXX/except/except.handle/p16.cpp +++ b/test/CXX/except/except.handle/p16.cpp @@ -11,12 +11,12 @@ class X { public: X(const X<T> &) { int *ip = 0; - ptr = ip; // expected-error{{incompatible type assigning 'int *', expected 'float *'}} + ptr = ip; // expected-error{{assigning to 'float *' from incompatible type 'int *'}} } ~X() { float *fp = 0; - ptr = fp; // expected-error{{incompatible type assigning 'float *', expected 'int *'}} + ptr = fp; // expected-error{{assigning to 'int *' from incompatible type 'float *'}} } }; diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m index 665ac74441..072d50a69b 100644 --- a/test/FixIt/fixit-objc.m +++ b/test/FixIt/fixit-objc.m @@ -27,7 +27,7 @@ void h(id a); void f(Test *t) { NSString *a = "Foo"; id b = "Foo"; - A* c = "Foo"; // expected-warning {{incompatible pointer types initializing 'char [4]', expected 'A *'}} + A* c = "Foo"; // expected-warning {{incompatible pointer types initializing 'A *' from an expression of type 'char [4]'}} g("Foo"); h("Foo"); h(("Foo")); diff --git a/test/PCH/functions.c b/test/PCH/functions.c index eb8579ab2e..5d7849e129 100644 --- a/test/PCH/functions.c +++ b/test/PCH/functions.c @@ -15,7 +15,7 @@ float *test_f1(int val, double x, double y) { } void test_g0(int *x, float * y) { - g0(y); // expected-warning{{incompatible pointer types passing 'float *', expected 'int *'}} + g0(y); // expected-warning{{incompatible pointer types passing 'float *' to parameter of type 'int *'}} g0(x); } diff --git a/test/PCH/types.c b/test/PCH/types.c index 1ebc01be6a..5ca6a6893f 100644 --- a/test/PCH/types.c +++ b/test/PCH/types.c @@ -66,7 +66,7 @@ int_ptr_ptr ipp = &int_value_ptr; // TYPE_TYPEOF_EXPR typeof_17 *t17 = &int_value; struct S { int x, y; }; -typeof_17 t17_2 = (struct S){1, 2}; // expected-error{{incompatible type initializing}} +typeof_17 t17_2 = (struct S){1, 2}; // expected-error{{initializing 'typeof_17' (aka 'int') from an expression of incompatible type 'struct S'}} // TYPE_TYPEOF int_ptr_ptr2 ipp2 = &int_value_ptr; diff --git a/test/Parser/altivec.c b/test/Parser/altivec.c index c2a32cfa39..6c4601abe9 100644 --- a/test/Parser/altivec.c +++ b/test/Parser/altivec.c @@ -81,8 +81,8 @@ void f() { gccvector unsigned int gv = v; gccvector int gvi = (gccvector int)v; __attribute__((vector_size(8))) unsigned int gv8; - gv8 = gccv; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int', expected '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int'}} - av = gv8; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int', expected '__vector unsigned int'}} + gv8 = gccv; // expected-error {{assigning to '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' from incompatible type '__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int'}} + av = gv8; // expected-error {{assigning to '__vector unsigned int' from incompatible type '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int'}} v = gccv; __vector unsigned int tv = gccv; diff --git a/test/Parser/builtin_types_compatible.c b/test/Parser/builtin_types_compatible.c index 325615c7ee..ac81e7b08d 100644 --- a/test/Parser/builtin_types_compatible.c +++ b/test/Parser/builtin_types_compatible.c @@ -35,7 +35,7 @@ static void test() struct xx { int a; } x, y; c = __builtin_choose_expr(a+3-7, b, x); // expected-error{{'__builtin_choose_expr' requires a constant expression}} - c = __builtin_choose_expr(0, b, x); // expected-error{{incompatible type assigning 'struct xx', expected 'int'}} + c = __builtin_choose_expr(0, b, x); // expected-error{{assigning to 'int' from incompatible type 'struct xx'}} c = __builtin_choose_expr(5+3-7, b, x); y = __builtin_choose_expr(4+3-7, b, x); diff --git a/test/Parser/cxx-altivec.cpp b/test/Parser/cxx-altivec.cpp index 3610c0e049..13a270b8e6 100644 --- a/test/Parser/cxx-altivec.cpp +++ b/test/Parser/cxx-altivec.cpp @@ -81,8 +81,8 @@ void f() { gccvector unsigned int gv = v; gccvector int gvi = (gccvector int)v; __attribute__((vector_size(8))) unsigned int gv8; - gv8 = gccv; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int', expected '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int'}} - av = gv8; // expected-error {{incompatible type assigning '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int', expected '__vector unsigned int'}} + gv8 = gccv; // expected-error {{assigning to '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' from incompatible type '__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int'}} + av = gv8; // expected-error {{assigning to '__vector unsigned int' from incompatible type '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int'}} v = gccv; __vector unsigned int tv = gccv; diff --git a/test/Parser/declarators.c b/test/Parser/declarators.c index 91803c1c5d..31712af26c 100644 --- a/test/Parser/declarators.c +++ b/test/Parser/declarators.c @@ -53,7 +53,7 @@ myenum c; // expected-error {{must use 'enum' tag to refer to type 'myenum' float *test7() { // We should recover 'b' by parsing it with a valid type of "struct xyz", which // allows us to diagnose other bad things done with y, such as this. - return &b.y; // expected-warning {{incompatible pointer types returning 'int *', expected 'float *'}} + return &b.y; // expected-warning {{incompatible pointer types returning 'int *' from a function with result type 'float *'}} } struct xyz test8() { return a; } // a should be be marked invalid, no diag. diff --git a/test/Parser/implicit-casts.c b/test/Parser/implicit-casts.c index 900b4ece8b..a2b31f929f 100644 --- a/test/Parser/implicit-casts.c +++ b/test/Parser/implicit-casts.c @@ -14,7 +14,7 @@ void test2() { } int test3() { int a[2]; - a[0] = test3; // expected-warning{{incompatible pointer to integer conversion assigning 'int ()', expected 'int'}} + a[0] = test3; // expected-warning{{incompatible pointer to integer conversion assigning to 'int' from 'int ()'}} return 0; } short x; void test4(char c) { x += c; } diff --git a/test/Sema/address_spaces.c b/test/Sema/address_spaces.c index badd2383ab..6258114578 100644 --- a/test/Sema/address_spaces.c +++ b/test/Sema/address_spaces.c @@ -37,6 +37,6 @@ struct _st { __attribute__((address_space(256))) void * * const base = 0; void * get_0(void) { return base[0]; // expected-error {{illegal implicit cast between two pointers with different address spaces}} \ - expected-warning {{returning 'void __attribute__((address_space(256))) *' discards qualifiers, expected 'void *'}} + expected-warning {{returning 'void __attribute__((address_space(256))) *' from a function with result type 'void *' discards qualifiers}} } diff --git a/test/Sema/anonymous-struct-union.c b/test/Sema/anonymous-struct-union.c index 118854fd47..b91426ca6c 100644 --- a/test/Sema/anonymous-struct-union.c +++ b/test/Sema/anonymous-struct-union.c @@ -101,4 +101,4 @@ struct s2 { typedef struct { int x; } a_struct; -int tmp = (a_struct) { .x = 0 }; // expected-error {{incompatible type initializing 'a_struct', expected 'int'}} +int tmp = (a_struct) { .x = 0 }; // expected-error {{initializing 'int' from an expression of incompatible type 'a_struct'}} diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c index 66f15c3a3c..8b577fa5d7 100644 --- a/test/Sema/array-constraint.c +++ b/test/Sema/array-constraint.c @@ -46,7 +46,7 @@ typedef int TA[I]; // expected-error {{variable length array declaration not all void strFunc(char *); const char staticAry[] = "test"; void checkStaticAry() { - strFunc(staticAry); // expected-warning{{passing 'char const [5]' discards qualifiers, expected 'char *'}} + strFunc(staticAry); // expected-warning |