18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
28b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Redistribution and use in source and binary forms, with or without
38b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// modification, are permitted provided that the following conditions are
48b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// met:
58b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//
68b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//     * Redistributions of source code must retain the above copyright
78b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//       notice, this list of conditions and the following disclaimer.
88b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//     * Redistributions in binary form must reproduce the above
98b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//       copyright notice, this list of conditions and the following
108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//       disclaimer in the documentation and/or other materials provided
118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//       with the distribution.
128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//       contributors may be used to endorse or promote products derived
148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//       from this software without specific prior written permission.
158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch//
168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// This is clang plugin used by gcmole tool. See README for more details.
298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/AST.h"
318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/ASTConsumer.h"
328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/Mangle.h"
338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/RecursiveASTVisitor.h"
348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/AST/StmtVisitor.h"
358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/Frontend/FrontendPluginRegistry.h"
368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "clang/Frontend/CompilerInstance.h"
378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include "llvm/Support/raw_ostream.h"
388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <bitset>
408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <fstream>
418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <iostream>
428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <map>
438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <set>
448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#include <stack>
458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochnamespace {
478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtypedef std::string MangledName;
498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtypedef std::set<MangledName> CalleesSet;
508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool GetMangledName(clang::MangleContext* ctx,
528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           const clang::NamedDecl* decl,
538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           MangledName* result) {
548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!isa<clang::CXXConstructorDecl>(decl) &&
558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      !isa<clang::CXXDestructorDecl>(decl)) {
568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    llvm::SmallVector<char, 512> output;
578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    llvm::raw_svector_ostream out(output);
588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ctx->mangleName(decl, out);
598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    *result = out.str().str();
608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return true;
618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return false;
648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool InV8Namespace(const clang::NamedDecl* decl) {
688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return decl->getQualifiedNameAsString().compare(0, 4, "v8::") == 0;
698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic std::string EXTERNAL("EXTERNAL");
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic std::string STATE_TAG("enum v8::internal::StateTag");
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsExternalVMState(const clang::ValueDecl* var) {
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const clang::EnumConstantDecl* enum_constant =
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      dyn_cast<clang::EnumConstantDecl>(var);
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (enum_constant != NULL && enum_constant->getNameAsString() == EXTERNAL) {
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    clang::QualType type = enum_constant->getType();
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return (type.getAsString() == STATE_TAG);
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
87257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstruct Resolver {
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  explicit Resolver(clang::ASTContext& ctx)
89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : ctx_(ctx), decl_ctx_(ctx.getTranslationUnitDecl()) {
90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
92257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Resolver(clang::ASTContext& ctx, clang::DeclContext* decl_ctx)
93257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : ctx_(ctx), decl_ctx_(decl_ctx) {
94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::DeclarationName ResolveName(const char* n) {
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::IdentifierInfo* ident = &ctx_.Idents.get(n);
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ctx_.DeclarationNames.getIdentifier(ident);
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Resolver ResolveNamespace(const char* n) {
102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Resolver(ctx_, Resolve<clang::NamespaceDecl>(n));
103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  template<typename T>
106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  T* Resolve(const char* n) {
107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (decl_ctx_ == NULL) return NULL;
108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::DeclContext::lookup_result result =
110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        decl_ctx_->lookup(ResolveName(n));
111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::DeclContext::lookup_iterator end = result.second;
113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (clang::DeclContext::lookup_iterator i = result.first;
114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         i != end;
115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         i++) {
116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (isa<T>(*i)) return cast<T>(*i);
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return NULL;
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::ASTContext& ctx_;
124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::DeclContext* decl_ctx_;
125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> {
1298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public:
1308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  explicit CalleesPrinter(clang::MangleContext* ctx) : ctx_(ctx) {
1318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual bool VisitCallExpr(clang::CallExpr* expr) {
1348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    const clang::FunctionDecl* callee = expr->getDirectCallee();
1358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (callee != NULL) AnalyzeFunction(callee);
1368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return true;
1378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool VisitDeclRefExpr(clang::DeclRefExpr* expr) {
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If function mentions EXTERNAL VMState add artificial garbage collection
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // mark.
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsExternalVMState(expr->getDecl())) AddCallee("CollectGarbage");
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void AnalyzeFunction(const clang::FunctionDecl* f) {
1478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    MangledName name;
1488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (InV8Namespace(f) && GetMangledName(ctx_, f, &name)) {
1498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddCallee(name);
1508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      const clang::FunctionDecl* body = NULL;
1528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (f->hasBody(body) && !Analyzed(name)) {
1538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        EnterScope(name);
1548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        TraverseStmt(body->getBody());
1558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        LeaveScope();
1568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
1578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
1588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef std::map<MangledName, CalleesSet* > Callgraph;
1618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  bool Analyzed(const MangledName& name) {
1638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return callgraph_[name] != NULL;
1648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void EnterScope(const MangledName& name) {
1678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    CalleesSet* callees = callgraph_[name];
1688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (callees == NULL) {
1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      callgraph_[name] = callees = new CalleesSet();
1718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
1728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    scopes_.push(callees);
1748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void LeaveScope() {
1778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    scopes_.pop();
1788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void AddCallee(const MangledName& name) {
1818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!scopes_.empty()) scopes_.top()->insert(name);
1828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void PrintCallGraph() {
1858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    for (Callgraph::const_iterator i = callgraph_.begin(), e = callgraph_.end();
1868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         i != e;
1878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         ++i) {
1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      std::cout << i->first << "\n";
1898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      CalleesSet* callees = i->second;
1918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      for (CalleesSet::const_iterator j = callees->begin(), e = callees->end();
1928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch           j != e;
1938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch           ++j) {
1948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        std::cout << "\t" << *j << "\n";
1958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
1968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
1978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
1988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private:
2008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  clang::MangleContext* ctx_;
2018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  std::stack<CalleesSet* > scopes_;
2038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Callgraph callgraph_;
2048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch};
2058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass FunctionDeclarationFinder
2088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : public clang::ASTConsumer,
2098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      public clang::RecursiveASTVisitor<FunctionDeclarationFinder> {
2108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public:
2118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  explicit FunctionDeclarationFinder(clang::Diagnostic& d,
212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     clang::SourceManager& sm,
213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                     const std::vector<std::string>& args)
2148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      : d_(d), sm_(sm) { }
2158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual void HandleTranslationUnit(clang::ASTContext &ctx) {
2178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    mangle_context_ = clang::createItaniumMangleContext(ctx, d_);
2188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    callees_printer_ = new CalleesPrinter(mangle_context_);
2198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    TraverseDecl(ctx.getTranslationUnitDecl());
2218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    callees_printer_->PrintCallGraph();
2238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
2248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) {
2268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    callees_printer_->AnalyzeFunction(decl);
2278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return true;
2288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
2298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private:
2318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  clang::Diagnostic& d_;
2328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  clang::SourceManager& sm_;
2338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  clang::MangleContext* mangle_context_;
2348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CalleesPrinter* callees_printer_;
2368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch};
2378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool loaded = false;
2408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic CalleesSet gc_suspects;
2418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic void LoadGCSuspects() {
2448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (loaded) return;
2458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  std::ifstream fin("gcsuspects");
2478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  std::string s;
2488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  while (fin >> s) gc_suspects.insert(s);
2508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  loaded = true;
2528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
2538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic bool KnownToCauseGC(clang::MangleContext* ctx,
2568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           const clang::FunctionDecl* decl) {
2578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  LoadGCSuspects();
2588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!InV8Namespace(decl)) return false;
2608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MangledName name;
2628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (GetMangledName(ctx, decl, &name)) {
2638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return gc_suspects.find(name) != gc_suspects.end();
2648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
2658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return false;
2678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
2688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kNoEffect = 0;
271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kCausesGC = 1;
272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kRawDef = 2;
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kRawUse = 4;
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kAllEffects = kCausesGC | kRawDef | kRawUse;
2758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass Environment;
277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass ExprEffect {
279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool hasGC() { return (effect_ & kCausesGC) != 0; }
281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void setGC() { effect_ |= kCausesGC; }
282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool hasRawDef() { return (effect_ & kRawDef) != 0; }
284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void setRawDef() { effect_ |= kRawDef; }
285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool hasRawUse() { return (effect_ & kRawUse) != 0; }
287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void setRawUse() { effect_ |= kRawUse; }
288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static ExprEffect None() { return ExprEffect(kNoEffect, NULL); }
290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static ExprEffect NoneWithEnv(Environment* env) {
291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ExprEffect(kNoEffect, env);
292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static ExprEffect RawUse() { return ExprEffect(kRawUse, NULL); }
294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static ExprEffect Merge(ExprEffect a, ExprEffect b);
296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static ExprEffect MergeSeq(ExprEffect a, ExprEffect b);
297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect Define(const std::string& name);
298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* env() {
300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return reinterpret_cast<Environment*>(effect_ & ~kAllEffects);
301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static ExprEffect GC() {
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ExprEffect(kCausesGC, NULL);
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect(int effect, Environment* env)
309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : effect_((effect & kAllEffects) |
310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                reinterpret_cast<intptr_t>(env)) { }
311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  intptr_t effect_;
313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst std::string BAD_EXPR_MSG("Possible problem with evaluation order.");
317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochconst std::string DEAD_VAR_MSG("Possibly dead variable.");
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass Environment {
321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment() { }
323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static Environment Unreachable() {
325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment env;
326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    env.live_.set();
327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return env;
328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static Environment Merge(const Environment& l,
331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           const Environment& r) {
332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Environment(l, r);
333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment ApplyEffect(ExprEffect effect) const {
336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment out = effect.hasGC() ? Environment() : Environment(*this);
337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (effect.env() != NULL) out.live_ |= effect.env()->live_;
338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return out;
339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  typedef std::map<std::string, int> SymbolTable;
342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool IsAlive(const std::string& name) const {
344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SymbolTable::iterator code = symbol_table_.find(name);
345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (code == symbol_table_.end()) return false;
346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return live_[code->second];
347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool Equal(const Environment& env) {
350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return live_ == env.live_;
351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment Define(const std::string& name) const {
354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Environment(*this, SymbolToCode(name));
355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void MDefine(const std::string& name) {
358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    live_.set(SymbolToCode(name));
359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static int SymbolToCode(const std::string& name) {
362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SymbolTable::iterator code = symbol_table_.find(name);
363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (code == symbol_table_.end()) {
365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      int new_code = symbol_table_.size();
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      symbol_table_.insert(std::make_pair(name, new_code));
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return new_code;
3688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return code->second;
371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void ClearSymbolTable() {
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    std::vector<Environment*>::iterator end = envs_.end();
375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (std::vector<Environment*>::iterator i = envs_.begin();
376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         i != end;
377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         ++i) {
378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      delete *i;
379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    envs_.clear();
381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    symbol_table_.clear();
382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void Print() const {
385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bool comma = false;
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    std::cout << "{";
387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    SymbolTable::iterator end = symbol_table_.end();
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (SymbolTable::iterator i = symbol_table_.begin();
389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         i != end;
390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         ++i) {
391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (live_[i->second]) {
392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (comma) std::cout << ", ";
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        std::cout << i->first;
394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        comma = true;
3958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
3968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    std::cout << "}";
3988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
3998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static Environment* Allocate(const Environment& env) {
401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment* allocated_env = new Environment(env);
402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    envs_.push_back(allocated_env);
403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return allocated_env;
404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment(const Environment& l, const Environment& r)
408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : live_(l.live_ & r.live_) {
409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment(const Environment& l, int code)
412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : live_(l.live_) {
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    live_.set(code);
414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static SymbolTable symbol_table_;
417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static std::vector<Environment* > envs_;
418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kMaxNumberOfLocals = 256;
420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  std::bitset<kMaxNumberOfLocals> live_;
421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  friend class ExprEffect;
423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  friend class CallProps;
424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass CallProps {
428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CallProps() : env_(NULL) { }
430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetEffect(int arg, ExprEffect in) {
432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (in.hasGC()) gc_.set(arg);
433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (in.hasRawDef()) raw_def_.set(arg);
434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (in.hasRawUse()) raw_use_.set(arg);
435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (in.env() != NULL) {
436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (env_ == NULL) env_ = in.env();
437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      env_->live_ |= in.env()->live_;
438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect ComputeCumulativeEffect(bool result_is_raw) {
442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ExprEffect out = ExprEffect::NoneWithEnv(env_);
443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (gc_.any()) out.setGC();
444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (raw_use_.any()) out.setRawUse();
445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (result_is_raw) out.setRawDef();
446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return out;
447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool IsSafe() {
450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!gc_.any()) return true;
451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    std::bitset<kMaxNumberOfArguments> raw = (raw_def_ | raw_use_);
452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!raw.any()) return true;
453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return gc_.count() == 1 && !((raw ^ gc_).any());
454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kMaxNumberOfArguments = 64;
458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  std::bitset<kMaxNumberOfArguments> raw_def_;
459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  std::bitset<kMaxNumberOfArguments> raw_use_;
460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  std::bitset<kMaxNumberOfArguments> gc_;
461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* env_;
462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochEnvironment::SymbolTable Environment::symbol_table_;
466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstd::vector<Environment* > Environment::envs_;
467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochExprEffect ExprEffect::Merge(ExprEffect a, ExprEffect b) {
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* a_env = a.env();
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* b_env = b.env();
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* out = NULL;
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (a_env != NULL && b_env != NULL) {
474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    out = Environment::Allocate(*a_env);
475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    out->live_ &= b_env->live_;
476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return ExprEffect(a.effect_ | b.effect_, out);
478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochExprEffect ExprEffect::MergeSeq(ExprEffect a, ExprEffect b) {
482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* a_env = b.hasGC() ? NULL : a.env();
483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* b_env = b.env();
484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* out = (b_env == NULL) ? a_env : b_env;
485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (a_env != NULL && b_env != NULL) {
486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    out = Environment::Allocate(*b_env);
487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    out->live_ |= a_env->live_;
488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return ExprEffect(a.effect_ | b.effect_, out);
4908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
4918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
4928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochExprEffect ExprEffect::Define(const std::string& name) {
494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment* e = env();
495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (e == NULL) {
496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    e = Environment::Allocate(Environment());
497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  e->MDefine(name);
499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return ExprEffect(effect_, e);
500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic std::string THIS ("this");
504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass FunctionAnalyzer {
5078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public:
508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  FunctionAnalyzer(clang::MangleContext* ctx,
509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   clang::DeclarationName handle_decl_name,
510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   clang::CXXRecordDecl* object_decl,
511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   clang::CXXRecordDecl* smi_decl,
512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   clang::Diagnostic& d,
513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   clang::SourceManager& sm,
514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   bool dead_vars_analysis)
515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : ctx_(ctx),
516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        handle_decl_name_(handle_decl_name),
517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        object_decl_(object_decl),
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        smi_decl_(smi_decl),
519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        d_(d),
520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        sm_(sm),
521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        block_(NULL),
522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        dead_vars_analysis_(dead_vars_analysis) {
5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
5248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // --------------------------------------------------------------------------
527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Expressions
528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // --------------------------------------------------------------------------
529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect VisitExpr(clang::Expr* expr, const Environment& env) {
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define VISIT(type) do {                                                \
532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      clang::type* concrete_expr = dyn_cast_or_null<clang::type>(expr); \
533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (concrete_expr != NULL) {                                      \
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Visit##type (concrete_expr, env);                        \
535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }                                                                 \
536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } while(0);
537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(AbstractConditionalOperator);
539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(AddrLabelExpr);
540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ArraySubscriptExpr);
541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(BinaryOperator);
542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(BinaryTypeTraitExpr);
543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(BlockDeclRefExpr);
544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(BlockExpr);
545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CallExpr);
546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CastExpr);
547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CharacterLiteral);
548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ChooseExpr);
549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CompoundLiteralExpr);
550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXBindTemporaryExpr);
551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXBoolLiteralExpr);
552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXConstructExpr);
553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXDefaultArgExpr);
554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXDeleteExpr);
555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXDependentScopeMemberExpr);
556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXNewExpr);
557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXNoexceptExpr);
558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXNullPtrLiteralExpr);
559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXPseudoDestructorExpr);
560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXScalarValueInitExpr);
561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXThisExpr);
562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXThrowExpr);
563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXTypeidExpr);
564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXUnresolvedConstructExpr);
565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXUuidofExpr);
566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(DeclRefExpr);
567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(DependentScopeDeclRefExpr);
568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(DesignatedInitExpr);
569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ExprWithCleanups);
570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ExtVectorElementExpr);
571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(FloatingLiteral);
572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(GNUNullExpr);
573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ImaginaryLiteral);
574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ImplicitValueInitExpr);
575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(InitListExpr);
576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(IntegerLiteral);
577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(MemberExpr);
578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(OffsetOfExpr);
579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(OpaqueValueExpr);
580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(OverloadExpr);
581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(PackExpansionExpr);
582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ParenExpr);
583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ParenListExpr);
584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(PredefinedExpr);
585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ShuffleVectorExpr);
586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(SizeOfPackExpr);
587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(StmtExpr);
588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(StringLiteral);
589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(SubstNonTypeTemplateParmPackExpr);
590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(UnaryExprOrTypeTraitExpr);
591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(UnaryOperator);
592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(UnaryTypeTraitExpr);
593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(VAArgExpr);
594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef VISIT
595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ExprEffect::None();
5978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
5988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define DECL_VISIT_EXPR(type)                                           \
600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect Visit##type (clang::type* expr, const Environment& env)
6018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define IGNORE_EXPR(type)                                               \
603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect Visit##type (clang::type* expr, const Environment& env) {  \
604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ExprEffect::None();                                          \
605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
6068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(AddrLabelExpr);
608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(BinaryTypeTraitExpr);
609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(BlockExpr);
610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CharacterLiteral);
611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(ChooseExpr);
612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CompoundLiteralExpr);
613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXBoolLiteralExpr);
614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXDependentScopeMemberExpr);
615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXNullPtrLiteralExpr);
616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXPseudoDestructorExpr);
617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXScalarValueInitExpr);
618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXNoexceptExpr);
619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXTypeidExpr);
620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXUnresolvedConstructExpr);
621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(CXXUuidofExpr);
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(DependentScopeDeclRefExpr);
623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(DesignatedInitExpr);
624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(ExtVectorElementExpr);
625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(FloatingLiteral);
626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(ImaginaryLiteral);
627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(IntegerLiteral);
628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(OffsetOfExpr);
629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(ImplicitValueInitExpr);
630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(PackExpansionExpr);
631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(PredefinedExpr);
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(ShuffleVectorExpr);
633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(SizeOfPackExpr);
634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(StmtExpr);
635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(StringLiteral);
636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(SubstNonTypeTemplateParmPackExpr);
637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(UnaryExprOrTypeTraitExpr);
638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(UnaryTypeTraitExpr);
639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(VAArgExpr);
640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(GNUNullExpr);
641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_EXPR(OverloadExpr);
642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CXXThisExpr) {
644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Use(expr, expr->getType(), THIS, env);
645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(AbstractConditionalOperator) {
648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment after_cond = env.ApplyEffect(VisitExpr(expr->getCond(), env));
649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ExprEffect::Merge(VisitExpr(expr->getTrueExpr(), after_cond),
650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             VisitExpr(expr->getFalseExpr(), after_cond));
651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(ArraySubscriptExpr) {
654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::Expr* exprs[2] = {expr->getBase(), expr->getIdx()};
655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Par(expr, 2, exprs, env);
656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool IsRawPointerVar(clang::Expr* expr, std::string* var_name) {
659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (isa<clang::BlockDeclRefExpr>(expr)) {
660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      *var_name = cast<clang::BlockDeclRefExpr>(expr)->getDecl()->
661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          getNameAsString();
662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return true;
663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (isa<clang::DeclRefExpr>(expr)) {
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      *var_name = cast<clang::DeclRefExpr>(expr)->getDecl()->getNameAsString();
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return true;
6668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
6678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return false;
6688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
6698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(BinaryOperator) {
671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::Expr* lhs = expr->getLHS();
672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::Expr* rhs = expr->getRHS();
673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::Expr* exprs[2] = {lhs, rhs};
674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    switch (expr->getOpcode()) {
676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case clang::BO_Comma:
677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Seq(expr, 2, exprs, env);
678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case clang::BO_LAnd:
680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case clang::BO_LOr:
681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return ExprEffect::Merge(VisitExpr(lhs, env), VisitExpr(rhs, env));
682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case clang::BO_Assign: {
684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        std::string var_name;
685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (IsRawPointerVar(lhs, &var_name)) {
686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          return VisitExpr(rhs, env).Define(var_name);
687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Par(expr, 2, exprs, env);
689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      default:
692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Par(expr, 2, exprs, env);
693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
6948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
6958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CXXBindTemporaryExpr) {
697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getSubExpr(), env);
6988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
6998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CXXConstructExpr) {
701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitArguments<>(expr, env);
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CXXDefaultArgExpr) {
705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getExpr(), env);
706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CXXDeleteExpr) {
709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getArgument(), env);
710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CXXNewExpr) {
713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Par(expr,
714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               expr->getNumConstructorArgs(),
715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               expr->getConstructorArgs(),
716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               env);
717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(ExprWithCleanups) {
720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getSubExpr(), env);
721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CXXThrowExpr) {
724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getSubExpr(), env);
725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(InitListExpr) {
728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Seq(expr, expr->getNumInits(), expr->getInits(), env);
729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(MemberExpr) {
732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getBase(), env);
733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(OpaqueValueExpr) {
736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getSourceExpr(), env);
737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(ParenExpr) {
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getSubExpr(), env);
741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(ParenListExpr) {
744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Par(expr, expr->getNumExprs(), expr->getExprs(), env);
745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(UnaryOperator) {
748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // TODO We are treating all expressions that look like &raw_pointer_var
749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    //      as definitions of raw_pointer_var. This should be changed to
750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    //      recognize less generic pattern:
751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    //
752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    //         if (maybe_object->ToObject(&obj)) return maybe_object;
753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    //
754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (expr->getOpcode() == clang::UO_AddrOf) {
755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      std::string var_name;
756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (IsRawPointerVar(expr->getSubExpr(), &var_name)) {
757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return ExprEffect::None().Define(var_name);
758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getSubExpr(), env);
761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(CastExpr) {
764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitExpr(expr->getSubExpr(), env);
765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(DeclRefExpr) {
768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Use(expr, expr->getDecl(), env);
769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_EXPR(BlockDeclRefExpr) {
772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Use(expr, expr->getDecl(), env);
773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect Par(clang::Expr* parent,
776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 int n,
777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 clang::Expr** exprs,
778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const Environment& env) {
779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CallProps props;
780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int i = 0; i < n; ++i) {
782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      props.SetEffect(i, VisitExpr(exprs[i], env));
783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!props.IsSafe()) ReportUnsafe(parent, BAD_EXPR_MSG);
786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return props.ComputeCumulativeEffect(IsRawPointerType(parent->getType()));
788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect Seq(clang::Stmt* parent,
791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 int n,
792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 clang::Expr** exprs,
793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const Environment& env) {
794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ExprEffect out = ExprEffect::None();
795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment out_env = env;
796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (int i = 0; i < n; ++i) {
797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      out = ExprEffect::MergeSeq(out, VisitExpr(exprs[i], out_env));
798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      out_env = out_env.ApplyEffect(out);
799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return out;
801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect Use(const clang::Expr* parent,
804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const clang::QualType& var_type,
805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const std::string& var_name,
806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const Environment& env) {
807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (IsRawPointerType(var_type)) {
808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (!env.IsAlive(var_name) && dead_vars_analysis_) {
809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        ReportUnsafe(parent, DEAD_VAR_MSG);
8108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return ExprEffect::RawUse();
8128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return ExprEffect::None();
814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect Use(const clang::Expr* parent,
817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const clang::ValueDecl* var,
818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const Environment& env) {
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsExternalVMState(var)) {
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ExprEffect::GC();
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Use(parent, var->getType(), var->getNameAsString(), env);
823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
8258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  template<typename ExprType>
827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect VisitArguments(ExprType* call, const Environment& env) {
828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CallProps props;
829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitArguments<>(call, &props, env);
830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG);
831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return props.ComputeCumulativeEffect(IsRawPointerType(call->getType()));
832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  template<typename ExprType>
835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void VisitArguments(ExprType* call,
836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      CallProps* props,
837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      const Environment& env) {
8388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    for (unsigned arg = 0; arg < call->getNumArgs(); arg++) {
839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      props->SetEffect(arg + 1, VisitExpr(call->getArg(arg), env));
8408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
8418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
8428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ExprEffect VisitCallExpr(clang::CallExpr* call,
845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           const Environment& env) {
846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    CallProps props;
8478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
8488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clang::CXXMemberCallExpr* memcall =
8498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        dyn_cast_or_null<clang::CXXMemberCallExpr>(call);
850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (memcall != NULL) {
851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      clang::Expr* receiver = memcall->getImplicitObjectArgument();
852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      props.SetEffect(0, VisitExpr(receiver, env));
8538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
8548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitArguments<>(call, &props, env);
856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG);
858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ExprEffect out =
860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        props.ComputeCumulativeEffect(IsRawPointerType(call->getType()));
861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::FunctionDecl* callee = call->getDirectCallee();
863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if ((callee != NULL) && KnownToCauseGC(ctx_, callee)) {
864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      out.setGC();
865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return out;
868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // --------------------------------------------------------------------------
871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Statements
872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // --------------------------------------------------------------------------
873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment VisitStmt(clang::Stmt* stmt, const Environment& env) {
875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define VISIT(type) do {                                                \
876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      clang::type* concrete_stmt = dyn_cast_or_null<clang::type>(stmt); \
877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (concrete_stmt != NULL) {                                      \
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return Visit##type (concrete_stmt, env);                        \
879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }                                                                 \
880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } while(0);
881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (clang::Expr* expr = dyn_cast_or_null<clang::Expr>(stmt)) {
883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return env.ApplyEffect(VisitExpr(expr, env));
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(AsmStmt);
887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(BreakStmt);
888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CompoundStmt);
889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ContinueStmt);
890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXCatchStmt);
891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CXXTryStmt);
892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(DeclStmt);
893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(DoStmt);
894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ForStmt);
895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(GotoStmt);
896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(IfStmt);
897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(IndirectGotoStmt);
898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(LabelStmt);
899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(NullStmt);
900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(ReturnStmt);
901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(CaseStmt);
902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(DefaultStmt);
903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(SwitchStmt);
904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VISIT(WhileStmt);
905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef VISIT
906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return env;
908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define DECL_VISIT_STMT(type)                                           \
911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment Visit##type (clang::type* stmt, const Environment& env)
912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define IGNORE_STMT(type)                                               \
914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment Visit##type (clang::type* stmt, const Environment& env) { \
915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return env;                                                         \
916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_STMT(IndirectGotoStmt);
919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_STMT(NullStmt);
920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_STMT(AsmStmt);
921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We are ignoring control flow for simplicity.
923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_STMT(GotoStmt);
924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_STMT(LabelStmt);
925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // We are ignoring try/catch because V8 does not use them.
927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_STMT(CXXCatchStmt);
928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  IGNORE_STMT(CXXTryStmt);
929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  class Block {
931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch   public:
932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Block(const Environment& in,
933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          FunctionAnalyzer* owner)
934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        : in_(in),
935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          out_(Environment::Unreachable()),
936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          changed_(false),
937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          owner_(owner) {
938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      parent_ = owner_->EnterBlock(this);
939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ~Block() {
942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      owner_->LeaveBlock(parent_);
943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    void MergeIn(const Environment& env) {
946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment old_in = in_;
947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      in_ = Environment::Merge(in_, env);
948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      changed_ = !old_in.Equal(in_);
949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bool changed() {
952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (changed_) {
953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        changed_ = false;
954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return true;
955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return false;
957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const Environment& in() {
960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return in_;
961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const Environment& out() {
964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return out_;
965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    void MergeOut(const Environment& env) {
968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      out_ = Environment::Merge(out_, env);
969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    void Seq(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) {
972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment a_out = owner_->VisitStmt(a, in());
973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment b_out = owner_->VisitStmt(b, a_out);
974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment c_out = owner_->VisitStmt(c, b_out);
975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      MergeOut(c_out);
976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    void Seq(clang::Stmt* a, clang::Stmt* b) {
979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment a_out = owner_->VisitStmt(a, in());
980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment b_out = owner_->VisitStmt(b, a_out);
981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      MergeOut(b_out);
982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    void Loop(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) {
985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Seq(a, b, c);
986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      MergeIn(out());
987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    void Loop(clang::Stmt* a, clang::Stmt* b) {
990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Seq(a, b);
991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      MergeIn(out());
9928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch   private:
996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment in_;
997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment out_;
998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    bool changed_;
999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    FunctionAnalyzer* owner_;
1000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Block* parent_;
1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  };
1002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(BreakStmt) {
1005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    block_->MergeOut(env);
1006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Environment::Unreachable();
1007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(ContinueStmt) {
1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    block_->MergeIn(env);
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Environment::Unreachable();
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(CompoundStmt) {
1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment out = env;
1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::CompoundStmt::body_iterator end = stmt->body_end();
1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (clang::CompoundStmt::body_iterator s = stmt->body_begin();
1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         s != end;
1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         ++s) {
1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      out = VisitStmt(*s, out);
1021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return out;
1023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(WhileStmt) {
1026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Block block (env, this);
1027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    do {
1028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      block.Loop(stmt->getCond(), stmt->getBody());
1029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } while (block.changed());
1030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return block.out();
1031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(DoStmt) {
1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Block block (env, this);
1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    do {
1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      block.Loop(stmt->getBody(), stmt->getCond());
1037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } while (block.changed());
1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return block.out();
1039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(ForStmt) {
1042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Block block (VisitStmt(stmt->getInit(), env), this);
1043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    do {
1044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      block.Loop(stmt->getCond(),
1045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 stmt->getBody(),
1046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 stmt->getInc());
1047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } while (block.changed());
1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return block.out();
1049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(IfStmt) {
1052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment cond_out = VisitStmt(stmt->getCond(), env);
1053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment then_out = VisitStmt(stmt->getThen(), cond_out);
1054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment else_out = VisitStmt(stmt->getElse(), cond_out);
1055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Environment::Merge(then_out, else_out);
1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(SwitchStmt) {
1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Block block (env, this);
1060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    block.Seq(stmt->getCond(), stmt->getBody());
1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return block.out();
1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(CaseStmt) {
1065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment in = Environment::Merge(env, block_->in());
1066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment after_lhs = VisitStmt(stmt->getLHS(), in);
1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitStmt(stmt->getSubStmt(), after_lhs);
1068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(DefaultStmt) {
1071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment in = Environment::Merge(env, block_->in());
1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return VisitStmt(stmt->getSubStmt(), in);
1073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(ReturnStmt) {
1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    VisitExpr(stmt->getRetValue(), env);
1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return Environment::Unreachable();
10788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
10798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
10808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  const clang::TagType* ToTagType(const clang::Type* t) {
10818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (t == NULL) {
10828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return NULL;
10838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else if (isa<clang::TagType>(t)) {
10848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return cast<clang::TagType>(t);
10858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else if (isa<clang::SubstTemplateTypeParmType>(t)) {
10868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return ToTagType(cast<clang::SubstTemplateTypeParmType>(t)->
10878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                           getReplacementType().getTypePtr());
10888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
10898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return NULL;
10908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
10918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
10928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool IsDerivedFrom(clang::CXXRecordDecl* record,
1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     clang::CXXRecordDecl* base) {
1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return (record == base) || record->isDerivedFrom(base);
1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
10978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool IsRawPointerType(clang::QualType qtype) {
10998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    const clang::PointerType* type =
1100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        dyn_cast_or_null<clang::PointerType>(qtype.getTypePtrOrNull());
11018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (type == NULL) return false;
11028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    const clang::TagType* pointee =
11048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        ToTagType(type->getPointeeType().getTypePtr());
11058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (pointee == NULL) return false;
11068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    clang::CXXRecordDecl* record =
11088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        dyn_cast_or_null<clang::CXXRecordDecl>(pointee->getDecl());
11098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (record == NULL) return false;
11108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!InV8Namespace(record)) return false;
11128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (!record->hasDefinition()) return false;
11148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    record = record->getDefinition();
11168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return IsDerivedFrom(record, object_decl_) &&
1118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        !IsDerivedFrom(record, smi_decl_);
11198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
11208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Environment VisitDecl(clang::Decl* decl, const Environment& env) {
1122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (clang::VarDecl* var = dyn_cast<clang::VarDecl>(decl)) {
1123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment out = var->hasInit() ? VisitStmt(var->getInit(), env) : env;
1124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (IsRawPointerType(var->getType())) {
1126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        out = out.Define(var->getNameAsString());
1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
11288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return out;
1130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // TODO: handle other declarations?
1132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return env;
11338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
11348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  DECL_VISIT_STMT(DeclStmt) {
1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Environment out = env;
1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::DeclStmt::decl_iterator end = stmt->decl_end();
1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (clang::DeclStmt::decl_iterator decl = stmt->decl_begin();
1139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         decl != end;
1140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         ++decl) {
1141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      out = VisitDecl(*decl, out);
1142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return out;
11448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
11458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void DefineParameters(const clang::FunctionDecl* f,
1148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        Environment* env) {
1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    env->MDefine(THIS);
1150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::FunctionDecl::param_const_iterator end = f->param_end();
1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (clang::FunctionDecl::param_const_iterator p = f->param_begin();
1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         p != end;
1153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         ++p) {
1154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      env->MDefine((*p)->getNameAsString());
1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void AnalyzeFunction(const clang::FunctionDecl* f) {
1160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    const clang::FunctionDecl* body = NULL;
1161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (f->hasBody(body)) {
1162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment env;
1163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      DefineParameters(body, &env);
1164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      VisitStmt(body->getBody(), env);
1165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Environment::ClearSymbolTable();
1166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Block* EnterBlock(Block* block) {
1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Block* parent = block_;
1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    block_ = block;
1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return parent;
1173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void LeaveBlock(Block* block) {
1176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    block_ = block;
1177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
1180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ReportUnsafe(const clang::Expr* expr, const std::string& msg) {
1181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    d_.Report(clang::FullSourceLoc(expr->getExprLoc(), sm_),
1182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              d_.getCustomDiagID(clang::Diagnostic::Warning, msg));
1183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
11848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::MangleContext* ctx_;
1187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::DeclarationName handle_decl_name_;
1188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::CXXRecordDecl* object_decl_;
1189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::CXXRecordDecl* smi_decl_;
11908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::Diagnostic& d_;
1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  clang::SourceManager& sm_;
11938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Block* block_;
1195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool dead_vars_analysis_;
1196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch};
11978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass ProblemsFinder : public clang::ASTConsumer,
1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                       public clang::RecursiveASTVisitor<ProblemsFinder> {
1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public:
1202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ProblemsFinder(clang::Diagnostic& d,
1203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 clang::SourceManager& sm,
1204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                 const std::vector<std::string>& args)
1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : d_(d), sm_(sm), dead_vars_analysis_(false) {
1206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    for (unsigned i = 0; i < args.size(); ++i) {
1207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (args[i] == "--dead-vars") {
1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        dead_vars_analysis_ = true;
1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
12108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
12128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  virtual void HandleTranslationUnit(clang::ASTContext &ctx) {
12148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Resolver r(ctx);
12158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::CXXRecordDecl* object_decl =
12178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        r.ResolveNamespace("v8").ResolveNamespace("internal").
12188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            Resolve<clang::CXXRecordDecl>("Object");
12198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    clang::CXXRecordDecl* smi_decl =
1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        r.ResolveNamespace("v8").ResolveNamespace("internal").
1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            Resolve<clang::CXXRecordDecl>("Smi");
1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (object_decl != NULL) object_decl = object_decl->getDefinition();
1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (smi_decl != NULL) smi_decl = smi_decl->getDefinition();
1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (object_decl != NULL && smi_decl != NULL) {
1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      function_analyzer_ =
1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          new FunctionAnalyzer(clang::createItaniumMangleContext(ctx, d_),
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               r.ResolveName("Handle"),
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               object_decl,
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               smi_decl,
1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               d_,
1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               sm_,
1236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                               dead_vars_analysis_);
12378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      TraverseDecl(ctx.getTranslationUnitDecl());
12388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (object_decl == NULL) {
1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        llvm::errs() << "Failed to resolve v8::internal::Object\n";
1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
1242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (smi_decl == NULL) {
1243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        llvm::errs() << "Failed to resolve v8::internal::Smi\n";
1244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      }
12458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
12468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
12478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) {
1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    function_analyzer_->AnalyzeFunction(decl);
12508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return true;
12518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
12528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private:
12548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  clang::Diagnostic& d_;
12558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  clang::SourceManager& sm_;
1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  bool dead_vars_analysis_;
12578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  FunctionAnalyzer* function_analyzer_;
12598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch};
12608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtemplate<typename ConsumerType>
12638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Action : public clang::PluginASTAction {
12648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch protected:
12658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &CI,
12668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                        llvm::StringRef InFile) {
1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return new ConsumerType(CI.getDiagnostics(), CI.getSourceManager(), args_);
12688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
12698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  bool ParseArgs(const clang::CompilerInstance &CI,
12718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                 const std::vector<std::string>& args) {
1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    args_ = args;
12738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return true;
12748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
12758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void PrintHelp(llvm::raw_ostream& ros) {
1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private:
1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  std::vector<std::string> args_;
12808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch};
12818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
12848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic clang::FrontendPluginRegistry::Add<Action<ProblemsFinder> >
1286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochFindProblems("find-problems", "Find GC-unsafe places.");
12878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic clang::FrontendPluginRegistry::Add<
1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Action<FunctionDeclarationFinder> >
12908b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochDumpCallees("dump-callees", "Dump callees for each function.");
1291