Author: Takuya Shimizu Date: 2023-08-06T16:24:09+09:00 New Revision: bd0ed0abc31fa5a49e87eeca7aa872e7f6e4d1e7
URL: https://github.com/llvm/llvm-project/commit/bd0ed0abc31fa5a49e87eeca7aa872e7f6e4d1e7 DIFF: https://github.com/llvm/llvm-project/commit/bd0ed0abc31fa5a49e87eeca7aa872e7f6e4d1e7.diff LOG: [Clang][SemaCXX] Add unused warning for variables declared in condition expressions This patch marks the declarations with initializations in condition expressions such as if (int var = init) as unreferenced so that -Wunused can warn on them. Fixes https://github.com/llvm/llvm-project/issues/61681 Reviewed By: cor3ntin Differential Revision: https://reviews.llvm.org/D152495 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaCXX/warn-unused-variables.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f03e5231215eb2..8ff9a019563447 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -121,6 +121,9 @@ Improvements to Clang's diagnostics ----------------------------------- - Clang constexpr evaluator now prints template arguments when displaying template-specialization function calls. +- Clang now warns on unused variables declared and initialized in condition + expressions. + (`#61681: <https://github.com/llvm/llvm-project/issues/61681>`_) Bug Fixes in This Version ------------------------- diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a24856b64ec92b..6ea3b88389735a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1995,7 +1995,7 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts, return false; } else if (!D->getDeclName()) { return false; - } else if (D->isReferenced() || D->isUsed()) { + } else if (D->isReferenced() || (!isa<VarDecl>(D) && D->isUsed())) { return false; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 423d5372a6f65a..ec7c146f08d2ea 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4015,6 +4015,10 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, ConditionVar, ConditionVar->getType().getNonReferenceType(), VK_LValue, ConditionVar->getLocation()); + // Ensure that `-Wunused-variable` will be emitted for condition variables + // that are not referenced later. e.g.: if (int var = init()); + ConditionVar->setReferenced(/*R=*/false); + switch (CK) { case ConditionKind::Boolean: return CheckBooleanCondition(StmtLoc, Condition.get()); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f78d46f5950360..522ec12de3d368 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5352,7 +5352,7 @@ void Sema::BuildVariableInstantiation( // will have been deferred. if (!NewVar->isInvalidDecl() && NewVar->getDeclContext()->isFunctionOrMethod() && - OldVar->getType()->isDependentType()) + OldVar->getType()->isDependentType() && !OldVar->isImplicit()) DiagnoseUnusedDecl(NewVar); } diff --git a/clang/test/SemaCXX/warn-unused-variables.cpp b/clang/test/SemaCXX/warn-unused-variables.cpp index 4db8bdf12e5de0..db33086436d3af 100644 --- a/clang/test/SemaCXX/warn-unused-variables.cpp +++ b/clang/test/SemaCXX/warn-unused-variables.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++14-extensions -Wno-c++17-extensions -verify -std=c++11 %s template<typename T> void f() { T t; t = 17; @@ -294,3 +294,115 @@ void RAIIWrapperTest() { } } // namespace gh54489 + +namespace inside_condition { + void ifs() { + if (int hoge = 0) // expected-warning {{unused variable 'hoge'}} + return; + if (const int const_hoge = 0) // expected-warning {{unused variable 'const_hoge'}} + return; + else if (int fuga = 0) + (void)fuga; + else if (int used = 1; int catched = used) // expected-warning {{unused variable 'catched'}} + return; + else if (int refed = 1; int used = refed) + (void)used; + else if (int unused1 = 2; int unused2 = 3) // expected-warning {{unused variable 'unused1'}} \ + // expected-warning {{unused variable 'unused2'}} + return; + else if (int unused = 4; int used = 5) // expected-warning {{unused variable 'unused'}} + (void)used; + else if (int used = 6; int unused = 7) // expected-warning {{unused variable 'unused'}} + (void)used; + else if (int used1 = 8; int used2 = 9) + (void)(used1 + used2); + else if (auto [a, b] = (int[2]){ 1, 2 }; 1) // expected-warning {{unused variable '[a, b]'}} + return; + else if (auto [a, b] = (int[2]){ 1, 2 }; a) + return; + } + + void fors() { + for (int i = 0;int unused = 0;); // expected-warning {{unused variable 'i'}} \ + // expected-warning {{unused variable 'unused'}} + for (int i = 0;int used = 0;) // expected-warning {{unused variable 'i'}} + (void)used; + while(int var = 1) // expected-warning {{unused variable 'var'}} + return; + } + + void whiles() { + while(int unused = 1) // expected-warning {{unused variable 'unused'}} + return; + while(int used = 1) + (void)used; + } + + + void switches() { + switch(int unused = 1) { // expected-warning {{unused variable 'unused'}} + case 1: return; + } + switch(constexpr int used = 3; int unused = 4) { // expected-warning {{unused variable 'unused'}} + case used: return; + } + switch(int used = 3; int unused = 4) { // expected-warning {{unused variable 'unused'}} + case 3: (void)used; + } + switch(constexpr int used1 = 0; constexpr int used2 = 6) { + case (used1+used2): return; + } + switch(auto [a, b] = (int[2]){ 1, 2 }; 1) { // expected-warning {{unused variable '[a, b]'}} + case 1: return; + } + switch(auto [a, b] = (int[2]){ 1, 2 }; b) { + case 1: return; + } + switch(auto [a, b] = (int[2]){ 1, 2 }; 1) { + case 1: (void)a; + } + } + template <typename T> + struct Vector { + void doIt() { + for (auto& e : elements){} // expected-warning {{unused variable 'e'}} + } + T elements[10]; + }; + void ranged_for() { + Vector<int> vector; + vector.doIt(); // expected-note {{here}} + } + + + struct RAII { + int &x; + RAII(int &ref) : x(ref) {} + ~RAII() { x = 0;} + operator int() const { return 1; } + }; + void aggregate() { + int x = 10; + int y = 10; + if (RAII var = x) {} + for(RAII var = x; RAII var2 = y;) {} + while (RAII var = x) {} + switch (RAII var = x) {} + } + + struct TrivialDtor{ + int &x; + TrivialDtor(int &ref) : x(ref) { ref = 32; } + operator int() const { return 1; } + }; + void trivial_dtor() { + int x = 10; + int y = 10; + if (TrivialDtor var = x) {} // expected-warning {{unused variable 'var'}} + for(TrivialDtor var = x; TrivialDtor var2 = y;) {} // expected-warning {{unused variable 'var'}} \ + // expected-warning {{unused variable 'var2'}} + while (TrivialDtor var = x) {} // expected-warning {{unused variable 'var'}} + switch (TrivialDtor var = x) {} // expected-warning {{unused variable 'var'}} + } + +} // namespace inside_condition _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits