Home | History | Annotate | Download | only in src
      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