From bdf69f63df2cf4c9e3cd1af5cfcd503bc8e2869b Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Sat, 12 Mar 2022 11:05:40 -0800 Subject: [PATCH] [Clang] Fix an unused-but-set-variable warning with volatile variable For the following code, void test() { volatile int j = 0; for (int i = 0; i < 1000; i++) j += 1; return; } If compiled with clang -g -Wall -Werror -S -emit-llvm test.c we will see the following error: test.c:2:6: error: variable 'j' set but not used [-Werror,-Wunused-but-set-variable] volatile int j = 0; ^ This is not quite right since 'j' is indeed used due to '+=' operator. gcc doesn't emit error either in this case. Also if we change 'j += 1' to 'j++', the warning will disappear with latest clang. Note that clang will issue the warning if the volatile declaration involves only simple assignment (var = ...). To fix the issue, in function MaybeDecrementCount(), if the operator is a compound assignment (i.e., +=, -=, etc.) and the variable is volatile, the count for RefsMinusAssignments will be decremented, similar to 'j++' case. Differential Revision: https://reviews.llvm.org/D121715 --- clang/lib/Sema/SemaExprCXX.cpp | 7 +++++++ clang/test/Sema/warn-unused-but-set-variables.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index ee4bff5..c923dddb 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7925,6 +7925,7 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, static void MaybeDecrementCount( Expr *E, llvm::DenseMap &RefsMinusAssignments) { DeclRefExpr *LHS = nullptr; + bool IsCompoundAssign = false; if (BinaryOperator *BO = dyn_cast(E)) { if (BO->getLHS()->getType()->isDependentType() || BO->getRHS()->getType()->isDependentType()) { @@ -7932,6 +7933,8 @@ static void MaybeDecrementCount( return; } else if (!BO->isAssignmentOp()) return; + else + IsCompoundAssign = BO->isCompoundAssignmentOp(); LHS = dyn_cast(BO->getLHS()); } else if (CXXOperatorCallExpr *COCE = dyn_cast(E)) { if (COCE->getOperator() != OO_Equal) @@ -7943,6 +7946,10 @@ static void MaybeDecrementCount( VarDecl *VD = dyn_cast(LHS->getDecl()); if (!VD) return; + // Don't decrement RefsMinusAssignments if volatile variable with compound + // assignment (+=, ...) to avoid potential unused-but-set-variable warning. + if (IsCompoundAssign && VD->getType().isVolatileQualified()) + return; auto iter = RefsMinusAssignments.find(VD); if (iter == RefsMinusAssignments.end()) return; diff --git a/clang/test/Sema/warn-unused-but-set-variables.c b/clang/test/Sema/warn-unused-but-set-variables.c index a8d2cea..6e5b7d6 100644 --- a/clang/test/Sema/warn-unused-but-set-variables.c +++ b/clang/test/Sema/warn-unused-but-set-variables.c @@ -23,10 +23,24 @@ int f0(void) { int a; w = (a = 0); + int j = 0; // expected-warning{{variable 'j' set but not used}} + for (int i = 0; i < 1000; i++) + j += 1; + // Following gcc, warn for a volatile variable. volatile int b; // expected-warning{{variable 'b' set but not used}} b = 0; + // volatile variable k is used, no warning. + volatile int k = 0; + for (int i = 0; i < 1000; i++) + k += 1; + + // typedef of volatile type, no warning. + typedef volatile int volint; + volint l = 0; + l += 1; + int x; x = 0; return x; -- 2.7.4