forked from OSchip/llvm-project
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. llvm-svn: 157511
This commit is contained in:
parent
3d8edc24c7
commit
1bb8edb8ac
|
@ -102,12 +102,15 @@ int f(bool b) {
|
|||
return n;
|
||||
}
|
||||
|
||||
<b>sometimes-uninit.cpp:5:10: <span class="warning">warning:</span> variable 'n' is sometimes uninitialized when used here [-Wsometimes-uninitialized]</b>
|
||||
return n;
|
||||
<span class="caret">^</span>
|
||||
<b>sometimes-uninit.cpp:3:7: <span class="note">note:</span></b> uninitialized use occurs whenever 'if' condition is false
|
||||
<b>sometimes-uninit.cpp:3:7: <span class="warning">warning:</span> variable 'n' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]</b>
|
||||
if (b)
|
||||
<span class="caret">^</span>
|
||||
<b>sometimes-uninit.cpp:5:10: <span class="note">note:</span></b> uninitialized use occurs here
|
||||
return n;
|
||||
<span class="caret">^</span>
|
||||
<b>sometimes-uninit.cpp:3:3: <span class="note">note:</span></b> remove the 'if' if its condition is always true
|
||||
if (b)
|
||||
<span class="caret">^~~~~~</span>
|
||||
<b>sometimes-uninit.cpp:2:8: <span class="note">note:</span></b> initialize the variable 'n' to silence this warning
|
||||
int n;
|
||||
<span class="caret">^</span>
|
||||
|
|
|
@ -1178,38 +1178,31 @@ def warn_uninit_self_reference_in_init : Warning<
|
|||
"variable %0 is uninitialized when used within its own initialization">,
|
||||
InGroup<Uninitialized>;
|
||||
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<Uninitialized>, DefaultIgnore;
|
||||
def warn_sometimes_uninit_var : Warning<
|
||||
"variable %0 is sometimes uninitialized when used here">,
|
||||
InGroup<UninitializedSometimes>, DefaultIgnore;
|
||||
def warn_maybe_uninit_var :
|
||||
Warning<"variable %0 may be uninitialized when used here">,
|
||||
InGroup<UninitializedMaybe>, 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<Uninitialized>, DefaultIgnore;
|
||||
def warn_sometimes_uninit_var_captured_by_block : Warning<
|
||||
"variable %0 is sometimes uninitialized when captured by block">,
|
||||
InGroup<UninitializedSometimes>, 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<UninitializedSometimes>, DefaultIgnore;
|
||||
def warn_maybe_uninit_var : Warning<
|
||||
"variable %0 may be uninitialized when "
|
||||
"%select{used here|captured by block}1">,
|
||||
InGroup<UninitializedMaybe>, 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<Uninitialized>, 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<
|
||||
|
|
|
@ -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<IfStmt>(Term);
|
||||
DiagKind = 0;
|
||||
Str = "if";
|
||||
Range = cast<IfStmt>(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<ConditionalOperator>(Term);
|
||||
DiagKind = 0;
|
||||
Str = "?:";
|
||||
Range = cast<ConditionalOperator>(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<BinaryOperator>(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<WhileStmt>(Term)->getCond()->getSourceRange();
|
||||
RemoveDiagKind = 1;
|
||||
Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
|
||||
break;
|
||||
case Stmt::ForStmtClass:
|
||||
DiagKind = 1;
|
||||
Str = "for";
|
||||
Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
|
||||
break;
|
||||
case Stmt::CXXForRangeStmtClass:
|
||||
DiagKind = 1;
|
||||
Str = "for";
|
||||
Range = cast<CXXForRangeStmt>(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<DoStmt>(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<BlockExpr>(Use.getUser());
|
||||
if (VD->getType()->isBlockPointerType() &&
|
||||
!VD->hasAttr<BlocksAttr>())
|
||||
S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block)
|
||||
if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
|
||||
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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue