danielmarjamaki created this revision. This patch clarify the error messages about uninitialized function arguments.
It can be really hard to see the problem if there are 10-20 arguments like: printf("debug:....", a, b.c, d, e, ...); with no info about which argument is uninitialized and with a complicated path to investigate it's hard to see the bug. Repository: rL LLVM https://reviews.llvm.org/D30341 Files: lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp test/Analysis/NewDelete-checker-test.cpp test/Analysis/diagnostics/undef-value-param.m test/Analysis/malloc.m test/Analysis/misc-ps-region-store.m test/Analysis/misc-ps.m test/Analysis/null-deref-ps.c test/Analysis/nullptr.cpp test/Analysis/uninit-const.c test/Analysis/uninit-const.cpp test/Analysis/uninit-msg-expr.m test/Analysis/uninit-vals-ps.c test/Analysis/uninit-vals.cpp
Index: test/Analysis/uninit-vals.cpp =================================================================== --- test/Analysis/uninit-vals.cpp +++ test/Analysis/uninit-vals.cpp @@ -27,7 +27,7 @@ // case with undefined values, too. c1.b.a = c2->b.a; #else - c1.b.a = c2->b.a; // expected-warning{{Function call argument is an uninitialized value}} + c1.b.a = c2->b.a; // expected-warning{{Function call argument number '1' is an uninitialized value}} #endif } } Index: test/Analysis/uninit-vals-ps.c =================================================================== --- test/Analysis/uninit-vals-ps.c +++ test/Analysis/uninit-vals-ps.c @@ -14,7 +14,7 @@ int f1_b() { int x; - return bar(x)+1; // expected-warning{{Function call argument is an uninitialized value}} + return bar(x)+1; // expected-warning{{Function call argument number '1' is an uninitialized value}} } int f2() { Index: test/Analysis/uninit-msg-expr.m =================================================================== --- test/Analysis/uninit-msg-expr.m +++ test/Analysis/uninit-msg-expr.m @@ -52,5 +52,5 @@ void f3() { NSMutableArray *aArray = [NSArray array]; NSString *aString; - [aArray addObject:aString]; // expected-warning {{Argument in message expression is an uninitialized value}} + [aArray addObject:aString]; // expected-warning {{Argument number '1' in message expression is an uninitialized value}} } Index: test/Analysis/uninit-const.cpp =================================================================== --- test/Analysis/uninit-const.cpp +++ test/Analysis/uninit-const.cpp @@ -66,8 +66,8 @@ int &p = t; int &s = p; int &q = s; //expected-note {{'q' initialized here}} - doStuff6(q); //expected-warning {{Function call argument is an uninitialized value}} - //expected-note@-1 {{Function call argument is an uninitialized value}} + doStuff6(q); //expected-warning {{Function call argument number '1' is an uninitialized value}} + //expected-note@-1 {{Function call argument number '1' is an uninitialized value}} } void doStuff6_3(int& q_, int *ptr_) {} @@ -78,32 +78,32 @@ int &p = t; int &s = p; int &q = s; - doStuff6_3(q,ptr); //expected-warning {{Function call argument is an uninitialized value}} - //expected-note@-1 {{Function call argument is an uninitialized value}} + doStuff6_3(q,ptr); //expected-warning {{Function call argument number '2' is an uninitialized value}} + //expected-note@-1 {{Function call argument number '2' is an uninitialized value}} } void f6(void) { int k; // expected-note {{'k' declared without an initial value}} - doStuff6(k); // expected-warning {{Function call argument is an uninitialized value}} - // expected-note@-1 {{Function call argument is an uninitialized value}} + doStuff6(k); // expected-warning {{Function call argument number '1' is an uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is an uninitialized value}} } void f5(void) { int t; int* tp = &t; // expected-note {{'tp' initialized here}} - doStuff_uninit(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_uninit(tp); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } void f4(void) { int y; // expected-note {{'y' declared without an initial value}} - doStuff4(y); // expected-warning {{Function call argument is an uninitialized value}} - // expected-note@-1 {{Function call argument is an uninitialized value}} + doStuff4(y); // expected-warning {{Function call argument number '1' is an uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is an uninitialized value}} } void f3(void) { @@ -123,6 +123,6 @@ void f_uninit(void) { int x; - doStuff_uninit(&x); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_uninit(&x); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } Index: test/Analysis/uninit-const.c =================================================================== --- test/Analysis/uninit-const.c +++ test/Analysis/uninit-const.c @@ -24,16 +24,16 @@ void f_1(void) { int t; int* tp = &t; // expected-note {{'tp' initialized here}} - doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } void f_1_1(void) { int t; int* tp1 = &t; int* tp2 = tp1; // expected-note {{'tp2' initialized here}} - doStuff_pointerToConstInt(tp2); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_pointerToConstInt(tp2); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } @@ -45,8 +45,8 @@ int t; int* p = f_2_sub(&t); int* tp = p; // expected-note {{'tp' initialized here}} - doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } int z; @@ -62,14 +62,14 @@ void f_5(void) { int ta[5]; int* tp = ta; // expected-note {{'tp' initialized here}} - doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } void f_5_1(void) { int ta[5]; // expected-note {{'ta' initialized here}} - doStuff_pointerToConstInt(ta); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_pointerToConstInt(ta); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } void f_6(void) { @@ -92,27 +92,27 @@ void f_8(void) { int g; // expected-note {{'g' declared without an initial value}} - doStuff2(g); // expected-warning {{Function call argument is an uninitialized value}} - // expected-note@-1 {{Function call argument is an uninitialized value}} + doStuff2(g); // expected-warning {{Function call argument number '1' is an uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is an uninitialized value}} } void f_9(void) { int a[6]; int const *ptau = a; // expected-note {{'ptau' initialized here}} - doStuff_arrayOfConstInt(ptau); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_arrayOfConstInt(ptau); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } void f_10(void) { int a[6]; // expected-note {{'a' initialized here}} - doStuff_arrayOfConstInt(a); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_arrayOfConstInt(a); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } void f_11(void) { int t[10]; //expected-note {{'t' initialized here}} - doStuff_constStaticSizedArray(t); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_constStaticSizedArray(t); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } void f_12(void) { @@ -126,8 +126,8 @@ ptr = (int *)malloc(sizeof(int)); // expected-note {{Value assigned to 'ptr'}} - doStuff_pointerToConstInt(ptr); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_pointerToConstInt(ptr); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} free(ptr); return 0; } @@ -148,25 +148,25 @@ int t; int v; int* tp = &t; // expected-note {{'tp' initialized here}} - doStuff_variadic(tp,v); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_variadic(tp,v); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } // uninit pointer, init val void f_variadic_unp_inv(void) { int t; int v = 3; int* tp = &t; // expected-note {{'tp' initialized here}} - doStuff_variadic(tp,v); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_variadic(tp,v); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } // init pointer, uninit val void f_variadic_inp_unv(void) { int t=5; int v; // expected-note {{'v' declared without an initial value}} int* tp = &t; - doStuff_variadic(tp,v);// expected-warning {{Function call argument is an uninitialized value}} - // expected-note@-1 {{Function call argument is an uninitialized value}} + doStuff_variadic(tp,v);// expected-warning {{Function call argument number '2' is an uninitialized value}} + // expected-note@-1 {{Function call argument number '2' is an uninitialized value}} } // init pointer, init val @@ -192,8 +192,8 @@ int u=3; int *vp = &u ; int *tp = &t; // expected-note {{'tp' initialized here}} - doStuff_variadic(tp,vp); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_variadic(tp,vp); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } //init pointer, uninit pointer @@ -211,6 +211,6 @@ int u; int *vp = &u ; int *tp = &t; // expected-note {{'tp' initialized here}} - doStuff_variadic(tp,vp); // expected-warning {{Function call argument is a pointer to uninitialized value}} - // expected-note@-1 {{Function call argument is a pointer to uninitialized value}} + doStuff_variadic(tp,vp); // expected-warning {{Function call argument number '1' is a pointer to uninitialized value}} + // expected-note@-1 {{Function call argument number '1' is a pointer to uninitialized value}} } Index: test/Analysis/nullptr.cpp =================================================================== --- test/Analysis/nullptr.cpp +++ test/Analysis/nullptr.cpp @@ -107,7 +107,7 @@ void shouldNotCrash() { decltype(nullptr) p; if (getSymbol()) - invokeF(p); // expected-warning{{Function call argument is an uninit}} + invokeF(p); // expected-warning{{Function call argument number '1' is an uninit}} if (getSymbol()) invokeF(nullptr); if (getSymbol()) { Index: test/Analysis/null-deref-ps.c =================================================================== --- test/Analysis/null-deref-ps.c +++ test/Analysis/null-deref-ps.c @@ -286,7 +286,7 @@ void pr4759() { int *p; - pr4759_aux(p); // expected-warning{{Function call argument is an uninitialized value}} + pr4759_aux(p); // expected-warning{{Function call argument number '1' is an uninitialized value}} } // Relax function call arguments invalidation to be aware of const Index: test/Analysis/misc-ps.m =================================================================== --- test/Analysis/misc-ps.m +++ test/Analysis/misc-ps.m @@ -796,16 +796,16 @@ void test_bad_call_aux(int x); void test_bad_call(void) { int y; - test_bad_call_aux(y); // expected-warning{{Function call argument is an uninitialized value}} + test_bad_call_aux(y); // expected-warning{{Function call argument number '1' is an uninitialized value}} } @interface TestBadArg {} - (void) testBadArg:(int) x; @end void test_bad_msg(TestBadArg *p) { int y; - [p testBadArg:y]; // expected-warning{{Argument in message expression is an uninitialized value}} + [p testBadArg:y]; // expected-warning{{Argument number '1' in message expression is an uninitialized value}} } //===----------------------------------------------------------------------===// Index: test/Analysis/misc-ps-region-store.m =================================================================== --- test/Analysis/misc-ps-region-store.m +++ test/Analysis/misc-ps-region-store.m @@ -396,7 +396,7 @@ int rdar_7332673_test2_aux(char *x); void rdar_7332673_test2() { char *value; - if ( rdar_7332673_test2_aux(value) != 1 ) {} // expected-warning{{Function call argument is an uninitialized value}} + if ( rdar_7332673_test2_aux(value) != 1 ) {} // expected-warning{{Function call argument number '1' is an uninitialized value}} } //===----------------------------------------------------------------------===// @@ -673,7 +673,7 @@ builder = ^(id object) { id x; if (object) { - builder(x); // expected-warning{{Block call argument is an uninitialized value}} + builder(x); // expected-warning{{Block call argument number '1' is an uninitialized value}} } }; builder(target); Index: test/Analysis/malloc.m =================================================================== --- test/Analysis/malloc.m +++ test/Analysis/malloc.m @@ -29,7 +29,7 @@ if (error != ((void*)0)) return error; - rdar10579586(buffer->str_c); // expected-warning {{Function call argument is an uninitialized value}} + rdar10579586(buffer->str_c); // expected-warning {{Function call argument number '1' is an uninitialized value}} free(buffer); return ((void*)0); } Index: test/Analysis/diagnostics/undef-value-param.m =================================================================== --- test/Analysis/diagnostics/undef-value-param.m +++ test/Analysis/diagnostics/undef-value-param.m @@ -45,8 +45,8 @@ CreateRefUndef(&storeRef, 4); //expected-note@-1{{Calling 'CreateRefUndef'}} //expected-note@-2{{Returning from 'CreateRefUndef'}} - CFRelease(storeRef); //expected-warning {{Function call argument is an uninitialized value}} - //expected-note@-1{{Function call argument is an uninitialized value}} + CFRelease(storeRef); //expected-warning {{Function call argument number '1' is an uninitialized value}} + //expected-note@-1{{Function call argument number '1' is an uninitialized value}} } @end @@ -918,12 +918,12 @@ // CHECK-NEXT: </array> // CHECK-NEXT: <key>depth</key><integer>0</integer> // CHECK-NEXT: <key>extended_message</key> -// CHECK-NEXT: <string>Function call argument is an uninitialized value</string> +// CHECK-NEXT: <string>Function call argument number '1' is an uninitialized value</string> // CHECK-NEXT: <key>message</key> -// CHECK-NEXT: <string>Function call argument is an uninitialized value</string> +// CHECK-NEXT: <string>Function call argument number '1' is an uninitialized value</string> // CHECK-NEXT: </dict> // CHECK-NEXT: </array> -// CHECK-NEXT: <key>description</key><string>Function call argument is an uninitialized value</string> +// CHECK-NEXT: <key>description</key><string>Function call argument number '1' is an uninitialized value</string> // CHECK-NEXT: <key>category</key><string>Logic error</string> // CHECK-NEXT: <key>type</key><string>Uninitialized argument value</string> // CHECK-NEXT: <key>check_name</key><string>core.CallAndMessage</string> Index: test/Analysis/NewDelete-checker-test.cpp =================================================================== --- test/Analysis/NewDelete-checker-test.cpp +++ test/Analysis/NewDelete-checker-test.cpp @@ -244,7 +244,7 @@ void testUninitFree() { int *x; - free(x); // expected-warning{{Function call argument is an uninitialized value}} + free(x); // expected-warning{{Function call argument number '1' is an uninitialized value}} } void testUninitDeleteSink() { Index: lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -71,7 +71,7 @@ private: bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange, - const Expr *ArgEx, bool IsFirstArgument, + const Expr *ArgEx, int ArgumentNumber, bool CheckUninitFields, const CallEvent &Call, std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl) const; @@ -89,9 +89,10 @@ BT.reset(new BuiltinBug(this, desc)); } bool uninitRefOrPointer(CheckerContext &C, const SVal &V, - SourceRange ArgRange, - const Expr *ArgEx, std::unique_ptr<BugType> &BT, - const ParmVarDecl *ParamDecl, const char *BD) const; + SourceRange ArgRange, const Expr *ArgEx, + std::unique_ptr<BugType> &BT, + const ParmVarDecl *ParamDecl, const char *BD, + int ArgumentNumber) const; }; } // end anonymous namespace @@ -111,58 +112,61 @@ C.emitReport(std::move(R)); } -static StringRef describeUninitializedArgumentInCall(const CallEvent &Call, - bool IsFirstArgument) { +static std::string describeUninitializedArgumentInCall(const CallEvent &Call, + int ArgumentNumber) { switch (Call.getKind()) { case CE_ObjCMessage: { const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call); switch (Msg.getMessageKind()) { case OCM_Message: - return "Argument in message expression is an uninitialized value"; + return "Argument number '" + std::to_string(ArgumentNumber+1) + + "' in message expression is an uninitialized value"; case OCM_PropertyAccess: assert(Msg.isSetter() && "Getters have no args"); return "Argument for property setter is an uninitialized value"; case OCM_Subscript: - if (Msg.isSetter() && IsFirstArgument) + if (Msg.isSetter() && (ArgumentNumber == 0)) return "Argument for subscript setter is an uninitialized value"; return "Subscript index is an uninitialized value"; } llvm_unreachable("Unknown message kind."); } case CE_Block: - return "Block call argument is an uninitialized value"; + return "Block call argument number '" + std::to_string(ArgumentNumber+1) + + "' is an uninitialized value"; default: - return "Function call argument is an uninitialized value"; + return "Function call argument number '" + std::to_string(ArgumentNumber+1) + + "' is an uninitialized value"; } } -bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C, - const SVal &V, - SourceRange ArgRange, - const Expr *ArgEx, - std::unique_ptr<BugType> &BT, - const ParmVarDecl *ParamDecl, - const char *BD) const { +bool CallAndMessageChecker::uninitRefOrPointer( + CheckerContext &C, const SVal &V, SourceRange ArgRange, const Expr *ArgEx, + std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl, const char *BD, + int ArgumentNumber) const { if (!Filter.Check_CallAndMessageUnInitRefArg) return false; // No parameter declaration available, i.e. variadic function argument. - if(!ParamDecl) + if (!ParamDecl) return false; // If parameter is declared as pointer to const in function declaration, // then check if corresponding argument in function call is // pointing to undefined symbol value (uninitialized memory). - StringRef Message; + std::string Message; if (ParamDecl->getType()->isPointerType()) { - Message = "Function call argument is a pointer to uninitialized value"; + Message = "Function call argument number '" + + std::to_string(ArgumentNumber+1) + + "' is a pointer to uninitialized value"; } else if (ParamDecl->getType()->isReferenceType()) { - Message = "Function call argument is an uninitialized value"; + Message = "Function call argument number '" + + std::to_string(ArgumentNumber+1) + "' is an uninitialized value"; } else return false; - if(!ParamDecl->getType()->getPointeeType().isConstQualified()) + if (!ParamDecl->getType()->getPointeeType().isConstQualified()) return false; if (const MemRegion *SValMemRegion = V.getAsRegion()) { @@ -188,24 +192,24 @@ SVal V, SourceRange ArgRange, const Expr *ArgEx, - bool IsFirstArgument, + int ArgumentNumber, bool CheckUninitFields, const CallEvent &Call, std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl ) const { const char *BD = "Uninitialized argument value"; - if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD)) + if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD, + ArgumentNumber)) return true; if (V.isUndef()) { if (ExplodedNode *N = C.generateErrorNode()) { LazyInit_BT(BD, BT); - // Generate a report for this bug. - StringRef Desc = - describeUninitializedArgumentInCall(Call, IsFirstArgument); + std::string Desc = + describeUninitializedArgumentInCall(Call, ArgumentNumber); auto R = llvm::make_unique<BugReport>(*BT, Desc, N); R->addRange(ArgRange); if (ArgEx) @@ -435,7 +439,7 @@ if(FD && i < FD->getNumParams()) ParamDecl = FD->getParamDecl(i); if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i), - Call.getArgExpr(i), /*IsFirstArgument=*/i == 0, + Call.getArgExpr(i), i, checkUninitFields, Call, *BT, ParamDecl)) return; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits