| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 #include <stack> | 44 #include <stack> |
| 45 | 45 |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 typedef std::string MangledName; | 48 typedef std::string MangledName; |
| 49 typedef std::set<MangledName> CalleesSet; | 49 typedef std::set<MangledName> CalleesSet; |
| 50 | 50 |
| 51 static bool GetMangledName(clang::MangleContext* ctx, | 51 static bool GetMangledName(clang::MangleContext* ctx, |
| 52 const clang::NamedDecl* decl, | 52 const clang::NamedDecl* decl, |
| 53 MangledName* result) { | 53 MangledName* result) { |
| 54 if (!isa<clang::CXXConstructorDecl>(decl) && | 54 if (!llvm::isa<clang::CXXConstructorDecl>(decl) && |
| 55 !isa<clang::CXXDestructorDecl>(decl)) { | 55 !llvm::isa<clang::CXXDestructorDecl>(decl)) { |
| 56 llvm::SmallVector<char, 512> output; | 56 llvm::SmallVector<char, 512> output; |
| 57 llvm::raw_svector_ostream out(output); | 57 llvm::raw_svector_ostream out(output); |
| 58 ctx->mangleName(decl, out); | 58 ctx->mangleName(decl, out); |
| 59 *result = out.str().str(); | 59 *result = out.str().str(); |
| 60 return true; | 60 return true; |
| 61 } | 61 } |
| 62 | 62 |
| 63 return false; | 63 return false; |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 static bool InV8Namespace(const clang::NamedDecl* decl) { | 67 static bool InV8Namespace(const clang::NamedDecl* decl) { |
| 68 return decl->getQualifiedNameAsString().compare(0, 4, "v8::") == 0; | 68 return decl->getQualifiedNameAsString().compare(0, 4, "v8::") == 0; |
| 69 } | 69 } |
| 70 | 70 |
| 71 | 71 |
| 72 static std::string EXTERNAL("EXTERNAL"); | 72 static std::string EXTERNAL("EXTERNAL"); |
| 73 static std::string STATE_TAG("enum v8::internal::StateTag"); | 73 static std::string STATE_TAG("enum v8::internal::StateTag"); |
| 74 | 74 |
| 75 static bool IsExternalVMState(const clang::ValueDecl* var) { | 75 static bool IsExternalVMState(const clang::ValueDecl* var) { |
| 76 const clang::EnumConstantDecl* enum_constant = | 76 const clang::EnumConstantDecl* enum_constant = |
| 77 dyn_cast<clang::EnumConstantDecl>(var); | 77 llvm::dyn_cast<clang::EnumConstantDecl>(var); |
| 78 if (enum_constant != NULL && enum_constant->getNameAsString() == EXTERNAL) { | 78 if (enum_constant != NULL && enum_constant->getNameAsString() == EXTERNAL) { |
| 79 clang::QualType type = enum_constant->getType(); | 79 clang::QualType type = enum_constant->getType(); |
| 80 return (type.getAsString() == STATE_TAG); | 80 return (type.getAsString() == STATE_TAG); |
| 81 } | 81 } |
| 82 | 82 |
| 83 return false; | 83 return false; |
| 84 } | 84 } |
| 85 | 85 |
| 86 | 86 |
| 87 struct Resolver { | 87 struct Resolver { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 102 return Resolver(ctx_, Resolve<clang::NamespaceDecl>(n)); | 102 return Resolver(ctx_, Resolve<clang::NamespaceDecl>(n)); |
| 103 } | 103 } |
| 104 | 104 |
| 105 template<typename T> | 105 template<typename T> |
| 106 T* Resolve(const char* n) { | 106 T* Resolve(const char* n) { |
| 107 if (decl_ctx_ == NULL) return NULL; | 107 if (decl_ctx_ == NULL) return NULL; |
| 108 | 108 |
| 109 clang::DeclContext::lookup_result result = | 109 clang::DeclContext::lookup_result result = |
| 110 decl_ctx_->lookup(ResolveName(n)); | 110 decl_ctx_->lookup(ResolveName(n)); |
| 111 | 111 |
| 112 clang::DeclContext::lookup_iterator end = result.second; | 112 clang::DeclContext::lookup_iterator end = result.end(); |
| 113 for (clang::DeclContext::lookup_iterator i = result.first; | 113 for (clang::DeclContext::lookup_iterator i = result.begin(); i != end; |
| 114 i != end; | |
| 115 i++) { | 114 i++) { |
| 116 if (isa<T>(*i)) return cast<T>(*i); | 115 if (llvm::isa<T>(*i)) return llvm::cast<T>(*i); |
| 117 } | 116 } |
| 118 | 117 |
| 119 return NULL; | 118 return NULL; |
| 120 } | 119 } |
| 121 | 120 |
| 122 private: | 121 private: |
| 123 clang::ASTContext& ctx_; | 122 clang::ASTContext& ctx_; |
| 124 clang::DeclContext* decl_ctx_; | 123 clang::DeclContext* decl_ctx_; |
| 125 }; | 124 }; |
| 126 | 125 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 | 200 |
| 202 std::stack<CalleesSet* > scopes_; | 201 std::stack<CalleesSet* > scopes_; |
| 203 Callgraph callgraph_; | 202 Callgraph callgraph_; |
| 204 }; | 203 }; |
| 205 | 204 |
| 206 | 205 |
| 207 class FunctionDeclarationFinder | 206 class FunctionDeclarationFinder |
| 208 : public clang::ASTConsumer, | 207 : public clang::ASTConsumer, |
| 209 public clang::RecursiveASTVisitor<FunctionDeclarationFinder> { | 208 public clang::RecursiveASTVisitor<FunctionDeclarationFinder> { |
| 210 public: | 209 public: |
| 211 explicit FunctionDeclarationFinder(clang::Diagnostic& d, | 210 explicit FunctionDeclarationFinder(clang::DiagnosticsEngine& d, |
| 212 clang::SourceManager& sm, | 211 clang::SourceManager& sm, |
| 213 const std::vector<std::string>& args) | 212 const std::vector<std::string>& args) |
| 214 : d_(d), sm_(sm) { } | 213 : d_(d), sm_(sm) {} |
| 215 | 214 |
| 216 virtual void HandleTranslationUnit(clang::ASTContext &ctx) { | 215 virtual void HandleTranslationUnit(clang::ASTContext &ctx) { |
| 217 mangle_context_ = clang::createItaniumMangleContext(ctx, d_); | 216 mangle_context_ = clang::ItaniumMangleContext::create(ctx, d_); |
| 218 callees_printer_ = new CalleesPrinter(mangle_context_); | 217 callees_printer_ = new CalleesPrinter(mangle_context_); |
| 219 | 218 |
| 220 TraverseDecl(ctx.getTranslationUnitDecl()); | 219 TraverseDecl(ctx.getTranslationUnitDecl()); |
| 221 | 220 |
| 222 callees_printer_->PrintCallGraph(); | 221 callees_printer_->PrintCallGraph(); |
| 223 } | 222 } |
| 224 | 223 |
| 225 virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) { | 224 virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) { |
| 226 callees_printer_->AnalyzeFunction(decl); | 225 callees_printer_->AnalyzeFunction(decl); |
| 227 return true; | 226 return true; |
| 228 } | 227 } |
| 229 | 228 |
| 230 private: | 229 private: |
| 231 clang::Diagnostic& d_; | 230 clang::DiagnosticsEngine& d_; |
| 232 clang::SourceManager& sm_; | 231 clang::SourceManager& sm_; |
| 233 clang::MangleContext* mangle_context_; | 232 clang::MangleContext* mangle_context_; |
| 234 | 233 |
| 235 CalleesPrinter* callees_printer_; | 234 CalleesPrinter* callees_printer_; |
| 236 }; | 235 }; |
| 237 | 236 |
| 238 | 237 |
| 239 static bool loaded = false; | 238 static bool loaded = false; |
| 240 static CalleesSet gc_suspects; | 239 static CalleesSet gc_suspects; |
| 241 | 240 |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 | 500 |
| 502 | 501 |
| 503 static std::string THIS ("this"); | 502 static std::string THIS ("this"); |
| 504 | 503 |
| 505 | 504 |
| 506 class FunctionAnalyzer { | 505 class FunctionAnalyzer { |
| 507 public: | 506 public: |
| 508 FunctionAnalyzer(clang::MangleContext* ctx, | 507 FunctionAnalyzer(clang::MangleContext* ctx, |
| 509 clang::DeclarationName handle_decl_name, | 508 clang::DeclarationName handle_decl_name, |
| 510 clang::CXXRecordDecl* object_decl, | 509 clang::CXXRecordDecl* object_decl, |
| 511 clang::CXXRecordDecl* smi_decl, | 510 clang::CXXRecordDecl* smi_decl, clang::DiagnosticsEngine& d, |
| 512 clang::Diagnostic& d, | 511 clang::SourceManager& sm, bool dead_vars_analysis) |
| 513 clang::SourceManager& sm, | |
| 514 bool dead_vars_analysis) | |
| 515 : ctx_(ctx), | 512 : ctx_(ctx), |
| 516 handle_decl_name_(handle_decl_name), | 513 handle_decl_name_(handle_decl_name), |
| 517 object_decl_(object_decl), | 514 object_decl_(object_decl), |
| 518 smi_decl_(smi_decl), | 515 smi_decl_(smi_decl), |
| 519 d_(d), | 516 d_(d), |
| 520 sm_(sm), | 517 sm_(sm), |
| 521 block_(NULL), | 518 block_(NULL), |
| 522 dead_vars_analysis_(dead_vars_analysis) { | 519 dead_vars_analysis_(dead_vars_analysis) {} |
| 523 } | |
| 524 | 520 |
| 525 | 521 |
| 526 // -------------------------------------------------------------------------- | 522 // -------------------------------------------------------------------------- |
| 527 // Expressions | 523 // Expressions |
| 528 // -------------------------------------------------------------------------- | 524 // -------------------------------------------------------------------------- |
| 529 | 525 |
| 530 ExprEffect VisitExpr(clang::Expr* expr, const Environment& env) { | 526 ExprEffect VisitExpr(clang::Expr* expr, const Environment& env) { |
| 531 #define VISIT(type) do { \ | 527 #define VISIT(type) \ |
| 532 clang::type* concrete_expr = dyn_cast_or_null<clang::type>(expr); \ | 528 do { \ |
| 533 if (concrete_expr != NULL) { \ | 529 clang::type* concrete_expr = llvm::dyn_cast_or_null<clang::type>(expr); \ |
| 534 return Visit##type (concrete_expr, env); \ | 530 if (concrete_expr != NULL) { \ |
| 535 } \ | 531 return Visit##type(concrete_expr, env); \ |
| 536 } while(0); | 532 } \ |
| 533 } while (0); |
| 537 | 534 |
| 538 VISIT(AbstractConditionalOperator); | 535 VISIT(AbstractConditionalOperator); |
| 539 VISIT(AddrLabelExpr); | 536 VISIT(AddrLabelExpr); |
| 540 VISIT(ArraySubscriptExpr); | 537 VISIT(ArraySubscriptExpr); |
| 541 VISIT(BinaryOperator); | 538 VISIT(BinaryOperator); |
| 542 VISIT(BinaryTypeTraitExpr); | |
| 543 VISIT(BlockDeclRefExpr); | |
| 544 VISIT(BlockExpr); | 539 VISIT(BlockExpr); |
| 545 VISIT(CallExpr); | 540 VISIT(CallExpr); |
| 546 VISIT(CastExpr); | 541 VISIT(CastExpr); |
| 547 VISIT(CharacterLiteral); | 542 VISIT(CharacterLiteral); |
| 548 VISIT(ChooseExpr); | 543 VISIT(ChooseExpr); |
| 549 VISIT(CompoundLiteralExpr); | 544 VISIT(CompoundLiteralExpr); |
| 550 VISIT(CXXBindTemporaryExpr); | 545 VISIT(CXXBindTemporaryExpr); |
| 551 VISIT(CXXBoolLiteralExpr); | 546 VISIT(CXXBoolLiteralExpr); |
| 552 VISIT(CXXConstructExpr); | 547 VISIT(CXXConstructExpr); |
| 553 VISIT(CXXDefaultArgExpr); | 548 VISIT(CXXDefaultArgExpr); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 580 VISIT(OverloadExpr); | 575 VISIT(OverloadExpr); |
| 581 VISIT(PackExpansionExpr); | 576 VISIT(PackExpansionExpr); |
| 582 VISIT(ParenExpr); | 577 VISIT(ParenExpr); |
| 583 VISIT(ParenListExpr); | 578 VISIT(ParenListExpr); |
| 584 VISIT(PredefinedExpr); | 579 VISIT(PredefinedExpr); |
| 585 VISIT(ShuffleVectorExpr); | 580 VISIT(ShuffleVectorExpr); |
| 586 VISIT(SizeOfPackExpr); | 581 VISIT(SizeOfPackExpr); |
| 587 VISIT(StmtExpr); | 582 VISIT(StmtExpr); |
| 588 VISIT(StringLiteral); | 583 VISIT(StringLiteral); |
| 589 VISIT(SubstNonTypeTemplateParmPackExpr); | 584 VISIT(SubstNonTypeTemplateParmPackExpr); |
| 585 VISIT(TypeTraitExpr); |
| 590 VISIT(UnaryOperator); | 586 VISIT(UnaryOperator); |
| 591 VISIT(UnaryTypeTraitExpr); | |
| 592 VISIT(VAArgExpr); | 587 VISIT(VAArgExpr); |
| 593 #undef VISIT | 588 #undef VISIT |
| 594 | 589 |
| 595 return ExprEffect::None(); | 590 return ExprEffect::None(); |
| 596 } | 591 } |
| 597 | 592 |
| 598 #define DECL_VISIT_EXPR(type) \ | 593 #define DECL_VISIT_EXPR(type) \ |
| 599 ExprEffect Visit##type (clang::type* expr, const Environment& env) | 594 ExprEffect Visit##type (clang::type* expr, const Environment& env) |
| 600 | 595 |
| 601 #define IGNORE_EXPR(type) \ | 596 #define IGNORE_EXPR(type) \ |
| 602 ExprEffect Visit##type (clang::type* expr, const Environment& env) { \ | 597 ExprEffect Visit##type (clang::type* expr, const Environment& env) { \ |
| 603 return ExprEffect::None(); \ | 598 return ExprEffect::None(); \ |
| 604 } | 599 } |
| 605 | 600 |
| 606 IGNORE_EXPR(AddrLabelExpr); | 601 IGNORE_EXPR(AddrLabelExpr); |
| 607 IGNORE_EXPR(BinaryTypeTraitExpr); | |
| 608 IGNORE_EXPR(BlockExpr); | 602 IGNORE_EXPR(BlockExpr); |
| 609 IGNORE_EXPR(CharacterLiteral); | 603 IGNORE_EXPR(CharacterLiteral); |
| 610 IGNORE_EXPR(ChooseExpr); | 604 IGNORE_EXPR(ChooseExpr); |
| 611 IGNORE_EXPR(CompoundLiteralExpr); | 605 IGNORE_EXPR(CompoundLiteralExpr); |
| 612 IGNORE_EXPR(CXXBoolLiteralExpr); | 606 IGNORE_EXPR(CXXBoolLiteralExpr); |
| 613 IGNORE_EXPR(CXXDependentScopeMemberExpr); | 607 IGNORE_EXPR(CXXDependentScopeMemberExpr); |
| 614 IGNORE_EXPR(CXXNullPtrLiteralExpr); | 608 IGNORE_EXPR(CXXNullPtrLiteralExpr); |
| 615 IGNORE_EXPR(CXXPseudoDestructorExpr); | 609 IGNORE_EXPR(CXXPseudoDestructorExpr); |
| 616 IGNORE_EXPR(CXXScalarValueInitExpr); | 610 IGNORE_EXPR(CXXScalarValueInitExpr); |
| 617 IGNORE_EXPR(CXXNoexceptExpr); | 611 IGNORE_EXPR(CXXNoexceptExpr); |
| 618 IGNORE_EXPR(CXXTypeidExpr); | 612 IGNORE_EXPR(CXXTypeidExpr); |
| 619 IGNORE_EXPR(CXXUnresolvedConstructExpr); | 613 IGNORE_EXPR(CXXUnresolvedConstructExpr); |
| 620 IGNORE_EXPR(CXXUuidofExpr); | 614 IGNORE_EXPR(CXXUuidofExpr); |
| 621 IGNORE_EXPR(DependentScopeDeclRefExpr); | 615 IGNORE_EXPR(DependentScopeDeclRefExpr); |
| 622 IGNORE_EXPR(DesignatedInitExpr); | 616 IGNORE_EXPR(DesignatedInitExpr); |
| 623 IGNORE_EXPR(ExtVectorElementExpr); | 617 IGNORE_EXPR(ExtVectorElementExpr); |
| 624 IGNORE_EXPR(FloatingLiteral); | 618 IGNORE_EXPR(FloatingLiteral); |
| 625 IGNORE_EXPR(ImaginaryLiteral); | 619 IGNORE_EXPR(ImaginaryLiteral); |
| 626 IGNORE_EXPR(IntegerLiteral); | 620 IGNORE_EXPR(IntegerLiteral); |
| 627 IGNORE_EXPR(OffsetOfExpr); | 621 IGNORE_EXPR(OffsetOfExpr); |
| 628 IGNORE_EXPR(ImplicitValueInitExpr); | 622 IGNORE_EXPR(ImplicitValueInitExpr); |
| 629 IGNORE_EXPR(PackExpansionExpr); | 623 IGNORE_EXPR(PackExpansionExpr); |
| 630 IGNORE_EXPR(PredefinedExpr); | 624 IGNORE_EXPR(PredefinedExpr); |
| 631 IGNORE_EXPR(ShuffleVectorExpr); | 625 IGNORE_EXPR(ShuffleVectorExpr); |
| 632 IGNORE_EXPR(SizeOfPackExpr); | 626 IGNORE_EXPR(SizeOfPackExpr); |
| 633 IGNORE_EXPR(StmtExpr); | 627 IGNORE_EXPR(StmtExpr); |
| 634 IGNORE_EXPR(StringLiteral); | 628 IGNORE_EXPR(StringLiteral); |
| 635 IGNORE_EXPR(SubstNonTypeTemplateParmPackExpr); | 629 IGNORE_EXPR(SubstNonTypeTemplateParmPackExpr); |
| 636 IGNORE_EXPR(UnaryTypeTraitExpr); | 630 IGNORE_EXPR(TypeTraitExpr); |
| 637 IGNORE_EXPR(VAArgExpr); | 631 IGNORE_EXPR(VAArgExpr); |
| 638 IGNORE_EXPR(GNUNullExpr); | 632 IGNORE_EXPR(GNUNullExpr); |
| 639 IGNORE_EXPR(OverloadExpr); | 633 IGNORE_EXPR(OverloadExpr); |
| 640 | 634 |
| 641 DECL_VISIT_EXPR(CXXThisExpr) { | 635 DECL_VISIT_EXPR(CXXThisExpr) { |
| 642 return Use(expr, expr->getType(), THIS, env); | 636 return Use(expr, expr->getType(), THIS, env); |
| 643 } | 637 } |
| 644 | 638 |
| 645 DECL_VISIT_EXPR(AbstractConditionalOperator) { | 639 DECL_VISIT_EXPR(AbstractConditionalOperator) { |
| 646 Environment after_cond = env.ApplyEffect(VisitExpr(expr->getCond(), env)); | 640 Environment after_cond = env.ApplyEffect(VisitExpr(expr->getCond(), env)); |
| 647 return ExprEffect::Merge(VisitExpr(expr->getTrueExpr(), after_cond), | 641 return ExprEffect::Merge(VisitExpr(expr->getTrueExpr(), after_cond), |
| 648 VisitExpr(expr->getFalseExpr(), after_cond)); | 642 VisitExpr(expr->getFalseExpr(), after_cond)); |
| 649 } | 643 } |
| 650 | 644 |
| 651 DECL_VISIT_EXPR(ArraySubscriptExpr) { | 645 DECL_VISIT_EXPR(ArraySubscriptExpr) { |
| 652 clang::Expr* exprs[2] = {expr->getBase(), expr->getIdx()}; | 646 clang::Expr* exprs[2] = {expr->getBase(), expr->getIdx()}; |
| 653 return Par(expr, 2, exprs, env); | 647 return Par(expr, 2, exprs, env); |
| 654 } | 648 } |
| 655 | 649 |
| 656 bool IsRawPointerVar(clang::Expr* expr, std::string* var_name) { | 650 bool IsRawPointerVar(clang::Expr* expr, std::string* var_name) { |
| 657 if (isa<clang::BlockDeclRefExpr>(expr)) { | 651 if (llvm::isa<clang::DeclRefExpr>(expr)) { |
| 658 *var_name = cast<clang::BlockDeclRefExpr>(expr)->getDecl()-> | 652 *var_name = |
| 659 getNameAsString(); | 653 llvm::cast<clang::DeclRefExpr>(expr)->getDecl()->getNameAsString(); |
| 660 return true; | |
| 661 } else if (isa<clang::DeclRefExpr>(expr)) { | |
| 662 *var_name = cast<clang::DeclRefExpr>(expr)->getDecl()->getNameAsString(); | |
| 663 return true; | 654 return true; |
| 664 } | 655 } |
| 665 return false; | 656 return false; |
| 666 } | 657 } |
| 667 | 658 |
| 668 DECL_VISIT_EXPR(BinaryOperator) { | 659 DECL_VISIT_EXPR(BinaryOperator) { |
| 669 clang::Expr* lhs = expr->getLHS(); | 660 clang::Expr* lhs = expr->getLHS(); |
| 670 clang::Expr* rhs = expr->getRHS(); | 661 clang::Expr* rhs = expr->getRHS(); |
| 671 clang::Expr* exprs[2] = {lhs, rhs}; | 662 clang::Expr* exprs[2] = {lhs, rhs}; |
| 672 | 663 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 700 } | 691 } |
| 701 | 692 |
| 702 DECL_VISIT_EXPR(CXXDefaultArgExpr) { | 693 DECL_VISIT_EXPR(CXXDefaultArgExpr) { |
| 703 return VisitExpr(expr->getExpr(), env); | 694 return VisitExpr(expr->getExpr(), env); |
| 704 } | 695 } |
| 705 | 696 |
| 706 DECL_VISIT_EXPR(CXXDeleteExpr) { | 697 DECL_VISIT_EXPR(CXXDeleteExpr) { |
| 707 return VisitExpr(expr->getArgument(), env); | 698 return VisitExpr(expr->getArgument(), env); |
| 708 } | 699 } |
| 709 | 700 |
| 710 DECL_VISIT_EXPR(CXXNewExpr) { | 701 DECL_VISIT_EXPR(CXXNewExpr) { return VisitExpr(expr->getInitializer(), env); } |
| 711 return Par(expr, | |
| 712 expr->getNumConstructorArgs(), | |
| 713 expr->getConstructorArgs(), | |
| 714 env); | |
| 715 } | |
| 716 | 702 |
| 717 DECL_VISIT_EXPR(ExprWithCleanups) { | 703 DECL_VISIT_EXPR(ExprWithCleanups) { |
| 718 return VisitExpr(expr->getSubExpr(), env); | 704 return VisitExpr(expr->getSubExpr(), env); |
| 719 } | 705 } |
| 720 | 706 |
| 721 DECL_VISIT_EXPR(CXXThrowExpr) { | 707 DECL_VISIT_EXPR(CXXThrowExpr) { |
| 722 return VisitExpr(expr->getSubExpr(), env); | 708 return VisitExpr(expr->getSubExpr(), env); |
| 723 } | 709 } |
| 724 | 710 |
| 725 DECL_VISIT_EXPR(InitListExpr) { | 711 DECL_VISIT_EXPR(InitListExpr) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 } | 745 } |
| 760 | 746 |
| 761 DECL_VISIT_EXPR(CastExpr) { | 747 DECL_VISIT_EXPR(CastExpr) { |
| 762 return VisitExpr(expr->getSubExpr(), env); | 748 return VisitExpr(expr->getSubExpr(), env); |
| 763 } | 749 } |
| 764 | 750 |
| 765 DECL_VISIT_EXPR(DeclRefExpr) { | 751 DECL_VISIT_EXPR(DeclRefExpr) { |
| 766 return Use(expr, expr->getDecl(), env); | 752 return Use(expr, expr->getDecl(), env); |
| 767 } | 753 } |
| 768 | 754 |
| 769 DECL_VISIT_EXPR(BlockDeclRefExpr) { | |
| 770 return Use(expr, expr->getDecl(), env); | |
| 771 } | |
| 772 | |
| 773 ExprEffect Par(clang::Expr* parent, | 755 ExprEffect Par(clang::Expr* parent, |
| 774 int n, | 756 int n, |
| 775 clang::Expr** exprs, | 757 clang::Expr** exprs, |
| 776 const Environment& env) { | 758 const Environment& env) { |
| 777 CallProps props; | 759 CallProps props; |
| 778 | 760 |
| 779 for (int i = 0; i < n; ++i) { | 761 for (int i = 0; i < n; ++i) { |
| 780 props.SetEffect(i, VisitExpr(exprs[i], env)); | 762 props.SetEffect(i, VisitExpr(exprs[i], env)); |
| 781 } | 763 } |
| 782 | 764 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 props->SetEffect(arg + 1, VisitExpr(call->getArg(arg), env)); | 819 props->SetEffect(arg + 1, VisitExpr(call->getArg(arg), env)); |
| 838 } | 820 } |
| 839 } | 821 } |
| 840 | 822 |
| 841 | 823 |
| 842 ExprEffect VisitCallExpr(clang::CallExpr* call, | 824 ExprEffect VisitCallExpr(clang::CallExpr* call, |
| 843 const Environment& env) { | 825 const Environment& env) { |
| 844 CallProps props; | 826 CallProps props; |
| 845 | 827 |
| 846 clang::CXXMemberCallExpr* memcall = | 828 clang::CXXMemberCallExpr* memcall = |
| 847 dyn_cast_or_null<clang::CXXMemberCallExpr>(call); | 829 llvm::dyn_cast_or_null<clang::CXXMemberCallExpr>(call); |
| 848 if (memcall != NULL) { | 830 if (memcall != NULL) { |
| 849 clang::Expr* receiver = memcall->getImplicitObjectArgument(); | 831 clang::Expr* receiver = memcall->getImplicitObjectArgument(); |
| 850 props.SetEffect(0, VisitExpr(receiver, env)); | 832 props.SetEffect(0, VisitExpr(receiver, env)); |
| 851 } | 833 } |
| 852 | 834 |
| 853 VisitArguments<>(call, &props, env); | 835 VisitArguments<>(call, &props, env); |
| 854 | 836 |
| 855 if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG); | 837 if (!props.IsSafe()) ReportUnsafe(call, BAD_EXPR_MSG); |
| 856 | 838 |
| 857 ExprEffect out = | 839 ExprEffect out = |
| 858 props.ComputeCumulativeEffect(IsRawPointerType(call->getType())); | 840 props.ComputeCumulativeEffect(IsRawPointerType(call->getType())); |
| 859 | 841 |
| 860 clang::FunctionDecl* callee = call->getDirectCallee(); | 842 clang::FunctionDecl* callee = call->getDirectCallee(); |
| 861 if ((callee != NULL) && KnownToCauseGC(ctx_, callee)) { | 843 if ((callee != NULL) && KnownToCauseGC(ctx_, callee)) { |
| 862 out.setGC(); | 844 out.setGC(); |
| 863 } | 845 } |
| 864 | 846 |
| 865 return out; | 847 return out; |
| 866 } | 848 } |
| 867 | 849 |
| 868 // -------------------------------------------------------------------------- | 850 // -------------------------------------------------------------------------- |
| 869 // Statements | 851 // Statements |
| 870 // -------------------------------------------------------------------------- | 852 // -------------------------------------------------------------------------- |
| 871 | 853 |
| 872 Environment VisitStmt(clang::Stmt* stmt, const Environment& env) { | 854 Environment VisitStmt(clang::Stmt* stmt, const Environment& env) { |
| 873 #define VISIT(type) do { \ | 855 #define VISIT(type) \ |
| 874 clang::type* concrete_stmt = dyn_cast_or_null<clang::type>(stmt); \ | 856 do { \ |
| 875 if (concrete_stmt != NULL) { \ | 857 clang::type* concrete_stmt = llvm::dyn_cast_or_null<clang::type>(stmt); \ |
| 876 return Visit##type (concrete_stmt, env); \ | 858 if (concrete_stmt != NULL) { \ |
| 877 } \ | 859 return Visit##type(concrete_stmt, env); \ |
| 878 } while(0); | 860 } \ |
| 861 } while (0); |
| 879 | 862 |
| 880 if (clang::Expr* expr = dyn_cast_or_null<clang::Expr>(stmt)) { | 863 if (clang::Expr* expr = llvm::dyn_cast_or_null<clang::Expr>(stmt)) { |
| 881 return env.ApplyEffect(VisitExpr(expr, env)); | 864 return env.ApplyEffect(VisitExpr(expr, env)); |
| 882 } | 865 } |
| 883 | 866 |
| 884 VISIT(AsmStmt); | 867 VISIT(AsmStmt); |
| 885 VISIT(BreakStmt); | 868 VISIT(BreakStmt); |
| 886 VISIT(CompoundStmt); | 869 VISIT(CompoundStmt); |
| 887 VISIT(ContinueStmt); | 870 VISIT(ContinueStmt); |
| 888 VISIT(CXXCatchStmt); | 871 VISIT(CXXCatchStmt); |
| 889 VISIT(CXXTryStmt); | 872 VISIT(CXXTryStmt); |
| 890 VISIT(DeclStmt); | 873 VISIT(DeclStmt); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 } | 1054 } |
| 1072 | 1055 |
| 1073 DECL_VISIT_STMT(ReturnStmt) { | 1056 DECL_VISIT_STMT(ReturnStmt) { |
| 1074 VisitExpr(stmt->getRetValue(), env); | 1057 VisitExpr(stmt->getRetValue(), env); |
| 1075 return Environment::Unreachable(); | 1058 return Environment::Unreachable(); |
| 1076 } | 1059 } |
| 1077 | 1060 |
| 1078 const clang::TagType* ToTagType(const clang::Type* t) { | 1061 const clang::TagType* ToTagType(const clang::Type* t) { |
| 1079 if (t == NULL) { | 1062 if (t == NULL) { |
| 1080 return NULL; | 1063 return NULL; |
| 1081 } else if (isa<clang::TagType>(t)) { | 1064 } else if (llvm::isa<clang::TagType>(t)) { |
| 1082 return cast<clang::TagType>(t); | 1065 return llvm::cast<clang::TagType>(t); |
| 1083 } else if (isa<clang::SubstTemplateTypeParmType>(t)) { | 1066 } else if (llvm::isa<clang::SubstTemplateTypeParmType>(t)) { |
| 1084 return ToTagType(cast<clang::SubstTemplateTypeParmType>(t)-> | 1067 return ToTagType(llvm::cast<clang::SubstTemplateTypeParmType>(t) |
| 1085 getReplacementType().getTypePtr()); | 1068 ->getReplacementType() |
| 1069 .getTypePtr()); |
| 1086 } else { | 1070 } else { |
| 1087 return NULL; | 1071 return NULL; |
| 1088 } | 1072 } |
| 1089 } | 1073 } |
| 1090 | 1074 |
| 1091 bool IsDerivedFrom(clang::CXXRecordDecl* record, | 1075 bool IsDerivedFrom(clang::CXXRecordDecl* record, |
| 1092 clang::CXXRecordDecl* base) { | 1076 clang::CXXRecordDecl* base) { |
| 1093 return (record == base) || record->isDerivedFrom(base); | 1077 return (record == base) || record->isDerivedFrom(base); |
| 1094 } | 1078 } |
| 1095 | 1079 |
| 1096 bool IsRawPointerType(clang::QualType qtype) { | 1080 bool IsRawPointerType(clang::QualType qtype) { |
| 1097 const clang::PointerType* type = | 1081 const clang::PointerType* type = |
| 1098 dyn_cast_or_null<clang::PointerType>(qtype.getTypePtrOrNull()); | 1082 llvm::dyn_cast_or_null<clang::PointerType>(qtype.getTypePtrOrNull()); |
| 1099 if (type == NULL) return false; | 1083 if (type == NULL) return false; |
| 1100 | 1084 |
| 1101 const clang::TagType* pointee = | 1085 const clang::TagType* pointee = |
| 1102 ToTagType(type->getPointeeType().getTypePtr()); | 1086 ToTagType(type->getPointeeType().getTypePtr()); |
| 1103 if (pointee == NULL) return false; | 1087 if (pointee == NULL) return false; |
| 1104 | 1088 |
| 1105 clang::CXXRecordDecl* record = | 1089 clang::CXXRecordDecl* record = |
| 1106 dyn_cast_or_null<clang::CXXRecordDecl>(pointee->getDecl()); | 1090 llvm::dyn_cast_or_null<clang::CXXRecordDecl>(pointee->getDecl()); |
| 1107 if (record == NULL) return false; | 1091 if (record == NULL) return false; |
| 1108 | 1092 |
| 1109 if (!InV8Namespace(record)) return false; | 1093 if (!InV8Namespace(record)) return false; |
| 1110 | 1094 |
| 1111 if (!record->hasDefinition()) return false; | 1095 if (!record->hasDefinition()) return false; |
| 1112 | 1096 |
| 1113 record = record->getDefinition(); | 1097 record = record->getDefinition(); |
| 1114 | 1098 |
| 1115 return IsDerivedFrom(record, object_decl_) && | 1099 return IsDerivedFrom(record, object_decl_) && |
| 1116 !IsDerivedFrom(record, smi_decl_); | 1100 !IsDerivedFrom(record, smi_decl_); |
| 1117 } | 1101 } |
| 1118 | 1102 |
| 1119 Environment VisitDecl(clang::Decl* decl, const Environment& env) { | 1103 Environment VisitDecl(clang::Decl* decl, const Environment& env) { |
| 1120 if (clang::VarDecl* var = dyn_cast<clang::VarDecl>(decl)) { | 1104 if (clang::VarDecl* var = llvm::dyn_cast<clang::VarDecl>(decl)) { |
| 1121 Environment out = var->hasInit() ? VisitStmt(var->getInit(), env) : env; | 1105 Environment out = var->hasInit() ? VisitStmt(var->getInit(), env) : env; |
| 1122 | 1106 |
| 1123 if (IsRawPointerType(var->getType())) { | 1107 if (IsRawPointerType(var->getType())) { |
| 1124 out = out.Define(var->getNameAsString()); | 1108 out = out.Define(var->getNameAsString()); |
| 1125 } | 1109 } |
| 1126 | 1110 |
| 1127 return out; | 1111 return out; |
| 1128 } | 1112 } |
| 1129 // TODO: handle other declarations? | 1113 // TODO: handle other declarations? |
| 1130 return env; | 1114 return env; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 return parent; | 1154 return parent; |
| 1171 } | 1155 } |
| 1172 | 1156 |
| 1173 void LeaveBlock(Block* block) { | 1157 void LeaveBlock(Block* block) { |
| 1174 block_ = block; | 1158 block_ = block; |
| 1175 } | 1159 } |
| 1176 | 1160 |
| 1177 private: | 1161 private: |
| 1178 void ReportUnsafe(const clang::Expr* expr, const std::string& msg) { | 1162 void ReportUnsafe(const clang::Expr* expr, const std::string& msg) { |
| 1179 d_.Report(clang::FullSourceLoc(expr->getExprLoc(), sm_), | 1163 d_.Report(clang::FullSourceLoc(expr->getExprLoc(), sm_), |
| 1180 d_.getCustomDiagID(clang::Diagnostic::Warning, msg)); | 1164 d_.getCustomDiagID(clang::DiagnosticsEngine::Warning, "%0")) |
| 1165 << msg; |
| 1181 } | 1166 } |
| 1182 | 1167 |
| 1183 | 1168 |
| 1184 clang::MangleContext* ctx_; | 1169 clang::MangleContext* ctx_; |
| 1185 clang::DeclarationName handle_decl_name_; | 1170 clang::DeclarationName handle_decl_name_; |
| 1186 clang::CXXRecordDecl* object_decl_; | 1171 clang::CXXRecordDecl* object_decl_; |
| 1187 clang::CXXRecordDecl* smi_decl_; | 1172 clang::CXXRecordDecl* smi_decl_; |
| 1188 | 1173 |
| 1189 clang::Diagnostic& d_; | 1174 clang::DiagnosticsEngine& d_; |
| 1190 clang::SourceManager& sm_; | 1175 clang::SourceManager& sm_; |
| 1191 | 1176 |
| 1192 Block* block_; | 1177 Block* block_; |
| 1193 bool dead_vars_analysis_; | 1178 bool dead_vars_analysis_; |
| 1194 }; | 1179 }; |
| 1195 | 1180 |
| 1196 | 1181 |
| 1197 class ProblemsFinder : public clang::ASTConsumer, | 1182 class ProblemsFinder : public clang::ASTConsumer, |
| 1198 public clang::RecursiveASTVisitor<ProblemsFinder> { | 1183 public clang::RecursiveASTVisitor<ProblemsFinder> { |
| 1199 public: | 1184 public: |
| 1200 ProblemsFinder(clang::Diagnostic& d, | 1185 ProblemsFinder(clang::DiagnosticsEngine& d, clang::SourceManager& sm, |
| 1201 clang::SourceManager& sm, | |
| 1202 const std::vector<std::string>& args) | 1186 const std::vector<std::string>& args) |
| 1203 : d_(d), sm_(sm), dead_vars_analysis_(false) { | 1187 : d_(d), sm_(sm), dead_vars_analysis_(false) { |
| 1204 for (unsigned i = 0; i < args.size(); ++i) { | 1188 for (unsigned i = 0; i < args.size(); ++i) { |
| 1205 if (args[i] == "--dead-vars") { | 1189 if (args[i] == "--dead-vars") { |
| 1206 dead_vars_analysis_ = true; | 1190 dead_vars_analysis_ = true; |
| 1207 } | 1191 } |
| 1208 } | 1192 } |
| 1209 } | 1193 } |
| 1210 | 1194 |
| 1211 virtual void HandleTranslationUnit(clang::ASTContext &ctx) { | 1195 virtual void HandleTranslationUnit(clang::ASTContext &ctx) { |
| 1212 Resolver r(ctx); | 1196 Resolver r(ctx); |
| 1213 | 1197 |
| 1214 clang::CXXRecordDecl* object_decl = | 1198 clang::CXXRecordDecl* object_decl = |
| 1215 r.ResolveNamespace("v8").ResolveNamespace("internal"). | 1199 r.ResolveNamespace("v8").ResolveNamespace("internal"). |
| 1216 Resolve<clang::CXXRecordDecl>("Object"); | 1200 Resolve<clang::CXXRecordDecl>("Object"); |
| 1217 | 1201 |
| 1218 clang::CXXRecordDecl* smi_decl = | 1202 clang::CXXRecordDecl* smi_decl = |
| 1219 r.ResolveNamespace("v8").ResolveNamespace("internal"). | 1203 r.ResolveNamespace("v8").ResolveNamespace("internal"). |
| 1220 Resolve<clang::CXXRecordDecl>("Smi"); | 1204 Resolve<clang::CXXRecordDecl>("Smi"); |
| 1221 | 1205 |
| 1222 if (object_decl != NULL) object_decl = object_decl->getDefinition(); | 1206 if (object_decl != NULL) object_decl = object_decl->getDefinition(); |
| 1223 | 1207 |
| 1224 if (smi_decl != NULL) smi_decl = smi_decl->getDefinition(); | 1208 if (smi_decl != NULL) smi_decl = smi_decl->getDefinition(); |
| 1225 | 1209 |
| 1226 if (object_decl != NULL && smi_decl != NULL) { | 1210 if (object_decl != NULL && smi_decl != NULL) { |
| 1227 function_analyzer_ = | 1211 function_analyzer_ = new FunctionAnalyzer( |
| 1228 new FunctionAnalyzer(clang::createItaniumMangleContext(ctx, d_), | 1212 clang::ItaniumMangleContext::create(ctx, d_), r.ResolveName("Handle"), |
| 1229 r.ResolveName("Handle"), | 1213 object_decl, smi_decl, d_, sm_, dead_vars_analysis_); |
| 1230 object_decl, | |
| 1231 smi_decl, | |
| 1232 d_, | |
| 1233 sm_, | |
| 1234 dead_vars_analysis_); | |
| 1235 TraverseDecl(ctx.getTranslationUnitDecl()); | 1214 TraverseDecl(ctx.getTranslationUnitDecl()); |
| 1236 } else { | 1215 } else { |
| 1237 if (object_decl == NULL) { | 1216 if (object_decl == NULL) { |
| 1238 llvm::errs() << "Failed to resolve v8::internal::Object\n"; | 1217 llvm::errs() << "Failed to resolve v8::internal::Object\n"; |
| 1239 } | 1218 } |
| 1240 if (smi_decl == NULL) { | 1219 if (smi_decl == NULL) { |
| 1241 llvm::errs() << "Failed to resolve v8::internal::Smi\n"; | 1220 llvm::errs() << "Failed to resolve v8::internal::Smi\n"; |
| 1242 } | 1221 } |
| 1243 } | 1222 } |
| 1244 } | 1223 } |
| 1245 | 1224 |
| 1246 virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) { | 1225 virtual bool VisitFunctionDecl(clang::FunctionDecl* decl) { |
| 1247 function_analyzer_->AnalyzeFunction(decl); | 1226 function_analyzer_->AnalyzeFunction(decl); |
| 1248 return true; | 1227 return true; |
| 1249 } | 1228 } |
| 1250 | 1229 |
| 1251 private: | 1230 private: |
| 1252 clang::Diagnostic& d_; | 1231 clang::DiagnosticsEngine& d_; |
| 1253 clang::SourceManager& sm_; | 1232 clang::SourceManager& sm_; |
| 1254 bool dead_vars_analysis_; | 1233 bool dead_vars_analysis_; |
| 1255 | 1234 |
| 1256 FunctionAnalyzer* function_analyzer_; | 1235 FunctionAnalyzer* function_analyzer_; |
| 1257 }; | 1236 }; |
| 1258 | 1237 |
| 1259 | 1238 |
| 1260 template<typename ConsumerType> | 1239 template<typename ConsumerType> |
| 1261 class Action : public clang::PluginASTAction { | 1240 class Action : public clang::PluginASTAction { |
| 1262 protected: | 1241 protected: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1279 | 1258 |
| 1280 | 1259 |
| 1281 } | 1260 } |
| 1282 | 1261 |
| 1283 static clang::FrontendPluginRegistry::Add<Action<ProblemsFinder> > | 1262 static clang::FrontendPluginRegistry::Add<Action<ProblemsFinder> > |
| 1284 FindProblems("find-problems", "Find GC-unsafe places."); | 1263 FindProblems("find-problems", "Find GC-unsafe places."); |
| 1285 | 1264 |
| 1286 static clang::FrontendPluginRegistry::Add< | 1265 static clang::FrontendPluginRegistry::Add< |
| 1287 Action<FunctionDeclarationFinder> > | 1266 Action<FunctionDeclarationFinder> > |
| 1288 DumpCallees("dump-callees", "Dump callees for each function."); | 1267 DumpCallees("dump-callees", "Dump callees for each function."); |
| OLD | NEW |