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

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

Issue 939303005: BlinkGCPlugin: Support overloaded trace() call from template. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix a subtle typo. 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 | « no previous file | tools/clang/blink_gc_plugin/Config.h » ('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 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 return true; 358 return true;
359 } 359 }
360 360
361 // A tracing call will have either a |visitor| or a |m_field| argument. 361 // A tracing call will have either a |visitor| or a |m_field| argument.
362 // A registerWeakMembers call will have a |this| argument. 362 // A registerWeakMembers call will have a |this| argument.
363 if (call->getNumArgs() != 1) 363 if (call->getNumArgs() != 1)
364 return true; 364 return true;
365 Expr* arg = call->getArg(0); 365 Expr* arg = call->getArg(0);
366 366
367 if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) { 367 if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) {
368 // This could be a trace call of a base class, as explained in the
369 // comments of CheckTraceBaseCall().
370 if (CheckTraceBaseCall(call))
371 return true;
372
368 // If we find a call to registerWeakMembers which is unresolved we 373 // If we find a call to registerWeakMembers which is unresolved we
369 // unsoundly consider all weak members as traced. 374 // unsoundly consider all weak members as traced.
370 // TODO: Find out how to validate weak member tracing for unresolved call. 375 // TODO: Find out how to validate weak member tracing for unresolved call.
371 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) { 376 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) {
372 for (RecordInfo::Fields::iterator it = info_->GetFields().begin(); 377 for (RecordInfo::Fields::iterator it = info_->GetFields().begin();
373 it != info_->GetFields().end(); 378 it != info_->GetFields().end();
374 ++it) { 379 ++it) {
375 if (it->second.edge()->IsWeakMember()) 380 if (it->second.edge()->IsWeakMember())
376 it->second.MarkTraced(); 381 it->second.MarkTraced();
377 } 382 }
(...skipping 18 matching lines...) Expand all
396 delegates_to_traceimpl_ = true; 401 delegates_to_traceimpl_ = true;
397 return true; 402 return true;
398 } 403 }
399 } 404 }
400 405
401 CheckTraceBaseCall(call); 406 CheckTraceBaseCall(call);
402 return true; 407 return true;
403 } 408 }
404 409
405 private: 410 private:
406
407 CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) { 411 CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) {
408 NestedNameSpecifier* qual = expr->getQualifier(); 412 NestedNameSpecifier* qual = expr->getQualifier();
409 if (!qual) 413 if (!qual)
410 return 0; 414 return 0;
411 415
412 const Type* type = qual->getAsType(); 416 const Type* type = qual->getAsType();
413 if (!type) 417 if (!type)
414 return 0; 418 return 0;
415 419
416 return RecordInfo::GetDependentTemplatedDecl(*type); 420 return RecordInfo::GetDependentTemplatedDecl(*type);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 if (call->getNumArgs() == 2 && fn_name == kTraceName && 458 if (call->getNumArgs() == 2 && fn_name == kTraceName &&
455 tmpl->getName() == kTraceIfNeededName) { 459 tmpl->getName() == kTraceIfNeededName) {
456 FindFieldVisitor finder; 460 FindFieldVisitor finder;
457 finder.TraverseStmt(call->getArg(1)); 461 finder.TraverseStmt(call->getArg(1));
458 if (finder.field()) 462 if (finder.field())
459 FoundField(finder.field()); 463 FoundField(finder.field());
460 } 464 }
461 } 465 }
462 466
463 bool CheckTraceBaseCall(CallExpr* call) { 467 bool CheckTraceBaseCall(CallExpr* call) {
464 MemberExpr* callee = dyn_cast<MemberExpr>(call->getCallee()); 468 // Checks for "Base::trace(visitor)"-like calls.
465 if (!callee)
466 return false;
467 469
468 FunctionDecl* fn = dyn_cast<FunctionDecl>(callee->getMemberDecl()); 470 // Checking code for these two variables is shared among MemberExpr* case
469 if (!fn || !Config::IsTraceMethod(fn)) 471 // and UnresolvedMemberCase* case below.
470 return false; 472 //
473 // For example, if we've got "Base::trace(visitor)" as |call|,
474 // callee_record will be "Base", and func_name will be "trace".
475 CXXRecordDecl* callee_record = nullptr;
476 std::string func_name;
477
478 if (MemberExpr* callee = dyn_cast<MemberExpr>(call->getCallee())) {
479 if (!callee->hasQualifier())
480 return false;
481
482 FunctionDecl* trace_decl =
483 dyn_cast<FunctionDecl>(callee->getMemberDecl());
484 if (!trace_decl || !Config::IsTraceMethod(trace_decl))
485 return false;
486
487 const Type* type = callee->getQualifier()->getAsType();
488 if (!type)
489 return false;
490
491 callee_record = type->getAsCXXRecordDecl();
492 func_name = trace_decl->getName();
493 } else if (UnresolvedMemberExpr* callee =
494 dyn_cast<UnresolvedMemberExpr>(call->getCallee())) {
495 // Callee part may become unresolved if the type of the argument
496 // ("visitor") is a template parameter and the called function is
497 // overloaded (i.e. trace(Visitor*) and
498 // trace(InlinedGlobalMarkingVisitor)).
499 //
500 // Here, we try to find a function that looks like trace() from the
501 // candidate overloaded functions, and if we find one, we assume it is
502 // called here.
503
504 CXXMethodDecl* trace_decl = nullptr;
505 for (NamedDecl* named_decl : callee->decls()) {
506 if (CXXMethodDecl* method_decl = dyn_cast<CXXMethodDecl>(named_decl)) {
507 if (Config::IsTraceMethod(method_decl)) {
508 trace_decl = method_decl;
509 break;
510 }
511 }
512 }
513 if (!trace_decl)
514 return false;
515
516 // Check if the passed argument is named "visitor".
kouhei (in TOK) 2015/02/24 07:46:32 Nit: Should we document this change in CL desc?
Yuta Kitamura 2015/02/24 08:35:58 Done.
517 if (call->getNumArgs() != 1)
518 return false;
519 DeclRefExpr* arg = dyn_cast<DeclRefExpr>(call->getArg(0));
520 if (!arg || arg->getNameInfo().getAsString() != kVisitorVarName)
521 return false;
522
523 callee_record = trace_decl->getParent();
524 func_name = callee->getMemberName().getAsString();
525 }
471 526
472 if (trace_->getName() == kTraceImplName) { 527 if (trace_->getName() == kTraceImplName) {
473 if (fn->getName() != kTraceName) 528 if (func_name != kTraceName)
474 return false; 529 return false;
475 } else if (trace_->getName() == kTraceAfterDispatchImplName) { 530 } else if (trace_->getName() == kTraceAfterDispatchImplName) {
476 if (fn->getName() != kTraceAfterDispatchName) 531 if (func_name != kTraceAfterDispatchName)
477 return false; 532 return false;
478 } else { 533 } else {
479 // Currently, a manually dispatched class cannot have mixin bases (having 534 // Currently, a manually dispatched class cannot have mixin bases (having
480 // one would add a vtable which we explicitly check against). This means 535 // one would add a vtable which we explicitly check against). This means
481 // that we can only make calls to a trace method of the same name. Revisit 536 // that we can only make calls to a trace method of the same name. Revisit
482 // this if our mixin/vtable assumption changes. 537 // this if our mixin/vtable assumption changes.
483 if (fn->getName() != trace_->getName()) 538 if (func_name != trace_->getName())
484 return false; 539 return false;
485 } 540 }
486 541
487 CXXRecordDecl* decl = 0; 542 if (!callee_record)
488 if (callee && callee->hasQualifier()) { 543 return false;
489 if (const Type* type = callee->getQualifier()->getAsType()) 544 RecordInfo::Bases::iterator iter = info_->GetBases().find(callee_record);
490 decl = type->getAsCXXRecordDecl(); 545 if (iter == info_->GetBases().end())
491 }
492 if (!decl)
493 return false; 546 return false;
494 547
495 RecordInfo::Bases::iterator it = info_->GetBases().find(decl); 548 iter->second.MarkTraced();
496 if (it != info_->GetBases().end()) {
497 it->second.MarkTraced();
498 }
499
500 return true; 549 return true;
501 } 550 }
502 551
503 bool CheckTraceFieldCall(CXXMemberCallExpr* call) { 552 bool CheckTraceFieldCall(CXXMemberCallExpr* call) {
504 return CheckTraceFieldCall(call->getMethodDecl()->getNameAsString(), 553 return CheckTraceFieldCall(call->getMethodDecl()->getNameAsString(),
505 call->getRecordDecl(), 554 call->getRecordDecl(),
506 call->getArg(0)); 555 call->getArg(0));
507 } 556 }
508 557
509 bool CheckTraceFieldCall(string name, CXXRecordDecl* callee, Expr* arg) { 558 bool CheckTraceFieldCall(string name, CXXRecordDecl* callee, Expr* arg) {
(...skipping 1431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1941 1990
1942 private: 1991 private:
1943 BlinkGCPluginOptions options_; 1992 BlinkGCPluginOptions options_;
1944 }; 1993 };
1945 1994
1946 } // namespace 1995 } // namespace
1947 1996
1948 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( 1997 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X(
1949 "blink-gc-plugin", 1998 "blink-gc-plugin",
1950 "Check Blink GC invariants"); 1999 "Check Blink GC invariants");
OLDNEW
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/Config.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698