https://github.com/jpjepko updated https://github.com/llvm/llvm-project/pull/178342
>From abb706af37605b5e8d664882d996e307aa2994cf Mon Sep 17 00:00:00 2001 From: John Jepko <[email protected]> Date: Wed, 28 Jan 2026 02:37:45 +0100 Subject: [PATCH 1/6] [clang] Extend -Wunused-but-set-variable to static globals This change extends -Wunused-but-set-variable to diagnose static globals within the translation unit that are assigned to within function bodies, but whose values are never used. Fixes #148361 --- clang/lib/Sema/Sema.cpp | 32 +++++++ clang/lib/Sema/SemaExpr.cpp | 6 +- clang/test/C/C2y/n3622.c | 8 +- .../Sema/warn-unused-but-set-static-global.c | 84 +++++++++++++++++++ 4 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 clang/test/Sema/warn-unused-but-set-static-global.c diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index d53527af38653..a533593f25c59 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1620,6 +1620,38 @@ void Sema::ActOnEndOfTranslationUnit() { if (Context.hasAnyFunctionEffects()) performFunctionEffectAnalysis(Context.getTranslationUnitDecl()); + // diagnose unused-but-set static globals in a deterministic order + // + // not trackings shadowing info for static globals; there's nothing to shadow + struct LocAndDiag { + SourceLocation Loc; + PartialDiagnostic PD; + }; + SmallVector<LocAndDiag, 16> DeclDiags; + auto addDiag = [&DeclDiags](SourceLocation Loc, PartialDiagnostic PD) { + DeclDiags.push_back(LocAndDiag{Loc, std::move(PD)}); + }; + + // for -Wunused-but-set-variable we only care about variables that were + // referenced by the TU end + for (const auto &Ref : RefsMinusAssignments) { + const VarDecl *VD = Ref.first; + if (VD->isFileVarDecl() && VD->getStorageClass() == SC_Static) { + DiagnoseUnusedButSetDecl(VD, addDiag); + RefsMinusAssignments.erase(VD); + } + } + + llvm::sort(DeclDiags, + [](const LocAndDiag &LHS, const LocAndDiag &RHS) -> bool { + // sorting purely for determinism; matches behavior in + // SemaDecl.cpp + return LHS.Loc.getRawEncoding() < RHS.Loc.getRawEncoding(); + }); + for (const LocAndDiag &D : DeclDiags) { + Diag(D.Loc, D.PD); + } + // Check we've noticed that we're no longer parsing the initializer for every // variable. If we miss cases, then at best we have a performance issue and // at worst a rejects-valid bug. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5795a71b5cae8..46434ce1511e5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -20257,7 +20257,11 @@ static void DoMarkVarDeclReferenced( bool UsableInConstantExpr = Var->mightBeUsableInConstantExpressions(SemaRef.Context); - if (Var->isLocalVarDeclOrParm() && !Var->hasExternalStorage()) { + bool StaticGlobalReferenced = Var->isFileVarDecl() && + Var->getStorageClass() == SC_Static && + !Var->isStaticDataMember(); + if ((Var->isLocalVarDeclOrParm() || StaticGlobalReferenced) && + !Var->hasExternalStorage()) { RefsMinusAssignments.insert({Var, 0}).first->getSecond()++; } diff --git a/clang/test/C/C2y/n3622.c b/clang/test/C/C2y/n3622.c index 95b92e8f235a8..d90b0c51d3ccf 100644 --- a/clang/test/C/C2y/n3622.c +++ b/clang/test/C/C2y/n3622.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -verify=good -pedantic -Wall -std=c2y %s -// RUN: %clang_cc1 -verify=compat,expected -pedantic -Wall -Wpre-c2y-compat -std=c2y %s -// RUN: %clang_cc1 -verify=ped,expected -pedantic -Wall -std=c23 %s -// RUN: %clang_cc1 -verify=ped,expected -pedantic -Wall -std=c17 %s +// RUN: %clang_cc1 -verify=good -pedantic -Wall -Wno-unused-but-set-variable -std=c2y %s +// RUN: %clang_cc1 -verify=compat,expected -pedantic -Wall -Wno-unused-but-set-variable -Wpre-c2y-compat -std=c2y %s +// RUN: %clang_cc1 -verify=ped,expected -pedantic -Wall -Wno-unused-but-set-variable -std=c23 %s +// RUN: %clang_cc1 -verify=ped,expected -pedantic -Wall -Wno-unused-but-set-variable -std=c17 %s // good-no-diagnostics /* WG14 N3622: Clang 22 diff --git a/clang/test/Sema/warn-unused-but-set-static-global.c b/clang/test/Sema/warn-unused-but-set-static-global.c new file mode 100644 index 0000000000000..a68136749047d --- /dev/null +++ b/clang/test/Sema/warn-unused-but-set-static-global.c @@ -0,0 +1,84 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-but-set-variable -verify %s + +static int set_unused; // expected-warning {{variable 'set_unused' set but not used}} +static int set_and_used; +static int only_used; +static int addr_taken; +extern int external_var; // no warning (external linkage) +extern int global_var; // no warning (not static) + +void f1() { + set_unused = 1; + set_and_used = 2; + + int x = set_and_used; + (void)x; + + int y = only_used; + (void)y; + + int *p = &addr_taken; + (void)p; + + external_var = 3; + global_var = 4; +} + +// test across multiple functions +static int set_used1; +static int set_used2; + +static int set1; // expected-warning {{variable 'set1' set but not used}} +static int set2; // expected-warning {{variable 'set2' set but not used}} + +void f2() { + set1 = 1; + set_used1 = 1; + + int x = set_used2; + (void)x; +} + +void f3() { + set2 = 2; + set_used2 = 2; + + int x = set_used1; + (void)x; +} + +static volatile int vol_set; // expected-warning {{variable 'vol_set' set but not used}} +void f4() { + vol_set = 1; +} + +// read and use +static int compound; // expected-warning{{variable 'compound' set but not used}} +static volatile int vol_compound; +static int unary; // expected-warning{{variable 'unary' set but not used}} +static volatile int vol_unary; +void f5() { + compound += 1; + vol_compound += 1; + unary++; + vol_unary++; +} + +struct S { + int i; +}; +static struct S s_set; // expected-warning{{variable 's_set' set but not used}} +static struct S s_used; +void f6() { + struct S t; + s_set = t; + t = s_used; +} + +// multiple assignments +static int multi; // expected-warning{{variable 'multi' set but not used}} +void f7() { + multi = 1; + multi = 2; + multi = 3; +} >From ca8f1b1da932dfe12a4f1ed5e3b73a4610c8843e Mon Sep 17 00:00:00 2001 From: John Jepko <[email protected]> Date: Wed, 28 Jan 2026 18:32:20 +0100 Subject: [PATCH 2/6] fix function ptr and namespace issues, add tests --- clang/lib/Sema/SemaExpr.cpp | 6 ++-- .../Sema/warn-unused-but-set-static-global.c | 35 +++++++++++++++++++ .../warn-unused-but-set-static-global.cpp | 28 +++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 clang/test/Sema/warn-unused-but-set-static-global.cpp diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 46434ce1511e5..0c29bb40fe6e7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -20257,9 +20257,9 @@ static void DoMarkVarDeclReferenced( bool UsableInConstantExpr = Var->mightBeUsableInConstantExpressions(SemaRef.Context); - bool StaticGlobalReferenced = Var->isFileVarDecl() && - Var->getStorageClass() == SC_Static && - !Var->isStaticDataMember(); + bool StaticGlobalReferenced = + Var->isFileVarDecl() && Var->getStorageClass() == SC_Static && + !Var->isStaticDataMember() && !Var->getType()->isFunctionPointerType(); if ((Var->isLocalVarDeclOrParm() || StaticGlobalReferenced) && !Var->hasExternalStorage()) { RefsMinusAssignments.insert({Var, 0}).first->getSecond()++; diff --git a/clang/test/Sema/warn-unused-but-set-static-global.c b/clang/test/Sema/warn-unused-but-set-static-global.c index a68136749047d..406b9af116646 100644 --- a/clang/test/Sema/warn-unused-but-set-static-global.c +++ b/clang/test/Sema/warn-unused-but-set-static-global.c @@ -1,5 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -Wunused-but-set-variable -verify %s +#define NULL (void*)0 + +void *set(int size); +void func_call(void *); + static int set_unused; // expected-warning {{variable 'set_unused' set but not used}} static int set_and_used; static int only_used; @@ -82,3 +87,33 @@ void f7() { multi = 2; multi = 3; } + +// unused pointers +static int *unused_ptr; // expected-warning{{variable 'unused_ptr' set but not used}} +static char *str_ptr; // expected-warning{{variable 'str_ptr' set but not used}} +void f8() { + unused_ptr = set(5); + str_ptr = "hello"; +} + +// used pointers +void a(void *); +static int *used_ptr; +static int *param_ptr; +static int *null_check_ptr; +void f9() { + used_ptr = set(5); + *used_ptr = 5; + + param_ptr = set(5); + func_call(param_ptr); + + null_check_ptr = set(5); + if (null_check_ptr == NULL) {} +} + +// function pointers +static void (*sandboxing_callback)(); +void SetSandboxingCallback(void (*f)()) { + sandboxing_callback = f; +} diff --git a/clang/test/Sema/warn-unused-but-set-static-global.cpp b/clang/test/Sema/warn-unused-but-set-static-global.cpp new file mode 100644 index 0000000000000..ead7599d6cc78 --- /dev/null +++ b/clang/test/Sema/warn-unused-but-set-static-global.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-but-set-variable -verify -std=c++11 %s + +namespace test { + static int set_unused; // expected-warning {{variable 'set_unused' set but not used}} + static int set_and_used; + + void f1() { + set_unused = 1; + set_and_used = 2; + int x = set_and_used; + (void)x; + } + + // function pointer in namespace + static void (*sandboxing_callback)(); + void SetSandboxingCallback(void (*f)()) { + sandboxing_callback = f; + } +} + +namespace outer { +namespace inner { +static int nested_unused; // expected-warning {{variable 'nested_unused' set but not used}} +void f2() { + nested_unused = 5; +} +} +} >From 68a66bfeefbae121948d15a8c6ef58d21b962cfe Mon Sep 17 00:00:00 2001 From: John Jepko <[email protected]> Date: Thu, 29 Jan 2026 21:56:23 +0100 Subject: [PATCH 3/6] ensure static globals only diagnosed at end of TU --- clang/lib/Sema/SemaDecl.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 907b7b367f19b..2b9218db95355 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2294,8 +2294,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (const auto *RD = dyn_cast<RecordDecl>(D)) DiagnoseUnusedNestedTypedefs(RD, addDiag); if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - DiagnoseUnusedButSetDecl(VD, addDiag); - RefsMinusAssignments.erase(VD); + // wait until end of TU to diagnose static globals + bool isStaticGlobal = + VD->isFileVarDecl() && VD->getStorageClass() == SC_Static; + if (!isStaticGlobal) { + DiagnoseUnusedButSetDecl(VD, addDiag); + RefsMinusAssignments.erase(VD); + } } } >From c06baa6cdf50a4a080c2a8570f91732ca15d02c2 Mon Sep 17 00:00:00 2001 From: John Jepko <[email protected]> Date: Mon, 2 Feb 2026 23:05:06 +0100 Subject: [PATCH 4/6] skip header-defined static globals, add tests and refactor --- clang/include/clang/AST/Decl.h | 5 +++++ clang/lib/Sema/Sema.cpp | 4 +++- clang/lib/Sema/SemaDecl.cpp | 4 +--- clang/lib/Sema/SemaExpr.cpp | 8 ++++---- .../warn-unused-but-set-static-global-header-test.c | 3 +++ .../Inputs/warn-unused-but-set-static-global-header.h | 3 +++ clang/test/Sema/warn-unused-but-set-static-global.c | 1 + 7 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c create mode 100644 clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 5c46c912186c4..3040514ab7dad 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1212,6 +1212,11 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { && !isFileVarDecl(); } + /// Returns true if a variable is a static file-scope variable. + bool isStaticFileVar() const { + return isFileVarDecl() && getStorageClass() == SC_Static; + } + /// Returns true if a variable has extern or __private_extern__ /// storage. bool hasExternalStorage() const { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index a533593f25c59..4266d073f358e 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1636,7 +1636,9 @@ void Sema::ActOnEndOfTranslationUnit() { // referenced by the TU end for (const auto &Ref : RefsMinusAssignments) { const VarDecl *VD = Ref.first; - if (VD->isFileVarDecl() && VD->getStorageClass() == SC_Static) { + // only diagnose static file vars defined in the main file to match + // -Wunused-variable behavior and avoid false positives from header vars + if (VD->isStaticFileVar() && SourceMgr.isInMainFile(VD->getLocation())) { DiagnoseUnusedButSetDecl(VD, addDiag); RefsMinusAssignments.erase(VD); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2b9218db95355..b86bff897289a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2295,9 +2295,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { DiagnoseUnusedNestedTypedefs(RD, addDiag); if (VarDecl *VD = dyn_cast<VarDecl>(D)) { // wait until end of TU to diagnose static globals - bool isStaticGlobal = - VD->isFileVarDecl() && VD->getStorageClass() == SC_Static; - if (!isStaticGlobal) { + if (!VD->isStaticFileVar()) { DiagnoseUnusedButSetDecl(VD, addDiag); RefsMinusAssignments.erase(VD); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0c29bb40fe6e7..d03f6cf4636e0 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -20257,10 +20257,10 @@ static void DoMarkVarDeclReferenced( bool UsableInConstantExpr = Var->mightBeUsableInConstantExpressions(SemaRef.Context); - bool StaticGlobalReferenced = - Var->isFileVarDecl() && Var->getStorageClass() == SC_Static && - !Var->isStaticDataMember() && !Var->getType()->isFunctionPointerType(); - if ((Var->isLocalVarDeclOrParm() || StaticGlobalReferenced) && + bool ShouldTrackForUnusedButSet = Var->isStaticFileVar() && + !Var->isStaticDataMember() && + !Var->getType()->isFunctionPointerType(); + if ((Var->isLocalVarDeclOrParm() || ShouldTrackForUnusedButSet) && !Var->hasExternalStorage()) { RefsMinusAssignments.insert({Var, 0}).first->getSecond()++; } diff --git a/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c new file mode 100644 index 0000000000000..e4c316b37d15f --- /dev/null +++ b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c @@ -0,0 +1,3 @@ +// expected-no-diagnostics +// test that header-defined static globals don't warn +#include "warn-unused-but-set-static-global-header.h" diff --git a/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h new file mode 100644 index 0000000000000..a06e9e66a34f4 --- /dev/null +++ b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h @@ -0,0 +1,3 @@ +// header file for testing that header-defined static globals don't warn +static int header_set_unused = 0; +static void header_init() { header_set_unused = 1; } diff --git a/clang/test/Sema/warn-unused-but-set-static-global.c b/clang/test/Sema/warn-unused-but-set-static-global.c index 406b9af116646..bf099d3c5759c 100644 --- a/clang/test/Sema/warn-unused-but-set-static-global.c +++ b/clang/test/Sema/warn-unused-but-set-static-global.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -Wunused-but-set-variable -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wunused-but-set-variable -I %S -verify %S/Inputs/warn-unused-but-set-static-global-header-test.c #define NULL (void*)0 >From 44c2f6f464094b547a04a66958fb2cac4e570bc8 Mon Sep 17 00:00:00 2001 From: John Jepko <[email protected]> Date: Tue, 3 Feb 2026 01:43:14 +0100 Subject: [PATCH 5/6] fix comment formatting --- clang/lib/Sema/Sema.cpp | 17 ++++++++--------- clang/lib/Sema/SemaDecl.cpp | 2 +- ...n-unused-but-set-static-global-header-test.c | 2 +- .../warn-unused-but-set-static-global-header.h | 2 +- .../Sema/warn-unused-but-set-static-global.c | 16 ++++++++-------- .../Sema/warn-unused-but-set-static-global.cpp | 2 +- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 4266d073f358e..0f0a749701615 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1620,9 +1620,8 @@ void Sema::ActOnEndOfTranslationUnit() { if (Context.hasAnyFunctionEffects()) performFunctionEffectAnalysis(Context.getTranslationUnitDecl()); - // diagnose unused-but-set static globals in a deterministic order - // - // not trackings shadowing info for static globals; there's nothing to shadow + // Diagnose unused-but-set static globals in a deterministic order. + // Not tracking shadowing info for static globals; there's nothing to shadow. struct LocAndDiag { SourceLocation Loc; PartialDiagnostic PD; @@ -1632,12 +1631,12 @@ void Sema::ActOnEndOfTranslationUnit() { DeclDiags.push_back(LocAndDiag{Loc, std::move(PD)}); }; - // for -Wunused-but-set-variable we only care about variables that were - // referenced by the TU end + // For -Wunused-but-set-variable we only care about variables that were + // referenced by the TU end. for (const auto &Ref : RefsMinusAssignments) { const VarDecl *VD = Ref.first; - // only diagnose static file vars defined in the main file to match - // -Wunused-variable behavior and avoid false positives from header vars + // Only diagnose static file vars defined in the main file to match + // -Wunused-variable behavior and avoid false positives from header vars. if (VD->isStaticFileVar() && SourceMgr.isInMainFile(VD->getLocation())) { DiagnoseUnusedButSetDecl(VD, addDiag); RefsMinusAssignments.erase(VD); @@ -1646,8 +1645,8 @@ void Sema::ActOnEndOfTranslationUnit() { llvm::sort(DeclDiags, [](const LocAndDiag &LHS, const LocAndDiag &RHS) -> bool { - // sorting purely for determinism; matches behavior in - // SemaDecl.cpp + // Sorting purely for determinism; matches behavior in + // SemaDecl.cpp. return LHS.Loc.getRawEncoding() < RHS.Loc.getRawEncoding(); }); for (const LocAndDiag &D : DeclDiags) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b86bff897289a..82f56b60aef65 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2294,7 +2294,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (const auto *RD = dyn_cast<RecordDecl>(D)) DiagnoseUnusedNestedTypedefs(RD, addDiag); if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - // wait until end of TU to diagnose static globals + // Wait until end of TU to diagnose static globals. if (!VD->isStaticFileVar()) { DiagnoseUnusedButSetDecl(VD, addDiag); RefsMinusAssignments.erase(VD); diff --git a/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c index e4c316b37d15f..f26c90733a2bd 100644 --- a/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c +++ b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header-test.c @@ -1,3 +1,3 @@ // expected-no-diagnostics -// test that header-defined static globals don't warn +// Test that header-defined static globals don't warn. #include "warn-unused-but-set-static-global-header.h" diff --git a/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h index a06e9e66a34f4..40637d644f717 100644 --- a/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h +++ b/clang/test/Sema/Inputs/warn-unused-but-set-static-global-header.h @@ -1,3 +1,3 @@ -// header file for testing that header-defined static globals don't warn +// Header file for testing that header-defined static globals don't warn. static int header_set_unused = 0; static void header_init() { header_set_unused = 1; } diff --git a/clang/test/Sema/warn-unused-but-set-static-global.c b/clang/test/Sema/warn-unused-but-set-static-global.c index bf099d3c5759c..12679a4de8a34 100644 --- a/clang/test/Sema/warn-unused-but-set-static-global.c +++ b/clang/test/Sema/warn-unused-but-set-static-global.c @@ -10,8 +10,8 @@ static int set_unused; // expected-warning {{variable 'set_unused' set but not u static int set_and_used; static int only_used; static int addr_taken; -extern int external_var; // no warning (external linkage) -extern int global_var; // no warning (not static) +extern int external_var; // No warning (external linkage). +extern int global_var; // No warning (not static). void f1() { set_unused = 1; @@ -30,7 +30,7 @@ void f1() { global_var = 4; } -// test across multiple functions +// Test across multiple functions. static int set_used1; static int set_used2; @@ -58,7 +58,7 @@ void f4() { vol_set = 1; } -// read and use +// Read and use static int compound; // expected-warning{{variable 'compound' set but not used}} static volatile int vol_compound; static int unary; // expected-warning{{variable 'unary' set but not used}} @@ -81,7 +81,7 @@ void f6() { t = s_used; } -// multiple assignments +// Multiple assignments static int multi; // expected-warning{{variable 'multi' set but not used}} void f7() { multi = 1; @@ -89,7 +89,7 @@ void f7() { multi = 3; } -// unused pointers +// Unused pointers static int *unused_ptr; // expected-warning{{variable 'unused_ptr' set but not used}} static char *str_ptr; // expected-warning{{variable 'str_ptr' set but not used}} void f8() { @@ -97,7 +97,7 @@ void f8() { str_ptr = "hello"; } -// used pointers +// Used pointers void a(void *); static int *used_ptr; static int *param_ptr; @@ -113,7 +113,7 @@ void f9() { if (null_check_ptr == NULL) {} } -// function pointers +// Function pointers static void (*sandboxing_callback)(); void SetSandboxingCallback(void (*f)()) { sandboxing_callback = f; diff --git a/clang/test/Sema/warn-unused-but-set-static-global.cpp b/clang/test/Sema/warn-unused-but-set-static-global.cpp index ead7599d6cc78..66d20bc242ca0 100644 --- a/clang/test/Sema/warn-unused-but-set-static-global.cpp +++ b/clang/test/Sema/warn-unused-but-set-static-global.cpp @@ -11,7 +11,7 @@ namespace test { (void)x; } - // function pointer in namespace + // Function pointer in namespace. static void (*sandboxing_callback)(); void SetSandboxingCallback(void (*f)()) { sandboxing_callback = f; >From 0c837b08d43e2e47194e27013f0471c7de167285 Mon Sep 17 00:00:00 2001 From: John Jepko <[email protected]> Date: Tue, 3 Feb 2026 02:10:11 +0100 Subject: [PATCH 6/6] wait after iterating to erase decls --- clang/lib/Sema/Sema.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 0f0a749701615..86770549b9369 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1633,15 +1633,19 @@ void Sema::ActOnEndOfTranslationUnit() { // For -Wunused-but-set-variable we only care about variables that were // referenced by the TU end. + SmallVector<const VarDecl *, 16> DeclsToErase; for (const auto &Ref : RefsMinusAssignments) { const VarDecl *VD = Ref.first; // Only diagnose static file vars defined in the main file to match // -Wunused-variable behavior and avoid false positives from header vars. if (VD->isStaticFileVar() && SourceMgr.isInMainFile(VD->getLocation())) { DiagnoseUnusedButSetDecl(VD, addDiag); - RefsMinusAssignments.erase(VD); + DeclsToErase.push_back(VD); } } + for (const VarDecl *VD : DeclsToErase) { + RefsMinusAssignments.erase(VD); + } llvm::sort(DeclDiags, [](const LocAndDiag &LHS, const LocAndDiag &RHS) -> bool { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
