Skip to content

Commit 4f4946a

Browse files
committed
Whenever we complain about a failed initialization of a function or
method parameter, provide a note pointing at the parameter itself so the user does not have to manually look for the function/method being called and match up parameters to arguments. For example, we now get: t.c:4:5: warning: incompatible pointer types passing 'long *' to parameter of type 'int *' [-pedantic] f(long_ptr); ^~~~~~~~ t.c:1:13: note: passing argument to parameter 'x' here void f(int *x); ^ llvm-svn: 102038
1 parent 3eeb741 commit 4f4946a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+109
-53
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2077,7 +2077,10 @@ def warn_setter_getter_impl_required_in_category : Warning<
20772077
"use @dynamic or provide a method implementation in category">;
20782078
def note_property_impl_required : Note<
20792079
"implementation is here">;
2080-
2080+
def note_parameter_named_here : Note<
2081+
"passing argument to parameter %0 here">;
2082+
def note_parameter_here : Note<
2083+
"passing argument to parameter here">;
20812084

20822085
// C++ casts
20832086
// These messages adhere to the TryCast pattern: %0 is an int specifying the

clang/lib/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4076,7 +4076,8 @@ class Sema : public Action {
40764076
bool DiagnoseAssignmentResult(AssignConvertType ConvTy,
40774077
SourceLocation Loc,
40784078
QualType DstType, QualType SrcType,
4079-
Expr *SrcExpr, AssignmentAction Action);
4079+
Expr *SrcExpr, AssignmentAction Action,
4080+
bool *Complained = 0);
40804081

40814082
/// CheckAssignmentConstraints - Perform type checking for assignment,
40824083
/// argument passing, variable initialization, and function return values.

clang/lib/Sema/SemaExpr.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7036,7 +7036,11 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType,
70367036
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
70377037
SourceLocation Loc,
70387038
QualType DstType, QualType SrcType,
7039-
Expr *SrcExpr, AssignmentAction Action) {
7039+
Expr *SrcExpr, AssignmentAction Action,
7040+
bool *Complained) {
7041+
if (Complained)
7042+
*Complained = false;
7043+
70407044
// Decode the result (notice that AST's are still created for extensions).
70417045
bool isInvalid = false;
70427046
unsigned DiagKind;
@@ -7121,6 +7125,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
71217125

71227126
Diag(Loc, DiagKind) << FirstType << SecondType << Action
71237127
<< SrcExpr->getSourceRange() << Hint;
7128+
if (Complained)
7129+
*Complained = true;
71247130
return isInvalid;
71257131
}
71267132

clang/lib/Sema/SemaInit.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3308,6 +3308,20 @@ static Sema::OwningExprResult CopyObject(Sema &S,
33083308
move_arg(ConstructorArgs));
33093309
}
33103310

3311+
void InitializationSequence::PrintInitLocationNote(Sema &S,
3312+
const InitializedEntity &Entity) {
3313+
if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) {
3314+
if (Entity.getDecl()->getLocation().isInvalid())
3315+
return;
3316+
3317+
if (Entity.getDecl()->getDeclName())
3318+
S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here)
3319+
<< Entity.getDecl()->getDeclName();
3320+
else
3321+
S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here);
3322+
}
3323+
}
3324+
33113325
Action::OwningExprResult
33123326
InitializationSequence::Perform(Sema &S,
33133327
const InitializedEntity &Entity,
@@ -3474,6 +3488,7 @@ InitializationSequence::Perform(Sema &S,
34743488
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
34753489
<< Entity.getType().isVolatileQualified()
34763490
<< CurInitExpr->getSourceRange();
3491+
PrintInitLocationNote(S, Entity);
34773492
return S.ExprError();
34783493
}
34793494

@@ -3695,10 +3710,16 @@ InitializationSequence::Perform(Sema &S,
36953710
== Sema::Compatible)
36963711
ConvTy = Sema::Compatible;
36973712

3713+
bool Complained;
36983714
if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
36993715
Step->Type, SourceType,
3700-
CurInitExpr, getAssignmentAction(Entity)))
3716+
CurInitExpr,
3717+
getAssignmentAction(Entity),
3718+
&Complained)) {
3719+
PrintInitLocationNote(S, Entity);
37013720
return S.ExprError();
3721+
} else if (Complained)
3722+
PrintInitLocationNote(S, Entity);
37023723

