Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,13 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) {
hasType(referenceType(pointee(hasCanonicalType(templateTypeParmType())))),
hasType(referenceType(pointee(substTemplateTypeParmType()))));

auto AllowedTypeDecl = namedDecl(
const auto AllowedTypeDecl = namedDecl(
anyOf(matchers::matchesAnyListedName(AllowedTypes), usingShadowDecl()));

const auto AllowedType = hasType(qualType(
anyOf(hasDeclaration(AllowedTypeDecl), references(AllowedTypeDecl),
pointerType(pointee(hasDeclaration(AllowedTypeDecl))))));

const auto AutoTemplateType = varDecl(
anyOf(hasType(autoType()), hasType(referenceType(pointee(autoType()))),
hasType(pointerType(pointee(autoType())))));

const auto FunctionPointerRef =
hasType(hasCanonicalType(referenceType(pointee(functionType()))));

Expand All @@ -117,10 +113,8 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) {
const auto LocalValDecl = varDecl(
isLocal(), hasInitializer(anything()),
unless(anyOf(ConstType, ConstReference, TemplateType,
hasInitializer(isInstantiationDependent()), AutoTemplateType,
RValueReference, FunctionPointerRef,
hasType(cxxRecordDecl(isLambda())), isImplicit(),
AllowedType)));
hasInitializer(isInstantiationDependent()), RValueReference,
FunctionPointerRef, isImplicit(), AllowedType)));

// Match the function scope for which the analysis of all local variables
// shall be run.
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ Changes in existing checks
adding an option to allow pointer arithmetic via prefix/postfix increment or
decrement operators.

- Improved :doc:`misc-const-correctness
<clang-tidy/checks/misc/const-correctness>` check to diagnose
variables declared with ``auto``.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not mentioning lambdas because lambdas must be declared with auto anyway.


- Improved :doc:`misc-header-include-cycle
<clang-tidy/checks/misc/header-include-cycle>` check performance.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ void range_for() {
int *p_local2[2] = {nullptr, nullptr};
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'int *[2]' can be declared 'const'
// CHECK-FIXES: int *const p_local2[2]
for (const auto *con_ptr : p_local2) {
for (const auto *p_local3 : p_local2) {
// CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local3' of type 'const int *' can be declared 'const'
// CHECK-FIXES: for (const auto *const p_local3 : p_local2)
}

}
Expand Down Expand Up @@ -62,6 +64,8 @@ void EmitProtocolMethodList(T &&Methods) {
// CHECK-FIXES: SmallVector<const int *> const p_local0
SmallVector<const int *> np_local0;
for (const auto *I : Methods) {
// CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'I' of type 'const int *' can be declared 'const'
// CHECK-FIXES: for (const auto *const I : Methods)
if (I == nullptr)
np_local0.push_back(I);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@
template <typename T>
void type_dependent_variables() {
T value = 42;
auto &ref = value;
T &templateRef = value;

auto &ref = value;
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'ref' of type 'int &' can be declared 'const'
// CHECK-FIXES: auto const&ref = value;
// FIXME: This is a false positive, the reference points to a template type
// and needs to be excluded from analysis. See the 'more_template_locals()'
// test in 'const-correctness-values.cpp' for more examples of the problem.
Comment on lines +17 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VarDecl::getIinit -> Expr::isTypeDependent should do the trick


int value_int = 42;
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'value_int' of type 'int' can be declared 'const'
// CHECK-FIXES: int const value_int = 42;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ int scoped;
float np_scoped = 1; // namespace variables are like globals
} // namespace foo

// Lambdas should be ignored, because they do not follow the normal variable
// semantic (e.g. the type is only known to the compiler).
void lambdas() {
auto Lambda = [](int i) { return i < 0; };
}

void some_function(double, wchar_t);

void some_function(double np_arg0, wchar_t np_arg1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,19 @@ int np_anonymous_global;
int p_anonymous_global = 43;
} // namespace

// Lambdas should be ignored, because they do not follow the normal variable
// semantic (e.g. the type is only known to the compiler).
void lambdas() {
auto Lambda = [](int i) { return i < 0; };
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'Lambda' of type '{{.*}}' can be declared 'const'
// CHECK-FIXES: auto const Lambda

auto LambdaWithMutableCallOperator = []() mutable {};
LambdaWithMutableCallOperator();

int x = 0;
auto LambdaModifyingCapture = [&x] { ++x; };
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'LambdaModifyingCapture' of type '{{.*}}' can be declared 'const'
// CHECK-FIXES: auto const LambdaModifyingCapture
LambdaModifyingCapture();
}

void some_function(double, wchar_t);
Expand Down Expand Up @@ -85,6 +94,11 @@ void ignore_reference_to_pointers() {
int *&np_local1 = np_local0;
}

void ignore_rvalue_references() {
int &&np_local0 = 42;
auto &&np_local1 = 42;
}

void some_lambda_environment_capture_all_by_reference(double np_arg0) {
int np_local0 = 0;
int p_local0 = 1;
Expand Down Expand Up @@ -965,14 +979,23 @@ template <typename T>
T *return_ptr() { return &return_ref<T>(); }

void auto_usage_variants() {
auto auto_int = int{};
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'auto_int' of type 'int' can be declared 'const'
// CHECK-FIXES: auto const auto_int

auto auto_val0 = int{};
// CHECK-FIXES-NOT: auto const auto_val0
auto &auto_val1 = auto_val0;
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'auto_val1' of type 'int &' can be declared 'const'
// CHECK-FIXES: auto const&auto_val1
auto *auto_val2 = &auto_val0;

auto auto_ref0 = return_ref<int>();
// CHECK-FIXES-NOT: auto const auto_ref0
auto &auto_ref1 = return_ref<int>(); // Bad
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'auto_ref0' of type 'int' can be declared 'const'
// CHECK-FIXES: auto const auto_ref0
auto &auto_ref1 = return_ref<int>();
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'auto_ref1' of type 'int &' can be declared 'const'
// CHECK-FIXES: auto const&auto_ref1
auto *auto_ref2 = return_ptr<int>();

auto auto_ptr0 = return_ptr<int>();
Expand All @@ -984,6 +1007,8 @@ void auto_usage_variants() {
auto auto_td0 = MyTypedef{};
// CHECK-FIXES-NOT: auto const auto_td0
auto &auto_td1 = auto_td0;
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: variable 'auto_td1' of type 'MyTypedef &' (aka 'int &') can be declared 'const'
// CHECK-FIXES: auto const&auto_td1
auto *auto_td2 = &auto_td0;
}

Expand Down