1// Methods for type_info for -*- C++ -*- Run Time Type Identification.
2// Copyright (C) 1994, 1996, 1998 Free Software Foundation
3
4// This file is part of GNU CC.
5
6// GNU CC is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2, or (at your option)
9// any later version.
10
11// GNU CC is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with GNU CC; see the file COPYING.  If not, write to
18// the Free Software Foundation, 59 Temple Place - Suite 330,
19// Boston, MA 02111-1307, USA.
20
21// As a special exception, if you link this library with other files,
22// some of which are compiled with GCC, to produce an executable,
23// this library does not by itself cause the resulting executable
24// to be covered by the GNU General Public License.
25// This exception does not however invalidate any other reasons why
26// the executable file might be covered by the GNU General Public License.
27
28#pragma implementation "typeinfo"
29
30#include <stddef.h>
31#include "tinfo.h"
32#include "new"			// for placement new
33
34// This file contains the minimal working set necessary to link with code
35// that uses virtual functions and -frtti but does not actually use RTTI
36// functionality.
37
38std::type_info::
39~type_info ()
40{ }
41
42// We can't rely on common symbols being shared between shared objects.
43bool std::type_info::
44operator== (const std::type_info& arg) const
45{
46  return (&arg == this) || (strcmp (name (), arg.name ()) == 0);
47}
48
49extern "C" void
50__rtti_class (void *addr, const char *name,
51	      const __class_type_info::base_info *bl, size_t bn)
52{ new (addr) __class_type_info (name, bl, bn); }
53
54extern "C" void
55__rtti_si (void *addr, const char *n, const std::type_info *ti)
56{
57  new (addr) __si_type_info
58    (n, static_cast <const __user_type_info &> (*ti));
59}
60
61extern "C" void
62__rtti_user (void *addr, const char *name)
63{ new (addr) __user_type_info (name); }
64
65// dynamic_cast helper methods.
66// Returns a pointer to the desired sub-object or 0.
67
68void * __user_type_info::
69dcast (const type_info& to, int, void *addr, const type_info *, void *) const
70{ return (*this == to) ? addr : 0; }
71
72void * __si_type_info::
73dcast (const type_info& to, int require_public, void *addr,
74       const type_info *sub, void *subptr) const
75{
76  if (*this == to)
77    return addr;
78  return base.dcast (to, require_public, addr, sub, subptr);
79}
80
81void* __class_type_info::
82dcast (const type_info& desired, int is_public, void *objptr,
83       const type_info *sub, void *subptr) const
84{
85  if (*this == desired)
86    return objptr;
87
88  void *match_found = 0;
89  for (size_t i = 0; i < n_bases; i++)
90    {
91      if (is_public && base_list[i].access != PUBLIC)
92	continue;
93
94      void *p = (char *)objptr + base_list[i].offset;
95      if (base_list[i].is_virtual)
96	p = *(void **)p;
97      p = base_list[i].base->dcast (desired, is_public, p, sub, subptr);
98      if (p)
99	{
100	  if (match_found == 0)
101	    match_found = p;
102	  else if (match_found != p)
103	    {
104	      if (sub)
105		{
106		  // Perhaps we're downcasting from *sub to desired; see if
107		  // subptr is a subobject of exactly one of {match_found,p}.
108
109		  const __user_type_info &d =
110		    static_cast <const __user_type_info &> (desired);
111
112		  void *os = d.dcast (*sub, 1, match_found);
113		  void *ns = d.dcast (*sub, 1, p);
114
115		  if (os == ns)
116		    /* ambiguous -- subptr is a virtual base */;
117		  else if (os == subptr)
118		    continue;
119		  else if (ns == subptr)
120		    {
121		      match_found = p;
122		      continue;
123		    }
124		}
125
126	      // base found at two different pointers,
127	      // conversion is not unique
128	      return 0;
129	    }
130	}
131    }
132
133  return match_found;
134}
135