37033724
CurInit.release();
37043725
CurInit = S.Owned(CurInitExpr);
@@ -3972,6 +3993,7 @@ bool InitializationSequence::Diagnose(Sema &S,
39723993
break;
39733994
}
39743995

3996+
PrintInitLocationNote(S, Entity);
39753997
return true;
39763998
}
39773999

clang/lib/Sema/SemaInit.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,11 @@ class InitializationSequence {
542542

543543
/// \brief The candidate set created when initialization failed.
544544
OverloadCandidateSet FailedCandidateSet;
545-
545+
546+
/// \brief Prints a follow-up note that highlights the location of
547+
/// the initialized entity, if it's remote.
548+
void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity);
549+
546550
public:
547551
/// \brief Try to perform initialization of the given entity, creating a
548552
/// record of the steps required to perform the initialization.

clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace Numbers {
3636
double d;
3737
};
3838
Number zero(0.0f);
39-
void g(Number);
39+
void g(Number); // expected-note 2{{passing argument to parameter here}}
4040
}
4141

4242
void test2() {

clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ namespace Test0 {
1212
test<1> foo(class foo);
1313

1414
namespace A {
15-
test<2> foo(class ::foo); // expected-note {{candidate}}
15+
test<2> foo(class ::foo); // expected-note {{candidate}} \
16+
// expected-note{{passing argument to parameter here}}
1617

1718
void test0() {
1819
using ::foo;

clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
float global_f;
44

5-
void f0(int *ip = &global_f); // expected-error{{cannot initialize}}
5+
void f0(int *ip = &global_f); // expected-error{{cannot initialize}} \
6+
// expected-note{{passing argument to parameter 'ip' here}}
67

78
// Example from C++03 standard
89
int a = 1;

clang/test/PCH/functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s
77

88
int f0(int x0, int y0, ...) { return x0 + y0; }
9-
9+
// expected-note{{passing argument to parameter here}}
1010
float *test_f1(int val, double x, double y) {
1111
if (val > 5)
1212
return f1(x, y);

clang/test/PCH/functions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/* For use with the functions.c test */
22

3-
int f0(int x, int y, ...);
3+
4+
5+
6+
int f0(int x, int y, ...);
47
float *f1(float x, float y);
58

69
void g0(int *);

clang/test/Sema/array-constraint.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void check_size() {
4343
static int I;
4444
typedef int TA[I]; // expected-error {{variable length array declaration not allowed at file scope}}
4545

46-
void strFunc(char *);
46+
void strFunc(char *); // expected-note{{passing argument to parameter here}}
4747
const char staticAry[] = "test";
4848
void checkStaticAry() {
4949
strFunc(staticAry); // expected-warning{{passing 'char const [5]' to parameter of type 'char *' discards qualifiers}}

clang/test/Sema/attr-format.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void e2(char *str, int c, ...) __attribute__((format(printf0, 2,3))); // expecte
4545
// FreeBSD usage
4646
#define __printf0like(fmt,va) __attribute__((__format__(__printf0__,fmt,va)))
4747
void null(int i, const char *a, ...) __printf0like(2,0); // no-error
48-
void null(int i, const char *a, ...) {
48+
void null(int i, const char *a, ...) { // expected-note{{passing argument to parameter 'a' here}}
4949
if (a)
5050
(void)0/* vprintf(...) would go here */;
5151
}

clang/test/Sema/block-misc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ void test14() {
139139

140140
enum { LESS };
141141

142-
void foo(long (^comp)()) {
142+
void foo(long (^comp)()) { // expected-note{{passing argument to parameter 'comp' here}}
143143
}
144144

145145
void (^test15f)(void);

clang/test/Sema/format-strings.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
typedef __typeof(sizeof(int)) size_t;
55
typedef struct _FILE FILE;
66
int fprintf(FILE *, const char *restrict, ...);
7-
int printf(const char *restrict, ...);
7+
int printf(const char *restrict, ...); // expected-note{{passing argument to parameter here}}
88
int snprintf(char *restrict, size_t, const char *restrict, ...);
99
int sprintf(char *restrict, const char *restrict, ...);
1010
int vasprintf(char **, const char *, va_list);
1111
int asprintf(char **, const char *, ...);
1212
int vfprintf(FILE *, const char *restrict, va_list);
1313
int vprintf(const char *restrict, va_list);
1414
int vsnprintf(char *, size_t, const char *, va_list);
15-
int vsprintf(char *restrict, const char *restrict, va_list);
15+
int vsprintf(char *restrict, const char *restrict, va_list); // expected-note{{passing argument to parameter here}}
1616

1717
char * global_fmt;
1818

clang/test/Sema/incompatible-sign.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %clang_cc1 %s -verify -fsyntax-only
22

3-
int a(int* x);
3+
int a(int* x); // expected-note{{passing argument to parameter 'x' here}}
44
int b(unsigned* y) { return a(y); } // expected-warning {{passing 'unsigned int *' to parameter of type 'int *' converts between pointers to integer types with different sign}}
55

clang/test/Sema/predefined-function.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ char *funk(int format);
44
enum Test {A=-1};
55
char *funk(enum Test x);
66

7-
int eli(float b); // expected-note {{previous declaration is here}}
7+
int eli(float b); // expected-note {{previous declaration is here}} \
8+
// expected-note{{passing argument to parameter 'b' here}}
89
int b(int c) {return 1;}
910

1011
int foo();

clang/test/Sema/transparent-union.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ typedef union {
44
float *fp;
55
} TU __attribute__((transparent_union));
66

7-
void f(TU);
7+
void f(TU); // expected-note{{passing argument to parameter here}}
88

99
void g(int *ip, float *fp, char *cp) {
1010
f(ip);

clang/test/Sema/vector-assign.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ float test2(__attribute__((vector_size(16))) float a, int b) {
4747
typedef long long __attribute__((__vector_size__(2 * sizeof(long long))))
4848
longlongvec;
4949

50-
void test3a(longlongvec *);
50+
void test3a(longlongvec *); // expected-note{{passing argument to parameter here}}
5151
void test3(const unsigned *src) {
5252
test3a(src); // expected-warning {{incompatible pointer types passing 'unsigned int const *' to parameter of type 'longlongvec *'}}
5353
}

clang/test/Sema/vector-cast.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type 't1' and integer type 'short' of different size}}
3030
}
3131

3232

33-
void f2(t2 X);
33+
void f2(t2 X); // expected-note{{passing argument to parameter 'X' here}}
3434

3535
void f3(t3 Y) {
3636
f2(Y); // expected-warning {{incompatible vector types passing 't3' to parameter of type 't2'}}

clang/test/SemaCXX/default1.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ void h(int i, int j = 2, int k = 3,
1414
int n);// expected-error {{missing default argument on parameter 'n'}}
1515

1616
struct S { } s;
17-
void i(int = s) { } // expected-error {{no viable conversion}}
17+
void i(int = s) { } // expected-error {{no viable conversion}} \
18+
// expected-note{{passing argument to parameter here}}
1819

1920
struct X {
2021
X(int);
@@ -26,6 +27,8 @@ struct Y { // expected-note 2{{candidate}}
2627
explicit Y(int);
2728
};
2829

29-
void k(Y y = 17); // expected-error{{no viable conversion}}
30+
void k(Y y = 17); // expected-error{{no viable conversion}} \
31+
// expected-note{{passing argument to parameter 'y' here}}
3032

31-
void kk(Y = 17); // expected-error{{no viable conversion}}
33+
void kk(Y = 17); // expected-error{{no viable conversion}} \
34+
// expected-note{{passing argument to parameter here}}

clang/test/SemaCXX/default2.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ void test_Z(const Z& z) {
102102
struct ZZ {
103103
static ZZ g(int = 17);
104104

105-
void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}}
105+
void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}} \
106+
// expected-note{{passing argument to parameter 'z' here}}
106107

107108
ZZ(ZZ&, int = 17); // expected-note{{candidate constructor}}
108109
};

clang/test/SemaCXX/elaborated-type-specifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace NS {
2222
void test_elab2(struct S4 *s4);
2323
};
2424

25-
void X::test_elab2(S4 *s4) { }
25+
void X::test_elab2(S4 *s4) { } // expected-note{{passing argument to parameter 's4' here}}
2626
}
2727

2828
void test_X_elab(NS::X x) {
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify %s
22
// PR4103: Make sure we have a location for the error
3-
class A { float a(int *); int b(); };
3+
class A {
4+
float a(int *); // expected-note{{passing argument to parameter here}}
5+
int b();
6+
};
47
int A::b() { return a(a((int*)0)); } // expected-error {{cannot initialize a parameter of type 'int *' with an rvalue of type 'float'}}
58

clang/test/SemaCXX/overload-call.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ namespace PR6078 {
425425
namespace PR6177 {
426426
struct String { String(char const*); };
427427

428-
void f(bool const volatile&);
428+
void f(bool const volatile&); // expected-note{{passing argument to parameter here}}
429429
void f(String);
430430

431431
void g() { f(""); } // expected-error{{volatile lvalue reference to type 'bool const volatile' cannot bind to a value of unrelated type 'char const [1]'}}

clang/test/SemaCXX/ref-init-ambiguous.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ void test(C c) {
1717
const E2 &e2 = c; // expected-error {{reference initialization of type 'E2 const &' with initializer of type 'C' is ambiguous}}
1818
}
1919

20-
void foo(const E2 &);
20+
void foo(const E2 &);// expected-note{{passing argument to parameter here}}
2121

2222
const E2 & re(C c) {
2323
foo(c); // expected-error {{reference initialization of type 'E2 const &' with initializer of type 'C' is ambiguous}}

clang/test/SemaObjC/argument-checking.m

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
struct S { int a; };
44

5-
extern int charStarFunc(char *);
6-
extern int charFunc(char);
5+
extern int charStarFunc(char *); // expected-note{{passing argument to parameter here}}
6+
extern int charFunc(char); // expected-note{{passing argument to parameter here}}
77

88
@interface Test
99
+alloc;
10-
-(int)charStarMeth:(char *)s;
11-
-structMeth:(struct S)s;
12-
-structMeth:(struct S)s :(struct S)s2;
10+
-(int)charStarMeth:(char *)s; // expected-note{{passing argument to parameter 's' here}}
11+
-structMeth:(struct S)s; // expected-note{{passing argument to parameter 's' here}}
12+
-structMeth:(struct S)s
13+
:(struct S)s2; // expected-note{{passing argument to parameter 's2' here}}
1314
@end
1415

1516
void test() {

clang/test/SemaObjC/block-type-safety.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
@interface Super @end
55
@interface Sub : Super @end
66

7-
void f2(void(^f)(Super *)) {
7+
void f2(void(^f)(Super *)) { // expected-note{{passing argument to parameter 'f' here}}
88
Super *o;
99
f(o);
1010
}
@@ -18,7 +18,7 @@ void r0(Super* (^f)()) {
1818
Super *o = f();
1919
}
2020

21-
void r1(Sub* (^f)()) {
21+
void r1(Sub* (^f)()) { // expected-note{{passing argument to parameter 'f' here}}
2222
Sub *o = f();
2323
}
2424

@@ -95,7 +95,7 @@ -(void) printThing { }
9595
@end
9696

9797
@protocol P, P2;
98-
void f4(void (^f)(id<P> x)) {
98+
void f4(void (^f)(id<P> x)) { // expected-note{{passing argument to parameter 'f' here}}
9999
NSArray<P2> *b;
100100
f(b); // expected-warning {{passing 'NSArray<P2> *' to parameter of incompatible type 'id<P>'}}
101101
}

clang/test/SemaObjC/blocks.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ void foo4(id (^objectCreationBlock)(int)) {
2121
return bar4(objectCreationBlock);
2222
}
2323

24-
void bar5(id(^)(void));
24+
void bar5(id(^)(void)); // expected-note{{passing argument to parameter here}}
2525
void foo5(id (^objectCreationBlock)(int)) {
2626
return bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(int)' to parameter of type 'id (^)(void)'}}
2727
}

clang/test/SemaObjC/class-method-self.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
typedef struct objc_class *Class;
44
@interface XX
55

6-
- (void)addObserver:(XX*)o;
6+
- (void)addObserver:(XX*)o; // expected-note 2{{passing argument to parameter 'o' here}}
77

88
@end
99

clang/test/SemaObjC/compatible-protocol-qualified-types.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ @protocol NSTextStorageDelegate;
4444

4545
@interface NSTextStorage : NSObject
4646

47-
- (void)setDelegate:(id <NSTextStorageDelegate>)delegate;
47+
- (void)setDelegate:(id <NSTextStorageDelegate>)delegate; // expected-note{{passing argument to parameter 'delegate' here}}
4848
- (id <NSTextStorageDelegate>)delegate;
4949

5050
@end

0 commit comments

Comments
 (0)