LegalizeAdulthood updated this revision to Diff 398281.
LegalizeAdulthood edited the summary of this revision.
LegalizeAdulthood added a comment.

Add more test cases and improve the Lexing state machine


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116425/new/

https://reviews.llvm.org/D116425

Files:
  clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
@@ -199,6 +199,7 @@
 // CHECK-FIXES-NEXT: {{^    \);$}}
 
 // intentionally not LLVM style to check preservation of whitespace
+// clang-format off
 typedef
 void
 (
@@ -240,7 +241,7 @@
 // CHECK-FIXES-NOT:  {{[^ ]}}
 // CHECK-FIXES:      {{^\)$}}
 // CHECK-FIXES-NEXT: {{^;$}}
-
+// clang-format on
 
 void (gronk::*p1)(void);
 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} in variable declaration
@@ -556,3 +557,38 @@
   S_3<int>();
   g_3<int>();
 }
+
+#define return_t(T) T
+extern return_t(void) func(void);
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: redundant void argument list in function declaration
+// CHECK-FIXES: extern return_t(void) func();
+
+return_t(void) func(void) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: redundant void argument list in function definition
+  // CHECK-FIXES: return_t(void) func() {
+  int a;
+  (void)a;
+}
+
+extern return_t(void) func(return_t(void) (*fp)(void));
+// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: redundant void argument list in variable declaration
+// CHECK-FIXES: extern return_t(void) func(return_t(void) (*fp)());
+
+return_t(void) func(return_t(void) (*fp)(void)) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:42: warning: redundant void argument list in variable declaration
+  // CHECK-FIXES: return_t(void) func(return_t(void) (*fp)()) {
+  int a;
+  (void)a;
+}
+
+extern return_t(return_t(void)) func2(return_t(return_t(void)) (*fp)(void));
+// CHECK-MESSAGES: :[[@LINE-1]]:70: warning: redundant void argument list in variable declaration
+// CHECK-FIXES: extern return_t(return_t(void)) func2(return_t(return_t(void)) (*fp)());
+
+return_t(return_t(void)) func2(return_t(return_t(void)) (*fp)(void)) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: redundant void argument list in variable declaration
+  // CHECK-FIXES: return_t(return_t(void)) func2(return_t(return_t(void)) (*fp)()) {
+  int a;
+  (void)a;
+}
+#undef return_t
Index: clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp
@@ -48,7 +48,7 @@
                                   unless(isInstantiated()), unless(isExternC()))
                          .bind(FunctionId),
                      this);
-  Finder->addMatcher(typedefNameDecl().bind(TypedefId), this);
+  Finder->addMatcher(typedefNameDecl(unless(isImplicit())).bind(TypedefId), this);
   auto ParenFunctionType = parenType(innerType(functionType()));
   auto PointerToFunctionType = pointee(ParenFunctionType);
   auto FunctionOrMemberPointer =
@@ -97,9 +97,12 @@
 
 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()) {
-    SourceLocation Start = Function->getBeginLoc();
-    SourceLocation End = Function->getEndLoc();
     if (const Stmt *Body = Function->getBody()) {
       End = Body->getBeginLoc();
       if (End.isMacroID() &&
@@ -110,11 +113,16 @@
     removeVoidArgumentTokens(Result, SourceRange(Start, End),
                              "function definition");
   } else {
-    removeVoidArgumentTokens(Result, Function->getSourceRange(),
+    removeVoidArgumentTokens(Result, SourceRange(Start, End),
                              "function declaration");
   }
 }
 
+bool isMacroIdentifier(IdentifierTable &Idents, const Token &ProtoToken) {
+  return ProtoToken.is(tok::TokenKind::raw_identifier) &&
+         Idents.get(ProtoToken.getRawIdentifier()).hadMacroDefinition();
+}
+
 void RedundantVoidArgCheck::removeVoidArgumentTokens(
     const ast_matchers::MatchFinder::MatchResult &Result, SourceRange Range,
     StringRef GrammarLocation) {
@@ -127,47 +135,93 @@
           .str();
   Lexer PrototypeLexer(CharRange.getBegin(), getLangOpts(), DeclText.data(),
                        DeclText.data(), DeclText.data() + DeclText.size());
-  enum TokenState {
-    NothingYet,
-    SawLeftParen,
-    SawVoid,
+  enum class TokenState {
+    Start,
+    MacroId,
+    MacroLeftParen,
+    MacroArguments,
+    LeftParen,
+    Void,
   };
-  TokenState State = NothingYet;
+  TokenState State = TokenState::Start;
   Token VoidToken;
   Token ProtoToken;
+  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 NothingYet:
+    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 = SawLeftParen;
+        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 SawLeftParen:
-      if (ProtoToken.is(tok::TokenKind::raw_identifier) &&
-          ProtoToken.getRawIdentifier() == "void") {
-        State = SawVoid;
-        VoidToken = ProtoToken;
+    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 = SawLeftParen;
+        State = TokenState::LeftParen;
       } else {
-        State = NothingYet;
+        State = TokenState::Start;
       }
       break;
-    case SawVoid:
-      State = NothingYet;
+    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 = SawLeftParen;
+        State = TokenState::LeftParen;
       }
       break;
     }
   }
 
-  if (State == SawVoid && ProtoToken.is(tok::TokenKind::r_paren)) {
+  if (State == TokenState::Void && ProtoToken.is(tok::TokenKind::r_paren)) {
     removeVoidToken(VoidToken, Diagnostic);
   }
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to