text:
namespace {

bool g_tracing_enabled = false;
bool g_dead_vars_analysis = false;

#define TRACE(str)                   \
  do {                               \
    if (g_tracing_enabled) {         \
      std::cout << str << std::endl; \
    }                                \
  } while (false)

#define TRACE_LLVM_TYPE(str, type)                                \
  do {                                                            \
    if (g_tracing_enabled) {                                      \
      std::cout << str << " " << type.getAsString() << std::endl; \
    }                                                             \
  } while (false)

// Node: The following is used when tracing --dead-vars
// to provide extra info for the GC suspect.
#define TRACE_LLVM_DECL(str, decl)                   \
  do {                                               \
    if (g_tracing_enabled && g_dead_vars_analysis) { \
      std::cout << str << std::endl;                 \
      decl->dump();                                  \
    }                                                \
  } while (false)

typedef std::string MangledName;
typedef std::set<MangledName> CalleesSet;
typedef std::map<MangledName, MangledName> CalleesMap;

static bool GetMangledName(clang::MangleContext* ctx,
                           const clang::NamedDecl* decl,
                           MangledName* result) {
  if (!llvm::isa<clang::CXXConstructorDecl>(decl) &&
      !llvm::isa<clang::CXXDestructorDecl>(decl)) {
    llvm::SmallVector<char, 512> output;
    llvm::raw_svector_ostream out(output);
    ctx->mangleName(decl, out);
    *result = out.str().str();
    return true;
  }

  return false;
}

static bool InV8Namespace(const clang::NamedDecl* decl) {
  return decl->getQualifiedNameAsString().compare(0, 4, "v8::") == 0;
}

static std::string EXTERNAL("EXTERNAL");
static std::string STATE_TAG("enum v8::internal::StateTag");

static bool IsExternalVMState(const clang::ValueDecl* var) {
  const clang::EnumConstantDecl* enum_constant =
      llvm::dyn_cast<clang::EnumConstantDecl>(var);
  if (enum_constant != NULL && enum_constant->getNameAsString() == EXTERNAL) {
    clang::QualType type = enum_constant->getType();
    return (type.getAsString() == STATE_TAG);
  }

  return false;
}

struct Resolver {
  explicit Resolver(clang::ASTContext& ctx)
      : ctx_(ctx), decl_ctx_(ctx.getTranslationUnitDecl()) {
  }

  Resolver(clang::ASTContext& ctx, clang::DeclContext* decl_ctx)
      : ctx_(ctx), decl_ctx_(decl_ctx) {
  }

  clang::DeclarationName ResolveName(const char* n) {
    clang::IdentifierInfo* ident = &ctx_.Idents.get(n);
    return ctx_.DeclarationNames.getIdentifier(ident);
  }

  Resolver ResolveNamespace(const char* n) {
    return Resolver(ctx_, Resolve<clang::NamespaceDecl>(n));
  }

  template<typename T>
  T* Resolve(const char* n) {
    if (decl_ctx_ == NULL) return NULL;

    clang::DeclContext::lookup_result result =
        decl_ctx_->lookup(ResolveName(n));

    clang::DeclContext::lookup_iterator end = result.end();
    for (clang::DeclContext::lookup_iterator i = result.begin(); i != end;
         i++) {
      if (llvm::isa<T>(*i)) {
        return llvm::cast<T>(*i);
      } else {
        llvm::errs() << "Didn't match declaration template against "
                     << (*i)->getNameAsString() << "\n";
      }
    }

    return NULL;
  }

  clang::CXXRecordDecl* ResolveTemplate(const char* n) {
    clang::NamedDecl* initial_template = Resolve<clang::NamedDecl>(n);
    if (!initial_template) return NULL;

    clang::NamedDecl* underlying_template =
        initial_template->getUnderlyingDecl();
    if (!underlying_template) {
      llvm::errs() << "Couldn't resolve underlying template\n";
      return NULL;
    }
    const clang::TypeAliasDecl* type_alias_decl =
        llvm::dyn_cast_or_null<clang::TypeAliasDecl>(underlying_template);
    if (!type_alias_decl) {
      llvm::errs() << "Couldn't resolve TypeAliasDecl\n";
      return NULL;
    }
    const clang::Type* type = type_alias_decl->getTypeForDecl();
    if (!type) {
      llvm::errs() << "Couldn't resolve TypeAliasDecl to Type\n";
      return NULL;
    }
    const clang::TypedefType* typedef_type =
        llvm::dyn_cast_or_null<clang::TypedefType>(type);
    if (!typedef_type) {
      llvm::errs() << "Couldn't resolve TypedefType\n";
      return NULL;
    }
    const clang::TypedefNameDecl* typedef_name_decl = typedef_type->getDecl();
    if (!typedef_name_decl) {
      llvm::errs() << "Couldn't resolve TypedefType to TypedefNameDecl\n";
      return NULL;
    }

    clang::QualType underlying_type = typedef_name_decl->getUnderlyingType();
    if (!llvm::isa<clang::TemplateSpecializationType>(underlying_type)) {
      llvm::errs() << "Couldn't resolve TemplateSpecializationType\n";
      return NULL;
    }

    const clang::TemplateSpecializationType* templ_specialization_type =
        llvm::cast<clang::TemplateSpecializationType>(underlying_type);
    if (!llvm::isa<clang::RecordType>(templ_specialization_type->desugar())) {
      llvm::errs() << "Couldn't resolve RecordType\n";
      return NULL;
    }

    const clang::RecordType* record_type =
        llvm::cast<clang::RecordType>(templ_specialization_type->desugar());
    clang::CXXRecordDecl* record_decl =
        llvm::dyn_cast_or_null<clang::CXXRecordDecl>(record_type->getDecl());
    if (!record_decl) {
      llvm::errs() << "Couldn't resolve CXXRecordDecl\n";
      return NULL;
    }
    return record_decl;
  }

 private:
  clang::ASTContext& ctx_;
  clang::DeclContext* decl_ctx_;
};

class CalleesPrinter : public clang::RecursiveASTVisitor<CalleesPrinter> {
 public:
  explicit CalleesPrinter(clang::MangleContext* ctx) : ctx_(ctx) {
  }

  virtual bool VisitCallExpr(clang::CallExpr* expr) {
    const clang::FunctionDecl* callee = expr->getDirectCallee();
    if (callee != NULL) AnalyzeFunction(callee);
    return true;
  }

  virtual bool VisitDeclRefExpr(clang::DeclRefExpr* expr) {
    // If function mentions EXTERNAL VMState add artificial garbage collection
    // mark.
    if (IsExternalVMState(expr->getDecl()))
      AddCallee("CollectGarbage", "CollectGarbage");
    return true;
  }

  void AnalyzeFunction(const clang::FunctionDecl* f) {
    MangledName name;
    if (InV8Namespace(f) && GetMangledName(ctx_, f, &name)) {
      const std::string& function = f->getNameAsString();
      AddCallee(name, function);

      const clang::FunctionDecl* body = NULL;
      if (f->hasBody(body) && !Analyzed(name)) {
        EnterScope(name);
        TraverseStmt(body->getBody());
        LeaveScope();
      }
    }
  }

  typedef std::map<MangledName, CalleesSet* > Callgraph;

  bool Analyzed(const MangledName& name) {
    return callgraph_[name] != NULL;
  }

  void EnterScope(const MangledName& name) {
    CalleesSet* callees = callgraph_[name];

    if (callees == NULL) {
      callgraph_[name] = callees = new CalleesSet();
    }

    scopes_.push(callees);
  }

  void LeaveScope() {
    scopes_.pop();
  }

  void AddCallee(const MangledName& name, const MangledName& function) {
    if (!scopes_.empty()) scopes_.top()->insert(name);
    mangled_to_function_[name] = function;
  }

  void PrintCallGraph() {
    for (Callgraph::const_iterator i = callgraph_.begin(), e = callgraph_.end();
         i != e;
         ++i) {
      std::cout << i->first << "," << mangled_to_function_[i->first] << "\n";

      CalleesSet* callees = i->second;
      for (CalleesSet::const_iterator j = callees->begin(), e = callees->end();
           j != e;
           ++j) {
        std::cout << "\t" << *j << "," << mangled_to_function_[*j] << "\n";
      }
    }
  }

 private:
  clang::MangleContext* ctx_;

  std::stack<CalleesSet* > scopes_;
  Callgraph callgraph_;
  CalleesMap mangled_to_function_;
};

class FunctionDeclarationFinder
    : public clang::ASTConsumer,
      public clang::RecursiveASTVisitor<FunctionDeclarationFinder> {
 public:
  explicit FunctionDeclarationFinder(clang::DiagnosticsEngine& d,
                                     clang::SourceManager& sm,
                                     const std::vector<std::string>& args)
      : d_(d), sm_(sm) {}

  virtual void HandleTranslationUnit(clang::ASTContext &ctx) {
    mangle_context_ = clang::ItaniumMangleContext::create(ctx, d_);
    callees_printer_ = new CalleesPrinter(mangle_context_);

    TraverseDecl(ctx.getTranslationUnitDecl());

    callees_printer_->PrintCallGraph();
  }

  virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) {
    callees_printer_->AnalyzeFunction(decl);
    return true;
  }

 private:
  clang::DiagnosticsEngine& d_;
  clang::SourceManager& sm_;
  clang::MangleContext* mangle_context_;

  CalleesPrinter* callees_printer_;
};

static bool gc_suspects_loaded = false;
static CalleesSet gc_suspects;
static CalleesSet gc_functions;
static bool whitelist_loaded = false;
static CalleesSet suspects_whitelist;

static void LoadGCSuspects() {
  if (gc_suspects_loaded) return;

  std::ifstream fin("gcsuspects");
  std::string mangled, function;

  while (!fin.eof()) {
    std::getline(fin, mangled, ',');
    gc_suspects.insert(mangled);
    std::getline(fin, function);
    gc_functions.insert(function);
  }

  gc_suspects_loaded = true;
}

static void LoadSuspectsWhitelist() {
  if (whitelist_loaded) return;

  std::ifstream fin("tools/gcmole/suspects.whitelist");
  std::string s;

  while (fin >> s) suspects_whitelist.insert(s);

  whitelist_loaded = true;
}

// Looks for exact match of the mangled name.
static bool KnownToCauseGC(clang::MangleContext* ctx,
                           const clang::FunctionDecl* decl) {
  LoadGCSuspects();

  if (!InV8Namespace(decl)) return false;

  if (suspects_whitelist.find(decl->getNameAsString()) !=
      suspects_whitelist.end()) {
    return false;
  }

  MangledName name;
  if (GetMangledName(ctx, decl, &name)) {
    return gc_suspects.find(name) != gc_suspects.end();
  }

  return false;
}

// Looks for partial match of only the function name.
static bool SuspectedToCauseGC(clang::MangleContext* ctx,
                               const clang::FunctionDecl* decl) {
  LoadGCSuspects();

  if (!InV8Namespace(decl)) return false;

  LoadSuspectsWhitelist();
  if (suspects_whitelist.find(decl->getNameAsString()) !=
      suspects_whitelist.end()) {
    return false;
  }

  if (gc_functions.find(decl->getNameAsString()) != gc_functions.end()) {
    TRACE_LLVM_DECL("Suspected by ", decl);
    return true;
  }

  return false;
}

static const int kNoEffect = 0;
static const int kCausesGC = 1;
static const int kRawDef = 2;
static const int kRawUse = 4;
static const int kAllEffects = kCausesGC | kRawDef | kRawUse;

class Environment;

class ExprEffect {
 public:
  bool hasGC() { return (effect_ & kCausesGC) != 0; }
  void setGC() { effect_ |= kCausesGC; }

  bool hasRawDef() { return (effect_ & kRawDef) != 0; }
  void setRawDef() { effect_ |= kRawDef; }

  bool hasRawUse() { return (effect_ & kRawUse) != 0; }
  void setRawUse() { effect_ |= kRawUse; }

  static ExprEffect None() { return ExprEffect(kNoEffect, NULL); }
  static ExprEffect NoneWithEnv(Environment* env) {
    return ExprEffect(kNoEffect, env);
  }
  static ExprEffect RawUse() { return ExprEffect(kRawUse, NULL); }

