clang-tidy: [misc-use-override] Fix 'override' insertion.
authorDaniel Jasper <djasper@google.com>
Fri, 9 Jan 2015 13:56:35 +0000 (13:56 +0000)
committerDaniel Jasper <djasper@google.com>
Fri, 9 Jan 2015 13:56:35 +0000 (13:56 +0000)
Before:
  void f() __attribute__((override unused))

After:
  void f() override __attribute__((unused))

llvm-svn: 225519

clang-tools-extra/clang-tidy/misc/UseOverride.cpp
clang-tools-extra/test/clang-tidy/misc-use-override.cpp

index 2b9ef5b..04a920b 100644 (file)
@@ -23,15 +23,16 @@ void UseOverride::registerMatchers(MatchFinder *Finder) {
 
 // Re-lex the tokens to get precise locations to insert 'override' and remove
 // 'virtual'.
-static SmallVector<Token, 16> ParseTokens(CharSourceRange Range,
-                                          const SourceManager &Sources,
-                                          LangOptions LangOpts) {
+static SmallVector<Token, 16>
+ParseTokens(CharSourceRange Range, const MatchFinder::MatchResult &Result) {
+  const SourceManager &Sources = *Result.SourceManager;
   std::pair<FileID, unsigned> LocInfo =
       Sources.getDecomposedLoc(Range.getBegin());
   StringRef File = Sources.getBufferData(LocInfo.first);
   const char *TokenBegin = File.data() + LocInfo.second;
-  Lexer RawLexer(Sources.getLocForStartOfFile(LocInfo.first), LangOpts,
-                 File.begin(), TokenBegin, File.end());
+  Lexer RawLexer(Sources.getLocForStartOfFile(LocInfo.first),
+                 Result.Context->getLangOpts(), File.begin(), TokenBegin,
+                 File.end());
   SmallVector<Token, 16> Tokens;
   Token Tok;
   while (!RawLexer.LexFromRawLexer(Tok)) {
@@ -39,6 +40,12 @@ static SmallVector<Token, 16> ParseTokens(CharSourceRange Range,
       break;
     if (Sources.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation()))
       break;
+    if (Tok.is(tok::raw_identifier)) {
+      IdentifierInfo &Info = Result.Context->Idents.get(StringRef(
+          Sources.getCharacterData(Tok.getLocation()), Tok.getLength()));
+      Tok.setIdentifierInfo(&Info);
+      Tok.setKind(Info.getTokenID());
+    }
     Tokens.push_back(Tok);
   }
   return Tokens;
@@ -87,18 +94,25 @@ void UseOverride::check(const MatchFinder::MatchResult &Result) {
   // FIXME: Instead of re-lexing and looking for specific macros such as
   // 'ABSTRACT', properly store the location of 'virtual' and '= 0' in each
   // FunctionDecl.
-  SmallVector<Token, 16> Tokens = ParseTokens(FileRange, Sources,
-                                              Result.Context->getLangOpts());
+  SmallVector<Token, 16> Tokens = ParseTokens(FileRange, Result);
 
   // Add 'override' on inline declarations that don't already have it.
   if (!HasFinal && !HasOverride) {
     SourceLocation InsertLoc;
     StringRef ReplacementText = "override ";
 
+    for (Token T : Tokens) {
+      if (T.is(tok::kw___attribute)) {
+        InsertLoc = T.getLocation();
+        break;
+      }
+    }
+
     if (Method->hasAttrs()) {
       for (const clang::Attr *A : Method->getAttrs()) {
         if (!A->isImplicit()) {
-          SourceLocation Loc = Sources.getExpansionLoc(A->getLocation());
+          SourceLocation Loc =
+              Sources.getExpansionLoc(A->getRange().getBegin());
           if (!InsertLoc.isValid() ||
               Sources.isBeforeInTranslationUnit(Loc, InsertLoc))
             InsertLoc = Loc;
@@ -134,7 +148,7 @@ void UseOverride::check(const MatchFinder::MatchResult &Result) {
 
   if (Method->isVirtualAsWritten()) {
     for (Token Tok : Tokens) {
-      if (Tok.is(tok::raw_identifier) && GetText(Tok, Sources) == "virtual") {
+      if (Tok.is(tok::kw_virtual)) {
         Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
             Tok.getLocation(), Tok.getLocation()));
         break;
index d2e5a82..3d62e63 100644 (file)
@@ -29,6 +29,7 @@ struct Base {
   virtual bool n() MUST_USE_RESULT UNUSED;
 
   virtual void m();
+  virtual void o() __attribute__((unused));
 };
 
 struct SimpleCases : public Base {
@@ -84,6 +85,10 @@ public:
   virtual void m() override final;
   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Annotate this
   // CHECK-FIXES: {{^  void m\(\) final;}}
+
+  virtual void o() __attribute__((unused));
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Prefer using
+  // CHECK-FIXES: {{^  void o\(\) override __attribute__\(\(unused\)\);}}
 };
 
 // CHECK-MESSAGES-NOT: warning: