Skip to content

Commit 6408317

Browse files
committed
[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
1 parent 6223b1e commit 6408317

File tree

4 files changed

+147
-10
lines changed

4 files changed

+147
-10
lines changed

clang/lib/Sema/Sema.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,50 +1347,61 @@ void Sema::ActOnEndOfTranslationUnit() {
13471347
DiagD = FD;
13481348
if (DiagD->isDeleted())
13491349
continue; // Deleted functions are supposed to be unused.
1350+
SourceRange DiagRange = DiagD->getLocation();
1351+
if (const ASTTemplateArgumentListInfo *ASTTAL =
1352+
DiagD->getTemplateSpecializationArgsAsWritten())
1353+
DiagRange.setEnd(ASTTAL->RAngleLoc);
13501354
if (DiagD->isReferenced()) {
13511355
if (isa<CXXMethodDecl>(DiagD))
13521356
Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
1353-
<< DiagD;
1357+
<< DiagD << DiagRange;
13541358
else {
13551359
if (FD->getStorageClass() == SC_Static &&
13561360
!FD->isInlineSpecified() &&
13571361
!SourceMgr.isInMainFile(
13581362
SourceMgr.getExpansionLoc(FD->getLocation())))
13591363
Diag(DiagD->getLocation(),
13601364
diag::warn_unneeded_static_internal_decl)
1361-
<< DiagD;
1365+
<< DiagD << DiagRange;
13621366
else
13631367
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
1364-
<< /*function*/ 0 << DiagD;
1368+
<< /*function*/ 0 << DiagD << DiagRange;
13651369
}
13661370
} else {
13671371
if (FD->getDescribedFunctionTemplate())
13681372
Diag(DiagD->getLocation(), diag::warn_unused_template)
1369-
<< /*function*/ 0 << DiagD;
1373+
<< /*function*/ 0 << DiagD << DiagRange;
13701374
else
13711375
Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD)
13721376
? diag::warn_unused_member_function
13731377
: diag::warn_unused_function)
1374-
<< DiagD;
1378+
<< DiagD << DiagRange;
13751379
}
13761380
} else {
13771381
const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
13781382
if (!DiagD)
13791383
DiagD = cast<VarDecl>(*I);
1384+
SourceRange DiagRange = DiagD->getLocation();
1385+
if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(DiagD)) {
1386+
if (const ASTTemplateArgumentListInfo *ASTTAL =
1387+
VTSD->getTemplateArgsInfo())
1388+
DiagRange.setEnd(ASTTAL->RAngleLoc);
1389+
}
13801390
if (DiagD->isReferenced()) {
13811391
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
1382-
<< /*variable*/ 1 << DiagD;
1392+
<< /*variable*/ 1 << DiagD << DiagRange;
13831393
} else if (DiagD->getDescribedVarTemplate()) {
13841394
Diag(DiagD->getLocation(), diag::warn_unused_template)
1385-
<< /*variable*/ 1 << DiagD;
1395+
<< /*variable*/ 1 << DiagD << DiagRange;
13861396
} else if (DiagD->getType().isConstQualified()) {
13871397
const SourceManager &SM = SourceMgr;
13881398
if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) ||
13891399
!PP.getLangOpts().IsHeaderFile)
13901400
Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
1391-
<< DiagD;
1401+
<< DiagD << DiagRange;
13921402
} else {
1393-
Diag(DiagD->getLocation(), diag::warn_unused_variable) << DiagD;
1403+
Diag(DiagD->getLocation(), diag::warn_unused_variable)
1404+
<< DiagD << DiagRange;
13941405
}
13951406
}
13961407
}

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2151,7 +2151,8 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D, DiagReceiverTy DiagReceiver) {
21512151
else
21522152
DiagID = diag::warn_unused_variable;
21532153

2154-
DiagReceiver(D->getLocation(), PDiag(DiagID) << D << Hint);
2154+
SourceLocation DiagLoc = D->getLocation();
2155+
DiagReceiver(DiagLoc, PDiag(DiagID) << D << Hint << SourceRange(DiagLoc));
21552156
}
21562157

