Skip to content

Commit 3bec1ac

Browse files
committed
Add option to show fully qualified names of functions
1 parent e90ab99 commit 3bec1ac

File tree

4 files changed

+62
-19
lines changed

4 files changed

+62
-19
lines changed

clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ namespace clang::tidy::bugprone {
2121

2222
static constexpr llvm::StringLiteral OptionNameCustomFunctions =
2323
"CustomFunctions";
24+
static constexpr llvm::StringLiteral OptionNameShowFullyQualifiedNames =
25+
"ShowFullyQualifiedNames";
2426
static constexpr llvm::StringLiteral OptionNameReportDefaultFunctions =
2527
"ReportDefaultFunctions";
2628
static constexpr llvm::StringLiteral OptionNameReportMoreUnsafeFunctions =
@@ -185,6 +187,8 @@ UnsafeFunctionsCheck::UnsafeFunctionsCheck(StringRef Name,
185187
: ClangTidyCheck(Name, Context),
186188
CustomFunctions(parseCheckedFunctions(
187189
Options.get(OptionNameCustomFunctions, ""), Context)),
190+
ShowFullyQualifiedNames(
191+
Options.get(OptionNameShowFullyQualifiedNames, false)),
188192
ReportDefaultFunctions(
189193
Options.get(OptionNameReportDefaultFunctions, true)),
190194
ReportMoreUnsafeFunctions(
@@ -193,6 +197,8 @@ UnsafeFunctionsCheck::UnsafeFunctionsCheck(StringRef Name,
193197
void UnsafeFunctionsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
194198
Options.store(Opts, OptionNameCustomFunctions,
195199
serializeCheckedFunctions(CustomFunctions));
200+
Options.store(Opts, OptionNameShowFullyQualifiedNames,
201+
ShowFullyQualifiedNames);
196202
Options.store(Opts, OptionNameReportDefaultFunctions, ReportDefaultFunctions);
197203
Options.store(Opts, OptionNameReportMoreUnsafeFunctions,
198204
ReportMoreUnsafeFunctions);
@@ -316,6 +322,12 @@ void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) {
316322
<< SourceExpr->getSourceRange();
317323
}
318324

325+
if (ShowFullyQualifiedNames) {
326+
diag(SourceExpr->getExprLoc(),
327+
"fully qualified name of function is: '%0'", DiagnosticIDs::Note)
328+
<< FuncDecl->getQualifiedNameAsString();
329+
}
330+
319331
return;
320332
}
321333
}

clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ class UnsafeFunctionsCheck : public ClangTidyCheck {
4343
private:
4444
const std::vector<CheckedFunction> CustomFunctions;
4545

46-
// If true, the default set of functions are reported.
46+
/// If true, the fully qualified name of custom functions will be shown in a
47+
/// note tag.
48+
const bool ShowFullyQualifiedNames;
49+
/// If true, the default set of functions are reported.
4750
const bool ReportDefaultFunctions;
4851
/// If true, additional functions from widely used API-s (such as POSIX) are
4952
/// added to the list of reported functions.

clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ qualified name (i.e. ``std::original``), otherwise the regex is matched against
114114
If the regular expression starts with `::` (or `^::`), it is matched against the
115115
fully qualified name (``::std::original``).
116116

117+
To aid with finding the fully qualified names of expressions, the option ``ShowFullyQualifiedNames`` can be used.
118+
This option will show the fully qualified name of all functions matched by the custom function matchers.
119+
117120
Options
118121
-------
119122

@@ -139,6 +142,12 @@ Options
139142
function, and an optional reason, separated by comma. For more information,
140143
see :ref:`Custom functions<CustomFunctions>`.
141144

145+
.. option:: ShowFullyQualifiedNames
146+
147+
When `true`, the fully qualified name of all functions matched by the custom
148+
function matchers will be shown.
149+
Default is `false`.
150+
142151
Examples
143152
--------
144153

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %check_clang_tidy -check-suffix=NON-STRICT-REGEX %s bugprone-unsafe-functions %t --\
2-
// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '::name_match,replacement,is a qualname match;^::prefix_match,,is matched on qualname prefix;^::S::member_match_,,is matched on a C++ class member'}}"
2+
// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '::name_match,replacement,is a qualname match;^::prefix_match,,is matched on qualname prefix;^::S::member_match_,,is matched on a C++ class member', bugprone-unsafe-functions.ShowFullyQualifiedNames: true}}"
33
// RUN: %check_clang_tidy -check-suffix=STRICT-REGEX %s bugprone-unsafe-functions %t --\
44
// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '^name_match$,replacement,is matched on function name only;^::prefix_match$,,is a full qualname match;^::S::member_match_1$,,is matched on a C++ class member'}}"
55

@@ -11,6 +11,9 @@ struct S {
1111
void member_match_2() {}
1212
};
1313

14+
void member_match_1() {}
15+
void member_match_unmatched() {}
16+
1417
namespace regex_test {
1518
void name_match();
1619
void prefix_match();
@@ -21,45 +24,61 @@ void prefix_match_regex();
2124

2225
void f1() {
2326
name_match();
24-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match; 'replacement' should be used instead
25-
// CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'name_match' is matched on function name only; 'replacement' should be used instead
27+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match; 'replacement' should be used instead
28+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'name_match'
29+
// CHECK-NOTES-STRICT-REGEX: :[[@LINE-3]]:3: warning: function 'name_match' is matched on function name only; 'replacement' should be used instead
2630
prefix_match();
27-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match' is matched on qualname prefix; it should not be used
28-
// CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'prefix_match' is a full qualname match; it should not be used
31+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match' is matched on qualname prefix; it should not be used
32+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'prefix_match'
33+
// CHECK-NOTES-STRICT-REGEX: :[[@LINE-3]]:3: warning: function 'prefix_match' is a full qualname match; it should not be used
2934

3035
::name_match();
31-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match; 'replacement' should be used instead
32-
// CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'name_match' is matched on function name only; 'replacement' should be used instead
36+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match; 'replacement' should be used instead
37+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'name_match'
38+
// CHECK-NOTES-STRICT-REGEX: :[[@LINE-3]]:3: warning: function 'name_match' is matched on function name only; 'replacement' should be used instead
3339
regex_test::name_match();
34-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match; 'replacement' should be used instead
35-
// CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'name_match' is matched on function name only; 'replacement' should be used instead
40+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match; 'replacement' should be used instead
41+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'regex_test::name_match'
42+
// CHECK-NOTES-STRICT-REGEX: :[[@LINE-3]]:3: warning: function 'name_match' is matched on function name only; 'replacement' should be used instead
3643
name_match_regex();
37-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match_regex' is a qualname match; 'replacement' should be used instead
44+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match_regex' is a qualname match; 'replacement' should be used instead
45+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'name_match_regex'
3846
// no-warning STRICT-REGEX
3947

4048
::prefix_match();
41-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match' is matched on qualname prefix; it should not be used
42-
// CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'prefix_match' is a full qualname match; it should not be used
49+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match' is matched on qualname prefix; it should not be used
50+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'prefix_match'
51+
// CHECK-NOTES-STRICT-REGEX: :[[@LINE-3]]:3: warning: function 'prefix_match' is a full qualname match; it should not be used
4352
regex_test::prefix_match();
4453
// no-warning NON-STRICT-REGEX
4554
// no-warning STRICT-REGEX
4655
prefix_match_regex();
47-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match_regex' is matched on qualname prefix; it should not be used
56+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match_regex' is matched on qualname prefix; it should not be used
57+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'prefix_match_regex'
4858
// no-warning STRICT-REGEX
4959
}
5060

5161
void f2() {
5262
S s;
5363

5464
S::member_match_1();
55-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
56-
// CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
65+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
66+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:3: note: fully qualified name of function is: 'S::member_match_1'
67+
// CHECK-NOTES-STRICT-REGEX: :[[@LINE-3]]:3: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
5768

5869
s.member_match_1();
59-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:5: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
60-
// CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:5: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
70+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:5: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
71+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:5: note: fully qualified name of function is: 'S::member_match_1'
72+
// CHECK-NOTES-STRICT-REGEX: :[[@LINE-3]]:5: warning: function 'member_match_1' is matched on a C++ class member; it should not be used
6173

6274
s.member_match_2();
63-
// CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:5: warning: function 'member_match_2' is matched on a C++ class member; it should not be used
75+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-1]]:5: warning: function 'member_match_2' is matched on a C++ class member; it should not be used
76+
// CHECK-NOTES-NON-STRICT-REGEX: :[[@LINE-2]]:5: note: fully qualified name of function is: 'S::member_match_2'
6477
// no-warning STRICT-REGEX
78+
79+
member_match_1();
80+
// no-warning
81+
82+
member_match_unmatched();
83+
// no-warning
6584
}

0 commit comments

Comments
 (0)