  static ExprEffect Merge(ExprEffect a, ExprEffect b);
  static ExprEffect MergeSeq(ExprEffect a, ExprEffect b);
  ExprEffect Define(const std::string& name);

  Environment* env() {
    return reinterpret_cast<Environment*>(effect_ & ~kAllEffects);
  }

  static ExprEffect GC() {
    return ExprEffect(kCausesGC, NULL);
  }

 private:
  ExprEffect(int effect, Environment* env)
      : effect_((effect & kAllEffects) |
                reinterpret_cast<intptr_t>(env)) { }

  intptr_t effect_;
};

const std::string BAD_EXPR_MSG("Possible problem with evaluation order.");
const std::string DEAD_VAR_MSG("Possibly dead variable.");

class Environment {
 public:
  Environment() = default;

  static Environment Unreachable() {
    Environment env;
    env.unreachable_ = true;
    return env;
  }

  static Environment Merge(const Environment& l,
                           const Environment& r) {
    Environment out(l);
    out &= r;
    return out;
  }

  Environment ApplyEffect(ExprEffect effect) const {
    Environment out = effect.hasGC() ? Environment() : Environment(*this);
    if (effect.env()) out |= *effect.env();
    return out;
  }

  typedef std::map<std::string, int> SymbolTable;

  bool IsAlive(const std::string& name) const {
    SymbolTable::iterator code = symbol_table_.find(name);
    if (code == symbol_table_.end()) return false;
    return is_live(code->second);
  }

  bool Equal(const Environment& env) {
    if (unreachable_ && env.unreachable_) return true;
    size_t size = std::max(live_.size(), env.live_.size());
    for (size_t i = 0; i < size; ++i) {
      if (is_live(i) != env.is_live(i)) return false;
    }
    return true;
  }

  Environment Define(const std::string& name) const {
    return Environment(*this, SymbolToCode(name));
  }

  void MDefine(const std::string& name) { set_live(SymbolToCode(name)); }

  static int SymbolToCode(const std::string& name) {
    SymbolTable::iterator code = symbol_table_.find(name);

    if (code == symbol_table_.end()) {
      int new_code = symbol_table_.size();
      symbol_table_.insert(std::make_pair(name, new_code));
      return new_code;
    }

    return code->second;
  }

  static void ClearSymbolTable() {
    for (Environment* e : envs_) delete e;
    envs_.clear();
    symbol_table_.clear();
  }

  void Print() const {
    bool comma = false;
    std::cout << "{";
    for (auto& e : symbol_table_) {
      if (!is_live(e.second)) continue;
      if (comma) std::cout << ", ";
      std::cout << e.first;
      comma = true;
    }
    std::cout << "}" << std::endl;
  }

  static Environment* Allocate(const Environment& env) {
    Environment* allocated_env = new Environment(env);
    envs_.push_back(allocated_env);
    return allocated_env;
  }

 private:
  Environment(const Environment& l, int code)
      : live_(l.live_) {
    set_live(code);
  }

  void set_live(size_t pos) {
    if (unreachable_) return;
    if (pos >= live_.size()) live_.resize(pos + 1);
    live_[pos] = true;
  }

  bool is_live(size_t pos) const {
    return unreachable_ || (live_.size() > pos && live_[pos]);
  }

  Environment& operator|=(const Environment& o) {
    if (o.unreachable_) {
      unreachable_ = true;
      live_.clear();
    } else if (!unreachable_) {
      for (size_t i = 0, e = o.live_.size(); i < e; ++i) {
        if (o.live_[i]) set_live(i);
      }
    }
    return *this;
  }

  Environment& operator&=(const Environment& o) {
    if (o.unreachable_) return *this;
    if (unreachable_) return *this = o;

    // Carry over false bits from the tail of o.live_, and reset all bits that
    // are not set in o.live_.
    size_t size = std::max(live_.size(), o.live_.size());
    if (size > live_.size()) live_.resize(size);
    for (size_t i = 0; i < size; ++i) {
      if (live_[i] && (i >= o.live_.size() || !o.live_[i])) live_[i] = false;
    }
    return *this;
  }

  static SymbolTable symbol_table_;
  static std::vector<Environment*> envs_;

  std::vector<bool> live_;
  // unreachable_ == true implies live_.empty(), but still is_live(i) returns
  // true for all i.
  bool unreachable_ = false;

  friend class ExprEffect;
  friend class CallProps;
};

class CallProps {
 public:
  CallProps() : env_(NULL) { }

  void SetEffect(int arg, ExprEffect in) {
    if (in.hasGC()) {
      gc_.set(arg);
    }
    if (in.hasRawDef()) raw_def_.set(arg);
    if (in.hasRawUse()) raw_use_.set(arg);
    if (in.env() != NULL) {
      if (env_ == NULL) {
        env_ = in.env();
      } else {
        *env_ |= *in.env();
      }
    }
  }

  ExprEffect ComputeCumulativeEffect(bool result_is_raw) {
    ExprEffect out = ExprEffect::NoneWithEnv(env_);
    if (gc_.any()) {
      out.setGC();
    }
    if (raw_use_.any()) out.setRawUse();
    if (result_is_raw) out.setRawDef();
    return out;
  }

  bool IsSafe() {
    if (!gc_.any()) {
      return true;
    }
    std::bitset<kMaxNumberOfArguments> raw = (raw_def_ | raw_use_);
    if (!raw.any()) {
      return true;
    }
    bool result = gc_.count() == 1 && !((raw ^ gc_).any());
    return result;
  }

 private:
  static const int kMaxNumberOfArguments = 64;
  std::bitset<kMaxNumberOfArguments> raw_def_;
  std::bitset<kMaxNumberOfArguments> raw_use_;
  std::bitset<kMaxNumberOfArguments> gc_;
  Environment* env_;
};

Environment::SymbolTable Environment::symbol_table_;
std::vector<Environment*> Environment::envs_;

ExprEffect ExprEffect::Merge(ExprEffect a, ExprEffect b) {
  Environment* a_env = a.env();
  Environment* b_env = b.env();
  Environment* out = NULL;
  if (a_env != NULL && b_env != NULL) {
    out = Environment::Allocate(*a_env);
    *out &= *b_env;
  }
  return ExprEffect(a.effect_ | b.effect_, out);
}

ExprEffect ExprEffect::MergeSeq(ExprEffect a, ExprEffect b) {
  Environment* a_env = b.hasGC() ? NULL : a.env();
  Environment* b_env = b.env();
  Environment* out = (b_env == NULL) ? a_env : b_env;
  if (a_env != NULL && b_env != NULL) {
    out = Environment::Allocate(*b_env);
    *out |= *a_env;
  }
  return ExprEffect(a.effect_ | b.effect_, out);
}

ExprEffect ExprEffect::Define(const std::string& name) {
  Environment* e = env();
  if (e == NULL) {
    e = Environment::Allocate(Environment());
  }
  e->MDefine(name);
  return ExprEffect(effect_, e);
}

static std::string THIS ("this");

class FunctionAnalyzer {
 public:
  FunctionAnalyzer(clang::MangleContext* ctx, clang::CXXRecordDecl* object_decl,
                   clang::CXXRecordDecl* maybe_object_decl,
                   clang::CXXRecordDecl* smi_decl,
                   clang::CXXRecordDecl* no_gc_decl,
                   clang::CXXRecordDecl* no_gc_or_safepoint_decl,
                   clang::CXXRecordDecl* no_heap_access_decl,
                   clang::DiagnosticsEngine& d, clang::SourceManager& sm)
      : ctx_(ctx),
        object_decl_(object_decl),
        maybe_object_decl_(maybe_object_decl),
        smi_decl_(smi_decl),
        no_gc_decl_(no_gc_decl),
        no_gc_or_safepoint_decl_(no_gc_or_safepoint_decl),
        no_heap_access_decl_(no_heap_access_decl),
        d_(d),
        sm_(sm),
        block_(NULL) {}

  // --------------------------------------------------------------------------
  // Expressions
  // --------------------------------------------------------------------------

