Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp

Issue 988693005: Chromium roll (https://codereview.chromium.org/976353002) (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: fixed bad android build patch Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/yasm/BUILD.gn ('k') | tools/clang/blink_gc_plugin/CMakeLists.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This clang plugin checks various invariants of the Blink garbage 5 // This clang plugin checks various invariants of the Blink garbage
6 // collection infrastructure. 6 // collection infrastructure.
7 // 7 //
8 // Errors are described at: 8 // Errors are described at:
9 // http://www.chromium.org/developers/blink-gc-plugin-errors 9 // http://www.chromium.org/developers/blink-gc-plugin-errors
10 10
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 bool dispatched_to_receiver() { return dispatched_to_receiver_; } 308 bool dispatched_to_receiver() { return dispatched_to_receiver_; }
309 309
310 bool VisitMemberExpr(MemberExpr* member) { 310 bool VisitMemberExpr(MemberExpr* member) {
311 if (CXXMethodDecl* fn = dyn_cast<CXXMethodDecl>(member->getMemberDecl())) { 311 if (CXXMethodDecl* fn = dyn_cast<CXXMethodDecl>(member->getMemberDecl())) {
312 if (fn->getParent() == receiver_->record()) 312 if (fn->getParent() == receiver_->record())
313 dispatched_to_receiver_ = true; 313 dispatched_to_receiver_ = true;
314 } 314 }
315 return true; 315 return true;
316 } 316 }
317 317
318 bool VisitUnresolvedMemberExpr(UnresolvedMemberExpr* member) {
319 for (Decl* decl : member->decls()) {
320 if (CXXMethodDecl* method = dyn_cast<CXXMethodDecl>(decl)) {
321 if (method->getParent() == receiver_->record() &&
322 Config::GetTraceMethodType(method) ==
323 Config::TRACE_AFTER_DISPATCH_METHOD) {
324 dispatched_to_receiver_ = true;
325 return true;
326 }
327 }
328 }
329 return true;
330 }
331
318 private: 332 private:
319 RecordInfo* receiver_; 333 RecordInfo* receiver_;
320 bool dispatched_to_receiver_; 334 bool dispatched_to_receiver_;
321 }; 335 };
322 336
323 // This visitor checks a tracing method by traversing its body. 337 // This visitor checks a tracing method by traversing its body.
324 // - A member field is considered traced if it is referenced in the body. 338 // - A member field is considered traced if it is referenced in the body.
325 // - A base is traced if a base-qualified call to a trace method is found. 339 // - A base is traced if a base-qualified call to a trace method is found.
326 class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> { 340 class CheckTraceVisitor : public RecursiveASTVisitor<CheckTraceVisitor> {
327 public: 341 public:
328 CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info) 342 CheckTraceVisitor(CXXMethodDecl* trace, RecordInfo* info, RecordCache* cache)
329 : trace_(trace), info_(info), delegates_to_traceimpl_(false) {} 343 : trace_(trace),
344 info_(info),
345 cache_(cache),
346 delegates_to_traceimpl_(false) {
347 }
330 348
331 bool delegates_to_traceimpl() const { return delegates_to_traceimpl_; } 349 bool delegates_to_traceimpl() const { return delegates_to_traceimpl_; }
332 350
333 bool VisitMemberExpr(MemberExpr* member) { 351 bool VisitMemberExpr(MemberExpr* member) {
334 // In weak callbacks, consider any occurrence as a correct usage. 352 // In weak callbacks, consider any occurrence as a correct usage.
335 // TODO: We really want to require that isAlive is checked on manually 353 // TODO: We really want to require that isAlive is checked on manually
336 // processed weak fields. 354 // processed weak fields.
337 if (IsWeakCallback()) { 355 if (IsWeakCallback()) {
338 if (FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl())) 356 if (FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl()))
339 FoundField(field); 357 FoundField(field);
(...skipping 23 matching lines...) Expand all
363 if (call->getNumArgs() != 1) 381 if (call->getNumArgs() != 1)
364 return true; 382 return true;
365 Expr* arg = call->getArg(0); 383 Expr* arg = call->getArg(0);
366 384
367 if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) { 385 if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) {
368 // This could be a trace call of a base class, as explained in the 386 // This could be a trace call of a base class, as explained in the
369 // comments of CheckTraceBaseCall(). 387 // comments of CheckTraceBaseCall().
370 if (CheckTraceBaseCall(call)) 388 if (CheckTraceBaseCall(call))
371 return true; 389 return true;
372 390
373 // If we find a call to registerWeakMembers which is unresolved we 391 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName)
374 // unsoundly consider all weak members as traced. 392 MarkAllWeakMembersTraced();
375 // TODO: Find out how to validate weak member tracing for unresolved call.
376 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) {
377 for (RecordInfo::Fields::iterator it = info_->GetFields().begin();
378 it != info_->GetFields().end();
379 ++it) {
380 if (it->second.edge()->IsWeakMember())
381 it->second.MarkTraced();
382 }
383 }
384 393
385 QualType base = expr->getBaseType(); 394 QualType base = expr->getBaseType();
386 if (!base->isPointerType()) 395 if (!base->isPointerType())
387 return true; 396 return true;
388 CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl(); 397 CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl();
389 if (decl) 398 if (decl)
390 CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg); 399 CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg);
391 if (Config::IsTraceImplName(expr->getMemberName().getAsString())) 400 if (Config::IsTraceImplName(expr->getMemberName().getAsString()))
392 delegates_to_traceimpl_ = true; 401 delegates_to_traceimpl_ = true;
393 return true; 402 return true;
394 } 403 }
395 404
396 if (CXXMemberCallExpr* expr = dyn_cast<CXXMemberCallExpr>(call)) { 405 if (CXXMemberCallExpr* expr = dyn_cast<CXXMemberCallExpr>(call)) {
397 if (CheckTraceFieldCall(expr) || CheckRegisterWeakMembers(expr)) 406 if (CheckTraceFieldCall(expr) || CheckRegisterWeakMembers(expr))
398 return true; 407 return true;
399 408
400 if (Config::IsTraceImplName(expr->getMethodDecl()->getNameAsString())) { 409 if (Config::IsTraceImplName(expr->getMethodDecl()->getNameAsString())) {
401 delegates_to_traceimpl_ = true; 410 delegates_to_traceimpl_ = true;
402 return true; 411 return true;
403 } 412 }
404 } 413 }
405 414
406 CheckTraceBaseCall(call); 415 CheckTraceBaseCall(call);
407 return true; 416 return true;
408 } 417 }
409 418
410 private: 419 private:
420 bool IsTraceCallName(const std::string& name) {
421 if (trace_->getName() == kTraceImplName)
422 return name == kTraceName;
423 if (trace_->getName() == kTraceAfterDispatchImplName)
424 return name == kTraceAfterDispatchName;
425 // Currently, a manually dispatched class cannot have mixin bases (having
426 // one would add a vtable which we explicitly check against). This means
427 // that we can only make calls to a trace method of the same name. Revisit
428 // this if our mixin/vtable assumption changes.
429 return name == trace_->getName();
430 }
431
411 CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) { 432 CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) {
412 NestedNameSpecifier* qual = expr->getQualifier(); 433 NestedNameSpecifier* qual = expr->getQualifier();
413 if (!qual) 434 if (!qual)
414 return 0; 435 return 0;
415 436
416 const Type* type = qual->getAsType(); 437 const Type* type = qual->getAsType();
417 if (!type) 438 if (!type)
418 return 0; 439 return 0;
419 440
420 return RecordInfo::GetDependentTemplatedDecl(*type); 441 return RecordInfo::GetDependentTemplatedDecl(*type);
421 } 442 }
422 443
423 void CheckCXXDependentScopeMemberExpr(CallExpr* call, 444 void CheckCXXDependentScopeMemberExpr(CallExpr* call,
424 CXXDependentScopeMemberExpr* expr) { 445 CXXDependentScopeMemberExpr* expr) {
425 string fn_name = expr->getMember().getAsString(); 446 string fn_name = expr->getMember().getAsString();
426 447
427 // Check for VisitorDispatcher::trace(field) 448 // Check for VisitorDispatcher::trace(field) and
449 // VisitorDispatcher::registerWeakMembers.
428 if (!expr->isImplicitAccess()) { 450 if (!expr->isImplicitAccess()) {
429 if (clang::DeclRefExpr* base_decl = 451 if (clang::DeclRefExpr* base_decl =
430 clang::dyn_cast<clang::DeclRefExpr>(expr->getBase())) { 452 clang::dyn_cast<clang::DeclRefExpr>(expr->getBase())) {
431 if (Config::IsVisitorDispatcherType(base_decl->getType()) && 453 if (Config::IsVisitorDispatcherType(base_decl->getType())) {
432 call->getNumArgs() == 1 && fn_name == kTraceName) { 454 if (call->getNumArgs() == 1 && fn_name == kTraceName) {
433 FindFieldVisitor finder; 455 FindFieldVisitor finder;
434 finder.TraverseStmt(call->getArg(0)); 456 finder.TraverseStmt(call->getArg(0));
435 if (finder.field()) 457 if (finder.field())
436 FoundField(finder.field()); 458 FoundField(finder.field());
437 459
438 return; 460 return;
461 } else if (call->getNumArgs() == 1 &&
462 fn_name == kRegisterWeakMembersName) {
463 MarkAllWeakMembersTraced();
464 }
439 } 465 }
440 } 466 }
441 } 467 }
442 468
443 CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr); 469 CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr);
444 if (!tmpl) 470 if (!tmpl)
445 return; 471 return;
446 472
447 // Check for Super<T>::trace(visitor) 473 // Check for Super<T>::trace(visitor)
448 if (call->getNumArgs() == 1 && fn_name == trace_->getName()) { 474 if (call->getNumArgs() == 1 && IsTraceCallName(fn_name)) {
449 RecordInfo::Bases::iterator it = info_->GetBases().begin(); 475 RecordInfo::Bases::iterator it = info_->GetBases().begin();
450 for (; it != info_->GetBases().end(); ++it) { 476 for (; it != info_->GetBases().end(); ++it) {
451 if (it->first->getName() == tmpl->getName()) 477 if (it->first->getName() == tmpl->getName())
452 it->second.MarkTraced(); 478 it->second.MarkTraced();
453 } 479 }
454 return;
455 } 480 }
456 481
457 // Check for TraceIfNeeded<T>::trace(visitor, &field) 482 // Check for TraceIfNeeded<T>::trace(visitor, &field)
458 if (call->getNumArgs() == 2 && fn_name == kTraceName && 483 if (call->getNumArgs() == 2 && fn_name == kTraceName &&
459 tmpl->getName() == kTraceIfNeededName) { 484 tmpl->getName() == kTraceIfNeededName) {
460 FindFieldVisitor finder; 485 FindFieldVisitor finder;
461 finder.TraverseStmt(call->getArg(1)); 486 finder.TraverseStmt(call->getArg(1));
462 if (finder.field()) 487 if (finder.field())
463 FoundField(finder.field()); 488 FoundField(finder.field());
464 } 489 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 if (call->getNumArgs() != 1) 542 if (call->getNumArgs() != 1)
518 return false; 543 return false;
519 DeclRefExpr* arg = dyn_cast<DeclRefExpr>(call->getArg(0)); 544 DeclRefExpr* arg = dyn_cast<DeclRefExpr>(call->getArg(0));
520 if (!arg || arg->getNameInfo().getAsString() != kVisitorVarName) 545 if (!arg || arg->getNameInfo().getAsString() != kVisitorVarName)
521 return false; 546 return false;
522 547
523 callee_record = trace_decl->getParent(); 548 callee_record = trace_decl->getParent();
524 func_name = callee->getMemberName().getAsString(); 549 func_name = callee->getMemberName().getAsString();
525 } 550 }
526 551
527 if (trace_->getName() == kTraceImplName) {
528 if (func_name != kTraceName)
529 return false;
530 } else if (trace_->getName() == kTraceAfterDispatchImplName) {
531 if (func_name != kTraceAfterDispatchName)
532 return false;
533 } else {
534 // Currently, a manually dispatched class cannot have mixin bases (having
535 // one would add a vtable which we explicitly check against). This means
536 // that we can only make calls to a trace method of the same name. Revisit
537 // this if our mixin/vtable assumption changes.
538 if (func_name != trace_->getName())
539 return false;
540 }
541
542 if (!callee_record) 552 if (!callee_record)
543 return false; 553 return false;
544 RecordInfo::Bases::iterator iter = info_->GetBases().find(callee_record); 554
545 if (iter == info_->GetBases().end()) 555 if (!IsTraceCallName(func_name))
546 return false; 556 return false;
547 557
548 iter->second.MarkTraced(); 558 for (auto& base : info_->GetBases()) {
549 return true; 559 // We want to deal with omitted trace() function in an intermediary
560 // class in the class hierarchy, e.g.:
561 // class A : public GarbageCollected<A> { trace() { ... } };
562 // class B : public A { /* No trace(); have nothing to trace. */ };
563 // class C : public B { trace() { B::trace(visitor); } }
564 // where, B::trace() is actually A::trace(), and in some cases we get
565 // A as |callee_record| instead of B. We somehow need to mark B as
566 // traced if we find A::trace() call.
567 //
568 // To solve this, here we keep going up the class hierarchy as long as
569 // they are not required to have a trace method. The implementation is
570 // a simple DFS, where |base_records| represents the set of base classes
571 // we need to visit.
572
573 std::vector<CXXRecordDecl*> base_records;
574 base_records.push_back(base.first);
575
576 while (!base_records.empty()) {
577 CXXRecordDecl* base_record = base_records.back();
578 base_records.pop_back();
579
580 if (base_record == callee_record) {
581 // If we find a matching trace method, pretend the user has written
582 // a correct trace() method of the base; in the example above, we
583 // find A::trace() here and mark B as correctly traced.
584 base.second.MarkTraced();
585 return true;
586 }
587
588 if (RecordInfo* base_info = cache_->Lookup(base_record)) {
589 if (!base_info->RequiresTraceMethod()) {
590 // If this base class is not required to have a trace method, then
591 // the actual trace method may be defined in an ancestor.
592 for (auto& inner_base : base_info->GetBases())
593 base_records.push_back(inner_base.first);
594 }
595 }
596 }
597 }
598
599 return false;
550 } 600 }
551 601
552 bool CheckTraceFieldCall(CXXMemberCallExpr* call) { 602 bool CheckTraceFieldCall(CXXMemberCallExpr* call) {
553 return CheckTraceFieldCall(call->getMethodDecl()->getNameAsString(), 603 return CheckTraceFieldCall(call->getMethodDecl()->getNameAsString(),
554 call->getRecordDecl(), 604 call->getRecordDecl(),
555 call->getArg(0)); 605 call->getArg(0));
556 } 606 }
557 607
558 bool CheckTraceFieldCall(string name, CXXRecordDecl* callee, Expr* arg) { 608 bool CheckTraceFieldCall(string name, CXXRecordDecl* callee, Expr* arg) {
559 if (name != kTraceName || !Config::IsVisitor(callee->getName())) 609 if (name != kTraceName || !Config::IsVisitor(callee->getName()))
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 return false; 652 return false;
603 } 653 }
604 return true; 654 return true;
605 } 655 }
606 private: 656 private:
607 MemberExpr* member_; 657 MemberExpr* member_;
608 FieldDecl* field_; 658 FieldDecl* field_;
609 }; 659 };
610 660
611 // Nested checking for weak callbacks. 661 // Nested checking for weak callbacks.
612 CheckTraceVisitor(RecordInfo* info) : trace_(0), info_(info) {} 662 CheckTraceVisitor(RecordInfo* info)
663 : trace_(nullptr), info_(info), cache_(nullptr) {}
613 664
614 bool IsWeakCallback() { return !trace_; } 665 bool IsWeakCallback() { return !trace_; }
615 666
616 void MarkTraced(RecordInfo::Fields::iterator it) { 667 void MarkTraced(RecordInfo::Fields::iterator it) {
617 // In a weak callback we can't mark strong fields as traced. 668 // In a weak callback we can't mark strong fields as traced.
618 if (IsWeakCallback() && !it->second.edge()->IsWeakMember()) 669 if (IsWeakCallback() && !it->second.edge()->IsWeakMember())
619 return; 670 return;
620 it->second.MarkTraced(); 671 it->second.MarkTraced();
621 } 672 }
622 673
(...skipping 11 matching lines...) Expand all
634 break; 685 break;
635 } 686 }
636 } 687 }
637 } else { 688 } else {
638 RecordInfo::Fields::iterator it = info_->GetFields().find(field); 689 RecordInfo::Fields::iterator it = info_->GetFields().find(field);
639 if (it != info_->GetFields().end()) 690 if (it != info_->GetFields().end())
640 MarkTraced(it); 691 MarkTraced(it);
641 } 692 }
642 } 693 }
643 694
695 void MarkAllWeakMembersTraced() {
696 // If we find a call to registerWeakMembers which is unresolved we
697 // unsoundly consider all weak members as traced.
698 // TODO: Find out how to validate weak member tracing for unresolved call.
699 for (auto& field : info_->GetFields()) {
700 if (field.second.edge()->IsWeakMember())
701 field.second.MarkTraced();
702 }
703 }
704
644 CXXMethodDecl* trace_; 705 CXXMethodDecl* trace_;
645 RecordInfo* info_; 706 RecordInfo* info_;
707 RecordCache* cache_;
646 bool delegates_to_traceimpl_; 708 bool delegates_to_traceimpl_;
647 }; 709 };
648 710
649 // This visitor checks that the fields of a class and the fields of 711 // This visitor checks that the fields of a class and the fields of
650 // its part objects don't define GC roots. 712 // its part objects don't define GC roots.
651 class CheckGCRootsVisitor : public RecursiveEdgeVisitor { 713 class CheckGCRootsVisitor : public RecursiveEdgeVisitor {
652 public: 714 public:
653 typedef std::vector<FieldPoint*> RootPath; 715 typedef std::vector<FieldPoint*> RootPath;
654 typedef std::set<RecordInfo*> VisitingSet; 716 typedef std::set<RecordInfo*> VisitingSet;
655 typedef std::vector<RootPath> Errors; 717 typedef std::vector<RootPath> Errors;
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 if (visitor.ContainsInvalidFields(info)) 1124 if (visitor.ContainsInvalidFields(info))
1063 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); 1125 ReportClassContainsInvalidFields(info, &visitor.invalid_fields());
1064 } 1126 }
1065 1127
1066 if (info->IsGCDerived()) { 1128 if (info->IsGCDerived()) {
1067 1129
1068 if (!info->IsGCMixin()) { 1130 if (!info->IsGCMixin()) {
1069 CheckLeftMostDerived(info); 1131 CheckLeftMostDerived(info);
1070 CheckDispatch(info); 1132 CheckDispatch(info);
1071 if (CXXMethodDecl* newop = info->DeclaresNewOperator()) 1133 if (CXXMethodDecl* newop = info->DeclaresNewOperator())
1072 ReportClassOverridesNew(info, newop); 1134 if (!Config::IsIgnoreAnnotated(newop))
1135 ReportClassOverridesNew(info, newop);
1073 if (info->IsGCMixinInstance()) { 1136 if (info->IsGCMixinInstance()) {
1074 // Require that declared GCMixin implementations 1137 // Require that declared GCMixin implementations
1075 // also provide a trace() override. 1138 // also provide a trace() override.
1076 if (info->DeclaresGCMixinMethods() 1139 if (info->DeclaresGCMixinMethods()
1077 && !info->DeclaresLocalTraceMethod()) 1140 && !info->DeclaresLocalTraceMethod())
1078 ReportClassMustDeclareGCMixinTraceMethod(info); 1141 ReportClassMustDeclareGCMixinTraceMethod(info);
1079 } 1142 }
1080 } 1143 }
1081 1144
1082 { 1145 {
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1358 } 1421 }
1359 return; 1422 return;
1360 } 1423 }
1361 1424
1362 CheckTraceOrDispatchMethod(parent, method); 1425 CheckTraceOrDispatchMethod(parent, method);
1363 } 1426 }
1364 1427
1365 // Determine what type of tracing method this is (dispatch or trace). 1428 // Determine what type of tracing method this is (dispatch or trace).
1366 void CheckTraceOrDispatchMethod(RecordInfo* parent, CXXMethodDecl* method) { 1429 void CheckTraceOrDispatchMethod(RecordInfo* parent, CXXMethodDecl* method) {
1367 Config::TraceMethodType trace_type = Config::GetTraceMethodType(method); 1430 Config::TraceMethodType trace_type = Config::GetTraceMethodType(method);
1368 if (trace_type != Config::TRACE_METHOD || 1431 if (trace_type == Config::TRACE_AFTER_DISPATCH_METHOD ||
1432 trace_type == Config::TRACE_AFTER_DISPATCH_IMPL_METHOD ||
1369 !parent->GetTraceDispatchMethod()) { 1433 !parent->GetTraceDispatchMethod()) {
1370 CheckTraceMethod(parent, method, trace_type); 1434 CheckTraceMethod(parent, method, trace_type);
1371 } 1435 }
1372 // Dispatch methods are checked when we identify subclasses. 1436 // Dispatch methods are checked when we identify subclasses.
1373 } 1437 }
1374 1438
1375 // Check an actual trace method. 1439 // Check an actual trace method.
1376 void CheckTraceMethod(RecordInfo* parent, 1440 void CheckTraceMethod(RecordInfo* parent,
1377 CXXMethodDecl* trace, 1441 CXXMethodDecl* trace,
1378 Config::TraceMethodType trace_type) { 1442 Config::TraceMethodType trace_type) {
1379 // A trace method must not override any non-virtual trace methods. 1443 // A trace method must not override any non-virtual trace methods.
1380 if (trace_type == Config::TRACE_METHOD) { 1444 if (trace_type == Config::TRACE_METHOD) {
1381 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); 1445 for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
1382 it != parent->GetBases().end(); 1446 it != parent->GetBases().end();
1383 ++it) { 1447 ++it) {
1384 RecordInfo* base = it->second.info(); 1448 RecordInfo* base = it->second.info();
1385 if (CXXMethodDecl* other = base->InheritsNonVirtualTrace()) 1449 if (CXXMethodDecl* other = base->InheritsNonVirtualTrace())
1386 ReportOverriddenNonVirtualTrace(parent, trace, other); 1450 ReportOverriddenNonVirtualTrace(parent, trace, other);
1387 } 1451 }
1388 } 1452 }
1389 1453
1390 CheckTraceVisitor visitor(trace, parent); 1454 CheckTraceVisitor visitor(trace, parent, &cache_);
1391 visitor.TraverseCXXMethodDecl(trace); 1455 visitor.TraverseCXXMethodDecl(trace);
1392 1456
1393 // Skip reporting if this trace method is a just delegate to 1457 // Skip reporting if this trace method is a just delegate to
1394 // traceImpl (or traceAfterDispatchImpl) method. We will report on 1458 // traceImpl (or traceAfterDispatchImpl) method. We will report on
1395 // CheckTraceMethod on traceImpl method. 1459 // CheckTraceMethod on traceImpl method.
1396 if (visitor.delegates_to_traceimpl()) 1460 if (visitor.delegates_to_traceimpl())
1397 return; 1461 return;
1398 1462
1399 for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); 1463 for (RecordInfo::Bases::iterator it = parent->GetBases().begin();
1400 it != parent->GetBases().end(); 1464 it != parent->GetBases().end();
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
1990 2054
1991 private: 2055 private:
1992 BlinkGCPluginOptions options_; 2056 BlinkGCPluginOptions options_;
1993 }; 2057 };
1994 2058
1995 } // namespace 2059 } // namespace
1996 2060
1997 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( 2061 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X(
1998 "blink-gc-plugin", 2062 "blink-gc-plugin",
1999 "Check Blink GC invariants"); 2063 "Check Blink GC invariants");
OLDNEW
« no previous file with comments | « third_party/yasm/BUILD.gn ('k') | tools/clang/blink_gc_plugin/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698