[clang-tools-extra] r292918 - [clang-tidy] Avoid incorrect fixes in modernize-use-using

Alexander Kornienko via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 24 03:41:02 PST 2017


Author: alexfh
Date: Tue Jan 24 05:41:02 2017
New Revision: 292918

URL: http://llvm.org/viewvc/llvm-project?rev=292918&view=rev
Log:
[clang-tidy] Avoid incorrect fixes in modernize-use-using

Avoid fixes for typedefs with multiple types and for typedefs with struct
definitions. Partially addresses http://llvm.org/PR28334

Modified:
    clang-tools-extra/trunk/clang-tidy/modernize/UseUsingCheck.cpp
    clang-tools-extra/trunk/test/clang-tidy/modernize-use-using.cpp

Modified: clang-tools-extra/trunk/clang-tidy/modernize/UseUsingCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseUsingCheck.cpp?rev=292918&r1=292917&r2=292918&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseUsingCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseUsingCheck.cpp Tue Jan 24 05:41:02 2017
@@ -25,9 +25,10 @@ void UseUsingCheck::registerMatchers(Mat
 
 // Checks if 'typedef' keyword can be removed - we do it only if
 // it is the only declaration in a declaration chain.
-static bool CheckRemoval(SourceManager &SM, const SourceLocation &LocStart,
-                         const SourceLocation &LocEnd, ASTContext &Context) {
-  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(LocStart);
+static bool CheckRemoval(SourceManager &SM, SourceLocation StartLoc,
+                         ASTContext &Context) {
+  assert(StartLoc.isFileID() && "StartLoc must not be in a macro");
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(StartLoc);
   StringRef File = SM.getBufferData(LocInfo.first);
   const char *TokenBegin = File.data() + LocInfo.second;
   Lexer DeclLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
@@ -35,28 +36,39 @@ static bool CheckRemoval(SourceManager &
 
   Token Tok;
   int ParenLevel = 0;
+  bool FoundTypedef = false;
 
-  while (!DeclLexer.LexFromRawLexer(Tok)) {
-    if (SM.isBeforeInTranslationUnit(LocEnd, Tok.getLocation()))
-      break;
-    if (Tok.getKind() == tok::TokenKind::l_paren)
+  while (!DeclLexer.LexFromRawLexer(Tok) && !Tok.is(tok::semi)) {
+    switch (Tok.getKind()) {
+    case tok::l_brace:
+    case tok::r_brace:
+      // This might be the `typedef struct {...} T;` case.
+      return false;
+    case tok::l_paren:
       ParenLevel++;
-    if (Tok.getKind() == tok::TokenKind::r_paren)
+      break;
+    case tok::r_paren:
       ParenLevel--;
-    if (Tok.getKind() == tok::TokenKind::semi)
       break;
-    // if there is comma and we are not between open parenthesis then it is
-    // two or more declatarions in this chain
-    if (ParenLevel == 0 && Tok.getKind() == tok::TokenKind::comma)
-      return false;
-
-    if (Tok.is(tok::TokenKind::raw_identifier)) {
-      if (Tok.getRawIdentifier() == "typedef")
-        return true;
+    case tok::comma:
+      if (ParenLevel == 0) {
+        // If there is comma and we are not between open parenthesis then it is
+        // two or more declarations in this chain.
+        return false;
+      }
+      break;
+    case tok::raw_identifier:
+      if (Tok.getRawIdentifier() == "typedef") {
+        FoundTypedef = true;
+      }
+      break;
+    default:
+      break;
     }
   }
 
-  return false;
+  // Sanity check against weird macro cases.
+  return FoundTypedef;
 }
 
 void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
@@ -67,14 +79,19 @@ void UseUsingCheck::check(const MatchFin
   auto &Context = *Result.Context;
   auto &SM = *Result.SourceManager;
 
+  if (auto *D = MatchedDecl->getUnderlyingType()->getAsCXXRecordDecl()) {
+    //TypeLoc TL = MatchedDecl->getTypeSourceInfo()->getTypeLoc();
+    llvm::errs() << D->getNameAsString() << "\n";
+  }
+
   auto Diag =
       diag(MatchedDecl->getLocStart(), "use 'using' instead of 'typedef'");
 
-  if (MatchedDecl->getLocStart().isMacroID())
+  SourceLocation StartLoc = MatchedDecl->getLocStart();
+  if (StartLoc.isMacroID())
     return;
 
-  if (CheckRemoval(SM, MatchedDecl->getLocStart(), MatchedDecl->getLocEnd(),
-                   Context)) {
+  if (CheckRemoval(SM, StartLoc, Context)) {
     Diag << FixItHint::CreateReplacement(
         MatchedDecl->getSourceRange(),
         "using " + MatchedDecl->getNameAsString() + " = " +

Modified: clang-tools-extra/trunk/test/clang-tidy/modernize-use-using.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-using.cpp?rev=292918&r1=292917&r2=292918&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-using.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-using.cpp Tue Jan 24 05:41:02 2017
@@ -78,8 +78,13 @@ typedef Test<my_class *> another;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
 // CHECK-FIXES: using another = Test<my_class *>;
 
+typedef int* PInt;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using PInt = int *;
+
 typedef int bla1, bla2, bla3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef int bla1, bla2, bla3;
 
 #define CODE typedef int INT
 
@@ -131,8 +136,15 @@ int typedef Bax;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
 // CHECK-FIXES: using Bax = int;
 
-// FIXME: Avoid incorrect fixes in these cases.
-//typedef struct Q1 { int a; } S1;
-//typedef struct { int b; } S2;
-//struct Q2 { int c; } typedef S3;
-//struct { int d; } typedef S4;
+typedef struct Q1 { int a; } S1;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef struct Q1 { int a; } S1;
+typedef struct { int b; } S2;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef struct { int b; } S2;
+struct Q2 { int c; } typedef S3;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: struct Q2 { int c; } typedef S3;
+struct { int d; } typedef S4;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: struct { int d; } typedef S4;




More information about the cfe-commits mailing list