aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/tools/extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2024-03-13 13:58:24 +0300
committerthegeorg <thegeorg@yandex-team.com>2024-03-13 14:11:53 +0300
commit11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch)
treefabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/tools/extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
parent9685917341315774aad5733b1793b1e533a88bbb (diff)
downloadydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/tools/extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp')
-rw-r--r--contrib/libs/clang16/tools/extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp288
1 files changed, 288 insertions, 0 deletions
diff --git a/contrib/libs/clang16/tools/extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp b/contrib/libs/clang16/tools/extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
new file mode 100644
index 0000000000..53447c2b96
--- /dev/null
+++ b/contrib/libs/clang16/tools/extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
@@ -0,0 +1,288 @@
+//===- RedundantVoidArgCheck.cpp - clang-tidy -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RedundantVoidArgCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+// Determine if the given QualType is a nullary function or pointer to same.
+bool protoTypeHasNoParms(QualType QT) {
+ if (const auto *PT = QT->getAs<PointerType>())
+ QT = PT->getPointeeType();
+ if (auto *MPT = QT->getAs<MemberPointerType>())
+ QT = MPT->getPointeeType();
+ if (const 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
+
+void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(functionDecl(parameterCountIs(0), unless(isImplicit()),
+ unless(isInstantiated()), unless(isExternC()))
+ .bind(FunctionId),
+ this);
+ Finder->addMatcher(typedefNameDecl(unless(isImplicit())).bind(TypedefId),
+ this);
+ auto ParenFunctionType = parenType(innerType(functionType()));
+ auto PointerToFunctionType = pointee(ParenFunctionType);
+ auto FunctionOrMemberPointer =
+ anyOf(hasType(pointerType(PointerToFunctionType)),
+ hasType(memberPointerType(PointerToFunctionType)));
+ Finder->addMatcher(fieldDecl(FunctionOrMemberPointer).bind(FieldId), this);
+ Finder->addMatcher(varDecl(FunctionOrMemberPointer).bind(VarId), this);
+ auto CastDestinationIsFunction =
+ hasDestinationType(pointsTo(ParenFunctionType));
+ Finder->addMatcher(
+ cStyleCastExpr(CastDestinationIsFunction).bind(CStyleCastId), this);
+ Finder->addMatcher(
+ cxxStaticCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
+ Finder->addMatcher(
+ cxxReinterpretCastExpr(CastDestinationIsFunction).bind(NamedCastId),
+ this);
+ Finder->addMatcher(
+ cxxConstCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
+ Finder->addMatcher(lambdaExpr().bind(LambdaId), this);
+}
+
+void RedundantVoidArgCheck::check(const MatchFinder::MatchResult &Result) {
+ const BoundNodes &Nodes = Result.Nodes;
+ if (const auto *Function = Nodes.getNodeAs<FunctionDecl>(FunctionId))
+ processFunctionDecl(Result, Function);
+ else if (const auto *TypedefName =
+ Nodes.getNodeAs<TypedefNameDecl>(TypedefId))
+ processTypedefNameDecl(Result, TypedefName);
+ 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) {
+ const auto *Method = dyn_cast<CXXMethodDecl>(Function);
+ SourceLocation Start = Method && Method->getParent()->isLambda()
+ ? Method->getBeginLoc()
+ : Function->getLocation();
+ SourceLocation End = Function->getEndLoc();
+ if (Function->isThisDeclarationADefinition()) {
+ if (const Stmt *Body = Function->getBody()) {
+ End = Body->getBeginLoc();
+ if (End.isMacroID() &&
+ Result.SourceManager->isAtStartOfImmediateMacroExpansion(End))
+ End = Result.SourceManager->getExpansionLoc(End);
+ End = End.getLocWithOffset(-1);
+ }
+ removeVoidArgumentTokens(Result, SourceRange(Start, End),
+ "function definition");
+ } else
+ removeVoidArgumentTokens(Result, SourceRange(Start, End),
+ "function declaration");
+}
+
+bool isMacroIdentifier(const IdentifierTable &Idents, const Token &ProtoToken) {
+ if (!ProtoToken.is(tok::TokenKind::raw_identifier))
+ return false;
+
+ IdentifierTable::iterator It = Idents.find(ProtoToken.getRawIdentifier());
+ if (It == Idents.end())
+ return false;
+
+ return It->second->hadMacroDefinition();
+}
+
+void RedundantVoidArgCheck::removeVoidArgumentTokens(
+ const ast_matchers::MatchFinder::MatchResult &Result, SourceRange Range,
+ StringRef GrammarLocation) {
+ CharSourceRange CharRange =
+ Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Range),
+ *Result.SourceManager, getLangOpts());
+
+ std::string DeclText =
+ Lexer::getSourceText(CharRange, *Result.SourceManager, getLangOpts())
+ .str();
+ Lexer PrototypeLexer(CharRange.getBegin(), getLangOpts(), DeclText.data(),
+ DeclText.data(), DeclText.data() + DeclText.size());
+ enum class TokenState {
+ Start,
+ MacroId,
+ MacroLeftParen,
+ MacroArguments,
+ LeftParen,
+ Void,
+ };
+ TokenState State = TokenState::Start;
+ Token VoidToken;
+ Token ProtoToken;
+ const IdentifierTable &Idents = Result.Context->Idents;
+ int MacroLevel = 0;
+ std::string Diagnostic =
+ ("redundant void argument list in " + GrammarLocation).str();
+
+ while (!PrototypeLexer.LexFromRawLexer(ProtoToken)) {
+ switch (State) {
+ case TokenState::Start:
+ if (ProtoToken.is(tok::TokenKind::l_paren))
+ State = TokenState::LeftParen;
+ else if (isMacroIdentifier(Idents, ProtoToken))
+ State = TokenState::MacroId;
+ break;
+ case TokenState::MacroId:
+ if (ProtoToken.is(tok::TokenKind::l_paren))
+ State = TokenState::MacroLeftParen;
+ else
+ State = TokenState::Start;
+ break;
+ case TokenState::MacroLeftParen:
+ ++MacroLevel;
+ if (ProtoToken.is(tok::TokenKind::raw_identifier)) {
+ if (isMacroIdentifier(Idents, ProtoToken))
+ State = TokenState::MacroId;
+ else
+ State = TokenState::MacroArguments;
+ } else if (ProtoToken.is(tok::TokenKind::r_paren)) {
+ --MacroLevel;
+ if (MacroLevel == 0)
+ State = TokenState::Start;
+ else
+ State = TokenState::MacroId;
+ } else
+ State = TokenState::MacroArguments;
+ break;
+ case TokenState::MacroArguments:
+ if (isMacroIdentifier(Idents, ProtoToken))
+ State = TokenState::MacroLeftParen;
+ else if (ProtoToken.is(tok::TokenKind::r_paren)) {
+ --MacroLevel;
+ if (MacroLevel == 0)
+ State = TokenState::Start;
+ }
+ break;
+ case TokenState::LeftParen:
+ if (ProtoToken.is(tok::TokenKind::raw_identifier)) {
+ if (isMacroIdentifier(Idents, ProtoToken))
+ State = TokenState::MacroId;
+ else if (ProtoToken.getRawIdentifier() == "void") {
+ State = TokenState::Void;
+ VoidToken = ProtoToken;
+ }
+ } else if (ProtoToken.is(tok::TokenKind::l_paren))
+ State = TokenState::LeftParen;
+ else
+ State = TokenState::Start;
+ break;
+ case TokenState::Void:
+ State = TokenState::Start;
+ if (ProtoToken.is(tok::TokenKind::r_paren))
+ removeVoidToken(VoidToken, Diagnostic);
+ else if (ProtoToken.is(tok::TokenKind::l_paren))
+ State = TokenState::LeftParen;
+ break;
+ }
+ }
+
+ if (State == TokenState::Void && ProtoToken.is(tok::TokenKind::r_paren))
+ removeVoidToken(VoidToken, Diagnostic);
+}
+
+void RedundantVoidArgCheck::removeVoidToken(Token VoidToken,
+ StringRef Diagnostic) {
+ SourceLocation VoidLoc = VoidToken.getLocation();
+ diag(VoidLoc, Diagnostic) << FixItHint::CreateRemoval(VoidLoc);
+}
+
+void RedundantVoidArgCheck::processTypedefNameDecl(
+ const MatchFinder::MatchResult &Result,
+ const TypedefNameDecl *TypedefName) {
+ if (protoTypeHasNoParms(TypedefName->getUnderlyingType()))
+ removeVoidArgumentTokens(Result, TypedefName->getSourceRange(),
+ isa<TypedefDecl>(TypedefName) ? "typedef"
+ : "type alias");
+}
+
+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->getBeginLoc();
+ if (Var->hasInit()) {
+ SourceLocation InitStart =
+ Result.SourceManager->getExpansionLoc(Var->getInit()->getBeginLoc())
+ .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()) {
+ SourceManager *SM = Result.SourceManager;
+ TypeLoc TL = Lambda->getLambdaClass()->getLambdaTypeInfo()->getTypeLoc();
+ removeVoidArgumentTokens(Result,
+ {SM->getSpellingLoc(TL.getBeginLoc()),
+ SM->getSpellingLoc(TL.getEndLoc())},
+ "lambda expression");
+ }
+}
+
+} // namespace clang::tidy::modernize