diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7925,6 +7925,7 @@ 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 @@ 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 @@ 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 --- 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 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;