Skip to content

Commit 8363b0a

Browse files
authored
[clang-tidy] add AllowedTypes option to misc-const-correctness (#122951)
Add option `AllowedTypes` which allow users to specify types they want to exclude from const-correctness check. Small real-world example: ```cpp #include <mutex> int main() { std::mutex m; std::lock_guard<std::mutex> l(m); // we want to ignore it since std::lock_guard is already immutable. } ``` Closes issue #122592
1 parent 5f8b256 commit 8363b0a

File tree

5 files changed

+228
-16
lines changed

5 files changed

+228
-16
lines changed

clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "ConstCorrectnessCheck.h"
1010
#include "../utils/FixItHintUtils.h"
11+
#include "../utils/Matchers.h"
12+
#include "../utils/OptionsUtils.h"
1113
#include "clang/AST/ASTContext.h"
1214
#include "clang/ASTMatchers/ASTMatchFinder.h"
1315
#include "clang/ASTMatchers/ASTMatchers.h"
@@ -41,7 +43,9 @@ ConstCorrectnessCheck::ConstCorrectnessCheck(StringRef Name,
4143
TransformValues(Options.get("TransformValues", true)),
4244
TransformReferences(Options.get("TransformReferences", true)),
4345
TransformPointersAsValues(
44-
Options.get("TransformPointersAsValues", false)) {
46+
Options.get("TransformPointersAsValues", false)),
47+
AllowedTypes(
48+
utils::options::parseStringList(Options.get("AllowedTypes", ""))) {
4549
if (AnalyzeValues == false && AnalyzeReferences == false)
4650
this->configurationDiag(
4751
"The check 'misc-const-correctness' will not "
@@ -57,6 +61,8 @@ void ConstCorrectnessCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
5761
Options.store(Opts, "TransformValues", TransformValues);
5862
Options.store(Opts, "TransformReferences", TransformReferences);
5963
Options.store(Opts, "TransformPointersAsValues", TransformPointersAsValues);
64+
Options.store(Opts, "AllowedTypes",
65+
utils::options::serializeStringList(AllowedTypes));
6066
}
6167

6268
void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) {
@@ -73,6 +79,12 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) {
7379
hasType(referenceType(pointee(hasCanonicalType(templateTypeParmType())))),
7480
hasType(referenceType(pointee(substTemplateTypeParmType()))));
7581

82+
const auto AllowedType = hasType(qualType(anyOf(
83+
hasDeclaration(namedDecl(matchers::matchesAnyListedName(AllowedTypes))),
84+
references(namedDecl(matchers::matchesAnyListedName(AllowedTypes))),
85+
pointerType(pointee(hasDeclaration(
86+
namedDecl(matchers::matchesAnyListedName(AllowedTypes))))))));
87+
7688
const auto AutoTemplateType = varDecl(
7789
anyOf(hasType(autoType()), hasType(referenceType(pointee(autoType()))),
7890
hasType(pointerType(pointee(autoType())))));
@@ -87,7 +99,8 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) {
8799
unless(anyOf(ConstType, ConstReference, TemplateType,
88100
hasInitializer(isInstantiationDependent()), AutoTemplateType,
89101
RValueReference, FunctionPointerRef,
90-
hasType(cxxRecordDecl(isLambda())), isImplicit())));
102+
hasType(cxxRecordDecl(isLambda())), isImplicit(),
103+
AllowedType)));
91104

92105
// Match the function scope for which the analysis of all local variables
93106
// shall be run.

clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ConstCorrectnessCheck : public ClangTidyCheck {
4545
const bool TransformValues;
4646
const bool TransformReferences;
4747
const bool TransformPointersAsValues;
48+
const std::vector<StringRef> AllowedTypes;
4849
};
4950

