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 |