Home | History | Annotate | Download | only in blink_gc_plugin
      1 // Copyright 2017 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "BadPatternFinder.h"
      6 #include "DiagnosticsReporter.h"
      7 
      8 #include "clang/AST/ASTContext.h"
      9 #include "clang/ASTMatchers/ASTMatchFinder.h"
     10 #include "clang/ASTMatchers/ASTMatchers.h"
     11 
     12 using namespace clang::ast_matchers;
     13 
     14 namespace {
     15 
     16 TypeMatcher GarbageCollectedType() {
     17   auto has_gc_base = hasCanonicalType(hasDeclaration(
     18       cxxRecordDecl(isDerivedFrom(hasAnyName("::blink::GarbageCollected",
     19                                              "::blink::GarbageCollectedMixin")))
     20           .bind("gctype")));
     21   return anyOf(has_gc_base,
     22                hasCanonicalType(arrayType(hasElementType(has_gc_base))));
     23 }
     24 
     25 class UniquePtrGarbageCollectedMatcher : public MatchFinder::MatchCallback {
     26  public:
     27   explicit UniquePtrGarbageCollectedMatcher(DiagnosticsReporter& diagnostics)
     28       : diagnostics_(diagnostics) {}
     29 
     30   void Register(MatchFinder& match_finder) {
     31     // Matches any application of make_unique where the template argument is
     32     // known to refer to a garbage-collected type.
     33     auto make_unique_matcher =
     34         callExpr(
     35             callee(functionDecl(
     36                        hasAnyName("::std::make_unique", "::base::WrapUnique"),
     37                        hasTemplateArgument(
     38                            0, refersToType(GarbageCollectedType())))
     39                        .bind("badfunc")))
     40             .bind("bad");
     41     match_finder.addDynamicMatcher(make_unique_matcher, this);
     42   }
     43 
     44   void run(const MatchFinder::MatchResult& result) {
     45     auto* bad_use = result.Nodes.getNodeAs<clang::Expr>("bad");
     46     auto* bad_function = result.Nodes.getNodeAs<clang::FunctionDecl>("badfunc");
     47     auto* gc_type = result.Nodes.getNodeAs<clang::CXXRecordDecl>("gctype");
     48     diagnostics_.UniquePtrUsedWithGC(bad_use, bad_function, gc_type);
     49   }
     50 
     51  private:
     52   DiagnosticsReporter& diagnostics_;
     53 };
     54 
     55 class OptionalGarbageCollectedMatcher : public MatchFinder::MatchCallback {
     56  public:
     57   explicit OptionalGarbageCollectedMatcher(DiagnosticsReporter& diagnostics)
     58       : diagnostics_(diagnostics) {}
     59 
     60   void Register(MatchFinder& match_finder) {
     61     // Matches any application of make_unique where the template argument is
     62     // known to refer to a garbage-collected type.
     63     auto optional_construction =
     64         cxxConstructExpr(hasDeclaration(cxxConstructorDecl(ofClass(
     65                              classTemplateSpecializationDecl(
     66                                  hasName("::base::Optional"),
     67                                  hasTemplateArgument(
     68                                      0, refersToType(GarbageCollectedType())))
     69                                  .bind("optional")))))
     70             .bind("bad");
     71     match_finder.addDynamicMatcher(optional_construction, this);
     72   }
     73 
     74   void run(const MatchFinder::MatchResult& result) {
     75     auto* bad_use = result.Nodes.getNodeAs<clang::Expr>("bad");
     76     auto* optional = result.Nodes.getNodeAs<clang::CXXRecordDecl>("optional");
     77     auto* gc_type = result.Nodes.getNodeAs<clang::CXXRecordDecl>("gctype");
     78     diagnostics_.OptionalUsedWithGC(bad_use, optional, gc_type);
     79   }
     80 
     81  private:
     82   DiagnosticsReporter& diagnostics_;
     83 };
     84 
     85 }  // namespace
     86 
     87 void FindBadPatterns(clang::ASTContext& ast_context,
     88                      DiagnosticsReporter& diagnostics) {
     89   MatchFinder match_finder;
     90 
     91   UniquePtrGarbageCollectedMatcher unique_ptr_gc(diagnostics);
     92   unique_ptr_gc.Register(match_finder);
     93 
     94   OptionalGarbageCollectedMatcher optional_gc(diagnostics);
     95   optional_gc.Register(match_finder);
     96 
     97   match_finder.matchAST(ast_context);
     98 }
     99