  ExprEffect VisitExpr(clang::Expr* expr, const Environment& env) {
#define VISIT(type)                                                         \
  do {                                                                      \
    clang::type* concrete_expr = llvm::dyn_cast_or_null<clang::type>(expr); \
    if (concrete_expr != NULL) {                                            \
      return Visit##type(concrete_expr, env);                               \
    }                                                                       \
  } while (0);

    VISIT(AbstractConditionalOperator);
    VISIT(AddrLabelExpr);
    VISIT(ArraySubscriptExpr);
    VISIT(BinaryOperator);
    VISIT(BlockExpr);
    VISIT(CallExpr);
    VISIT(CastExpr);
    VISIT(CharacterLiteral);
    VISIT(ChooseExpr);
    VISIT(CompoundLiteralExpr);
    VISIT(ConstantExpr);
    VISIT(CXXBindTemporaryExpr);
    VISIT(CXXBoolLiteralExpr);
    VISIT(CXXConstructExpr);
    VISIT(CXXDefaultArgExpr);
    VISIT(CXXDeleteExpr);
    VISIT(CXXDependentScopeMemberExpr);
    VISIT(CXXNewExpr);
    VISIT(CXXNoexceptExpr);
    VISIT(CXXNullPtrLiteralExpr);
    VISIT(CXXPseudoDestructorExpr);
    VISIT(CXXScalarValueInitExpr);
    VISIT(CXXThisExpr);
    VISIT(CXXThrowExpr);
    VISIT(CXXTypeidExpr);
    VISIT(CXXUnresolvedConstructExpr);
    VISIT(CXXUuidofExpr);
    VISIT(DeclRefExpr);
    VISIT(DependentScopeDeclRefExpr);
    VISIT(DesignatedInitExpr);
    VISIT(ExprWithCleanups);
    VISIT(ExtVectorElementExpr);
    VISIT(FloatingLiteral);
    VISIT(GNUNullExpr);
    VISIT(ImaginaryLiteral);
    VISIT(ImplicitCastExpr);
    VISIT(ImplicitValueInitExpr);
    VISIT(InitListExpr);
    VISIT(IntegerLiteral);
    VISIT(MaterializeTemporaryExpr);
    VISIT(MemberExpr);
    VISIT(OffsetOfExpr);
    VISIT(OpaqueValueExpr);
    VISIT(OverloadExpr);
    VISIT(PackExpansionExpr);
    VISIT(ParenExpr);
    VISIT(ParenListExpr);
    VISIT(PredefinedExpr);
    VISIT(ShuffleVectorExpr);
    VISIT(SizeOfPackExpr);
    VISIT(StmtExpr);
    VISIT(StringLiteral);
    VISIT(SubstNonTypeTemplateParmPackExpr);
    VISIT(TypeTraitExpr);
    VISIT(UnaryOperator);
    VISIT(UnaryExprOrTypeTraitExpr);
    VISIT(VAArgExpr);
#undef VISIT

    return ExprEffect::None();
  }

#define DECL_VISIT_EXPR(type)                                           \
  ExprEffect Visit##type (clang::type* expr, const Environment& env)

#define IGNORE_EXPR(type)                                               \
  ExprEffect Visit##type (clang::type* expr, const Environment& env) {  \
    return ExprEffect::None();                                          \
  }

  IGNORE_EXPR(AddrLabelExpr);
  IGNORE_EXPR(BlockExpr);
  IGNORE_EXPR(CharacterLiteral);
  IGNORE_EXPR(ChooseExpr);
  IGNORE_EXPR(CompoundLiteralExpr);
  IGNORE_EXPR(CXXBoolLiteralExpr);
  IGNORE_EXPR(CXXDependentScopeMemberExpr);
  IGNORE_EXPR(CXXNullPtrLiteralExpr);
  IGNORE_EXPR(CXXPseudoDestructorExpr);
  IGNORE_EXPR(CXXScalarValueInitExpr);
  IGNORE_EXPR(CXXNoexceptExpr);
  IGNORE_EXPR(CXXTypeidExpr);
  IGNORE_EXPR(CXXUnresolvedConstructExpr);
  IGNORE_EXPR(CXXUuidofExpr);
  IGNORE_EXPR(DependentScopeDeclRefExpr);
  IGNORE_EXPR(DesignatedInitExpr);
  IGNORE_EXPR(ExtVectorElementExpr);
  IGNORE_EXPR(FloatingLiteral);
  IGNORE_EXPR(ImaginaryLiteral);
  IGNORE_EXPR(IntegerLiteral);
  IGNORE_EXPR(OffsetOfExpr);
  IGNORE_EXPR(ImplicitValueInitExpr);
  IGNORE_EXPR(PackExpansionExpr);
  IGNORE_EXPR(PredefinedExpr);
  IGNORE_EXPR(ShuffleVectorExpr);
  IGNORE_EXPR(SizeOfPackExpr);
  IGNORE_EXPR(StmtExpr);
  IGNORE_EXPR(StringLiteral);
  IGNORE_EXPR(SubstNonTypeTemplateParmPackExpr);
  IGNORE_EXPR(TypeTraitExpr);
  IGNORE_EXPR(VAArgExpr);
  IGNORE_EXPR(GNUNullExpr);
  IGNORE_EXPR(OverloadExpr);

  DECL_VISIT_EXPR(CXXThisExpr) {
    return Use(expr, expr->getType(), THIS, env);
  }

  DECL_VISIT_EXPR(AbstractConditionalOperator) {
    Environment after_cond = env.ApplyEffect(VisitExpr(expr->getCond(), env));
    return ExprEffect::Merge(VisitExpr(expr->getTrueExpr(), after_cond),
                             VisitExpr(expr->getFalseExpr(), after_cond));
  }

  DECL_VISIT_EXPR(ArraySubscriptExpr) {
    clang::Expr* exprs[2] = {expr->getBase(), expr->getIdx()};
    return Parallel(expr, 2, exprs, env);
  }

  bool IsRawPointerVar(clang::Expr* expr, std::string* var_name) {
    if (llvm::isa<clang::DeclRefExpr>(expr)) {
      *var_name =
          llvm::cast<clang::DeclRefExpr>(expr)->getDecl()->getNameAsString();
      return true;
    }

    return false;
  }

  DECL_VISIT_EXPR(BinaryOperator) {
    clang::Expr* lhs = expr->getLHS();
    clang::Expr* rhs = expr->getRHS();
    clang::Expr* exprs[2] = {lhs, rhs};

    switch (expr->getOpcode()) {
      case clang::BO_Comma:
        return Sequential(expr, 2, exprs, env);

      case clang::BO_LAnd:
      case clang::BO_LOr:
        return ExprEffect::Merge(VisitExpr(lhs, env), VisitExpr(rhs, env));

      default:
        return Parallel(expr, 2, exprs, env);
    }
  }

  DECL_VISIT_EXPR(CXXBindTemporaryExpr) {
    return VisitExpr(expr->getSubExpr(), env);
  }

  DECL_VISIT_EXPR(MaterializeTemporaryExpr) {
    return VisitExpr(expr->GetTemporaryExpr(), env);
  }

  DECL_VISIT_EXPR(CXXConstructExpr) {
    return VisitArguments<>(expr, env);
  }

  DECL_VISIT_EXPR(CXXDefaultArgExpr) {
    return VisitExpr(expr->getExpr(), env);
  }

  DECL_VISIT_EXPR(CXXDeleteExpr) {
    return VisitExpr(expr->getArgument(), env);
  }

  DECL_VISIT_EXPR(CXXNewExpr) { return VisitExpr(expr->getInitializer(), env); }

  DECL_VISIT_EXPR(ExprWithCleanups) {
    return VisitExpr(expr->getSubExpr(), env);
  }

  DECL_VISIT_EXPR(CXXThrowExpr) {
    return VisitExpr(expr->getSubExpr(), env);
  }

  DECL_VISIT_EXPR(ImplicitCastExpr) {
    return VisitExpr(expr->getSubExpr(), env);
  }

  DECL_VISIT_EXPR(ConstantExpr) { return VisitExpr(expr->getSubExpr(), env); }

  DECL_VISIT_EXPR(InitListExpr) {
    return Sequential(expr, expr->getNumInits(), expr->getInits(), env);
  }

  DECL_VISIT_EXPR(MemberExpr) {
    return VisitExpr(expr->getBase(), env);
  }

  DECL_VISIT_EXPR(OpaqueValueExpr) {
    return VisitExpr(expr->getSourceExpr(), env);
  }

  DECL_VISIT_EXPR(ParenExpr) {
    return VisitExpr(expr->getSubExpr(), env);
  }

  DECL_VISIT_EXPR(ParenListExpr) {
    return Parallel(expr, expr->getNumExprs(), expr->getExprs(), env);
  }

  DECL_VISIT_EXPR(UnaryOperator) {
    // TODO(gcmole): We are treating all expressions that look like
    // {&raw_pointer_var} as definitions of {raw_pointer_var}. This should be
    // changed to recognize less generic pattern:
    //
    //   if (maybe_object->ToObject(&obj)) return maybe_object;
    //
    if (expr->getOpcode() == clang::UO_AddrOf) {
      std::string var_name;
      if (IsRawPointerVar(expr->getSubExpr(), &var_name)) {
        return ExprEffect::None().Define(var_name);
      }
    }
    return VisitExpr(expr->getSubExpr(), env);
  }

  DECL_VISIT_EXPR(UnaryExprOrTypeTraitExpr) {
    if (expr->isArgumentType()) {
      return ExprEffect::None();
    }

    return VisitExpr(expr->getArgumentExpr(), env);
  }

  DECL_VISIT_EXPR(CastExpr) {
    return VisitExpr(expr->getSubExpr(), env);
  }

  DECL_VISIT_EXPR(DeclRefExpr) {
    return Use(expr, expr->getDecl(), env);
  }

  // Represents a node in the AST {parent} whose children {exprs} have
  // undefined order of evaluation, e.g. array subscript or a binary operator.
  ExprEffect Parallel(clang::Expr* parent, int n, clang::Expr** exprs,
                      const Environment& env) {
    CallProps props;

    for (int i = 0; i < n; ++i) {
      props.SetEffect(i, VisitExpr(exprs[i], env));
    }

    if (!props.IsSafe()) ReportUnsafe(parent, BAD_EXPR_MSG);

    return props.ComputeCumulativeEffect(
        RepresentsRawPointerType(parent->getType()));
  }

  // Represents a node in the AST {parent} whose children {exprs} are
  // executed in sequence, e.g. a switch statement or an initializer list.
  ExprEffect Sequential(clang::Stmt* parent, int n, clang::Expr** exprs,
                        const Environment& env) {
    ExprEffect out = ExprEffect::None();
    Environment out_env = env;
    for (int i = 0; i < n; ++i) {
      out = ExprEffect::MergeSeq(out, VisitExpr(exprs[i], out_env));
      out_env = out_env.ApplyEffect(out);
    }
    return out;
  }

  // Represents a node in the AST {parent} which uses the variable {var_name},
  // e.g. this expression or operator&.
  // Here we observe the type in {var_type} of a previously declared variable
  // and if it's a raw heap object type, we do the following:
  // 1. If it got stale due to GC since its declaration, we report it as such.
  // 2. Mark its raw usage in the ExprEffect returned by this function.
  ExprEffect Use(const clang::Expr* parent,
                 const clang::QualType& var_type,
                 const std::string& var_name,
                 const Environment& env) {
    if (RepresentsRawPointerType(var_type)) {
      // We currently care only about our internal pointer types and not about
      // raw C++ pointers, because normally special care is taken when storing
      // raw pointers to the managed heap. Furthermore, checking for raw
      // pointers produces too many false positives in the dead variable
      // analysis.
      if (IsInternalPointerType(var_type) && !env.IsAlive(var_name) &&
          !HasActiveGuard() && g_dead_vars_analysis) {
        ReportUnsafe(parent, DEAD_VAR_MSG);
      }
      return ExprEffect::RawUse();
    }
    return ExprEffect::None();
  }

  ExprEffect Use(const clang::Expr* parent,
                 const clang::ValueDecl* var,
                 const Environment& env) {
    if (IsExternalVMState(var)) {
      return ExprEffect::GC();
    }
    return Use(parent, var->getType(), var->getNameAsString(), env);
  }

  template<typename ExprType>
  ExprEffect VisitArguments(ExprType* call, const Environment& env) {
    CallProps props;
    VisitArguments<>(call, &props, env);
    if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG);
    return props.ComputeCumulativeEffect(
        RepresentsRawPointerType(call->getType()));
  }

  template<typename ExprType>
  void VisitArguments(ExprType* call,
                      CallProps* props,
                      const Environment& env) {
    for (unsigned arg = 0; arg < call->getNumArgs(); arg++) {
      props->SetEffect(arg + 1, VisitExpr(call->getArg(arg), env));
    }
  }

  // After visiting the receiver and the arguments of the {call} node, this
  // function might report a GC-unsafe usage (due to the undefined evaluation
  // order of the receiver and the rest of the arguments).
  ExprEffect VisitCallExpr(clang::CallExpr* call,
                           const Environment& env) {
    CallProps props;

    clang::CXXMemberCallExpr* memcall =
        llvm::dyn_cast_or_null<clang::CXXMemberCallExpr>(call);
    if (memcall != NULL) {
      clang::Expr* receiver = memcall->getImplicitObjectArgument();
      props.SetEffect(0, VisitExpr(receiver, env));
    }

    std::string var_name;
    clang::CXXOperatorCallExpr* opcall =
        llvm::dyn_cast_or_null<clang::CXXOperatorCallExpr>(call);
    if (opcall != NULL && opcall->isAssignmentOp() &&
        IsRawPointerVar(opcall->getArg(0), &var_name)) {
      // TODO(gcmole): We are treating all assignment operator calls with
      // the left hand side looking like {raw_pointer_var} as safe independent
      // of the concrete assignment operator implementation. This should be
      // changed to be more narrow only if the assignment operator of the base
      // {Object} or {HeapObject} class was used, which we know to be safe.
      props.SetEffect(1, VisitExpr(call->getArg(1), env).Define(var_name));
    } else {
      VisitArguments<>(call, &props, env);
    }

    if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG);

    ExprEffect out = props.ComputeCumulativeEffect(
        RepresentsRawPointerType(call->getType()));

    clang::FunctionDecl* callee = call->getDirectCallee();
    if (callee != NULL) {
      if (KnownToCauseGC(ctx_, callee)) {
        out.setGC();
        scopes_.back().SetGCCauseLocation(
            clang::FullSourceLoc(call->getExprLoc(), sm_));
      }

      // Support for virtual methods that might be GC suspects.
      clang::CXXMethodDecl* method =
          llvm::dyn_cast_or_null<clang::CXXMethodDecl>(callee);
      if (method != NULL && method->isVirtual()) {
        clang::CXXMemberCallExpr* memcall =
            llvm::dyn_cast_or_null<clang::CXXMemberCallExpr>(call);
        if (memcall != NULL) {
          clang::CXXMethodDecl* target = method->getDevirtualizedMethod(
              memcall->getImplicitObjectArgument(), false);
          if (target != NULL) {
            if (KnownToCauseGC(ctx_, target)) {
              out.setGC();
              scopes_.back().SetGCCauseLocation(
                  clang::FullSourceLoc(call->getExprLoc(), sm_));
            }
          } else {
            // According to the documentation, {getDevirtualizedMethod} might
            // return NULL, in which case we still want to use the partial
            // match of the {method}'s name against the GC suspects in order
            // to increase coverage.
            if (SuspectedToCauseGC(ctx_, method)) {
              out.setGC();
              scopes_.back().SetGCCauseLocation(
                  clang::FullSourceLoc(call->getExprLoc(), sm_));
            }
          }
        }
      }
    }

    return out;
  }

  // --------------------------------------------------------------------------
  // Statements
  // --------------------------------------------------------------------------

  Environment VisitStmt(clang::Stmt* stmt, const Environment& env) {
#define VISIT(type)                                                         \
  do {                                                                      \
    clang::type* concrete_stmt = llvm::dyn_cast_or_null<clang::type>(stmt); \
    if (concrete_stmt != NULL) {                                            \
      return Visit##type(concrete_stmt, env);                               \
    }                                                                       \
  } while (0);

    if (clang::Expr* expr = llvm::dyn_cast_or_null<clang::Expr>(stmt)) {
      return env.ApplyEffect(VisitExpr(expr, env));
    }

    VISIT(AsmStmt);
    VISIT(BreakStmt);
    VISIT(CompoundStmt);
    VISIT(ContinueStmt);
    VISIT(CXXCatchStmt);
    VISIT(CXXTryStmt);
    VISIT(DeclStmt);
    VISIT(DoStmt);
    VISIT(ForStmt);
    VISIT(GotoStmt);
    VISIT(IfStmt);
    VISIT(IndirectGotoStmt);
    VISIT(LabelStmt);
    VISIT(NullStmt);
    VISIT(ReturnStmt);
    VISIT(CaseStmt);
    VISIT(DefaultStmt);
    VISIT(SwitchStmt);
    VISIT(WhileStmt);
#undef VISIT

    return env;
  }

#define DECL_VISIT_STMT(type)                                           \
  Environment Visit##type (clang::type* stmt, const Environment& env)

#define IGNORE_STMT(type)                                               \
  Environment Visit##type (clang::type* stmt, const Environment& env) { \
    return env;                                                         \
  }

  IGNORE_STMT(IndirectGotoStmt);
  IGNORE_STMT(NullStmt);
  IGNORE_STMT(AsmStmt);

  // We are ignoring control flow for simplicity.
  IGNORE_STMT(GotoStmt);
  IGNORE_STMT(LabelStmt);

  // We are ignoring try/catch because V8 does not use them.
  IGNORE_STMT(CXXCatchStmt);
  IGNORE_STMT(CXXTryStmt);

  class Block {
   public:
    Block(const Environment& in,
          FunctionAnalyzer* owner)
        : in_(in),
          out_(Environment::Unreachable()),
          changed_(false),
          owner_(owner) {
      parent_ = owner_->EnterBlock(this);
    }

    ~Block() {
      owner_->LeaveBlock(parent_);
    }

    void MergeIn(const Environment& env) {
      Environment old_in = in_;
      in_ = Environment::Merge(in_, env);
      changed_ = !old_in.Equal(in_);
    }

    bool changed() {
      if (changed_) {
        changed_ = false;
        return true;
      }
      return false;
    }

    const Environment& in() {
      return in_;
    }

    const Environment& out() {
      return out_;
    }

    void MergeOut(const Environment& env) {
      out_ = Environment::Merge(out_, env);
    }

    void Sequential(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) {
      Environment a_out = owner_->VisitStmt(a, in());
      Environment b_out = owner_->VisitStmt(b, a_out);
      Environment c_out = owner_->VisitStmt(c, b_out);
      MergeOut(c_out);
    }

    void Sequential(clang::Stmt* a, clang::Stmt* b) {
      Environment a_out = owner_->VisitStmt(a, in());
      Environment b_out = owner_->VisitStmt(b, a_out);
      MergeOut(b_out);
    }

    void Loop(clang::Stmt* a, clang::Stmt* b, clang::Stmt* c) {
      Sequential(a, b, c);
      MergeIn(out());
    }

    void Loop(clang::Stmt* a, clang::Stmt* b) {
      Sequential(a, b);
      MergeIn(out());
    }

   private:
    Environment in_;
    Environment out_;
    bool changed_;
    FunctionAnalyzer* owner_;
    Block* parent_;
  };

  DECL_VISIT_STMT(BreakStmt) {
    block_->MergeOut(env);
    return Environment::Unreachable();
  }

  DECL_VISIT_STMT(ContinueStmt) {
    block_->MergeIn(env);
    return Environment::Unreachable();
  }

  DECL_VISIT_STMT(CompoundStmt) {
    scopes_.push_back(GCScope());
    Environment out = env;
    clang::CompoundStmt::body_iterator end = stmt->body_end();
    for (clang::CompoundStmt::body_iterator s = stmt->body_begin();
         s != end;
         ++s) {
      out = VisitStmt(*s, out);
    }
    scopes_.pop_back();
    return out;
  }

  DECL_VISIT_STMT(WhileStmt) {
    Block block (env, this);
    do {
      block.Loop(stmt->getCond(), stmt->getBody());
    } while (block.changed());
    return block.out();
  }

  DECL_VISIT_STMT(DoStmt) {
    Block block (env, this);
    do {
      block.Loop(stmt->getBody(), stmt->getCond());
    } while (block.changed());
    return block.out();
  }

  DECL_VISIT_STMT(ForStmt) {
    Block block (VisitStmt(stmt->getInit(), env), this);
    do {
      block.Loop(stmt->getCond(),
                 stmt->getBody(),
                 stmt->getInc());
    } while (block.changed());
    return block.out();
  }

  DECL_VISIT_STMT(IfStmt) {
    Environment cond_out = VisitStmt(stmt->getCond(), env);
    Environment then_out = VisitStmt(stmt->getThen(), cond_out);
    Environment else_out = VisitStmt(stmt->getElse(), cond_out);
    return Environment::Merge(then_out, else_out);
  }

  DECL_VISIT_STMT(SwitchStmt) {
    Block block (env, this);
    block.Sequential(stmt->getCond(), stmt->getBody());
    return block.out();
  }

  DECL_VISIT_STMT(CaseStmt) {
    Environment in = Environment::Merge(env, block_->in());
    Environment after_lhs = VisitStmt(stmt->getLHS(), in);
    return VisitStmt(stmt->getSubStmt(), after_lhs);
  }

  DECL_VISIT_STMT(DefaultStmt) {
    Environment in = Environment::Merge(env, block_->in());
    return VisitStmt(stmt->getSubStmt(), in);
  }

  DECL_VISIT_STMT(ReturnStmt) {
    VisitExpr(stmt->getRetValue(), env);
    return Environment::Unreachable();
  }

  const clang::TagType* ToTagType(const clang::Type* t) {
    if (t == NULL) {
      return NULL;
    } else if (llvm::isa<clang::TagType>(t)) {
      return llvm::cast<clang::TagType>(t);
    } else if (llvm::isa<clang::SubstTemplateTypeParmType>(t)) {
      return ToTagType(llvm::cast<clang::SubstTemplateTypeParmType>(t)
                           ->getReplacementType()
                           .getTypePtr());
    } else {
      return NULL;
    }
  }

  bool IsDerivedFrom(const clang::CXXRecordDecl* record,
                     const clang::CXXRecordDecl* base) {
    return (record == base) || record->isDerivedFrom(base);
  }

  const clang::CXXRecordDecl* GetDefinitionOrNull(
      const clang::CXXRecordDecl* record) {
    if (record == NULL) {
      return NULL;
    }

    if (!InV8Namespace(record)) return NULL;

    if (!record->hasDefinition()) {
      return NULL;
    }

    return record->getDefinition();
  }

  bool IsDerivedFromInternalPointer(const clang::CXXRecordDecl* record) {
    const clang::CXXRecordDecl* definition = GetDefinitionOrNull(record);
    if (!definition) {
      return false;
    }

    bool result = (IsDerivedFrom(record, object_decl_) &&
                   !IsDerivedFrom(record, smi_decl_)) ||
                  IsDerivedFrom(record, maybe_object_decl_);
    return result;
  }

  bool IsRawPointerType(const clang::PointerType* type) {
    const clang::CXXRecordDecl* record = type->getPointeeCXXRecordDecl();
    bool result = IsDerivedFromInternalPointer(record);
    TRACE("is raw " << result << " " << record->getNameAsString());
    return result;
  }

  bool IsInternalPointerType(clang::QualType qtype) {
    const clang::CXXRecordDecl* record = qtype->getAsCXXRecordDecl();
    bool result = IsDerivedFromInternalPointer(record);
    TRACE_LLVM_TYPE("is internal " << result, qtype);
    return result;
  }

  // Returns weather the given type is a raw pointer or a wrapper around
  // such. For V8 that means Object and MaybeObject instances.
  bool RepresentsRawPointerType(clang::QualType qtype) {
    // Not yet assigned pointers can't get moved by the GC.
    if (qtype.isNull()) {
      return false;
    }
    // nullptr can't get moved by the GC.
    if (qtype->isNullPtrType()) {
      return false;
    }

    const clang::PointerType* pointer_type =
        llvm::dyn_cast_or_null<clang::PointerType>(qtype.getTypePtrOrNull());
    if (pointer_type != NULL) {
      return IsRawPointerType(pointer_type);
    } else {
      return IsInternalPointerType(qtype);
    }
  }

  bool IsGCGuard(clang::QualType qtype) {
    if (qtype.isNull()) {
      return false;
    }
    if (qtype->isNullPtrType()) {
      return false;
    }

    const clang::CXXRecordDecl* record = qtype->getAsCXXRecordDecl();
    const clang::CXXRecordDecl* definition = GetDefinitionOrNull(record);

    if (!definition) {
      return false;
    }

    return (no_gc_decl_ && IsDerivedFrom(definition, no_gc_decl_)) ||
           (no_gc_or_safepoint_decl_ &&
            IsDerivedFrom(definition, no_gc_or_safepoint_decl_)) ||
           (no_heap_access_decl_ &&
            IsDerivedFrom(definition, no_heap_access_decl_));
  }

  Environment VisitDecl(clang::Decl* decl, Environment& env) {
    if (clang::VarDecl* var = llvm::dyn_cast<clang::VarDecl>(decl)) {
      Environment out = var->hasInit() ? VisitStmt(var->getInit(), env) : env;

      if (RepresentsRawPointerType(var->getType())) {
        out = out.Define(var->getNameAsString());
      }
      if (IsGCGuard(var->getType())) {
        scopes_.back().guard_location =
            clang::FullSourceLoc(decl->getLocation(), sm_);
      }

      return out;
    }
    // TODO(gcmole): handle other declarations?
    return env;
  }

  DECL_VISIT_STMT(DeclStmt) {
    Environment out = env;
    clang::DeclStmt::decl_iterator end = stmt->decl_end();
    for (clang::DeclStmt::decl_iterator decl = stmt->decl_begin();
         decl != end;
         ++decl) {
      out = VisitDecl(*decl, out);
    }
    return out;
  }

  void DefineParameters(const clang::FunctionDecl* f,
                        Environment* env) {
    env->MDefine(THIS);
    clang::FunctionDecl::param_const_iterator end = f->param_end();
    for (clang::FunctionDecl::param_const_iterator p = f->param_begin();
         p != end;
         ++p) {
      env->MDefine((*p)->getNameAsString());
    }
  }

  void AnalyzeFunction(const clang::FunctionDecl* f) {
    const clang::FunctionDecl* body = NULL;
    if (f->hasBody(body)) {
      Environment env;
      DefineParameters(body, &env);
      VisitStmt(body->getBody(), env);
      Environment::ClearSymbolTable();
    }
  }

  Block* EnterBlock(Block* block) {
    Block* parent = block_;
    block_ = block;
    return parent;
  }

  void LeaveBlock(Block* block) {
    block_ = block;
  }

  bool HasActiveGuard() {
    for (auto s : scopes_) {
      if (s.IsBeforeGCCause()) return true;
    }
    return false;
  }

 private:
  void ReportUnsafe(const clang::Expr* expr, const std::string& msg) {
    d_.Report(clang::FullSourceLoc(expr->getExprLoc(), sm_),
              d_.getCustomDiagID(clang::DiagnosticsEngine::Warning, "%0"))
        << msg;
  }

  clang::MangleContext* ctx_;
  clang::CXXRecordDecl* object_decl_;
  clang::CXXRecordDecl* maybe_object_decl_;
  clang::CXXRecordDecl* smi_decl_;
  clang::CXXRecordDecl* no_gc_decl_;
  clang::CXXRecordDecl* no_gc_or_safepoint_decl_;
  clang::CXXRecordDecl* no_heap_access_decl_;

  clang::DiagnosticsEngine& d_;
  clang::SourceManager& sm_;

  Block* block_;

  struct GCScope {
    clang::FullSourceLoc guard_location;
    clang::FullSourceLoc gccause_location;

    // We're only interested in guards that are declared before any further GC
    // causing calls (see TestGuardedDeadVarAnalysisMidFunction for example).
    bool IsBeforeGCCause() {
      if (!guard_location.isValid()) return false;
      if (!gccause_location.isValid()) return true;
      return guard_location.isBeforeInTranslationUnitThan(gccause_location);
    }

    // After we set the first GC cause in the scope, we don't need the later
    // ones.
    void SetGCCauseLocation(clang::FullSourceLoc gccause_location_) {
      if (gccause_location.isValid()) return;
      gccause_location = gccause_location_;
    }
  };
  std::vector<GCScope> scopes_;
};

