Bug 1324325 - Port the muse-use check to the clang-tidy compatible framework; r=mystor
authorEhsan Akhgari <ehsan@mozilla.com>
Sun, 18 Dec 2016 20:30:47 -0500
changeset 327520 0da90da58ab7c914e79ab184c834b5f38d5b06f3
parent 327519 7d0b2be362337907af5b11f038900a0bf28b5c67
child 327521 20134b5c4194fc6ed826e1f22dc2e4afd3b68cdc
push id35517
push userkwierso@gmail.com
push dateThu, 29 Dec 2016 20:22:54 +0000
treeherderautoland@3f2f8d77ad27 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1324325
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1324325 - Port the muse-use check to the clang-tidy compatible framework; r=mystor
build/clang-plugin/Checks.inc
build/clang-plugin/ChecksIncludes.inc
build/clang-plugin/CustomMatchers.h
build/clang-plugin/CustomTypeAnnotation.cpp
build/clang-plugin/CustomTypeAnnotation.h
build/clang-plugin/MozChecker.cpp
build/clang-plugin/MozChecker.h
build/clang-plugin/MustUseChecker.cpp
build/clang-plugin/MustUseChecker.h
build/clang-plugin/moz.build
--- a/build/clang-plugin/Checks.inc
+++ b/build/clang-plugin/Checks.inc
@@ -5,16 +5,17 @@
 // The list of checker classes that are compatible with clang-tidy.
 
 CHECK(ArithmeticArgChecker, "arithmetic-argument")
 CHECK(AssertAssignmentChecker, "assignment-in-assert")
 CHECK(ExplicitImplicitChecker, "implicit-constructor")
 CHECK(ExplicitOperatorBoolChecker, "explicit-operator-bool")
 CHECK(KungFuDeathGripChecker, "kungfu-death-grip")
 CHECK(MustOverrideChecker, "must-override")
+CHECK(MustUseChecker, "must-use")
 CHECK(NaNExprChecker, "nan-expr")
 CHECK(NeedsNoVTableTypeChecker, "needs-no-vtable-type")
 CHECK(NoAddRefReleaseOnReturnChecker, "no-addref-release-on-return")
 CHECK(NoAutoTypeChecker, "no-auto-type")
 CHECK(NoDuplicateRefCntMemberChecker, "no-duplicate-refcnt-member")
 CHECK(NoExplicitMoveConstructorChecker, "no-explicit-move-constructor")
 CHECK(NonMemMovableMemberChecker, "non-memmovable-member")
 CHECK(NonMemMovableTemplateArgChecker, "non-memmovable-template-arg")
--- a/build/clang-plugin/ChecksIncludes.inc
+++ b/build/clang-plugin/ChecksIncludes.inc
@@ -6,16 +6,17 @@
 // are compatible with clang-tidy.
 
 #include "ArithmeticArgChecker.h"
 #include "AssertAssignmentChecker.h"
 #include "ExplicitImplicitChecker.h"
 #include "ExplicitOperatorBoolChecker.h"
 #include "KungFuDeathGripChecker.h"
 #include "MustOverrideChecker.h"
+#include "MustUseChecker.h"
 #include "NaNExprChecker.h"
 #include "NeedsNoVTableTypeChecker.h"
 #include "NoAddRefReleaseOnReturnChecker.h"
 #include "NoAutoTypeChecker.h"
 #include "NoDuplicateRefCntMemberChecker.h"
 #include "NoExplicitMoveConstructorChecker.h"
 #include "NonMemMovableMemberChecker.h"
 #include "NonMemMovableTemplateArgChecker.h"
--- a/build/clang-plugin/CustomMatchers.h
+++ b/build/clang-plugin/CustomMatchers.h
@@ -59,16 +59,22 @@ AST_MATCHER(UnaryOperator, unaryArithmet
 }
 
 /// This matcher will match == and != binary operators.
 AST_MATCHER(BinaryOperator, binaryEqualityOperator) {
   BinaryOperatorKind OpCode = Node.getOpcode();
   return OpCode == BO_EQ || OpCode == BO_NE;
 }
 