5051
} // namespace clang::tidy::misc

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ Changes in existing checks
106106
<clang-tidy/checks/bugprone/unsafe-functions>` check to allow specifying
107107
additional C++ member functions to match.
108108

109+
- Improved :doc:`misc-const-correctness
110+
<clang-tidy/checks/misc/const-correctness>` check by adding the option
111+
`AllowedTypes`, that excludes specified types from const-correctness
112+
checking.
113+
109114
- Improved :doc:`misc-redundant-expression
110115
<clang-tidy/checks/misc/redundant-expression>` check by providing additional
111116
examples and fixing some macro related false positives.

clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ This limitation affects the capability to add ``const`` to methods which is not
8080
Options
8181
-------
8282

83-
.. option:: AnalyzeValues (default = true)
83+
.. option:: AnalyzeValues
8484

85-
Enable or disable the analysis of ordinary value variables, like ``int i = 42;``
85+
Enable or disable the analysis of ordinary value variables, like
86+
``int i = 42;``. Default is `true`.
8687

8788
.. code-block:: c++
8889

@@ -96,9 +97,10 @@ Options
9697
// No warning
9798
int const a[] = {42, 42, 42};
9899

99-
.. option:: AnalyzeReferences (default = true)
100+
.. option:: AnalyzeReferences
100101

101-
Enable or disable the analysis of reference variables, like ``int &ref = i;``
102+
Enable or disable the analysis of reference variables, like
103+
``int &ref = i;``. Default is `true`.
102104

103105
.. code-block:: c++
104106

@@ -108,11 +110,11 @@ Options
108110
// No warning
109111
int const& ref = i;
110112

111-
.. option:: WarnPointersAsValues (default = false)
113+
.. option:: WarnPointersAsValues
112114

113115
This option enables the suggestion for ``const`` of the pointer itself.
114116
Pointer values have two possibilities to be ``const``, the pointer
115-
and the value pointing to.
117+
and the value pointing to. Default is `false`.
116118

117119
.. code-block:: c++
118120

@@ -123,9 +125,10 @@ Options
123125
// No warning
124126
const int *const pointer_variable = &value;
125127
126-
.. option:: TransformValues (default = true)
128+
.. option:: TransformValues
127129

128-
Provides fixit-hints for value types that automatically add ``const`` if its a single declaration.
130+
Provides fixit-hints for value types that automatically add ``const`` if
131+
its a single declaration. Default is `true`.
129132

130133
.. code-block:: c++
131134

@@ -143,10 +146,10 @@ Options
143146
int result = value * 3;
144147
result -= 10;
145148

146-
.. option:: TransformReferences (default = true)
149+
.. option:: TransformReferences
147150

148-
Provides fixit-hints for reference types that automatically add ``const`` if its a single
149-
declaration.
151+
Provides fixit-hints for reference types that automatically add ``const`` if
152+
its a single declaration. Default is `true`.
150153

151154
.. code-block:: c++
152155

@@ -163,10 +166,10 @@ Options
163166
int result = ref_value * 3;
164167
result -= 10;
165168

166-
.. option:: TransformPointersAsValues (default = false)
169+
.. option:: TransformPointersAsValues
167170

168-
Provides fixit-hints for pointers if their pointee is not changed. This does not analyze if the
169-
value-pointed-to is unchanged!
171+
Provides fixit-hints for pointers if their pointee is not changed. This does
172+
not analyze if the value-pointed-to is unchanged! Default is `false`.
170173

171174
Requires 'WarnPointersAsValues' to be 'true'.
172175

@@ -196,3 +199,13 @@ Options
196199
// The following pointer may not become a 'int *const'.
197200
int *changing_pointee = &value;
198201
changing_pointee = &result;
202+
203+
.. option:: AllowedTypes
204+
205+
A semicolon-separated list of names of types that will be excluded from
206+
const-correctness checking. Regular expressions are accepted, e.g.
207+
``[Rr]ef(erence)?$`` matches every type with suffix ``Ref``, ``ref``,
208+
``Reference`` and ``reference``. If a name in the list contains the sequence
209+
`::`, it is matched against the qualified type name
210+
(i.e. ``namespace::Type``), otherwise it is matched against only the type
211+
name (i.e. ``Type``). Default is empty string.
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// RUN: %check_clang_tidy %s misc-const-correctness %t -- \
2+
// RUN: -config="{CheckOptions: {\
3+
// RUN: misc-const-correctness.AllowedTypes: '[Pp]ointer$;[Pp]tr$;[Rr]ef(erence)?$;qualified::Type;::fully::QualifiedType;ConstTemplate', \
4+
// RUN: misc-const-correctness.TransformPointersAsValues: true, \
5+
// RUN: misc-const-correctness.TransformReferences: true, \
6+
// RUN: misc-const-correctness.WarnPointersAsValues: true } \
7+
// RUN: }" -- -fno-delayed-template-parsing
8+
9+
struct SmartPointer {
10+
};
11+
12+
struct smart_pointer {
13+
};
14+
15+
struct SmartPtr {
16+
};
17+
18+
struct smart_ptr {
19+
};
20+
21+
struct SmartReference {
22+
};
23+
24+
struct smart_reference {
25+
};
26+
27+
struct SmartRef {
28+
};
29+
30+
struct smart_ref {
31+
};
32+
33+
struct OtherType {
34+
};
35+
36+
template <typename T> struct ConstTemplate {
37+
};
38+
39+
namespace qualified {
40+
struct Type {
41+
};
42+
} // namespace qualified
43+
44+
namespace fully {
45+
struct QualifiedType {
46+
};
47+
} // namespace fully
48+
49+
void negativeSmartPointer() {
50+
SmartPointer p1 = {};
51+
SmartPointer* p2 = {};
52+
SmartPointer& p3 = p1;
53+
}
54+
55+
void negative_smart_pointer() {
56+
smart_pointer p1 = {};
57+
smart_pointer* p2 = {};
58+
smart_pointer& p3 = p1;
59+
}
60+
61+
void negativeSmartPtr() {
62+
SmartPtr p1 = {};
63+
SmartPtr* p2 = {};
64+
SmartPtr& p3 = p1;
65+
}
66+
67+
void negative_smart_ptr() {
68+
smart_ptr p1 = {};
69+
smart_ptr* p2 = {};
70+
smart_ptr& p3 = p1;
71+
}
72+
73+
void negativeSmartReference() {
74+
SmartReference p1 = {};
75+
SmartReference* p2 = {};
76+
SmartReference& p3 = p1;
77+
}
78+
79+
void negative_smart_reference() {
80+
smart_reference p1 = {};
81+
smart_reference* p2 = {};
82+
smart_reference& p3 = p1;
83+
}
84+
85+
void negativeSmartRef() {
86+
SmartRef p1 = {};
87+
SmartRef* p2 = {};
88+
SmartRef& p3 = p1;
89+
}
90+
91+
void negative_smart_ref() {
92+
smart_ref p1 = {};
93+
smart_ref* p2 = {};
94+
smart_ref& p3 = p1;
95+
}
96+
97+
void positiveOtherType() {
98+
OtherType t = {};
99+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 't' of type 'OtherType' can be declared 'const'
100+
// CHECK-FIXES: OtherType const t = {};
101+
}
102+
103+
void negativeSomeComplex() {
104+
ConstTemplate<int> t1 = {};
105+
ConstTemplate<int>* t2 = {};
106+
ConstTemplate<int>& t3 = t1;
107+
}
108+
109+
void negativeQualified() {
110+
qualified::Type t1 = {};
111+
qualified::Type* t2 = {};
112+
qualified::Type& t3 = t1;
113+
114+
using qualified::Type;
115+
Type t4 = {};
116+
Type* t5 = {};
117+
Type& t6 = t4;
118+
}
119+
120+
void negativeFullyQualified() {
121+
fully::QualifiedType t1 = {};
122+
fully::QualifiedType* t2 = {};
123+
fully::QualifiedType& t3 = t1;
124+
125+
using fully::QualifiedType;
126+
QualifiedType t4 = {};
127+
QualifiedType* t5 = {};
128+
QualifiedType& t6 = t4;
129+
}
130+
131+
using MySP = SmartPointer;
132+
using MyTemplate = ConstTemplate<int>;
133+
template <typename T> using MyTemplate2 = ConstTemplate<T>;
134+
135+
void positiveTypedefs() {
136+
MySP p1 = {};
137+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p1' of type 'MySP' (aka 'SmartPointer') can be declared 'const'
138+
// CHECK-FIXES: MySP const p1 = {};
139+
140+
MySP* p2 = {};
141+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p2' of type 'MySP *' (aka 'SmartPointer *') can be declared 'const'
142+
// CHECK-FIXES: MySP* const p2 = {};
143+
144+
MySP& p3 = p1;
145+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p3' of type 'MySP &' (aka 'SmartPointer &') can be declared 'const'
146+
// CHECK-FIXES: MySP const& p3 = p1;
147+
148+
MyTemplate t1 = {};
149+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 't1' of type 'MyTemplate' (aka 'ConstTemplate<int>') can be declared 'const'
150+
// CHECK-FIXES: MyTemplate const t1 = {};
151+
152+
MyTemplate* t2 = {};
153+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 't2' of type 'MyTemplate *' (aka 'ConstTemplate<int> *') can be declared 'const'
154+
// CHECK-FIXES: MyTemplate* const t2 = {};
155+
156+
MyTemplate& t3 = t1;
157+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 't3' of type 'MyTemplate &' (aka 'ConstTemplate<int> &') can be declared 'const'
158+
// CHECK-FIXES: MyTemplate const& t3 = t1;
159+
160+
MyTemplate2<int> t4 = {};
161+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 't4' of type 'MyTemplate2<int>' (aka 'ConstTemplate<int>') can be declared 'const'
162+
// CHECK-FIXES: MyTemplate2<int> const t4 = {};
163+
164+
MyTemplate2<int>* t5 = {};
165+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 't5' of type 'MyTemplate2<int> *' (aka 'ConstTemplate<int> *') can be declared 'const'
166+
// CHECK-FIXES: MyTemplate2<int>* const t5 = {};
167+
168+
MyTemplate2<int>& t6 = t4;
169+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 't6' of type 'MyTemplate2<int> &' (aka 'ConstTemplate<int> &') can be declared 'const'
170+
// CHECK-FIXES: MyTemplate2<int> const& t6 = t4;
171+
}
172+
173+
template <typename T>
174+
class Vector {};
175+
176+
void positiveSmartPtrWrapped() {
177+
Vector<SmartPtr> vec = {};
178+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'vec' of type 'Vector<SmartPtr>' can be declared 'const'
179+
// CHECK-FIXES: Vector<SmartPtr> const vec = {};
180+
}

0 commit comments

Comments
 (0)