class ProblemsFinder : public clang::ASTConsumer,
                       public clang::RecursiveASTVisitor<ProblemsFinder> {
 public:
  ProblemsFinder(clang::DiagnosticsEngine& d, clang::SourceManager& sm,
                 const std::vector<std::string>& args)
      : d_(d), sm_(sm) {
    for (unsigned i = 0; i < args.size(); ++i) {
      if (args[i] == "--dead-vars") {
        g_dead_vars_analysis = true;
      }
      if (args[i] == "--verbose") {
        g_tracing_enabled = true;
      }
    }
  }

  bool TranslationUnitIgnored() {
    if (!ignored_files_loaded_) {
      std::ifstream fin("tools/gcmole/ignored_files");
      std::string s;
      while (fin >> s) ignored_files_.insert(s);
      ignored_files_loaded_ = true;
    }

    clang::FileID main_file_id = sm_.getMainFileID();
    std::string filename = sm_.getFileEntryForID(main_file_id)->getName().str();

    bool result = ignored_files_.find(filename) != ignored_files_.end();
    if (result) {
      llvm::outs() << "Ignoring file " << filename << "\n";
    }
    return result;
  }

  virtual void HandleTranslationUnit(clang::ASTContext &ctx) {
    if (TranslationUnitIgnored()) {
      return;
    }

    Resolver r(ctx);

    // It is a valid situation that no_gc_decl == NULL when the
    // DisallowHeapAllocation is not included and can't be resolved.
    // This is gracefully handled in the FunctionAnalyzer later.
    clang::CXXRecordDecl* no_gc_decl =
        r.ResolveNamespace("v8")
            .ResolveNamespace("internal")
            .ResolveTemplate("DisallowHeapAllocation");

    clang::CXXRecordDecl* no_gc_or_safepoint_decl =
        r.ResolveNamespace("v8")
            .ResolveNamespace("internal")
            .ResolveTemplate("DisallowGarbageCollection");

    clang::CXXRecordDecl* no_heap_access_decl =
        r.ResolveNamespace("v8")
            .ResolveNamespace("internal")
            .Resolve<clang::CXXRecordDecl>("DisallowHeapAccess");

    clang::CXXRecordDecl* object_decl =
        r.ResolveNamespace("v8").ResolveNamespace("internal").
            Resolve<clang::CXXRecordDecl>("Object");

    clang::CXXRecordDecl* maybe_object_decl =
        r.ResolveNamespace("v8")
            .ResolveNamespace("internal")
            .Resolve<clang::CXXRecordDecl>("MaybeObject");

    clang::CXXRecordDecl* smi_decl =
        r.ResolveNamespace("v8").ResolveNamespace("internal").
            Resolve<clang::CXXRecordDecl>("Smi");

    if (object_decl != NULL) object_decl = object_decl->getDefinition();

    if (maybe_object_decl != NULL)
      maybe_object_decl = maybe_object_decl->getDefinition();

    if (smi_decl != NULL) smi_decl = smi_decl->getDefinition();

    if (no_heap_access_decl != NULL)
      no_heap_access_decl = no_heap_access_decl->getDefinition();

    if (object_decl != NULL && smi_decl != NULL && maybe_object_decl != NULL) {
      function_analyzer_ = new FunctionAnalyzer(
          clang::ItaniumMangleContext::create(ctx, d_), object_decl,
          maybe_object_decl, smi_decl, no_gc_decl, no_gc_or_safepoint_decl,
          no_heap_access_decl, d_, sm_);
      TraverseDecl(ctx.getTranslationUnitDecl());
    } else {
      if (object_decl == NULL) {
        llvm::errs() << "Failed to resolve v8::internal::Object\n";
      }
      if (maybe_object_decl == NULL) {
        llvm::errs() << "Failed to resolve v8::internal::MaybeObject\n";
      }
      if (smi_decl == NULL) {
        llvm::errs() << "Failed to resolve v8::internal::Smi\n";
      }
    }
  }

  virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) {
    // Don't print tracing from includes, otherwise the output is too big.
    bool tracing = g_tracing_enabled;
    const auto& fileID = sm_.getFileID(decl->getLocation());
    if (fileID != sm_.getMainFileID()) {
      g_tracing_enabled = false;
    }

    TRACE("Visiting function " << decl->getNameAsString());
    function_analyzer_->AnalyzeFunction(decl);

    g_tracing_enabled = tracing;
    return true;
  }

 private:
  clang::DiagnosticsEngine& d_;
  clang::SourceManager& sm_;

  bool ignored_files_loaded_ = false;
  std::set<std::string> ignored_files_;

  FunctionAnalyzer* function_analyzer_;
};

template<typename ConsumerType>
class Action : public clang::PluginASTAction {
 protected:
  virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
      clang::CompilerInstance& CI, llvm::StringRef InFile) {
    return std::unique_ptr<clang::ASTConsumer>(
        new ConsumerType(CI.getDiagnostics(), CI.getSourceManager(), args_));
  }

  bool ParseArgs(const clang::CompilerInstance &CI,
                 const std::vector<std::string>& args) {
    args_ = args;
    return true;
  }

  void PrintHelp(llvm::raw_ostream& ros) {
  }
 private:
  std::vector<std::string> args_;
};

}

static clang::FrontendPluginRegistry::Add<Action<ProblemsFinder> >
FindProblems("find-problems", "Find GC-unsafe places.");

static clang::FrontendPluginRegistry::Add<
  Action<FunctionDeclarationFinder> >
DumpCallees("dump-callees", "Dump callees for each function.");

#undef TRACE
#undef TRACE_LLVM_TYPE
#undef TRACE_LLVM_DECL
#undef DECL_VISIT_EXPR
#undef IGNORE_EXPR
#undef DECL_VISIT_STMT
#undef IGNORE_STMT


text:
/* ====================================== *\

 CHARTIST Statistiken
 http://gionkunz.github.io/chartist-js/

 \* ====================================== */
var ChartHelper = function () {
    this.$chart = jQuery('[data-js-chart="chartist"]');
    this.$stats = jQuery('[data-js-chart="stats"]');
};

ChartHelper.prototype.init = function () {
    var _this = this;

    if (this.$stats.length > 0) {
        this.appendGlobalStats();
    }

    if (this.$chart.length > 0) {
        jQuery.each(this.$chart, function (k, elem) {
            _this.appendChartist(elem);
        });
    }
};

/**
 *
 * Append Global Statistics
 * Player | Games | Goals
 */
ChartHelper.prototype.appendGlobalStats = function () {
    var _this = this;

    $.ajax({
        url: 'https://www.kickerligakoeln.de/wp-kkl/statistik.php?q=globalStats',
        dataType: 'json',
        success: function (response) {
            console.log(response);
            var stats = response;
            stats['player'] = {
                all: 741,
                m: 646,
                w: 95
            };
            stats['teams'] = {
                all: 62
            };

            jQuery.get(bloginfo.template_url + "/inc/templates/stats-global.html", function (response) {
                _this.$stats.html(Mark.up(response, stats));
            }, "html");
        }
    });
};

/**
 *
 * Append Chart by Chartist
 * @param elem
 */
ChartHelper.prototype.appendChartist = function (elem) {
    var endpoint = jQuery(elem).attr('data-point');
    var $elem = jQuery(elem).attr('id');

    jQuery.ajax({
        url: 'https://www.kickerligakoeln.de/wp-kkl/statistik.php?q=' + endpoint,
        dataType: 'json',
        success: function (response) {

            var series = [];
            jQuery.each(response, function (k, value) {
                series.push(value);
            });

            var data = {
                labels: ['10:10', '11:9', '12:8', '13:7', '14:6', '15:5', '16:4', '17:3', '18:2', '19:1', '20:0'],
                series: [series]
            };

            new Chartist.Bar('#' + $elem, data, {seriesBarDistance: 10}, [
                ['screen and (max-width: 640px)', {
                    seriesBarDistance: 5,
                    axisX: {
                        labelInterpolationFnc: function (value) {
                            return value[0];
                        }
                    }
                }]
            ]);
        }
    });

};

redpajama_set_name: RedPajamaGithub


text:
using NEasyMessaging.Contracts.Messaging;

namespace NEasyMessaging.Contracts.WebApi.Providers
{
    public interface IApiMessageMutator : IWebApiContract
    {
        void Mutate(ApiCommandEnvelope apiCommandEnvelope, IMessage message);
    }
}


text:
pc.extend(pc, function () {
    'use strict';

    /**
    * @name pc.ResourceLoader
    * @class Load resource data, potentially from remote sources. Caches resource on load to prevent multiple requests
    * Add ResourceHandlers to handle different types of resources
    */
    var ResourceLoader = function () {
        this._handlers = {};
        this._requests = {};
        this._cache = {};
    };

    ResourceLoader.prototype = {
        /**
        * @function
        * @name pc.ResourceLoader#addHandler
        * @description Add a handler for a resource type. Handler should support: load(url, callback) and open(url, data).
        * Handlers can optionally support patch(asset, assets) to handle dependencies on other assets
        * @param {String} type The name of the type that the handler will load
        * @param {pc.ResourceHandler} handler An instance of a resource handler supporting load() and open().
        * @example
        * var loader = new ResourceLoader();
        * loader.addHandler("json", new pc.JsonHandler());
        */
        addHandler: function (type, handler) {
            this._handlers[type] = handler;
        },

        removeHandler: function (type) {
            delete this._handlers[type];
        },

        getHandler: function (type) {
            return this._handlers[type];
        },

        /**
        * @function
        * @name pc.ResourceLoader#load
        * @description Make a request for a resource from a remote URL. Parse the returned data using the handler for the specified type
        * When loaded and parsed use the callback to return an instance of the resource. Handles multiple requests for
        * @param {String} url The URL of the resource to load
        * @param {String} type The type of resource expected
        * @param {Function} callback The callback used when the resource is loaded or an error occurs. Passed (err, resource) where err is null if there are no errors
        * @example
        * app.loader.load("../path/to/texture.png", "texture", function (err, texture) {
        *     // use texture here
        * });
        */
        load: function(url, type, callback) {
            var handler = this._handlers[type];
            if (!handler) {
                var err = "No handler for asset type: " + type;
                callback(err);
                return;
            }

            var key = url + type;

            if (this._cache[key] !== undefined) {
                // in cache
                callback(null, this._cache[key]);
            } else if (this._requests[key]) {
                // existing request
                this._requests[key].push(callback);
            } else {
                // new request
                this._requests[key] = [callback];
                handler.load(url, function (err, data) {
                    // make sure key exists because loader
                    // might have been destroyed by now
                    if (!this._requests[key])
                        return;

                    var i, len = this._requests[key].length;
                    if (!err) {
                        var resource = handler.open(url, data);
                        this._cache[key] = resource;
                        for(var i = 0; i < len; i++)
                            this._requests[key][i](null, resource);
                    } else {
                        for(var i = 0; i < len; i++)
                            this._requests[key][i](err);
                    }
                    delete this._requests[key];
                }.bind(this));
            }
        },

        /**
        * @function
        * @name pc.ResourceLoader#open
        * @description Convert raw resource data into a resource instance. e.g. take 3D model format JSON and return a pc.Model.
        */
        open: function (type, data) {
            var handler = this._handlers[type];
            return handler.open(null, data);
        },

        /**
        * @function
        * @name pc.ResourceLoader#patch
        * @description Perform any operations on a resource, that requires a dependency on it's asset data or any other asset data
        */
        patch: function (asset, assets) {
            var handler = this._handlers[asset.type];
            if (handler.patch) {
                handler.patch(asset, assets);
            }
        },

        clearCache: function (url, type) {
            delete this._cache[url + type];
        },

        /**
        * @function
        * @name pc.ResourceLoader#getFromCache
        * @description Check cache for resource from a URL. If present return the cached value
        */
        getFromCache: function (url, type) {
            if (this._cache[url + type]) {
                return this._cache[url + type];
            }
        },

        /**
        * @function
        * @name  pc.ResourceLoader#destroy
        * @description Destroys resource loader
        */
        destroy: function () {
            this._handlers = {};
            this._requests = {};
            this._cache = {};
        }
    };

    return {
        ResourceLoader: ResourceLoader
    }
}());


