[clang-tidy] google-runtime-int: fix a false positive in implicit code.
authorAlexander Kornienko <alexfh@google.com>
Thu, 11 Feb 2016 16:22:58 +0000 (16:22 +0000)
committerAlexander Kornienko <alexfh@google.com>
Thu, 11 Feb 2016 16:22:58 +0000 (16:22 +0000)
llvm-svn: 260535

clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp
clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h
clang-tools-extra/test/clang-tidy/google-runtime-int.cpp

index 0ac3124..0045812 100644 (file)
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/CharInfo.h"
+#include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Lexer.h"
 
 namespace clang {
+
+using namespace ast_matchers;
+
+static Token getTokenAtLoc(SourceLocation Loc,
+                           const MatchFinder::MatchResult &MatchResult,
+                           IdentifierTable &IdentTable) {
+  Token Tok;
+  if (Lexer::getRawToken(Loc, Tok, *MatchResult.SourceManager,
+                         MatchResult.Context->getLangOpts(), false))
+    return Tok;
+
+  if (Tok.is(tok::raw_identifier)) {
+    IdentifierInfo &Info = IdentTable.get(Tok.getRawIdentifier());
+    Tok.setIdentifierInfo(&Info);
+    Tok.setKind(Info.getTokenID());
+  }
+  return Tok;
+}
+
 namespace tidy {
 namespace google {
 namespace runtime {
 
-using namespace ast_matchers;
 
 IntegerTypesCheck::IntegerTypesCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
@@ -35,8 +55,10 @@ void IntegerTypesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
 
 void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
   // Find all TypeLocs. The relevant Style Guide rule only applies to C++.
-  if (getLangOpts().CPlusPlus)
-    Finder->addMatcher(typeLoc(loc(isInteger())).bind("tl"), this);
+  if (!getLangOpts().CPlusPlus)
+    return;
+  Finder->addMatcher(typeLoc(loc(isInteger())).bind("tl"), this);
+  IdentTable = llvm::make_unique<IdentifierTable>(getLangOpts());
 }
 
 void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) {
@@ -54,6 +76,15 @@ void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) {
   if (!BuiltinLoc)
     return;
 
+  Token Tok = getTokenAtLoc(Loc, Result, *IdentTable);
+  // Ensure the location actually points to one of the builting integral type
+  // names we're interested in. Otherwise, we might be getting this match from
+  // implicit code (e.g. an implicit assignment operator of a class containing
+  // an array of non-POD types).
+  if (!Tok.isOneOf(tok::kw_short, tok::kw_long, tok::kw_unsigned,
+                   tok::kw_signed))
+    return;
+
   bool IsSigned;
   unsigned Width;
   const TargetInfo &TargetInfo = Result.Context->getTargetInfo();
index c7193c0..8d8f903 100644 (file)
 
 #include "../ClangTidy.h"
 
+#include <memory>
+
 namespace clang {
+
+class IdentifierTable;
+
 namespace tidy {
 namespace google {
 namespace runtime {
@@ -32,6 +37,8 @@ private:
   const std::string UnsignedTypePrefix;
   const std::string SignedTypePrefix;
   const std::string TypeSuffix;
+
+  std::unique_ptr<IdentifierTable> IdentTable;
 };
 
 } // namespace runtime
index bcf6eb6..e51ca7d 100644 (file)
@@ -65,3 +65,10 @@ struct some_value {};
 constexpr some_value operator"" _some_literal(unsigned long long int i);
 // CHECK-MESSAGES: [[@LINE-1]]:47: warning: consider replacing 'unsigned long long'
 
+struct A { A& operator=(const A&); };
+class B { A a[0]; };
+
+void fff() {
+  B a, b;
+  a = b;
+}