[clang-tidy] readability check for const params in declarations

Summary: Adds a clang-tidy warning for top-level consts in function declarations.

Reviewers: hokein, sbenza, alexfh

Subscribers: cfe-commits

Patch by Matt Kulukundis!

Differential Revision: http://reviews.llvm.org/D18408


git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@264856 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alexander Kornienko 2016-03-30 11:31:33 +00:00
Родитель 2f39d0198a
Коммит a1f0b8e1a7
7 изменённых файлов: 205 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,71 @@
//===--- AvoidConstParamsInDecls.cpp - clang-tidy--------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "AvoidConstParamsInDecls.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace readability {
namespace {
SourceRange getTypeRange(const ParmVarDecl &Param) {
if (Param.getIdentifier() != nullptr)
return SourceRange(Param.getLocStart(),
Param.getLocEnd().getLocWithOffset(-1));
return Param.getSourceRange();
}
} // namespace
void AvoidConstParamsInDecls::registerMatchers(MatchFinder *Finder) {
const auto ConstParamDecl =
parmVarDecl(hasType(qualType(isConstQualified()))).bind("param");
Finder->addMatcher(functionDecl(unless(isDefinition()),
has(typeLoc(forEach(ConstParamDecl))))
.bind("func"),
this);
}
void AvoidConstParamsInDecls::check(const MatchFinder::MatchResult &Result) {
const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
const auto *Param = Result.Nodes.getNodeAs<ParmVarDecl>("param");
QualType Type = Param->getType();
if (!Type.isLocalConstQualified())
return;
Type.removeLocalConst();
auto Diag = diag(Param->getLocStart(),
"parameter %0 is const-qualified in the function "
"declaration; const-qualification of parameters only has an "
"effect in function definitions");
if (Param->getName().empty()) {
for (unsigned int i = 0; i < Func->getNumParams(); ++i) {
if (Param == Func->getParamDecl(i)) {
Diag << (i + 1);
break;
}
}
} else {
Diag << Param;
}
Diag << FixItHint::CreateReplacement(getTypeRange(*Param),
Type.getAsString());
}
} // namespace readability
} // namespace tidy
} // namespace clang

Просмотреть файл

@ -0,0 +1,33 @@
//===--- AvoidConstParamsInDecls.h - clang-tidy----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace readability {
// Detect function declarations that have const value parameters and discourage
// them.
class AvoidConstParamsInDecls : public ClangTidyCheck {
public:
using ClangTidyCheck::ClangTidyCheck;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace readability
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_AVOID_CONST_PARAMS_IN_DECLS_H

Просмотреть файл

@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyReadabilityModule
AvoidConstParamsInDecls.cpp
BracesAroundStatementsCheck.cpp
ContainerSizeEmptyCheck.cpp
ElseAfterReturnCheck.cpp

Просмотреть файл

@ -10,6 +10,7 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "AvoidConstParamsInDecls.h"
#include "BracesAroundStatementsCheck.h"
#include "ContainerSizeEmptyCheck.h"
#include "ElseAfterReturnCheck.h"
@ -32,6 +33,8 @@ namespace readability {
class ReadabilityModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<AvoidConstParamsInDecls>(
"readability-avoid-const-params-in-decls");
CheckFactories.registerCheck<BracesAroundStatementsCheck>(
"readability-braces-around-statements");
CheckFactories.registerCheck<ContainerSizeEmptyCheck>(

Просмотреть файл

@ -90,8 +90,9 @@ Clang-Tidy Checks
performance-faster-string-find
performance-for-range-copy
performance-implicit-cast-in-loop
performance-unnecessary-value-param
performance-unnecessary-copy-initialization
performance-unnecessary-value-param
readability-avoid-const-params-in-decls
readability-braces-around-statements
readability-container-size-empty
readability-else-after-return

Просмотреть файл

@ -0,0 +1,17 @@
.. title:: clang-tidy - readability-avoid-const-params-in-decls
readability-avoid-const-params-in-decls
=======================================
Checks whether a function declaration has parameters that are top level const.
`const` values in declarations do not affect the signature of a function, so
they should not be put there. For example:
Examples:
.. code:: c++
void f(const string); // Bad: const is top level.
void f(const string&); // Good: const is not top level.

Просмотреть файл

@ -0,0 +1,78 @@
// RUN: %check_clang_tidy %s readability-avoid-const-params-in-decls %t
using alias_type = bool;
using alias_const_type = const bool;
void F1(const int i);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions [readability-avoid-const-params-in-decls]
// CHECK-FIXES: void F1(int i);
void F2(const int *const i);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
// CHECK-FIXES: void F2(const int * i);
void F3(int const i);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
// CHECK-FIXES: void F3(int i);
void F4(alias_type const i);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is const-qualified
// CHECK-FIXES: void F4(alias_type i);
void F5(const int);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
// CHECK-FIXES: void F5(int);
void F6(const int *const);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
// BUG(b/27584482): void F6(const int *); should be produced
void F7(int, const int);
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: parameter 2 is const-qualified
// CHECK-FIXES: void F7(int, int);
void F8(const int, const int);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 1 is const-qualified
// CHECK-MESSAGES: :[[@LINE-2]]:20: warning: parameter 2 is const-qualified
// CHECK-FIXES: void F8(int, int);
void F9(const int long_name);
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'long_name'
// CHECK-FIXES: void F9(int long_name);
void F10(const int *const *const long_name);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: parameter 'long_name'
// CHECK-FIXES: void F10(const int *const * long_name);
struct Foo {
Foo(const int i);
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: parameter 'i'
// CHECK-FIXES: Foo(int i);
void operator()(const int i);
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: parameter 'i'
// CHECK-FIXES: void operator()(int i);
};
// Do not match on definitions
void NF1(const int i) {}
void NF2(const int *const i) {}
void NF3(int const i) {}
void NF4(alias_type const i) {}
void NF5(const int) {}
void NF6(const int *const) {}
void NF7(int, const int) {}
void NF8(const int, const int) {}
// Do not match on other stuff
void NF(const alias_type& i);
void NF(const int &i);
void NF(const int *i);
void NF(alias_const_type i);
void NF(const alias_type&);
void NF(const int&);
void NF(const int*);
void NF(const int* const*);
void NF(alias_const_type);