From bdb97ff687ce85e45cc728b87612ed546f48c1e7 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 26 May 2012 06:20:46 +0000 Subject: [PATCH] In response to some discussions on IRC, tweak the wording of the new -Wsometimes-uninitialized diagnostics to make it clearer that the cause of the issue may be a condition which must always evaluate to true or false, rather than an uninitialized variable. To emphasize this, add a new note with a fixit which removes the impossible condition or replaces it with a constant. Also, downgrade the diagnostic from -Wsometimes-uninitialized to -Wconditional-uninitialized when it applies to a range-based for loop, since the condition is not written explicitly in the code in that case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157511 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ReleaseNotes.html | 9 +- include/clang/Basic/DiagnosticSemaKinds.td | 37 ++-- lib/Sema/AnalysisBasedWarnings.cpp | 156 +++++++++++----- test/Analysis/uninit-sometimes.cpp | 199 ++++++++++++++++----- test/Sema/uninit-variables.c | 10 +- 5 files changed, 295 insertions(+), 116 deletions(-) diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html index 8f30808f04..509e149ad2 100644 --- a/docs/ReleaseNotes.html +++ b/docs/ReleaseNotes.html @@ -102,12 +102,15 @@ int f(bool b) { return n; } -sometimes-uninit.cpp:5:10: warning: variable 'n' is sometimes uninitialized when used here [-Wsometimes-uninitialized] +sometimes-uninit.cpp:3:7: warning: variable 'n' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized] + if (b) + ^ +sometimes-uninit.cpp:5:10: note: uninitialized use occurs here return n; ^ -sometimes-uninit.cpp:3:7: note: uninitialized use occurs whenever 'if' condition is false +sometimes-uninit.cpp:3:3: note: remove the 'if' if its condition is always true if (b) - ^ + ^~~~~~ sometimes-uninit.cpp:2:8: note: initialize the variable 'n' to silence this warning int n; ^ diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2f64326222..66dfafef15 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1178,38 +1178,31 @@ def warn_uninit_self_reference_in_init : Warning< "variable %0 is uninitialized when used within its own initialization">, InGroup; def warn_uninit_var : Warning< - "variable %0 is uninitialized when used here">, + "variable %0 is uninitialized when %select{used here|captured by block}1">, InGroup, DefaultIgnore; def warn_sometimes_uninit_var : Warning< - "variable %0 is sometimes uninitialized when used here">, - InGroup, DefaultIgnore; -def warn_maybe_uninit_var : - Warning<"variable %0 may be uninitialized when used here">, - InGroup, DefaultIgnore; -def note_uninit_var_def : Note< - "variable %0 is declared here">; -def warn_uninit_var_captured_by_block : Warning< - "variable %0 is uninitialized when captured by block">, - InGroup, DefaultIgnore; -def warn_sometimes_uninit_var_captured_by_block : Warning< - "variable %0 is sometimes uninitialized when captured by block">, - InGroup, DefaultIgnore; -def warn_maybe_uninit_var_captured_by_block : Warning< - "variable %0 may be uninitialized when captured by block">, + "variable %0 is %select{used|captured}1 uninitialized whenever " + "%select{'%3' condition is %select{true|false}4|" + "'%3' loop %select{is entered|exits because its condition is false}4|" + "'%3' loop %select{condition is true|exits because its condition is false}4|" + "switch %3 is taken}2">, InGroup, DefaultIgnore; +def warn_maybe_uninit_var : Warning< + "variable %0 may be uninitialized when " + "%select{used here|captured by block}1">, InGroup, DefaultIgnore; +def note_uninit_var_def : Note<"variable %0 is declared here">; +def note_uninit_var_use : Note< + "%select{uninitialized use occurs|variable is captured by block}0 here">; def warn_uninit_byref_blockvar_captured_by_block : Warning< "block pointer variable %0 is uninitialized when captured by block">, InGroup, DefaultIgnore; -def note_sometimes_uninit_var_branch : Note< - "uninitialized use occurs whenever " - "%select{'%1' condition is %select{true|false}2|" - "'%1' loop %select{is entered|exits because its condition is false}2|" - "'%1' loop %select{condition is true|exits because its condition is false}2|" - "switch %1 is taken}0">; def note_block_var_fixit_add_initialization : Note< "maybe you meant to use __block %0">; def note_var_fixit_add_initialization : Note< "initialize the variable %0 to silence this warning">; +def note_uninit_fixit_remove_cond : Note< + "remove the %select{'%1' if its condition|condition if it}0 " + "is always %select{false|true}2">; 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 562fe68292..8f16e70b15 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/Lexer.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprObjC.h" @@ -456,31 +457,92 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { return true; } -/// NoteUninitBranches -- Helper function to produce notes for branches which -/// inevitably lead to an uninitialized variable use. -static void NoteUninitBranches(Sema &S, const UninitUse &Use) { +/// Create a fixit to remove an if-like statement, on the assumption that its +/// condition is CondVal. +static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, + const Stmt *Else, bool CondVal, + FixItHint &Fixit1, FixItHint &Fixit2) { + if (CondVal) { + // If condition is always true, remove all but the 'then'. + Fixit1 = FixItHint::CreateRemoval( + CharSourceRange::getCharRange(If->getLocStart(), + Then->getLocStart())); + if (Else) { + SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken( + Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts()); + Fixit2 = FixItHint::CreateRemoval( + SourceRange(ElseKwLoc, Else->getLocEnd())); + } + } else { + // If condition is always false, remove all but the 'else'. + if (Else) + Fixit1 = FixItHint::CreateRemoval( + CharSourceRange::getCharRange(If->getLocStart(), + Else->getLocStart())); + else + Fixit1 = FixItHint::CreateRemoval(If->getSourceRange()); + } +} + +/// DiagUninitUse -- Helper function to produce a diagnostic for an +/// uninitialized use of a variable. +static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, + bool IsCapturedByBlock) { + bool Diagnosed = false; + + // Diagnose each branch which leads to a sometimes-uninitialized use. for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end(); I != E; ++I) { + assert(Use.getKind() == UninitUse::Sometimes); + + const Expr *User = Use.getUser(); const Stmt *Term = I->Terminator; + + // Information used when building the diagnostic. unsigned DiagKind; - SourceRange Range; const char *Str; + SourceRange Range; + + // FixIts to suppress the diagnosic by removing the dead condition. + // For all binary terminators, branch 0 is taken if the condition is true, + // and branch 1 is taken if the condition is false. + int RemoveDiagKind = -1; + const char *FixitStr = + S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false") + : (I->Output ? "1" : "0"); + FixItHint Fixit1, Fixit2; + switch (Term->getStmtClass()) { default: - // Don't know how to report this. + // Don't know how to report this. Just fall back to 'may be used + // uninitialized'. This happens for range-based for, which the user + // can't explicitly fix. + // FIXME: This also happens if the first use of a variable is always + // uninitialized, eg "for (int n; n < 10; ++n)". We should report that + // with the 'is uninitialized' diagnostic. continue; // "condition is true / condition is false". - case Stmt::IfStmtClass: + case Stmt::IfStmtClass: { + const IfStmt *IS = cast(Term); DiagKind = 0; Str = "if"; - Range = cast(Term)->getCond()->getSourceRange(); + Range = IS->getCond()->getSourceRange(); + RemoveDiagKind = 0; + CreateIfFixit(S, IS, IS->getThen(), IS->getElse(), + I->Output, Fixit1, Fixit2); break; - case Stmt::ConditionalOperatorClass: + } + case Stmt::ConditionalOperatorClass: { + const ConditionalOperator *CO = cast(Term); DiagKind = 0; Str = "?:"; - Range = cast(Term)->getCond()->getSourceRange(); + Range = CO->getCond()->getSourceRange(); + RemoveDiagKind = 0; + CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(), + I->Output, Fixit1, Fixit2); break; + } case Stmt::BinaryOperatorClass: { const BinaryOperator *BO = cast(Term); if (!BO->isLogicalOp()) @@ -488,6 +550,15 @@ static void NoteUninitBranches(Sema &S, const UninitUse &Use) { DiagKind = 0; Str = BO->getOpcodeStr(); Range = BO->getLHS()->getSourceRange(); + RemoveDiagKind = 0; + if ((BO->getOpcode() == BO_LAnd && I->Output) || + (BO->getOpcode() == BO_LOr && !I->Output)) + // true && y -> y, false || y -> y. + Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(), + BO->getOperatorLoc())); + else + // false && y -> false, true || y -> true. + Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr); break; } @@ -496,16 +567,18 @@ static void NoteUninitBranches(Sema &S, const UninitUse &Use) { DiagKind = 1; Str = "while"; Range = cast(Term)->getCond()->getSourceRange(); + RemoveDiagKind = 1; + Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); break; case Stmt::ForStmtClass: DiagKind = 1; Str = "for"; Range = cast(Term)->getCond()->getSourceRange(); - break; - case Stmt::CXXForRangeStmtClass: - DiagKind = 1; - Str = "for"; - Range = cast(Term)->getCond()->getSourceRange(); + RemoveDiagKind = 1; + if (I->Output) + Fixit1 = FixItHint::CreateRemoval(Range); + else + Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); break; // "condition is true / loop is exited". @@ -513,6 +586,8 @@ static void NoteUninitBranches(Sema &S, const UninitUse &Use) { DiagKind = 2; Str = "do"; Range = cast(Term)->getCond()->getSourceRange(); + RemoveDiagKind = 1; + Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); break; // "switch case is taken". @@ -528,9 +603,24 @@ static void NoteUninitBranches(Sema &S, const UninitUse &Use) { break; } - S.Diag(Range.getBegin(), diag::note_sometimes_uninit_var_branch) - << DiagKind << Str << I->Output << Range; + S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var) + << VD->getDeclName() << IsCapturedByBlock << DiagKind + << Str << I->Output << Range; + S.Diag(User->getLocStart(), diag::note_uninit_var_use) + << IsCapturedByBlock << User->getSourceRange(); + if (RemoveDiagKind != -1) + S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond) + << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2; + + Diagnosed = true; } + + if (!Diagnosed) + S.Diag(Use.getUser()->getLocStart(), + Use.getKind() == UninitUse::Always ? diag::warn_uninit_var + : diag::warn_maybe_uninit_var) + << VD->getDeclName() << IsCapturedByBlock + << Use.getUser()->getSourceRange(); } /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an @@ -568,37 +658,15 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, } } - unsigned DiagID = 0; - switch (Use.getKind()) { - case UninitUse::Always: DiagID = diag::warn_uninit_var; break; - case UninitUse::Sometimes: DiagID = diag::warn_sometimes_uninit_var; break; - case UninitUse::Maybe: DiagID = diag::warn_maybe_uninit_var; break; - } - S.Diag(DRE->getLocStart(), DiagID) - << VD->getDeclName() << DRE->getSourceRange(); - NoteUninitBranches(S, Use); + DiagUninitUse(S, VD, Use, false); } else { const BlockExpr *BE = cast(Use.getUser()); - if (VD->getType()->isBlockPointerType() && - !VD->hasAttr()) - S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block) + if (VD->getType()->isBlockPointerType() && !VD->hasAttr()) + S.Diag(BE->getLocStart(), + diag::warn_uninit_byref_blockvar_captured_by_block) << VD->getDeclName(); - else { - unsigned DiagID = 0; - switch (Use.getKind()) { - case UninitUse::Always: - DiagID = diag::warn_uninit_var_captured_by_block; - break; - case UninitUse::Sometimes: - DiagID = diag::warn_sometimes_uninit_var_captured_by_block; - break; - case UninitUse::Maybe: - DiagID = diag::warn_maybe_uninit_var_captured_by_block; - break; - } - S.Diag(BE->getLocStart(), DiagID) << VD->getDeclName(); - NoteUninitBranches(S, Use); - } + else + DiagUninitUse(S, VD, Use, true); } // Report where the variable was declared when the use wasn't within diff --git a/test/Analysis/uninit-sometimes.cpp b/test/Analysis/uninit-sometimes.cpp index 0c77f892e1..9667e2a65c 100644 --- a/test/Analysis/uninit-sometimes.cpp +++ b/test/Analysis/uninit-sometimes.cpp @@ -1,41 +1,63 @@ // RUN: %clang_cc1 -std=gnu++11 -Wsometimes-uninitialized -verify %s +// RUN: %clang_cc1 -std=gnu++11 -Wsometimes-uninitialized -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s bool maybe(); int test_if_false(bool b) { int x; // expected-note {{variable}} - if (b) x = 1; // expected-note {{whenever 'if' condition is false}} - return x; // expected-warning {{sometimes uninit}} + if (b) // expected-warning {{whenever 'if' condition is false}} \ + // expected-note {{remove the 'if' if its condition is always true}} + x = 1; + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{8:3-10:5}:"" +// CHECK: fix-it:"{{.*}}":{7:8-7:8}:" = 0" + + int test_if_true(bool b) { int x; // expected-note {{variable}} - if (b) {} // expected-note {{whenever 'if' condition is true}} + if (b) {} // expected-warning {{whenever 'if' condition is true}} \ + // expected-note {{remove the 'if' if its condition is always false}} else x = 1; - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{20:3-22:8}:"" +// CHECK: fix-it:"{{.*}}":{19:8-19:8}:" = 0" + + int test_while_false(bool b) { int x; // expected-note {{variable}} - while (b) { // expected-note {{whenever 'while' loop exits because its condition is false}} + while (b) { // expected-warning {{whenever 'while' loop exits because its condition is false}} \ + // expected-note {{remove the condition if it is always true}} if (maybe()) { x = 1; break; } }; - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{32:10-32:11}:"true" +// CHECK: fix-it:"{{.*}}":{31:8-31:8}:" = 0" + + int test_while_true(bool b) { int x; // expected-note {{variable}} - while (b) { // expected-note {{whenever 'while' loop is entered}} + while (b) { // expected-warning {{whenever 'while' loop is entered}} \ + // expected-note {{remove the condition if it is always false}} label: - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } x = 0; goto label; } +// CHECK: fix-it:"{{.*}}":{48:10-48:11}:"false" +// CHECK: fix-it:"{{.*}}":{47:8-47:8}:" = 0" + + int test_do_while_false(bool b) { int x; // expected-note {{variable}} do { @@ -43,131 +65,193 @@ int test_do_while_false(bool b) { x = 1; break; } - } while (b); // expected-note {{whenever 'do' loop exits because its condition is false}} - return x; // expected-warning {{sometimes uninit}} + } while (b); // expected-warning {{whenever 'do' loop exits because its condition is false}} \ + // expected-note {{remove the condition if it is always true}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{68:12-68:13}:"true" +// CHECK: fix-it:"{{.*}}":{62:8-62:8}:" = 0" + + int test_do_while_true(bool b) { int x; // expected-note {{variable}} goto label2; do { label1: - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} label2: ; - } while (b); // expected-note {{whenever 'do' loop condition is true}} + } while (b); // expected-warning {{whenever 'do' loop condition is true}} \ + // expected-note {{remove the condition if it is always false}} x = 0; goto label1; } +// CHECK: fix-it:"{{.*}}":{84:12-84:13}:"false" +// CHECK: fix-it:"{{.*}}":{78:8-78:8}:" = 0" + + int test_for_false(int k) { int x; // expected-note {{variable}} for (int n = 0; - n < k; // expected-note {{whenever 'for' loop exits because its condition is false}} + n < k; // expected-warning {{whenever 'for' loop exits because its condition is false}} \ + // expected-note {{remove the condition if it is always true}} ++n) { if (maybe()) { x = n; break; } } - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{97:8-97:13}:"" +// CHECK: fix-it:"{{.*}}":{95:8-95:8}:" = 0" + + int test_for_true(int k) { int x; // expected-note {{variable}} int n = 0; for (; - n < k; // expected-note {{whenever 'for' loop is entered}} + n < k; // expected-warning {{whenever 'for' loop is entered}} \ + // expected-note {{remove the condition if it is always false}} ++n) { label: - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } x = 1; goto label; } +// CHECK: fix-it:"{{.*}}":{116:8-116:13}:"false" +// CHECK: fix-it:"{{.*}}":{113:8-113:8}:" = 0" + + int test_for_range_false(int k) { int arr[3] = { 1, 2, 3 }; - int x; // expected-note {{variable}} - for (int &a : arr) { // expected-note {{whenever 'for' loop exits because its condition is false}} + int x; + for (int &a : arr) { // no-warning, condition was not explicitly specified if (a == k) { x = &a - arr; break; } } - return x; // expected-warning {{sometimes uninit}} + return x; } + + + + int test_for_range_true(int k) { int arr[3] = { 1, 2, 3 }; - int x; // expected-note {{variable}} - for (int &a : arr) { // expected-note {{whenever 'for' loop is entered}} + int x; + for (int &a : arr) { // no-warning goto label; } x = 0; label: - return x; // expected-warning {{sometimes uninit}} + return x; } + + + + int test_conditional_false(int k) { int x; // expected-note {{variable}} (void)( - maybe() // expected-note {{whenever '?:' condition is false}} + maybe() // expected-warning {{whenever '?:' condition is false}} \ + // expected-note {{remove the '?:' if its condition is always true}} ? x = 1 : 0); - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{164:7-166:9}:"" +// CHECK: fix-it:"{{.*}}":{166:14-166:18}:"" +// CHECK: fix-it:"{{.*}}":{162:8-162:8}:" = 0" + int test_conditional_true(int k) { int x; // expected-note {{variable}} (void)( - maybe() // expected-note {{whenever '?:' condition is true}} + maybe() // expected-warning {{whenever '?:' condition is true}} \ + // expected-note {{remove the '?:' if its condition is always false}} ? 0 : x = 1); - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{177:7-179:13}:"" +// CHECK: fix-it:"{{.*}}":{175:8-175:8}:" = 0" + + int test_logical_and_false(int k) { int x; // expected-note {{variable}} - maybe() // expected-note {{whenever '&&' condition is false}} + maybe() // expected-warning {{whenever '&&' condition is false}} \ + // expected-note {{remove the '&&' if its condition is always true}} && (x = 1); - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{189:3-191:9}:"" +// CHECK: fix-it:"{{.*}}":{188:8-188:8}:" = 0" + + int test_logical_and_true(int k) { int x; // expected-note {{variable}} - maybe() // expected-note {{whenever '&&' condition is true}} + maybe() // expected-warning {{whenever '&&' condition is true}} \ + // expected-note {{remove the '&&' if its condition is always false}} && ({ goto skip_init; 0; }); x = 1; skip_init: - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{201:3-203:34}:"false" +// CHECK: fix-it:"{{.*}}":{200:8-200:8}:" = 0" + + int test_logical_or_false(int k) { int x; // expected-note {{variable}} - maybe() // expected-note {{whenever '||' condition is false}} + maybe() // expected-warning {{whenever '||' condition is false}} \ + // expected-note {{remove the '||' if its condition is always true}} || ({ goto skip_init; 0; }); x = 1; skip_init: - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{215:3-217:34}:"true" +// CHECK: fix-it:"{{.*}}":{214:8-214:8}:" = 0" + + int test_logical_or_true(int k) { int x; // expected-note {{variable}} - maybe() // expected-note {{whenever '||' condition is true}} + maybe() // expected-warning {{whenever '||' condition is true}} \ + // expected-note {{remove the '||' if its condition is always false}} || (x = 1); - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{229:3-231:9}:"" +// CHECK: fix-it:"{{.*}}":{228:8-228:8}:" = 0" + + int test_switch_case(int k) { int x; // expected-note {{variable}} switch (k) { case 0: x = 0; break; - case 1: // expected-note {{whenever switch case is taken}} + case 1: // expected-warning {{whenever switch case is taken}} break; } - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{240:8-240:8}:" = 0" + + + int test_switch_default(int k) { int x; // expected-note {{variable}} switch (k) { @@ -177,12 +261,16 @@ int test_switch_default(int k) { case 1: x = 1; break; - default: // expected-note {{whenever switch default is taken}} + default: // expected-warning {{whenever switch default is taken}} break; } - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note {{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{256:8-256:8}:" = 0" + + + int test_switch_suppress_1(int k) { int x; switch (k) { @@ -196,6 +284,10 @@ int test_switch_suppress_1(int k) { return x; // no-warning } + + + + int test_switch_suppress_2(int k) { int x; switch (k) { @@ -214,22 +306,32 @@ int test_switch_suppress_2(int k) { return x; // no-warning } + + + + int test_multiple_notes(int k) { int x; // expected-note {{variable}} if (k > 0) { if (k == 5) x = 1; - else if (k == 2) // expected-note {{whenever 'if' condition is false}} + else if (k == 2) // expected-warning {{whenever 'if' condition is false}} \ + // expected-note {{remove the 'if' if its condition is always true}} x = 2; } else { if (k == -5) x = 3; - else if (k == -2) // expected-note {{whenever 'if' condition is false}} + else if (k == -2) // expected-warning {{whenever 'if' condition is false}} \ + // expected-note {{remove the 'if' if its condition is always true}} x = 4; } - return x; // expected-warning {{sometimes uninit}} + return x; // expected-note 2{{uninitialized use}} } +// CHECK: fix-it:"{{.*}}":{324:10-326:7}:"" +// CHECK: fix-it:"{{.*}}":{318:10-320:7}:"" +// CHECK: fix-it:"{{.*}}":{314:8-314:8}:" = 0" + int test_no_false_positive_1(int k) { int x; if (k) @@ -239,6 +341,10 @@ int test_no_false_positive_1(int k) { return x; } + + + + int test_no_false_positive_2() { int x; bool b = false; @@ -249,10 +355,17 @@ int test_no_false_positive_2() { return b ? x : 0; } + + + + void test_null_pred_succ() { int x; // expected-note {{variable}} - if (0) // expected-note {{whenever}} + if (0) // expected-warning {{whenever}} expected-note {{remove}} foo: x = 0; - if (x) // expected-warning {{sometimes uninit}} + if (x) // expected-note {{uninitialized use}} goto foo; } + +// CHECK: fix-it:"{{.*}}":{364:3-365:5}:"" +// CHECK: fix-it:"{{.*}}":{363:8-363:8}:" = 0" diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c index 1be8da8148..ef03d44d97 100644 --- a/test/Sema/uninit-variables.c +++ b/test/Sema/uninit-variables.c @@ -39,9 +39,10 @@ int test6() { int test7(int y) { int x; // expected-note{{initialize the variable 'x' to silence this warning}} - if (y) // expected-note{{uninitialized use occurs whenever 'if' condition is false}} + if (y) // expected-warning{{variable 'x' is used uninitialized whenever 'if' condition is false}} \ + // expected-note{{remove the 'if' if its condition is always true}} x = 1; - return x; // expected-warning{{variable 'x' is sometimes uninitialized when used here}} + return x; // expected-note{{uninitialized use occurs here}} } int test7b(int y) { @@ -294,8 +295,9 @@ int test40(int x) { int test41(int x) { int y; // expected-note{{initialize the variable 'y' to silence this warning}} - if (x) y = 1; // expected-note{{uninitialized use occurs whenever 'if' condition is false}} - return y; // expected-warning {{variable 'y' is sometimes uninitialized when used here}} + if (x) y = 1; // expected-warning{{variable 'y' is used uninitialized whenever 'if' condition is false}} \ + // expected-note{{remove the 'if' if its condition is always true}} + return y; // expected-note{{uninitialized use occurs here}} } void test42() { -- 2.40.0