+/// This matcher will match comma operator.
+AST_MATCHER(BinaryOperator, binaryCommaOperator) {
+  BinaryOperatorKind OpCode = Node.getOpcode();
+  return OpCode == BO_Comma;
+}
+
 /// This matcher will match floating point types.
 AST_MATCHER(QualType, isFloat) { return Node->isRealFloatingType(); }
 
 /// This matcher will match locations in system headers.  This is adopted from
 /// isExpansionInSystemHeader in newer clangs, but modified in order to work
 /// with old clangs that we use on infra.
 AST_MATCHER(BinaryOperator, isInSystemHeader) {
   return ASTIsInSystemHeader(Finder->getASTContext(), Node);
--- a/build/clang-plugin/CustomTypeAnnotation.cpp
+++ b/build/clang-plugin/CustomTypeAnnotation.cpp
@@ -10,18 +10,16 @@ CustomTypeAnnotation StackClass =
 CustomTypeAnnotation GlobalClass =
     CustomTypeAnnotation("moz_global_class", "global");
 CustomTypeAnnotation NonHeapClass =
     CustomTypeAnnotation("moz_nonheap_class", "non-heap");
 CustomTypeAnnotation HeapClass =
     CustomTypeAnnotation("moz_heap_class", "heap");
 CustomTypeAnnotation NonTemporaryClass =
     CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
-CustomTypeAnnotation MustUse =
-    CustomTypeAnnotation("moz_must_use_type", "must-use");
 CustomTypeAnnotation NonParam =
     CustomTypeAnnotation("moz_non_param", "non-param");
 
 void CustomTypeAnnotation::dumpAnnotationReason(DiagnosticsEngine &Diag,
                                                 QualType T,
                                                 SourceLocation Loc) {
   unsigned InheritsID = Diag.getDiagnosticIDs()->getCustomDiagID(
       DiagnosticIDs::Note,
--- a/build/clang-plugin/CustomTypeAnnotation.h
+++ b/build/clang-plugin/CustomTypeAnnotation.h
@@ -64,12 +64,11 @@ protected:
   virtual bool hasFakeAnnotation(const TagDecl *D) const { return false; }
 };
 
 extern CustomTypeAnnotation StackClass;
 extern CustomTypeAnnotation GlobalClass;
 extern CustomTypeAnnotation NonHeapClass;
 extern CustomTypeAnnotation HeapClass;
 extern CustomTypeAnnotation NonTemporaryClass;
-extern CustomTypeAnnotation MustUse;
 extern CustomTypeAnnotation NonParam;
 
 #endif
--- a/build/clang-plugin/MozChecker.cpp
+++ b/build/clang-plugin/MozChecker.cpp
@@ -1,81 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MozChecker.h"
 #include "CustomTypeAnnotation.h"
 #include "Utils.h"
 
-void MozChecker::HandleTranslationUnit(ASTContext &Ctx) {
-  TraverseDecl(Ctx.getTranslationUnitDecl());
-}
-
 bool MozChecker::hasCustomAnnotation(const Decl *D, const char *Spelling) {
   iterator_range<specific_attr_iterator<AnnotateAttr>> Attrs =
       D->specific_attrs<AnnotateAttr>();
 
   for (AnnotateAttr *Attr : Attrs) {
     if (Attr->getAnnotation() == Spelling) {
       return true;
     }
   }
 
   return false;
 }
-
-void MozChecker::handleUnusedExprResult(const Stmt *Statement) {
-  const Expr *E = dyn_cast_or_null<Expr>(Statement);
-  if (E) {
-    E = E->IgnoreImplicit(); // Ignore ExprWithCleanup etc. implicit wrappers
-    QualType T = E->getType();
-    if (MustUse.hasEffectiveAnnotation(T) && !isIgnoredExprForMustUse(E)) {
-      unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
-          DiagnosticIDs::Error, "Unused value of must-use type %0");
-
-      Diag.Report(E->getLocStart(), ErrorID) << T;
-      MustUse.dumpAnnotationReason(Diag, T, E->getLocStart());
-    }
-  }
-}
-
-bool MozChecker::VisitSwitchCase(SwitchCase *Statement) {
-  handleUnusedExprResult(Statement->getSubStmt());
-  return true;
-}
-
-bool MozChecker::VisitCompoundStmt(CompoundStmt *Statement) {
-  for (CompoundStmt::body_iterator It = Statement->body_begin(),
-                                   E = Statement->body_end();
-       It != E; ++It) {
-    handleUnusedExprResult(*It);
-  }
-  return true;
-}
-
-bool MozChecker::VisitIfStmt(IfStmt *Statement) {
-  handleUnusedExprResult(Statement->getThen());
-  handleUnusedExprResult(Statement->getElse());
-  return true;
-}
-
-bool MozChecker::VisitWhileStmt(WhileStmt *Statement) {
-  handleUnusedExprResult(Statement->getBody());
-  return true;
-}
-
-bool MozChecker::VisitDoStmt(DoStmt *Statement) {
-  handleUnusedExprResult(Statement->getBody());
-  return true;
-}
-
-bool MozChecker::VisitForStmt(ForStmt *Statement) {
-  handleUnusedExprResult(Statement->getBody());
-  handleUnusedExprResult(Statement->getInit());
-  handleUnusedExprResult(Statement->getInc());
-  return true;
-}
-
-bool MozChecker::VisitBinComma(BinaryOperator *Op) {
-  handleUnusedExprResult(Op->getLHS());
-  return true;
-}
--- a/build/clang-plugin/MozChecker.h
+++ b/build/clang-plugin/MozChecker.h
@@ -3,34 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MozChecker_h__
 #define MozChecker_h__
 
 #include "DiagnosticsMatcher.h"
 
 class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
-  DiagnosticsEngine &Diag;
   DiagnosticsMatcher Matcher;
 
 public:
   MozChecker(CompilerInstance &CI) :
-    Diag(CI.getDiagnostics()), Matcher(CI) {}
+    Matcher(CI) {}
   virtual ~MozChecker() {}
 
   ASTConsumerPtr getOtherConsumer() { return Matcher.makeASTConsumer(); }
 
-  virtual void HandleTranslationUnit(ASTContext &Ctx) override;
-
   static bool hasCustomAnnotation(const Decl *D, const char *Spelling);
-
-  void handleUnusedExprResult(const Stmt *Statement);
-
-  bool VisitSwitchCase(SwitchCase *Statement);
-  bool VisitCompoundStmt(CompoundStmt *Statement);
-  bool VisitIfStmt(IfStmt *Statement);
-  bool VisitWhileStmt(WhileStmt *Statement);
-  bool VisitDoStmt(DoStmt *Statement);
-  bool VisitForStmt(ForStmt *Statement);
-  bool VisitBinComma(BinaryOperator *Op);
 };
 
 #endif
