Skip to content

Commit 8a68c40

Browse files
committed
[clang-tidy] Added option for disabling const qualifiers in readability-qualified-auto
Summary: Adds an option called `AddConstToQualified` to readability-qualified-auto to toggle adding const to the auto typed pointers and references. By default its enabled but in the LLVM module its disabled. Reviewers: aaron.ballman, alexfh, JonasToth, hokein, sammccall Reviewed By: aaron.ballman Subscribers: Quuxplusone, merge_guards_bot, lebedev.ri, xazax.hun, cfe-commits Tags: #clang, #clang-tools-extra Differential Revision: https://reviews.llvm.org/D73548
1 parent efcd09c commit 8a68c40

File tree

6 files changed

+110
-60
lines changed

6 files changed

+110
-60
lines changed

clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ class LLVMModule : public ClangTidyModule {
3636
"llvm-qualified-auto");
3737
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
3838
}
39+
40+
ClangTidyOptions getModuleOptions() override {
41+
ClangTidyOptions Options;
42+
Options.CheckOptions["llvm-qualified-auto.AddConstToQualified"] = "0";
43+
return Options;
44+
}
3945
};
4046

4147
// Register the LLVMTidyModule using this statically initialized variable.

clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ bool isAutoPointerConst(QualType QType) {
102102

103103
} // namespace
104104

105+
void QualifiedAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
106+
Options.store(Opts, "AddConstToQualified", AddConstToQualified);
107+
}
108+
105109
void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) {
106110
if (!getLangOpts().CPlusPlus11)
107111
return; // Auto deduction not used in 'C or C++03 and earlier', so don't
@@ -142,6 +146,8 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) {
142146
hasAnyTemplateArgument(IsBoundToType))))),
143147
"auto"),
144148
this);
149+
if (!AddConstToQualified)
150+
return;
145151
Finder->addMatcher(ExplicitSingleVarDecl(
146152
hasType(pointerType(pointee(autoType()))), "auto_ptr"),
147153
this);
@@ -177,11 +183,9 @@ void QualifiedAutoCheck::check(const MatchFinder::MatchResult &Result) {
177183
bool IsLocalVolatile = Var->getType().isLocalVolatileQualified();
178184
bool IsLocalRestrict = Var->getType().isLocalRestrictQualified();
179185

180-
if (CheckQualifier(IsLocalConst, Qualifier::Const))
181-
return;
182-
if (CheckQualifier(IsLocalVolatile, Qualifier::Volatile))
183-
return;
184-
if (CheckQualifier(IsLocalRestrict, Qualifier::Restrict))
186+
if (CheckQualifier(IsLocalConst, Qualifier::Const) ||
187+
CheckQualifier(IsLocalVolatile, Qualifier::Volatile) ||
188+
CheckQualifier(IsLocalRestrict, Qualifier::Restrict))
185189
return;
186190

187191
// Check for bridging the gap between the asterisk and name.
@@ -214,8 +218,7 @@ void QualifiedAutoCheck::check(const MatchFinder::MatchResult &Result) {
214218
<< (IsLocalRestrict ? "__restrict " : "") << Var->getName() << ReplStr;
215219

216220
for (SourceRange &Range : RemoveQualifiersRange) {
217-
Diag << FixItHint::CreateRemoval(
218-
CharSourceRange::getCharRange(Range.getBegin(), Range.getEnd()));
221+
Diag << FixItHint::CreateRemoval(CharSourceRange::getCharRange(Range));
219222
}
220223

221224
Diag << FixItHint::CreateReplacement(FixItRange, ReplStr);
@@ -247,22 +250,17 @@ void QualifiedAutoCheck::check(const MatchFinder::MatchResult &Result) {
247250
return;
248251
}
249252

250-
CharSourceRange FixItRange;
251253
if (llvm::Optional<SourceRange> TypeSpec =
252254
getTypeSpecifierLocation(Var, Result)) {
253-
FixItRange = CharSourceRange::getCharRange(*TypeSpec);
254-
if (FixItRange.isInvalid())
255+
if (TypeSpec->isInvalid() || TypeSpec->getBegin().isMacroID() ||
256+
TypeSpec->getEnd().isMacroID())
255257
return;
256-
} else
257-
return;
258-
259-
DiagnosticBuilder Diag =
260-
diag(FixItRange.getBegin(),
261-
"'auto *%0%1%2' can be declared as 'const auto *%0%1%2'")
262-
<< (Var->getType().isLocalConstQualified() ? "const " : "")
263-
<< (Var->getType().isLocalVolatileQualified() ? "volatile " : "")
264-
<< Var->getName();
265-
Diag << FixItHint::CreateReplacement(FixItRange, "const auto *");
258+
SourceLocation InsertPos = TypeSpec->getBegin();
259+
diag(InsertPos, "'auto *%0%1%2' can be declared as 'const auto *%0%1%2'")
260+
<< (Var->getType().isLocalConstQualified() ? "const " : "")
261+
<< (Var->getType().isLocalVolatileQualified() ? "volatile " : "")
262+
<< Var->getName() << FixItHint::CreateInsertion(InsertPos, "const ");
263+
}
266264
return;
267265
}
268266
if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("auto_ref")) {
@@ -272,20 +270,15 @@ void QualifiedAutoCheck::check(const MatchFinder::MatchResult &Result) {
272270
// Const isnt wrapped in the auto type, so must be declared explicitly.
273271
return;
274272

275-
CharSourceRange FixItRange;
276273
if (llvm::Optional<SourceRange> TypeSpec =
277274
getTypeSpecifierLocation(Var, Result)) {
278-
FixItRange = CharSourceRange::getCharRange(*TypeSpec);
279-
if (FixItRange.isInvalid())
275+
if (TypeSpec->isInvalid() || TypeSpec->getBegin().isMacroID() ||
276+
TypeSpec->getEnd().isMacroID())
280277
return;
281-
} else
282-
return;
283-
284-
DiagnosticBuilder Diag =
285-
diag(FixItRange.getBegin(),
286-
"'auto &%0' can be declared as 'const auto &%0'")
287-
<< Var->getName();
288-
Diag << FixItHint::CreateReplacement(FixItRange, "const auto &");
278+
SourceLocation InsertPos = TypeSpec->getBegin();
279+
diag(InsertPos, "'auto &%0' can be declared as 'const auto &%0'")
280+
<< Var->getName() << FixItHint::CreateInsertion(InsertPos, "const ");
281+
}
289282
return;
290283
}
291284
}

clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@ namespace readability {
2424
class QualifiedAutoCheck : public ClangTidyCheck {
2525
public:
2626
QualifiedAutoCheck(StringRef Name, ClangTidyContext *Context)
27-
: ClangTidyCheck(Name, Context) {}
27+
: ClangTidyCheck(Name, Context),
28+
AddConstToQualified(Options.get("AddConstToQualified", true)) {}
29+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
2830
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2931
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
32+
33+
private:
34+
const bool AddConstToQualified;
3035
};
3136

3237
} // namespace readability

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ New check aliases
104104
Changes in existing checks
105105
^^^^^^^^^^^^^^^^^^^^^^^^^^
106106

107+
- Improved :doc:`readability-qualified-auto
108+
<clang-tidy/checks/readability-qualified-about>` check now supports a
109+
`AddConstToQualified` to enable adding ``const`` qualifiers to variables
110+
typed with ``auto *`` and ``auto &``.
111+
107112
- Improved :doc:`readability-redundant-string-init
108113
<clang-tidy/checks/readability-redundant-string-init>` check now supports a
109114
`StringNames` option enabling its application to custom string classes. The

clang-tools-extra/docs/clang-tidy/checks/readability-qualified-auto.rst

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,16 @@
33
readability-qualified-auto
44
==========================
55

6-
Adds pointer and ``const`` qualifications to ``auto``-typed variables that are deduced
7-
to pointers and ``const`` pointers.
6+
Adds pointer qualifications to ``auto``-typed variables that are deduced to
7+
pointers.
88

9-
`LLVM Coding Standards <https://llvm.org/docs/CodingStandards.html>`_ advises to
10-
make it obvious if a ``auto`` typed variable is a pointer, constant pointer or
11-
constant reference. This check will transform ``auto`` to ``auto *`` when the
12-
type is deduced to be a pointer, as well as adding ``const`` when applicable to
13-
``auto`` pointers or references
9+
`LLVM Coding Standards <https://llvm.org/docs/CodingStandards.html#beware-unnecessary-copies-with-auto>`_
10+
advises to make it obvious if a ``auto`` typed variable is a pointer. This
11+
check will transform ``auto`` to ``auto *`` when the type is deduced to be a
12+
pointer.
1413

1514
.. code-block:: c++
1615

