| 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 #include "clang/Sema/Sema.h" | 7 #include "clang/Sema/Sema.h" |
| 8 | 8 |
| 9 using namespace clang; | 9 using namespace clang; |
| 10 using std::string; | 10 using std::string; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 | 106 |
| 107 return dyn_cast_or_null<CXXRecordDecl>(tmpl_decl->getTemplatedDecl()); | 107 return dyn_cast_or_null<CXXRecordDecl>(tmpl_decl->getTemplatedDecl()); |
| 108 } | 108 } |
| 109 | 109 |
| 110 void RecordInfo::walkBases() { | 110 void RecordInfo::walkBases() { |
| 111 // This traversal is akin to CXXRecordDecl::forallBases()'s, | 111 // This traversal is akin to CXXRecordDecl::forallBases()'s, |
| 112 // but without stepping over dependent bases -- these might also | 112 // but without stepping over dependent bases -- these might also |
| 113 // have a "GC base name", so are to be included and considered. | 113 // have a "GC base name", so are to be included and considered. |
| 114 SmallVector<const CXXRecordDecl*, 8> queue; | 114 SmallVector<const CXXRecordDecl*, 8> queue; |
| 115 | 115 |
| 116 const CXXRecordDecl *base_record = record(); | 116 const CXXRecordDecl* base_record = record(); |
| 117 while (true) { | 117 while (true) { |
| 118 for (const auto& it : base_record->bases()) { | 118 for (const auto& it : base_record->bases()) { |
| 119 const RecordType *type = it.getType()->getAs<RecordType>(); | 119 const RecordType* type = it.getType()->getAs<RecordType>(); |
| 120 CXXRecordDecl* base; | 120 CXXRecordDecl* base; |
| 121 if (!type) | 121 if (!type) |
| 122 base = GetDependentTemplatedDecl(*it.getType()); | 122 base = GetDependentTemplatedDecl(*it.getType()); |
| 123 else { | 123 else { |
| 124 base = cast_or_null<CXXRecordDecl>(type->getDecl()->getDefinition()); | 124 base = cast_or_null<CXXRecordDecl>(type->getDecl()->getDefinition()); |
| 125 if (base) | 125 if (base) |
| 126 queue.push_back(base); | 126 queue.push_back(base); |
| 127 } | 127 } |
| 128 if (!base) | 128 if (!base) |
| 129 continue; | 129 continue; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 // This is a mixin if all GC bases are mixins. | 164 // This is a mixin if all GC bases are mixins. |
| 165 return true; | 165 return true; |
| 166 } | 166 } |
| 167 | 167 |
| 168 // Test if a record is allocated on the managed heap. | 168 // Test if a record is allocated on the managed heap. |
| 169 bool RecordInfo::IsGCAllocated() { | 169 bool RecordInfo::IsGCAllocated() { |
| 170 return IsGCDerived() || IsHeapAllocatedCollection(); | 170 return IsGCDerived() || IsHeapAllocatedCollection(); |
| 171 } | 171 } |
| 172 | 172 |
| 173 bool RecordInfo::IsEagerlyFinalized() { | 173 bool RecordInfo::IsEagerlyFinalized() { |
| 174 if (is_eagerly_finalized_ == kNotComputed) { | 174 if (is_eagerly_finalized_ != kNotComputed) |
| 175 is_eagerly_finalized_ = kFalse; | 175 return is_eagerly_finalized_; |
| 176 if (IsGCFinalized()) { | 176 |
| 177 for (Decl* decl : record_->decls()) { | 177 is_eagerly_finalized_ = kFalse; |
| 178 if (TypedefDecl* typedef_decl = dyn_cast<TypedefDecl>(decl)) { | 178 if (!IsGCFinalized()) |
| 179 if (typedef_decl->getNameAsString() == kIsEagerlyFinalizedName) { | 179 return is_eagerly_finalized_; |
| 180 is_eagerly_finalized_ = kTrue; | 180 |
| 181 break; | 181 for (Decl* decl : record_->decls()) { |
| 182 } | 182 if (TypedefDecl* typedef_decl = dyn_cast<TypedefDecl>(decl)) { |
| 183 } | 183 if (typedef_decl->getNameAsString() != kIsEagerlyFinalizedName) |
| 184 } | 184 continue; |
| 185 is_eagerly_finalized_ = kTrue; |
| 186 break; |
| 185 } | 187 } |
| 186 } | 188 } |
| 187 return is_eagerly_finalized_; | 189 return is_eagerly_finalized_; |
| 188 } | 190 } |
| 189 | 191 |
| 190 bool RecordInfo::HasDefinition() { | 192 bool RecordInfo::HasDefinition() { |
| 191 return record_->hasDefinition(); | 193 return record_->hasDefinition(); |
| 192 } | 194 } |
| 193 | 195 |
| 194 RecordInfo* RecordCache::Lookup(CXXRecordDecl* record) { | 196 RecordInfo* RecordCache::Lookup(CXXRecordDecl* record) { |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 if (!record_->hasDefinition()) | 409 if (!record_->hasDefinition()) |
| 408 return fields; | 410 return fields; |
| 409 TracingStatus fields_status = TracingStatus::Unneeded(); | 411 TracingStatus fields_status = TracingStatus::Unneeded(); |
| 410 for (RecordDecl::field_iterator it = record_->field_begin(); | 412 for (RecordDecl::field_iterator it = record_->field_begin(); |
| 411 it != record_->field_end(); | 413 it != record_->field_end(); |
| 412 ++it) { | 414 ++it) { |
| 413 FieldDecl* field = *it; | 415 FieldDecl* field = *it; |
| 414 // Ignore fields annotated with the GC_PLUGIN_IGNORE macro. | 416 // Ignore fields annotated with the GC_PLUGIN_IGNORE macro. |
| 415 if (Config::IsIgnoreAnnotated(field)) | 417 if (Config::IsIgnoreAnnotated(field)) |
| 416 continue; | 418 continue; |
| 417 if (Edge* edge = CreateEdge(field->getType().getTypePtrOrNull())) { | 419 // Check if the unexpanded type should be recorded; needed |
| 420 // to track iterator aliases only |
| 421 const Type* unexpandedType = field->getType().getSplitUnqualifiedType().Ty; |
| 422 Edge* edge = CreateEdgeFromOriginalType(unexpandedType); |
| 423 if (!edge) |
| 424 edge = CreateEdge(field->getType().getTypePtrOrNull()); |
| 425 if (edge) { |
| 418 fields_status = fields_status.LUB(edge->NeedsTracing(Edge::kRecursive)); | 426 fields_status = fields_status.LUB(edge->NeedsTracing(Edge::kRecursive)); |
| 419 fields->insert(std::make_pair(field, FieldPoint(field, edge))); | 427 fields->insert(std::make_pair(field, FieldPoint(field, edge))); |
| 420 } | 428 } |
| 421 } | 429 } |
| 422 fields_need_tracing_ = fields_status; | 430 fields_need_tracing_ = fields_status; |
| 423 return fields; | 431 return fields; |
| 424 } | 432 } |
| 425 | 433 |
| 426 void RecordInfo::DetermineTracingMethods() { | 434 void RecordInfo::DetermineTracingMethods() { |
| 427 if (determined_trace_methods_) | 435 if (determined_trace_methods_) |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 static bool isInStdNamespace(clang::Sema& sema, NamespaceDecl* ns) | 568 static bool isInStdNamespace(clang::Sema& sema, NamespaceDecl* ns) |
| 561 { | 569 { |
| 562 while (ns) { | 570 while (ns) { |
| 563 if (sema.getStdNamespace()->InEnclosingNamespaceSetOf(ns)) | 571 if (sema.getStdNamespace()->InEnclosingNamespaceSetOf(ns)) |
| 564 return true; | 572 return true; |
| 565 ns = dyn_cast<NamespaceDecl>(ns->getParent()); | 573 ns = dyn_cast<NamespaceDecl>(ns->getParent()); |
| 566 } | 574 } |
| 567 return false; | 575 return false; |
| 568 } | 576 } |
| 569 | 577 |
| 578 Edge* RecordInfo::CreateEdgeFromOriginalType(const Type* type) { |
| 579 if (!type) |
| 580 return nullptr; |
| 581 |
| 582 // look for "typedef ... iterator;" |
| 583 if (!isa<ElaboratedType>(type)) |
| 584 return nullptr; |
| 585 const ElaboratedType* elaboratedType = cast<ElaboratedType>(type); |
| 586 if (!isa<TypedefType>(elaboratedType->getNamedType())) |
| 587 return nullptr; |
| 588 const TypedefType* typedefType = |
| 589 cast<TypedefType>(elaboratedType->getNamedType()); |
| 590 std::string typeName = typedefType->getDecl()->getNameAsString(); |
| 591 if (!Config::IsIterator(typeName)) |
| 592 return nullptr; |
| 593 RecordInfo* info = |
| 594 cache_->Lookup(elaboratedType->getQualifier()->getAsType()); |
| 595 |
| 596 bool on_heap = false; |
| 597 bool is_unsafe = false; |
| 598 // Silently handle unknown types; the on-heap collection types will |
| 599 // have to be in scope for the declaration to compile, though. |
| 600 if (info) { |
| 601 is_unsafe = Config::IsGCCollectionWithUnsafeIterator(info->name()); |
| 602 // Don't mark iterator as being on the heap if it is not supported. |
| 603 on_heap = !is_unsafe && Config::IsGCCollection(info->name()); |
| 604 } |
| 605 return new Iterator(info, on_heap, is_unsafe); |
| 606 } |
| 607 |
| 570 Edge* RecordInfo::CreateEdge(const Type* type) { | 608 Edge* RecordInfo::CreateEdge(const Type* type) { |
| 571 if (!type) { | 609 if (!type) { |
| 572 return 0; | 610 return 0; |
| 573 } | 611 } |
| 574 | 612 |
| 575 if (type->isPointerType() || type->isReferenceType()) { | 613 if (type->isPointerType() || type->isReferenceType()) { |
| 576 if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull())) | 614 if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull())) |
| 577 return new RawPtr(ptr, type->isReferenceType()); | 615 return new RawPtr(ptr, type->isReferenceType()); |
| 578 return 0; | 616 return 0; |
| 579 } | 617 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 edge->members().push_back(member); | 693 edge->members().push_back(member); |
| 656 } | 694 } |
| 657 // TODO: Handle the case where we fail to create an edge (eg, if the | 695 // TODO: Handle the case where we fail to create an edge (eg, if the |
| 658 // argument is a primitive type or just not fully known yet). | 696 // argument is a primitive type or just not fully known yet). |
| 659 } | 697 } |
| 660 return edge; | 698 return edge; |
| 661 } | 699 } |
| 662 | 700 |
| 663 return new Value(info); | 701 return new Value(info); |
| 664 } | 702 } |
| OLD | NEW |