new file mode 100644
--- /dev/null
+++ b/build/clang-plugin/MustUseChecker.cpp
@@ -0,0 +1,63 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MustUseChecker.h"
+#include "CustomMatchers.h"
+#include "CustomTypeAnnotation.h"
+
+CustomTypeAnnotation MustUse =
+    CustomTypeAnnotation("moz_must_use_type", "must-use");
+
+void MustUseChecker::registerMatchers(MatchFinder* AstMatcher) {
+  AstMatcher->addMatcher(switchCase().bind("switchcase"), this);
+  AstMatcher->addMatcher(compoundStmt().bind("compound"), this);
+  AstMatcher->addMatcher(ifStmt().bind("if"), this);
+  AstMatcher->addMatcher(whileStmt().bind("while"), this);
+  AstMatcher->addMatcher(doStmt().bind("do"), this);
+  AstMatcher->addMatcher(forStmt().bind("for"), this);
+  AstMatcher->addMatcher(binaryOperator(binaryCommaOperator()).bind("bin"), this);
+}
+
+void MustUseChecker::check(
+    const MatchFinder::MatchResult &Result) {
+  if (auto SC = Result.Nodes.getNodeAs<SwitchCase>("switchcase")) {
+    handleUnusedExprResult(SC->getSubStmt());
+  }
+  if (auto C = Result.Nodes.getNodeAs<CompoundStmt>("compound")) {
+    for (const auto& S : C->body()) {
+      handleUnusedExprResult(S);
+    }
+  }
+  if (auto IF = Result.Nodes.getNodeAs<IfStmt>("if")) {
+    handleUnusedExprResult(IF->getThen());
+    handleUnusedExprResult(IF->getElse());
+  }
+  if (auto W = Result.Nodes.getNodeAs<WhileStmt>("while")) {
+    handleUnusedExprResult(W->getBody());
+  }
+  if (auto D = Result.Nodes.getNodeAs<DoStmt>("do")) {
+    handleUnusedExprResult(D->getBody());
+  }
+  if (auto F = Result.Nodes.getNodeAs<ForStmt>("for")) {
+    handleUnusedExprResult(F->getBody());
+    handleUnusedExprResult(F->getInit());
+    handleUnusedExprResult(F->getInc());
+  }
+  if (auto C = Result.Nodes.getNodeAs<BinaryOperator>("bin")) {
+    handleUnusedExprResult(C->getLHS());
+  }
+}
+
+void MustUseChecker::handleUnusedExprResult(const Stmt *Statement) {
+  const Expr *E = dyn_cast_or_null<Expr>(Statement);
+  if (E) {
+    E = E->IgnoreImplicit(); // Ignore ExprWithCleanup etc. implicit wrappers
+    QualType T = E->getType();
+    if (MustUse.hasEffectiveAnnotation(T) && !isIgnoredExprForMustUse(E)) {
+      diag(E->getLocStart(), "Unused value of must-use type %0",
+           DiagnosticIDs::Error) << T;
+      MustUse.dumpAnnotationReason(*this, T, E->getLocStart());
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/build/clang-plugin/MustUseChecker.h
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MustUseChecker_h__
+#define MustUseChecker_h__
+
+#include "plugin.h"
+
+class MustUseChecker : public BaseCheck {
+public:
+  MustUseChecker(StringRef CheckName,
+                 ContextType *Context = nullptr)
+    : BaseCheck(CheckName, Context) {}
+  void registerMatchers(MatchFinder* AstMatcher) override;
+  void check(const MatchFinder::MatchResult &Result) override;
+
+private:
+  void handleUnusedExprResult(const Stmt *Statement);
+};
+
+#endif
--- a/build/clang-plugin/moz.build
+++ b/build/clang-plugin/moz.build
@@ -12,16 +12,17 @@ UNIFIED_SOURCES += [
     'CustomTypeAnnotation.cpp',
     'DiagnosticsMatcher.cpp',
     'ExplicitImplicitChecker.cpp',
     'ExplicitOperatorBoolChecker.cpp',
     'KungFuDeathGripChecker.cpp',
     'MozCheckAction.cpp',
     'MozChecker.cpp',
     'MustOverrideChecker.cpp',
+    'MustUseChecker.cpp',
     'NaNExprChecker.cpp',
     'NeedsNoVTableTypeChecker.cpp',
     'NoAddRefReleaseOnReturnChecker.cpp',
     'NoAutoTypeChecker.cpp',
     'NoDuplicateRefCntMemberChecker.cpp',
     'NoExplicitMoveConstructorChecker.cpp',
     'NonMemMovableMemberChecker.cpp',
     'NonMemMovableTemplateArgChecker.cpp',