diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp index 7e388201bf79..f07b49444f3e 100644 --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp @@ -23,6 +23,12 @@ namespace { // FIXME: This matcher exists in some other code-review as well. // It should probably move to ASTMatchers. AST_MATCHER(VarDecl, isLocal) { return Node.isLocalVarDecl(); } +// FIXME: The matcher 'hasName(Name)' asserts that its argument 'Name' is +// nonempty. Perhaps remove that assertion and replace 'isUnnamed()' with +// 'hasName("")'. +AST_MATCHER(VarDecl, isUnnamed) { + return Node.getDeclName().isIdentifier() && Node.getName().empty(); +} AST_MATCHER_P(DeclStmt, containsAnyDeclaration, ast_matchers::internal::Matcher, InnerMatcher) { return ast_matchers::internal::matchesFirstInPointerRange( @@ -148,7 +154,7 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) { if (AnalyzeParameters) { const auto ParamMatcher = - parmVarDecl(unless(CommonExcludeTypes), + parmVarDecl(unless(CommonExcludeTypes), unless(isUnnamed()), anyOf(hasType(referenceType()), hasType(pointerType()))) .bind("value"); diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst index 0365df2aa450..7a0c73e09949 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst @@ -110,15 +110,15 @@ Options Enable or disable the analysis of function parameters, like ``void foo(int* ptr)``. Only reference and pointer parameters are analyzed. - Currently, member functions (including constructors) and lambdas are excluded - from the analysis. Default is `true`. + Unnamed parameters, member functions (including constructors) and lambdas are + excluded from the analysis. Default is `true`. .. code-block:: c++ // Warning void function(int& param) {} // No warning - void function(const int& param) {} + void function(const int& param, int&) {} .. option:: WarnPointersAsValues diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp index 96d54b844170..8ff099eadb5a 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp @@ -509,3 +509,34 @@ void struct_ptr_param_modified(Bar** bp) { // CHECK-FIXES: void struct_ptr_param_modified(Bar** const bp) { (*bp)->mutating_method(); } + +void unnamed_parameters(int&, char*, Bar, Bar&, int[5]) { + // Unnamed parameters are never reported. +} + +void unnamed_and_named_irrelevant_params(const int& X, char*, Bar Z, Bar&, int[5]) { + // No report, all parameters are excluded for various reasons. +} + +void unnamed_and_named_params(int& X, int&) { + // But a named parameter is reported even if it is next to an unnamed one. + // CHECK-MESSAGES: [[@LINE-2]]:31: warning: variable 'X' of type 'int &' can be declared 'const' + // CHECK-FIXES: void unnamed_and_named_params(int const& X, int&) { +} + +// If the parameter is named in the definition, its type will be updated in all +// declarations, inclunding ones where it is unnamed. +void unnamed_in_decl_named_in_def(int&); +// CHECK-FIXES: void unnamed_in_decl_named_in_def(int const&); + +void unnamed_in_decl_named_in_def(int& X) { + // CHECK-MESSAGES: [[@LINE-1]]:35: warning: variable 'X' of type 'int &' can be declared 'const' + // CHECK-FIXES: void unnamed_in_decl_named_in_def(int const& X) { +} + +void named_in_decl_unnamed_in_def(int& X); + +void named_in_decl_unnamed_in_def(int&) { + // If the parameter is unnamed in the definition, it will not be reported, even + // if it is named in some declaration. +}