Add modernize-redundant-void-arg check to clang-tidy

This check for clang-tidy looks for function with zero arguments declared as (void) and removes the unnecessary void token.

  int foo(void);

becomes

  int foo();

The check performs no formatting of the surrounding context but uses the lexer to look for the token sequence "(", "void", ")" in the prototype text. If this sequence of tokens is found, a removal is issued for the void token only.


Patch by Richard Thomson!

(+fixed tests, moved the check to the modernize module)

Differential revision: http://reviews.llvm.org/D7639

llvm-svn: 251475
This commit is contained in:
Alexander Kornienko 2015-10-28 01:36:20 +00:00
parent a1036e5d08
commit c3ceb27690
6 changed files with 811 additions and 0 deletions

View File

@ -6,6 +6,7 @@ add_clang_library(clangTidyModernizeModule
MakeUniqueCheck.cpp
ModernizeTidyModule.cpp
PassByValueCheck.cpp
RedundantVoidArgCheck.cpp
ReplaceAutoPtrCheck.cpp
ShrinkToFitCheck.cpp
UseAutoCheck.cpp

View File

@ -13,6 +13,7 @@
#include "LoopConvertCheck.h"
#include "MakeUniqueCheck.h"
#include "PassByValueCheck.h"
#include "RedundantVoidArgCheck.h"
#include "ReplaceAutoPtrCheck.h"
#include "ShrinkToFitCheck.h"
#include "UseAutoCheck.h"
@ -32,6 +33,8 @@ public:
CheckFactories.registerCheck<LoopConvertCheck>("modernize-loop-convert");
CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique");
CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
CheckFactories.registerCheck<RedundantVoidArgCheck>(
"modernize-redundant-void-arg");
CheckFactories.registerCheck<ReplaceAutoPtrCheck>(
"modernize-replace-auto-ptr");
CheckFactories.registerCheck<ShrinkToFitCheck>("modernize-shrink-to-fit");

View File

@ -0,0 +1,254 @@
//===- RedundantVoidArgCheck.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 "RedundantVoidArgCheck.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace {
// Determine if the given QualType is a nullary function or pointer to same.
bool protoTypeHasNoParms(QualType QT) {
if (auto PT = QT->getAs<PointerType>()) {
QT = PT->getPointeeType();
}
if (auto *MPT = QT->getAs<MemberPointerType>()) {
QT = MPT->getPointeeType();
}
if (auto FP = QT->getAs<FunctionProtoType>()) {
return FP->getNumParams() == 0;
}
return false;
}
const char FunctionId[] = "function";
const char TypedefId[] = "typedef";
const char FieldId[] = "field";
const char VarId[] = "var";
const char NamedCastId[] = "named-cast";
const char CStyleCastId[] = "c-style-cast";
const char ExplicitCastId[] = "explicit-cast";
const char LambdaId[] = "lambda";
} // namespace
namespace tidy {
namespace modernize {
void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(functionDecl(isExpansionInMainFile(), parameterCountIs(0),
unless(isImplicit()),
unless(isExternC())).bind(FunctionId),
this);
Finder->addMatcher(typedefDecl(isExpansionInMainFile()).bind(TypedefId),
this);
auto ParenFunctionType = parenType(innerType(functionType()));
auto PointerToFunctionType = pointee(ParenFunctionType);
auto FunctionOrMemberPointer =
anyOf(hasType(pointerType(PointerToFunctionType)),
hasType(memberPointerType(PointerToFunctionType)));
Finder->addMatcher(
fieldDecl(isExpansionInMainFile(), FunctionOrMemberPointer).bind(FieldId),
this);
Finder->addMatcher(
varDecl(isExpansionInMainFile(), FunctionOrMemberPointer).bind(VarId),
this);
auto CastDestinationIsFunction =
hasDestinationType(pointsTo(ParenFunctionType));
Finder->addMatcher(
cStyleCastExpr(isExpansionInMainFile(), CastDestinationIsFunction)
.bind(CStyleCastId),
this);
Finder->addMatcher(
cxxStaticCastExpr(isExpansionInMainFile(), CastDestinationIsFunction)
.bind(NamedCastId),
this);
Finder->addMatcher(
cxxReinterpretCastExpr(isExpansionInMainFile(), CastDestinationIsFunction)
.bind(NamedCastId),
this);
Finder->addMatcher(cxxConstCastExpr(isExpansionInMainFile(),
CastDestinationIsFunction).bind(NamedCastId),
this);
Finder->addMatcher(lambdaExpr(isExpansionInMainFile()).bind(LambdaId), this);
}
void RedundantVoidArgCheck::check(const MatchFinder::MatchResult &Result) {
if (!Result.Context->getLangOpts().CPlusPlus) {
return;
}
const BoundNodes &Nodes = Result.Nodes;
if (const auto *Function = Nodes.getNodeAs<FunctionDecl>(FunctionId)) {
processFunctionDecl(Result, Function);
} else if (const auto *Typedef = Nodes.getNodeAs<TypedefDecl>(TypedefId)) {
processTypedefDecl(Result, Typedef);
} else if (const auto *Member = Nodes.getNodeAs<FieldDecl>(FieldId)) {
processFieldDecl(Result, Member);
} else if (const auto *Var = Nodes.getNodeAs<VarDecl>(VarId)) {
processVarDecl(Result, Var);
} else if (const auto *NamedCast =
Nodes.getNodeAs<CXXNamedCastExpr>(NamedCastId)) {
processNamedCastExpr(Result, NamedCast);
} else if (const auto *CStyleCast =
Nodes.getNodeAs<CStyleCastExpr>(CStyleCastId)) {
processExplicitCastExpr(Result, CStyleCast);
} else if (const auto *ExplicitCast =
Nodes.getNodeAs<ExplicitCastExpr>(ExplicitCastId)) {
processExplicitCastExpr(Result, ExplicitCast);
} else if (const auto *Lambda = Nodes.getNodeAs<LambdaExpr>(LambdaId)) {
processLambdaExpr(Result, Lambda);
}
}
void RedundantVoidArgCheck::processFunctionDecl(
const MatchFinder::MatchResult &Result, const FunctionDecl *Function) {
SourceLocation Start = Function->getLocStart();
if (Function->isThisDeclarationADefinition()) {
SourceLocation BeforeBody =
Function->getBody()->getLocStart().getLocWithOffset(-1);
removeVoidArgumentTokens(Result, SourceRange(Start, BeforeBody),
"function definition");
} else {
removeVoidArgumentTokens(Result, Function->getSourceRange(),
"function declaration");
}
}
void RedundantVoidArgCheck::removeVoidArgumentTokens(
const ast_matchers::MatchFinder::MatchResult &Result, SourceRange Range,
StringRef GrammarLocation) {
std::string DeclText =
Lexer::getSourceText(CharSourceRange::getTokenRange(Range),
*Result.SourceManager,
Result.Context->getLangOpts()).str();
Lexer PrototypeLexer(Range.getBegin(), Result.Context->getLangOpts(),
DeclText.data(), DeclText.data(),
DeclText.data() + DeclText.size());
enum TokenState {
NothingYet,
SawLeftParen,
SawVoid,
};
TokenState State = NothingYet;
Token VoidToken;
Token ProtoToken;
std::string Diagnostic =
("redundant void argument list in " + GrammarLocation).str();
while (!PrototypeLexer.LexFromRawLexer(ProtoToken)) {
switch (State) {
case NothingYet:
if (ProtoToken.is(tok::TokenKind::l_paren)) {
State = SawLeftParen;
}
break;
case SawLeftParen:
if (ProtoToken.is(tok::TokenKind::raw_identifier) &&
ProtoToken.getRawIdentifier() == "void") {
State = SawVoid;
VoidToken = ProtoToken;
} else {
State = NothingYet;
}
break;
case SawVoid:
State = NothingYet;
if (ProtoToken.is(tok::TokenKind::r_paren)) {
removeVoidToken(VoidToken, Diagnostic);
} else if (ProtoToken.is(tok::TokenKind::l_paren)) {
State = SawLeftParen;
}
break;
}
}
if (State == SawVoid && ProtoToken.is(tok::TokenKind::r_paren)) {
removeVoidToken(VoidToken, Diagnostic);
}
}
void RedundantVoidArgCheck::removeVoidToken(Token VoidToken,
StringRef Diagnostic) {
SourceLocation VoidLoc(VoidToken.getLocation());
auto VoidRange =
CharSourceRange::getTokenRange(VoidLoc, VoidLoc.getLocWithOffset(3));
diag(VoidLoc, Diagnostic) << FixItHint::CreateRemoval(VoidRange);
}
void RedundantVoidArgCheck::processTypedefDecl(
const MatchFinder::MatchResult &Result, const TypedefDecl *Typedef) {
if (protoTypeHasNoParms(Typedef->getUnderlyingType())) {
removeVoidArgumentTokens(Result, Typedef->getSourceRange(), "typedef");
}
}
void RedundantVoidArgCheck::processFieldDecl(
const MatchFinder::MatchResult &Result, const FieldDecl *Member) {
if (protoTypeHasNoParms(Member->getType())) {
removeVoidArgumentTokens(Result, Member->getSourceRange(),
"field declaration");
}
}
void RedundantVoidArgCheck::processVarDecl(
const MatchFinder::MatchResult &Result, const VarDecl *Var) {
if (protoTypeHasNoParms(Var->getType())) {
SourceLocation Begin = Var->getLocStart();
if (Var->hasInit()) {
SourceLocation InitStart =
Result.SourceManager->getExpansionLoc(Var->getInit()->getLocStart())
.getLocWithOffset(-1);
removeVoidArgumentTokens(Result, SourceRange(Begin, InitStart),
"variable declaration with initializer");
} else {
removeVoidArgumentTokens(Result, Var->getSourceRange(),
"variable declaration");
}
}
}
void RedundantVoidArgCheck::processNamedCastExpr(
const MatchFinder::MatchResult &Result, const CXXNamedCastExpr *NamedCast) {
if (protoTypeHasNoParms(NamedCast->getTypeAsWritten())) {
removeVoidArgumentTokens(
Result,
NamedCast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(),
"named cast");
}
}
void RedundantVoidArgCheck::processExplicitCastExpr(
const MatchFinder::MatchResult &Result,
const ExplicitCastExpr *ExplicitCast) {
if (protoTypeHasNoParms(ExplicitCast->getTypeAsWritten())) {
removeVoidArgumentTokens(Result, ExplicitCast->getSourceRange(),
"cast expression");
}
}
void RedundantVoidArgCheck::processLambdaExpr(
const MatchFinder::MatchResult &Result, const LambdaExpr *Lambda) {
if (Lambda->getLambdaClass()->getLambdaCallOperator()->getNumParams() == 0 &&
Lambda->hasExplicitParameters()) {
SourceLocation Begin =
Lambda->getIntroducerRange().getEnd().getLocWithOffset(1);
SourceLocation End = Lambda->getBody()->getLocStart().getLocWithOffset(-1);
removeVoidArgumentTokens(Result, SourceRange(Begin, End),
"lambda expression");
}
}
} // namespace modernize
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,76 @@
//===--- RedundantVoidArgCheck.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_MODERNIZE_REDUNDANT_VOID_ARG_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REDUNDANT_VOID_ARG_CHECK_H
#include "../ClangTidy.h"
#include "clang/Lex/Token.h"
#include <string>
namespace clang {
namespace tidy {
namespace modernize {
/// \brief Find and remove redundant void argument lists.
///
/// Examples:
/// `int f(void);` becomes `int f();`
/// `int (*f(void))(void);` becomes `int (*f())();`
/// `typedef int (*f_t(void))(void);` becomes `typedef int (*f_t())();`
/// `void (C::*p)(void);` becomes `void (C::*p)();`
/// `C::C(void) {}` becomes `C::C() {}`
/// `C::~C(void) {}` becomes `C::~C() {}`
///
class RedundantVoidArgCheck : public ClangTidyCheck {
public:
RedundantVoidArgCheck(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 processFunctionDecl(const ast_matchers::MatchFinder::MatchResult &Result,
const FunctionDecl *Function);
void processTypedefDecl(const ast_matchers::MatchFinder::MatchResult &Result,
const TypedefDecl *Typedef);
void processFieldDecl(const ast_matchers::MatchFinder::MatchResult &Result,
const FieldDecl *Member);
void processVarDecl(const ast_matchers::MatchFinder::MatchResult &Result,
const VarDecl *Var);
void
processNamedCastExpr(const ast_matchers::MatchFinder::MatchResult &Result,
const CXXNamedCastExpr *NamedCast);
void
processExplicitCastExpr(const ast_matchers::MatchFinder::MatchResult &Result,
const ExplicitCastExpr *ExplicitCast);
void processLambdaExpr(const ast_matchers::MatchFinder::MatchResult &Result,
const LambdaExpr *Lambda);
void
removeVoidArgumentTokens(const ast_matchers::MatchFinder::MatchResult &Result,
SourceRange Range, StringRef GrammarLocation);
void removeVoidToken(Token VoidToken, StringRef Diagnostic);
};
} // namespace modernize
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REDUNDANT_VOID_ARG_CHECK_H

View File

@ -0,0 +1,58 @@
// RUN: clang-tidy -checks=-*,modernize-redundant-void-arg %s -- -x c | count 0
#include <stdio.h>
extern int i;
int foo2() {
return 0;
}
int j = 1;
int foo(void) {
return 0;
}
typedef unsigned int my_uint;
typedef void my_void;
// A function taking void and returning a pointer to function taking void
// and returning int.
int (*returns_fn_void_int(void))(void);
typedef int (*returns_fn_void_int_t(void))(void);
int (*returns_fn_void_int(void))(void) {
return NULL;
}
// A function taking void and returning a pointer to a function taking void
// and returning a pointer to a function taking void and returning void.
void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
typedef void (*(*returns_fn_returns_fn_void_void_t(void))(void))(void);
void (*(*returns_fn_returns_fn_void_void(void))(void))(void) {
return NULL;
}
void bar() {
int i;
int *pi = NULL;
void *pv = (void *) pi;
float f;
float *fi;
double d;
double *pd;
}
void (*f1)(void);
void (*f2)(void) = NULL;
void (*f3)(void) = bar;
void (*fa)();
void (*fb)() = NULL;
void (*fc)() = bar;
typedef void (function_ptr)(void);

View File

@ -0,0 +1,419 @@
// RUN: %check_clang_tidy %s modernize-redundant-void-arg %t
#include <iostream>
int foo();
void bar();
void bar2();
extern "C" void ecfoo(void);
extern "C" void ecfoo(void) {
}
extern int i;
int j = 1;
int foo(void) {
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
// CHECK-FIXES: {{^}}int foo() {{{$}}
return 0;
}
typedef unsigned int my_uint;
typedef void my_void;
// A function taking void and returning a pointer to function taking void
// and returning int.
int (*returns_fn_void_int(void))(void);
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} in function declaration
// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: {{.*}} in function declaration
// CHECK-FIXES: {{^}}int (*returns_fn_void_int())();{{$}}
typedef int (*returns_fn_void_int_t(void))(void);
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: {{.*}} in typedef
// CHECK-MESSAGES: :[[@LINE-2]]:44: warning: {{.*}} in typedef
// CHECK-FIXES: {{^}}typedef int (*returns_fn_void_int_t())();{{$}}
int (*returns_fn_void_int(void))(void) {
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} in function definition
// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: {{.*}} in function definition
// CHECK-FIXES: {{^}}int (*returns_fn_void_int())() {{{$}}
return nullptr;
}
// A function taking void and returning a pointer to a function taking void
// and returning a pointer to a function taking void and returning void.
void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: {{.*}} in function declaration
// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: {{.*}} in function declaration
// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: {{.*}} in function declaration
// CHECK-FIXES: {{^}}void (*(*returns_fn_returns_fn_void_void())())();{{$}}
typedef void (*(*returns_fn_returns_fn_void_void_t(void))(void))(void);
// CHECK-MESSAGES: :[[@LINE-1]]:52: warning: {{.*}} in typedef
// CHECK-MESSAGES: :[[@LINE-2]]:59: warning: {{.*}} in typedef
// CHECK-MESSAGES: :[[@LINE-3]]:66: warning: {{.*}} in typedef
// CHECK-FIXES: {{^}}typedef void (*(*returns_fn_returns_fn_void_void_t())())();{{$}}
void (*(*returns_fn_returns_fn_void_void(void))(void))(void) {
// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: {{.*}} in function definition
// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: {{.*}} in function definition
// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: {{.*}} in function definition
// CHECK-FIXES: {{^}}void (*(*returns_fn_returns_fn_void_void())())() {{{$}}
return nullptr;
}
void bar(void) {
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: {{.*}} in function definition
// CHECK-FIXES: {{^}}void bar() {{{$}}
}
void op_fn(int i) {
}
class gronk {
public:
gronk();
~gronk();
void foo();
void bar();
void bar2
();
void operation(int i) { }
private:
int m_i;
int *m_pi;
float m_f;
float *m_pf;
double m_d;
double *m_pd;
void (*f1)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in field declaration
// CHECK-FIXES: {{^ }}void (*f1)();{{$}}
void (*op)(int i);
void (gronk::*p1)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in field declaration
// CHECK-FIXES: {{^ }}void (gronk::*p1)();{{$}}
int (gronk::*p_mi);
void (gronk::*p2)(int);
void (*(*returns_fn_returns_fn_void_void(void))(void))(void);
// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: {{.*}} in function declaration
// CHECK-MESSAGES: :[[@LINE-2]]:51: warning: {{.*}} in function declaration
// CHECK-MESSAGES: :[[@LINE-3]]:58: warning: {{.*}} in function declaration
// CHECK-FIXES: {{^}} void (*(*returns_fn_returns_fn_void_void())())();{{$}}
void (*(*(gronk::*returns_fn_returns_fn_void_void_mem)(void))(void))(void);
// CHECK-MESSAGES: :[[@LINE-1]]:58: warning: {{.*}} in field declaration
// CHECK-MESSAGES: :[[@LINE-2]]:65: warning: {{.*}} in field declaration
// CHECK-MESSAGES: :[[@LINE-3]]:72: warning: {{.*}} in field declaration
// CHECK-FIXES: {{^}} void (*(*(gronk::*returns_fn_returns_fn_void_void_mem)())())();{{$}}
};
int i;
int *pi;
void *pv = (void *) pi;
float f;
float *fi;
double d;
double *pd;
void (*f1)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration
// CHECK-FIXES: {{^}}void (*f1)();{{$}}
void (*f2)(void) = nullptr;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (*f2)() = nullptr;{{$}}
void (*f2b)(void)(nullptr);
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (*f2b)()(nullptr);{{$}}
void (*f2c)(void){nullptr};
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (*f2c)(){nullptr};{{$}}
void (*f2d)(void) = NULL;
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (*f2d)() = NULL;{{$}}
void (*f2e)(void)(NULL);
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (*f2e)()(NULL);{{$}}
void (*f2f)(void){NULL};
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (*f2f)(){NULL};{{$}}
void (*f3)(void) = bar;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (*f3)() = bar;{{$}}
void (*o1)(int i);
void (*o2)(int i) = nullptr;
void (*o3)(int i)(nullptr);
void (*o4)(int i){nullptr};
void (*o5)(int i) = NULL;
void (*o6)(int i)(NULL);
void (*o7)(int i){NULL};
void (*o8)(int i) = op_fn;
void (*fa)();
void (*fb)() = nullptr;
void (*fc)() = bar;
typedef void (function_ptr)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: {{.*}} in typedef
// CHECK-FIXES: {{^}}typedef void (function_ptr)();{{$}}
// intentionally not LLVM style to check preservation of whitesapce
typedef void (function_ptr2)
(
void
);
// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: {{.*}} in typedef
// CHECK-FIXES: {{^typedef void \(function_ptr2\)$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NEXT: {{^ $}}
// CHECK-FIXES-NEXT: {{^ \);$}}
// intentionally not LLVM style to check preservation of whitesapce
typedef
void
(
*
(
*
returns_fn_returns_fn_void_void_t2
(
void
)
)
(
void
)
)
(
void
)
;
// CHECK-MESSAGES: :[[@LINE-11]]:1: warning: {{.*}} in typedef
// CHECK-MESSAGES: :[[@LINE-8]]:1: warning: {{.*}} in typedef
// CHECK-MESSAGES: :[[@LINE-5]]:1: warning: {{.*}} in typedef
// CHECK-FIXES: {{^typedef$}}
// CHECK-FIXES-NEXT: {{^void$}}
// CHECK-FIXES-NEXT: {{^\($}}
// CHECK-FIXES-NEXT: {{^\*$}}
// CHECK-FIXES-NEXT: {{^\($}}
// CHECK-FIXES-NEXT: {{^\*$}}
// CHECK-FIXES-NEXT: {{^returns_fn_returns_fn_void_void_t2$}}
// CHECK-FIXES-NEXT: {{^\($}}
// CHECK-FIXES-NOT: {{[^ ]}}
// CHECK-FIXES: {{^\)$}}
// CHECK-FIXES-NEXT: {{^\)$}}
// CHECK-FIXES-NEXT: {{^\($}}
// CHECK-FIXES-NOT: {{[^ ]}}
// CHECK-FIXES: {{^\)$}}
// CHECK-FIXES-NEXT: {{^\)$}}
// CHECK-FIXES-NEXT: {{^\($}}
// CHECK-FIXES-NOT: {{[^ ]}}
// CHECK-FIXES: {{^\)$}}
// CHECK-FIXES-NEXT: {{^;$}}
void (gronk::*p1)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} in variable declaration
// CHECK-FIXES: {{^}}void (gronk::*p1)();{{$}}
void (gronk::*p2)(void) = &gronk::foo;
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^}}void (gronk::*p2)() = &gronk::foo;{{$}}
typedef void (gronk::*member_function_ptr)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: {{.*}} in typedef
// CHECK-FIXES: {{^}}typedef void (gronk::*member_function_ptr)();{{$}}
// intentionally not LLVM style to check preservation of whitesapce
typedef void (gronk::*member_function_ptr2)
(
void
);
// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: {{.*}} in typedef
// CHECK-FIXES: {{^typedef void \(gronk::\*member_function_ptr2\)$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NEXT: {{^ $}}
// CHECK-FIXES-NEXT: {{^ \);$}}
void gronk::foo() {
void (*f1)(void) = &::bar;
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^ }}void (*f1)() = &::bar;{{$}}
void (*f2)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration
// CHECK-FIXES: {{^ }}void (*f2)();{{$}}
// intentionally not LLVM style to check preservation of whitesapce
void (*f3)
(
void
);
// CHECK-MESSAGES: :[[@LINE-2]]:11: warning: {{.*}} in variable declaration
// CHECK-FIXES: {{^ }}void (*f3){{$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NEXT: {{^ $}}
// CHECK-FIXES-NEXT: {{^ \);$}}
}
void gronk::bar(void) {
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} in function definition
// CHECK-FIXES: {{^}}void gronk::bar() {{{$}}
void (gronk::*p3)(void) = &gronk::foo;
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in variable declaration with initializer
// CHECK-FIXES: {{^ }}void (gronk::*p3)() = &gronk::foo;{{$}}
void (gronk::*p4)(void);
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in variable declaration
// CHECK-FIXES: {{^ }}void (gronk::*p4)();{{$}}
// intentionally not LLVM style to check preservation of whitesapce
void (gronk::*p5)
(
void
);
// CHECK-MESSAGES: :[[@LINE-2]]:11: warning: {{.*}} in variable declaration
// CHECK-FIXES: {{^ }}void (gronk::*p5){{$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NExT: {{^ $}}
// CHECK-FIXES-NExT: {{^ \);$}}
}
// intentionally not LLVM style to check preservation of whitesapce
void gronk::bar2
(
void
)
// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: {{.*}} in function definition
// CHECK-FIXES: {{^void gronk::bar2$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NEXT: {{^ $}}
// CHECK-FIXES-NEXT: {{^ \)$}}
{
}
gronk::gronk(void)
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in function definition
// CHECK-FIXES: {{^}}gronk::gronk(){{$}}
: f1(nullptr),
p1(nullptr) {
}
gronk::~gronk(void) {
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} in function definition
// CHECK-FIXES: {{^}}gronk::~gronk() {{{$}}
}
class nutter {
public:
nutter();
};
nutter::nutter(void) {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} in function definition
// CHECK-FIXES: {{^}}nutter::nutter() {{{$}}
void (*f3)(void) = static_cast<void (*)(void)>(0);
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
// CHECK-MESSAGES: :[[@LINE-2]]:43: warning: {{.*}} in named cast
// CHECK-FIXES: void (*f3)() = static_cast<void (*)()>(0);{{$}}
void (*f4)(void) = (void (*)(void)) 0;
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
// CHECK-MESSAGES: :[[@LINE-2]]:32: warning: {{.*}} in cast expression
// CHECK-FIXES: void (*f4)() = (void (*)()) 0;{{$}}
void (*f5)(void) = reinterpret_cast<void (*)(void)>(0);
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} in variable declaration with initializer
// CHECK-MESSAGES: :[[@LINE-2]]:48: warning: {{.*}} in named cast
// CHECK-FIXES: void (*f5)() = reinterpret_cast<void (*)()>(0);{{$}}
// intentionally not LLVM style to check preservation of whitesapce
void (*f6)(void) = static_cast<void (*)
(
void
)>(0);
// CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
// CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in named cast
// CHECK-FIXES: {{^ }}void (*f6)() = static_cast<void (*){{$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NEXT: {{^ $}}
// CHECK-FIXES-NEXT: {{^ }})>(0);{{$}}
// intentionally not LLVM style to check preservation of whitesapce
void (*f7)(void) = (void (*)
(
void
)) 0;
// CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
// CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in cast expression
// CHECK-FIXES: {{^ }}void (*f7)() = (void (*){{$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NEXT: {{^ $}}
// CHECK-FIXES-NEXT: {{^ \)\) 0;$}}
// intentionally not LLVM style to check preservation of whitesapce
void (*f8)(void) = reinterpret_cast<void (*)
(
void
)>(0);
// CHECK-MESSAGES: :[[@LINE-4]]:14: warning: {{.*}} in variable declaration with initializer
// CHECK-MESSAGES: :[[@LINE-3]]:11: warning: {{.*}} in named cast
// CHECK-FIXES: {{^ }}void (*f8)() = reinterpret_cast<void (*){{$}}
// CHECK-FIXES-NEXT: {{^ \($}}
// CHECK-FIXES-NEXT: {{^ $}}
// CHECK-FIXES-NEXT: {{^ \)>\(0\);$}}
void (*o1)(int) = static_cast<void (*)(int)>(0);
void (*o2)(int) = (void (*)(int)) 0;
void (*o3)(int) = reinterpret_cast<void (*)(int)>(0);
}
class generator {
public:
int operator()(void) { return 1; }
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}} in function definition
// CHECK-FIXES: {{^ }}int operator()() { return 1; }{{$}}
};
void test_lambda_functions() {
auto lamb_duh = [](void (*fn)(void)) { (*fn)(); };
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: {{.*}} in variable declaration
// CHECK-FIXES: {{^ }}auto lamb_duh = [](void (*fn)()) { (*fn)(); };{{$}}
auto lambda_generator = [](void) { return 1; };
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: {{.*}} in lambda expression
// CHECK-FIXES: {{^ }}auto lambda_generator = []() { return 1; };{{$}}
auto gen2 = []() { return 1; };
auto gen3 = []{ return 1; };
auto void_returner = [](void) -> void (*)(void) { return f1; };
// CHECK-MESSAGES: [[@LINE-1]]:27: warning: {{.*}} in lambda expression
// CHECK-MESSAGES: [[@LINE-2]]:45: warning: {{.*}} in lambda expression
// CHECK-FIXES: {{^ }}auto void_returner = []() -> void (*)() { return f1; };{{$}}
}