Commit a0a33927 by Mike Stump

39th Cygnus<->FSF merge

From-SVN: r7439
parent 5345f91a
......@@ -41,6 +41,15 @@ CXX_FLAGS_TO_PASS = \
"CXXFLAGS=$(CXXFLAGS)" \
"CXX_FOR_TARGET=$(CXX_FOR_TARGET)"
# Actual names to use when installing a native compiler.
CXX_INSTALL_NAME = c++
GXX_INSTALL_NAME = g++
# Actual names to use when installing a cross-compiler.
CXX_CROSS_NAME = $(target)-c++
GXX_CROSS_NAME = $(target)-g++
# Define the names for selecting c++ in LANGUAGES.
# Note that it would be nice to move the dependency on g++
# into the C++ rule, but that needs a little bit of work
......@@ -90,17 +99,17 @@ c++.install-normal:
c++.install-common:
-if [ -f cc1plus ] ; then \
if [ -f g++-cross ] ; then \
rm -f $(bindir)/$(target)-g++; \
$(INSTALL_PROGRAM) g++-cross $(bindir)/$(target)-g++; \
chmod a+x $(bindir)/$(target)-g++; \
rm -f $(bindir)/$(target)-c++; \
ln $(bindir)/$(target)-g++ $(bindir)/$(target)-c++; \
rm -f $(bindir)/$(GXX_CROSS_NAME); \
$(INSTALL_PROGRAM) g++-cross $(bindir)/$(GXX_CROSS_NAME); \
chmod a+x $(bindir)/$(GXX_CROSS_NAME); \
rm -f $(bindir)/$(CXX_CROSS_NAME); \
ln $(bindir)/$(GXX_CROSS_NAME) $(bindir)/$(CXX_CROSS_NAME); \
else \
rm -f $(bindir)/g++; \
$(INSTALL_PROGRAM) g++ $(bindir)/g++; \
chmod a+x $(bindir)/g++; \
rm -f $(bindir)/c++; \
ln $(bindir)/g++ $(bindir)/c++; \
rm -f $(bindir)/$(GXX_INSTALL_NAME); \
$(INSTALL_PROGRAM) g++ $(bindir)/$(GXX_INSTALL_NAME); \
chmod a+x $(bindir)/$(GXX_INSTALL_NAME); \
rm -f $(bindir)/$(CXX_INSTALL_NAME); \
ln $(bindir)/$(GXX_INSTALL_NAME) $(bindir)/$(CXX_INSTALL_NAME); \
fi ; \
fi
......@@ -113,8 +122,10 @@ c++.install-man: $(srcdir)/cp/g++.1
else true; fi
c++.uninstall:
-rm -rf $(bindir)/g++ $(bindir)/c++
-rm -rf $(bindir)/$(target)-g++ $(bindir)/$(target)-c++
-rm -rf $(bindir)/$(CXX_INSTALL_NAME)
-rm -rf $(bindir)/$(CXX_CROSS_NAME)
-rm -rf $(bindir)/$(GXX_INSTALL_NAME)
-rm -rf $(bindir)/$(GXX_CROSS_NAME)
-rm -rf $(mandir)/g++$(manext)
# Clean hooks:
......
......@@ -193,7 +193,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
`echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
@echo expect 33 reduce/reduce conflicts.
@echo expect 1 shift/reduce confict and 33 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
......
......@@ -1123,6 +1123,24 @@ get_vfield_offset (binfo)
BINFO_OFFSET (binfo));
}
/* Get the offset to the start of the original binfo that we derived this
binfo from. */
tree get_derived_offset (binfo)
tree binfo;
{
tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
tree offset2;
int i;
while (BINFO_BASETYPES (binfo)
&& (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
{
tree binfos = BINFO_BASETYPES (binfo);
binfo = TREE_VEC_ELT (binfos, i);
}
offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
return size_binop (MINUS_EXPR, offset1, offset2);
}
/* If FOR_TYPE needs to reinitialize virtual function table pointers
for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
Returns BASE_INIT_LIST appropriately modified. */
......@@ -2171,8 +2189,13 @@ modify_one_vtable (binfo, t, fndecl, pfn)
/* Find the right offset for the this pointer based on the
base class we just found. We have to take into
consideration the virtual base class pointers that we
stick in before the virtual function table pointer. */
base_offset = get_vfield_offset (binfo);
stick in before the virtual function table pointer.
Also, we want just the delta bewteen the most base class
that we derived this vfield from and us. */
base_offset = size_binop (PLUS_EXPR,
get_derived_offset (binfo),
BINFO_OFFSET (binfo));
this_offset = size_binop (MINUS_EXPR, offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
......@@ -2374,8 +2397,8 @@ override_one_vtable (binfo, old, t)
override_one_vtable (binfo, old, t);
return;
}
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
}
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
}
else
{
......@@ -2547,7 +2570,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
int ref_sans_init = 0;
int nonprivate_method = 0;
tree t_binfo = TYPE_BINFO (t);
tree access_decls = 0;
tree access_decls = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
......@@ -2578,7 +2601,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name))
warning ("anonymous class type not used to declare any objects");
pedwarn ("anonymous class type not used to declare any objects");
if (TYPE_SIZE (t))
{
......@@ -2599,7 +2622,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
/* If this type was previously laid out as a forward reference,
make sure we lay it out again. */
TYPE_SIZE (t) = 0;
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
/* A signature type will contain the fields of the signature table.
......@@ -3025,7 +3048,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (code == UNION_TYPE)
{
char * fie = 0;
char *fie = NULL;
if (TYPE_NEEDS_CONSTRUCTING (type))
fie = "constructor";
else if (TYPE_NEEDS_DESTRUCTOR (type))
......@@ -3252,9 +3275,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name)
{
cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
cp_error_at ("because of local method `%#D' with same name",
cp_error_at (" because of local method `%#D' with same name",
TREE_VEC_ELT (method_vec, i));
fdecl = 0;
fdecl = NULL_TREE;
break;
}
......@@ -3265,8 +3288,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_NAME (tmp) == name)
{
cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
cp_error_at ("because of local field `%#D' with same name", tmp);
fdecl = 0;
cp_error_at (" because of local field `%#D' with same name", tmp);
fdecl = NULL_TREE;
break;
}
......@@ -3315,7 +3338,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
else if (last_x)
{
my_friendly_assert (TREE_CHAIN (last_x) == 0, 175);
my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175);
TREE_CHAIN (last_x) = vfield;
last_x = vfield;
}
......@@ -3378,7 +3401,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
moved into the type of this field, but nothing seems to break
by doing this. */
if (DECL_NAME (field) == 0
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
......@@ -3405,7 +3428,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t);
DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype);
/* Don't re-use old size. */
DECL_SIZE (base_layout_decl) = 0;
DECL_SIZE (base_layout_decl) = NULL_TREE;
}
layout_type (t);
......@@ -3432,7 +3455,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
moved into the type of this field, but nothing seems to break
by doing this. */
if (DECL_NAME (field) == 0
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
......@@ -3709,12 +3732,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
while (x)
{
#if 0 /* What's wrong with using the decl the type already has? */
tree tag = build_lang_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x));
tree tag = build_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x));
DECL_CONTEXT (tag) = t;
#else
tree tag = TYPE_NAME (TREE_VALUE (x));
#endif
DECL_CLASS_CONTEXT (tag) = t;
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
......@@ -3729,7 +3751,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
x = TREE_CHAIN (x);
last_x = chainon (last_x, tag);
}
if (TYPE_FIELDS (t) == 0)
if (TYPE_FIELDS (t) == NULL_TREE)
TYPE_FIELDS (t) = last_x;
CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
}
......@@ -4220,7 +4242,9 @@ popclass (modify)
{
if (CLASSTYPE_VTBL_PTR (current_class_type))
{
current_vtable_decl = lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)), 0);
current_vtable_decl
= lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)),
0);
if (current_vtable_decl)
current_vtable_decl = build_indirect_ref (current_vtable_decl,
NULL_PTR);
......@@ -4525,9 +4549,10 @@ instantiate_type (lhstype, rhs, complain)
{
if (complain)
{
cp_error ("cannot resolve overload to target type `%#T';", lhstype);
cp_error_at ("ambiguity between `%#D'", save_elem);
cp_error_at ("and `%#D', at least", elem);
cp_error ("cannot resolve overload to target type `%#T'",
lhstype);
cp_error_at (" ambiguity between `%#D'", save_elem);
cp_error_at (" and `%#D', at least", elem);
}
return error_mark_node;
}
......@@ -4547,9 +4572,9 @@ instantiate_type (lhstype, rhs, complain)
}
if (complain)
{
cp_error ("cannot resolve overload to target type `%#T';",
cp_error ("cannot resolve overload to target type `%#T'",
lhstype);
cp_error ("no suitable overload of function `%D' exists",
cp_error (" because no suitable overload of function `%D' exists",
TREE_PURPOSE (rhs));
}
return error_mark_node;
......@@ -4631,10 +4656,12 @@ instantiate_type (lhstype, rhs, complain)
case PLUS_EXPR:
case MINUS_EXPR:
case COMPOUND_EXPR:
TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
TREE_OPERAND (rhs, 0)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
TREE_OPERAND (rhs, 1)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
......@@ -4701,10 +4728,12 @@ instantiate_type (lhstype, rhs, complain)
error ("not enough type information");
return error_mark_node;
}
TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
TREE_OPERAND (rhs, 1)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 2) = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
TREE_OPERAND (rhs, 2)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
if (TREE_OPERAND (rhs, 2) == error_mark_node)
return error_mark_node;
......@@ -4712,7 +4741,8 @@ instantiate_type (lhstype, rhs, complain)
return rhs;
case MODIFY_EXPR:
TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
TREE_OPERAND (rhs, 1)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
......@@ -4730,8 +4760,8 @@ instantiate_type (lhstype, rhs, complain)
}
TREE_TYPE (rhs) = lhstype;
lhstype = TREE_TYPE (lhstype);
TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0),
complain);
TREE_OPERAND (rhs, 0)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;
......
......@@ -362,6 +362,7 @@ enum languages { lang_c, lang_cplusplus };
#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0)
#define ACCESSIBLY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, -1, (tree *)0) >= 0)
#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0)
#define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
enum conversion_type { ptr_conv, constptr_conv, int_conv,
real_conv, last_conversion_type };
......@@ -497,8 +498,11 @@ struct lang_type
union tree_node *signature_reference_to;
};
/* Indicates whether a template should be (or has been) expanded for this
class definition. 0=do, 1=did, 2=don't, 3=didn't. */
/* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class
1=implicit template instantiation
2=explicit template specialization
3=explicit template instantiation */
#define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.use_template)
/* Fields used for storing information before the class is defined.
......@@ -931,7 +935,9 @@ struct lang_decl_flags
unsigned mutable_flag : 1;
unsigned is_default_implementation : 1;
unsigned saved_inline : 1;
unsigned dummy : 10;
unsigned use_template : 2;
unsigned dummy : 8;
tree access;
tree context;
......@@ -1101,7 +1107,7 @@ struct lang_decl
#if 0
/* Same, but tells if this field is private in current context. */
#define DECL_PRIVATE(NODE) NOTHING
#define DECL_PRIVATE(NODE) (DECL_LANG_FLAG_5 (NODE))
/* Same, but tells if this field is private in current context. */
#define DECL_PROTECTED(NODE) (DECL_LANG_FLAG_6 (NODE))
......@@ -1266,11 +1272,39 @@ struct lang_decl
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
/* Macros for a DECL or TYPE generated from a template to indicate that it
was explicitly instantiated. */
#define DECL_EXPLICITLY_INSTANTIATED(NODE) (DECL_LANG_FLAG_5 (NODE))
#define CLASSTYPE_EXPLICITLY_INSTANTIATED(NODE) \
(DECL_EXPLICITLY_INSTANTIATED (TYPE_NAME (NODE)))
/* Indicates whether or not (and how) a template was expanded for this
FUNCTION_DECL or VAR_DECL.
0=normal declaration, e.g. int min (int, int);
1=implicit template instantiation
2=explicit template specialization, e.g. int min<int> (int, int);
3=explicit template instantiation, e.g. template int min<int> (int, int);
*/
#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.use_template)
#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) & 1)
#define DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) == 2)
#define SET_DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) = 2)
#define CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) == 2)
#define SET_CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) = 2)
#define DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 1)
#define SET_DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 1)
#define CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) == 1)
#define SET_CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 1)
#define DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 3)
#define SET_DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 3)
#define CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) == 3)
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 3)
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
......@@ -1309,6 +1343,7 @@ extern void check_function_format PROTO((tree, tree, tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
extern tree c_build_type_variant PROTO((tree, int, int));
extern void c_expand_expr_stmt PROTO((tree));
/* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PROTO((tree));
......@@ -1462,7 +1497,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_NAME "_$tmp_"
#define AUTO_TEMP_FORMAT "_$tmp_%d"
#define VTABLE_BASE "$vb"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT$%s" : "_vt$%s")
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt$%s")
#define VFIELD_BASE "$vf"
#define VFIELD_NAME "_vptr$"
#define VFIELD_NAME_FORMAT "_vptr$%s"
......@@ -1484,7 +1519,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_NAME "_.tmp_"
#define AUTO_TEMP_FORMAT "_.tmp_%d"
#define VTABLE_BASE ".vb"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT.%s" : "_vt.%s")
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt.%s")
#define VFIELD_BASE ".vf"
#define VFIELD_NAME "_vptr."
#define VFIELD_NAME_FORMAT "_vptr.%s"
......@@ -1513,7 +1548,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_FORMAT "__tmp_%d"
#define VTABLE_BASE "__vtb"
#define VTABLE_NAME "__vt_"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT_%s" : "_vt_%s")
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt_%s")
#define VTABLE_NAME_P(ID_NODE) \
(!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \
sizeof (VTABLE_NAME) - 1))
......@@ -1668,6 +1703,11 @@ extern int flag_gc;
extern int flag_dossier;
/* Nonzero means do emit exported implementations of functions even if
they can be inlined. */
extern int flag_implement_inlines;
/* Nonzero means templates obey #pragma interface and implementation. */
extern int flag_external_templates;
......@@ -1676,6 +1716,10 @@ extern int flag_external_templates;
extern int flag_alt_external_templates;
/* Nonzero means implicit template instantatiations are emitted. */
extern int flag_implicit_templates;
/* Current end of entries in the gc obstack for stack pointer variables. */
extern int current_function_obstack_index;
......@@ -1875,7 +1919,7 @@ extern tree lookup_name_current_level PROTO((tree));
extern void init_decl_processing PROTO((void));
/* skipped define_function */
extern void shadow_tag PROTO((tree));
extern void grok_ctor_properties PROTO((tree, tree));
extern int grok_ctor_properties PROTO((tree, tree));
extern tree groktypename PROTO((tree));
extern tree start_decl PROTO((tree, tree, int, tree));
extern void finish_decl PROTO((tree, tree, tree, int));
......
......@@ -1226,6 +1226,9 @@ cp_convert (type, expr, convtype, flags)
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
if (TREE_READONLY_DECL_P (e))
e = decl_constant_value (e);
if (INTEGRAL_CODE_P (code))
{
tree intype = TREE_TYPE (expr);
......@@ -1332,8 +1335,12 @@ cp_convert (type, expr, convtype, flags)
{
tree binfo;
tree conversion = TYPE_HAS_CONVERSION (dtype)
? build_type_conversion (CONVERT_EXPR, type, e, 1) : NULL_TREE;
tree conversion;
if (! DERIVED_FROM_P (type, dtype) && TYPE_HAS_CONVERSION (dtype))
conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
else
conversion = NULL_TREE;
if (TYPE_HAS_CONSTRUCTOR (type))
{
......@@ -1493,8 +1500,7 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
else
flags = LOOKUP_NORMAL;
rval = build_method_call (first_arg, constructor_name_full (typename),
NULL_TREE, NULL_TREE, flags);
rval = build_method_call (first_arg, typename, NULL_TREE, NULL_TREE, flags);
if (rval == error_mark_node)
{
if (for_sure == 0)
......
......@@ -116,6 +116,10 @@ int flag_external_templates = 0;
int flag_alt_external_templates = 0;
/* Nonzero means that implicit instantiations will be emitted if needed. */
int flag_implicit_templates = 1;
/* Nonzero means warn about implicit declarations. */
int warn_implicit = 1;
......@@ -352,6 +356,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"nonnull-objects", &flag_assume_nonnull_objects, 1},
{"implement-inlines", &flag_implement_inlines, 1},
{"external-templates", &flag_external_templates, 1},
{"implicit-templates", &flag_implicit_templates, 1},
{"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
......@@ -1181,7 +1186,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises);
if (! value)
return NULL_TREE; /* friends went bad. */
return value; /* friend or constructor went bad. */
/* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE)
......@@ -1236,21 +1241,13 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
grok_function_init (value, init);
init = NULL_TREE;
}
else if (pedantic)
{
#if 0
/* Already warned in grokdeclarator. */
if (DECL_NAME (value))
pedwarn ("ANSI C++ forbids initialization of member `%s'",
IDENTIFIER_POINTER (DECL_NAME (value)));
else
pedwarn ("ANSI C++ forbids initialization of fields");
#endif
init = NULL_TREE;
}
else if (pedantic && ! TREE_STATIC (value))
/* Already complained in grokdeclarator. */
init = NULL_TREE;
else
{
/* We allow initializers to become parameters to base initializers. */
/* We allow initializers to become parameters to base
initializers. */
if (TREE_CODE (init) == TREE_LIST)
{
if (TREE_CHAIN (init) == NULL_TREE)
......@@ -1352,8 +1349,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
}
if (TREE_CODE (value) == FUNCTION_DECL)
{
/* grokdeclarator defers setting this. */
TREE_PUBLIC (value) = 1;
if (DECL_CHAIN (value) != NULL_TREE)
{
/* Need a fresh node here so that we don't get circularity
......@@ -1368,7 +1363,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
if (DECL_FRIEND_P (value))
return void_type_node;
if (current_function_decl)
if (current_function_decl && ! IS_SIGNATURE (current_class_type))
cp_error ("method `%#D' of local class must be defined in class body",
value);
......@@ -2345,7 +2340,8 @@ finish_vtable_vardecl (prev, vars)
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
method = DECL_NEXT_METHOD (method))
{
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method))
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method))
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
......@@ -2376,20 +2372,6 @@ finish_vtable_vardecl (prev, vars)
mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
store_init_value (vars, DECL_INITIAL (vars));
if (flag_vtable_thunks)
{
tree list = CONSTRUCTOR_ELTS (DECL_INITIAL (vars));
for (; list; list = TREE_CHAIN (list))
{
tree vfunc = TREE_VALUE (list);
if (TREE_CODE (vfunc) == ADDR_EXPR)
{
vfunc = TREE_OPERAND (vfunc, 0);
if (TREE_CODE (vfunc) == THUNK_DECL)
emit_thunk (vfunc);
}
}
}
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
......@@ -2737,6 +2719,12 @@ finish_file ()
walk_vtables ((void (*)())0, finish_vtable_vardecl);
for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
{
if (TREE_CODE (vars) == THUNK_DECL)
emit_thunk (vars);
}
/* Now write out inline functions which had their addresses taken
and which were not declared virtual and which were not declared
`extern inline'. */
......@@ -2752,12 +2740,16 @@ finish_file ()
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (ctype);
DECL_EXTERNAL (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines));
}
}
if (TREE_PUBLIC (decl) || TREE_ADDRESSABLE (decl))
{
if (DECL_EXTERNAL (decl))
if (DECL_EXTERNAL (decl)
|| (DECL_IMPLICIT_INSTANTIATION (decl)
&& ! flag_implicit_templates))
assemble_external (decl);
else
{
......
......@@ -837,25 +837,25 @@ dump_char (c)
{
switch (c)
{
case '\n':
case TARGET_NEWLINE:
OB_PUTS ("\\n");
break;
case '\t':
case TARGET_TAB:
OB_PUTS ("\\t");
break;
case '\v':
case TARGET_VT:
OB_PUTS ("\\v");
break;
case '\b':
case TARGET_BS:
OB_PUTS ("\\b");
break;
case '\r':
case TARGET_CR:
OB_PUTS ("\\r");
break;
case '\f':
case TARGET_FF:
OB_PUTS ("\\f");
break;
case '\a':
case TARGET_BELL:
OB_PUTS ("\\a");
break;
case '\\':
......
......@@ -1866,7 +1866,7 @@ build_member_call (cname, name, parmlist)
{
tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
TYPE_VOLATILE (oldtype));
decl = convert_force (TYPE_POINTER_TO (newtype), olddecl);
decl = convert_force (build_pointer_type (newtype), olddecl);
}
else
decl = olddecl;
......
......@@ -1936,15 +1936,17 @@ default_assign_ref_body (bufp, lenp, type, fields)
name = TYPE_NESTED_NAME (btype);
s = IDENTIFIER_POINTER (name);
tneed = (2 * strlen (s)) + 33;
tneed = (2 * strlen (s)) + 42;
if (tgot < tneed)
{
tgot = tneed;
tbuf = (char *) alloca (tgot);
}
sprintf (tbuf, "%s::operator=((%s%s&)_ctor_arg);", s,
TYPE_READONLY (type) ? "const " : "", s);
sprintf (tbuf, "%s::operator=((%s%s ::%s&)_ctor_arg);", s,
TYPE_READONLY (type) ? "const " : "",
CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
s);
obstack_grow (&body, tbuf, strlen (tbuf));
}
}
......@@ -2101,15 +2103,17 @@ default_copy_constructor_body (bufp, lenp, type, fields)
name = TYPE_NESTED_NAME (btype);
s = IDENTIFIER_POINTER (name);
tneed = (2 * strlen (s)) + 30;
tneed = (2 * strlen (s)) + 39;
if (tgot < tneed)
{
tgot = tneed;
tbuf = (char *) alloca (tgot);
}
sprintf (tbuf, "%c%s((%s%s&)_ctor_arg)", sep, s,
TYPE_READONLY (type) ? "const " : "", s);
sprintf (tbuf, "%c%s((%s%s ::%s&)_ctor_arg)", sep, s,
TYPE_READONLY (type) ? "const " : "",
CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
s);
sep = ',';
obstack_grow (&prologue, tbuf, strlen (tbuf));
}
......
......@@ -115,6 +115,7 @@ extern char *token_buffer; /* Pointer to token buffer. */
/* Back-door communication channel to the lexer. */
extern int looking_for_typename;
extern int looking_for_template;
/* Tell the lexer where to look for names. */
extern tree got_scope;
......
......@@ -938,7 +938,9 @@ build_typename_overload (type)
build_overload_name (type, 0, 1);
id = get_identifier (obstack_base (&scratch_obstack));
IDENTIFIER_OPNAME_P (id) = 1;
#if 0
IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);
#endif
TREE_TYPE (id) = type;
return id;
}
......@@ -1676,8 +1678,9 @@ make_thunk (function, delta)
int delta;
{
char buffer[250];
tree thunk_fndecl;
tree thunk_fndecl, thunk_id;
tree thunk;
char *func_name;
static int thunk_number = 0;
tree func_decl;
if (TREE_CODE (function) != ADDR_EXPR)
......@@ -1685,14 +1688,26 @@ make_thunk (function, delta)
func_decl = TREE_OPERAND (function, 0);
if (TREE_CODE (func_decl) != FUNCTION_DECL)
abort ();
sprintf (buffer, "__thunk_%d_%d", -delta, thunk_number++);
thunk = build_decl (THUNK_DECL, get_identifier (buffer),
TREE_TYPE (func_decl));
DECL_RESULT (thunk)
= build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl));
sprintf (buffer, "__thunk_%d_%s", -delta, func_name);
thunk_id = get_identifier (buffer);
thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
if (thunk && TREE_CODE (thunk) != THUNK_DECL)
{
error_with_decl ("implementation-reserved name `%s' used");
IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;
}
if (thunk == NULL_TREE)
{
thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl));
DECL_RESULT (thunk)
= build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
/* So that finish_file can write out any thunks that need to be: */
pushdecl_top_level (thunk);
}
return thunk;
}
......@@ -1725,6 +1740,19 @@ emit_thunk (thunk_fndecl)
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
if (TREE_PUBLIC (function))
{
TREE_PUBLIC (thunk_fndecl) = 1;
if (DECL_EXTERNAL (function))
{
DECL_EXTERNAL (thunk_fndecl) = 1;
assemble_external (thunk_fndecl);
return;
}
}
decl_printable_name = thunk_printable_name;
if (current_function_decl)
abort ();
......@@ -1833,8 +1861,6 @@ emit_thunk (thunk_fndecl)
expand_end_bindings (NULL, 1, 0);
poplevel (0, 0, 0);
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
/* From now on, allocate rtl in current_obstack, not in saveable_obstack.
Note that that may have been done above, in save_for_inline_copying.
The call to resume_temporary_allocation near the end of this function
......@@ -1848,10 +1874,6 @@ emit_thunk (thunk_fndecl)
unshare_all_rtl (insns);
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, get_insns ());
/* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1;
......
......@@ -543,11 +543,12 @@ datadef:
&& TREE_PURPOSE (t) == NULL_TREE)
{
t = TREE_VALUE (t);
if (TREE_CODE (t) == RECORD_TYPE)
if (IS_AGGR_TYPE (t)
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (t)))
{
if (CLASSTYPE_USE_TEMPLATE (t) == 0)
CLASSTYPE_USE_TEMPLATE (t) = 2;
else if (CLASSTYPE_USE_TEMPLATE (t) == 1)
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
error ("override declaration for already-expanded template");
}
}
......@@ -2914,14 +2915,18 @@ absdcl:
{ $$ = make_pointer_declarator ($2, $3); }
| '*' absdcl
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '*' type_quals %prec EMPTY
| '*' nonempty_type_quals %prec EMPTY
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
| '*' %prec EMPTY
{ $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); }
| '&' nonempty_type_quals absdcl
{ $$ = make_reference_declarator ($2, $3); }
| '&' absdcl
{ $$ = make_reference_declarator (NULL_TREE, $2); }
| '&' type_quals %prec EMPTY
| '&' nonempty_type_quals %prec EMPTY
{ $$ = make_reference_declarator ($2, NULL_TREE); }
| '&' %prec EMPTY
{ $$ = make_reference_declarator (NULL_TREE, NULL_TREE); }
| ptr_to_mem type_quals %prec EMPTY
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
$$ = build_parse_node (SCOPE_REF, $1, arg);
......
......@@ -116,7 +116,7 @@ process_template_parm (list, next)
else
{
tree t = make_node (TEMPLATE_TYPE_PARM);
decl = build_lang_decl (TYPE_DECL, TREE_PURPOSE (parm), t);
decl = build_decl (TYPE_DECL, TREE_PURPOSE (parm), t);
TYPE_NAME (t) = decl;
TREE_VALUE (parm) = t;
}
......@@ -581,7 +581,7 @@ lookup_template_class (d1, arglist, in_decl)
tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
tree d;
id = make_anon_name ();
d = build_lang_decl (TYPE_DECL, id, t);
d = build_decl (TYPE_DECL, id, t);
TYPE_NAME (t) = d;
TYPE_VALUES (t) = build_tree_list (template, arglist);
pushdecl_top_level (d);
......@@ -635,7 +635,7 @@ push_template_decls (parmlist, arglist, class_level)
}
decl = arg;
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
decl = build_lang_decl (TYPE_DECL, parm, decl);
decl = build_decl (TYPE_DECL, parm, decl);
}
else
{
......@@ -987,7 +987,7 @@ instantiate_class_template (classname, setup_parse)
if (!TREE_TYPE (classname))
{
tree t = make_lang_type (RECORD_TYPE);
tree d = build_lang_decl (TYPE_DECL, classname, t);
tree d = build_decl (TYPE_DECL, classname, t);
DECL_NAME (d) = classname;
TYPE_NAME (t) = d;
pushdecl (d);
......@@ -1320,7 +1320,7 @@ tsubst (t, args, nargs, in_decl)
tree decls;
int got_it = 0;
decls = lookup_name (r, 0);
decls = lookup_name_nonclass (r);
if (decls == NULL_TREE)
/* no match */;
else if (TREE_CODE (decls) == TREE_LIST)
......@@ -1645,11 +1645,18 @@ instantiate_template (tmpl, targ_ptr)
DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
}
t = DECL_TEMPLATE_INFO (tmpl);
/* If we have a preexisting version of this function, don't expand
the template version, use the other instead. */
t = DECL_TEMPLATE_INFO (tmpl);
if (t->text && !(DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl)))
if (DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl))
{
SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
p = (struct pending_inline *)0;
}
else if (t->text)
{
SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
p->parm_vec = t->parm_vec;
p->bindings = targs;
......@@ -1819,7 +1826,7 @@ end_template_instantiation (name)
my_friendly_assert (t != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (t)) == 't',
287);
CLASSTYPE_USE_TEMPLATE (t) = 2;
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
/* Make methods of template classes static, unless
-fexternal-templates is given. */
if (!flag_external_templates)
......@@ -2227,8 +2234,10 @@ do_pending_expansions ()
if (TREE_ASM_WRITTEN (t))
DECIDE (0);
if (DECL_EXPLICITLY_INSTANTIATED (t))
if (DECL_EXPLICIT_INSTANTIATION (t))
DECIDE (1);
else if (! flag_implicit_templates)
DECIDE (0);
/* If it's a method, let the class type decide it.
@@ What if the method template is in a separate file?
......@@ -2357,7 +2366,12 @@ do_function_instantiation (declspecs, declarator)
if (! result)
cp_error ("no matching template for `%D' found", decl);
DECL_EXPLICITLY_INSTANTIATED (result) = 1;
if (flag_external_templates)
return;
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
DECL_EXTERNAL (result) = DECL_INLINE (result) && ! flag_implement_inlines;
}
void
......@@ -2366,14 +2380,24 @@ do_type_instantiation (name)
{
tree t = TREE_TYPE (name);
CLASSTYPE_EXPLICITLY_INSTANTIATED (t) = 1;
if (flag_external_templates)
return;
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = 0;
/* this should really be done by instantiate_member_templates */
{
tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; method; method = TREE_CHAIN (method))
DECL_EXPLICITLY_INSTANTIATED (method) = 1;
{
SET_DECL_EXPLICIT_INSTANTIATION (method);
TREE_PUBLIC (method) = 1;
DECL_EXTERNAL (method) = (DECL_INLINE (method)
&& ! flag_implement_inlines);
}
}
/* and data member templates, too */
......@@ -2384,7 +2408,7 @@ create_nested_upt (scope, name)
tree scope, name;
{
tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
tree d = build_lang_decl (TYPE_DECL, name, t);
tree d = build_decl (TYPE_DECL, name, t);
TYPE_NAME (t) = d;
TYPE_VALUES (t) = TYPE_VALUES (scope);
......
......@@ -512,8 +512,8 @@ build_signature_table_constructor (sig_ty, rhs)
{
if (! IS_DEFAULT_IMPLEMENTATION (sig_method))
{
cp_error ("class `%T' does not contain method `%s'",
rhstype, (int) IDENTIFIER_POINTER (sig_mname));
cp_error ("class `%T' does not contain method `%D'",
rhstype, sig_mname);
undo_casts (sig_ty);
return error_mark_node;
}
......
......@@ -236,6 +236,7 @@ probe_obstack (h, obj, nlevels)
a typename (when it may be a local variable or a class variable).
Value is 0 if we treat this name in a default fashion. */
extern int looking_for_typename;
int looking_for_template;
extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope;
......@@ -298,6 +299,8 @@ yylex()
if (nth_token (1)->yychar == SCOPE)
/* Don't interfere with the setting from an 'aggr' prefix. */
looking_for_typename++;
else if (nth_token (1)->yychar == '<')
looking_for_template = 1;
trrr = lookup_name (tmp_token.yylval.ttype, -2);
......@@ -334,6 +337,7 @@ yylex()
consume_token ();
if (looking_for_typename > 0)
looking_for_typename--;
looking_for_template = 0;
break;
case SCSPEC:
......
......@@ -860,7 +860,7 @@ list_hash_add (hashcode, list)
This function frees the list you pass in if it is a duplicate. */
/* Set to 1 to debug without canonicalization. Never set by program. */
int debug_no_list_hash = 0;
static int debug_no_list_hash = 0;
tree
list_hash_canon (hashcode, list)
......
......@@ -655,6 +655,7 @@ digest_init (type, init, tail)
&& ((TREE_CODE (init) == ADDR_EXPR
&& TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE)
|| TREE_CODE (init) == TREE_LIST
|| integer_zerop (init)
|| (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))))
{
......@@ -1237,6 +1238,12 @@ build_x_arrow (datum)
if (type == error_mark_node)
return error_mark_node;
if (TREE_CODE (rval) == OFFSET_REF)
{
rval = resolve_offset_ref (datum);
type = TREE_TYPE (rval);
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
rval = convert_from_reference (rval);
......@@ -1268,7 +1275,6 @@ build_x_arrow (datum)
else
last_rval = default_conversion (rval);
more:
/* Signature pointers are not dereferenced. */
if (TYPE_LANG_SPECIFIC (TREE_TYPE (last_rval))
&& IS_SIGNATURE_POINTER (TREE_TYPE (last_rval)))
......@@ -1277,20 +1283,6 @@ build_x_arrow (datum)
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
return build_indirect_ref (last_rval, NULL_PTR);
if (TREE_CODE (TREE_TYPE (last_rval)) == OFFSET_TYPE)
{
if (TREE_CODE (last_rval) == OFFSET_REF
&& TREE_STATIC (TREE_OPERAND (last_rval, 1)))
{
last_rval = TREE_OPERAND (last_rval, 1);
if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE)
last_rval = convert_from_reference (last_rval);
goto more;
}
compiler_error ("invalid member type in build_x_arrow");
return error_mark_node;
}
if (types_memoized)
error ("result of `operator->()' yields non-pointer result");
else
......@@ -1372,7 +1364,6 @@ build_functional_cast (exp, parms)
or a C cast in C++'s `functional' notation. */
tree type, name = NULL_TREE;
tree expr_as_ctor = NULL_TREE;
tree expr_as_conversion = NULL_TREE;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
......@@ -1423,7 +1414,12 @@ build_functional_cast (exp, parms)
/* this must build a C cast */
if (parms == NULL_TREE)
return build1 (NOP_EXPR, type, integer_zero_node);
return build_c_cast (type, build_compound_expr (parms));
else if (TREE_CHAIN (parms) != NULL_TREE)
{
pedwarn ("initializer list being treated as compound expression");
parms = build_compound_expr (parms);
}
return build_c_cast (type, parms);
}
if (TYPE_SIZE (type) == NULL_TREE)
......@@ -1433,90 +1429,45 @@ build_functional_cast (exp, parms)
}
if (parms && TREE_CHAIN (parms) == NULL_TREE)
expr_as_conversion
= build_type_conversion (CONVERT_EXPR, type, TREE_VALUE (parms), 0);
if (! TYPE_HAS_CONSTRUCTOR (type) && parms != NULL_TREE)
{
char *msg = 0;
return build_c_cast (type, parms);
if (parms == NULL_TREE)
msg = "argument missing in cast to `%T' type";
else if (TREE_CHAIN (parms) == NULL_TREE)
{
if (expr_as_conversion == NULL_TREE)
msg = "conversion to type `%T' failed";
}
else msg = "type `%T' does not have a constructor";
expr_as_ctor = build_method_call (NULL_TREE, name, parms,
NULL_TREE, LOOKUP_NORMAL);
if (expr_as_conversion)
return expr_as_conversion;
if (expr_as_ctor == error_mark_node)
return error_mark_node;
cp_error (msg, type);
return error_mark_node;
}
if (current_function_decl)
return build_cplus_new (type, expr_as_ctor, 0);
{
int flags = LOOKUP_SPECULATIVELY|LOOKUP_NORMAL;
if (parms && TREE_CHAIN (parms) == NULL_TREE)
flags |= LOOKUP_NO_CONVERSION;
register tree parm = TREE_OPERAND (expr_as_ctor, 1);
expr_as_ctor = build_method_call (NULL_TREE, name, parms,
NULL_TREE, flags);
if (expr_as_ctor == error_mark_node)
return error_mark_node;
else if (expr_as_ctor)
{
if (expr_as_conversion && expr_as_conversion != error_mark_node)
{
/* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
cp_error ("ambiguity between conversion to `%T' and constructor",
type);
return error_mark_node;
}
if (current_function_decl)
return build_cplus_new (type, expr_as_ctor, 0);
{
register tree parm = TREE_OPERAND (expr_as_ctor, 1);
/* Initializers for static variables and parameters have
to handle doing the initialization and cleanup themselves. */
my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322);
/* Initializers for static variables and parameters have
to handle doing the initialization and cleanup themselves. */
my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322);
#if 0
/* The following assertion fails in cases where we are initializing
a static member variable of a particular instance of a template
class with a call to a constructor of the given instance, as in:
TMPL<int> object = TMPL<int>();
Curiously, the assertion does not fail if we do the same thing
for a static member of a non-template class, as in:
T object = T();
I can't see why we should care here whether or not the initializer
expression involves a call to `new', so for the time being, it
seems best to just avoid doing this assertion. */
my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323);
/* The following assertion fails in cases where we are initializing
a static member variable of a particular instance of a template
class with a call to a constructor of the given instance, as in:
TMPL<int> object = TMPL<int>();
Curiously, the assertion does not fail if we do the same thing
for a static member of a non-template class, as in:
T object = T();
I can't see why we should care here whether or not the initializer
expression involves a call to `new', so for the time being, it
seems best to just avoid doing this assertion. */
my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323);
#endif
TREE_VALUE (parm) = NULL_TREE;
expr_as_ctor = build_indirect_ref (expr_as_ctor, NULL_PTR);
TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1;
}
return expr_as_ctor;
}
if (expr_as_conversion)
return expr_as_conversion;
cp_error ("no suitable conversion to `%T' exists", type);
return error_mark_node;
TREE_VALUE (parm) = NULL_TREE;
expr_as_ctor = build_indirect_ref (expr_as_ctor, NULL_PTR);
TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1;
}
return expr_as_ctor;
}
/* Return the character string for the name that encodes the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment