diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp index b32507d66cbac..390046873f2d7 100644 --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp @@ -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())))); @@ -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. diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 780e5b3fc21cf..1ae709c9a2744 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -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 + ` check to diagnose + variables declared with ``auto``. + - Improved :doc:`misc-header-include-cycle ` check performance. diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp index 74be3dccc9daa..c675482513819 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp @@ -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) } } @@ -62,6 +64,8 @@ void EmitProtocolMethodList(T &&Methods) { // CHECK-FIXES: SmallVector const p_local0 SmallVector 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); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp index 5a890f212a603..98bf27033c3b5 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp @@ -9,9 +9,15 @@ template 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. + 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; diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp index 190d8ecec4c59..46ecb521b74cf 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp @@ -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) { diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp index 17dcf12e2536c..c0020a2b3c182 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp @@ -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); @@ -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; @@ -965,14 +979,23 @@ template T *return_ptr() { return &return_ref(); } 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(); - // CHECK-FIXES-NOT: auto const auto_ref0 - auto &auto_ref1 = return_ref(); // 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(); + // 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(); auto auto_ptr0 = return_ptr(); @@ -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; }