From: Ted Kremenek Date: Fri, 21 Jan 2011 19:41:41 +0000 (+0000) Subject: Enhance -Wuninitialized-experimental diagnostics X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=94b1b4d785bc0f09f6af4be394e59d51f35dda60;p=clang Enhance -Wuninitialized-experimental diagnostics to issue the warning at an uninitialized variable's declaration, but to issue notes at possible uninitialized uses (which could be multiple). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123994 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 84b2a88d58..f595a1cc4b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -822,6 +822,8 @@ def warn_field_is_uninit : Warning<"field is uninitialized when used here">, InGroup>; def warn_var_is_uninit : Warning<"use of uninitialized variable %0">, InGroup>, DefaultIgnore; +def note_var_is_uninit : Note< + "variable %0 is possibly uninitialized when used here">; 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 eb8590d60c..67ddbf5bf9 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -364,14 +364,62 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, //===----------------------------------------------------------------------===// namespace { +struct SLocSort { + bool operator()(const DeclRefExpr *a, const DeclRefExpr *b) { + SourceLocation aLoc = a->getLocStart(); + SourceLocation bLoc = b->getLocStart(); + return aLoc.getRawEncoding() < bLoc.getRawEncoding(); + } +}; + class UninitValsDiagReporter : public UninitVariablesHandler { Sema &S; + typedef llvm::SmallVector UsesVec; + typedef llvm::DenseMap UsesMap; + UsesMap *uses; + public: - UninitValsDiagReporter(Sema &S) : S(S) {} + UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} + ~UninitValsDiagReporter() { + flushDiagnostics(); + } void handleUseOfUninitVariable(const DeclRefExpr *dr, const VarDecl *vd) { - S.Diag(dr->getLocStart(), diag::warn_var_is_uninit) - << vd->getDeclName() << dr->getSourceRange(); + if (!uses) + uses = new UsesMap(); + + UsesVec *&vec = (*uses)[vd]; + if (!vec) + vec = new UsesVec(); + + vec->push_back(dr); + } + + void flushDiagnostics() { + if (!uses) + return; + + for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { + const VarDecl *vd = i->first; + UsesVec *vec = i->second; + + S.Diag(vd->getLocStart(), diag::warn_var_is_uninit) + << vd->getDeclName() << vd->getSourceRange(); + + // Sort the uses by their SourceLocations. While not strictly + // guaranteed to produce them in line/column order, this will provide + // a stable ordering. + std::sort(vec->begin(), vec->end(), SLocSort()); + + for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi) + { + const DeclRefExpr *dr = *vi; + S.Diag(dr->getLocStart(), diag::note_var_is_uninit) + << vd->getDeclName() << dr->getSourceRange(); + } + delete vec; + } + delete uses; } }; } diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c index 7ac225f5a3..62fcda019a 100644 --- a/test/Sema/uninit-variables.c +++ b/test/Sema/uninit-variables.c @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -Wuninitialized-experimental -fsyntax-only %s -verify int test1() { - int x; - return x; // expected-warning{{use of uninitialized variable 'x'}} + int x; // expected-warning{{use of uninitialized variable 'x'}} + return x; // expected-note{{variable 'x' is possibly uninitialized when used here}} } int test2() { @@ -17,28 +17,28 @@ int test3() { } int test4() { - int x; - ++x; // expected-warning{{use of uninitialized variable 'x'}} + int x; // expected-warning{{use of uninitialized variable 'x'}} + ++x; // expected-note{{variable 'x' is possibly uninitialized when used here}} return x; } int test5() { - int x, y; - x = y; // expected-warning{{use of uninitialized variable 'y'}} + int x, y; // expected-warning{{use of uninitialized variable 'y'}} + x = y; // expected-note{{variable 'y' is possibly uninitialized when used here}} return x; } int test6() { - int x; - x += 2; // expected-warning{{use of uninitialized variable 'x'}} + int x; // expected-warning{{use of uninitialized variable 'x'}} + x += 2; // expected-note{{variable 'x' is possibly uninitialized when used here}} return x; } int test7(int y) { - int x; + int x; // expected-warning{{use of uninitialized variable 'x'}} if (y) x = 1; - return x; // expected-warning{{use of uninitialized variable 'x'}} + return x; // expected-note{{variable 'x' is possibly uninitialized when used here}} } int test8(int y) { @@ -51,33 +51,33 @@ int test8(int y) { } int test9(int n) { - int x; + int x; // expected-warning{{use of uninitialized variable 'x'}} for (unsigned i = 0 ; i < n; ++i) { if (i == n - 1) break; - x = 1; + x = 1; } - return x; // expected-warning{{use of uninitialized variable 'x'}} + return x; // expected-note{{variable 'x' is possibly uninitialized when used here}} } int test10(unsigned n) { - int x; + int x; // expected-warning{{use of uninitialized variable 'x'}} for (unsigned i = 0 ; i < n; ++i) { x = 1; } - return x; // expected-warning{{use of uninitialized variable 'x'}} + return x; // expected-note{{variable 'x' is possibly uninitialized when used here}} } int test11(unsigned n) { - int x; + int x; // expected-warning{{use of uninitialized variable 'x'}} for (unsigned i = 0 ; i <= n; ++i) { x = 1; } - return x; // expected-warning{{use of uninitialized variable 'x'}} + return x; //expected-note{{variable 'x' is possibly uninitialized when used here}} } void test12(unsigned n) { - for (unsigned i ; n ; ++i) ; // expected-warning{{use of uninitialized variable 'i'}} + for (unsigned i ; n ; ++i) ; // expected-warning{{use of uninitialized variable 'i'}} expected-note{{variable 'i' is possibly uninitialized when used here}}} } int test13() { @@ -92,7 +92,7 @@ void test14() { } void test15() { - int x = x; // expected-warning{{use of uninitialized variable 'x'}} + int x = x; // expected-warning{{use of uninitialized variable 'x'}} expected-note{{variable 'x' is possibly uninitialized when used here}} } // Don't warn in the following example; shows dataflow confluence. @@ -106,8 +106,8 @@ void test16() { void test17() { // Don't warn multiple times about the same uninitialized variable // along the same path. - int *x; - *x = 1; // expected-warning{{use of uninitialized variable 'x'}} + int *x; // expected-warning{{use of uninitialized variable 'x'}} + *x = 1; // expected-note{{variable 'x' is possibly uninitialized when used here}} *x = 1; // no-warning } @@ -130,16 +130,16 @@ int test19() { } int test20() { - int z; + int z; // expected-warning{{use of uninitialized variable 'z'}} if ((test19_aux1() + test19_aux2() && test19_aux1()) || test19_aux3(&z)) - return z; // expected-warning{{use of uninitialized variable 'z'}} + return z; // expected-note{{variable 'z' is possibly uninitialized when used here}} return 0; } int test21(int x, int y) { - int z; + int z; // expected-warning{{use of uninitialized variable 'z'}} if ((x && y) || test19_aux3(&z) || test19_aux2()) - return z; // expected-warning{{use of uninitialized variable 'z'}} + return z; // expected-note{{variable 'z' is possibly uninitialized when used here}} return 0; } @@ -162,11 +162,11 @@ 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; + unsigned val; // expected-warning{{use of uninitialized variable 'val'}} if (flag) val = 1; if (!flag) val = 1; - return val; // expected-warning{{use of uninitialized variable 'val'}} + return val; // expected-note{{variable 'val' is possibly uninitialized when used here}} } diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp index 0d6920ceb3..6d2956296a 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -33,11 +33,11 @@ unsigned test3_b() { return x; // no-warning } unsigned test3_c() { - unsigned x ; + unsigned x ; // expected-warning{{use of uninitialized variable 'x'}} const bool flag = false; if (flag && (x = test3_aux()) == 0) { x = 1; } - return x; // expected-warning{{use of uninitialized variable 'x'}} + return x; // expected-note{{variable 'x' is possibly uninitialized when used here}} }