21572158
void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
static void thing(void) {}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// 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
2+
#include "Inputs/diag-unused-source-ranges.h"
3+
4+
#define CAT(a, b) a ## b
5+
6+
// CHECK: :{55:15-55:20}: warning: unused exception parameter 'param'
7+
// CHECK-NEXT: catch (int &param) {}
8+
// CHECK-NEXT: ^~~~~{{$}}
9+
10+
// CHECK: :{53:7-53:12}: warning: unused variable 'local'
11+
// CHECK-NEXT: int local = 0;
12+
// CHECK-NEXT: ^~~~~{{$}}
13+
14+
// CHECK: In file included from
15+
// CHECK-NEXT: :{1:13-1:18}: warning: 'static' function 'thing' declared in header file should be declared 'static inline'
16+
// CHECK-NEXT: static void thing(void) {}
17+
// CHECK-NEXT: ^~~~~{{$}}
18+
19+
namespace {
20+
class A {
21+
// CHECK: :{[[@LINE+3]]:10-[[@LINE+3]]:14}: warning: member function 'func' is not needed
22+
// CHECK-NEXT: void func() {}
23+
// CHECK-NEXT: ^~~~{{$}}
24+
void func() {}
25+
// CHECK: :{[[@LINE+3]]:32-[[@LINE+3]]:37}: warning: unused function template
26+
// CHECK-NEXT: void templ(T) {}
27+
// CHECK-NEXT: ^~~~~{{$}}
28+
template <typename T> void templ(T) {}
29+
// CHECK: :{[[@LINE+3]]:22-[[@LINE+3]]:32}: warning: member function 'templ<int>' is not needed
30+
// CHECK-NEXT: void templ<int>(int) {}
31+
// CHECK-NEXT: ^~~~~~~~~~{{$}}
32+
template <> void templ<int>(int) {}
33+
// CHECK: :{[[@LINE+3]]:22-[[@LINE+3]]:27}: warning: member function 'templ<float>' is not needed
34+
// CHECK-NEXT: void templ(float) {}
35+
// CHECK-NEXT: ^~~~~{{$}}
36+
template <> void templ(float) {}
37+
38+
// CHECK: :{[[@LINE+4]]:10-[[@LINE+4]]:13}: warning: unused function template
39+
// CHECK-NEXT: void foo() {
40+
// CHECK-NEXT: ^~~{{$}}
41+
template <typename T>
42+
void foo() {
43+
func();
44+
templ(0);
45+
templ(0.0f);
46+
templ(0.0);
47+
}
48+
};
49+
// CHECK: :{[[@LINE+3]]:12-[[@LINE+3]]:23}: warning: unused function 'unused_func'
50+
// CHECK-NEXT: static int unused_func(int aaa, char bbb) {
51+
// CHECK-NEXT: ^~~~~~~~~~~{{$}}
52+
static int unused_func(int aaa, char bbb) {
53+
int local = 0;
54+
try{}
55+
catch (int &param) {}
56+
return 0;
57+
}
58+
59+
// CHECK: :{[[@LINE+4]]:6-[[@LINE+4]]:16}: warning: unused function template
60+
// CHECK-NEXT: auto arrow_decl(T a, T b) ->
61+
// CHECK-NEXT: ^~~~~~~~~~{{$}}
62+
template <typename T>
63+
auto arrow_decl(T a, T b) -> decltype(a + b) { thing(); return a + b; }
64+
65+
// CHECK: :{[[@LINE+4]]:6-[[@LINE+4]]:21}: warning: unused function 'arrow_decl<int>'
66+
// CHECK-NEXT: auto arrow_decl<int>(int a, int b) ->
67+
// CHECK-NEXT: ^~~~~~~~~~~~~~~{{$}}
68+
template <>
69+
auto arrow_decl<int>(int a, int b) -> int { return a + b; }
70+
71+
72+
// CHECK: :{[[@LINE+4]]:10-[[@LINE+4]]:20}: warning: unused function template
73+
// CHECK-NEXT: static T func_templ(int bbb, T ccc) {
74+
// CHECK-NEXT: ^~~~~~~~~~{{$}}
75+
template <typename T>
76+
static T func_templ(int bbb, T ccc) {
77+
return ccc;
78+
}
79+
80+
// CHECK: :{[[@LINE+3]]:17-[[@LINE+3]]:32}: warning: function 'func_templ<int>' is not needed
81+
// CHECK-NEXT: int func_templ<int>(int bbb, int ccc) {
82+
// CHECK-NEXT: ^~~~~~~~~~~~~~~{{$}}
83+
template <> int func_templ<int>(int bbb, int ccc) {
84+
return bbb;
85+
}
86+
87+
// CHECK: :{[[@LINE+3]]:35-[[@LINE+3]]:47}: warning: unused function template
88+
// CHECK-NEXT: static void never_called() {
89+
// CHECK-NEXT: ^~~~~~~~~~~~{{$}}
90+
template <typename T> static void never_called() {
91+
func_templ<int>(0, 0);
92+
}
93+
94+
// CHECK: :{[[@LINE+3]]:22-[[@LINE+3]]:31}: warning: unused variable template
95+
// CHECK-NEXT: int var_templ =
96+
// CHECK-NEXT: ^~~~~~~~~{{$}}
97+
template <int n> int var_templ = n * var_templ<n-1>;
98+
// CHECK: :{[[@LINE+3]]:17-[[@LINE+3]]:29}: warning: variable 'var_templ<0>' is not needed
99+
// CHECK-NEXT: int var_templ<0> =
100+
// CHECK-NEXT: ^~~~~~~~~~~~{{$}}
101+
template <> int var_templ<0> = 1;
102+
struct {
103+
// CHECK: :{[[@LINE+3]]:8-[[@LINE+3]]:11}: warning: unused member function 'fun'
104+
// CHECK-NEXT: void fun() {}
105+
// CHECK-NEXT: ^~~{{$}}
106+
void fun() {}
107+
// CHECK: :{[[@LINE+3]]:3-[[@LINE+3]]:8}: warning: unused variable 'var_x'
108+
// CHECK-NEXT: } var_x;
109+
// CHECK-NEXT: ^~~~~{{$}}
110+
} var_x;
111+
112+
// CHECK: :{[[@LINE+5]]:12-[[@LINE+6]]:12}: warning: unused variable 'new_line'
113+
// CHECK-NEXT: static int CAT(new_,
114+
// CHECK-NEXT: ^~~~~~~~~{{$}}
115+
// CHECK-NEXT: line) =
116+
// CHECK-NEXT: ~~~~~{{$}}
117+
static int CAT(new_,
118+
line) = sizeof(var_templ<0>);
119+
}
120+
121+
// CHECK: :{[[@LINE+3]]:15-[[@LINE+3]]:27}: warning: unused variable 'const_unused'
122+
// CHECK-NEXT: constexpr int const_unused = 1
123+
// CHECK-NEXT: ^~~~~~~~~~~~{{$}}
124+
constexpr int const_unused = 1;

0 commit comments

Comments
 (0)