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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits