[clang-tidy] readability-redundant-declaration: fix false positive with C "extern inline"

Summary:
readability-redundant-declaration was diagnosing a redundant declaration
on "extern inline void f();", which is needed in C code to force an external definition
of the inline function f. (This is different to how inline behaves in C++).

Reviewers: alexfh, danielmarjamaki

Subscribers: xazax.hun, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D61700

llvm-svn: 360613
This commit is contained in:
Matthias Gehre 2019-05-13 19:21:57 +00:00
parent ae54fc9f04
commit 5f9afe953d
3 changed files with 49 additions and 2 deletions

View File

@ -17,6 +17,10 @@ namespace clang {
namespace tidy { namespace tidy {
namespace readability { namespace readability {
AST_MATCHER(FunctionDecl, doesDeclarationForceExternallyVisibleDefinition) {
return Node.doesDeclarationForceExternallyVisibleDefinition();
}
RedundantDeclarationCheck::RedundantDeclarationCheck(StringRef Name, RedundantDeclarationCheck::RedundantDeclarationCheck(StringRef Name,
ClangTidyContext *Context) ClangTidyContext *Context)
: ClangTidyCheck(Name, Context), : ClangTidyCheck(Name, Context),
@ -25,7 +29,9 @@ RedundantDeclarationCheck::RedundantDeclarationCheck(StringRef Name,
void RedundantDeclarationCheck::registerMatchers(MatchFinder *Finder) { void RedundantDeclarationCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher( Finder->addMatcher(
namedDecl(anyOf(varDecl(unless(isDefinition())), namedDecl(anyOf(varDecl(unless(isDefinition())),
functionDecl(unless(anyOf(isDefinition(), isDefaulted(), functionDecl(unless(anyOf(
isDefinition(), isDefaulted(),
doesDeclarationForceExternallyVisibleDefinition(),
hasParent(friendDecl())))))) hasParent(friendDecl()))))))
.bind("Decl"), .bind("Decl"),
this); this);

View File

@ -0,0 +1,31 @@
// RUN: %check_clang_tidy %s readability-redundant-declaration %t
extern int Xyz;
extern int Xyz; // Xyz
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Xyz' declaration [readability-redundant-declaration]
// CHECK-FIXES: {{^}}// Xyz{{$}}
int Xyz = 123;
extern int A;
extern int A, B;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'A' declaration
// CHECK-FIXES: {{^}}extern int A, B;{{$}}
extern int Buf[10];
extern int Buf[10]; // Buf[10]
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'Buf' declaration
// CHECK-FIXES: {{^}}// Buf[10]{{$}}
static int f();
static int f(); // f
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant 'f' declaration
// CHECK-FIXES: {{^}}// f{{$}}
static int f() {}
inline void g() {}
inline void g();
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant 'g' declaration
// OK: Needed to emit an external definition.
extern inline void g();

View File

@ -68,3 +68,13 @@ DEFINE(test);
// CHECK-FIXES: {{^}}DEFINE(test);{{$}} // CHECK-FIXES: {{^}}DEFINE(test);{{$}}
} // namespace macros } // namespace macros
inline void g() {}
inline void g(); // g
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant 'g' declaration
// CHECK-FIXES: {{^}}// g{{$}}
extern inline void g(); // extern g
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant 'g' declaration
// CHECK-FIXES: {{^}}// extern g{{$}}