text:
package com.intellij.ide.plugins;

import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.project.DumbAware;
import com.intellij.util.net.IOExceptionDialog;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created by IntelliJ IDEA.
 * User: lloix
 * Date: May 24, 2006
 * Time: 2:47:54 PM
 * To change this template use File | Settings | File Templates.
 */
public class ActionInstallPlugin extends AnAction implements DumbAware {
  final private static String updateMessage = IdeBundle.message("action.update.plugin");

  private final PluginManagerMain host;

  public ActionInstallPlugin(PluginManagerMain mgr) {
    super(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("action.download.and.install.plugin"), IconLoader.getIcon("/actions/install.png"));
    host = mgr;
  }

  public void update(AnActionEvent e) {
    Presentation presentation = e.getPresentation();
    IdeaPluginDescriptor[] selection = getPluginTable().getSelectedObjects();
    boolean enabled = (selection != null);

    if (enabled) {
      for (IdeaPluginDescriptor descr : selection) {
        presentation.setText(IdeBundle.message("action.download.and.install.plugin"));
        presentation.setDescription(IdeBundle.message("action.download.and.install.plugin"));
        if (descr instanceof PluginNode) {
          int status = PluginManagerColumnInfo.getRealNodeState((PluginNode)descr);
          enabled &= status != PluginNode.STATUS_DOWNLOADED;
          if (((PluginNode)descr).getStatus() == PluginNode.STATUS_INSTALLED) {
            presentation.setText(updateMessage);
            presentation.setDescription(updateMessage);
          }
        }
        else if (descr instanceof IdeaPluginDescriptorImpl) {
          presentation.setText(updateMessage);
          presentation.setDescription(updateMessage);
          PluginId id = descr.getPluginId();
          enabled = enabled && InstalledPluginsTableModel.hasNewerVersion(id);
        }
      }
    }

    presentation.setEnabled(enabled);
  }

  public void actionPerformed(AnActionEvent e) {
    IdeaPluginDescriptor[] selection = getPluginTable().getSelectedObjects();

    if (userConfirm(selection)) {
      ArrayList<PluginNode> list = new ArrayList<PluginNode>();
      for (IdeaPluginDescriptor descr : selection) {
        PluginNode pluginNode = null;
        if (descr instanceof PluginNode) {
          pluginNode = (PluginNode)descr;
        }
        else if (descr instanceof IdeaPluginDescriptorImpl) {
          pluginNode = new PluginNode(descr.getPluginId());
          pluginNode.setName(descr.getName());
          pluginNode.setDepends(Arrays.asList(descr.getDependentPluginIds()));
          pluginNode.setSize("-1");
        }

        if (pluginNode != null) {
          list.add(pluginNode);
        }
      }
      try {
        if (PluginManagerMain.downloadPlugins(list)) {
          host.getInstalledPluginsModel().modifyData(new ArrayList<IdeaPluginDescriptor>(list));
          host.setRequireShutdown(true);
        }
      }
      catch (IOException e1) {
        PluginManagerMain.LOG.error(e1);
        IOExceptionDialog.showErrorDialog(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("error.plugin.download.failed"));
      }
      getPluginTable().updateUI();
    }
  }

  public PluginTable getPluginTable() {
    return host.getPluginTable();
  }//---------------------------------------------------------------------------
  //  Show confirmation message depending on the amount and type of the
  //  selected plugin descriptors: already downloaded plugins need "update"
  //  while non-installed yet need "install".
  //---------------------------------------------------------------------------
  private boolean userConfirm(IdeaPluginDescriptor[] selection) {
    String message;
    if (selection.length == 1) {
      if (selection[0] instanceof IdeaPluginDescriptorImpl) {
        message = IdeBundle.message("prompt.update.plugin", selection[0].getName());
      }
      else {
        message = IdeBundle.message("prompt.download.and.install.plugin", selection[0].getName());
      }
    }
    else {
      message = IdeBundle.message("prompt.install.several.plugins", selection.length);
    }

    return Messages.showYesNoDialog(host.getMainPanel(), message, IdeBundle.message("action.download.and.install.plugin"), Messages.getQuestionIcon()) == 0;
  }
}


text:
package quasar.connector.datasource

import slamdata.Predef._

import quasar.api.datasource.DatasourceType
import quasar.api.resource._
import quasar.connector._
import quasar.contrib.cats.monadError

import cats.MonadError
import cats.data.OptionT
import cats.effect.{IO, Resource}
import cats.instances.list._

import scalaz.IMap

object MapBasedDatasourceSpec extends DatasourceSpec[IO, List, ResourcePathType.Physical] {

  implicit val ioMonadResourceErr: MonadError[IO, ResourceError] =
    monadError.facet[IO](ResourceError.throwableP)

  val mapDatasource =
    MapBasedDatasource.pure[Resource[IO, ?], List](
      DatasourceType("pure-test", 1),
      IMap(
        ResourcePath.root() / ResourceName("a") -> 0,
        ResourcePath.root() / ResourceName("a") / ResourceName("b") -> 1,
        ResourcePath.root() / ResourceName("a") / ResourceName("c") -> 2,
        ResourcePath.root() / ResourceName("a") / ResourceName("c") / ResourceName("d") -> 3,
        ResourcePath.root() / ResourceName("d") / ResourceName("e") -> 4,
        ResourcePath.root() / ResourceName("f") -> 5))

  val datasource =
    Resource.pure[IO, Datasource[Resource[IO, ?], List, _, _, ResourcePathType.Physical]](mapDatasource)

  def nonExistentPath: ResourcePath =
    ResourcePath.root() / ResourceName("x") / ResourceName("y")

  def gatherMultiple[A](fga: List[A]): IO[List[A]] =
    IO.pure(fga)

  def assertPrefixedChildPaths(path: ResourcePath, expected: Set[(ResourceName, ResourcePathType)]) =
    OptionT(mapDatasource.prefixedChildPaths(path))
      .getOrElseF(MonadError[Resource[IO, ?], Throwable].raiseError(
        new Exception(s"Failed to list resources under $path")))
      .use(r => IO.pure(r.toSet must_== expected))

  def full(path: ResourcePath): IO[Int] = {
    val loader = mapDatasource.loaders.toList collectFirst {
      case Loader.Batch(BatchLoader.Full(f)) => f
    }

    loader.fold(Resource.pure[IO, Int](-1))(_(path))
      .use(IO.pure(_))
  }

  "evaluation" >> {
    "known resource returns result" >>* {
      full(ResourcePath.root() / ResourceName("d") / ResourceName("e"))
        .map(_ must_=== 4)
    }

    "known prefix errors with 'not a resource'" >>* {
      val pfx = ResourcePath.root() / ResourceName("d")

      MonadError[IO, ResourceError].attempt(full(pfx)).map(_ must beLeft.like {
        case ResourceError.NotAResource(p) => p must equal(pfx)
      })
    }

    "unknown path errors with 'not found'" >>* {
      MonadError[IO, ResourceError].attempt(full(nonExistentPath)).map(_ must beLeft.like {
        case ResourceError.PathNotFound(p) => p must equal(nonExistentPath)
      })
    }

    "children of root is correct" >>* {
      assertPrefixedChildPaths(
        ResourcePath.root(),
        Set(
          ResourceName("a") -> ResourcePathType.prefixResource,
          ResourceName("d") -> ResourcePathType.prefix,
          ResourceName("f") -> ResourcePathType.leafResource))
    }

    "children of non-root is correct" >>* {
      assertPrefixedChildPaths(
        ResourcePath.root() / ResourceName("a"),
        Set(
          ResourceName("b") -> ResourcePathType.leafResource,
          ResourceName("c") -> ResourcePathType.prefixResource))
    }
  }
}


text:
var passport = require('passport');
var logger = require('winston');
var passportLocal = require('passport-local');
/**
 * Confiuration for securing the REST services.
 */
function setup(router) {
    logger.info('Configuring Local authentication strategy');
    var Strategy = passportLocal.Strategy;
    /**
     * Configuring local authentication
     */
    passport.use('local', new Strategy(function (username, password, done) {
        logger.debug('Authenticating user:%s', username);
        console.log(username);
        //TODO: To be changed to authenticate with mongo.
        if (username == 'pavan' && password == 'pavan') {
            var userDetails = {
                username: 'pavan',
                name: 'Pavan Andhukuri'
            };
            done(null, userDetails);
        }
        else {
            done(null, false);
        }
    }));
    /**
     * Function called to serialize the user once login is successful.
     */
    passport.serializeUser(function (user, done) {
        done(null, user);
    });
    /**
     * Function called to deserialize user. This user is appended with every request.
     */
    passport.deserializeUser(function (user, done) {
        done(null, user);
    });
    /**
     * Function to check if the user is logged in.
     */
    function requireLogin(req, res, next) {
        if (req.session.passport.user.username) {
            next();
        }
        else {
            next({ 'status': 'unauthorized' });
        }
    }
    /**
     * Securing all the REST URLs that start with /secure/
     */
    logger.info('Setting up authorization for all URLs starting with /secure');
    router.all('/secure/*', requireLogin, function (req, res, next) {
        next();
    });
    /**
     * Login handler to login the user into the system
     */
    logger.info('Configuring post handler for /login');
    router.post('/login', passport.authenticate('local'), function (req, res) {
        res.json(req.session.passport.user);
    });
    /**
     * Logout handler to clear the session
     */
    logger.info('Configuring get handler for /logout');
    router.get('/logout', function (req, res) {
        logger.debug('Logging out user');
        req.logout();
        res.json({ 'status': 'success' });
    });
    return router;
}
exports.setup = setup;
//# sourceMappingURL=auth.js.map


text:
/**
 * Created by Mihail on 1/6/2017.
 */
import React from 'react'
import { IndexRoute, Route } from 'react-router'
import App from './components/App'
import PhotosPage from './components/PhotosPage'
import VideosPage from './components/VideosPage'

export default (
  <Route path="/" component={App}>
    <IndexRoute component={PhotosPage}/>
    <Route path="videos" component={VideosPage}/>
  </Route>
)


text:
/**
 * Represents a location in a Source.
 */
'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});
exports.getLocation = getLocation;

/**
 * Takes a Source and a UTF-8 character offset, and returns the corresponding
 * line and column as a SourceLocation.
 */

function getLocation(source, position) {
  var line = 1;
  var column = position + 1;
  var lineRegexp = /\r\n|[\n\r\u2028\u2029]/g;
  var match;
  while ((match = lineRegexp.exec(source.body)) && match.index < position) {
    line += 1;
    column = position + 1 - (match.index + match[0].length);
  }
  return { line: line, column: column };
}


text:
package info.smartkit.hairy_batman.domain;

import info.smartkit.hairy_batman.config.GlobalConsts;

/**
 * Foo object entity
 *
 * @author yangboz
 */
public class WxSimpleSubscriber
{

    public WxSimpleSubscriber()
    {

    }

    public WxSimpleSubscriber(Integer id, String code, String agency, String unit, String store, String onSubscribe,
        String subscribeId)
    {
        this.id = id;
        this.code = code;
        this.agency = agency;
        this.unit = unit;
        this.store = store;
        this.onSubscribe = onSubscribe;
        this.subscribeId = subscribeId;
    }

    protected Integer id;// 序号

