Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -8,6 +8,7 @@ NamespaceCommentCheck.cpp ReadabilityTidyModule.cpp RedundantSmartptrGet.cpp + RemoveVoidArg.cpp ShrinkToFitCheck.cpp LINK_LIBS Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -15,6 +15,7 @@ #include "ElseAfterReturnCheck.h" #include "FunctionSize.h" #include "RedundantSmartptrGet.h" +#include "RemoveVoidArg.h" #include "ShrinkToFitCheck.h" namespace clang { @@ -36,6 +37,7 @@ "readability-redundant-smartptr-get"); CheckFactories.registerCheck( "readability-shrink-to-fit"); + CheckFactories.registerCheck("readability-remove-void-arg"); } }; Index: clang-tidy/readability/RemoveVoidArg.h =================================================================== --- /dev/null +++ clang-tidy/readability/RemoveVoidArg.h @@ -0,0 +1,70 @@ +//===--- RemoveVoidArg.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_REMOVEVOIDARG_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REMOVEVOIDARG_H + +#include + +#include "../ClangTidy.h" +#include "clang/Lex/Token.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// \brief Find and remove redundant void argument lists. +/// +/// Examples: +/// int foo(void); ==> int foo(); +class RemoveVoidArg : public ClangTidyCheck +{ +public: + RemoveVoidArg(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, FunctionDecl const *const Function); + + void processTypedefDecl(const ast_matchers::MatchFinder::MatchResult &Result, TypedefDecl const *const Typedef); + + void processFieldDecl(const ast_matchers::MatchFinder::MatchResult &Result, FieldDecl const *const Member); + + void processVarDecl(const ast_matchers::MatchFinder::MatchResult &Result, VarDecl const *const Var); + + void processNamedCastExpr(const ast_matchers::MatchFinder::MatchResult &Result, CXXNamedCastExpr const *const NamedCast); + + void processCStyleCastExpr(const ast_matchers::MatchFinder::MatchResult &Result, CStyleCastExpr const *const CStyleCast); + + void processFunctionalCast(const ast_matchers::MatchFinder::MatchResult &Result, CXXFunctionalCastExpr const *const FunctionalCast); + + void processExplicitCastExpr(const ast_matchers::MatchFinder::MatchResult &Result, ExplicitCastExpr const *const ExplicitCast); + + void processLambdaExpr(const ast_matchers::MatchFinder::MatchResult &Result, LambdaExpr const *const Lambda); + + void removeVoidArgumentTokens( + const ast_matchers::MatchFinder::MatchResult &Result, + SourceLocation StartLoc, + std::string const &DeclText, + std::string const &Diagnostic); + + void removeVoidToken(Token VoidToken, std::string const &Diagnostic); +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REMOVEVOIDARG_H + Index: clang-tidy/readability/RemoveVoidArg.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/RemoveVoidArg.cpp @@ -0,0 +1,229 @@ +//===- RemoveVoidArg.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 "RemoveVoidArg.h" +#include "clang/Lex/Lexer.h" + +#include + +using namespace clang; +using namespace clang::ast_matchers; +using namespace llvm; +using clang::tooling::newFrontendActionFactory; +using clang::tooling::Replacement; +using clang::tooling::CompilationDatabase; + +namespace { + +// Returns the source text for a source range +inline StringRef getText(const MatchFinder::MatchResult &Result, + SourceRange Range) { + return Lexer::getSourceText( + CharSourceRange::getTokenRange(Range), + *Result.SourceManager, Result.Context->getLangOpts()); +} + +// Returns the source text for a pair of source locations. +inline StringRef getText(const MatchFinder::MatchResult &Result, + SourceLocation Begin, SourceLocation End) { + return getText(Result, SourceRange(Begin, End)); +} + +// Returns the text that makes up 'node' in the source. +// Returns an empty string if the text cannot be found. + +template +StringRef getText(const MatchFinder::MatchResult &Result, const T &Node) { + return getText(Result, Node.getSourceRange()); +} + +char const *const FunctionId = "fn"; +char const *const TypedefId = "td"; +char const *const FieldId = "fd"; +char const *const VarId = "var"; +char const *const NamedCastId = "nc"; +char const *const CStyleCastId = "csc"; +char const *const ExplicitCastId = "cast"; +char const *const FunctionalCastId = "fncast"; +char const *const LambdaId = "lambda"; + +} // namespace + +namespace clang { +namespace tidy { +namespace readability { + +void RemoveVoidArg::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(functionDecl(parameterCountIs(0), isExpansionInMainFile(), unless(isExternC())).bind(FunctionId), this); + Finder->addMatcher(typedefDecl(isExpansionInMainFile()).bind(TypedefId), this); + auto FunctionOrMemberPointer = anyOf(hasType(pointerType()), hasType(memberPointerType())); + Finder->addMatcher(fieldDecl(FunctionOrMemberPointer, isExpansionInMainFile()).bind(FieldId), this); + Finder->addMatcher(varDecl(FunctionOrMemberPointer, isExpansionInMainFile()).bind(VarId), this); + Finder->addMatcher(cStyleCastExpr(isExpansionInMainFile()).bind(CStyleCastId), this); + Finder->addMatcher(staticCastExpr(isExpansionInMainFile()).bind(NamedCastId), this); + Finder->addMatcher(reinterpretCastExpr(isExpansionInMainFile()).bind(NamedCastId), this); + Finder->addMatcher(constCastExpr(isExpansionInMainFile()).bind(NamedCastId), this); + Finder->addMatcher(functionalCastExpr(isExpansionInMainFile()).bind(FunctionalCastId), this); + Finder->addMatcher(lambdaExpr(isExpansionInMainFile()).bind(LambdaId), this); +} + +void RemoveVoidArg::check(const MatchFinder::MatchResult &Result) { + BoundNodes const &Nodes = Result.Nodes; + if (FunctionDecl const *const Function = Nodes.getNodeAs(FunctionId)) { + processFunctionDecl(Result, Function); + } else if (auto const Typedef = Nodes.getNodeAs(TypedefId)) { + processTypedefDecl(Result, Typedef); + } else if (auto const Member = Nodes.getNodeAs(FieldId)) { + processFieldDecl(Result, Member); + } else if (auto const Var = Nodes.getNodeAs(VarId)) { + processVarDecl(Result, Var); + } else if (auto const NamedCast = Nodes.getNodeAs(NamedCastId)) { + processNamedCastExpr(Result, NamedCast); + } else if (auto const CStyleCast = Nodes.getNodeAs(CStyleCastId)) { + processCStyleCastExpr(Result, CStyleCast); + } else if (auto const FunctionalCast = Nodes.getNodeAs(FunctionalCastId)) { + processFunctionalCast(Result, FunctionalCast); + } else if (auto const ExplicitCast = Nodes.getNodeAs(ExplicitCastId)) { + processExplicitCastExpr(Result, ExplicitCast); + } else if (auto const Lambda = Nodes.getNodeAs(LambdaId)) { + processLambdaExpr(Result, Lambda); + } +} + +void RemoveVoidArg::processFunctionDecl(const MatchFinder::MatchResult &Result, FunctionDecl const *const Function) { + SourceLocation const Start = Function->getLocStart(); + if (Function->isThisDeclarationADefinition()) { + SourceLocation const BeforeBody = Function->getBody()->getLocStart().getLocWithOffset(-1); + std::string const DeclText = getText(Result, Start, BeforeBody); + removeVoidArgumentTokens(Result, Start, DeclText, + "Redundant void argument list in function definition."); + } else { + std::string const Text = getText(Result, *Function); + removeVoidArgumentTokens(Result, Start, Text, + "Redundant void argument list in function declaration."); + } +} + +void RemoveVoidArg::removeVoidArgumentTokens( + const MatchFinder::MatchResult &Result, + SourceLocation StartLoc, + std::string const &DeclText, + std::string const &Diagnostic) +{ + clang::Lexer PrototypeLexer(StartLoc, Result.Context->getLangOpts(), + DeclText.c_str(), DeclText.c_str(), DeclText.c_str() + DeclText.length()); + enum TokenState { + NothingYet, + SawLeftParen, + SawVoid, + }; + TokenState State = NothingYet; + Token VoidToken; + Token ProtoToken; + 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::kw_void) + || (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 RemoveVoidArg::removeVoidToken(Token VoidToken, std::string const &Diagnostic) +{ + SourceLocation const VoidLoc(VoidToken.getLocation()); + SourceRange const VoidRange = SourceRange(VoidLoc, VoidLoc.getLocWithOffset(3)); + this->diag(VoidLoc, Diagnostic) << FixItHint::CreateRemoval(VoidRange); +} + +void RemoveVoidArg::processTypedefDecl(const MatchFinder::MatchResult &Result, TypedefDecl const *const Typedef) { + std::string const Text = getText(Result, *Typedef); + removeVoidArgumentTokens(Result, Typedef->getLocStart(), Text, "Redundant void argument list in typedef."); +} + +void RemoveVoidArg::processFieldDecl(const MatchFinder::MatchResult &Result, FieldDecl const *const Member) { + std::string const Text = getText(Result, *Member); + removeVoidArgumentTokens(Result, Member->getLocStart(), Text, "Redundant void argument list in field declaration."); +} + +void RemoveVoidArg::processVarDecl(const MatchFinder::MatchResult &Result, VarDecl const *const Var) { + SourceLocation const Begin = Var->getLocStart(); + if (Var->hasInit()) { + SourceLocation const InitStart = Var->getInit()->getLocStart().getLocWithOffset(-1); + std::string const Text = getText(Result, Begin, InitStart); + removeVoidArgumentTokens(Result, Begin, Text, + "Redundant void argument list in variable declaration with initializer."); + } else { + std::string const Text = getText(Result, *Var); + removeVoidArgumentTokens(Result, Begin, Text, "Redundant void argument list in variable declaration."); + } +} + +void RemoveVoidArg::processNamedCastExpr(const MatchFinder::MatchResult &Result, CXXNamedCastExpr const* const NamedCast) { + SourceRange const AngleBrackets = NamedCast->getAngleBrackets(); + SourceLocation const Begin = AngleBrackets.getBegin().getLocWithOffset(1); + SourceLocation const End = AngleBrackets.getEnd().getLocWithOffset(-1); + std::string const TemplateArgument = getText(Result, Begin, End); + removeVoidArgumentTokens(Result, Begin, TemplateArgument, "Redundant void argument list in named cast."); +} + +void RemoveVoidArg::processCStyleCastExpr(const MatchFinder::MatchResult &Result, CStyleCastExpr const* const CStyleCast) { + SourceLocation const Begin = CStyleCast->getLParenLoc().getLocWithOffset(1); + SourceLocation End = CStyleCast->getRParenLoc().getLocWithOffset(-1); + std::string ExprText = getText(Result, Begin, End); + removeVoidArgumentTokens(Result, Begin, ExprText, "Redundant void argument list in C style cast."); +} + +void RemoveVoidArg::processFunctionalCast(const MatchFinder::MatchResult &Result, CXXFunctionalCastExpr const *const FunctionalCast) { + SourceLocation const Begin = FunctionalCast->getLocStart(); + std::string ExprText = getText(Result, Begin, FunctionalCast->getLParenLoc().getLocWithOffset(-1)); + removeVoidArgumentTokens(Result, Begin, ExprText, "Redundant void argument list in functional cast."); +} + +void RemoveVoidArg::processExplicitCastExpr(const MatchFinder::MatchResult &Result, ExplicitCastExpr const* const ExplicitCast) { + std::string const ExprText = getText(Result, *ExplicitCast); + removeVoidArgumentTokens(Result, ExplicitCast->getLocStart(), ExprText, "Redundant void argument list in explicit cast."); +} + +void RemoveVoidArg::processLambdaExpr(const ast_matchers::MatchFinder::MatchResult &Result, LambdaExpr const *const Lambda) { + bool const HasNoParams = Lambda->getLambdaClass()->getLambdaCallOperator()->getNumParams() == 0; + if (Lambda->hasExplicitParameters() && HasNoParams) { + SourceLocation Begin = Lambda->getIntroducerRange().getEnd().getLocWithOffset(1); + SourceLocation End = Lambda->getBody()->getLocStart().getLocWithOffset(-1); + std::string const LambdaProtoText = getText(Result, Begin, End); + removeVoidArgumentTokens(Result, Begin, LambdaProtoText, "Redundant void argument list in lambda expression."); + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: test/clang-tidy/readability-remove-void-arg.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-remove-void-arg.cpp @@ -0,0 +1,369 @@ +// RUN: $(dirname %s)/check_clang_tidy.sh %s readability-remove-void-arg %t +// REQUIRES: shell + +#include + +int foo(); + +void bar(); + +void bar2(); + +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. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}int foo(){{$}} +{ + return 0; +} + +// 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: Redundant void argument list in function declaration. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: Redundant void argument list in function declaration. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}int (*returns_fn_void_int())();{{$}} + +typedef int (*returns_fn_void_int_t(void))(void); +// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-2]]:44: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}typedef int (*returns_fn_void_int_t())();{{$}} + +int (*returns_fn_void_int(void))(void) +// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// 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: Redundant void argument list in function declaration. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: Redundant void argument list in function declaration. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: Redundant void argument list in function declaration. [readability-remove-void-arg] +// 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: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-2]]:59: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-3]]:66: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// 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: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-2]]:49: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-3]]:56: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (*(*returns_fn_returns_fn_void_void())())(){{$}} +{ + return nullptr; +} + +void bar(void) +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void bar(){{$}} +{ +} + +class gronk +{ +public: + gronk(); + ~gronk(); + + void foo(); + void bar(); + void bar2 + (); + +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: Redundant void argument list in field declaration. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (*f1)();{{$}} + + void (gronk::*p1)(void); + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: Redundant void argument list in field declaration. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (gronk::*p1)();{{$}} +}; + +int i; +int *pi; +float f; +float *fi; +double d; +double *pd; + +void (*f1)(void); +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Redundant void argument list in variable declaration. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (*f1)();{{$}} + +void (*f2)(void) = nullptr; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (*f2)() = nullptr;{{$}} + +void (*f2b)(void)(nullptr); +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (*f2b)()(nullptr);{{$}} + +void (*f2c)(void){nullptr}; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (*f2c)(){nullptr};{{$}} + +void (*f3)(void) = bar; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (*f3)() = bar;{{$}} + +void (*fa)(); + +void (*fb)() = nullptr; + +void (*fc)() = bar; + +typedef void (function_ptr)(void); +// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}typedef void (function_ptr)();{{$}} + +typedef void (function_ptr2) + ( + void + ); +// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}typedef void (function_ptr2){{$}} +// CHECK-FIXES-NEXT: {{^ }}({{$}} +// CHECK-FIXES-NEXT: {{^ $}} +// CHECK-FIXES-NEXT: {{^ }});{{$}} + +typedef +void +( +* +( +* +returns_fn_returns_fn_void_void_t2 +( +void +) +) +( +void +) +) +( +void +) +; +// CHECK-MESSAGES: :[[@LINE-11]]:1: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-8]]:1: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-MESSAGES: :[[@LINE-5]]:1: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// 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: Redundant void argument list in variable declaration. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (gronk::*p1)();{{$}} + +void (gronk::*p2)(void) = &gronk::foo; +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void (gronk::*p2)() = &gronk::foo;{{$}} + +typedef void (gronk::*member_function_ptr)(void); +// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}typedef void (gronk::*member_function_ptr)();{{$}} + +typedef void (gronk::*member_function_ptr2) + ( + void + ); +// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: Redundant void argument list in typedef. [readability-remove-void-arg] +// 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]]:16: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (*f1)() = &::bar;{{$}} + + void (*f2)(void); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Redundant void argument list in variable declaration. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (*f2)();{{$}} + + void (*f3) + ( + void + ); + // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: Redundant void argument list in variable declaration. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (*f3){{$}} + // CHECK-FIXES-NEXT: {{^ }}({{$}} + // CHECK-FIXES-NEXT: {{^ $}} + // CHECK-FIXES-NEXT: {{^ }});{{$}} +} + +void gronk::bar(void) +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void gronk::bar(){{$}} +{ + void (gronk::*p3)(void) = &gronk::foo; + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (gronk::*p3)() = &gronk::foo;{{$}} + + void (gronk::*p4)(void); + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: Redundant void argument list in variable declaration. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (gronk::*p4)();{{$}} + + void (gronk::*p5) + ( + void + ); + // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: Redundant void argument list in variable declaration. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (gronk::*p5){{$}} + // CHECK-FIXES-NEXT: {{^ }}({{$}} + // CHECK-FIXES-NExT: {{^ $}} + // CHECK-FIXES-NExT: {{^ }});{{$}} +} + +void gronk::bar2 + ( + void + ) +// CHECK-MESSAGES: :[[@LINE-2]]:5: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}void gronk::bar2{{$}} +// CHECK-FIXES-NEXT: {{^ }}({{$}} +// CHECK-FIXES-NEXT: {{^ $}} +// CHECK-FIXES-NEXT: {{^ }}){{$}} +{ +} + +gronk::gronk(void) +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}gronk::gronk(){{$}} + : f1(nullptr), + p1(nullptr) +{ +} + +gronk::~gronk(void) +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}gronk::~gronk(){{$}} +{ +} + +class nutter +{ +public: + nutter(); +}; + +nutter::nutter(void) +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Redundant void argument list in function definition. [readability-remove-void-arg] +// CHECK-FIXES: {{^}}nutter::nutter(){{$}} +{ + void (*f3)(void) = static_cast(0); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: Redundant void argument list in named cast. [readability-remove-void-arg] + // CHECK-FIXES: void (*f3)() = static_cast(0);{{$}} + + void (*f4)(void) = (void (*)(void)) 0; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: Redundant void argument list in C style cast. [readability-remove-void-arg] + // CHECK-FIXES: void (*f4)() = (void (*)()) 0;{{$}} + + void (*f5)(void) = reinterpret_cast(0); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-MESSAGES: :[[@LINE-2]]:50: warning: Redundant void argument list in named cast. [readability-remove-void-arg] + // CHECK-FIXES: void (*f5)() = reinterpret_cast(0);{{$}} + + void (*f6)(void) = static_cast(0); + // CHECK-MESSAGES: :[[@LINE-4]]:16: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: Redundant void argument list in named cast. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (*f6)() = static_cast(0);{{$}} + + void (*f7)(void) = (void (*) + ( + void + )) 0; + // CHECK-MESSAGES: :[[@LINE-4]]:16: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: Redundant void argument list in C style cast. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (*f7)() = (void (*){{$}} + // CHECK-FIXES-NEXT: {{^ }}({{$}} + // CHECK-FIXES-NEXT: {{^ }} + // CHECK-FIXES-NEXT: {{^ }})) 0;{{$}} + + void (*f8)(void) = reinterpret_cast(0); + // CHECK-MESSAGES: :[[@LINE-4]]:16: warning: Redundant void argument list in variable declaration with initializer. [readability-remove-void-arg] + // CHECK-MESSAGES: :[[@LINE-3]]:13: warning: Redundant void argument list in named cast. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}void (*f8)() = reinterpret_cast(0);{{$}} +} + +class generator +{ +public: + int operator()(void) { return 1; } + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: Redundant void argument list in function definition. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}int operator()() { return 1; }{{$}} +}; + +void test_lambda_functions() +{ + auto lamb_duh = [](void (*fn)(void)) { (*fn)(); }; + // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: Redundant void argument list in variable declaration. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}auto lamb_duh = [](void (*fn)()) { (*fn)(); };{{$}} + + auto lambda_generator = [](void) { return 1; }; + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: Redundant void argument list in lambda expression. [readability-remove-void-arg] + // 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]]:29: warning: Redundant void argument list in lambda expression. [readability-remove-void-arg] + // CHECK-MESSAGES: [[@LINE-2]]:47: warning: Redundant void argument list in lambda expression. [readability-remove-void-arg] + // CHECK-FIXES: {{^ }}auto void_returner = []() -> void (*)() { return f1; };{{$}} +}