Skip to content

Commit e5ded95

Browse files
committed
[Sema] Diagnose use of if/else-if condition variable inside else-if/else branch(s)
1 parent a53a5ed commit e5ded95

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13594,6 +13594,9 @@ def warn_acc_var_referenced_lacks_op
1359413594
"reference has no effect">,
1359513595
InGroup<DiagGroup<"openacc-var-lacks-operation">>,
1359613596
DefaultError;
13597+
def warn_out_of_scope_var_usage
13598+
: Warning<"variable %0 declared in 'if' block is either false or null">,
13599+
InGroup<DiagGroup<"conditional-scope">>;
1359713600

1359813601
// AMDGCN builtins diagnostics
1359913602
def err_amdgcn_load_lds_size_invalid_value : Error<"invalid size value">;

clang/lib/Sema/SemaStmt.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,35 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc,
971971
if (!ConstevalOrNegatedConsteval && !elseStmt)
972972
DiagnoseEmptyStmtBody(RParenLoc, thenStmt, diag::warn_empty_if_body);
973973

974+
// Checks for if condition variable usage in else scope
975+
if (elseStmt) {
976+
if (auto* CondVar = dyn_cast_or_null<VarDecl>(Cond.get().first)) {
977+
bool usedInElse = false;
978+
std::function<bool(Stmt*)> checkForUsage = [&](Stmt *S) -> bool {
979+
if (!S) return false;
980+
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
981+
if (DRE->getDecl() == CondVar) {
982+
return true;
983+
}
984+
}
985+
986+
for (Stmt *Child: S->children()) {
987+
if (checkForUsage(Child)) {
988+
return true;
989+
}
990+
}
991+
992+
return false;
993+
};
994+
usedInElse = checkForUsage(elseStmt);
995+
996+
if (usedInElse) {
997+
Diag(elseStmt->getBeginLoc(), diag::warn_out_of_scope_var_usage)
998+
<< CondVar->getName();
999+
}
1000+
}
1001+
}
1002+
9741003
if (ConstevalOrNegatedConsteval ||
9751004
StatementKind == IfStatementKind::Constexpr) {
9761005
auto DiagnoseLikelihood = [&](const Stmt *S) {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -Wconditional-scope -DTEST_1 %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -Wconditional-scope -DTEST_2 %s
3+
// RUN: %clang_cc1 -fsyntax-only -verify -Wconditional-scope -DTEST_3 %s
4+
5+
int *get_something();
6+
int *get_something_else();
7+
int *get_something_else_again();
8+
int *get_something_else_again_now();
9+
10+
#ifdef TEST_1
11+
12+
int test() {
13+
if (int *ptr = get_something()) {
14+
return ptr[0] * ptr[0];
15+
}
16+
// expected-warning@+1{{variable ptr declared in 'if' block is either false or null}}
17+
else if (int *ptr2 = get_something_else()) {
18+
return ptr[0] * ptr2[0];
19+
}
20+
// expected-warning@+1{{variable ptr2 declared in 'if' block is either false or null}}
21+
else if (int* ptr3 = get_something_else_again()) {
22+
return ptr[0] * ptr2[0] * ptr3[0];
23+
}
24+
// expected-warning@+1{{variable ptr3 declared in 'if' block is either false or null}}
25+
else if (int *ptr4 = get_something_else_again_now()) {
26+
return ptr[0] * ptr2[0] * ptr3[0] * ptr4[0];
27+
}
28+
else {
29+
return -1;
30+
}
31+
}
32+
33+
#endif
34+
35+
#ifdef TEST_2
36+
37+
int test() {
38+
if (int *ptr = get_something()) {
39+
return ptr[0] * ptr[0];
40+
}
41+
// expected-warning@+1{{variable ptr declared in 'if' block is either false or null}}
42+
else if (int *ptr2 = get_something_else()) {
43+
return ptr2[0] * ptr2[0];
44+
}
45+
// expected-warning@+1{{variable ptr2 declared in 'if' block is either false or null}}
46+
else if (int* ptr3 = get_something_else_again()) {
47+
return ptr[0] * ptr2[0] * ptr3[0];
48+
}
49+
else {
50+
return -1;
51+
}
52+
}
53+
54+
#endif
55+
56+
#ifdef TEST_3
57+
58+
int test() {
59+
if (int *ptr = get_something()) {
60+
return ptr[0] * ptr[0];
61+
}
62+
else if (int *ptr2 = get_something_else()) {
63+
return ptr2[0] * ptr2[0];
64+
}
65+
// expected-warning@+1{{variable ptr2 declared in 'if' block is either false or null}}
66+
else if (int* ptr3 = get_something_else_again()) {
67+
return ptr2[0] * ptr2[0] * ptr3[0];
68+
}
69+
else {
70+
return -1;
71+
}
72+
}
73+
74+
#endif

0 commit comments

Comments
 (0)