1 // Copyright (C) 2011 The Android Open Source Project 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 1. Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // 2. Redistributions in binary form must reproduce the above copyright 10 // notice, this list of conditions and the following disclaimer in the 11 // documentation and/or other materials provided with the distribution. 12 // 3. Neither the name of the project nor the names of its contributors 13 // may be used to endorse or promote products derived from this software 14 // without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 // ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 // SUCH DAMAGE. 27 // 28 // vmi_class_type_info.cc: Methods for __vmi_class_type_info. 29 30 #include <cassert> 31 #include "cxxabi_defines.h" 32 33 namespace __cxxabiv1 34 { 35 __vmi_class_type_info::~__vmi_class_type_info() 36 { 37 } 38 39 bool __vmi_class_type_info::walk_to(const __class_type_info* base_type, 40 void*& adjustedPtr, 41 __UpcastInfo& info) const { 42 if (self_class_type_match(base_type, adjustedPtr, info)) { 43 return true; 44 } 45 46 for (size_t i = 0, e = __base_count; i != e; ++i) { 47 __UpcastInfo cur_base_info(this); 48 void* cur_base_ptr = adjustedPtr; 49 const __class_type_info* cur_base_type = __base_info[i].__base_type; 50 long cur_base_offset = __base_info[i].offset(); 51 bool cur_base_is_virtual = __base_info[i].is_virtual(); 52 bool cur_base_is_public = __base_info[i].is_public(); 53 54 // Adjust cur_base_ptr to correct position 55 if (cur_base_ptr) { 56 if (cur_base_is_virtual) { 57 void* vtable = *reinterpret_cast<void**>(cur_base_ptr); 58 cur_base_offset = *reinterpret_cast<long*>( 59 static_cast<uint8_t*>(vtable) + cur_base_offset); 60 } 61 cur_base_ptr = static_cast<uint8_t*>(cur_base_ptr) + cur_base_offset; 62 } 63 64 65 if (!cur_base_is_public && 66 (info.premier_flags & __non_diamond_repeat_mask) == 0) { 67 continue; 68 } 69 70 71 /*** Body ***/ 72 73 74 if (!cur_base_type->walk_to(base_type, cur_base_ptr, cur_base_info)) { 75 continue; 76 } 77 78 79 /*** Post ***/ 80 81 82 if (!cur_base_is_public) { // Narrow public attribute 83 cur_base_info.status = __UpcastInfo::has_ambig_or_not_public; 84 } 85 86 if (cur_base_is_virtual) { 87 // We can make sure it may not conflict from now. 88 cur_base_info.nullobj_may_conflict = false; 89 } 90 91 // First time found 92 if (info.base_type == NULL && cur_base_info.base_type != NULL) { 93 info = cur_base_info; 94 if (info.status == __UpcastInfo::has_public_contained && 95 (__flags & __non_diamond_repeat_mask) == 0) { 96 // Don't need to call deeper recursively since 97 // it has no non-diamond repeat superclass 98 99 // Return true only means we found one. 100 // It didn't guarantee it is the unique public one. We need to check 101 // publicity in the recursive caller-side. 102 // 103 // Why we don't just return false? No, we can't. 104 // Return false will make the caller ignore this base class directly, 105 // but we need some information kept in the info. 106 return true; 107 } 108 continue; 109 } 110 111 assert (info.base_type != NULL && cur_base_info.base_type != NULL); 112 113 // Found twice, but different types 114 if (*cur_base_info.base_type != *info.base_type) { 115 info.status = __UpcastInfo::has_ambig_or_not_public; 116 return true; 117 } 118 119 // Found twice, but null object 120 if (!info.adjustedPtr && !cur_base_info.adjustedPtr) { 121 if (info.nullobj_may_conflict || cur_base_info.nullobj_may_conflict) { 122 info.status = __UpcastInfo::has_ambig_or_not_public; 123 return true; 124 } 125 126 if (*info.base_type == *cur_base_info.base_type) { 127 // The two ptr definitely not point to the same object, although 128 // their base_type are the same. 129 // Otherwise, It will immediately return back at the statement before: 130 // 131 // if (info.status == __UpcastInfo::has_public_contained && 132 // (__flags & __non_diamond_repeat_mask) == 0) { return true; } 133 info.status = __UpcastInfo::has_ambig_or_not_public; 134 return true; 135 } 136 } 137 138 assert (*info.base_type == *cur_base_info.base_type); 139 140 // Logically, this should be: 141 // assert (info.adjustedPtr || cur_base_info.adjustedPtr); 142 // But in reality, this will be: 143 assert (info.adjustedPtr && cur_base_info.adjustedPtr); 144 145 // Found twice, but different real objects 146 if (info.adjustedPtr != cur_base_info.adjustedPtr) { 147 info.status = __UpcastInfo::has_ambig_or_not_public; 148 return true; 149 } 150 151 // Found twice, but the same real object (virtual base) 152 continue; 153 } 154 155 // We need information in info unless we know nothing 156 return info.status != __UpcastInfo::unknown; 157 } 158 } // namespace __cxxabiv1 159