| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/become.h" | 10 #include "vm/become.h" |
| (...skipping 5138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5149 for (intptr_t i = 0; i < num_types; i++) { | 5149 for (intptr_t i = 0; i < num_types; i++) { |
| 5150 type = TypeAt(i); | 5150 type = TypeAt(i); |
| 5151 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); | 5151 pieces.SetAt(i, String::Handle(zone, type.EnumerateURIs())); |
| 5152 } | 5152 } |
| 5153 return String::ConcatAll(pieces); | 5153 return String::ConcatAll(pieces); |
| 5154 } | 5154 } |
| 5155 | 5155 |
| 5156 | 5156 |
| 5157 const char* TypeArguments::ToCString() const { | 5157 const char* TypeArguments::ToCString() const { |
| 5158 if (IsNull()) { | 5158 if (IsNull()) { |
| 5159 return "NULL TypeArguments"; | 5159 return "TypeArguments: null"; |
| 5160 } | 5160 } |
| 5161 Zone* zone = Thread::Current()->zone(); | 5161 Zone* zone = Thread::Current()->zone(); |
| 5162 const char* prev_cstr = OS::SCreate(zone, "TypeArguments: (%" Pd ")", | 5162 const char* prev_cstr = OS::SCreate(zone, "TypeArguments: (%" Pd ")", |
| 5163 Smi::Value(raw_ptr()->hash_)); | 5163 Smi::Value(raw_ptr()->hash_)); |
| 5164 for (int i = 0; i < Length(); i++) { | 5164 for (int i = 0; i < Length(); i++) { |
| 5165 const AbstractType& type_at = AbstractType::Handle(zone, TypeAt(i)); | 5165 const AbstractType& type_at = AbstractType::Handle(zone, TypeAt(i)); |
| 5166 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); | 5166 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString(); |
| 5167 char* chars = OS::SCreate(zone, "%s [%s]", prev_cstr, type_cstr); | 5167 char* chars = OS::SCreate(zone, "%s [%s]", prev_cstr, type_cstr); |
| 5168 prev_cstr = chars; | 5168 prev_cstr = chars; |
| 5169 } | 5169 } |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5550 // argument vector. Therefore, we only need to set the type arguments | 5550 // argument vector. Therefore, we only need to set the type arguments |
| 5551 // matching the type parameters here. | 5551 // matching the type parameters here. |
| 5552 // In case of a function type alias, the function owner is the alias class, | 5552 // In case of a function type alias, the function owner is the alias class, |
| 5553 // i.e. the typedef. The signature type is therefore parameterized according | 5553 // i.e. the typedef. The signature type is therefore parameterized according |
| 5554 // to the alias class declaration, even if the function type is not generic. | 5554 // to the alias class declaration, even if the function type is not generic. |
| 5555 // Otherwise, if the function is static or if its signature type is | 5555 // Otherwise, if the function is static or if its signature type is |
| 5556 // non-generic, i.e. it does not depend on any type parameter of the owner | 5556 // non-generic, i.e. it does not depend on any type parameter of the owner |
| 5557 // class, then the signature type is not parameterized, although the owner | 5557 // class, then the signature type is not parameterized, although the owner |
| 5558 // class may be. In this case, the scope class of the function type is reset | 5558 // class may be. In this case, the scope class of the function type is reset |
| 5559 // to _Closure class as well as the owner of the signature function. | 5559 // to _Closure class as well as the owner of the signature function. |
| 5560 // With the introduction of generic functions, we may reach here before the |
| 5561 // function type parameters have been resolved. Therefore, we cannot yet |
| 5562 // check whether the function type has an instantiated signature. |
| 5563 // We will do it later when resolving the type. |
| 5560 Class& scope_class = Class::Handle(Owner()); | 5564 Class& scope_class = Class::Handle(Owner()); |
| 5561 if (!scope_class.IsTypedefClass() && | 5565 if (!scope_class.IsTypedefClass() && |
| 5562 (is_static() || !scope_class.IsGeneric() || | 5566 (is_static() || !scope_class.IsGeneric())) { |
| 5563 HasInstantiatedSignature())) { | |
| 5564 scope_class = Isolate::Current()->object_store()->closure_class(); | 5567 scope_class = Isolate::Current()->object_store()->closure_class(); |
| 5565 if (IsSignatureFunction()) { | 5568 if (IsSignatureFunction()) { |
| 5566 set_owner(scope_class); | 5569 set_owner(scope_class); |
| 5567 set_token_pos(TokenPosition::kNoSource); | 5570 set_token_pos(TokenPosition::kNoSource); |
| 5568 } | 5571 } |
| 5569 } | 5572 } |
| 5573 // TODO(regis): With generic functions, this type is not only parameterized |
| 5574 // with the type parameters of the scope class, but also with those of all |
| 5575 // enclosing generic functions, which may not even have been parsed at this |
| 5576 // point. What actually matters is that a signature type can be expressed in |
| 5577 // a right-hand side type test by name. This is only possible with a typedef |
| 5578 // and the free variables are only the type parameters of the typedef. |
| 5570 const TypeArguments& signature_type_arguments = | 5579 const TypeArguments& signature_type_arguments = |
| 5571 TypeArguments::Handle(scope_class.type_parameters()); | 5580 TypeArguments::Handle(scope_class.type_parameters()); |
| 5572 // Return the still unfinalized signature type. | 5581 // Return the still unfinalized signature type. |
| 5573 type = Type::New(scope_class, signature_type_arguments, token_pos()); | 5582 type = Type::New(scope_class, signature_type_arguments, token_pos()); |
| 5574 type.set_signature(*this); | 5583 type.set_signature(*this); |
| 5575 SetSignatureType(type); | 5584 SetSignatureType(type); |
| 5576 } | 5585 } |
| 5577 return type.raw(); | 5586 return type.raw(); |
| 5578 } | 5587 } |
| 5579 | 5588 |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5803 const Array& pair = Array::Handle(Array::New(2, Heap::kOld)); | 5812 const Array& pair = Array::Handle(Array::New(2, Heap::kOld)); |
| 5804 pair.SetAt(0, value); | 5813 pair.SetAt(0, value); |
| 5805 // pair[1] will be the implicit closure function if needed. | 5814 // pair[1] will be the implicit closure function if needed. |
| 5806 set_data(pair); | 5815 set_data(pair); |
| 5807 } | 5816 } |
| 5808 | 5817 |
| 5809 | 5818 |
| 5810 void Function::set_result_type(const AbstractType& value) const { | 5819 void Function::set_result_type(const AbstractType& value) const { |
| 5811 ASSERT(!value.IsNull()); | 5820 ASSERT(!value.IsNull()); |
| 5812 StorePointer(&raw_ptr()->result_type_, value.raw()); | 5821 StorePointer(&raw_ptr()->result_type_, value.raw()); |
| 5822 if (value.IsFunctionType() && !value.IsResolved()) { |
| 5823 // The unresolved function result type may refer to this |
| 5824 // function's type parameters. Change its parent function. |
| 5825 const Function& result_signature_function = |
| 5826 Function::Handle(Type::Cast(value).signature()); |
| 5827 result_signature_function.set_parent_function(*this); |
| 5828 } |
| 5813 } | 5829 } |
| 5814 | 5830 |
| 5815 | 5831 |
| 5816 RawAbstractType* Function::ParameterTypeAt(intptr_t index) const { | 5832 RawAbstractType* Function::ParameterTypeAt(intptr_t index) const { |
| 5817 const Array& parameter_types = Array::Handle(raw_ptr()->parameter_types_); | 5833 const Array& parameter_types = Array::Handle(raw_ptr()->parameter_types_); |
| 5818 return AbstractType::RawCast(parameter_types.At(index)); | 5834 return AbstractType::RawCast(parameter_types.At(index)); |
| 5819 } | 5835 } |
| 5820 | 5836 |
| 5821 | 5837 |
| 5822 void Function::SetParameterTypeAt(intptr_t index, | 5838 void Function::SetParameterTypeAt(intptr_t index, |
| (...skipping 1395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7218 " expecting 0x%08x found 0x%08x\n", | 7234 " expecting 0x%08x found 0x%08x\n", |
| 7219 ToFullyQualifiedCString(), fp, SourceFingerprint()); | 7235 ToFullyQualifiedCString(), fp, SourceFingerprint()); |
| 7220 return false; | 7236 return false; |
| 7221 } | 7237 } |
| 7222 } | 7238 } |
| 7223 return true; | 7239 return true; |
| 7224 } | 7240 } |
| 7225 | 7241 |
| 7226 | 7242 |
| 7227 const char* Function::ToCString() const { | 7243 const char* Function::ToCString() const { |
| 7244 if (IsNull()) { |
| 7245 return "Function: null"; |
| 7246 } |
| 7228 const char* static_str = is_static() ? " static" : ""; | 7247 const char* static_str = is_static() ? " static" : ""; |
| 7229 const char* abstract_str = is_abstract() ? " abstract" : ""; | 7248 const char* abstract_str = is_abstract() ? " abstract" : ""; |
| 7230 const char* kind_str = NULL; | 7249 const char* kind_str = NULL; |
| 7231 const char* const_str = is_const() ? " const" : ""; | 7250 const char* const_str = is_const() ? " const" : ""; |
| 7232 switch (kind()) { | 7251 switch (kind()) { |
| 7233 case RawFunction::kRegularFunction: | 7252 case RawFunction::kRegularFunction: |
| 7234 case RawFunction::kClosureFunction: | 7253 case RawFunction::kClosureFunction: |
| 7235 case RawFunction::kGetterFunction: | 7254 case RawFunction::kGetterFunction: |
| 7236 case RawFunction::kSetterFunction: | 7255 case RawFunction::kSetterFunction: |
| 7237 kind_str = ""; | 7256 kind_str = ""; |
| (...skipping 5128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12366 " begin=%-3d end=%-3d name=%s\n", | 12385 " begin=%-3d end=%-3d name=%s\n", |
| 12367 i, LocalVarDescriptors::KindToCString(kind), info.scope_id, index, | 12386 i, LocalVarDescriptors::KindToCString(kind), info.scope_id, index, |
| 12368 static_cast<int>(info.begin_pos.Pos()), | 12387 static_cast<int>(info.begin_pos.Pos()), |
| 12369 static_cast<int>(info.end_pos.Pos()), var_name.ToCString()); | 12388 static_cast<int>(info.end_pos.Pos()), var_name.ToCString()); |
| 12370 } | 12389 } |
| 12371 } | 12390 } |
| 12372 | 12391 |
| 12373 | 12392 |
| 12374 const char* LocalVarDescriptors::ToCString() const { | 12393 const char* LocalVarDescriptors::ToCString() const { |
| 12375 if (IsNull()) { | 12394 if (IsNull()) { |
| 12376 return "LocalVarDescriptors(NULL)"; | 12395 return "LocalVarDescriptors: null"; |
| 12377 } | 12396 } |
| 12378 if (Length() == 0) { | 12397 if (Length() == 0) { |
| 12379 return "empty LocalVarDescriptors"; | 12398 return "empty LocalVarDescriptors"; |
| 12380 } | 12399 } |
| 12381 intptr_t len = 1; // Trailing '\0'. | 12400 intptr_t len = 1; // Trailing '\0'. |
| 12382 String& var_name = String::Handle(); | 12401 String& var_name = String::Handle(); |
| 12383 for (intptr_t i = 0; i < Length(); i++) { | 12402 for (intptr_t i = 0; i < Length(); i++) { |
| 12384 RawLocalVarDescriptors::VarInfo info; | 12403 RawLocalVarDescriptors::VarInfo info; |
| 12385 var_name = GetName(i); | 12404 var_name = GetName(i); |
| 12386 GetInfo(i, &info); | 12405 GetInfo(i, &info); |
| (...skipping 2394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14781 NoSafepointScope no_safepoint; | 14800 NoSafepointScope no_safepoint; |
| 14782 result ^= raw; | 14801 result ^= raw; |
| 14783 result.set_num_variables(num_variables); | 14802 result.set_num_variables(num_variables); |
| 14784 } | 14803 } |
| 14785 return result.raw(); | 14804 return result.raw(); |
| 14786 } | 14805 } |
| 14787 | 14806 |
| 14788 | 14807 |
| 14789 const char* Context::ToCString() const { | 14808 const char* Context::ToCString() const { |
| 14790 if (IsNull()) { | 14809 if (IsNull()) { |
| 14791 return "Context (Null)"; | 14810 return "Context: null"; |
| 14792 } | 14811 } |
| 14793 Zone* zone = Thread::Current()->zone(); | 14812 Zone* zone = Thread::Current()->zone(); |
| 14794 const Context& parent_ctx = Context::Handle(parent()); | 14813 const Context& parent_ctx = Context::Handle(parent()); |
| 14795 if (parent_ctx.IsNull()) { | 14814 if (parent_ctx.IsNull()) { |
| 14796 return zone->PrintToString("Context num_variables: %" Pd "", | 14815 return zone->PrintToString("Context num_variables: %" Pd "", |
| 14797 num_variables()); | 14816 num_variables()); |
| 14798 } else { | 14817 } else { |
| 14799 const char* parent_str = parent_ctx.ToCString(); | 14818 const char* parent_str = parent_ctx.ToCString(); |
| 14800 return zone->PrintToString("Context num_variables: %" Pd " parent:{ %s }", | 14819 return zone->PrintToString("Context num_variables: %" Pd " parent:{ %s }", |
| 14801 num_variables(), parent_str); | 14820 num_variables(), parent_str); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15194 *test_result ^= data.At(data_pos + kTestResult); | 15213 *test_result ^= data.At(data_pos + kTestResult); |
| 15195 } | 15214 } |
| 15196 | 15215 |
| 15197 | 15216 |
| 15198 const char* SubtypeTestCache::ToCString() const { | 15217 const char* SubtypeTestCache::ToCString() const { |
| 15199 return "SubtypeTestCache"; | 15218 return "SubtypeTestCache"; |
| 15200 } | 15219 } |
| 15201 | 15220 |
| 15202 | 15221 |
| 15203 const char* Error::ToErrorCString() const { | 15222 const char* Error::ToErrorCString() const { |
| 15223 if (IsNull()) { |
| 15224 return "Error: null"; |
| 15225 } |
| 15204 UNREACHABLE(); | 15226 UNREACHABLE(); |
| 15205 return "Internal Error"; | 15227 return "Error"; |
| 15206 } | 15228 } |
| 15207 | 15229 |
| 15208 | 15230 |
| 15209 const char* Error::ToCString() const { | 15231 const char* Error::ToCString() const { |
| 15232 if (IsNull()) { |
| 15233 return "Error: null"; |
| 15234 } |
| 15210 // Error is an abstract class. We should never reach here. | 15235 // Error is an abstract class. We should never reach here. |
| 15211 UNREACHABLE(); | 15236 UNREACHABLE(); |
| 15212 return "Error"; | 15237 return "Error"; |
| 15213 } | 15238 } |
| 15214 | 15239 |
| 15215 | 15240 |
| 15216 RawApiError* ApiError::New() { | 15241 RawApiError* ApiError::New() { |
| 15217 ASSERT(Object::api_error_class() != Class::null()); | 15242 ASSERT(Object::api_error_class() != Class::null()); |
| 15218 RawObject* raw = Object::Allocate(ApiError::kClassId, | 15243 RawObject* raw = Object::Allocate(ApiError::kClassId, |
| 15219 ApiError::InstanceSize(), Heap::kOld); | 15244 ApiError::InstanceSize(), Heap::kOld); |
| (...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16695 | 16720 |
| 16696 | 16721 |
| 16697 intptr_t AbstractType::Hash() const { | 16722 intptr_t AbstractType::Hash() const { |
| 16698 // AbstractType is an abstract class. | 16723 // AbstractType is an abstract class. |
| 16699 UNREACHABLE(); | 16724 UNREACHABLE(); |
| 16700 return 0; | 16725 return 0; |
| 16701 } | 16726 } |
| 16702 | 16727 |
| 16703 | 16728 |
| 16704 const char* AbstractType::ToCString() const { | 16729 const char* AbstractType::ToCString() const { |
| 16730 if (IsNull()) { |
| 16731 return "AbstractType: null"; |
| 16732 } |
| 16705 // AbstractType is an abstract class. | 16733 // AbstractType is an abstract class. |
| 16706 UNREACHABLE(); | 16734 UNREACHABLE(); |
| 16707 return "AbstractType"; | 16735 return "AbstractType"; |
| 16708 } | 16736 } |
| 16709 | 16737 |
| 16710 | 16738 |
| 16711 RawType* Type::NullType() { | 16739 RawType* Type::NullType() { |
| 16712 return Isolate::Current()->object_store()->null_type(); | 16740 return Isolate::Current()->object_store()->null_type(); |
| 16713 } | 16741 } |
| 16714 | 16742 |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16954 intptr_t num_type_args = args.Length(); | 16982 intptr_t num_type_args = args.Length(); |
| 16955 intptr_t len = num_type_args; // Check the full vector of type args. | 16983 intptr_t len = num_type_args; // Check the full vector of type args. |
| 16956 ASSERT(num_type_args > 0); | 16984 ASSERT(num_type_args > 0); |
| 16957 // This type is not instantiated if it refers to type parameters. | 16985 // This type is not instantiated if it refers to type parameters. |
| 16958 // Although this type may still be unresolved, the type parameters it may | 16986 // Although this type may still be unresolved, the type parameters it may |
| 16959 // refer to are resolved by definition. We can therefore return the correct | 16987 // refer to are resolved by definition. We can therefore return the correct |
| 16960 // result even for an unresolved type. We just need to look at all type | 16988 // result even for an unresolved type. We just need to look at all type |
| 16961 // arguments and not just at the type parameters. | 16989 // arguments and not just at the type parameters. |
| 16962 if (HasResolvedTypeClass()) { | 16990 if (HasResolvedTypeClass()) { |
| 16963 const Class& cls = Class::Handle(type_class()); | 16991 const Class& cls = Class::Handle(type_class()); |
| 16964 len = cls.NumTypeArguments(); | |
| 16965 ASSERT(num_type_args >= len); // The vector may be longer than necessary. | |
| 16966 num_type_args = len; | |
| 16967 len = cls.NumTypeParameters(); // Check the type parameters only. | 16992 len = cls.NumTypeParameters(); // Check the type parameters only. |
| 16968 } | 16993 } |
| 16969 return (len == 0) || args.IsSubvectorInstantiated(num_type_args - len, len); | 16994 return (len == 0) || args.IsSubvectorInstantiated(num_type_args - len, len); |
| 16970 } | 16995 } |
| 16971 | 16996 |
| 16972 | 16997 |
| 16973 RawAbstractType* Type::InstantiateFrom( | 16998 RawAbstractType* Type::InstantiateFrom( |
| 16974 const TypeArguments& instantiator_type_arguments, | 16999 const TypeArguments& instantiator_type_arguments, |
| 16975 Error* bound_error, | 17000 Error* bound_error, |
| 16976 TrailPtr instantiation_trail, | 17001 TrailPtr instantiation_trail, |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17605 | 17630 |
| 17606 | 17631 |
| 17607 void Type::set_type_state(int8_t state) const { | 17632 void Type::set_type_state(int8_t state) const { |
| 17608 ASSERT((state >= RawType::kAllocated) && | 17633 ASSERT((state >= RawType::kAllocated) && |
| 17609 (state <= RawType::kFinalizedUninstantiated)); | 17634 (state <= RawType::kFinalizedUninstantiated)); |
| 17610 StoreNonPointer(&raw_ptr()->type_state_, state); | 17635 StoreNonPointer(&raw_ptr()->type_state_, state); |
| 17611 } | 17636 } |
| 17612 | 17637 |
| 17613 | 17638 |
| 17614 const char* Type::ToCString() const { | 17639 const char* Type::ToCString() const { |
| 17640 if (IsNull()) { |
| 17641 return "Type: null"; |
| 17642 } |
| 17615 Zone* zone = Thread::Current()->zone(); | 17643 Zone* zone = Thread::Current()->zone(); |
| 17616 const char* unresolved = IsResolved() ? "" : "Unresolved "; | 17644 const char* unresolved = IsResolved() ? "" : "Unresolved "; |
| 17617 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); | 17645 const TypeArguments& type_args = TypeArguments::Handle(zone, arguments()); |
| 17618 const char* args_cstr = type_args.IsNull() ? "null" : type_args.ToCString(); | 17646 const char* args_cstr = type_args.IsNull() ? "null" : type_args.ToCString(); |
| 17619 Class& cls = Class::Handle(zone); | 17647 Class& cls = Class::Handle(zone); |
| 17620 const char* class_name; | 17648 const char* class_name; |
| 17621 if (HasResolvedTypeClass()) { | 17649 if (HasResolvedTypeClass()) { |
| 17622 cls = type_class(); | 17650 cls = type_class(); |
| 17623 class_name = String::Handle(zone, cls.Name()).ToCString(); | 17651 class_name = String::Handle(zone, cls.Name()).ToCString(); |
| 17624 } else { | 17652 } else { |
| (...skipping 4266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21891 result ^= raw; | 21919 result ^= raw; |
| 21892 result.SetLength(0); | 21920 result.SetLength(0); |
| 21893 result.SetData(array); | 21921 result.SetData(array); |
| 21894 } | 21922 } |
| 21895 return result.raw(); | 21923 return result.raw(); |
| 21896 } | 21924 } |
| 21897 | 21925 |
| 21898 | 21926 |
| 21899 const char* GrowableObjectArray::ToCString() const { | 21927 const char* GrowableObjectArray::ToCString() const { |
| 21900 if (IsNull()) { | 21928 if (IsNull()) { |
| 21901 return "_GrowableList NULL"; | 21929 return "_GrowableList: null"; |
| 21902 } | 21930 } |
| 21903 return OS::SCreate(Thread::Current()->zone(), | 21931 return OS::SCreate(Thread::Current()->zone(), |
| 21904 "Instance(length:%" Pd ") of '_GrowableList'", Length()); | 21932 "Instance(length:%" Pd ") of '_GrowableList'", Length()); |
| 21905 } | 21933 } |
| 21906 | 21934 |
| 21907 | 21935 |
| 21908 // Equivalent to Dart's operator "==" and hashCode. | 21936 // Equivalent to Dart's operator "==" and hashCode. |
| 21909 class DefaultHashTraits { | 21937 class DefaultHashTraits { |
| 21910 public: | 21938 public: |
| 21911 static const char* Name() { return "DefaultHashTraits"; } | 21939 static const char* Name() { return "DefaultHashTraits"; } |
| (...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22999 return UserTag::null(); | 23027 return UserTag::null(); |
| 23000 } | 23028 } |
| 23001 | 23029 |
| 23002 | 23030 |
| 23003 const char* UserTag::ToCString() const { | 23031 const char* UserTag::ToCString() const { |
| 23004 const String& tag_label = String::Handle(label()); | 23032 const String& tag_label = String::Handle(label()); |
| 23005 return tag_label.ToCString(); | 23033 return tag_label.ToCString(); |
| 23006 } | 23034 } |
| 23007 | 23035 |
| 23008 } // namespace dart | 23036 } // namespace dart |
| OLD | NEW |