[clang] 6408317 - [clang][Sema] Provide source range to several Wunused warnings
Takuya Shimizu via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 16 03:31:00 PDT 2023
Author: Takuya Shimizu
Date: 2023-06-16T19:26:53+09:00
New Revision: 64083172eea26e50c8b22b85697a825be8bda424
URL: https://github.com/llvm/llvm-project/commit/64083172eea26e50c8b22b85697a825be8bda424
DIFF: https://github.com/llvm/llvm-project/commit/64083172eea26e50c8b22b85697a825be8bda424.diff
LOG: [clang][Sema] Provide source range to several Wunused warnings
When the diagnosed function/variable is a template specialization, the source range covers the specialization arguments.
e.g.
```
warning: unused function 'func<int>' [-Wunused-function]
template <> int func<int> () {}
^~~~~~~~~
```
This comes in line with the printed text in the warning message. In the above case, `func<int>`
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D152707
Added:
clang/test/Misc/Inputs/diag-unused-source-ranges.h
clang/test/Misc/diag-unused-source-ranges.cpp
Modified:
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaDecl.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 09084176cbf41..694e07b46aaf0 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1347,10 +1347,14 @@ void Sema::ActOnEndOfTranslationUnit() {
DiagD = FD;
if (DiagD->isDeleted())
continue; // Deleted functions are supposed to be unused.
+ SourceRange DiagRange = DiagD->getLocation();
+ if (const ASTTemplateArgumentListInfo *ASTTAL =
+ DiagD->getTemplateSpecializationArgsAsWritten())
+ DiagRange.setEnd(ASTTAL->RAngleLoc);
if (DiagD->isReferenced()) {
if (isa<CXXMethodDecl>(DiagD))
Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
- << DiagD;
+ << DiagD << DiagRange;
else {
if (FD->getStorageClass() == SC_Static &&
!FD->isInlineSpecified() &&
@@ -1358,39 +1362,46 @@ void Sema::ActOnEndOfTranslationUnit() {
SourceMgr.getExpansionLoc(FD->getLocation())))
Diag(DiagD->getLocation(),
diag::warn_unneeded_static_internal_decl)
- << DiagD;
+ << DiagD << DiagRange;
else
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
- << /*function*/ 0 << DiagD;
+ << /*function*/ 0 << DiagD << DiagRange;
}
} else {
if (FD->getDescribedFunctionTemplate())
Diag(DiagD->getLocation(), diag::warn_unused_template)
- << /*function*/ 0 << DiagD;
+ << /*function*/ 0 << DiagD << DiagRange;
else
Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD)
? diag::warn_unused_member_function
: diag::warn_unused_function)
- << DiagD;
+ << DiagD << DiagRange;
}
} else {
const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
if (!DiagD)
DiagD = cast<VarDecl>(*I);
+ SourceRange DiagRange = DiagD->getLocation();
+ if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(DiagD)) {
+ if (const ASTTemplateArgumentListInfo *ASTTAL =
+ VTSD->getTemplateArgsInfo())
+ DiagRange.setEnd(ASTTAL->RAngleLoc);
+ }
if (DiagD->isReferenced()) {
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
- << /*variable*/ 1 << DiagD;
+ << /*variable*/ 1 << DiagD << DiagRange;
} else if (DiagD->getDescribedVarTemplate()) {
Diag(DiagD->getLocation(), diag::warn_unused_template)
- << /*variable*/ 1 << DiagD;
+ << /*variable*/ 1 << DiagD << DiagRange;
} else if (DiagD->getType().isConstQualified()) {
const SourceManager &SM = SourceMgr;
if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) ||
!PP.getLangOpts().IsHeaderFile)
Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
- << DiagD;
+ << DiagD << DiagRange;
} else {
- Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD;
+ Diag(DiagD->getLocation(), diag::warn_unused_variable)
+ << DiagD << DiagRange;
}
}
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 757c4c310be3d..e93f86821d846 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2151,7 +2151,8 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D, DiagReceiverTy DiagReceiver) {
else
DiagID = diag::warn_unused_variable;
- DiagReceiver(D->getLocation(), PDiag(DiagID) << D << Hint);
+ SourceLocation DiagLoc = D->getLocation();
+ DiagReceiver(DiagLoc, PDiag(DiagID) << D << Hint << SourceRange(DiagLoc));
}
void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD,
diff --git a/clang/test/Misc/Inputs/diag-unused-source-ranges.h b/clang/test/Misc/Inputs/diag-unused-source-ranges.h
new file mode 100644
index 0000000000000..e737732654102
--- /dev/null
+++ b/clang/test/Misc/Inputs/diag-unused-source-ranges.h
@@ -0,0 +1 @@
+static void thing(void) {}
diff --git a/clang/test/Misc/diag-unused-source-ranges.cpp b/clang/test/Misc/diag-unused-source-ranges.cpp
new file mode 100644
index 0000000000000..6b7fd7d263278
--- /dev/null
+++ b/clang/test/Misc/diag-unused-source-ranges.cpp
@@ -0,0 +1,124 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -Wunused -Wunused-template -Wunused-exception-parameter -Wunused-member-function -fdiagnostics-print-source-range-info %s 2>&1 | FileCheck %s --strict-whitespace
+#include "Inputs/diag-unused-source-ranges.h"
+
+#define CAT(a, b) a ## b
+
+// CHECK: :{55:15-55:20}: warning: unused exception parameter 'param'
+// CHECK-NEXT: catch (int ¶m) {}
+// CHECK-NEXT: ^~~~~{{$}}
+
+// CHECK: :{53:7-53:12}: warning: unused variable 'local'
+// CHECK-NEXT: int local = 0;
+// CHECK-NEXT: ^~~~~{{$}}
+
+// CHECK: In file included from
+// CHECK-NEXT: :{1:13-1:18}: warning: 'static' function 'thing' declared in header file should be declared 'static inline'
+// CHECK-NEXT: static void thing(void) {}
+// CHECK-NEXT: ^~~~~{{$}}
+
+namespace {
+class A {
+ // CHECK: :{[[@LINE+3]]:10-[[@LINE+3]]:14}: warning: member function 'func' is not needed
+ // CHECK-NEXT: void func() {}
+ // CHECK-NEXT: ^~~~{{$}}
+ void func() {}
+ // CHECK: :{[[@LINE+3]]:32-[[@LINE+3]]:37}: warning: unused function template
+ // CHECK-NEXT: void templ(T) {}
+ // CHECK-NEXT: ^~~~~{{$}}
+ template <typename T> void templ(T) {}
+ // CHECK: :{[[@LINE+3]]:22-[[@LINE+3]]:32}: warning: member function 'templ<int>' is not needed
+ // CHECK-NEXT: void templ<int>(int) {}
+ // CHECK-NEXT: ^~~~~~~~~~{{$}}
+ template <> void templ<int>(int) {}
+ // CHECK: :{[[@LINE+3]]:22-[[@LINE+3]]:27}: warning: member function 'templ<float>' is not needed
+ // CHECK-NEXT: void templ(float) {}
+ // CHECK-NEXT: ^~~~~{{$}}
+ template <> void templ(float) {}
+
+ // CHECK: :{[[@LINE+4]]:10-[[@LINE+4]]:13}: warning: unused function template
+ // CHECK-NEXT: void foo() {
+ // CHECK-NEXT: ^~~{{$}}
+ template <typename T>
+ void foo() {
+ func();
+ templ(0);
+ templ(0.0f);
+ templ(0.0);
+ }
+};
+// CHECK: :{[[@LINE+3]]:12-[[@LINE+3]]:23}: warning: unused function 'unused_func'
+// CHECK-NEXT: static int unused_func(int aaa, char bbb) {
+// CHECK-NEXT: ^~~~~~~~~~~{{$}}
+static int unused_func(int aaa, char bbb) {
+ int local = 0;
+ try{}
+ catch (int ¶m) {}
+ return 0;
+}
+
+// CHECK: :{[[@LINE+4]]:6-[[@LINE+4]]:16}: warning: unused function template
+// CHECK-NEXT: auto arrow_decl(T a, T b) ->
+// CHECK-NEXT: ^~~~~~~~~~{{$}}
+template <typename T>
+auto arrow_decl(T a, T b) -> decltype(a + b) { thing(); return a + b; }
+
+// CHECK: :{[[@LINE+4]]:6-[[@LINE+4]]:21}: warning: unused function 'arrow_decl<int>'
+// CHECK-NEXT: auto arrow_decl<int>(int a, int b) ->
+// CHECK-NEXT: ^~~~~~~~~~~~~~~{{$}}
+template <>
+auto arrow_decl<int>(int a, int b) -> int { return a + b; }
+
+
+// CHECK: :{[[@LINE+4]]:10-[[@LINE+4]]:20}: warning: unused function template
+// CHECK-NEXT: static T func_templ(int bbb, T ccc) {
+// CHECK-NEXT: ^~~~~~~~~~{{$}}
+template <typename T>
+static T func_templ(int bbb, T ccc) {
+ return ccc;
+}
+
+// CHECK: :{[[@LINE+3]]:17-[[@LINE+3]]:32}: warning: function 'func_templ<int>' is not needed
+// CHECK-NEXT: int func_templ<int>(int bbb, int ccc) {
+// CHECK-NEXT: ^~~~~~~~~~~~~~~{{$}}
+template <> int func_templ<int>(int bbb, int ccc) {
+ return bbb;
+}
+
+// CHECK: :{[[@LINE+3]]:35-[[@LINE+3]]:47}: warning: unused function template
+// CHECK-NEXT: static void never_called() {
+// CHECK-NEXT: ^~~~~~~~~~~~{{$}}
+template <typename T> static void never_called() {
+ func_templ<int>(0, 0);
+}
+
+// CHECK: :{[[@LINE+3]]:22-[[@LINE+3]]:31}: warning: unused variable template
+// CHECK-NEXT: int var_templ =
+// CHECK-NEXT: ^~~~~~~~~{{$}}
+template <int n> int var_templ = n * var_templ<n-1>;
+// CHECK: :{[[@LINE+3]]:17-[[@LINE+3]]:29}: warning: variable 'var_templ<0>' is not needed
+// CHECK-NEXT: int var_templ<0> =
+// CHECK-NEXT: ^~~~~~~~~~~~{{$}}
+template <> int var_templ<0> = 1;
+struct {
+// CHECK: :{[[@LINE+3]]:8-[[@LINE+3]]:11}: warning: unused member function 'fun'
+// CHECK-NEXT: void fun() {}
+// CHECK-NEXT: ^~~{{$}}
+ void fun() {}
+// CHECK: :{[[@LINE+3]]:3-[[@LINE+3]]:8}: warning: unused variable 'var_x'
+// CHECK-NEXT: } var_x;
+// CHECK-NEXT: ^~~~~{{$}}
+} var_x;
+
+// CHECK: :{[[@LINE+5]]:12-[[@LINE+6]]:12}: warning: unused variable 'new_line'
+// CHECK-NEXT: static int CAT(new_,
+// CHECK-NEXT: ^~~~~~~~~{{$}}
+// CHECK-NEXT: line) =
+// CHECK-NEXT: ~~~~~{{$}}
+static int CAT(new_,
+ line) = sizeof(var_templ<0>);
+}
+
+// CHECK: :{[[@LINE+3]]:15-[[@LINE+3]]:27}: warning: unused variable 'const_unused'
+// CHECK-NEXT: constexpr int const_unused = 1
+// CHECK-NEXT: ^~~~~~~~~~~~{{$}}
+constexpr int const_unused = 1;
More information about the cfe-commits
mailing list