144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// Redistribution and use in source and binary forms, with or without
344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// modification, are permitted provided that the following conditions are
444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// met:
544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//
644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//     * Redistributions of source code must retain the above copyright
744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//       notice, this list of conditions and the following disclaimer.
844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//     * Redistributions in binary form must reproduce the above
944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//       copyright notice, this list of conditions and the following
1044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//       disclaimer in the documentation and/or other materials provided
1144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//       with the distribution.
1244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//     * Neither the name of Google Inc. nor the names of its
1344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//       contributors may be used to endorse or promote products derived
1444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//       from this software without specific prior written permission.
1544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org//
1644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
2844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org// This is clang plugin used by gcmole tool. See README for more details.
2944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
3044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "clang/AST/AST.h"
3144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "clang/AST/ASTConsumer.h"
3244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "clang/AST/Mangle.h"
3344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "clang/AST/RecursiveASTVisitor.h"
3444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "clang/AST/StmtVisitor.h"
3544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "clang/Frontend/FrontendPluginRegistry.h"
3644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "clang/Frontend/CompilerInstance.h"
3744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "llvm/Support/raw_ostream.h"
3844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
3944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include <bitset>
4044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include <fstream>
4144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include <iostream>
4244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include <map>
4344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include <set>
4444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include <stack>
4544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
4644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgnamespace {
4744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
4844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgtypedef std::string MangledName;
4944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgtypedef std::set<MangledName> CalleesSet;
5044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
5144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgstatic bool GetMangledName(clang::MangleContext* ctx,
5244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                           const clang::NamedDecl* decl,
5344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                           MangledName* result) {
5444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  if (!isa<clang::CXXConstructorDecl>(decl) &&
5544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      !isa<clang::CXXDestructorDecl>(decl)) {
5644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    llvm::SmallVector<char, 512> output;
5744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    llvm::raw_svector_ostream out(output);
5844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    ctx->mangleName(decl, out);
5944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    *result = out.str().str();
6044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return true;
6144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
6244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  return false;
6444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org}
6544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgstatic bool InV8Namespace(const clang::NamedDecl* decl) {
6844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  return decl->getQualifiedNameAsString().compare(0, 4, "v8::") == 0;
6944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org}
7044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
7144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
72f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgstatic std::string EXTERNAL("EXTERNAL");
73f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgstatic std::string STATE_TAG("enum v8::internal::StateTag");
74f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
75f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgstatic bool IsExternalVMState(const clang::ValueDecl* var) {
76f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  const clang::EnumConstantDecl* enum_constant =
77f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      dyn_cast<clang::EnumConstantDecl>(var);
78f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  if (enum_constant != NULL && enum_constant->getNameAsString() == EXTERNAL) {
79f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    clang::QualType type = enum_constant->getType();
80f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    return (type.getAsString() == STATE_TAG);
81f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
82f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
83f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  return false;
84f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
85f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
86f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstruct Resolver {
887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  explicit Resolver(clang::ASTContext& ctx)
897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      : ctx_(ctx), decl_ctx_(ctx.getTranslationUnitDecl()) {
907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Resolver(clang::ASTContext& ctx, clang::DeclContext* decl_ctx)
937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      : ctx_(ctx), decl_ctx_(decl_ctx) {
947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::DeclarationName ResolveName(const char* n) {
977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::IdentifierInfo* ident = &ctx_.Idents.get(n);
987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return ctx_.DeclarationNames.getIdentifier(ident);
997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
1007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Resolver ResolveNamespace(const char* n) {
1027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Resolver(ctx_, Resolve<clang::NamespaceDecl>(n));
1037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
1047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  template<typename T>
1067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  T* Resolve(const char* n) {
1077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (decl_ctx_ == NULL) return NULL;
1087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::DeclContext::lookup_result result =
1107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        decl_ctx_->lookup(ResolveName(n));
1117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::DeclContext::lookup_iterator end = result.second;
1137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (clang::DeclContext::lookup_iterator i = result.first;
1147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         i != end;
1157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         i++) {
1167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (isa<T>(*i)) return cast<T>(*i);
1177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
1187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return NULL;
1207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
1217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org private:
1237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::ASTContext& ctx_;
1247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::DeclContext* decl_ctx_;
1257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org};
1267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
1277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
12844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgclass CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> {
12944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org public:
13044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  explicit CalleesPrinter(clang::MangleContext* ctx) : ctx_(ctx) {
13144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
13244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
13344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  virtual bool VisitCallExpr(clang::CallExpr* expr) {
13444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    const clang::FunctionDecl* callee = expr->getDirectCallee();
13544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (callee != NULL) AnalyzeFunction(callee);
13644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return true;
13744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
13844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
139f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  virtual bool VisitDeclRefExpr(clang::DeclRefExpr* expr) {
140f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    // If function mentions EXTERNAL VMState add artificial garbage collection
141f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    // mark.
142f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    if (IsExternalVMState(expr->getDecl())) AddCallee("CollectGarbage");
143f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    return true;
144f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
145f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
14644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  void AnalyzeFunction(const clang::FunctionDecl* f) {
14744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    MangledName name;
14844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (InV8Namespace(f) && GetMangledName(ctx_, f, &name)) {
14944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      AddCallee(name);
15044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
15144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      const clang::FunctionDecl* body = NULL;
15244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      if (f->hasBody(body) && !Analyzed(name)) {
15344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        EnterScope(name);
15444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        TraverseStmt(body->getBody());
15544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        LeaveScope();
15644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      }
15744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
15844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
15944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
16044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  typedef std::map<MangledName, CalleesSet* > Callgraph;
16144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
16244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  bool Analyzed(const MangledName& name) {
16344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return callgraph_[name] != NULL;
16444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
16544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
16644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  void EnterScope(const MangledName& name) {
16744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    CalleesSet* callees = callgraph_[name];
16844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
16944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (callees == NULL) {
17044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      callgraph_[name] = callees = new CalleesSet();
17144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
17244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
17344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    scopes_.push(callees);
17444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
17544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
17644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  void LeaveScope() {
17744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    scopes_.pop();
17844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
17944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
18044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  void AddCallee(const MangledName& name) {
18144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (!scopes_.empty()) scopes_.top()->insert(name);
18244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
18344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
18444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  void PrintCallGraph() {
18544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    for (Callgraph::const_iterator i = callgraph_.begin(), e = callgraph_.end();
18644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org         i != e;
18744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org         ++i) {
18844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      std::cout << i->first << "\n";
18944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
19044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      CalleesSet* callees = i->second;
19144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      for (CalleesSet::const_iterator j = callees->begin(), e = callees->end();
19244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org           j != e;
19344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org           ++j) {
19444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        std::cout << "\t" << *j << "\n";
19544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      }
19644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
19744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
19844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
19944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org private:
20044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  clang::MangleContext* ctx_;
20144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
20244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  std::stack<CalleesSet* > scopes_;
20344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  Callgraph callgraph_;
20444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org};
20544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
2067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
20744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgclass FunctionDeclarationFinder
20844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    : public clang::ASTConsumer,
20944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      public clang::RecursiveASTVisitor<FunctionDeclarationFinder> {
21044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org public:
21144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  explicit FunctionDeclarationFinder(clang::Diagnostic& d,
2127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                                     clang::SourceManager& sm,
2137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                                     const std::vector<std::string>& args)
21444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      : d_(d), sm_(sm) { }
21544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
21644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  virtual void HandleTranslationUnit(clang::ASTContext &ctx) {
21744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    mangle_context_ = clang::createItaniumMangleContext(ctx, d_);
21844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    callees_printer_ = new CalleesPrinter(mangle_context_);
21944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
22044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    TraverseDecl(ctx.getTranslationUnitDecl());
22144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
22244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    callees_printer_->PrintCallGraph();
22344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
22444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
22544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) {
22644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    callees_printer_->AnalyzeFunction(decl);
22744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return true;
22844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
22944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
23044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org private:
23144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  clang::Diagnostic& d_;
23244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  clang::SourceManager& sm_;
23344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  clang::MangleContext* mangle_context_;
23444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
23544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  CalleesPrinter* callees_printer_;
23644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org};
23744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
23844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
23944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgstatic bool loaded = false;
24044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgstatic CalleesSet gc_suspects;
24144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
24244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
24344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgstatic void LoadGCSuspects() {
24444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  if (loaded) return;
24544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
24644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  std::ifstream fin("gcsuspects");
24744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  std::string s;
24844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
24944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  while (fin >> s) gc_suspects.insert(s);
25044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
25144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  loaded = true;
25244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org}
25344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
25444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
25544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgstatic bool KnownToCauseGC(clang::MangleContext* ctx,
25644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                           const clang::FunctionDecl* decl) {
25744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  LoadGCSuspects();
25844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
25944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  if (!InV8Namespace(decl)) return false;
26044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
26144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  MangledName name;
26244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  if (GetMangledName(ctx, decl, &name)) {
26344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return gc_suspects.find(name) != gc_suspects.end();
26444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
26544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
26644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  return false;
26744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org}
26844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
26944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
2707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic const int kNoEffect = 0;
2717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic const int kCausesGC = 1;
2727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic const int kRawDef = 2;
2737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic const int kRawUse = 4;
2747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic const int kAllEffects = kCausesGC | kRawDef | kRawUse;
27544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
2767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgclass Environment;
2777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgclass ExprEffect {
2797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org public:
2807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool hasGC() { return (effect_ & kCausesGC) != 0; }
2817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void setGC() { effect_ |= kCausesGC; }
2827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool hasRawDef() { return (effect_ & kRawDef) != 0; }
2847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void setRawDef() { effect_ |= kRawDef; }
2857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool hasRawUse() { return (effect_ & kRawUse) != 0; }
2877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void setRawUse() { effect_ |= kRawUse; }
2887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static ExprEffect None() { return ExprEffect(kNoEffect, NULL); }
2907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static ExprEffect NoneWithEnv(Environment* env) {
2917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return ExprEffect(kNoEffect, env);
2927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
2937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static ExprEffect RawUse() { return ExprEffect(kRawUse, NULL); }
2947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static ExprEffect Merge(ExprEffect a, ExprEffect b);
2967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static ExprEffect MergeSeq(ExprEffect a, ExprEffect b);
2977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect Define(const std::string& name);
2987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
2997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* env() {
3007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return reinterpret_cast<Environment*>(effect_ & ~kAllEffects);
3017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
303f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  static ExprEffect GC() {
304f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    return ExprEffect(kCausesGC, NULL);
305f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
306f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
3077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org private:
3087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect(int effect, Environment* env)
3097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      : effect_((effect & kAllEffects) |
3107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                reinterpret_cast<intptr_t>(env)) { }
3117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  intptr_t effect_;
3137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org};
3147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgconst std::string BAD_EXPR_MSG("Possible problem with evaluation order.");
3177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgconst std::string DEAD_VAR_MSG("Possibly dead variable.");
3187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgclass Environment {
3217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org public:
3227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment() { }
3237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static Environment Unreachable() {
3257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment env;
3267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    env.live_.set();
3277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return env;
3287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static Environment Merge(const Environment& l,
3317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                           const Environment& r) {
3327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Environment(l, r);
3337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment ApplyEffect(ExprEffect effect) const {
3367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment out = effect.hasGC() ? Environment() : Environment(*this);
3377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (effect.env() != NULL) out.live_ |= effect.env()->live_;
3387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return out;
3397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  typedef std::map<std::string, int> SymbolTable;
3427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool IsAlive(const std::string& name) const {
3447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    SymbolTable::iterator code = symbol_table_.find(name);
3457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (code == symbol_table_.end()) return false;
3467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return live_[code->second];
3477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool Equal(const Environment& env) {
3507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return live_ == env.live_;
3517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment Define(const std::string& name) const {
3547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Environment(*this, SymbolToCode(name));
3557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void MDefine(const std::string& name) {
3587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    live_.set(SymbolToCode(name));
3597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static int SymbolToCode(const std::string& name) {
3627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    SymbolTable::iterator code = symbol_table_.find(name);
3637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (code == symbol_table_.end()) {
3657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      int new_code = symbol_table_.size();
3667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      symbol_table_.insert(std::make_pair(name, new_code));
3677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return new_code;
36844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
3697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return code->second;
3717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static void ClearSymbolTable() {
3747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    std::vector<Environment*>::iterator end = envs_.end();
3757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (std::vector<Environment*>::iterator i = envs_.begin();
3767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         i != end;
3777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         ++i) {
3787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      delete *i;
3797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
3807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    envs_.clear();
3817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    symbol_table_.clear();
3827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
3837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
3847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void Print() const {
3857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    bool comma = false;
3867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    std::cout << "{";
3877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    SymbolTable::iterator end = symbol_table_.end();
3887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (SymbolTable::iterator i = symbol_table_.begin();
3897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         i != end;
3907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         ++i) {
3917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (live_[i->second]) {
3927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        if (comma) std::cout << ", ";
3937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        std::cout << i->first;
3947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        comma = true;
39544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      }
39644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
3977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    std::cout << "}";
39844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
39944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
4007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static Environment* Allocate(const Environment& env) {
4017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment* allocated_env = new Environment(env);
4027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    envs_.push_back(allocated_env);
4037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return allocated_env;
4047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org private:
4077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment(const Environment& l, const Environment& r)
4087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      : live_(l.live_ & r.live_) {
4097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment(const Environment& l, int code)
4127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      : live_(l.live_) {
4137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    live_.set(code);
4147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static SymbolTable symbol_table_;
4177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static std::vector<Environment* > envs_;
4187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static const int kMaxNumberOfLocals = 256;
4207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  std::bitset<kMaxNumberOfLocals> live_;
4217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  friend class ExprEffect;
4237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  friend class CallProps;
4247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org};
4257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgclass CallProps {
4287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org public:
4297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  CallProps() : env_(NULL) { }
4307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void SetEffect(int arg, ExprEffect in) {
4327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (in.hasGC()) gc_.set(arg);
4337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (in.hasRawDef()) raw_def_.set(arg);
4347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (in.hasRawUse()) raw_use_.set(arg);
4357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (in.env() != NULL) {
4367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (env_ == NULL) env_ = in.env();
4377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      env_->live_ |= in.env()->live_;
4387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
4397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect ComputeCumulativeEffect(bool result_is_raw) {
4427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    ExprEffect out = ExprEffect::NoneWithEnv(env_);
4437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (gc_.any()) out.setGC();
4447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (raw_use_.any()) out.setRawUse();
4457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (result_is_raw) out.setRawDef();
4467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return out;
4477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool IsSafe() {
4507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (!gc_.any()) return true;
4517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    std::bitset<kMaxNumberOfArguments> raw = (raw_def_ | raw_use_);
4527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (!raw.any()) return true;
4537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return gc_.count() == 1 && !((raw ^ gc_).any());
4547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org private:
4577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  static const int kMaxNumberOfArguments = 64;
4587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  std::bitset<kMaxNumberOfArguments> raw_def_;
4597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  std::bitset<kMaxNumberOfArguments> raw_use_;
4607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  std::bitset<kMaxNumberOfArguments> gc_;
4617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* env_;
4627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org};
4637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgEnvironment::SymbolTable Environment::symbol_table_;
4667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstd::vector<Environment* > Environment::envs_;
4677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgExprEffect ExprEffect::Merge(ExprEffect a, ExprEffect b) {
4707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* a_env = a.env();
4717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* b_env = b.env();
4727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* out = NULL;
4737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  if (a_env != NULL && b_env != NULL) {
4747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    out = Environment::Allocate(*a_env);
4757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    out->live_ &= b_env->live_;
4767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  return ExprEffect(a.effect_ | b.effect_, out);
4787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org}
4797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
4817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgExprEffect ExprEffect::MergeSeq(ExprEffect a, ExprEffect b) {
4827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* a_env = b.hasGC() ? NULL : a.env();
4837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* b_env = b.env();
4847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* out = (b_env == NULL) ? a_env : b_env;
4857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  if (a_env != NULL && b_env != NULL) {
4867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    out = Environment::Allocate(*b_env);
4877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    out->live_ |= a_env->live_;
4887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  return ExprEffect(a.effect_ | b.effect_, out);
49044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org}
49144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
49244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
4937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgExprEffect ExprEffect::Define(const std::string& name) {
4947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment* e = env();
4957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  if (e == NULL) {
4967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    e = Environment::Allocate(Environment());
4977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
4987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  e->MDefine(name);
4997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  return ExprEffect(effect_, e);
5007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org}
5017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic std::string THIS ("this");
5047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgclass FunctionAnalyzer {
50744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org public:
5087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  FunctionAnalyzer(clang::MangleContext* ctx,
5097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                   clang::DeclarationName handle_decl_name,
5107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                   clang::CXXRecordDecl* object_decl,
5117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                   clang::CXXRecordDecl* smi_decl,
5127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                   clang::Diagnostic& d,
5137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                   clang::SourceManager& sm,
5147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                   bool dead_vars_analysis)
5157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      : ctx_(ctx),
5167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        handle_decl_name_(handle_decl_name),
5177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        object_decl_(object_decl),
5187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        smi_decl_(smi_decl),
5197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        d_(d),
5207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        sm_(sm),
5217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        block_(NULL),
5227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        dead_vars_analysis_(dead_vars_analysis) {
52344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
52444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
5257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // --------------------------------------------------------------------------
5277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Expressions
5287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // --------------------------------------------------------------------------
5297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect VisitExpr(clang::Expr* expr, const Environment& env) {
5317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#define VISIT(type) do {                                                \
5327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      clang::type* concrete_expr = dyn_cast_or_null<clang::type>(expr); \
5337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (concrete_expr != NULL) {                                      \
5347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return Visit##type (concrete_expr, env);                        \
5357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }                                                                 \
5367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    } while(0);
5377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(AbstractConditionalOperator);
5397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(AddrLabelExpr);
5407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ArraySubscriptExpr);
5417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(BinaryOperator);
5427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(BinaryTypeTraitExpr);
5437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(BlockDeclRefExpr);
5447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(BlockExpr);
5457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CallExpr);
5467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CastExpr);
5477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CharacterLiteral);
5487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ChooseExpr);
5497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CompoundLiteralExpr);
5507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXBindTemporaryExpr);
5517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXBoolLiteralExpr);
5527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXConstructExpr);
5537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXDefaultArgExpr);
5547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXDeleteExpr);
5557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXDependentScopeMemberExpr);
5567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXNewExpr);
5577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXNoexceptExpr);
5587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXNullPtrLiteralExpr);
5597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXPseudoDestructorExpr);
5607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXScalarValueInitExpr);
5617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXThisExpr);
5627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXThrowExpr);
5637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXTypeidExpr);
5647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXUnresolvedConstructExpr);
5657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXUuidofExpr);
5667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(DeclRefExpr);
5677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(DependentScopeDeclRefExpr);
5687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(DesignatedInitExpr);
5697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ExprWithCleanups);
5707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ExtVectorElementExpr);
5717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(FloatingLiteral);
5727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(GNUNullExpr);
5737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ImaginaryLiteral);
5747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ImplicitValueInitExpr);
5757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(InitListExpr);
5767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(IntegerLiteral);
5777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(MemberExpr);
5787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(OffsetOfExpr);
5797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(OpaqueValueExpr);
5807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(OverloadExpr);
5817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(PackExpansionExpr);
5827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ParenExpr);
5837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ParenListExpr);
5847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(PredefinedExpr);
5857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ShuffleVectorExpr);
5867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(SizeOfPackExpr);
5877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(StmtExpr);
5887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(StringLiteral);
5897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(SubstNonTypeTemplateParmPackExpr);
5907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(UnaryOperator);
5917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(UnaryTypeTraitExpr);
5927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(VAArgExpr);
5937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#undef VISIT
5947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
5957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return ExprEffect::None();
59644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
59744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
5987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#define DECL_VISIT_EXPR(type)                                           \
5997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect Visit##type (clang::type* expr, const Environment& env)
60044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#define IGNORE_EXPR(type)                                               \
6027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect Visit##type (clang::type* expr, const Environment& env) {  \
6037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return ExprEffect::None();                                          \
6047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
60544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(AddrLabelExpr);
6077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(BinaryTypeTraitExpr);
6087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(BlockExpr);
6097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CharacterLiteral);
6107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(ChooseExpr);
6117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CompoundLiteralExpr);
6127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXBoolLiteralExpr);
6137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXDependentScopeMemberExpr);
6147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXNullPtrLiteralExpr);
6157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXPseudoDestructorExpr);
6167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXScalarValueInitExpr);
6177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXNoexceptExpr);
6187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXTypeidExpr);
6197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXUnresolvedConstructExpr);
6207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(CXXUuidofExpr);
6217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(DependentScopeDeclRefExpr);
6227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(DesignatedInitExpr);
6237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(ExtVectorElementExpr);
6247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(FloatingLiteral);
6257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(ImaginaryLiteral);
6267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(IntegerLiteral);
6277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(OffsetOfExpr);
6287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(ImplicitValueInitExpr);
6297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(PackExpansionExpr);
6307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(PredefinedExpr);
6317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(ShuffleVectorExpr);
6327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(SizeOfPackExpr);
6337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(StmtExpr);
6347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(StringLiteral);
6357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(SubstNonTypeTemplateParmPackExpr);
6367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(UnaryTypeTraitExpr);
6377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(VAArgExpr);
6387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(GNUNullExpr);
6397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_EXPR(OverloadExpr);
6407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CXXThisExpr) {
6427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Use(expr, expr->getType(), THIS, env);
6437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
6447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(AbstractConditionalOperator) {
6467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment after_cond = env.ApplyEffect(VisitExpr(expr->getCond(), env));
6477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return ExprEffect::Merge(VisitExpr(expr->getTrueExpr(), after_cond),
6487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                             VisitExpr(expr->getFalseExpr(), after_cond));
6497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
6507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(ArraySubscriptExpr) {
6527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::Expr* exprs[2] = {expr->getBase(), expr->getIdx()};
6537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Par(expr, 2, exprs, env);
6547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
6557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool IsRawPointerVar(clang::Expr* expr, std::string* var_name) {
6577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (isa<clang::BlockDeclRefExpr>(expr)) {
6587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      *var_name = cast<clang::BlockDeclRefExpr>(expr)->getDecl()->
6597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          getNameAsString();
6607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return true;
6617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    } else if (isa<clang::DeclRefExpr>(expr)) {
6627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      *var_name = cast<clang::DeclRefExpr>(expr)->getDecl()->getNameAsString();
6637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return true;
66444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
66544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return false;
66644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
66744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(BinaryOperator) {
6697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::Expr* lhs = expr->getLHS();
6707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::Expr* rhs = expr->getRHS();
6717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::Expr* exprs[2] = {lhs, rhs};
6727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    switch (expr->getOpcode()) {
6747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      case clang::BO_Comma:
6757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return Seq(expr, 2, exprs, env);
6767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      case clang::BO_LAnd:
6787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      case clang::BO_LOr:
6797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return ExprEffect::Merge(VisitExpr(lhs, env), VisitExpr(rhs, env));
6807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      case clang::BO_Assign: {
6827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        std::string var_name;
6837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        if (IsRawPointerVar(lhs, &var_name)) {
6847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          return VisitExpr(rhs, env).Define(var_name);
6857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        }
6867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return Par(expr, 2, exprs, env);
6877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
6887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
6897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      default:
6907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return Par(expr, 2, exprs, env);
6917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
69244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
69344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CXXBindTemporaryExpr) {
6957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getSubExpr(), env);
69644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
69744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
6987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CXXConstructExpr) {
6997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitArguments<>(expr, env);
7007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CXXDefaultArgExpr) {
7037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getExpr(), env);
7047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CXXDeleteExpr) {
7077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getArgument(), env);
7087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CXXNewExpr) {
7117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Par(expr,
7127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org               expr->getNumConstructorArgs(),
7137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org               expr->getConstructorArgs(),
7147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org               env);
7157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(ExprWithCleanups) {
7187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getSubExpr(), env);
7197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CXXThrowExpr) {
7227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getSubExpr(), env);
7237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(InitListExpr) {
7267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Seq(expr, expr->getNumInits(), expr->getInits(), env);
7277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(MemberExpr) {
7307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getBase(), env);
7317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(OpaqueValueExpr) {
7347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getSourceExpr(), env);
7357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(ParenExpr) {
7387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getSubExpr(), env);
7397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(ParenListExpr) {
7427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Par(expr, expr->getNumExprs(), expr->getExprs(), env);
7437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(UnaryOperator) {
7467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // TODO We are treating all expressions that look like &raw_pointer_var
7477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    //      as definitions of raw_pointer_var. This should be changed to
7487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    //      recognize less generic pattern:
7497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    //
7507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    //         if (maybe_object->ToObject(&obj)) return maybe_object;
7517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    //
7527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (expr->getOpcode() == clang::UO_AddrOf) {
7537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      std::string var_name;
7547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (IsRawPointerVar(expr->getSubExpr(), &var_name)) {
7557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return ExprEffect::None().Define(var_name);
7567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
7577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
7587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getSubExpr(), env);
7597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(CastExpr) {
7627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitExpr(expr->getSubExpr(), env);
7637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(DeclRefExpr) {
7667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Use(expr, expr->getDecl(), env);
7677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_EXPR(BlockDeclRefExpr) {
7707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Use(expr, expr->getDecl(), env);
7717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect Par(clang::Expr* parent,
7747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 int n,
7757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 clang::Expr** exprs,
7767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const Environment& env) {
7777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    CallProps props;
7787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (int i = 0; i < n; ++i) {
7807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      props.SetEffect(i, VisitExpr(exprs[i], env));
7817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
7827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (!props.IsSafe()) ReportUnsafe(parent, BAD_EXPR_MSG);
7847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return props.ComputeCumulativeEffect(IsRawPointerType(parent->getType()));
7867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
7877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
7887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect Seq(clang::Stmt* parent,
7897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 int n,
7907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 clang::Expr** exprs,
7917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const Environment& env) {
7927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    ExprEffect out = ExprEffect::None();
7937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment out_env = env;
7947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (int i = 0; i < n; ++i) {
7957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      out = ExprEffect::MergeSeq(out, VisitExpr(exprs[i], out_env));
7967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      out_env = out_env.ApplyEffect(out);
7977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
7987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return out;
7997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
8007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect Use(const clang::Expr* parent,
8027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const clang::QualType& var_type,
8037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const std::string& var_name,
8047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const Environment& env) {
8057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (IsRawPointerType(var_type)) {
8067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (!env.IsAlive(var_name) && dead_vars_analysis_) {
8077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        ReportUnsafe(parent, DEAD_VAR_MSG);
80844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      }
8097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return ExprEffect::RawUse();
81044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
8117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return ExprEffect::None();
8127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
8137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect Use(const clang::Expr* parent,
8157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const clang::ValueDecl* var,
8167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const Environment& env) {
817f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    if (IsExternalVMState(var)) {
818f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ExprEffect::GC();
819f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    }
8207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Use(parent, var->getType(), var->getNameAsString(), env);
8217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
8227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
82344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
8247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  template<typename ExprType>
8257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect VisitArguments(ExprType* call, const Environment& env) {
8267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    CallProps props;
8277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VisitArguments<>(call, &props, env);
8287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG);
8297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return props.ComputeCumulativeEffect(IsRawPointerType(call->getType()));
8307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
8317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  template<typename ExprType>
8337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void VisitArguments(ExprType* call,
8347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                      CallProps* props,
8357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                      const Environment& env) {
83644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    for (unsigned arg = 0; arg < call->getNumArgs(); arg++) {
8377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      props->SetEffect(arg + 1, VisitExpr(call->getArg(arg), env));
83844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
83944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
84044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
8417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ExprEffect VisitCallExpr(clang::CallExpr* call,
8437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                           const Environment& env) {
8447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    CallProps props;
84544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
84644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    clang::CXXMemberCallExpr* memcall =
84744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        dyn_cast_or_null<clang::CXXMemberCallExpr>(call);
8487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (memcall != NULL) {
8497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      clang::Expr* receiver = memcall->getImplicitObjectArgument();
8507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      props.SetEffect(0, VisitExpr(receiver, env));
85144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
85244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
8537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VisitArguments<>(call, &props, env);
8547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG);
8567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    ExprEffect out =
8587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        props.ComputeCumulativeEffect(IsRawPointerType(call->getType()));
8597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::FunctionDecl* callee = call->getDirectCallee();
8617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if ((callee != NULL) && KnownToCauseGC(ctx_, callee)) {
8627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      out.setGC();
8637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
8647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return out;
8667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
8677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // --------------------------------------------------------------------------
8697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // Statements
8707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // --------------------------------------------------------------------------
8717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment VisitStmt(clang::Stmt* stmt, const Environment& env) {
8737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#define VISIT(type) do {                                                \
8747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      clang::type* concrete_stmt = dyn_cast_or_null<clang::type>(stmt); \
8757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (concrete_stmt != NULL) {                                      \
8767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return Visit##type (concrete_stmt, env);                        \
8777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }                                                                 \
8787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    } while(0);
8797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (clang::Expr* expr = dyn_cast_or_null<clang::Expr>(stmt)) {
8817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return env.ApplyEffect(VisitExpr(expr, env));
8827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
8837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
8847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(AsmStmt);
8857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(BreakStmt);
8867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CompoundStmt);
8877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ContinueStmt);
8887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXCatchStmt);
8897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CXXTryStmt);
8907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(DeclStmt);
8917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(DoStmt);
8927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ForStmt);
8937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(GotoStmt);
8947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(IfStmt);
8957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(IndirectGotoStmt);
8967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(LabelStmt);
8977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(NullStmt);
8987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(ReturnStmt);
8997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(CaseStmt);
9007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(DefaultStmt);
9017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(SwitchStmt);
9027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VISIT(WhileStmt);
9037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#undef VISIT
9047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return env;
9067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
9077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#define DECL_VISIT_STMT(type)                                           \
9097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment Visit##type (clang::type* stmt, const Environment& env)
9107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#define IGNORE_STMT(type)                                               \
9127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment Visit##type (clang::type* stmt, const Environment& env) { \
9137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return env;                                                         \
9147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
9157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_STMT(IndirectGotoStmt);
9177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_STMT(NullStmt);
9187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_STMT(AsmStmt);
9197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // We are ignoring control flow for simplicity.
9217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_STMT(GotoStmt);
9227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_STMT(LabelStmt);
9237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  // We are ignoring try/catch because V8 does not use them.
9257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_STMT(CXXCatchStmt);
9267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  IGNORE_STMT(CXXTryStmt);
9277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  class Block {
9297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org   public:
9307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Block(const Environment& in,
9317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          FunctionAnalyzer* owner)
9327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        : in_(in),
9337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          out_(Environment::Unreachable()),
9347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          changed_(false),
9357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          owner_(owner) {
9367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      parent_ = owner_->EnterBlock(this);
9377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    ~Block() {
9407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      owner_->LeaveBlock(parent_);
9417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    void MergeIn(const Environment& env) {
9447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment old_in = in_;
9457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      in_ = Environment::Merge(in_, env);
9467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      changed_ = !old_in.Equal(in_);
9477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    bool changed() {
9507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (changed_) {
9517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        changed_ = false;
9527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        return true;
9537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
9547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return false;
9557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    const Environment& in() {
9587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return in_;
9597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    const Environment& out() {
9627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return out_;
9637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    void MergeOut(const Environment& env) {
9667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      out_ = Environment::Merge(out_, env);
9677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    void Seq(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) {
9707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment a_out = owner_->VisitStmt(a, in());
9717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment b_out = owner_->VisitStmt(b, a_out);
9727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment c_out = owner_->VisitStmt(c, b_out);
9737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      MergeOut(c_out);
9747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    void Seq(clang::Stmt* a, clang::Stmt* b) {
9777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment a_out = owner_->VisitStmt(a, in());
9787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment b_out = owner_->VisitStmt(b, a_out);
9797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      MergeOut(b_out);
9807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    void Loop(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) {
9837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Seq(a, b, c);
9847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      MergeIn(out());
9857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
9867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    void Loop(clang::Stmt* a, clang::Stmt* b) {
9887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Seq(a, b);
9897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      MergeIn(out());
99044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
9917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
9937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org   private:
9947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment in_;
9957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment out_;
9967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    bool changed_;
9977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    FunctionAnalyzer* owner_;
9987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Block* parent_;
9997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  };
10007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(BreakStmt) {
10037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    block_->MergeOut(env);
10047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Environment::Unreachable();
10057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(ContinueStmt) {
10087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    block_->MergeIn(env);
10097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Environment::Unreachable();
10107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(CompoundStmt) {
10137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment out = env;
10147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::CompoundStmt::body_iterator end = stmt->body_end();
10157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (clang::CompoundStmt::body_iterator s = stmt->body_begin();
10167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         s != end;
10177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         ++s) {
10187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      out = VisitStmt(*s, out);
10197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
10207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return out;
10217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(WhileStmt) {
10247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Block block (env, this);
10257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    do {
10267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      block.Loop(stmt->getCond(), stmt->getBody());
10277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    } while (block.changed());
10287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return block.out();
10297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(DoStmt) {
10327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Block block (env, this);
10337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    do {
10347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      block.Loop(stmt->getBody(), stmt->getCond());
10357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    } while (block.changed());
10367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return block.out();
10377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(ForStmt) {
10407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Block block (VisitStmt(stmt->getInit(), env), this);
10417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    do {
10427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      block.Loop(stmt->getCond(),
10437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 stmt->getBody(),
10447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 stmt->getInc());
10457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    } while (block.changed());
10467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return block.out();
10477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(IfStmt) {
10507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment cond_out = VisitStmt(stmt->getCond(), env);
10517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment then_out = VisitStmt(stmt->getThen(), cond_out);
10527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment else_out = VisitStmt(stmt->getElse(), cond_out);
10537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Environment::Merge(then_out, else_out);
10547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(SwitchStmt) {
10577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Block block (env, this);
10587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    block.Seq(stmt->getCond(), stmt->getBody());
10597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return block.out();
10607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(CaseStmt) {
10637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment in = Environment::Merge(env, block_->in());
10647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment after_lhs = VisitStmt(stmt->getLHS(), in);
10657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitStmt(stmt->getSubStmt(), after_lhs);
10667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(DefaultStmt) {
10697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment in = Environment::Merge(env, block_->in());
10707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return VisitStmt(stmt->getSubStmt(), in);
10717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
10727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
10737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(ReturnStmt) {
10747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    VisitExpr(stmt->getRetValue(), env);
10757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return Environment::Unreachable();
107644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
107744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
107844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  const clang::TagType* ToTagType(const clang::Type* t) {
107944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (t == NULL) {
108044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      return NULL;
108144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    } else if (isa<clang::TagType>(t)) {
108244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      return cast<clang::TagType>(t);
108344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    } else if (isa<clang::SubstTemplateTypeParmType>(t)) {
108444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      return ToTagType(cast<clang::SubstTemplateTypeParmType>(t)->
108544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                           getReplacementType().getTypePtr());
108644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    } else {
108744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      return NULL;
108844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
108944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
109044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
10917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool IsDerivedFrom(clang::CXXRecordDecl* record,
10927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                     clang::CXXRecordDecl* base) {
10937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return (record == base) || record->isDerivedFrom(base);
10947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
109544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
10967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool IsRawPointerType(clang::QualType qtype) {
109744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    const clang::PointerType* type =
10987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        dyn_cast_or_null<clang::PointerType>(qtype.getTypePtrOrNull());
109944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (type == NULL) return false;
110044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
110144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    const clang::TagType* pointee =
110244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        ToTagType(type->getPointeeType().getTypePtr());
110344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (pointee == NULL) return false;
110444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
110544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    clang::CXXRecordDecl* record =
110644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        dyn_cast_or_null<clang::CXXRecordDecl>(pointee->getDecl());
110744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    if (record == NULL) return false;
110844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (!InV8Namespace(record)) return false;
111044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (!record->hasDefinition()) return false;
111244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    record = record->getDefinition();
111444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return IsDerivedFrom(record, object_decl_) &&
11167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        !IsDerivedFrom(record, smi_decl_);
111744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
111844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Environment VisitDecl(clang::Decl* decl, const Environment& env) {
11207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (clang::VarDecl* var = dyn_cast<clang::VarDecl>(decl)) {
11217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment out = var->hasInit() ? VisitStmt(var->getInit(), env) : env;
11227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
11237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (IsRawPointerType(var->getType())) {
11247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        out = out.Define(var->getNameAsString());
11257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
112644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return out;
11287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
11297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    // TODO: handle other declarations?
11307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return env;
113144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
113244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  DECL_VISIT_STMT(DeclStmt) {
11347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Environment out = env;
11357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::DeclStmt::decl_iterator end = stmt->decl_end();
11367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (clang::DeclStmt::decl_iterator decl = stmt->decl_begin();
11377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         decl != end;
11387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         ++decl) {
11397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      out = VisitDecl(*decl, out);
11407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
11417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return out;
114244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
114344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
114444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void DefineParameters(const clang::FunctionDecl* f,
11467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                        Environment* env) {
11477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    env->MDefine(THIS);
11487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::FunctionDecl::param_const_iterator end = f->param_end();
11497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (clang::FunctionDecl::param_const_iterator p = f->param_begin();
11507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         p != end;
11517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org         ++p) {
11527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      env->MDefine((*p)->getNameAsString());
11537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
11547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
115544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
115644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void AnalyzeFunction(const clang::FunctionDecl* f) {
11587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    const clang::FunctionDecl* body = NULL;
11597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (f->hasBody(body)) {
11607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment env;
11617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      DefineParameters(body, &env);
11627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      VisitStmt(body->getBody(), env);
11637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      Environment::ClearSymbolTable();
11647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
11657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
116644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Block* EnterBlock(Block* block) {
11687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    Block* parent = block_;
11697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    block_ = block;
11707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return parent;
11717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
117244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void LeaveBlock(Block* block) {
11747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    block_ = block;
11757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
117644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org private:
11787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void ReportUnsafe(const clang::Expr* expr, const std::string& msg) {
11797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    d_.Report(clang::FullSourceLoc(expr->getExprLoc(), sm_),
11807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org              d_.getCustomDiagID(clang::Diagnostic::Warning, msg));
11817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
118244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
118344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::MangleContext* ctx_;
11857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::DeclarationName handle_decl_name_;
11867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::CXXRecordDecl* object_decl_;
11877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::CXXRecordDecl* smi_decl_;
118844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::Diagnostic& d_;
11907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  clang::SourceManager& sm_;
119144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Block* block_;
11937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool dead_vars_analysis_;
11947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org};
119544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
119644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
11977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgclass ProblemsFinder : public clang::ASTConsumer,
11987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                       public clang::RecursiveASTVisitor<ProblemsFinder> {
11997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org public:
12007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  ProblemsFinder(clang::Diagnostic& d,
12017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 clang::SourceManager& sm,
12027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                 const std::vector<std::string>& args)
12037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      : d_(d), sm_(sm), dead_vars_analysis_(false) {
12047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    for (unsigned i = 0; i < args.size(); ++i) {
12057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (args[i] == "--dead-vars") {
12067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        dead_vars_analysis_ = true;
12077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
120844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
12097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
121044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
121144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  virtual void HandleTranslationUnit(clang::ASTContext &ctx) {
121244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    Resolver r(ctx);
121344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
12147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::CXXRecordDecl* object_decl =
121544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org        r.ResolveNamespace("v8").ResolveNamespace("internal").
121644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org            Resolve<clang::CXXRecordDecl>("Object");
121744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
12187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    clang::CXXRecordDecl* smi_decl =
12197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        r.ResolveNamespace("v8").ResolveNamespace("internal").
12207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org            Resolve<clang::CXXRecordDecl>("Smi");
12217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
12227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (object_decl != NULL) object_decl = object_decl->getDefinition();
12237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
12247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (smi_decl != NULL) smi_decl = smi_decl->getDefinition();
12257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org
12267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    if (object_decl != NULL && smi_decl != NULL) {
12277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      function_analyzer_ =
12287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org          new FunctionAnalyzer(clang::createItaniumMangleContext(ctx, d_),
12297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                               r.ResolveName("Handle"),
12307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                               object_decl,
12317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                               smi_decl,
12327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                               d_,
12337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                               sm_,
12347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                               dead_vars_analysis_);
123544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      TraverseDecl(ctx.getTranslationUnitDecl());
123644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    } else {
12377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (object_decl == NULL) {
12387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        llvm::errs() << "Failed to resolve v8::internal::Object\n";
12397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
12407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      if (smi_decl == NULL) {
12417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org        llvm::errs() << "Failed to resolve v8::internal::Smi\n";
12427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      }
124344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    }
124444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
124544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
12467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) {
12477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    function_analyzer_->AnalyzeFunction(decl);
124844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return true;
124944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
125044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
125144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org private:
125244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  clang::Diagnostic& d_;
125344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  clang::SourceManager& sm_;
12547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  bool dead_vars_analysis_;
125544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
12567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  FunctionAnalyzer* function_analyzer_;
125744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org};
125844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
125944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
126044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgtemplate<typename ConsumerType>
126144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgclass Action : public clang::PluginASTAction {
126244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org protected:
126344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &CI,
126444bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                                        llvm::StringRef InFile) {
12657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    return new ConsumerType(CI.getDiagnostics(), CI.getSourceManager(), args_);
126644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
126744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
126844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  bool ParseArgs(const clang::CompilerInstance &CI,
126944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org                 const std::vector<std::string>& args) {
12707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    args_ = args;
127144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    return true;
127244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  }
127344bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
12747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  void PrintHelp(llvm::raw_ostream& ros) {
12757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  }
12767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org private:
12777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  std::vector<std::string> args_;
127844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org};
127944bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
128044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
128144bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org}
128244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
12837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic clang::FrontendPluginRegistry::Add<Action<ProblemsFinder> >
12847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgFindProblems("find-problems", "Find GC-unsafe places.");
128544bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
12867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic clang::FrontendPluginRegistry::Add<
12877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  Action<FunctionDeclarationFinder> >
128844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgDumpCallees("dump-callees", "Dump callees for each function.");
1289