17-
for (auto &Data : MutatableContainer) {
18-
change(Data);
19-
}
20-
for (auto &Data : ConstantContainer) {
21-
observe(Data);
22-
}
2316
for (auto Data : MutatablePtrContainer) {
2417
change(*Data);
2518
}
@@ -31,34 +24,61 @@ Would be transformed into:
3124

3225
.. code-block:: c++
3326

34-
for (auto &Data : MutatableContainer) {
35-
change(Data);
36-
}
37-
for (const auto &Data : ConstantContainer) {
38-
observe(Data);
39-
}
4027
for (auto *Data : MutatablePtrContainer) {
4128
change(*Data);
4229
}
4330
for (const auto *Data : ConstantPtrContainer) {
4431
observe(*Data);
4532
}
4633
47-
Note const volatile qualified types will retain their const and volatile qualifiers.
34+
Note ``const`` ``volatile`` qualified types will retain their ``const`` and
35+
``volatile`` qualifiers. Pointers to pointers will not be fully qualified.
4836

4937
.. code-block:: c++
5038

51-
const auto Foo = cast<int *>(Baz1);
52-
const auto Bar = cast<const int *>(Baz2);
53-
volatile auto FooBar = cast<int*>(Baz3);
39+
const auto Foo = cast<int *>(Baz1);
40+
const auto Bar = cast<const int *>(Baz2);
41+
volatile auto FooBar = cast<int *>(Baz3);
42+
auto BarFoo = cast<int **>(Baz4);
5443

5544
Would be transformed into:
5645

5746
.. code-block:: c++
5847

59-
auto *const Foo = cast<int *>(Baz1);
60-
const auto *const Bar = cast<const int *>(Baz2);
61-
auto *volatile FooBar = cast<int*>(Baz3);
48+
auto *const Foo = cast<int *>(Baz1);
49+
const auto *const Bar = cast<const int *>(Baz2);
50+
auto *volatile FooBar = cast<int *>(Baz3);
51+
auto *BarFoo = cast<int **>(Baz4);
52+
53+
Options
54+
-------
55+
56+
.. option:: AddConstToQualified
57+
58+
When set to `1` the check will add const qualifiers variables defined as
59+
``auto *`` or ``auto &`` when applicable.
60+
Default value is '1'.
61+
62+
.. code-block:: c++
63+
64+
auto Foo1 = cast<const int *>(Bar1);
65+
auto *Foo2 = cast<const int *>(Bar2);
66+
auto &Foo3 = cast<const int &>(Bar3);
67+
68+
If AddConstToQualified is set to `0`, it will be transformed into:
69+
70+
.. code-block:: c++
71+
72+
const auto *Foo1 = cast<const int *>(Bar1);
73+
auto *Foo2 = cast<const int *>(Bar2);
74+
auto &Foo3 = cast<const int &>(Bar3);
75+
76+
Otherwise it will be transformed into:
77+
78+
.. code-block:: c++
79+
80+
const auto *Foo1 = cast<const int *>(Bar1);
81+
const auto *Foo2 = cast<const int *>(Bar2);
82+
const auto &Foo3 = cast<const int &>(Bar3);
6283
63-
This check helps to enforce this `LLVM Coding Standards recommendation
64-
<https://llvm.org/docs/CodingStandards.html#beware-unnecessary-copies-with-auto>`_.
84+
Note in the LLVM alias, the default value is `0`.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %check_clang_tidy %s llvm-qualified-auto %t
2+
3+
// This check just ensures by default the llvm alias doesn't add const
4+
// qualifiers to decls, so no need to copy the entire test file from
5+
// readability-qualified-auto.
6+
7+
int *getIntPtr();
8+
const int *getCIntPtr();
9+
10+
void foo() {
11+
auto NakedPtr = getIntPtr();
12+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr'
13+
// CHECK-FIXES: {{^}} auto *NakedPtr = getIntPtr();
14+
auto NakedConstPtr = getCIntPtr();
15+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedConstPtr' can be declared as 'const auto *NakedConstPtr'
16+
// CHECK-FIXES: {{^}} const auto *NakedConstPtr = getCIntPtr();
17+
auto *Ptr = getIntPtr();
18+
auto *ConstPtr = getCIntPtr();
19+
auto &NakedRef = *getIntPtr();
20+
auto &NakedConstRef = *getCIntPtr();
21+
}

0 commit comments

Comments
 (0)