From: David Blaikie Date: Sat, 10 Sep 2011 05:35:08 +0000 (+0000) Subject: Show either a location or a fixit note, not both, for uninitialized variable warnings. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4f4f349208b2b2307454e169ac7b039e989f003f;p=clang Show either a location or a fixit note, not both, for uninitialized variable warnings. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139463 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 58bfbcfd28..b67f7aec7e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1032,7 +1032,7 @@ def warn_maybe_uninit_var_captured_by_block : Warning< "variable %0 may be uninitialized when captured by block">, InGroup, DefaultIgnore; def note_var_fixit_add_initialization : Note< - "add initialization to silence this warning">; + "initialize the variable %0 to silence this warning">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; def err_temp_copy_no_viable : Error< diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 30b6b0c8e3..6a7c5d3dc3 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -433,6 +433,50 @@ public: }; } +static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { + // Don't issue a fixit if there is already an initializer. + if (VD->getInit()) + return false; + + // Suggest possible initialization (if any). + const char *initialization = 0; + QualType VariableTy = VD->getType().getCanonicalType(); + + if (VariableTy->isObjCObjectPointerType() || + VariableTy->isBlockPointerType()) { + // Check if 'nil' is defined. + if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) + initialization = " = nil"; + else + initialization = " = 0"; + } + else if (VariableTy->isRealFloatingType()) + initialization = " = 0.0"; + else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) + initialization = " = false"; + else if (VariableTy->isEnumeralType()) + return false; + else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) { + if (S.Context.getLangOptions().CPlusPlus0x) + initialization = " = nullptr"; + // Check if 'NULL' is defined. + else if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL"))) + initialization = " = NULL"; + else + initialization = " = 0"; + } + else if (VariableTy->isScalarType()) + initialization = " = 0"; + + if (initialization) { + SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); + S.Diag(loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() + << FixItHint::CreateInsertion(loc, initialization); + return true; + } + return false; +} + /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an /// uninitialized variable. This manages the different forms of diagnostic /// emitted for particular types of uses. Returns true if the use was diagnosed @@ -487,56 +531,15 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, } // Report where the variable was declared when the use wasn't within - // the initializer of that declaration. - if (!isSelfInit) + // the initializer of that declaration & we didn't already suggest + // an initialization fixit. + if (!isSelfInit && !SuggestInitializationFixit(S, VD)) S.Diag(VD->getLocStart(), diag::note_uninit_var_def) << VD->getDeclName(); return true; } -static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) { - // Don't issue a fixit if there is already an initializer. - if (VD->getInit()) - return; - - // Suggest possible initialization (if any). - const char *initialization = 0; - QualType VariableTy = VD->getType().getCanonicalType(); - - if (VariableTy->isObjCObjectPointerType() || - VariableTy->isBlockPointerType()) { - // Check if 'nil' is defined. - if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) - initialization = " = nil"; - else - initialization = " = 0"; - } - else if (VariableTy->isRealFloatingType()) - initialization = " = 0.0"; - else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) - initialization = " = false"; - else if (VariableTy->isEnumeralType()) - return; - else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) { - if (S.Context.getLangOptions().CPlusPlus0x) - initialization = " = nullptr"; - // Check if 'NULL' is defined. - else if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL"))) - initialization = " = NULL"; - else - initialization = " = 0"; - } - else if (VariableTy->isScalarType()) - initialization = " = 0"; - - if (initialization) { - SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); - S.Diag(loc, diag::note_var_fixit_add_initialization) - << FixItHint::CreateInsertion(loc, initialization); - } -} - typedef std::pair UninitUse; namespace { @@ -587,15 +590,11 @@ public: for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi) { - if (!DiagnoseUninitializedUse(S, vd, vi->first, + if (DiagnoseUninitializedUse(S, vd, vi->first, /*isAlwaysUninit=*/vi->second)) - continue; - - SuggestInitializationFixit(S, vd); - - // Skip further diagnostics for this variable. We try to warn only on - // the first point at which a variable is used uninitialized. - break; + // Skip further diagnostics for this variable. We try to warn only on + // the first point at which a variable is used uninitialized. + break; } delete vec; diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c index dbde333d75..2398504347 100644 --- a/test/Sema/uninit-variables.c +++ b/test/Sema/uninit-variables.c @@ -4,7 +4,7 @@ typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); int test1() { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} return x; // expected-warning{{variable 'x' is uninitialized when used here}} } @@ -20,25 +20,25 @@ int test3() { } int test4() { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} ++x; // expected-warning{{variable 'x' is uninitialized when used here}} return x; } int test5() { - int x, y; // expected-note{{variable 'y' is declared here}} expected-note{{add initialization to silence this warning}} + int x, y; // expected-note{{initialize the variable 'y' to silence this warning}} x = y; // expected-warning{{variable 'y' is uninitialized when used here}} return x; } int test6() { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} x += 2; // expected-warning{{variable 'x' is uninitialized when used here}} return x; } int test7(int y) { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} if (y) x = 1; return x; // expected-warning{{variable 'x' may be uninitialized when used here}} @@ -54,7 +54,7 @@ int test8(int y) { } int test9(int n) { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} for (unsigned i = 0 ; i < n; ++i) { if (i == n - 1) break; @@ -64,7 +64,7 @@ int test9(int n) { } int test10(unsigned n) { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} for (unsigned i = 0 ; i < n; ++i) { x = 1; } @@ -72,7 +72,7 @@ int test10(unsigned n) { } int test11(unsigned n) { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} for (unsigned i = 0 ; i <= n; ++i) { x = 1; } @@ -80,7 +80,7 @@ int test11(unsigned n) { } void test12(unsigned n) { - for (unsigned i ; n ; ++i) ; // expected-warning{{variable 'i' is uninitialized when used here}} expected-note{{variable 'i' is declared here}} expected-note{{add initialization to silence this warning}} + for (unsigned i ; n ; ++i) ; // expected-warning{{variable 'i' is uninitialized when used here}} expected-note{{initialize the variable 'i' to silence this warning}} } int test13() { @@ -111,7 +111,7 @@ void test16() { void test17() { // Don't warn multiple times about the same uninitialized variable // along the same path. - int *x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int *x; // expected-note{{initialize the variable 'x' to silence this warning}} *x = 1; // expected-warning{{variable 'x' is uninitialized when used here}} *x = 1; // no-warning } @@ -135,14 +135,14 @@ int test19() { } int test20() { - int z; // expected-note{{variable 'z' is declared here}} expected-note{{add initialization to silence this warning}} + int z; // expected-note{{initialize the variable 'z' to silence this warning}} if ((test19_aux1() + test19_aux2() && test19_aux1()) || test19_aux3(&z)) return z; // expected-warning{{variable 'z' may be uninitialized when used here}} return 0; } int test21(int x, int y) { - int z; // expected-note{{variable 'z' is declared here}} expected-note{{add initialization to silence this warning}} + int z; // expected-note{{initialize the variable 'z' to silence this warning}} if ((x && y) || test19_aux3(&z) || test19_aux2()) return z; // expected-warning{{variable 'z' may be uninitialized when used here}} return 0; @@ -167,7 +167,7 @@ int test23() { // conditionals. This possibly can be handled by making the CFG itself // represent such control-dependencies, but it is a niche case. int test24(int flag) { - unsigned val; // expected-note{{variable 'val' is declared here}} expected-note{{add initialization to silence this warning}} + unsigned val; // expected-note{{initialize the variable 'val' to silence this warning}} if (flag) val = 1; if (!flag) @@ -176,13 +176,13 @@ int test24(int flag) { } float test25() { - float x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + float x; // expected-note{{initialize the variable 'x' to silence this warning}} return x; // expected-warning{{variable 'x' is uninitialized when used here}} } typedef int MyInt; MyInt test26() { - MyInt x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + MyInt x; // expected-note{{initialize the variable 'x' to silence this warning}} return x; // expected-warning{{variable 'x' is uninitialized when used here}} } @@ -193,12 +193,12 @@ int test27() { } int test28() { - int len; // expected-note{{variable 'len' is declared here}} expected-note{{add initialization to silence this warning}} + int len; // expected-note{{initialize the variable 'len' to silence this warning}} return sizeof(int[len]); // expected-warning{{variable 'len' is uninitialized when used here}} } void test29() { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} (void) ^{ (void) x; }; // expected-warning{{variable 'x' is uninitialized when captured by block}} } @@ -223,7 +223,7 @@ void test_33() { } int test_34() { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} (void) x; return x; // expected-warning{{variable 'x' is uninitialized when used here}} } @@ -237,7 +237,7 @@ void test35(int x) { // Test handling of indirect goto. void test36() { - void **pc; // expected-note{{variable 'pc' is declared here}} expected-note{{add initialization to silence this warning}} + void **pc; // expected-note{{initialize the variable 'pc' to silence this warning}} void *dummy[] = { &&L1, &&L2 }; L1: goto *pc; // expected-warning{{variable 'pc' is uninitialized when used here}} @@ -266,19 +266,19 @@ int test38(int r, int x, int y) } int test39(int x) { - int y; // expected-note {{variable 'y' is declared here}} expected-note{{add initialization to silence this warning}} + int y; // expected-note{{initialize the variable 'y' to silence this warning}} int z = x + y; // expected-warning {{variable 'y' is uninitialized when used here}} return z; } int test40(int x) { - int y; // expected-note {{variable 'y' is declared here}} expected-note{{add initialization to silence this warning}} + int y; // expected-note{{initialize the variable 'y' to silence this warning}} return x ? 1 : y; // expected-warning {{variable 'y' is uninitialized when used here}} } int test41(int x) { - int y; // expected-note {{variable 'y' is declared here}} expected-note{{add initialization to silence this warning}} + int y; // expected-note{{initialize the variable 'y' to silence this warning}} if (x) y = 1; // no-warning return y; // expected-warning {{variable 'y' may be uninitialized when used here}} } @@ -290,14 +290,14 @@ void test42() { void test43_aux(int x); void test43(int i) { - int x; // expected-note {{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} for (i = 0 ; i < 10; i++) test43_aux(x++); // expected-warning {{variable 'x' is uninitialized when used here}} } void test44(int i) { int x = i; - int y; // expected-note {{variable 'y' is declared here}} expected-note{{add initialization to silence this warning}} + int y; // expected-note{{initialize the variable 'y' to silence this warning}} for (i = 0; i < 10; i++ ) { test43_aux(x++); // no-warning x += y; // expected-warning {{variable 'y' is uninitialized when used here}} @@ -313,7 +313,7 @@ int test45(int j) { void test46() { - int i; // expected-note {{variable 'i' is declared here}} expected-note{{add initialization to silence this warning}} + int i; // expected-note{{initialize the variable 'i' to silence this warning}} int j = i ? : 1; // expected-warning {{variable 'i' is uninitialized when used here}} } @@ -344,7 +344,7 @@ int test51(void) // FIXME: This is a false positive, but it tests logical operations in switch statements. int test52(int a, int b) { - int x; // expected-note {{variable 'x' is declared here}} expected-note {{add initialization to silence this warning}} + int x; // expected-note {{initialize the variable 'x' to silence this warning}} switch (a || b) { // expected-warning {{switch condition has boolean value}} case 0: x = 1; @@ -357,14 +357,14 @@ int test52(int a, int b) { } void test53() { - int x; // expected-note {{variable 'x' is declared here}} expected-note {{add initialization to silence this warning}} + int x; // expected-note {{initialize the variable 'x' to silence this warning}} int y = (x); // expected-warning {{variable 'x' is uninitialized when used here}} } // This CFG caused the uninitialized values warning to inf-loop. extern int PR10379_g(); void PR10379_f(int *len) { - int new_len; // expected-note {{variable 'new_len' is declared here}} expected-note{{add initialization to silence this warning}} + int new_len; // expected-note{{initialize the variable 'new_len' to silence this warning}} for (int i = 0; i < 42 && PR10379_g() == 0; i++) { if (PR10379_g() == 1) continue; diff --git a/test/SemaCXX/uninit-variables-conditional.cpp b/test/SemaCXX/uninit-variables-conditional.cpp index 3324215621..3c44c7249d 100644 --- a/test/SemaCXX/uninit-variables-conditional.cpp +++ b/test/SemaCXX/uninit-variables-conditional.cpp @@ -15,7 +15,7 @@ int init(double *); // the destructor in Foo fouls about the minor bit of path-sensitivity in // -Wuninitialized. double test() { - double x; // expected-note {{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + double x; // expected-note{{initialize the variable 'x' to silence this warning}} if (bar() || baz() || Foo() || init(&x)) return 1.0; diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp index 9abccf0751..358a572356 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -26,7 +26,7 @@ void unevaluated_tests() { // Warn for glvalue arguments to typeid whose type is polymorphic. struct A { virtual ~A() {} }; void polymorphic_test() { - A *a; // expected-note{{declared here}} expected-note{{add initialization}} + A *a; // expected-note{{initialize the variable 'a' to silence this warning}} (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here }} } @@ -50,7 +50,7 @@ unsigned test3_b() { return x; // no-warning } unsigned test3_c() { - unsigned x; // expected-note{{declared here}} expected-note{{add initialization}} + unsigned x; // expected-note{{initialize the variable 'x' to silence this warning}} const bool flag = false; if (flag && (x = test3_aux()) == 0) { x = 1; @@ -126,7 +126,7 @@ void test_noop_cast() } void test_noop_cast2() { - int x; // expected-note {{declared here}} expected-note {{add initialization}} + int x; // expected-note {{initialize the variable 'x' to silence this warning}} int y = (int&)x; // expected-warning {{uninitialized when used here}} } @@ -137,7 +137,7 @@ void test_bitcasts() { } void test_bitcasts_2() { - int x; // expected-note {{declared here}} expected-note {{add initialization}} + int x; // expected-note {{initialize the variable 'x' to silence this warning}} int y = (float &)x; // expected-warning {{uninitialized when used here}} } diff --git a/test/SemaObjC/uninit-variables.m b/test/SemaObjC/uninit-variables.m index b5c49184f4..cad0f54b2d 100644 --- a/test/SemaObjC/uninit-variables.m +++ b/test/SemaObjC/uninit-variables.m @@ -3,7 +3,7 @@ // Duplicated from uninit-variables.c. // Test just to ensure the analysis is working. int test1() { - int x; // expected-note{{variable 'x' is declared here}} expected-note{{add initialization}} + int x; // expected-note{{initialize the variable 'x' to silence this warning}} return x; // expected-warning{{variable 'x' is uninitialized when used here}} }