[clang-tidy] Add inconsistent declaration parameter name check
This is first of series of patches, porting code from my project colobot-lint, as I mentioned recently in cfe-dev mailing list. This patch adds a new check in readability module: readability-inconsistent-declaration-parameter-name. I also added appropriate testcases and documentation. I chose readability module, as it seems it is the best place for it. I think I followed the rules of LLVM coding guideline, but I may have missed something, as I usually use other code formatting style. http://reviews.llvm.org/D12462 Patch by Piotr Dziwinski! git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@247261 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
3834176449
Коммит
340f73f358
|
@ -6,6 +6,7 @@ add_clang_library(clangTidyReadabilityModule
|
|||
ElseAfterReturnCheck.cpp
|
||||
FunctionSizeCheck.cpp
|
||||
IdentifierNamingCheck.cpp
|
||||
InconsistentDeclarationParameterNameCheck.cpp
|
||||
NamedParameterCheck.cpp
|
||||
NamespaceCommentCheck.cpp
|
||||
ReadabilityTidyModule.cpp
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
//===--- InconsistentDeclarationParameterNameCheck.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 "InconsistentDeclarationParameterNameCheck.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace readability {
|
||||
|
||||
using namespace ast_matchers;
|
||||
|
||||
namespace {
|
||||
|
||||
AST_MATCHER(FunctionDecl, hasOtherDeclarations) {
|
||||
auto It = Node.redecls_begin();
|
||||
auto EndIt = Node.redecls_end();
|
||||
|
||||
if (It == EndIt)
|
||||
return false;
|
||||
|
||||
++It;
|
||||
return It != EndIt;
|
||||
}
|
||||
|
||||
struct DifferingParamInfo {
|
||||
DifferingParamInfo(StringRef SourceName, StringRef OtherName,
|
||||
SourceRange OtherNameRange, bool GenerateFixItHint)
|
||||
: SourceName(SourceName), OtherName(OtherName),
|
||||
OtherNameRange(OtherNameRange), GenerateFixItHint(GenerateFixItHint) {}
|
||||
|
||||
StringRef SourceName;
|
||||
StringRef OtherName;
|
||||
SourceRange OtherNameRange;
|
||||
bool GenerateFixItHint;
|
||||
};
|
||||
|
||||
using DifferingParamsContainer = llvm::SmallVector<DifferingParamInfo, 10>;
|
||||
|
||||
struct InconsistentDeclarationInfo {
|
||||
InconsistentDeclarationInfo(SourceLocation DeclarationLocation,
|
||||
DifferingParamsContainer &&DifferingParams)
|
||||
: DeclarationLocation(DeclarationLocation),
|
||||
DifferingParams(std::move(DifferingParams)) {}
|
||||
|
||||
SourceLocation DeclarationLocation;
|
||||
DifferingParamsContainer DifferingParams;
|
||||
};
|
||||
|
||||
using InconsistentDeclarationsContainer =
|
||||
llvm::SmallVector<InconsistentDeclarationInfo, 2>;
|
||||
|
||||
bool checkIfFixItHintIsApplicable(
|
||||
const FunctionDecl *ParameterSourceDeclaration,
|
||||
const ParmVarDecl *SourceParam, const FunctionDecl *OriginalDeclaration) {
|
||||
// Assumptions with regard to function declarations/definition:
|
||||
// * If both function declaration and definition are seen, assume that
|
||||
// definition is most up-to-date, and use it to generate replacements.
|
||||
// * If only function declarations are seen, there is no easy way to tell
|
||||
// which is up-to-date and which is not, so don't do anything.
|
||||
// TODO: This may be changed later, but for now it seems the reasonable
|
||||
// solution.
|
||||
if (!ParameterSourceDeclaration->isThisDeclarationADefinition())
|
||||
return false;
|
||||
|
||||
// Assumption: if parameter is not referenced in function defintion body, it
|
||||
// may indicate that it's outdated, so don't touch it.
|
||||
if (!SourceParam->isReferenced())
|
||||
return false;
|
||||
|
||||
// In case there is the primary template definition and (possibly several)
|
||||
// template specializations (and each with possibly several redeclarations),
|
||||
// it is not at all clear what to change.
|
||||
if (OriginalDeclaration->getTemplatedKind() ==
|
||||
FunctionDecl::TK_FunctionTemplateSpecialization)
|
||||
return false;
|
||||
|
||||
// Other cases seem OK to allow replacements.
|
||||
return true;
|
||||
}
|
||||
|
||||
DifferingParamsContainer
|
||||
findDifferingParamsInDeclaration(const FunctionDecl *ParameterSourceDeclaration,
|
||||
const FunctionDecl *OtherDeclaration,
|
||||
const FunctionDecl *OriginalDeclaration) {
|
||||
DifferingParamsContainer DifferingParams;
|
||||
|
||||
auto SourceParamIt = ParameterSourceDeclaration->param_begin();
|
||||
auto OtherParamIt = OtherDeclaration->param_begin();
|
||||
|
||||
while (SourceParamIt != ParameterSourceDeclaration->param_end() &&
|
||||
OtherParamIt != OtherDeclaration->param_end()) {
|
||||
auto SourceParamName = (*SourceParamIt)->getName();
|
||||
auto OtherParamName = (*OtherParamIt)->getName();
|
||||
|
||||
// FIXME: Provide a way to extract commented out parameter name from comment
|
||||
// next to it.
|
||||
if (!SourceParamName.empty() && !OtherParamName.empty() &&
|
||||
SourceParamName != OtherParamName) {
|
||||
SourceRange OtherParamNameRange =
|
||||
DeclarationNameInfo((*OtherParamIt)->getDeclName(),
|
||||
(*OtherParamIt)->getLocation()).getSourceRange();
|
||||
|
||||
bool GenerateFixItHint = checkIfFixItHintIsApplicable(
|
||||
ParameterSourceDeclaration, *SourceParamIt, OriginalDeclaration);
|
||||
|
||||
DifferingParams.emplace_back(SourceParamName, OtherParamName,
|
||||
OtherParamNameRange, GenerateFixItHint);
|
||||
}
|
||||
|
||||
++SourceParamIt;
|
||||
++OtherParamIt;
|
||||
}
|
||||
|
||||
return DifferingParams;
|
||||
}
|
||||
|
||||
InconsistentDeclarationsContainer
|
||||
findInconsitentDeclarations(const FunctionDecl *OriginalDeclaration,
|
||||
const FunctionDecl *ParameterSourceDeclaration,
|
||||
SourceManager &SM) {
|
||||
InconsistentDeclarationsContainer InconsistentDeclarations;
|
||||
SourceLocation ParameterSourceLocation =
|
||||
ParameterSourceDeclaration->getLocation();
|
||||
|
||||
for (const FunctionDecl *OtherDeclaration : OriginalDeclaration->redecls()) {
|
||||
SourceLocation OtherLocation = OtherDeclaration->getLocation();
|
||||
if (OtherLocation != ParameterSourceLocation) { // Skip self.
|
||||
DifferingParamsContainer DifferingParams =
|
||||
findDifferingParamsInDeclaration(ParameterSourceDeclaration,
|
||||
OtherDeclaration,
|
||||
OriginalDeclaration);
|
||||
if (!DifferingParams.empty()) {
|
||||
InconsistentDeclarations.emplace_back(OtherDeclaration->getLocation(),
|
||||
std::move(DifferingParams));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort in order of appearance in translation unit to generate clear
|
||||
// diagnostics.
|
||||
std::sort(InconsistentDeclarations.begin(), InconsistentDeclarations.end(),
|
||||
[&SM](const InconsistentDeclarationInfo &Info1,
|
||||
const InconsistentDeclarationInfo &Info2) {
|
||||
return SM.isBeforeInTranslationUnit(Info1.DeclarationLocation,
|
||||
Info2.DeclarationLocation);
|
||||
});
|
||||
return InconsistentDeclarations;
|
||||
}
|
||||
|
||||
const FunctionDecl *
|
||||
getParameterSourceDeclaration(const FunctionDecl *OriginalDeclaration) {
|
||||
const FunctionTemplateDecl *PrimaryTemplate =
|
||||
OriginalDeclaration->getPrimaryTemplate();
|
||||
if (PrimaryTemplate != nullptr) {
|
||||
// In case of template specializations, use primary template declaration as
|
||||
// the source of parameter names.
|
||||
return PrimaryTemplate->getTemplatedDecl();
|
||||
}
|
||||
|
||||
// In other cases, try to change to function definition, if available.
|
||||
|
||||
if (OriginalDeclaration->isThisDeclarationADefinition())
|
||||
return OriginalDeclaration;
|
||||
|
||||
for (const FunctionDecl *OtherDeclaration : OriginalDeclaration->redecls()) {
|
||||
if (OtherDeclaration->isThisDeclarationADefinition()) {
|
||||
return OtherDeclaration;
|
||||
}
|
||||
}
|
||||
|
||||
// No definition found, so return original declaration.
|
||||
return OriginalDeclaration;
|
||||
}
|
||||
|
||||
std::string joinParameterNames(
|
||||
const DifferingParamsContainer &DifferingParams,
|
||||
std::function<StringRef(const DifferingParamInfo &)> ChooseParamName) {
|
||||
llvm::SmallVector<char, 40> Buffer;
|
||||
llvm::raw_svector_ostream Str(Buffer);
|
||||
bool First = true;
|
||||
for (const DifferingParamInfo &ParamInfo : DifferingParams) {
|
||||
if (First)
|
||||
First = false;
|
||||
else
|
||||
Str << ", ";
|
||||
|
||||
Str << "'" << ChooseParamName(ParamInfo).str() << "'";
|
||||
}
|
||||
return Str.str().str();
|
||||
}
|
||||
|
||||
void formatDifferingParamsDiagnostic(
|
||||
InconsistentDeclarationParameterNameCheck *Check,
|
||||
const SourceLocation &Location, StringRef OtherDeclarationDescription,
|
||||
const DifferingParamsContainer &DifferingParams) {
|
||||
auto ChooseOtherName =
|
||||
[](const DifferingParamInfo &ParamInfo) { return ParamInfo.OtherName; };
|
||||
auto ChooseSourceName =
|
||||
[](const DifferingParamInfo &ParamInfo) { return ParamInfo.SourceName; };
|
||||
|
||||
auto ParamDiag =
|
||||
Check->diag(Location,
|
||||
"differing parameters are named here: (%0), in %1: (%2)",
|
||||
DiagnosticIDs::Level::Note)
|
||||
<< joinParameterNames(DifferingParams, ChooseOtherName)
|
||||
<< OtherDeclarationDescription
|
||||
<< joinParameterNames(DifferingParams, ChooseSourceName);
|
||||
|
||||
for (const DifferingParamInfo &ParamInfo : DifferingParams) {
|
||||
if (ParamInfo.GenerateFixItHint) {
|
||||
ParamDiag << FixItHint::CreateReplacement(
|
||||
CharSourceRange::getTokenRange(ParamInfo.OtherNameRange),
|
||||
ParamInfo.SourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void formatDiagnosticsForDeclarations(
|
||||
InconsistentDeclarationParameterNameCheck *Check,
|
||||
const FunctionDecl *ParameterSourceDeclaration,
|
||||
const FunctionDecl *OriginalDeclaration,
|
||||
const InconsistentDeclarationsContainer &InconsistentDeclarations) {
|
||||
Check->diag(
|
||||
OriginalDeclaration->getLocation(),
|
||||
"function %q0 has %1 other declaration%s1 with different parameter names")
|
||||
<< OriginalDeclaration
|
||||
<< static_cast<int>(InconsistentDeclarations.size());
|
||||
int Count = 1;
|
||||
for (const InconsistentDeclarationInfo &InconsistentDeclaration :
|
||||
InconsistentDeclarations) {
|
||||
Check->diag(InconsistentDeclaration.DeclarationLocation,
|
||||
"the %ordinal0 inconsistent declaration seen here",
|
||||
DiagnosticIDs::Level::Note)
|
||||
<< Count;
|
||||
|
||||
formatDifferingParamsDiagnostic(
|
||||
Check, InconsistentDeclaration.DeclarationLocation,
|
||||
"the other declaration", InconsistentDeclaration.DifferingParams);
|
||||
|
||||
++Count;
|
||||
}
|
||||
}
|
||||
|
||||
void formatDiagnostics(
|
||||
InconsistentDeclarationParameterNameCheck *Check,
|
||||
const FunctionDecl *ParameterSourceDeclaration,
|
||||
const FunctionDecl *OriginalDeclaration,
|
||||
const InconsistentDeclarationsContainer &InconsistentDeclarations,
|
||||
StringRef FunctionDescription, StringRef ParameterSourceDescription) {
|
||||
for (const InconsistentDeclarationInfo &InconsistentDeclaration :
|
||||
InconsistentDeclarations) {
|
||||
Check->diag(InconsistentDeclaration.DeclarationLocation,
|
||||
"%0 %q1 has a %2 with different parameter names")
|
||||
<< FunctionDescription << OriginalDeclaration
|
||||
<< ParameterSourceDescription;
|
||||
|
||||
Check->diag(ParameterSourceDeclaration->getLocation(), "the %0 seen here",
|
||||
DiagnosticIDs::Level::Note)
|
||||
<< ParameterSourceDescription;
|
||||
|
||||
formatDifferingParamsDiagnostic(
|
||||
Check, InconsistentDeclaration.DeclarationLocation,
|
||||
ParameterSourceDescription, InconsistentDeclaration.DifferingParams);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void InconsistentDeclarationParameterNameCheck::registerMatchers(
|
||||
MatchFinder *Finder) {
|
||||
Finder->addMatcher(functionDecl(unless(isImplicit()), hasOtherDeclarations())
|
||||
.bind("functionDecl"),
|
||||
this);
|
||||
}
|
||||
|
||||
void InconsistentDeclarationParameterNameCheck::check(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
const auto *OriginalDeclaration =
|
||||
Result.Nodes.getNodeAs<FunctionDecl>("functionDecl");
|
||||
|
||||
if (VisitedDeclarations.count(OriginalDeclaration) > 0)
|
||||
return; // Avoid multiple warnings.
|
||||
|
||||
const FunctionDecl *ParameterSourceDeclaration =
|
||||
getParameterSourceDeclaration(OriginalDeclaration);
|
||||
|
||||
InconsistentDeclarationsContainer InconsistentDeclarations =
|
||||
findInconsitentDeclarations(OriginalDeclaration,
|
||||
ParameterSourceDeclaration,
|
||||
*Result.SourceManager);
|
||||
if (InconsistentDeclarations.empty()) {
|
||||
// Avoid unnecessary further visits.
|
||||
markRedeclarationsAsVisited(OriginalDeclaration);
|
||||
return;
|
||||
}
|
||||
|
||||
if (OriginalDeclaration->getTemplatedKind() ==
|
||||
FunctionDecl::TK_FunctionTemplateSpecialization) {
|
||||
formatDiagnostics(this, ParameterSourceDeclaration, OriginalDeclaration,
|
||||
InconsistentDeclarations,
|
||||
"function template specialization",
|
||||
"primary template declaration");
|
||||
} else if (ParameterSourceDeclaration->isThisDeclarationADefinition()) {
|
||||
formatDiagnostics(this, ParameterSourceDeclaration, OriginalDeclaration,
|
||||
InconsistentDeclarations, "function", "definition");
|
||||
} else {
|
||||
formatDiagnosticsForDeclarations(this, ParameterSourceDeclaration,
|
||||
OriginalDeclaration,
|
||||
InconsistentDeclarations);
|
||||
}
|
||||
|
||||
markRedeclarationsAsVisited(OriginalDeclaration);
|
||||
}
|
||||
|
||||
void InconsistentDeclarationParameterNameCheck::markRedeclarationsAsVisited(
|
||||
const FunctionDecl *OriginalDeclaration) {
|
||||
for (const FunctionDecl *Redecl : OriginalDeclaration->redecls()) {
|
||||
VisitedDeclarations.insert(Redecl);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace readability
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
|
@ -0,0 +1,45 @@
|
|||
//===- InconsistentDeclarationParameterNameCheck.h - clang-tidy-*- C++ -*-===//
|
||||
//
|
||||
// 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_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
|
||||
|
||||
#include "../ClangTidy.h"
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
|
||||
namespace clang {
|
||||
namespace tidy {
|
||||
namespace readability {
|
||||
|
||||
/// \brief Checks for declarations of functions which differ in parameter names.
|
||||
///
|
||||
/// For detailed documentation see:
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.html
|
||||
///
|
||||
class InconsistentDeclarationParameterNameCheck : public ClangTidyCheck {
|
||||
public:
|
||||
InconsistentDeclarationParameterNameCheck(StringRef Name,
|
||||
ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
|
||||
private:
|
||||
void markRedeclarationsAsVisited(const FunctionDecl *FunctionDeclaration);
|
||||
|
||||
llvm::DenseSet<const FunctionDecl *> VisitedDeclarations;
|
||||
};
|
||||
|
||||
} // namespace readability
|
||||
} // namespace tidy
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_INCONSISTENT_DECLARATION_PARAMETER_NAME_H
|
|
@ -15,6 +15,7 @@
|
|||
#include "ElseAfterReturnCheck.h"
|
||||
#include "FunctionSizeCheck.h"
|
||||
#include "IdentifierNamingCheck.h"
|
||||
#include "InconsistentDeclarationParameterNameCheck.h"
|
||||
#include "NamedParameterCheck.h"
|
||||
#include "RedundantSmartptrGetCheck.h"
|
||||
#include "RedundantStringCStrCheck.h"
|
||||
|
@ -37,6 +38,8 @@ public:
|
|||
"readability-function-size");
|
||||
CheckFactories.registerCheck<IdentifierNamingCheck>(
|
||||
"readability-identifier-naming");
|
||||
CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
|
||||
"readability-inconsistent-declaration-parameter-name");
|
||||
CheckFactories.registerCheck<readability::NamedParameterCheck>(
|
||||
"readability-named-parameter");
|
||||
CheckFactories.registerCheck<RedundantSmartptrGetCheck>(
|
||||
|
|
|
@ -50,6 +50,7 @@ List of clang-tidy Checks
|
|||
readability-else-after-return
|
||||
readability-function-size
|
||||
readability-identifier-naming
|
||||
readability-inconsistent-declaration-parameter-name
|
||||
readability-named-parameter
|
||||
readability-redundant-smartptr-get
|
||||
readability-redundant-string-cstr
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
readability-inconsistent-declaration-parameter-name
|
||||
===================================================
|
||||
|
||||
|
||||
Find function declarations which differ in parameter names.
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
// in foo.hpp:
|
||||
void foo(int a, int b, int c);
|
||||
|
||||
// in foo.cpp:
|
||||
void foo(int d, int e, int f); // warning
|
||||
|
||||
This check should help to enforce consistency in large projects, where it often
|
||||
happens that a definition of function is refactored, changing the parameter
|
||||
names, but its declaration in header file is not updated. With this check, we
|
||||
can easily find and correct such inconsistencies, keeping declaration and
|
||||
definition always in sync.
|
||||
|
||||
Unnamed parameters are allowed and are not taken into account when comparing
|
||||
function declarations, for example:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
void foo(int a);
|
||||
void foo(int); // no warning
|
||||
|
||||
If there are multiple declarations of same function, only one warning will be
|
||||
generated.
|
|
@ -0,0 +1,188 @@
|
|||
// RUN: %python %S/check_clang_tidy.py %s readability-inconsistent-declaration-parameter-name %t
|
||||
|
||||
void consistentFunction(int a, int b, int c);
|
||||
void consistentFunction(int a, int b, int c);
|
||||
void consistentFunction(int a, int b, int /*c*/);
|
||||
void consistentFunction(int /*c*/, int /*c*/, int /*c*/);
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: function 'inconsistentFunction' has 2 other declarations with different parameter names [readability-inconsistent-declaration-parameter-name]
|
||||
void inconsistentFunction(int a, int b, int c);
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:6: note: the 1st inconsistent declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('d', 'e', 'f'), in the other declaration: ('a', 'b', 'c')
|
||||
void inconsistentFunction(int d, int e, int f);
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:6: note: the 2nd inconsistent declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('x', 'y', 'z'), in the other declaration: ('a', 'b', 'c')
|
||||
void inconsistentFunction(int x, int y, int z);
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:6: warning: function 'inconsistentFunctionWithVisibleDefinition' has a definition with different parameter names [readability-inconsistent-declaration-parameter-name]
|
||||
// CHECK-MESSAGES: :[[@LINE+9]]:6: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:6: note: differing parameters are named here: ('a'), in definition: ('c')
|
||||
// CHECK-FIXES: void inconsistentFunctionWithVisibleDefinition(int c);
|
||||
void inconsistentFunctionWithVisibleDefinition(int a);
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:6: warning: function 'inconsistentFunctionWithVisibleDefinition' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:6: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:6: note: differing parameters are named here: ('b'), in definition: ('c')
|
||||
// CHECK-FIXES: void inconsistentFunctionWithVisibleDefinition(int c);
|
||||
void inconsistentFunctionWithVisibleDefinition(int b);
|
||||
void inconsistentFunctionWithVisibleDefinition(int c) { c; }
|
||||
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function 'inconsidentFunctionWithUnreferencedParameterInDefinition' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('a'), in definition: ('b')
|
||||
void inconsidentFunctionWithUnreferencedParameterInDefinition(int a);
|
||||
void inconsidentFunctionWithUnreferencedParameterInDefinition(int b) {}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
struct Struct {
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: function 'Struct::inconsistentFunction' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+6]]:14: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:8: note: differing parameters are named here: ('a'), in definition: ('b')
|
||||
// CHECK-FIXES: void inconsistentFunction(int b);
|
||||
void inconsistentFunction(int a);
|
||||
};
|
||||
|
||||
void Struct::inconsistentFunction(int b) { b = 0; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
struct SpecialFunctions {
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:3: warning: function 'SpecialFunctions::SpecialFunctions' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+12]]:19: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:3: note: differing parameters are named here: ('a'), in definition: ('b')
|
||||
// CHECK-FIXES: SpecialFunctions(int b);
|
||||
SpecialFunctions(int a);
|
||||
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:21: warning: function 'SpecialFunctions::operator=' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+8]]:37: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:21: note: differing parameters are named here: ('a'), in definition: ('b')
|
||||
// CHECK-FIXES: SpecialFunctions& operator=(const SpecialFunctions& b);
|
||||
SpecialFunctions& operator=(const SpecialFunctions& a);
|
||||
};
|
||||
|
||||
SpecialFunctions::SpecialFunctions(int b) { b; }
|
||||
|
||||
SpecialFunctions& SpecialFunctions::operator=(const SpecialFunctions& b) { b; return *this; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
// CHECK-MESSAGES: :[[@LINE+5]]:6: warning: function 'templateFunctionWithSeparateDeclarationAndDefinition' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+7]]:6: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: note: differing parameters are named here: ('a'), in definition: ('b')
|
||||
// CHECK-FIXES: void templateFunctionWithSeparateDeclarationAndDefinition(T b);
|
||||
template<typename T>
|
||||
void templateFunctionWithSeparateDeclarationAndDefinition(T a);
|
||||
|
||||
template<typename T>
|
||||
void templateFunctionWithSeparateDeclarationAndDefinition(T b) { b; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
void templateFunctionWithSpecializations(T a) { a; }
|
||||
|
||||
template<>
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSpecializations<int>' has a primary template declaration with different parameter names [readability-inconsistent-declaration-parameter-name]
|
||||
// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
|
||||
void templateFunctionWithSpecializations(int b) { b; }
|
||||
|
||||
template<>
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSpecializations<float>' has a primary template
|
||||
// CHECK-MESSAGES: :[[@LINE-10]]:6: note: the primary template declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
|
||||
void templateFunctionWithSpecializations(float c) { c; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
void templateFunctionWithoutDefinitionButWithSpecialization(T a);
|
||||
|
||||
template<>
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithoutDefinitionButWithSpecialization<int>' has a primary template
|
||||
// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
|
||||
void templateFunctionWithoutDefinitionButWithSpecialization(int b) { b; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(T a);
|
||||
|
||||
template<>
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSeparateSpecializationDeclarationAndDefinition<int>' has a primary template
|
||||
// CHECK-MESSAGES: :[[@LINE-4]]:6: note: the primary template declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
|
||||
void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(int b);
|
||||
|
||||
template<>
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'templateFunctionWithSeparateSpecializationDeclarationAndDefinition<int>' has a primary template
|
||||
// CHECK-MESSAGES: :[[@LINE-10]]:6: note: the primary template declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
|
||||
void templateFunctionWithSeparateSpecializationDeclarationAndDefinition(int c) { c; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
class ClassTemplate
|
||||
{
|
||||
public:
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:10: warning: function 'ClassTemplate::functionInClassTemplateWithSeparateDeclarationAndDefinition' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+7]]:24: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:10: note: differing parameters are named here: ('a'), in definition: ('b')
|
||||
// CHECK-FIXES: void functionInClassTemplateWithSeparateDeclarationAndDefinition(int b);
|
||||
void functionInClassTemplateWithSeparateDeclarationAndDefinition(int a);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void ClassTemplate<T>::functionInClassTemplateWithSeparateDeclarationAndDefinition(int b) { b; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
class Class
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
// CHECK-MESSAGES: :[[@LINE+4]]:8: warning: function 'Class::memberFunctionTemplateWithSeparateDeclarationAndDefinition' has a definition
|
||||
// CHECK-MESSAGES: :[[@LINE+12]]:13: note: the definition seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:8: note: differing parameters are named here: ('a'), in definition: ('b')
|
||||
// CHECK-FIXES: void memberFunctionTemplateWithSeparateDeclarationAndDefinition(T b);
|
||||
void memberFunctionTemplateWithSeparateDeclarationAndDefinition(T a);
|
||||
|
||||
template<typename T>
|
||||
void memberFunctionTemplateWithSpecializations(T a) { a; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
void Class::memberFunctionTemplateWithSeparateDeclarationAndDefinition(T b) { b; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:13: warning: function template specialization 'Class::memberFunctionTemplateWithSpecializations<int>' has a primary template
|
||||
// CHECK-MESSAGES: :[[@LINE-12]]:8: note: the primary template declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:13: note: differing parameters are named here: ('b'), in primary template declaration: ('a')
|
||||
void Class::memberFunctionTemplateWithSpecializations(int b) { b; }
|
||||
|
||||
template<>
|
||||
// CHECK-MESSAGES: :[[@LINE+3]]:13: warning: function template specialization 'Class::memberFunctionTemplateWithSpecializations<float>' has a primary template
|
||||
// CHECK-MESSAGES: :[[@LINE-18]]:8: note: the primary template declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:13: note: differing parameters are named here: ('c'), in primary template declaration: ('a')
|
||||
void Class::memberFunctionTemplateWithSpecializations(float c) { c; }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
#define DECLARE_FUNCTION_WITH_PARAM_NAME(function_name, param_name) \
|
||||
void function_name(int param_name)
|
||||
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:34: warning: function 'macroFunction' has 1 other declaration with different parameter names [readability-inconsistent-declaration-parameter-name]
|
||||
DECLARE_FUNCTION_WITH_PARAM_NAME(macroFunction, a);
|
||||
// CHECK-MESSAGES: :[[@LINE+2]]:34: note: the 1st inconsistent declaration seen here
|
||||
// CHECK-MESSAGES: :[[@LINE+1]]:34: note: differing parameters are named here: ('b'), in the other declaration: ('a')
|
||||
DECLARE_FUNCTION_WITH_PARAM_NAME(macroFunction, b);
|
Загрузка…
Ссылка в новой задаче