    public Integer getId()
    {
        return id + GlobalConsts.LINES_SKIP_FOR_HEADER_EXCEL;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    protected String code;// 代码

    public String getCode()
    {
        return code;
    }

    public void setCode(String code)
    {
        this.code = code;
    }

    protected String store;// 店名

    public String getStore()
    {
        return store;
    }

    public void setStore(String store)
    {
        this.store = store;
    }

    protected String subscribeId;// 订阅号名全称,subscribeId VARCHAR(20),

    public String getSubscribeId()
    {
        return subscribeId;
    }

    public void setSubscribeId(String subscribeId)
    {
        this.subscribeId = subscribeId;
    }

    // private String manager;// 区域经理
    //
    // public String getManager()
    // {
    // return manager;
    // }
    //
    // public void setManager(String manager)
    // {
    // this.manager = manager;
    // }

    protected String agency;// 办事处

    public String getAgency()
    {
        return agency;
    }

    public void setAgency(String agency)
    {
        this.agency = agency;
    }

    protected String unit;// 事业部

    public String getUnit()
    {
        return unit;
    }

    public void setUnit(String unit)
    {
        this.unit = unit;
    }

    protected String onSubscribe;// 是否开通订阅号/订阅号类型

    public String getOnSubscribe()
    {
        return onSubscribe;
    }

    public void setOnSubscribe(String onSubscribe)
    {
        this.onSubscribe = onSubscribe;
    }

    @Override
    public String toString()
    {
        return "id: " + id + ", store: " + store + ",agency: " + agency + ",unit: " + unit + ",onSubscribe: "
            + onSubscribe + ",subscribeId: " + subscribeId + ",code: " + code;
    }

    public String[] toStringArray()
    {
        return new String[] {this.getId().toString(), this.getStore(), this.getAgency(), this.getUnit(),
        this.getOnSubscribe(), this.getSubscribeId(), this.getCode()};
    }

}


text:
package command

import (
	"fmt"
	"sort"
	"strings"

	"github.com/iobeam/iobeam/client"
)

type deviceData struct {
	ProjectId  uint64 `json:"project_id"`
	DeviceId   string `json:"device_id,omitempty"`
	DeviceName string `json:"device_name,omitempty"`
	DeviceType string `json:"device_type,omitempty"`
	Created    string `json:"created,omitempty"`
	// Private fields, not marshalled into JSON
	isUpdate bool
}

func (d *deviceData) IsValid() bool {
	if d.isUpdate {
		return len(d.DeviceId) > 0 &&
			(len(d.DeviceName) > 0 || len(d.DeviceType) > 0)
	}
	return d.ProjectId != 0
}

func (d *deviceData) Print() {
	fmt.Println("Device ID  :", d.DeviceId)
	fmt.Println("Device name:", d.DeviceName)
	fmt.Println("Project ID :", d.ProjectId)
	fmt.Println("Type       :", d.DeviceType)
	fmt.Println("Created    :", d.Created)
	fmt.Println()
}

// baseDeviceArgs is a simpler struct for calls that just consist of
// optionally a projectId and either (a) a device id or (b) a device name
type baseDeviceArgs struct {
	projectId uint64
	id        string
	name      string
}

func (d *baseDeviceArgs) IsValid() bool {
	return len(d.id) > 0 || len(d.name) > 0
}

// NewDevicesCommand returns the base 'device' command.
func NewDevicesCommand(ctx *Context) *Command {
	cmd := &Command{
		Name:  "device",
		Usage: "Commands for managing devices.",
		SubCommands: Mux{
			"create": newCreateDeviceCmd(ctx),
			"delete": newDeleteDeviceCmd(ctx),
			"get":    newGetDeviceCmd(ctx),
			"list":   newListDevicesCmd(ctx),
			"update": newUpdateDeviceCmd(ctx),
		},
	}
	cmd.NewFlagSet("iobeam device")

	return cmd
}

func newCreateOrUpdateDeviceCmd(ctx *Context, update bool, name string, action Action) *Command {
	device := deviceData{
		isUpdate: update,
	}

	cmd := &Command{
		Name:    name,
		ApiPath: "/v1/devices",
		Usage:   strings.Title(name) + " device.",
		Data:    &device,
		Action:  action,
	}
	flags := cmd.NewFlagSet("iobeam device " + name)
	var idDesc string
	if update {
		idDesc = "ID of the device to be updated"
	} else {
		idDesc = "Device ID, if omitted a random one will be assigned (must be > 16 chars)"
	}
	flags.StringVar(&device.DeviceId, "id", "", idDesc)
	flags.StringVar(&device.DeviceName, "name", "", "The device name")
	flags.StringVar(&device.DeviceType, "type", "", "The type of device")
	flags.Uint64Var(&device.ProjectId, "projectId", ctx.Profile.ActiveProject, "Project ID associated with the device (if omitted, defaults to active project).")

	return cmd
}

func newCreateDeviceCmd(ctx *Context) *Command {
	return newCreateOrUpdateDeviceCmd(ctx, false, "create", createDevice)
}

func newUpdateDeviceCmd(ctx *Context) *Command {
	return newCreateOrUpdateDeviceCmd(ctx, true, "update", updateDevice)
}

func createDevice(c *Command, ctx *Context) error {
	data := c.Data.(*deviceData)
	_, err := ctx.Client.
		Post(c.ApiPath).
		Expect(201).
		ProjectToken(ctx.Profile, data.ProjectId).
		Body(data).
		ResponseBody(c.Data).
		ResponseBodyHandler(func(body interface{}) error {

		device := body.(*deviceData)
		fmt.Println("New device created.")
		fmt.Printf("Device ID: %v\n", device.DeviceId)
		fmt.Printf("Device Name: %v\n", device.DeviceName)
		fmt.Println()

		return nil
	}).Execute()

	return err
}

func updateDevice(c *Command, ctx *Context) error {

	device := c.Data.(*deviceData)

	rsp, err := ctx.Client.
		Patch(c.ApiPath+"/"+device.DeviceId).
		Expect(200).
		ProjectToken(ctx.Profile, device.ProjectId).
		Body(c.Data).
		Execute()

	if err == nil {
		fmt.Println("Device successfully updated")
	} else if rsp.Http().StatusCode == 204 {
		fmt.Println("Device not modified")
		return nil
	}

	return err
}

func newGetDeviceCmd(ctx *Context) *Command {
	data := new(baseDeviceArgs)

	cmd := &Command{
		Name:    "get",
		ApiPath: "/v1/devices",
		Usage:   "Get device information.",
		Data:    data,
		Action:  getDevice,
	}
	flags := cmd.NewFlagSet("iobeam device get")
	flags.StringVar(&data.id, "id", "", "Device ID to get (this or -name is required)")
	flags.StringVar(&data.name, "name", "", "Device name to get (this or -id is required)")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject,
		"Project ID to get devices from (defaults to active project)")

	return cmd
}

func getDevice(c *Command, ctx *Context) error {
	data := c.Data.(*baseDeviceArgs)
	var req *client.Request
	if len(data.id) > 0 {
		req = ctx.Client.Get(c.ApiPath + "/" + data.id)
	} else {
		req = ctx.Client.Get(c.ApiPath).Param("name", data.name)
	}

	device := new(deviceData)
	_, err := req.Expect(200).
		ProjectToken(ctx.Profile, data.projectId).
		ResponseBody(device).
		ResponseBodyHandler(func(body interface{}) error {
		body.(*deviceData).Print()

		return nil
	}).Execute()

	return err
}

const (
	orderName        = "name"
	orderNameReverse = orderName + "-r"
	orderId          = "id"
	orderIdReverse   = orderId + "-r"
	orderDate        = "date"
	orderDateReverse = orderDate + "-r"
)

var orders = []string{orderName, orderNameReverse, orderId, orderIdReverse,
	orderDate, orderDateReverse}

type listData struct {
	projectId uint64
	order     string
}

func (d *listData) IsValid() bool {
	pidOk := d.projectId > 0
	orderOk := isInList(d.order, orders)
	return pidOk && orderOk
}

func newListDevicesCmd(ctx *Context) *Command {
	data := new(listData)

	cmd := &Command{
		Name:    "list",
		ApiPath: "/v1/devices",
		Usage:   "List devices in a project.",
		Data:    data,
		Action:  listDevices,
	}
	flags := cmd.NewFlagSet("iobeam device list")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject,
		"Project ID to get devices from (if omitted, defaults to active project)")
	flags.StringVar(&data.order, "order", orderDate,
		"Sort order for results. Valid values: date(-r), id(-r), name(-r). Values ending with -r are reverse ordering.")

	return cmd
}

type deviceSort struct {
	items []deviceData
	order string
}

func (a deviceSort) Len() int      { return len(a.items) }
func (a deviceSort) Swap(i, j int) { a.items[i], a.items[j] = a.items[j], a.items[i] }
func (a deviceSort) Less(i, j int) bool {
	switch a.order {
	case orderName:
		return a.items[i].DeviceName < a.items[j].DeviceName
	case orderNameReverse:
		return a.items[j].DeviceName < a.items[i].DeviceName
	case orderId:
		return a.items[i].DeviceId < a.items[j].DeviceId
	case orderIdReverse:
		return a.items[i].DeviceId < a.items[j].DeviceId
	case orderDateReverse:
		return a.items[j].Created < a.items[i].Created
	case orderDate:
		fallthrough
	default:
		return a.items[i].Created < a.items[j].Created
	}
	return false
}

func listDevices(c *Command, ctx *Context) error {
	type deviceList struct {
		Devices []deviceData
	}

	cmdArgs := c.Data.(*listData)
	pid := cmdArgs.projectId

	_, err := ctx.Client.
		Get(c.ApiPath).
		ParamUint64("project_id", pid).
		Expect(200).
		ProjectToken(ctx.Profile, pid).
		ResponseBody(new(deviceList)).
		ResponseBodyHandler(func(body interface{}) error {

		list := body.(*deviceList)

		fmt.Printf("Devices in project %v\n", pid)
		fmt.Println("-----")

		sorted := &deviceSort{items: list.Devices, order: cmdArgs.order}
		sort.Sort(sorted)
		for _, device := range sorted.items {
			device.Print()
		}

		return nil
	}).Execute()

	return err
}

func newDeleteDeviceCmd(ctx *Context) *Command {
	data := new(baseDeviceArgs)

	cmd := &Command{
		Name:    "delete",
		ApiPath: "/v1/devices",
		Usage:   "Delete device.",
		Data:    data,
		Action:  deleteDevice,
	}
	flags := cmd.NewFlagSet("iobeam device delete")
	flags.StringVar(&data.id, "id", "", "The ID of the device to delete (REQUIRED)")
	flags.Uint64Var(&data.projectId, "projectId", ctx.Profile.ActiveProject, "The ID of the project the device belongs to (defaults to active project)")

	return cmd
}

func deleteDevice(c *Command, ctx *Context) error {
	data := c.Data.(*baseDeviceArgs)
	path := c.ApiPath + "/" + data.id
	_, err := ctx.Client.
		Delete(path).
		Expect(204).
		ProjectToken(ctx.Profile, data.projectId).
		Execute()

	if err == nil {
		fmt.Println("Device successfully deleted")
	}

	return err
}


text:
var config = require('app.config'),
    _ = require('underscore');

apiService.$inject = ['$http', '$q', '$timeout', '$httpParamSerializer'];
function apiService($http, $q, $timeout, $httpParamSerializer) {
    var self = this;

    self.fake = function(stub){
        var deffered = $q.defer();

        $timeout(function(){
            deffered.resolve(stub)
        }, 500);

        return deffered.promise;
    };

    var articles = [
        { id: 1, title: 'Article 1', text: 'Article 1 text' },
        { id: 2, title: 'Article 2', text: 'Article 2 text' },
        { id: 3, title: 'Article 3', text: 'Article 3 text' }
    ];

    self.getArticles = function(){
        return self.fake(articles)
    }

    self.getArticle = function(id){
        var article = _.find(articles, function(article){ return article.id == id })
        return self.fake(article);
    }

    self.search = function(query, operator){

        var result;

        if( !query || query.trim().length == 0 ){
            result = articles;
        } else {
            var words = query.replace(/\s+/g, ' ').trim().split(' ');
            result = _.filter(articles, function(article){

                var foundWords = _.filter(words, function(word){
                    return article.text.indexOf(word) != -1;
                });

                return foundWords.length == words.length && operator == 'and' || foundWords.length != 0 && operator == 'or';
            })

        }

        return self.fake(result);
    };

	self.getCrosses = function (options) {
		var data = $http({
			url: makeApiGetUrl(options),
			method: "JSONP",
			responseType: "json"
		});

		return data;
	};

	function makeApiGetUrl(options) {
		options.action = options.action || 'search_listings';
		options.encoding = options.encoding || 'json';
		options.country = options.country || 'uk';
		options.page = options.page || '1';
		options.pretty = options.pretty || '1';
		options.callback = options.callback || 'JSON_CALLBACK';

		return 'http://api.nestoria.co.uk/api?' + $httpParamSerializer(options);
	}

}

