Commit a0a33927 by Mike Stump

39th Cygnus<->FSF merge

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