parent
ec497122f7
commit
a80e41955a
|
@ -1,14 +1,83 @@
|
|||
Wed Apr 17 15:20:10 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
|
||||
Thu Apr 18 08:56:54 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* decl.c (make_typename_type): Handle getting a TYPE_DECL for a
|
||||
name.
|
||||
* parse.y (base_class.1): Allow 'typename foo::bar'.
|
||||
|
||||
* lex.c (check_newline): Remove #pragma code that plays with the
|
||||
input stream, since we now deal with tokens. Clear nextchar when
|
||||
we're done.
|
||||
(handle_cp_pragma): Use real_yylex.
|
||||
(handle_sysv_pragma): Don't do skipline here. Only call real_yylex
|
||||
in one place.
|
||||
|
||||
* lex.c (check_for_missing_semicolon): Handle SELFNAME.
|
||||
|
||||
* lex.c (handle_cp_pragma): Fix "#pragma implementation".
|
||||
|
||||
Wed Apr 17 16:51:33 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* parse.y: New token SELFNAME for potential constructor.
|
||||
* spew.c (yylex): Handle it.
|
||||
* lex.c (identifier_type): Produce it.
|
||||
|
||||
* parse.y (complete_type_name): In :: case, don't push class binding.
|
||||
(complex_type_name): Ditto.
|
||||
|
||||
Wed Apr 17 15:02:40 1996 Mike Stump <mrs@cygnus.com>
|
||||
|
||||
* typeck.c (build_reinterpret_cast): Handle pointer to member
|
||||
functions.
|
||||
|
||||
Wed Apr 17 12:28:26 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
|
||||
|
||||
* lex.c (handle_cp_pragma): New function, with decl, doing the cc1plus
|
||||
pragmas.
|
||||
pragmas.
|
||||
(check_newline): Put the vtable/unit/implementation/interface pragma
|
||||
code into handle_cp_pragma, replacing it with a call.
|
||||
code into handle_cp_pragma, replacing it with a call.
|
||||
(handle_sysv_pragma): Give int return type, and take FINPUT and TOKEN
|
||||
args. Get the next token after handling the pragma token.
|
||||
args. Get the next token after handling the pragma token.
|
||||
|
||||
Wed Apr 17 10:28:34 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* cvt.c (cp_convert_to_pointer): Avoid doing base analysis on pmfs.
|
||||
(convert_to_pointer_force): Ditto.
|
||||
|
||||
* init.c (build_new): Fix array new without -fcheck-new.
|
||||
|
||||
Tue Apr 16 13:44:58 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* cp-tree.h, call.c, class.c, decl.c, parse.y, pt.c, rtti.c,
|
||||
tree.c: Lose TYPE_NESTED_NAME.
|
||||
|
||||
* parse.y (nested_name_specifier_1): Don't treat non-identifiers
|
||||
as identifiers.
|
||||
|
||||
* tree.def: Add VEC_INIT_EXPR.
|
||||
* expr.c (cplus_expand_expr): Handle it.
|
||||
* init.c (build_new): Use it instead of the RTL_EXPR nastiness and
|
||||
the extra file-scope symbol nastiness.
|
||||
|
||||
Mon Apr 15 16:21:29 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* method.c (make_thunk): Thunks are static.
|
||||
(emit_thunk): Use ASM_OUTPUT_MI_THUNK if it's defined.
|
||||
|
||||
* decl2.c (mark_vtable_entries): Emit thunks as needed.
|
||||
(finish_file): Don't emit them here.
|
||||
|
||||
Sun Apr 14 11:34:39 1996 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* rtti.c (build_dynamic_cast): Handle null pointers.
|
||||
(ifnonnull): New function.
|
||||
|
||||
Fri Apr 12 09:08:27 1996 Bob Manson <manson@charmed.cygnus.com>
|
||||
|
||||
* call.c (build_method_call): Remember the original basetype we
|
||||
were called with. Give an error message instead of trying
|
||||
(incorrectly) to call a non-static member function through a
|
||||
non-inherited class.
|
||||
|
||||
* search.c (expand_upcast_fixups): Mark the new fixup as
|
||||
DECL_ARTIFICIAL.
|
||||
|
||||
|
|
|
@ -1296,7 +1296,7 @@ find_scoped_type (type, inner_name, inner_types)
|
|||
if (TREE_PURPOSE (tags) == inner_name)
|
||||
{
|
||||
if (inner_types == NULL_TREE)
|
||||
return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags)));
|
||||
return TYPE_NAME (TREE_VALUE (tags));
|
||||
return resolve_scope_to_name (TREE_VALUE (tags), inner_types);
|
||||
}
|
||||
tags = TREE_CHAIN (tags);
|
||||
|
@ -1308,7 +1308,7 @@ find_scoped_type (type, inner_name, inner_types)
|
|||
{
|
||||
/* Code by raeburn. */
|
||||
if (inner_types == NULL_TREE)
|
||||
return DECL_NESTED_TYPENAME (tags);
|
||||
return tags;
|
||||
return resolve_scope_to_name (TREE_TYPE (tags), inner_types);
|
||||
}
|
||||
|
||||
|
@ -1569,6 +1569,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
|
|||
tree last;
|
||||
int pass;
|
||||
tree access = access_public_node;
|
||||
tree orig_basetype = basetype_path ? BINFO_TYPE (basetype_path) : NULL_TREE;
|
||||
|
||||
/* Range of cases for vtable optimization. */
|
||||
enum vtable_needs { not_needed, maybe_needed, unneeded, needed };
|
||||
|
@ -2416,21 +2417,23 @@ build_method_call (instance, name, parms, basetype_path, flags)
|
|||
if (TREE_CODE (fntype) == METHOD_TYPE && static_call_context
|
||||
&& !DECL_CONSTRUCTOR_P (function))
|
||||
{
|
||||
/* Let's be nice to the user for now, and give reasonable
|
||||
default behavior. */
|
||||
/* Let's be nasty to the user now, and give reasonable
|
||||
error messages. */
|
||||
instance_ptr = current_class_decl;
|
||||
if (instance_ptr)
|
||||
{
|
||||
if (basetype != current_class_type)
|
||||
{
|
||||
tree binfo = get_binfo (basetype, current_class_type, 1);
|
||||
if (binfo == NULL_TREE)
|
||||
{
|
||||
error_not_base_type (function, current_class_type);
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (basetype == error_mark_node)
|
||||
if (basetype == error_mark_node)
|
||||
return error_mark_node;
|
||||
else
|
||||
{
|
||||
if (orig_basetype != NULL_TREE)
|
||||
error_not_base_type (orig_basetype, current_class_type);
|
||||
else
|
||||
error_not_base_type (function, current_class_type);
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Only allow a static member function to call another static member
|
||||
|
|
|
@ -4388,9 +4388,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
|
|||
|| TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM))
|
||||
|| TREE_CODE (d) == CONST_DECL)
|
||||
break;
|
||||
/* Don't inject TYPE_NESTED_NAMEs. */
|
||||
else if (TREE_MANGLED (DECL_NAME (d))
|
||||
|| IDENTIFIER_TEMPLATE (DECL_NAME (d)))
|
||||
/* Don't inject cache decls. */
|
||||
else if (IDENTIFIER_TEMPLATE (DECL_NAME (d)))
|
||||
continue;
|
||||
DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))
|
||||
= tree_cons (NULL_TREE, d,
|
||||
|
|
|
@ -69,6 +69,11 @@ DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3)
|
|||
else it is NULL_TREE. */
|
||||
DEFTREECODE (THROW_EXPR, "throw_expr", "e", 1)
|
||||
|
||||
/* Initialization of a vector, used in build_new. Operand 0 is the target
|
||||
of the initialization, operand 1 is the initializer, and operand 2 is
|
||||
the number of elements. */
|
||||
DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", "e", 3)
|
||||
|
||||
/* Template definition. The following fields have the specified uses,
|
||||
although there are other macros in cp-tree.h that should be used for
|
||||
accessing this data.
|
||||
|
|
|
@ -1123,10 +1123,12 @@ struct lang_decl
|
|||
or virtual baseclasses. */
|
||||
#define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE))
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
/* Nonzero in IDENTIFIER_NODE means that this name is not the name the user
|
||||
gave; it's a DECL_NESTED_TYPENAME. Someone may want to set this on
|
||||
mangled function names, too, but it isn't currently. */
|
||||
#define TREE_MANGLED(NODE) (TREE_LANG_FLAG_0 (NODE))
|
||||
#endif
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
/* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
|
||||
|
@ -1310,12 +1312,6 @@ extern int flag_new_for_scope;
|
|||
#define DECL_VPARENT(NODE) ((NODE)->decl.arguments)
|
||||
#endif
|
||||
|
||||
/* Make a slot so we can implement nested types. This slot holds
|
||||
the IDENTIFIER_NODE that uniquely names the nested type. This
|
||||
is for TYPE_DECLs only. */
|
||||
#define DECL_NESTED_TYPENAME(NODE) ((NODE)->decl.arguments)
|
||||
#define TYPE_NESTED_NAME(NODE) (DECL_NESTED_TYPENAME (TYPE_NAME (NODE)))
|
||||
|
||||
#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.was_anonymous)
|
||||
|
||||
/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
|
||||
|
|
|
@ -133,6 +133,8 @@ cp_convert_to_pointer (type, expr)
|
|||
|
||||
if (TYPE_MAIN_VARIANT (type) != intype
|
||||
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
|
||||
&& IS_AGGR_TYPE (TREE_TYPE (type))
|
||||
&& IS_AGGR_TYPE (TREE_TYPE (intype))
|
||||
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
|
||||
{
|
||||
enum tree_code code = PLUS_EXPR;
|
||||
|
@ -281,6 +283,8 @@ convert_to_pointer_force (type, expr)
|
|||
|
||||
if (TYPE_MAIN_VARIANT (type) != intype
|
||||
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
|
||||
&& IS_AGGR_TYPE (TREE_TYPE (type))
|
||||
&& IS_AGGR_TYPE (TREE_TYPE (intype))
|
||||
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
|
||||
{
|
||||
enum tree_code code = PLUS_EXPR;
|
||||
|
|
125
gcc/cp/decl.c
125
gcc/cp/decl.c
|
@ -1955,56 +1955,6 @@ set_identifier_type_value (id, type)
|
|||
set_identifier_type_value_with_scope (id, type, inner_binding_level);
|
||||
}
|
||||
|
||||
/* Subroutine "set_nested_typename" builds the nested-typename of
|
||||
the type decl in question. (Argument CLASSNAME can actually be
|
||||
a function as well, if that's the smallest containing scope.) */
|
||||
|
||||
void
|
||||
set_nested_typename (decl, classname, name, type)
|
||||
tree decl, classname, name, type;
|
||||
{
|
||||
char *buf;
|
||||
my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
|
||||
|
||||
/* No need to do this for anonymous names, since they're unique. */
|
||||
if (ANON_AGGRNAME_P (name))
|
||||
{
|
||||
DECL_NESTED_TYPENAME (decl) = name;
|
||||
return;
|
||||
}
|
||||
|
||||
if (classname == NULL_TREE)
|
||||
classname = get_identifier ("");
|
||||
|
||||
my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
|
||||
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
|
||||
buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
|
||||
+ IDENTIFIER_LENGTH (name));
|
||||
sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
|
||||
IDENTIFIER_POINTER (name));
|
||||
DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
|
||||
TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
|
||||
|
||||
/* Create an extra decl so that the nested name will have a type value
|
||||
where appropriate. */
|
||||
{
|
||||
tree nested, type_decl;
|
||||
nested = DECL_NESTED_TYPENAME (decl);
|
||||
type_decl = build_decl (TYPE_DECL, nested, type);
|
||||
DECL_NESTED_TYPENAME (type_decl) = nested;
|
||||
SET_DECL_ARTIFICIAL (type_decl);
|
||||
/* Mark the TYPE_DECL node created just above as a gratuitous one so that
|
||||
dwarfout.c will know not to generate a TAG_typedef DIE for it, and
|
||||
sdbout.c won't try to output a .def for "::foo". */
|
||||
DECL_IGNORED_P (type_decl) = 1;
|
||||
|
||||
/* Remove this when local classes are fixed. */
|
||||
SET_IDENTIFIER_TYPE_VALUE (nested, type);
|
||||
|
||||
pushdecl_nonclass_level (type_decl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pop off extraneous binding levels left over due to syntax errors.
|
||||
|
||||
We don't pop past namespaces, as they might be valid. */
|
||||
|
@ -2138,19 +2088,6 @@ pushtag (name, type, globalize)
|
|||
}
|
||||
|
||||
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
|
||||
|
||||
if (context == NULL_TREE)
|
||||
/* Non-nested class. */
|
||||
set_nested_typename (d, NULL_TREE, name, type);
|
||||
else if (context && TREE_CODE (context) == FUNCTION_DECL)
|
||||
/* Function-nested class. */
|
||||
set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl),
|
||||
name, type);
|
||||
else /* if (context && IS_AGGR_TYPE (context)) */
|
||||
/* Class-nested class. */
|
||||
set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
|
||||
name, type);
|
||||
|
||||
DECL_ASSEMBLER_NAME (d)
|
||||
= get_identifier (build_overload_name (type, 1, 1));
|
||||
}
|
||||
|
@ -2681,8 +2618,6 @@ duplicate_decls (newdecl, olddecl)
|
|||
register tree newtype = TREE_TYPE (newdecl);
|
||||
register tree oldtype = TREE_TYPE (olddecl);
|
||||
|
||||
DECL_NESTED_TYPENAME (newdecl) = DECL_NESTED_TYPENAME (olddecl);
|
||||
|
||||
if (newtype != error_mark_node && oldtype != error_mark_node
|
||||
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
|
||||
{
|
||||
|
@ -3160,12 +3095,6 @@ pushdecl (x)
|
|||
}
|
||||
my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
|
||||
|
||||
/* Don't set nested_typename on template type parms, for instance.
|
||||
Any artificial decls that need DECL_NESTED_TYPENAME will have it
|
||||
set in pushtag. */
|
||||
if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
|
||||
set_nested_typename (x, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, DECL_NAME (x), type);
|
||||
|
||||
if (type != error_mark_node
|
||||
&& TYPE_NAME (type)
|
||||
&& TYPE_IDENTIFIER (type))
|
||||
|
@ -3486,12 +3415,6 @@ pushdecl_class_level (x)
|
|||
if (TREE_CODE (x) == TYPE_DECL)
|
||||
{
|
||||
set_identifier_type_value (name, TREE_TYPE (x));
|
||||
|
||||
/* Don't set nested_typename on template type parms, for instance.
|
||||
Any artificial decls that need DECL_NESTED_TYPENAME will have it
|
||||
set in pushtag. */
|
||||
if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
|
||||
set_nested_typename (x, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, name, TREE_TYPE (x));
|
||||
}
|
||||
}
|
||||
return x;
|
||||
|
@ -4105,8 +4028,7 @@ lookup_tag (form, name, binding_level, thislevel_only)
|
|||
else
|
||||
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
|
||||
{
|
||||
if (TREE_PURPOSE (tail) == name
|
||||
|| TYPE_NESTED_NAME (TREE_VALUE (tail)) == name)
|
||||
if (TREE_PURPOSE (tail) == name)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (TREE_VALUE (tail));
|
||||
/* Should tighten this up; it'll probably permit
|
||||
|
@ -4327,7 +4249,12 @@ tree
|
|||
make_typename_type (context, name)
|
||||
tree context, name;
|
||||
{
|
||||
tree t, d, i;
|
||||
tree t, d;
|
||||
|
||||
if (TREE_CODE (name) == TYPE_DECL)
|
||||
name = DECL_NAME (name);
|
||||
else if (TREE_CODE (name) != IDENTIFIER_NODE)
|
||||
my_friendly_abort (2000);
|
||||
|
||||
if (! current_template_parms
|
||||
|| ! uses_template_parms (context))
|
||||
|
@ -4345,16 +4272,12 @@ make_typename_type (context, name)
|
|||
push_obstacks (&permanent_obstack, &permanent_obstack);
|
||||
t = make_lang_type (TYPENAME_TYPE);
|
||||
d = build_decl (TYPE_DECL, name, t);
|
||||
i = make_anon_name ();
|
||||
if (current_template_parms)
|
||||
pop_obstacks ();
|
||||
|
||||
TYPE_CONTEXT (t) = context;
|
||||
TYPE_MAIN_DECL (TREE_TYPE (d)) = d;
|
||||
DECL_CONTEXT (d) = context;
|
||||
DECL_NESTED_TYPENAME (d) = i;
|
||||
IDENTIFIER_LOCAL_VALUE (i) = d;
|
||||
TREE_TYPE (i) = t;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
@ -4396,6 +4319,8 @@ lookup_name_real (name, prefer_type, nonclass)
|
|||
{
|
||||
if (type == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
|
||||
type = TREE_TYPE (type);
|
||||
|
||||
type = complete_type (type);
|
||||
|
||||
|
@ -4437,6 +4362,18 @@ lookup_name_real (name, prefer_type, nonclass)
|
|||
else
|
||||
val = NULL_TREE;
|
||||
|
||||
#if 0
|
||||
if (got_scope && current_template_parms
|
||||
&& uses_template_parms (got_scope)
|
||||
&& val && TREE_CODE (val) == TYPE_DECL
|
||||
&& ! DECL_ARTIFICIAL (val))
|
||||
{
|
||||
tree t = make_typename_type (got_scope, DECL_NAME (val));
|
||||
TREE_TYPE (t) = TREE_TYPE (val);
|
||||
val = TYPE_MAIN_DECL (t);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (got_scope)
|
||||
goto done;
|
||||
|
||||
|
@ -8992,14 +8929,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
|
|||
{
|
||||
tree d = TYPE_NAME (type), c = DECL_CONTEXT (d);
|
||||
|
||||
if (!c)
|
||||
set_nested_typename (d, NULL_TREE, declarator, type);
|
||||
else if (TREE_CODE (c) == FUNCTION_DECL)
|
||||
set_nested_typename (d, DECL_ASSEMBLER_NAME (c),
|
||||
declarator, type);
|
||||
else
|
||||
set_nested_typename (d, TYPE_NESTED_NAME (c), declarator, type);
|
||||
|
||||
DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
|
||||
DECL_ASSEMBLER_NAME (d)
|
||||
= get_identifier (build_overload_name (type, 1, 1));
|
||||
|
@ -10251,6 +10180,7 @@ xref_tag (code_type_node, name, binfo, globalize)
|
|||
int temp = 0;
|
||||
register tree ref, t;
|
||||
struct binding_level *b = inner_binding_level;
|
||||
int got_type = 0;
|
||||
|
||||
tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
|
||||
switch (tag_code)
|
||||
|
@ -10275,7 +10205,8 @@ xref_tag (code_type_node, name, binfo, globalize)
|
|||
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
|
||||
{
|
||||
t = name;
|
||||
name = TYPE_NESTED_NAME (t);
|
||||
name = TYPE_IDENTIFIER (t);
|
||||
got_type = 1;
|
||||
}
|
||||
else
|
||||
t = IDENTIFIER_TYPE_VALUE (name);
|
||||
|
@ -10289,11 +10220,11 @@ xref_tag (code_type_node, name, binfo, globalize)
|
|||
cp_pedwarn ("redeclaration of template type-parameter `%T'", name);
|
||||
cp_pedwarn_at (" previously declared here", t);
|
||||
}
|
||||
/* If we know we are defining this tag, only look it up in this scope
|
||||
* and don't try to find it as a type. */
|
||||
if (t && TYPE_CONTEXT (t) && TREE_MANGLED (name))
|
||||
if (t && TYPE_CONTEXT (t) && got_type)
|
||||
ref = t;
|
||||
else
|
||||
/* If we know we are defining this tag, only look it up in this scope
|
||||
* and don't try to find it as a type. */
|
||||
ref = lookup_tag (code, name, b, 1);
|
||||
}
|
||||
else
|
||||
|
@ -10478,6 +10409,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
|
|||
basetype = TREE_TYPE (basetype);
|
||||
if (!basetype
|
||||
|| (TREE_CODE (basetype) != RECORD_TYPE
|
||||
&& TREE_CODE (basetype) != TYPENAME_TYPE
|
||||
&& TREE_CODE (basetype) != TEMPLATE_TYPE_PARM))
|
||||
{
|
||||
cp_error ("base type `%T' fails to be a struct or class type",
|
||||
|
@ -10487,6 +10419,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
|
|||
#if 1
|
||||
/* This code replaces similar code in layout_basetypes. */
|
||||
else if (TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
|
||||
&& TREE_CODE (basetype) != TYPENAME_TYPE
|
||||
&& TYPE_SIZE (complete_type (basetype)) == NULL_TREE)
|
||||
{
|
||||
cp_error ("base class `%T' has incomplete type", basetype);
|
||||
|
|
|
@ -150,7 +150,7 @@ int warn_implicit = 1;
|
|||
|
||||
int warn_ctor_dtor_privacy = 1;
|
||||
|
||||
/* True if we want to implement vtbvales using "thunks".
|
||||
/* True if we want to implement vtables using "thunks".
|
||||
The default is off now, but will be on later. */
|
||||
|
||||
int flag_vtable_thunks;
|
||||
|
@ -2448,6 +2448,11 @@ mark_vtable_entries (decl)
|
|||
TREE_ADDRESSABLE (fn) = 1;
|
||||
if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
|
||||
TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
|
||||
if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn))
|
||||
{
|
||||
DECL_EXTERNAL (fn) = 0;
|
||||
emit_thunk (fn);
|
||||
}
|
||||
mark_used (fn);
|
||||
}
|
||||
}
|
||||
|
@ -3187,11 +3192,9 @@ finish_file ()
|
|||
|
||||
for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
|
||||
{
|
||||
if (TREE_CODE (vars) == THUNK_DECL)
|
||||
emit_thunk (vars);
|
||||
else if (TREE_CODE (vars) == FUNCTION_DECL
|
||||
&& ! DECL_INTERFACE_KNOWN (vars)
|
||||
&& DECL_C_STATIC (vars))
|
||||
if (TREE_CODE (vars) == FUNCTION_DECL
|
||||
&& ! DECL_INTERFACE_KNOWN (vars)
|
||||
&& DECL_C_STATIC (vars))
|
||||
TREE_PUBLIC (vars) = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -234,6 +234,14 @@ cplus_expand_expr (exp, target, tmode, modifier)
|
|||
return temp;
|
||||
}
|
||||
|
||||
case VEC_INIT_EXPR:
|
||||
return expand_expr
|
||||
(expand_vec_init
|
||||
(NULL_TREE, TREE_OPERAND (exp, 0),
|
||||
build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
|
||||
integer_one_node, 1),
|
||||
TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2823,17 +2823,7 @@ build_new (placement, decl, init, use_global_new)
|
|||
}
|
||||
|
||||
if (flag_check_new && rval)
|
||||
{
|
||||
/* For array new, we need to make sure that the call to new is
|
||||
not expanded as part of the RTL_EXPR for the initialization,
|
||||
so we can't just use save_expr here. */
|
||||
|
||||
alloc_temp = build (VAR_DECL, TREE_TYPE (rval));
|
||||
layout_decl (alloc_temp, 0);
|
||||
alloc_expr = build (TARGET_EXPR, TREE_TYPE (rval), alloc_temp, rval, 0);
|
||||
TREE_SIDE_EFFECTS (alloc_expr) = 1;
|
||||
rval = alloc_temp;
|
||||
}
|
||||
alloc_expr = rval = save_expr (rval);
|
||||
else
|
||||
alloc_expr = NULL_TREE;
|
||||
|
||||
|
@ -2930,6 +2920,10 @@ build_new (placement, decl, init, use_global_new)
|
|||
else
|
||||
rval = error_mark_node;
|
||||
}
|
||||
else
|
||||
rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
|
||||
save_expr (rval), init, nelts);
|
||||
#if 0
|
||||
else if (current_function_decl == NULL_TREE)
|
||||
{
|
||||
extern tree static_aggregates;
|
||||
|
@ -3010,23 +3004,19 @@ build_new (placement, decl, init, use_global_new)
|
|||
}
|
||||
rval = xval;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (TYPE_READONLY (true_type))
|
||||
cp_error ("uninitialized const in `new' of `%#T'", true_type);
|
||||
|
||||
done:
|
||||
|
||||
if (alloc_expr)
|
||||
if (alloc_expr && rval != alloc_expr)
|
||||
{
|
||||
/* Did we modify the storage? */
|
||||
if (rval != alloc_temp)
|
||||
{
|
||||
tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
|
||||
integer_zero_node, 1);
|
||||
rval = build_conditional_expr (ifexp, rval, alloc_temp);
|
||||
}
|
||||
else
|
||||
rval = alloc_expr;
|
||||
tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
|
||||
integer_zero_node, 1);
|
||||
rval = build_conditional_expr (ifexp, rval, alloc_expr);
|
||||
}
|
||||
|
||||
if (rval && TREE_TYPE (rval) != build_pointer_type (type))
|
||||
|
|
140
gcc/cp/lex.c
140
gcc/cp/lex.c
|
@ -1743,7 +1743,8 @@ check_for_missing_semicolon (type)
|
|||
if ((yychar > 255
|
||||
&& yychar != SCSPEC
|
||||
&& yychar != IDENTIFIER
|
||||
&& yychar != TYPENAME)
|
||||
&& yychar != TYPENAME
|
||||
&& yychar != SELFNAME)
|
||||
|| end_of_file)
|
||||
{
|
||||
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
|
||||
|
@ -1911,12 +1912,6 @@ check_newline ()
|
|||
&& getch () == 'm'
|
||||
&& getch () == 'a')
|
||||
{
|
||||
c = getch ();
|
||||
while (c == ' ' || c == '\t')
|
||||
c = getch ();
|
||||
put_back (c);
|
||||
if (c == '\n' || c == EOF)
|
||||
goto skipline;
|
||||
token = real_yylex ();
|
||||
if (token == IDENTIFIER
|
||||
&& TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
|
||||
|
@ -1999,15 +1994,9 @@ check_newline ()
|
|||
/* Here we have just seen `#ident '.
|
||||
A string constant should follow. */
|
||||
|
||||
while (c == ' ' || c == '\t')
|
||||
c = getch ();
|
||||
|
||||
/* If no argument, ignore the line. */
|
||||
if (c == EOF)
|
||||
goto skipline;
|
||||
|
||||
put_back (c);
|
||||
token = real_yylex ();
|
||||
if (token == END_OF_LINE)
|
||||
goto skipline;
|
||||
if (token != STRING
|
||||
|| TREE_CODE (yylval.ttype) != STRING_CST)
|
||||
{
|
||||
|
@ -2281,6 +2270,7 @@ linenum:
|
|||
skipline:
|
||||
linemode = 0;
|
||||
end_of_file = 0;
|
||||
nextchar = -1;
|
||||
while ((c = getch ()) != EOF && c != '\n');
|
||||
return c;
|
||||
}
|
||||
|
@ -2471,6 +2461,10 @@ identifier_type (decl)
|
|||
return NSNAME;
|
||||
if (TREE_CODE (decl) != TYPE_DECL)
|
||||
return IDENTIFIER;
|
||||
if (((got_scope && TREE_TYPE (decl) == got_scope)
|
||||
|| TREE_TYPE (decl) == current_class_type)
|
||||
&& DECL_ARTIFICIAL (decl))
|
||||
return SELFNAME;
|
||||
return TYPENAME;
|
||||
}
|
||||
|
||||
|
@ -4389,7 +4383,6 @@ handle_cp_pragma (pname)
|
|||
char *pname;
|
||||
{
|
||||
register int token;
|
||||
register int c;
|
||||
|
||||
if (! strcmp (pname, "vtable"))
|
||||
{
|
||||
|
@ -4412,10 +4405,8 @@ handle_cp_pragma (pname)
|
|||
= perm_tree_cons (NULL_TREE,
|
||||
get_identifier (TREE_STRING_POINTER (yylval.ttype)),
|
||||
pending_vtables);
|
||||
if (nextchar < 0)
|
||||
nextchar = getch ();
|
||||
c = nextchar;
|
||||
if (c != EOF)
|
||||
token = real_yylex ();
|
||||
if (token != END_OF_LINE)
|
||||
warning ("trailing characters ignored");
|
||||
return 1;
|
||||
}
|
||||
|
@ -4428,10 +4419,8 @@ handle_cp_pragma (pname)
|
|||
error ("invalid #pragma unit");
|
||||
return -1;
|
||||
}
|
||||
if (nextchar < 0)
|
||||
nextchar = getch ();
|
||||
c = nextchar;
|
||||
if (c != EOF)
|
||||
token = real_yylex ();
|
||||
if (token != END_OF_LINE)
|
||||
warning ("trailing characters ignored");
|
||||
return 1;
|
||||
}
|
||||
|
@ -4443,15 +4432,10 @@ handle_cp_pragma (pname)
|
|||
|
||||
main_filename = FILE_NAME_NONDIRECTORY (main_filename);
|
||||
|
||||
do
|
||||
token = real_yylex ();
|
||||
|
||||
if (token != END_OF_LINE)
|
||||
{
|
||||
c = getch ();
|
||||
} while (c == ' ' || c == '\t');
|
||||
|
||||
if (c != EOF)
|
||||
{
|
||||
put_back (c);
|
||||
token = real_yylex ();
|
||||
if (token != STRING
|
||||
|| TREE_CODE (yylval.ttype) != STRING_CST)
|
||||
{
|
||||
|
@ -4459,44 +4443,38 @@ handle_cp_pragma (pname)
|
|||
return -1;
|
||||
}
|
||||
main_filename = TREE_STRING_POINTER (yylval.ttype);
|
||||
c = getch();
|
||||
put_back (c);
|
||||
|
||||
while (c == ' ' || c == '\t')
|
||||
c = getch ();
|
||||
|
||||
while (c != EOF)
|
||||
}
|
||||
|
||||
while (token != END_OF_LINE)
|
||||
{
|
||||
if (!warned_already && extra_warnings)
|
||||
{
|
||||
if (!warned_already && extra_warnings
|
||||
&& c != ' ' && c != '\t')
|
||||
{
|
||||
warning ("garbage after `#pragma interface' ignored");
|
||||
warned_already = 1;
|
||||
}
|
||||
c = getch ();
|
||||
warning ("garbage after `#pragma interface' ignored");
|
||||
warned_already = 1;
|
||||
}
|
||||
token = real_yylex ();
|
||||
}
|
||||
|
||||
write_virtuals = 3;
|
||||
write_virtuals = 3;
|
||||
|
||||
if (impl_file_chain == 0)
|
||||
{
|
||||
/* If this is zero at this point, then we are
|
||||
auto-implementing. */
|
||||
if (main_input_filename == 0)
|
||||
main_input_filename = input_filename;
|
||||
if (impl_file_chain == 0)
|
||||
{
|
||||
/* If this is zero at this point, then we are
|
||||
auto-implementing. */
|
||||
if (main_input_filename == 0)
|
||||
main_input_filename = input_filename;
|
||||
|
||||
#ifdef AUTO_IMPLEMENT
|
||||
filename = FILE_NAME_NONDIRECTORY (main_input_filename);
|
||||
fi = get_time_identifier (filename);
|
||||
fi = IDENTIFIER_CLASS_VALUE (fi);
|
||||
TREE_INT_CST_LOW (fi) = 0;
|
||||
TREE_INT_CST_HIGH (fi) = 1;
|
||||
/* Get default. */
|
||||
impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
|
||||
impl_file_chain->filename = filename;
|
||||
impl_file_chain->next = 0;
|
||||
filename = FILE_NAME_NONDIRECTORY (main_input_filename);
|
||||
fi = get_time_identifier (filename);
|
||||
fi = IDENTIFIER_CLASS_VALUE (fi);
|
||||
TREE_INT_CST_LOW (fi) = 0;
|
||||
TREE_INT_CST_HIGH (fi) = 1;
|
||||
/* Get default. */
|
||||
impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
|
||||
impl_file_chain->filename = filename;
|
||||
impl_file_chain->next = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
interface_only = interface_strcmp (main_filename);
|
||||
|
@ -4514,28 +4492,25 @@ handle_cp_pragma (pname)
|
|||
|
||||
main_filename = FILE_NAME_NONDIRECTORY (main_filename);
|
||||
token = real_yylex ();
|
||||
if (token != STRING
|
||||
|| TREE_CODE (yylval.ttype) != STRING_CST)
|
||||
if (token != END_OF_LINE)
|
||||
{
|
||||
error ("invalid `#pragma implementation'");
|
||||
return -1;
|
||||
if (token != STRING
|
||||
|| TREE_CODE (yylval.ttype) != STRING_CST)
|
||||
{
|
||||
error ("invalid `#pragma implementation'");
|
||||
return -1;
|
||||
}
|
||||
main_filename = TREE_STRING_POINTER (yylval.ttype);
|
||||
}
|
||||
main_filename = TREE_STRING_POINTER (yylval.ttype);
|
||||
c = getch();
|
||||
put_back (c);
|
||||
|
||||
while (c == ' ' || c == '\t')
|
||||
c = getch ();
|
||||
|
||||
while (c != EOF)
|
||||
while (token != END_OF_LINE)
|
||||
{
|
||||
if (!warned_already && extra_warnings
|
||||
&& c != ' ' && c != '\t')
|
||||
if (!warned_already && extra_warnings)
|
||||
{
|
||||
warning ("garbage after `#pragma implementation' ignored");
|
||||
warned_already = 1;
|
||||
}
|
||||
c = getch ();
|
||||
token = real_yylex ();
|
||||
}
|
||||
|
||||
if (write_virtuals == 3)
|
||||
|
@ -4610,38 +4585,29 @@ handle_sysv_pragma (finput, token)
|
|||
case STRING:
|
||||
case CONSTANT:
|
||||
handle_pragma_token ("ignored", yylval.ttype);
|
||||
token = yylex ();
|
||||
break;
|
||||
case '(':
|
||||
handle_pragma_token ("(", NULL_TREE);
|
||||
token = yylex ();
|
||||
break;
|
||||
case ')':
|
||||
handle_pragma_token (")", NULL_TREE);
|
||||
token = yylex ();
|
||||
break;
|
||||
case ',':
|
||||
handle_pragma_token (",", NULL_TREE);
|
||||
token = yylex ();
|
||||
break;
|
||||
case '=':
|
||||
handle_pragma_token ("=", NULL_TREE);
|
||||
token = yylex ();
|
||||
break;
|
||||
case LEFT_RIGHT:
|
||||
handle_pragma_token ("(", NULL_TREE);
|
||||
handle_pragma_token (")", NULL_TREE);
|
||||
token = yylex ();
|
||||
break;
|
||||
case END_OF_LINE:
|
||||
handle_pragma_token (NULL_PTR, NULL_TREE);
|
||||
return 1;
|
||||
default:
|
||||
handle_pragma_token (NULL_PTR, NULL_TREE);
|
||||
while (yylex () != END_OF_LINE)
|
||||
/* continue */;
|
||||
return 1;
|
||||
}
|
||||
token = real_yylex ();
|
||||
}
|
||||
}
|
||||
#endif /* HANDLE_SYSV_PRAGMA */
|
||||
|
|
|
@ -1819,7 +1819,7 @@ make_thunk (function, delta)
|
|||
DECL_INITIAL (thunk) = function;
|
||||
THUNK_DELTA (thunk) = delta;
|
||||
DECL_EXTERNAL (thunk) = 1;
|
||||
TREE_PUBLIC (thunk) = 1;
|
||||
TREE_PUBLIC (thunk) = 0;
|
||||
/* So that finish_file can write out any thunks that need to be: */
|
||||
pushdecl_top_level (thunk);
|
||||
}
|
||||
|
@ -1831,12 +1831,12 @@ emit_thunk (thunk_fndecl)
|
|||
tree thunk_fndecl;
|
||||
{
|
||||
rtx insns;
|
||||
char *fnname;
|
||||
char buffer[250];
|
||||
tree argp;
|
||||
struct args_size stack_args_size;
|
||||
tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);
|
||||
int delta = THUNK_DELTA (thunk_fndecl);
|
||||
char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
|
||||
int tem;
|
||||
int failure = 0;
|
||||
|
||||
|
@ -1856,16 +1856,14 @@ emit_thunk (thunk_fndecl)
|
|||
|
||||
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
|
||||
|
||||
if (! TREE_PUBLIC (function))
|
||||
TREE_PUBLIC (thunk_fndecl) = 0;
|
||||
if (DECL_EXTERNAL (function))
|
||||
return;
|
||||
DECL_EXTERNAL (thunk_fndecl) = 0;
|
||||
|
||||
decl_printable_name = thunk_printable_name;
|
||||
if (current_function_decl)
|
||||
abort ();
|
||||
current_function_decl = thunk_fndecl;
|
||||
#ifdef ASM_OUTPUT_MI_THUNK
|
||||
assemble_start_function (thunk_fndecl, fnname);
|
||||
ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
|
||||
#else
|
||||
init_function_start (thunk_fndecl, input_filename, lineno);
|
||||
pushlevel (0);
|
||||
expand_start_bindings (1);
|
||||
|
@ -2031,12 +2029,9 @@ emit_thunk (thunk_fndecl)
|
|||
|
||||
/* Now turn the rtl into assembler code. */
|
||||
|
||||
{
|
||||
char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
|
||||
assemble_start_function (thunk_fndecl, fnname);
|
||||
final (insns, asm_out_file, optimize, 0);
|
||||
assemble_end_function (thunk_fndecl, fnname);
|
||||
};
|
||||
assemble_start_function (thunk_fndecl, fnname);
|
||||
final (insns, asm_out_file, optimize, 0);
|
||||
assemble_end_function (thunk_fndecl, fnname);
|
||||
|
||||
exit_rest_of_compilation:
|
||||
|
||||
|
@ -2047,6 +2042,7 @@ emit_thunk (thunk_fndecl)
|
|||
resume_temporary_allocation ();
|
||||
|
||||
decl_printable_name = save_decl_printable_name;
|
||||
#endif /* ASM_OUTPUT_MI_THUNK */
|
||||
current_function_decl = 0;
|
||||
}
|
||||
|
||||
|
|
135
gcc/cp/parse.y
135
gcc/cp/parse.y
|
@ -108,6 +108,7 @@ empty_parms ()
|
|||
In some contexts, they are treated just like IDENTIFIER,
|
||||
but they can also serve as typespecs in declarations. */
|
||||
%token TYPENAME
|
||||
%token SELFNAME
|
||||
|
||||
/* Reserved words that specify storage class.
|
||||
yylval contains an IDENTIFIER_NODE which indicates which one. */
|
||||
|
@ -160,7 +161,7 @@ empty_parms ()
|
|||
%nonassoc IF
|
||||
%nonassoc ELSE
|
||||
|
||||
%left IDENTIFIER TYPENAME PTYPENAME SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD
|
||||
%left IDENTIFIER TYPENAME SELFNAME PTYPENAME SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS TYPEOF SIGOF OPERATOR NSNAME TYPENAME_KEYWORD
|
||||
|
||||
%left '{' ',' ';'
|
||||
|
||||
|
@ -191,7 +192,7 @@ empty_parms ()
|
|||
%type <code> unop
|
||||
|
||||
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
|
||||
%type <ttype> paren_expr_or_null nontrivial_exprlist
|
||||
%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
|
||||
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
|
||||
%type <ttype> typed_declspecs reserved_declspecs boolean.literal
|
||||
%type <ttype> typed_typespecs reserved_typespecquals
|
||||
|
@ -230,7 +231,7 @@ empty_parms ()
|
|||
%token <ttype> TYPENAME_ELLIPSIS PTYPENAME
|
||||
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
|
||||
%token <ttype> PRE_PARSED_CLASS_DECL
|
||||
%type <ttype> fn.def1 /* Not really! */
|
||||
%type <ttype> fn.def1 /* Not really! */ component_constructor_declarator
|
||||
%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
|
||||
%type <itype> ctor_initializer_opt
|
||||
%type <ttype> named_class_head named_class_head_sans_basetype
|
||||
|
@ -552,7 +553,7 @@ fndef:
|
|||
;
|
||||
|
||||
constructor_declarator:
|
||||
nested_name_specifier type_name '('
|
||||
nested_name_specifier SELFNAME '('
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $1, $2);
|
||||
if ($1 != current_class_type)
|
||||
|
@ -563,7 +564,7 @@ constructor_declarator:
|
|||
}
|
||||
parmlist ')' type_quals
|
||||
{ $$ = build_parse_node (CALL_EXPR, $<ttype>4, $5, $7); }
|
||||
| nested_name_specifier type_name LEFT_RIGHT type_quals
|
||||
| nested_name_specifier SELFNAME LEFT_RIGHT type_quals
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $1, $2);
|
||||
if ($1 != current_class_type)
|
||||
|
@ -573,7 +574,7 @@ constructor_declarator:
|
|||
}
|
||||
$$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $4);
|
||||
}
|
||||
| global_scope nested_name_specifier type_name '('
|
||||
| global_scope nested_name_specifier SELFNAME '('
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $2, $3);
|
||||
if ($2 != current_class_type)
|
||||
|
@ -584,7 +585,7 @@ constructor_declarator:
|
|||
}
|
||||
parmlist ')' type_quals
|
||||
{ $$ = build_parse_node (CALL_EXPR, $<ttype>5, $6, $8); }
|
||||
| global_scope nested_name_specifier type_name LEFT_RIGHT type_quals
|
||||
| global_scope nested_name_specifier SELFNAME LEFT_RIGHT type_quals
|
||||
{
|
||||
$$ = build_parse_node (SCOPE_REF, $2, $3);
|
||||
if ($2 != current_class_type)
|
||||
|
@ -630,26 +631,27 @@ fn.def1:
|
|||
$$ = NULL_TREE; }
|
||||
;
|
||||
|
||||
component_constructor_declarator:
|
||||
SELFNAME '(' parmlist ')' type_quals
|
||||
{ $$ = build_parse_node (CALL_EXPR, $1, $3, $5); }
|
||||
| SELFNAME LEFT_RIGHT type_quals
|
||||
{ $$ = build_parse_node (CALL_EXPR, $1, empty_parms (), $3); }
|
||||
;
|
||||
|
||||
/* more C++ complexity. See component_decl for a comment on the
|
||||
reduce/reduce conflict introduced by these rules. */
|
||||
fn.def2:
|
||||
typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
|
||||
declmods component_constructor_declarator exception_specification_opt
|
||||
{ tree specs = strip_attrs ($1);
|
||||
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5);
|
||||
$$ = start_method (TREE_CHAIN (specs), $$, $6);
|
||||
$$ = start_method (specs, $2, $3);
|
||||
rest_of_mdef:
|
||||
if (! $$)
|
||||
YYERROR1;
|
||||
if (yychar == YYEMPTY)
|
||||
yychar = YYLEX;
|
||||
reinit_parse_for_method (yychar, $$); }
|
||||
| typed_declspecs LEFT_RIGHT type_quals exception_specification_opt
|
||||
{ tree specs = strip_attrs ($1);
|
||||
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
|
||||
empty_parms (), $3);
|
||||
$$ = start_method (TREE_CHAIN (specs), $$, $4);
|
||||
goto rest_of_mdef;
|
||||
}
|
||||
| component_constructor_declarator exception_specification_opt
|
||||
{ $$ = start_method (NULL_TREE, $1, $2); goto rest_of_mdef; }
|
||||
| typed_declspecs declarator exception_specification_opt
|
||||
{ tree specs = strip_attrs ($1);
|
||||
$$ = start_method (specs, $2, $3); goto rest_of_mdef; }
|
||||
|
@ -757,6 +759,7 @@ member_init: '(' nonnull_exprlist ')'
|
|||
identifier:
|
||||
IDENTIFIER
|
||||
| TYPENAME
|
||||
| SELFNAME
|
||||
| PTYPENAME
|
||||
| NSNAME
|
||||
;
|
||||
|
@ -823,6 +826,18 @@ template_type:
|
|||
if ($$ != error_mark_node)
|
||||
$$ = TYPE_STUB_DECL ($$);
|
||||
}
|
||||
| SELFNAME '<' template_arg_list template_close_bracket
|
||||
{
|
||||
$$ = lookup_template_class ($1, $3, NULL_TREE);
|
||||
if ($$ != error_mark_node)
|
||||
$$ = TYPE_STUB_DECL ($$);
|
||||
}
|
||||
| SELFNAME '<' template_close_bracket
|
||||
{
|
||||
$$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
|
||||
if ($$ != error_mark_node)
|
||||
$$ = TYPE_STUB_DECL ($$);
|
||||
}
|
||||
;
|
||||
|
||||
template_close_bracket:
|
||||
|
@ -1192,6 +1207,7 @@ notype_unqualified_id:
|
|||
unqualified_id:
|
||||
notype_unqualified_id
|
||||
| TYPENAME
|
||||
| SELFNAME
|
||||
;
|
||||
|
||||
expr_or_declarator:
|
||||
|
@ -2305,6 +2321,10 @@ base_class:
|
|||
|
||||
base_class.1:
|
||||
complete_type_name
|
||||
| TYPENAME_KEYWORD nested_name_specifier identifier
|
||||
{ $$ = TYPE_MAIN_DECL (make_typename_type ($2, $3)); }
|
||||
| TYPENAME_KEYWORD global_scope nested_name_specifier identifier
|
||||
{ $$ = TYPE_MAIN_DECL (make_typename_type ($3, $4)); }
|
||||
| SIGOF '(' expr ')'
|
||||
{
|
||||
if (current_aggr == signature_type_node)
|
||||
|
@ -2574,34 +2594,13 @@ component_decl_1:
|
|||
should "A::foo" be declared as a function or "A::bar" as a data
|
||||
member? In other words, is "bar" an after_type_declarator or a
|
||||
parmlist? */
|
||||
| typed_declspecs '(' parmlist ')' type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
|
||||
| declmods component_constructor_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
|
||||
{ tree specs, attrs;
|
||||
split_specs_attrs ($1, &specs, &attrs);
|
||||
if (TREE_VALUE (specs) == current_class_type)
|
||||
{
|
||||
if (TREE_CHAIN (specs) == NULL_TREE)
|
||||
specs = get_decl_list (current_class_name);
|
||||
else
|
||||
TREE_VALUE (specs) = current_class_name;
|
||||
}
|
||||
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
|
||||
$3, $5);
|
||||
$$ = grokfield ($$, TREE_CHAIN (specs), $6, $9, $7,
|
||||
build_tree_list ($8, attrs)); }
|
||||
| typed_declspecs LEFT_RIGHT type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
|
||||
{ tree specs, attrs;
|
||||
split_specs_attrs ($1, &specs, &attrs);
|
||||
if (TREE_VALUE (specs) == current_class_type)
|
||||
{
|
||||
if (TREE_CHAIN (specs) == NULL_TREE)
|
||||
specs = get_decl_list (current_class_name);
|
||||
else
|
||||
TREE_VALUE (specs) = current_class_name;
|
||||
}
|
||||
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
|
||||
empty_parms (), $3);
|
||||
$$ = grokfield ($$, TREE_CHAIN (specs), $4, $7, $5,
|
||||
build_tree_list ($6, attrs)); }
|
||||
$$ = grokfield ($2, specs, $3, $6, $4,
|
||||
build_tree_list ($5, attrs)); }
|
||||
| component_constructor_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
|
||||
{ $$ = grokfield ($$, NULL_TREE, $2, $5, $3, $4); }
|
||||
| using_decl
|
||||
{ $$ = do_class_using_decl ($1); }
|
||||
;
|
||||
|
@ -2808,7 +2807,6 @@ complete_type_name:
|
|||
{
|
||||
if (current_class_type
|
||||
&& TYPE_BEING_DEFINED (current_class_type)
|
||||
&& ! TREE_MANGLED ($1)
|
||||
&& ! IDENTIFIER_CLASS_VALUE ($1))
|
||||
{
|
||||
/* Be sure to get an inherited typedef. */
|
||||
|
@ -2826,16 +2824,7 @@ complete_type_name:
|
|||
| global_scope type_name
|
||||
{
|
||||
if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
||||
{
|
||||
if (current_class_type
|
||||
&& TYPE_BEING_DEFINED (current_class_type)
|
||||
&& ! TREE_MANGLED ($2)
|
||||
&& ! IDENTIFIER_CLASS_VALUE ($2))
|
||||
/* Be sure to get an inherited typedef. */
|
||||
$$ = lookup_name ($2, 1);
|
||||
else
|
||||
$$ = identifier_typedecl_value ($2);
|
||||
}
|
||||
$$ = identifier_typedecl_value ($2);
|
||||
else
|
||||
$$ = $2;
|
||||
got_scope = NULL_TREE;
|
||||
|
@ -2948,6 +2937,7 @@ functional_cast:
|
|||
|
||||
type_name:
|
||||
TYPENAME
|
||||
| SELFNAME
|
||||
| template_type %prec EMPTY
|
||||
;
|
||||
|
||||
|
@ -2962,14 +2952,22 @@ nested_name_specifier:
|
|||
nested_name_specifier_1:
|
||||
TYPENAME SCOPE
|
||||
{
|
||||
$$ = lastiddecl;
|
||||
/* Remember that this name has been used in the class
|
||||
definition, as per [class.scope0] */
|
||||
if (current_class_type
|
||||
&& TYPE_BEING_DEFINED (current_class_type)
|
||||
&& ! TREE_MANGLED ($1)
|
||||
&& ! IDENTIFIER_CLASS_VALUE ($1))
|
||||
pushdecl_class_level ($$);
|
||||
if (TREE_CODE ($1) == IDENTIFIER_NODE)
|
||||
{
|
||||
$$ = lastiddecl;
|
||||
/* Remember that this name has been used in the class
|
||||
definition, as per [class.scope0] */
|
||||
if (current_class_type
|
||||
&& TYPE_BEING_DEFINED (current_class_type)
|
||||
&& ! IDENTIFIER_CLASS_VALUE ($1))
|
||||
pushdecl_class_level ($$);
|
||||
}
|
||||
got_scope = $$ = TREE_TYPE ($$);
|
||||
}
|
||||
| SELFNAME SCOPE
|
||||
{
|
||||
if (TREE_CODE ($1) == IDENTIFIER_NODE)
|
||||
$$ = lastiddecl;
|
||||
got_scope = $$ = TREE_TYPE ($$);
|
||||
}
|
||||
| NSNAME SCOPE
|
||||
|
@ -2992,16 +2990,7 @@ complex_type_name:
|
|||
global_scope type_name
|
||||
{
|
||||
if (TREE_CODE ($2) == IDENTIFIER_NODE)
|
||||
{
|
||||
if (current_class_type
|
||||
&& TYPE_BEING_DEFINED (current_class_type)
|
||||
&& ! TREE_MANGLED ($2)
|
||||
&& ! IDENTIFIER_CLASS_VALUE ($2))
|
||||
/* Be sure to get an inherited typedef. */
|
||||
$$ = lookup_name ($2, 1);
|
||||
else
|
||||
$$ = identifier_typedecl_value ($2);
|
||||
}
|
||||
$$ = identifier_typedecl_value ($2);
|
||||
else
|
||||
$$ = $2;
|
||||
got_scope = NULL_TREE;
|
||||
|
@ -3675,6 +3664,8 @@ label_colon:
|
|||
{ goto do_label; }
|
||||
| TYPENAME ':'
|
||||
{ goto do_label; }
|
||||
| SELFNAME ':'
|
||||
{ goto do_label; }
|
||||
;
|
||||
|
||||
for.init.statement:
|
||||
|
|
|
@ -1578,7 +1578,6 @@ tsubst (t, args, nargs, in_decl)
|
|||
tree r = copy_node (t);
|
||||
TREE_TYPE (r) = type;
|
||||
DECL_CONTEXT (r) = current_class_type;
|
||||
set_nested_typename (r, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, DECL_NAME (r), type);
|
||||
TREE_CHAIN (r) = NULL_TREE;
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -320,6 +320,18 @@ throw_bad_cast ()
|
|||
return d;
|
||||
}
|
||||
|
||||
/* Check whether TEST is null before returning RESULT. If TEST is used in
|
||||
RESULT, it must have previously had a save_expr applied to it. */
|
||||
|
||||
tree ifnonnull (test, result)
|
||||
tree test, result;
|
||||
{
|
||||
return build (COND_EXPR, TREE_TYPE (result),
|
||||
build (EQ_EXPR, boolean_type_node, test, integer_zero_node),
|
||||
convert (TREE_TYPE (result), integer_zero_node),
|
||||
result);
|
||||
}
|
||||
|
||||
/* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
|
||||
paper. */
|
||||
|
||||
|
@ -406,6 +418,7 @@ build_dynamic_cast (type, expr)
|
|||
/* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
|
||||
if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))
|
||||
{
|
||||
tree expr1;
|
||||
/* if TYPE is `void *', return pointer to complete object. */
|
||||
if (tc == POINTER_TYPE
|
||||
&& TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
|
||||
|
@ -416,15 +429,18 @@ build_dynamic_cast (type, expr)
|
|||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
|
||||
return build1 (NOP_EXPR, type, expr);
|
||||
|
||||
expr = build_headof (expr);
|
||||
if (TREE_TYPE (expr) != type)
|
||||
expr = build1 (NOP_EXPR, type, expr);
|
||||
return expr;
|
||||
/* Since expr is used twice below, save it. */
|
||||
expr = save_expr (expr);
|
||||
|
||||
expr1 = build_headof (expr);
|
||||
if (TREE_TYPE (expr1) != type)
|
||||
expr1 = build1 (NOP_EXPR, type, expr1);
|
||||
return ifnonnull (expr, expr1);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree retval;
|
||||
tree result, td1, td2, td3, elems, expr1, expr2;
|
||||
tree result, td1, td2, td3, elems, expr2;
|
||||
|
||||
/* If we got here, we can't convert statically. Therefore,
|
||||
dynamic_cast<D&>(b) (b an object) cannot succeed. */
|
||||
|
@ -522,7 +538,7 @@ build_dynamic_cast (type, expr)
|
|||
|
||||
/* Now back to the type we want from a void*. */
|
||||
result = convert (type, result);
|
||||
return result;
|
||||
return ifnonnull (expr, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -603,7 +619,6 @@ expand_class_desc (tdecl, type)
|
|||
tree tdecl;
|
||||
tree type;
|
||||
{
|
||||
tree tname = TYPE_NESTED_NAME (type);
|
||||
tree name_string;
|
||||
tree fn, tmp;
|
||||
char *name;
|
||||
|
|
|
@ -291,6 +291,7 @@ yylex ()
|
|||
switch (tmp_token.yychar)
|
||||
{
|
||||
case TYPENAME:
|
||||
case SELFNAME:
|
||||
lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
|
||||
if (lastiddecl != trrr)
|
||||
{
|
||||
|
|
|
@ -1073,17 +1073,9 @@ get_identifier_list (value)
|
|||
list = tree_cons (NULL_TREE, value, NULL_TREE);
|
||||
else
|
||||
{
|
||||
register tree id;
|
||||
/* This will return the correct thing for regular types,
|
||||
nested types, and templates. Yay! */
|
||||
if (TYPE_NESTED_NAME (type))
|
||||
id = TYPE_NESTED_NAME (type);
|
||||
else
|
||||
id = TYPE_IDENTIFIER (type);
|
||||
|
||||
if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
|
||||
if (! CLASSTYPE_ID_AS_LIST (type))
|
||||
CLASSTYPE_ID_AS_LIST (type)
|
||||
= perm_tree_cons (NULL_TREE, id, NULL_TREE);
|
||||
= perm_tree_cons (NULL_TREE, TYPE_IDENTIFIER (type), NULL_TREE);
|
||||
list = CLASSTYPE_ID_AS_LIST (type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5088,15 +5088,19 @@ build_reinterpret_cast (type, expr)
|
|||
{
|
||||
tree intype = TREE_TYPE (expr);
|
||||
|
||||
if (TYPE_PTRMEMFUNC_P (type))
|
||||
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
|
||||
|
||||
if (current_template_parms)
|
||||
{
|
||||
tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
|
||||
return t;
|
||||
}
|
||||
|
||||
if (TYPE_PTRMEMFUNC_P (type))
|
||||
if (TYPE_PTRMEMFUNC_P (intype))
|
||||
return build1 (NOP_EXPR, type, expr);
|
||||
|
||||
if (TYPE_PTRMEMFUNC_P (type))
|
||||
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
|
||||
|
||||
if (TYPE_PTRMEMFUNC_P (intype))
|
||||
intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
|
||||
|
||||
|
|
Loading…
Reference in New Issue