86th Cygnus<->FSF quick merge

From-SVN: r11850
This commit is contained in:
Mike Stump 1996-04-19 00:48:03 +00:00
parent ec497122f7
commit a80e41955a
18 changed files with 314 additions and 340 deletions

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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.

View File

@ -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. */

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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))

View File

@ -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 */

View File

@ -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;
}

View File

@ -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:

View File

@ -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;
}

View File

@ -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;

View File

@ -291,6 +291,7 @@ yylex ()
switch (tmp_token.yychar)
{
case TYPENAME:
case SELFNAME:
lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
if (lastiddecl != trrr)
{

View File

@ -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);
}
}

View File

@ -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);