module.exports = apiService;


text:
<?php

/**
 * Encapsulates methods for application initialization.
 */
class oxStart extends oxUBase
{

    /**
     * Initializes globals and environment vars
     *
     * @return null
     */
    public function appInit()
    {
        $this->pageStart();

        if ('oxstart' == oxRegistry::getConfig()->getRequestParameter('cl') || $this->isAdmin()) {
            return;
        }

        $oSystemEventHandler = $this->_getSystemEventHandler();
        $oSystemEventHandler->onShopStart();
    }

    /**
     * Renders error screen
     *
     * @return string
     */
    public function render()
    {
        parent::render();

        $sErrorNo = oxRegistry::getConfig()->getRequestParameter('execerror');

        $sTemplate = '';

        if ($sErrorNo == 'unknown') {
            $sTemplate = 'message/err_unknown.tpl';
        }

        if ($sTemplate) {
            return $sTemplate;
        } else {
            return 'message/err_unknown.tpl';
        }
    }

    /**
     * Creates and starts session object, sets default currency.
     */
    public function pageStart()
    {
        $myConfig = $this->getConfig();

        $myConfig->setConfigParam('iMaxMandates', $myConfig->getConfigParam('IMS'));
        $myConfig->setConfigParam('iMaxArticles', $myConfig->getConfigParam('IMA'));
    }

    /**
     * Finalizes the script.
     */
    public function pageClose()
    {
        $mySession = $this->getSession();

        if (isset($mySession)) {
            $mySession->freeze();
        }

        //commit file cache
        oxRegistry::getUtils()->commitFileCache();
    }

    /**
     * Return error number
     *
     * @return integer
     */
    public function getErrorNumber()
    {
        return oxRegistry::getConfig()->getRequestParameter('errornr');
    }

    /**
     * Gets system event handler.
     *
     * @return oxSystemEventHandler
     */
    protected function _getSystemEventHandler()
    {
        return oxNew('oxSystemEventHandler');
    }
}


text:
#!/usr/bin/env python3

"""
   Add a C file with matching header to the Tor codebase.  Creates
   both files from templates, and adds them to the right include.am file.

   This script takes paths relative to the top-level tor directory. It
   expects to be run from that directory.

   This script creates files, and inserts them into include.am, also
   relative to the top-level tor directory.

   But the template content in those files is relative to tor's src
   directory. (This script strips "src" from the paths used to create
   templated comments and macros.)

   This script expects posix paths, so it should be run with a python
   where os.path is posixpath. (Rather than ntpath.) This probably means
   Linux, macOS, or BSD, although it might work on Windows if your python
   was compiled with mingw, MSYS, or cygwin.

   Example usage:

   % add_c_file.py ./src/feature/dirauth/ocelot.c
"""

# Future imports for Python 2.7, mandatory in 3.0
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import os
import re
import time

def tordir_file(fname):
    """Make fname relative to the current directory, which should be the
       top-level tor directory. Also performs basic path simplifications."""
    return os.path.normpath(os.path.relpath(fname))

def srcdir_file(tor_fname):
    """Make tor_fname relative to tor's "src" directory.
       Also performs basic path simplifications.
       (This function takes paths relative to the top-level tor directory,
       but outputs a path that is relative to tor's src directory.)"""
    return os.path.normpath(os.path.relpath(tor_fname, 'src'))

def guard_macro(src_fname):
    """Return the guard macro that should be used for the header file
       'src_fname'. This function takes paths relative to tor's src directory.
    """
    td = src_fname.replace(".", "_").replace("/", "_").upper()
    return "TOR_{}".format(td)

def makeext(fname, new_extension):
    """Replace the extension for the file called 'fname' with 'new_extension'.
       This function takes and returns paths relative to either the top-level
       tor directory, or tor's src directory, and returns the same kind
       of path.
    """
    base = os.path.splitext(fname)[0]
    return base + "." + new_extension

def instantiate_template(template, tor_fname):
    """
    Fill in a template with string using the fields that should be used
    for 'tor_fname'.

    This function takes paths relative to the top-level tor directory,
    but the paths in the completed template are relative to tor's src
    directory. (Except for one of the fields, which is just a basename).
    """
    src_fname = srcdir_file(tor_fname)
    names = {
        # The relative location of the header file.
        'header_path' : makeext(src_fname, "h"),
        # The relative location of the C file file.
        'c_file_path' : makeext(src_fname, "c"),
        # The truncated name of the file.
        'short_name' : os.path.basename(src_fname),
        # The current year, for the copyright notice
        'this_year' : time.localtime().tm_year,
        # An appropriate guard macro, for the header.
        'guard_macro' : guard_macro(src_fname),
    }

    return template.format(**names)

# This template operates on paths relative to tor's src directory
HEADER_TEMPLATE = """\

/* See LICENSE for licensing information */

/**
 * @file {short_name}
 * @brief Header for {c_file_path}
 **/

#ifndef {guard_macro}
#define {guard_macro}

#endif /* !defined({guard_macro}) */
"""

# This template operates on paths relative to the tor's src directory
C_FILE_TEMPLATE = """\
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-{this_year}, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * @file {short_name}
 * @brief DOCDOC
 **/

#include "orconfig.h"
#include "{header_path}"
"""

class AutomakeChunk:
    """
    Represents part of an automake file.  If it is decorated with
    an ADD_C_FILE comment, it has a "kind" based on what to add to it.
    Otherwise, it only has a bunch of lines in it.

    This class operates on paths relative to the top-level tor directory.
    """
    pat = re.compile(r'# ADD_C_FILE: INSERT (\S*) HERE', re.I)

    def __init__(self):
        self.lines = []
        self.kind = ""
        self.hasBlank = False # true if we end with a blank line.

    def addLine(self, line):
        """
        Insert a line into this chunk while parsing the automake file.

        Return True if we have just read the last line in the chunk, and
        False otherwise.
        """
        m = self.pat.match(line)
        if m:
            if self.lines:
                raise ValueError("control line not preceded by a blank line")
            self.kind = m.group(1)

        if line.strip() == "":
            self.hasBlank = True
            return True

        self.lines.append(line)

        return False

    def insertMember(self, new_tor_fname):
        """
        Add a new file name new_tor_fname to this chunk.  Try to insert it in
        alphabetical order with matching indentation, but don't freak out too
        much if the source isn't consistent.

        Assumes that this chunk is of the form:
           FOOBAR = \
              X     \
              Y     \
              Z

        This function operates on paths relative to the top-level tor
        directory.
        """
        prespace = "\t"
        postspace = "\t\t"
        for lineno, line in enumerate(self.lines):
            m = re.match(r'(\s+)(\S+)(\s+)\\', line)
            if not m:
                continue
            prespace, cur_tor_fname, postspace = m.groups()
            if cur_tor_fname > new_tor_fname:
                self.insert_before(lineno, new_tor_fname, prespace, postspace)
                return
        self.insert_at_end(new_tor_fname, prespace, postspace)

    def insert_before(self, lineno, new_tor_fname, prespace, postspace):
        self.lines.insert(lineno,
                          "{}{}{}\\\n".format(prespace, new_tor_fname,
                                              postspace))

    def insert_at_end(self, new_tor_fname, prespace, postspace):
        lastline = self.lines[-1].strip()
        self.lines[-1] = '{}{}{}\\\n'.format(prespace, lastline, postspace)
        self.lines.append("{}{}\n".format(prespace, new_tor_fname))

    def dump(self, f):
        """Write all the lines in this chunk to the file 'f'."""
        for line in self.lines:
            f.write(line)
            if not line.endswith("\n"):
                f.write("\n")

        if self.hasBlank:
            f.write("\n")

class ParsedAutomake:
    """A sort-of-parsed automake file, with identified chunks into which
       headers and c files can be inserted.

       This class operates on paths relative to the top-level tor directory.
    """
    def __init__(self):
        self.chunks = []
        self.by_type = {}

    def addChunk(self, chunk):
        """Add a newly parsed AutomakeChunk to this file."""
        self.chunks.append(chunk)
        self.by_type[chunk.kind.lower()] = chunk

    def add_file(self, tor_fname, kind):
        """Insert a file tor_fname of kind 'kind' to the appropriate
           section of this file. Return True if we added it.

           This function operates on paths relative to the top-level tor
           directory.
        """
        if kind.lower() in self.by_type:
            self.by_type[kind.lower()].insertMember(tor_fname)
            return True
        else:
            return False

    def dump(self, f):
        """Write this file into a file 'f'."""
        for chunk in self.chunks:
            chunk.dump(f)

def get_include_am_location(tor_fname):
    """Find the right include.am file for introducing a new file
       tor_fname.  Return None if we can't guess one.

       Note that this function is imperfect because our include.am layout is
       not (yet) consistent.

       This function operates on paths relative to the top-level tor directory.
    """
    # Strip src for pattern matching, but add it back when returning the path
    src_fname = srcdir_file(tor_fname)
    m = re.match(r'^(lib|core|feature|app)/([a-z0-9_]*)/', src_fname)
    if m:
        return "src/{}/{}/include.am".format(m.group(1),m.group(2))

    if re.match(r'^test/', src_fname):
        return "src/test/include.am"

    return None

def run(fname):
    """
    Create a new C file and H file corresponding to the filename "fname",
    and add them to the corresponding include.am.

    This function operates on paths relative to the top-level tor directory.
    """

    # Make sure we're in the top-level tor directory,
    # which contains the src directory
    if not os.path.isdir("src"):
        raise RuntimeError("Could not find './src/'. "
                           "Run this script from the top-level tor source "
                           "directory.")

    # And it looks like a tor/src directory
    if not os.path.isfile("src/include.am"):
        raise RuntimeError("Could not find './src/include.am'. "
                           "Run this script from the top-level tor source "
                           "directory.")

    # Make the file name relative to the top-level tor directory
    tor_fname = tordir_file(fname)
    # And check that we're adding files to the "src" directory,
    # with canonical paths
    if tor_fname[:4] != "src/":
        raise ValueError("Requested file path '{}' canonicalized to '{}', "
                         "but the canonical path did not start with 'src/'. "
                         "Please add files to the src directory."
                         .format(fname, tor_fname))

    c_tor_fname = makeext(tor_fname, "c")
    h_tor_fname = makeext(tor_fname, "h")

    if os.path.exists(c_tor_fname):
        print("{} already exists".format(c_tor_fname))
        return 1
    if os.path.exists(h_tor_fname):
        print("{} already exists".format(h_tor_fname))
        return 1

    with open(c_tor_fname, 'w') as f:
        f.write(instantiate_template(C_FILE_TEMPLATE, c_tor_fname))

    with open(h_tor_fname, 'w') as f:
        f.write(instantiate_template(HEADER_TEMPLATE, h_tor_fname))

    iam = get_include_am_location(c_tor_fname)
    if iam is None or not os.path.exists(iam):
        print("Made files successfully but couldn't identify include.am for {}"
              .format(c_tor_fname))
        return 1

    amfile = ParsedAutomake()
    cur_chunk = AutomakeChunk()
    with open(iam) as f:
        for line in f:
            if cur_chunk.addLine(line):
                amfile.addChunk(cur_chunk)
                cur_chunk = AutomakeChunk()
        amfile.addChunk(cur_chunk)

    amfile.add_file(c_tor_fname, "sources")
    amfile.add_file(h_tor_fname, "headers")

    with open(iam+".tmp", 'w') as f:
        amfile.dump(f)

    os.rename(iam+".tmp", iam)

if __name__ == '__main__':
    import sys
    sys.exit(run(sys.argv[1]))


text: package securitycontextconstraints


text:
/**
 *
 */
package fr.imie;

/**
 * @author imie
 *
 */
public class BoiteDeNuit implements BoiteDeNuitInterface {

	/* (non-Javadoc)
	 * @see fr.imie.BoiteDeNuitInterface#entrer(fr.imie.Client)
	 */
	@Override
	public void entrer(Client client) {
		System.out.println("bienvenue au LC");

	}

}