Index: clang-tools-extra/trunk/clang-tidy/google/NamedParameterCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/google/NamedParameterCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/google/NamedParameterCheck.cpp @@ -37,6 +37,14 @@ if (Function->isImplicit()) return; + // Ignore declarations without a definition if we're not dealing with an + // overriden method. + const FunctionDecl *Definition = nullptr; + if (!Function->isDefined(Definition) && + (!isa(Function) || + cast(Function)->size_overridden_methods() == 0)) + return; + // TODO: Handle overloads. // TODO: We could check that all redeclarations use the same name for // arguments in the same position. @@ -69,26 +77,35 @@ auto D = diag(FirstParm->getLocation(), "all parameters should be named in a function"); + // Fallback to an unused marker. + StringRef NewName = "unused"; + for (auto P : UnnamedParams) { // If the method is overridden, try to copy the name from the base method // into the overrider. - const ParmVarDecl *Parm = P.first->getParamDecl(P.second); const auto *M = dyn_cast(P.first); if (M && M->size_overridden_methods() > 0) { const ParmVarDecl *OtherParm = (*M->begin_overridden_methods())->getParamDecl(P.second); - std::string Name = OtherParm->getNameAsString(); - if (!Name.empty()) { - D << FixItHint::CreateInsertion(Parm->getLocation(), - " /*" + Name + "*/"); - continue; - } + StringRef Name = OtherParm->getName(); + if (!Name.empty()) + NewName = Name; } - // Otherwise just insert an unused marker. Note that getLocation() points - // to the place where the name would be, this allows us to also get - // complex cases like function pointers right. - D << FixItHint::CreateInsertion(Parm->getLocation(), " /*unused*/"); + // If the definition has a named parameter use that name. + if (Definition) { + const ParmVarDecl *DefParm = Definition->getParamDecl(P.second); + StringRef Name = DefParm->getName(); + if (!Name.empty()) + NewName = Name; + } + + // Now insert the comment. Note that getLocation() points to the place + // where the name would be, this allows us to also get complex cases like + // function pointers right. + const ParmVarDecl *Parm = P.first->getParamDecl(P.second); + D << FixItHint::CreateInsertion(Parm->getLocation(), + " /*" + NewName.str() + "*/"); } } } Index: clang-tools-extra/trunk/test/clang-tidy/google-readability-function.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/google-readability-function.cpp +++ clang-tools-extra/trunk/test/clang-tidy/google-readability-function.cpp @@ -4,57 +4,57 @@ void Method(char *) { /* */ } // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: all parameters should be named in a function // CHECK-FIXES: void Method(char * /*unused*/) { /* */ } -void Method2(char *); +void Method2(char *) {} // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function -// CHECK-FIXES: void Method2(char * /*unused*/); -void Method3(char *, void *); +// CHECK-FIXES: void Method2(char * /*unused*/) {} +void Method3(char *, void *) {} // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function -// CHECK-FIXES: void Method3(char * /*unused*/, void * /*unused*/); -void Method4(char *, int /*unused*/); +// CHECK-FIXES: void Method3(char * /*unused*/, void * /*unused*/) {} +void Method4(char *, int /*unused*/) {} // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: all parameters should be named in a function -// CHECK-FIXES: void Method4(char * /*unused*/, int /*unused*/); -void operator delete[](void *) throw(); +// CHECK-FIXES: void Method4(char * /*unused*/, int /*unused*/) {} +void operator delete[](void *) throw() {} // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: all parameters should be named in a function -// CHECK-FIXES: void operator delete[](void * /*unused*/) throw(); -int Method5(int); +// CHECK-FIXES: void operator delete[](void * /*unused*/) throw() {} +int Method5(int) { return 0; } // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: all parameters should be named in a function -// CHECK-FIXES: int Method5(int /*unused*/); +// CHECK-FIXES: int Method5(int /*unused*/) { return 0; } void Method6(void (*)(void *)) {} // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: all parameters should be named in a function // CHECK-FIXES: void Method6(void (* /*unused*/)(void *)) {} -template void Method7(T); +template void Method7(T) {} // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: all parameters should be named in a function -// CHECK-FIXES: template void Method7(T /*unused*/); +// CHECK-FIXES: template void Method7(T /*unused*/) {} // Don't warn in macros. -#define M void MethodM(int); +#define M void MethodM(int) {} M -void operator delete(void *x) throw(); +void operator delete(void *x) throw() {} void Method7(char * /*x*/) {} -void Method8(char *x); +void Method8(char *x) {} typedef void (*TypeM)(int x); void operator delete[](void *x) throw(); void operator delete[](void * /*x*/) throw(); struct X { - X operator++(int); + X operator++(int) {} // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: all parameters should be named in a function -// CHECK-FIXES: X operator++(int /*unused*/); - X operator--(int /*unused*/); +// CHECK-FIXES: X operator++(int /*unused*/) {} + X operator--(int /*unused*/) {} const int &i; }; void (*Func1)(void *); void Func2(void (*func)(void *)) {} -template void Func3(); +template void Func3() {} template struct Y { - void foo(T); + void foo(T) {} // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: all parameters should be named in a function -// CHECK-FIXES: void foo(T /*unused*/); +// CHECK-FIXES: void foo(T /*unused*/) {} }; Y y; @@ -70,3 +70,10 @@ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: all parameters should be named in a function // CHECK-FIXES: void foo(int /*argname*/); }; + +void FDef(int); +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: all parameters should be named in a function +// CHECK-FIXES: void FDef(int /*n*/); +void FDef(int n) {}; + +void FNoDef(int);