https://github.com/arrowten created https://github.com/llvm/llvm-project/pull/156436
This patch adds a warning when variable(s) declared in if/else-if scope are used in else-if/else branch(s) >From 232cb40aecf07eeac0c9bf9a1aa302f3a55a5ee1 Mon Sep 17 00:00:00 2001 From: arrowten <[email protected]> Date: Tue, 2 Sep 2025 15:33:52 +0530 Subject: [PATCH] [Sema] Diagnose use of if/else-if condition variable inside else-if/else branch(s) --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/Sema/SemaStmt.cpp | 29 +++++++++++++++++++ clang/test/Sema/warn-conditional-scope.cpp | 23 +++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 clang/test/Sema/warn-conditional-scope.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c934fed2c7462..3d370d46480d5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13594,6 +13594,9 @@ def warn_acc_var_referenced_lacks_op "reference has no effect">, InGroup<DiagGroup<"openacc-var-lacks-operation">>, DefaultError; +def warn_out_of_scope_var_usage + : Warning<"variable %0 used in else/else if block is out of scope">, + InGroup<DiagGroup<"conditional-scope">>; // AMDGCN builtins diagnostics def err_amdgcn_load_lds_size_invalid_value : Error<"invalid size value">; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 5625fb359807a..f0f5c62380f30 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -25,6 +25,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" @@ -971,6 +972,34 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, if (!ConstevalOrNegatedConsteval && !elseStmt) DiagnoseEmptyStmtBody(RParenLoc, thenStmt, diag::warn_empty_if_body); + // Checks for if/else-if condition variable usage in else-if/else scope + if (elseStmt) { + VarDecl *ConditionVar = nullptr; + + if (auto *CondVar = Cond.get().first) { + ConditionVar = dyn_cast<VarDecl>(CondVar); + } + + if (ConditionVar) { + struct ElseVariableUsageChecker + : public RecursiveASTVisitor<ElseVariableUsageChecker> { + VarDecl *TargetVar; + Sema &SemaRef; + ElseVariableUsageChecker(VarDecl *Var, Sema &S) : TargetVar(Var), SemaRef(S) {} + + bool VisitDeclRefExpr(DeclRefExpr *DRE) { + if (DRE->getDecl() == TargetVar) { + SemaRef.Diag(DRE->getBeginLoc(), diag::warn_out_of_scope_var_usage) << TargetVar->getName(); + } + return true; + } + }; + + ElseVariableUsageChecker Checker(ConditionVar, *this); + Checker.TraverseStmt(elseStmt); + } + } + if (ConstevalOrNegatedConsteval || StatementKind == IfStatementKind::Constexpr) { auto DiagnoseLikelihood = [&](const Stmt *S) { diff --git a/clang/test/Sema/warn-conditional-scope.cpp b/clang/test/Sema/warn-conditional-scope.cpp new file mode 100644 index 0000000000000..3d7d1ad522fdd --- /dev/null +++ b/clang/test/Sema/warn-conditional-scope.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wconditional-scope %s + +int *get_something(); +int *get_something_else(); +int *get_something_else_again(); + +int test() { + if (int *ptr = get_something()) { + return ptr[0] * ptr[0]; + } + else if (int *ptr2 = get_something_else()) { + // expected-warning@+1{{variable ptr used in else/else if block is out of scope}} + return ptr[0] * ptr2[0]; + } + else if (int* ptr3 = get_something_else_again()) { + // expected-warning@+2{{variable ptr used in else/else if block is out of scope}} + // expected-warning@+1{{variable ptr2 used in else/else if block is out of scope}} + return ptr[0] * ptr2[0] * ptr3[0]; + } + else { + return -1; + } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
