Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 #include "Config.h" | 5 #include "Config.h" |
| 6 #include "RecordInfo.h" | 6 #include "RecordInfo.h" |
| 7 | 7 |
| 8 using namespace clang; | 8 using namespace clang; |
| 9 using std::string; | 9 using std::string; |
| 10 | 10 |
| 11 RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache) | 11 RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache) |
| 12 : cache_(cache), | 12 : cache_(cache), |
| 13 record_(record), | 13 record_(record), |
| 14 name_(record->getName()), | 14 name_(record->getName()), |
| 15 fields_need_tracing_(TracingStatus::Unknown()), | 15 fields_need_tracing_(TracingStatus::Unknown()), |
| 16 bases_(0), | 16 bases_(0), |
| 17 fields_(0), | 17 fields_(0), |
| 18 is_stack_allocated_(kNotComputed), | 18 is_stack_allocated_(kNotComputed), |
| 19 is_non_newable_(kNotComputed), | 19 is_non_newable_(kNotComputed), |
| 20 is_only_placement_newable_(kNotComputed), | 20 is_only_placement_newable_(kNotComputed), |
| 21 does_need_finalization_(kNotComputed), | |
| 21 determined_trace_methods_(false), | 22 determined_trace_methods_(false), |
| 22 trace_method_(0), | 23 trace_method_(0), |
| 23 trace_dispatch_method_(0), | 24 trace_dispatch_method_(0), |
| 24 finalize_dispatch_method_(0), | 25 finalize_dispatch_method_(0), |
| 25 is_gc_derived_(false), | 26 is_gc_derived_(false), |
| 26 base_paths_(0) {} | 27 base_paths_(0) {} |
| 27 | 28 |
| 28 RecordInfo::~RecordInfo() { | 29 RecordInfo::~RecordInfo() { |
| 29 delete fields_; | 30 delete fields_; |
| 30 delete bases_; | 31 delete bases_; |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 it->second.info()->GetFinalizeDispatchMethod()) { | 394 it->second.info()->GetFinalizeDispatchMethod()) { |
| 394 assert(!finalize_dispatch_method_ && | 395 assert(!finalize_dispatch_method_ && |
| 395 "Multiple finalize dispatching methods"); | 396 "Multiple finalize dispatching methods"); |
| 396 finalize_dispatch_method_ = dispatch; | 397 finalize_dispatch_method_ = dispatch; |
| 397 } | 398 } |
| 398 } | 399 } |
| 399 } | 400 } |
| 400 | 401 |
| 401 // TODO: Add classes with a finalize() method that specialize FinalizerTrait. | 402 // TODO: Add classes with a finalize() method that specialize FinalizerTrait. |
| 402 bool RecordInfo::NeedsFinalization() { | 403 bool RecordInfo::NeedsFinalization() { |
| 403 return record_->hasNonTrivialDestructor(); | 404 if (does_need_finalization_ == kNotComputed) { |
| 405 // Rely on hasNonTrivialDestructor(), but if the only | |
| 406 // identifiable reason why it is true is the presence | |
| 407 // of a class with a safely ignorable class as a direct base, | |
| 408 // or such a class is being represented here, then it does | |
| 409 // not need finalization. | |
| 410 does_need_finalization_ = | |
| 411 record_->hasNonTrivialDestructor() ? kTrue : kFalse; | |
| 412 if (does_need_finalization_) { | |
|
zerny-chromium
2014/07/08 07:45:03
Add early exit instead:
if (!does_need_finalizati
sof
2014/07/08 08:47:05
Rephrased to use early returns instead of fallthro
| |
| 413 // Checking if processing a class with a safely-ignorable destructor. | |
| 414 NamespaceDecl* ns = | |
| 415 dyn_cast<NamespaceDecl>(record_->getDeclContext()); | |
| 416 if (ns && Config::HasIgnorableDestructor(ns->getName(), name_)) | |
| 417 does_need_finalization_ = kFalse; | |
|
zerny-chromium
2014/07/08 07:45:02
Do an early return in this block as well and avoid
| |
| 418 } | |
| 419 if (does_need_finalization_) { | |
| 420 CXXDestructorDecl* dtor = record_->getDestructor(); | |
| 421 bool is_candidate = !dtor || !dtor->isUserProvided(); | |
| 422 for (Fields::iterator it = GetFields().begin(); | |
| 423 is_candidate && it != GetFields().end(); | |
| 424 ++it) { | |
| 425 if (it->second.edge()->NeedsFinalization()) | |
| 426 is_candidate = false; | |
|
zerny-chromium
2014/07/08 07:45:03
This can just return does_need_finalization_ which
| |
| 427 } | |
| 428 | |
| 429 for (Bases::iterator it = GetBases().begin(); | |
| 430 is_candidate && it != GetBases().end(); | |
| 431 ++it) { | |
| 432 NamespaceDecl* ns = dyn_cast<NamespaceDecl>( | |
| 433 it->second.info()->record()->getDeclContext()); | |
| 434 if (ns && | |
|
zerny-chromium
2014/07/08 07:45:03
This check is not be needed here. The ignored case
sof
2014/07/08 08:47:05
I was hesitant to remove it, in case the complete
sof
2014/07/08 08:48:49
s/in case/in scope/. Need more coffee.
| |
| 435 Config::HasIgnorableDestructor(ns->getName(), | |
| 436 it->second.info()->name())) | |
| 437 continue; | |
| 438 if (it->second.info()->NeedsFinalization()) | |
| 439 is_candidate = false; | |
|
zerny-chromium
2014/07/08 07:45:02
Just return does_need_finalization_
| |
| 440 } | |
| 441 if (is_candidate) | |
|
zerny-chromium
2014/07/08 07:45:02
Here we can unconditionally set does_need_finaliza
| |
| 442 does_need_finalization_ = kFalse; | |
| 443 } | |
| 444 } | |
| 445 return does_need_finalization_; | |
| 404 } | 446 } |
| 405 | 447 |
| 406 // A class needs tracing if: | 448 // A class needs tracing if: |
| 407 // - it is allocated on the managed heap, | 449 // - it is allocated on the managed heap, |
| 408 // - it is derived from a class that needs tracing, or | 450 // - it is derived from a class that needs tracing, or |
| 409 // - it contains fields that need tracing. | 451 // - it contains fields that need tracing. |
| 410 // TODO: Defining NeedsTracing based on whether a class defines a trace method | 452 // TODO: Defining NeedsTracing based on whether a class defines a trace method |
| 411 // (of the proper signature) over approximates too much. The use of transition | 453 // (of the proper signature) over approximates too much. The use of transition |
| 412 // types causes some classes to have trace methods without them needing to be | 454 // types causes some classes to have trace methods without them needing to be |
| 413 // traced. | 455 // traced. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 506 edge->members().push_back(member); | 548 edge->members().push_back(member); |
| 507 } | 549 } |
| 508 // TODO: Handle the case where we fail to create an edge (eg, if the | 550 // TODO: Handle the case where we fail to create an edge (eg, if the |
| 509 // argument is a primitive type or just not fully known yet). | 551 // argument is a primitive type or just not fully known yet). |
| 510 } | 552 } |
| 511 return edge; | 553 return edge; |
| 512 } | 554 } |
| 513 | 555 |
| 514 return new Value(info); | 556 return new Value(info); |
| 515 } | 557 } |
| OLD | NEW |