/* RunTime Type Identification
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006
+ 2005, 2006, 2007
Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "assert.h"
#include "toplev.h"
#include "convert.h"
+#include "target.h"
/* C++ returns type information to the user in struct type_info
objects. We also use type information to implement dynamic_cast and
typedef enum tinfo_kind
{
- TK_TYPE_INFO_TYPE, /* std::type_info */
+ TK_TYPE_INFO_TYPE, /* abi::__type_info_pseudo */
TK_BASE_TYPE, /* abi::__base_class_type_info */
TK_BUILTIN_TYPE, /* abi::__fundamental_type_info */
TK_ARRAY_TYPE, /* abi::__array_type_info */
and are generated as needed. */
static GTY (()) VEC(tinfo_s,gc) *tinfo_descs;
-static tree build_headof (tree);
static tree ifnonnull (tree, tree);
static tree tinfo_name (tree);
static tree build_dynamic_cast_1 (tree, tree);
virtual functions (TYPE_POLYMORPHIC_P), else just return the
expression. */
-static tree
+tree
build_headof (tree exp)
{
tree type = TREE_TYPE (exp);
type = build_qualified_type (ptr_type_node,
cp_type_quals (TREE_TYPE (exp)));
- return build2 (PLUS_EXPR, type, exp,
- convert_to_integer (ptrdiff_type_node, offset));
+ return build2 (POINTER_PLUS_EXPR, type, exp,
+ convert_to_integer (sizetype, offset));
}
/* Get a bad_cast node for the program to throw...
fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
void_list_node));
- return build_cxx_call (fn, NULL_TREE);
+ return build_cxx_call (fn, 0, NULL);
}
/* Return an expression for "__cxa_bad_typeid()". The expression
fn = push_throw_library_fn (fn, t);
}
- return build_cxx_call (fn, NULL_TREE);
+ return build_cxx_call (fn, 0, NULL);
}
\f
/* Return an lvalue expression whose type is "const std::type_info"
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
- if (!VOID_TYPE_P (type))
+ if (CLASS_TYPE_P (type))
type = complete_type_or_else (type, exp);
if (!type)
static bool
typeid_ok_p (void)
{
+ tree pseudo_type_info, type_info_type;
+
if (! flag_rtti)
{
error ("cannot use typeid with -fno-rtti");
return false;
}
+ pseudo_type_info
+ = VEC_index (tinfo_s, tinfo_descs, TK_TYPE_INFO_TYPE)->type;
+ type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node);
+
+ /* Make sure abi::__type_info_pseudo has the same alias set
+ as std::type_info. */
+ if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info))
+ TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type);
+ else
+ gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
+ == get_alias_set (type_info_type));
+
return true;
}
tree name;
tree d;
- if (COMPLETE_TYPE_P (type)
- && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ if (variably_modified_type_p (type, /*fn=*/NULL_TREE))
{
error ("cannot create type information for type %qT because "
- "its size is variable",
+ "it involves types of variable size",
type);
return error_mark_node;
}
define it later if we need to do so. */
DECL_EXTERNAL (d) = 1;
DECL_NOT_REALLY_EXTERN (d) = 1;
+ set_linkage_according_to_type (type, d);
+
+ d = pushdecl_top_level_and_finish (d, NULL_TREE);
if (CLASS_TYPE_P (type))
CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
- set_linkage_according_to_type (type, d);
- pushdecl_top_level_and_finish (d, NULL_TREE);
/* Add decl to the global array of tinfo decls. */
VEC_safe_push (tree, gc, unemitted_tinfo_decls, d);
that is the operand of typeid are always ignored. */
type = TYPE_MAIN_VARIANT (type);
- if (!VOID_TYPE_P (type))
+ if (CLASS_TYPE_P (type))
type = complete_type_or_else (type, NULL_TREE);
if (!type)
else
{
tree retval;
- tree result, td2, td3, elems;
+ tree result, td2, td3;
+ tree elems[4];
tree static_type, target_type, boff;
/* If we got here, we can't convert statically. Therefore,
}
}
+ /* Use of dynamic_cast when -fno-rtti is prohibited. */
+ if (!flag_rtti)
+ {
+ error ("%<dynamic_cast%> not permitted with -fno-rtti");
+ return error_mark_node;
+ }
+
target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
td2 = get_tinfo_decl (target_type);
if (tc == REFERENCE_TYPE)
expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
- elems = tree_cons
- (NULL_TREE, expr1, tree_cons
- (NULL_TREE, td3, tree_cons
- (NULL_TREE, td2, tree_cons
- (NULL_TREE, boff, NULL_TREE))));
+ elems[0] = expr1;
+ elems[1] = td3;
+ elems[2] = td2;
+ elems[3] = boff;
dcast_fn = dynamic_cast_node;
if (!dcast_fn)
pop_nested_namespace (ns);
dynamic_cast_node = dcast_fn;
}
- result = build_cxx_call (dcast_fn, elems);
+ result = build_cxx_call (dcast_fn, 4, elems);
if (tc == REFERENCE_TYPE)
{
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
- /* Use of dynamic_cast when -fno-rtti is prohibited. */
- if (!flag_rtti)
- {
- error ("%<dynamic_cast%> not permitted with -fno-rtti");
- return error_mark_node;
- }
-
if (processing_template_decl)
{
expr = build_min (DYNAMIC_CAST_EXPR, type, expr);
TREE_SIDE_EFFECTS (expr) = 1;
-
- return expr;
+ return convert_from_reference (expr);
}
return convert_from_reference (build_dynamic_cast_1 (type, expr));
TREE_STATIC (name_decl) = 1;
DECL_EXTERNAL (name_decl) = 0;
DECL_TINFO_P (name_decl) = 1;
- if (involves_incomplete_p (target))
- {
- TREE_PUBLIC (name_decl) = 0;
- DECL_INTERFACE_KNOWN (name_decl) = 1;
- }
- else
- set_linkage_according_to_type (target, name_decl);
+ set_linkage_according_to_type (target, name_decl);
import_export_decl (name_decl);
DECL_INITIAL (name_decl) = name_string;
mark_used (name_decl);
/* We need to point into the middle of the vtable. */
vtable_ptr = build2
- (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
+ (POINTER_PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
size_binop (MULT_EXPR,
size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
TYPE_SIZE_UNIT (vtable_entry_type)));
tree binfo = TYPE_BINFO (type);
int nbases = BINFO_N_BASE_BINFOS (binfo);
VEC(tree,gc) *base_accesses = BINFO_BASE_ACCESSES (binfo);
+ tree offset_type = integer_types[itk_long];
tree base_inits = NULL_TREE;
int ix;
/* We store the vtable offset at which the virtual
base offset can be found. */
offset = BINFO_VPTR_FIELD (base_binfo);
- offset = convert (sizetype, offset);
flags |= 1;
}
else
offset = BINFO_OFFSET (base_binfo);
/* Combine offset and flags into one field. */
- offset = cp_build_binary_op (LSHIFT_EXPR, offset,
- build_int_cst (NULL_TREE, 8));
- offset = cp_build_binary_op (BIT_IOR_EXPR, offset,
- build_int_cst (NULL_TREE, flags));
+ offset = fold_convert (offset_type, offset);
+ offset = fold_build2 (LSHIFT_EXPR, offset_type, offset,
+ build_int_cst (offset_type, 8));
+ offset = fold_build2 (BIT_IOR_EXPR, offset_type, offset,
+ build_int_cst (offset_type, flags));
base_init = tree_cons (NULL_TREE, offset, base_init);
base_init = tree_cons (NULL_TREE, tinfo, base_init);
base_init = build_constructor_from_list (NULL_TREE, base_init);
ti->name = get_identifier (real_name);
ti->vtable = NULL_TREE;
+ /* Pretend this is public so determine_visibility doesn't give vtables
+ internal linkage. */
+ TREE_PUBLIC (TYPE_MAIN_DECL (ti->type)) = 1;
+
va_end (ap);
}
comdat_linkage for details.) Since we want these objects
to have external linkage so that copies do not have to be
emitted in code outside the runtime library, we make them
- non-COMDAT here. */
- if (!flag_weak)
+ non-COMDAT here.
+
+ It might also not be necessary to follow this detail of the
+ ABI. */
+ if (!flag_weak || ! targetm.cxx.library_rtti_comdat ())
{
gcc_assert (TREE_PUBLIC (tinfo) && !DECL_COMDAT (tinfo));
DECL_INTERFACE_KNOWN (tinfo) = 1;