Commit e1cd6e56 by Mike Stump

53rd Cygnus<->FSF merge

From-SVN: r8794
parent 43238b97
...@@ -47,6 +47,7 @@ extern tree unary_complex_lvalue (); ...@@ -47,6 +47,7 @@ extern tree unary_complex_lvalue ();
static struct harshness_code convert_harshness (); static struct harshness_code convert_harshness ();
#define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG)) #define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG))
#define STD_RETURN(ARG) ((ARG).code = STD_CODE, (ARG))
#define QUAL_RETURN(ARG) ((ARG).code = QUAL_CODE, (ARG)) #define QUAL_RETURN(ARG) ((ARG).code = QUAL_CODE, (ARG))
#define TRIVIAL_RETURN(ARG) ((ARG).code = TRIVIAL_CODE, (ARG)) #define TRIVIAL_RETURN(ARG) ((ARG).code = TRIVIAL_CODE, (ARG))
#define ZERO_RETURN(ARG) ((ARG).code = 0, (ARG)) #define ZERO_RETURN(ARG) ((ARG).code = 0, (ARG))
...@@ -117,6 +118,7 @@ convert_harshness (type, parmtype, parm) ...@@ -117,6 +118,7 @@ convert_harshness (type, parmtype, parm)
struct harshness_code h; struct harshness_code h;
register enum tree_code codel; register enum tree_code codel;
register enum tree_code coder; register enum tree_code coder;
int lvalue;
h.code = 0; h.code = 0;
h.distance = 0; h.distance = 0;
...@@ -136,7 +138,12 @@ convert_harshness (type, parmtype, parm) ...@@ -136,7 +138,12 @@ convert_harshness (type, parmtype, parm)
if (parm) if (parm)
parm = convert_from_reference (parm); parm = convert_from_reference (parm);
parmtype = TREE_TYPE (parmtype); parmtype = TREE_TYPE (parmtype);
lvalue = 1;
} }
else if (parm)
lvalue = lvalue_p (parm);
else
lvalue = 0;
codel = TREE_CODE (type); codel = TREE_CODE (type);
coder = TREE_CODE (parmtype); coder = TREE_CODE (parmtype);
...@@ -300,6 +307,14 @@ convert_harshness (type, parmtype, parm) ...@@ -300,6 +307,14 @@ convert_harshness (type, parmtype, parm)
if (coder == VOID_TYPE) if (coder == VOID_TYPE)
return EVIL_RETURN (h); return EVIL_RETURN (h);
if (codel == BOOLEAN_TYPE)
{
if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE
|| coder == POINTER_TYPE || coder == OFFSET_TYPE)
return STD_RETURN (h);
return EVIL_RETURN (h);
}
if (INTEGRAL_CODE_P (codel)) if (INTEGRAL_CODE_P (codel))
{ {
/* Control equivalence of ints an enums. */ /* Control equivalence of ints an enums. */
...@@ -375,11 +390,10 @@ convert_harshness (type, parmtype, parm) ...@@ -375,11 +390,10 @@ convert_harshness (type, parmtype, parm)
register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)); register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));
int penalty = 4 * (ttl != ttr); int penalty = 4 * (ttl != ttr);
/* Anything converts to void *. void * converts to anything. /* Anything converts to void *. Since this may be `const void *'
Since these may be `const void *' (etc.) use VOID_TYPE (etc.) use VOID_TYPE instead of void_type_node. Otherwise, the
instead of void_type_node. Otherwise, the targets must be the same, targets must be the same, except that we do allow (at some cost)
except that we do allow (at some cost) conversion between signed and conversion between signed and unsigned pointer types. */
unsigned pointer types. */
if ((TREE_CODE (ttl) == METHOD_TYPE if ((TREE_CODE (ttl) == METHOD_TYPE
|| TREE_CODE (ttl) == FUNCTION_TYPE) || TREE_CODE (ttl) == FUNCTION_TYPE)
...@@ -396,7 +410,8 @@ convert_harshness (type, parmtype, parm) ...@@ -396,7 +410,8 @@ convert_harshness (type, parmtype, parm)
} }
#if 1 #if 1
if (TREE_CODE (ttl) != VOID_TYPE && TREE_CODE (ttr) != VOID_TYPE) if (TREE_CODE (ttl) != VOID_TYPE
&& (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
{ {
if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr)) if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
{ {
...@@ -404,7 +419,7 @@ convert_harshness (type, parmtype, parm) ...@@ -404,7 +419,7 @@ convert_harshness (type, parmtype, parm)
ttr = unsigned_type (ttr); ttr = unsigned_type (ttr);
penalty = 10; penalty = 10;
} }
if (! comp_target_types (ttl, ttr, 0)) if (comp_target_types (ttl, ttr, 0) <= 0)
return EVIL_RETURN (h); return EVIL_RETURN (h);
} }
#else #else
...@@ -414,7 +429,7 @@ convert_harshness (type, parmtype, parm) ...@@ -414,7 +429,7 @@ convert_harshness (type, parmtype, parm)
&& (ttl = unsigned_type (ttl), && (ttl = unsigned_type (ttl),
ttr = unsigned_type (ttr), ttr = unsigned_type (ttr),
penalty = 10, 0)) penalty = 10, 0))
|| (comp_target_types (ttl, ttr, 0)))) || (comp_target_types (ttl, ttr, 0) > 0)))
return EVIL_RETURN (h); return EVIL_RETURN (h);
#endif #endif
...@@ -503,14 +518,21 @@ convert_harshness (type, parmtype, parm) ...@@ -503,14 +518,21 @@ convert_harshness (type, parmtype, parm)
ttl = TREE_TYPE (type); ttl = TREE_TYPE (type);
/* When passing a non-const argument into a const reference (or vice /* Only allow const reference binding if we were given a parm to deal
versa), dig it a little, so a non-const reference is preferred with, since it isn't really a conversion. This is a hack to
over this one. (mrs) */ prevent build_type_conversion from finding this conversion, but
if (TYPE_READONLY (ttl) != constp still allow overloading to find it. */
|| TYPE_VOLATILE (ttl) != volatilep) if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
penalty = 2; return EVIL_RETURN (h);
else
penalty = 0; if (TYPE_READONLY (ttl) < constp
|| TYPE_VOLATILE (ttl) < volatilep)
return EVIL_RETURN (h);
/* When passing a non-const argument into a const reference, dig it a
little, so a non-const reference is preferred over this one. */
penalty = ((TYPE_READONLY (ttl) > constp)
+ (TYPE_VOLATILE (ttl) > volatilep));
ttl = TYPE_MAIN_VARIANT (ttl); ttl = TYPE_MAIN_VARIANT (ttl);
...@@ -520,98 +542,17 @@ convert_harshness (type, parmtype, parm) ...@@ -520,98 +542,17 @@ convert_harshness (type, parmtype, parm)
form = TREE_CODE (intype); form = TREE_CODE (intype);
} }
if (ttl == intype && penalty == 0)
return ZERO_RETURN (h);
else
penalty = 2;
ttr = intype; ttr = intype;
/* If the initializer is not an lvalue, then it does not /* Maybe handle conversion to base here? */
matter if we make life easier for the programmer
by creating a temporary variable with which to
hold the result. */
if (parm && (INTEGRAL_CODE_P (coder)
|| coder == REAL_TYPE)
&& ! lvalue_p (parm))
{
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty > 2 || h.code != 0)
h.code |= STD_CODE;
else
h.code |= TRIVIAL_CODE;
h.distance = 0;
return h;
}
if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
{
ttl = unsigned_type (ttl);
ttr = intype = unsigned_type (intype);
penalty += 2;
}
if (ttl == ttr)
{
if (penalty > 2)
{
h.code = STD_CODE;
h.distance = 0;
}
else
{
h.code = TRIVIAL_CODE;
/* We set this here so that build_overload_call_real will be
able to see the penalty we found, rather than just looking
at a TRIVIAL_CODE with no other information. */
h.int_penalty = penalty;
}
return h;
}
/* Pointers to voids always convert for pointers. But h = convert_harshness (ttl, ttr, NULL_TREE);
make them less natural than more specific matches. */ if (penalty && h.code == 0)
if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
{ {
if (TREE_TYPE (ttl) == void_type_node h.code = QUAL_CODE;
|| TREE_TYPE (ttr) == void_type_node) h.int_penalty = penalty;
{
h.code = STD_CODE;
h.distance = 0;
return h;
}
}
/* Here it does matter. If this conversion is from derived to base,
allow it. Otherwise, types must be compatible in the strong sense. */
if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
{
int b_or_d = get_base_distance (ttl, ttr, 0, 0);
if (b_or_d < 0)
{
b_or_d = get_base_distance (ttr, ttl, 0, 0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
}
/* Say that this conversion is relatively painless.
If it turns out that there is a user-defined X(X&)
constructor, then that will be invoked, but that's
preferable to dealing with other user-defined conversions
that may produce surprising results. */
else
h.distance = b_or_d;
h.code = STD_CODE;
return h;
}
if (comp_target_types (ttl, intype, 1))
{
if (penalty)
h.code = STD_CODE;
h.distance = 0;
return h;
} }
return h;
} }
if (codel == RECORD_TYPE && coder == RECORD_TYPE) if (codel == RECORD_TYPE && coder == RECORD_TYPE)
{ {
...@@ -631,6 +572,15 @@ convert_harshness (type, parmtype, parm) ...@@ -631,6 +572,15 @@ convert_harshness (type, parmtype, parm)
return EVIL_RETURN (h); return EVIL_RETURN (h);
} }
int
can_convert (to, from)
tree to, from;
{
struct harshness_code h;
h = convert_harshness (to, from, NULL_TREE);
return h.code < USER_CODE;
}
#ifdef DEBUG_MATCHING #ifdef DEBUG_MATCHING
static char * static char *
print_harshness (h) print_harshness (h)
...@@ -2134,6 +2084,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2134,6 +2084,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype_path = TREE_VALUE (basetype_path); basetype_path = TREE_VALUE (basetype_path);
basetype = BINFO_TYPE (basetype_path); basetype = BINFO_TYPE (basetype_path);
#if 0
/* Cast the instance variable if necessary. */ /* Cast the instance variable if necessary. */
if (basetype != TYPE_MAIN_VARIANT if (basetype != TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))))) (TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)))))
...@@ -2152,6 +2103,7 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2152,6 +2103,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
the access-control rewrite will make this change more cleanly. */ the access-control rewrite will make this change more cleanly. */
if (TREE_VALUE (parms) == error_mark_node) if (TREE_VALUE (parms) == error_mark_node)
return error_mark_node; return error_mark_node;
#endif
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))) if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
function = DECL_CHAIN (function); function = DECL_CHAIN (function);
...@@ -2208,19 +2160,6 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2208,19 +2160,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& (cp->h.code & USER_CODE)) && (cp->h.code & USER_CODE))
continue; continue;
/* If we used default parameters, we must
check to see whether anyone else might
use them also, and report a possible
ambiguity. */
if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype)
&& cp->harshness[len].distance == 0
&& cp->h.code < best)
{
if (! DECL_STATIC_FUNCTION_P (function))
TREE_VALUE (parms) = cp->arg;
if (best == 1)
goto found_and_maybe_warn;
}
cp++; cp++;
} }
} }
......
...@@ -114,6 +114,14 @@ extern int pedantic; ...@@ -114,6 +114,14 @@ extern int pedantic;
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */ /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
#define C_TYPE_FIELDS_READONLY(type) TYPE_LANG_FLAG_0 (type) #define C_TYPE_FIELDS_READONLY(type) TYPE_LANG_FLAG_0 (type)
/* Record in each node resulting from a binary operator
what operator was specified for it. */
#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
/* Store a value in that field. */
#define C_SET_EXP_ORIGINAL_CODE(exp, code) \
(TREE_COMPLEXITY (exp) = (int)(code))
/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the /* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
next exception handler. */ next exception handler. */
...@@ -271,7 +279,8 @@ extern int interface_only, interface_unknown; ...@@ -271,7 +279,8 @@ extern int interface_only, interface_unknown;
extern int flag_elide_constructors; extern int flag_elide_constructors;
/* Nonzero means handle things in ANSI, instead of GNU fashion. */ /* Nonzero means enable obscure ANSI features and disable GNU extensions
that might cause ANSI-compliant code to be miscompiled. */
extern int flag_ansi; extern int flag_ansi;
...@@ -369,9 +378,6 @@ enum languages { lang_c, lang_cplusplus }; ...@@ -369,9 +378,6 @@ enum languages { lang_c, lang_cplusplus };
#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) #define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
enum conversion_type { ptr_conv, constptr_conv, int_conv,
real_conv, last_conversion_type };
/* Statistics show that while the GNU C++ compiler may generate /* Statistics show that while the GNU C++ compiler may generate
thousands of different types during a compilation run, it thousands of different types during a compilation run, it
generates relatively few (tens) of classtypes. Because of this, generates relatively few (tens) of classtypes. Because of this,
...@@ -492,7 +498,6 @@ struct lang_type ...@@ -492,7 +498,6 @@ struct lang_type
union tree_node *friend_classes; union tree_node *friend_classes;
char *mi_matrix; char *mi_matrix;
union tree_node *conversions[last_conversion_type];
union tree_node *rtti; union tree_node *rtti;
...@@ -657,6 +662,12 @@ struct lang_type ...@@ -657,6 +662,12 @@ struct lang_type
/* List of lists of member functions defined in this class. */ /* List of lists of member functions defined in this class. */
#define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE) #define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE)
/* The first type conversion operator in the class (the others can be
searched with TREE_CHAIN), or the first non-constructor function if
there are no type conversion operators. */
#define CLASSTYPE_FIRST_CONVERSION(NODE) \
TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1)
/* Pointer from any member function to the head of the list of /* Pointer from any member function to the head of the list of
member functions of the type that member function belongs to. */ member functions of the type that member function belongs to. */
#define CLASSTYPE_BASELINK_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->baselink_vec) #define CLASSTYPE_BASELINK_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->baselink_vec)
...@@ -807,12 +818,6 @@ struct lang_type ...@@ -807,12 +818,6 @@ struct lang_type
a type is derived from another or not. */ a type is derived from another or not. */
#define CLASSTYPE_MI_MATRIX(NODE) (TYPE_LANG_SPECIFIC(NODE)->mi_matrix) #define CLASSTYPE_MI_MATRIX(NODE) (TYPE_LANG_SPECIFIC(NODE)->mi_matrix)
/* If there is exactly one conversion to a non-void, non-const pointer type,
remember that here. If there are more than one, put
`error_mark_node' here. If there are none, this holds NULL_TREE. */
#define CLASSTYPE_CONVERSION(NODE,KIND) \
(TYPE_LANG_SPECIFIC(NODE)->conversions[(int) KIND])
/* Say whether this node was declared as a "class" or a "struct". */ /* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class) #define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
/* whether this can be globalized. */ /* whether this can be globalized. */
...@@ -2243,6 +2248,7 @@ extern void print_search_statistics PROTO((void)); ...@@ -2243,6 +2248,7 @@ extern void print_search_statistics PROTO((void));
extern void init_search_processing PROTO((void)); extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void)); extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void)); extern tree current_scope PROTO((void));
extern tree lookup_conversions PROTO((tree));
/* in sig.c */ /* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int)); extern tree build_signature_pointer_type PROTO((tree, int, int));
......
...@@ -64,6 +64,10 @@ static int global_temp_name_counter; ...@@ -64,6 +64,10 @@ static int global_temp_name_counter;
/* Flag used when debugging spew.c */ /* Flag used when debugging spew.c */
extern int spew_debug; extern int spew_debug;
/* Functions called along with real static constructors and destructors. */
tree static_ctors, static_dtors;
/* C (and C++) language-specific option variables. */ /* C (and C++) language-specific option variables. */
...@@ -80,6 +84,10 @@ int flag_short_double; ...@@ -80,6 +84,10 @@ int flag_short_double;
int flag_no_asm; int flag_no_asm;
/* Nonzero means don't recognize any extension keywords. */
int flag_no_gnu_keywords;
/* Nonzero means don't recognize the non-ANSI builtin functions. */ /* Nonzero means don't recognize the non-ANSI builtin functions. */
int flag_no_builtin; int flag_no_builtin;
...@@ -99,11 +107,12 @@ int flag_signed_bitfields = 1; ...@@ -99,11 +107,12 @@ int flag_signed_bitfields = 1;
/* Nonzero means handle `#ident' directives. 0 means ignore them. */ /* Nonzero means handle `#ident' directives. 0 means ignore them. */
int flag_no_ident = 0; int flag_no_ident;
/* Nonzero means disable GNU extensions. */ /* Nonzero means enable obscure ANSI features and disable GNU extensions
that might cause ANSI-compliant code to be miscompiled. */
int flag_ansi = 0; int flag_ansi;
/* Nonzero means do emit exported implementations of functions even if /* Nonzero means do emit exported implementations of functions even if
they can be inlined. */ they can be inlined. */
...@@ -113,13 +122,13 @@ int flag_implement_inlines = 1; ...@@ -113,13 +122,13 @@ int flag_implement_inlines = 1;
/* Nonzero means do emit exported implementations of templates, instead of /* Nonzero means do emit exported implementations of templates, instead of
multiple static copies in each file that needs a definition. */ multiple static copies in each file that needs a definition. */
int flag_external_templates = 0; int flag_external_templates;
/* Nonzero means that the decision to emit or not emit the implementation of a /* Nonzero means that the decision to emit or not emit the implementation of a
template depends on where the template is instantiated, rather than where template depends on where the template is instantiated, rather than where
it is defined. */ it is defined. */
int flag_alt_external_templates = 0; int flag_alt_external_templates;
/* Nonzero means that implicit instantiations will be emitted if needed. */ /* Nonzero means that implicit instantiations will be emitted if needed. */
...@@ -139,7 +148,7 @@ int warn_ctor_dtor_privacy = 1; ...@@ -139,7 +148,7 @@ int warn_ctor_dtor_privacy = 1;
Also causes output of vtables to be controlled by whether Also causes output of vtables to be controlled by whether
we seen the class's first non-inline virtual function. */ we seen the class's first non-inline virtual function. */
int flag_vtable_thunks = 0; int flag_vtable_thunks;
/* Nonzero means give string constants the type `const char *' /* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous to get extra warnings from them. These warnings will be too numerous
...@@ -198,7 +207,7 @@ int warn_conversion; ...@@ -198,7 +207,7 @@ int warn_conversion;
/* Warn if adding () is suggested. */ /* Warn if adding () is suggested. */
int warn_parentheses = 1; int warn_parentheses;
/* Non-zero means warn in function declared in derived class has the /* Non-zero means warn in function declared in derived class has the
same name as a virtual in the base class, but fails to match the same name as a virtual in the base class, but fails to match the
...@@ -229,6 +238,7 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; ...@@ -229,6 +238,7 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
/* Nonzero for -fno-strict-prototype switch: do not consider empty /* Nonzero for -fno-strict-prototype switch: do not consider empty
argument prototype to mean function takes no arguments. */ argument prototype to mean function takes no arguments. */
int flag_strict_prototype = 2;
int strict_prototype = 1; int strict_prototype = 1;
int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1; int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1;
...@@ -303,7 +313,7 @@ int flag_gc; ...@@ -303,7 +313,7 @@ int flag_gc;
/* Controls whether compiler generates 'type descriptor' that give /* Controls whether compiler generates 'type descriptor' that give
run-time type information. */ run-time type information. */
int flag_rtti = 0; int flag_rtti;
/* Nonzero if we wish to output cross-referencing information /* Nonzero if we wish to output cross-referencing information
for the GNU class browser. */ for the GNU class browser. */
...@@ -319,21 +329,28 @@ extern int flag_gnu_xref; ...@@ -319,21 +329,28 @@ extern int flag_gnu_xref;
In general, it is `reasonable' to assume that for many programs, In general, it is `reasonable' to assume that for many programs,
and better code can be generated in that case. */ and better code can be generated in that case. */
int flag_assume_nonnull_objects; int flag_assume_nonnull_objects = 1;
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes) /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
objects. */ objects. */
int flag_huge_objects; int flag_huge_objects;
/* Nonzero if we want to conserve space in the .o files. We do this /* Nonzero if we want to conserve space in the .o files. We do this
by putting uninitialized data and runtime initialized data into by putting uninitialized data and runtime initialized data into
.common instead of .data at the expense of not flaging multiple .common instead of .data at the expense of not flaging multiple
definitions. */ definitions. */
int flag_conserve_space; int flag_conserve_space;
/* Nonzero if we want to obey access control semantics. */ /* Nonzero if we want to obey access control semantics. */
int flag_access_control = 1; int flag_access_control = 1;
/* Nonzero if we want to understand the operator names, i.e. 'bitand'. */
int flag_operator_names;
/* Table of language-dependent -f options. /* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable. STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE ON_VALUE is the value to store in VARIABLE
...@@ -355,7 +372,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -355,7 +372,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"labels-ok", &flag_labels_ok, 1}, {"labels-ok", &flag_labels_ok, 1},
{"stats", &flag_detailed_statistics, 1}, {"stats", &flag_detailed_statistics, 1},
{"this-is-variable", &flag_this_is_variable, 1}, {"this-is-variable", &flag_this_is_variable, 1},
{"strict-prototype", &strict_prototypes_lang_cplusplus, 1}, {"strict-prototype", &flag_strict_prototype, 1},
{"all-virtual", &flag_all_virtual, 1}, {"all-virtual", &flag_all_virtual, 1},
{"memoize-lookups", &flag_memoize_lookups, 1}, {"memoize-lookups", &flag_memoize_lookups, 1},
{"elide-constructors", &flag_elide_constructors, 1}, {"elide-constructors", &flag_elide_constructors, 1},
...@@ -376,7 +393,9 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -376,7 +393,9 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"vtable-thunks", &flag_vtable_thunks, 1}, {"vtable-thunks", &flag_vtable_thunks, 1},
{"short-temps", &flag_short_temps, 1}, {"short-temps", &flag_short_temps, 1},
{"access-control", &flag_access_control, 1}, {"access-control", &flag_access_control, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0} {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1}
}; };
/* Decode the string P as a language-specific option. /* Decode the string P as a language-specific option.
...@@ -552,6 +571,7 @@ lang_decode_option (p) ...@@ -552,6 +571,7 @@ lang_decode_option (p)
warn_ctor_dtor_privacy = setting; warn_ctor_dtor_privacy = setting;
warn_switch = setting; warn_switch = setting;
warn_format = setting; warn_format = setting;
warn_parentheses = setting;
warn_missing_braces = setting; warn_missing_braces = setting;
warn_extern_inline = setting; warn_extern_inline = setting;
warn_nonvdtor = setting; warn_nonvdtor = setting;
...@@ -569,8 +589,8 @@ lang_decode_option (p) ...@@ -569,8 +589,8 @@ lang_decode_option (p)
else return 0; else return 0;
} }
else if (!strcmp (p, "-ansi")) else if (!strcmp (p, "-ansi"))
flag_no_asm = 1, dollars_in_ident = 0, flag_no_nonansi_builtin = 1, dollars_in_ident = 0, flag_no_nonansi_builtin = 1, flag_ansi = 1,
flag_ansi = 1; flag_no_gnu_keywords = 1, flag_operator_names = 1;
#ifdef SPEW_DEBUG #ifdef SPEW_DEBUG
/* Undocumented, only ever used when you're invoking cc1plus by hand, since /* Undocumented, only ever used when you're invoking cc1plus by hand, since
it's probably safe to assume no sane person would ever want to use this it's probably safe to assume no sane person would ever want to use this
...@@ -2674,10 +2694,10 @@ finish_file () ...@@ -2674,10 +2694,10 @@ finish_file ()
we'll need here. */ we'll need here. */
push_lang_context (lang_name_c); push_lang_context (lang_name_c);
/* Set up the name of the file-level functions we may need. */ if (static_ctors || vars || have_exception_handlers)
/* Use a global object (which is already required to be unique over needs_messing_up = 1;
the program) rather than the file name (which imposes extra if (static_dtors)
constraints). -- Raeburn@MIT.EDU, 10 Jan 1990. */ needs_cleaning = 1;
/* See if we really need the hassle. */ /* See if we really need the hassle. */
while (vars && needs_cleaning == 0) while (vars && needs_cleaning == 0)
...@@ -2740,6 +2760,10 @@ finish_file () ...@@ -2740,6 +2760,10 @@ finish_file ()
vars = TREE_CHAIN (vars); vars = TREE_CHAIN (vars);
} }
for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
NULL_TREE));
expand_end_bindings (getdecls(), 1, 0); expand_end_bindings (getdecls(), 1, 0);
poplevel (1, 0, 0); poplevel (1, 0, 0);
pop_momentary (); pop_momentary ();
...@@ -2753,7 +2777,7 @@ finish_file () ...@@ -2753,7 +2777,7 @@ finish_file ()
mess_up: mess_up:
/* Must do this while we think we are at the top level. */ /* Must do this while we think we are at the top level. */
vars = nreverse (static_aggregates); vars = nreverse (static_aggregates);
if (vars != NULL_TREE || have_exception_handlers) if (needs_messing_up)
{ {
fnname = get_file_function_name ('I'); fnname = get_file_function_name ('I');
start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
...@@ -2797,6 +2821,7 @@ finish_file () ...@@ -2797,6 +2821,7 @@ finish_file ()
the same acess rights as a member function. */ the same acess rights as a member function. */
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl); DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
#if 0
if (init) if (init)
{ {
if (TREE_CODE (init) == VAR_DECL) if (TREE_CODE (init) == VAR_DECL)
...@@ -2815,7 +2840,6 @@ finish_file () ...@@ -2815,7 +2840,6 @@ finish_file ()
&& CONSTRUCTOR_ELTS (init) == NULL_TREE) && CONSTRUCTOR_ELTS (init) == NULL_TREE)
init = NULL_TREE; init = NULL_TREE;
} }
#if 0
else if (TREE_TYPE (decl) == TREE_TYPE (init)) else if (TREE_TYPE (decl) == TREE_TYPE (init))
{ {
#if 1 #if 1
...@@ -2828,9 +2852,9 @@ finish_file () ...@@ -2828,9 +2852,9 @@ finish_file ()
init = DECL_INITIAL (init); init = DECL_INITIAL (init);
#endif /* 1 */ #endif /* 1 */
} }
#endif /* 0 */
} }
} }
#endif /* 0 */
if (IS_AGGR_TYPE (TREE_TYPE (decl)) if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0, 0); expand_aggr_init (decl, init, 0, 0);
...@@ -2865,6 +2889,10 @@ finish_file () ...@@ -2865,6 +2889,10 @@ finish_file ()
expand_cleanups_to (old_cleanups); expand_cleanups_to (old_cleanups);
} }
for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
NULL_TREE));
expand_end_bindings (getdecls(), 1, 0); expand_end_bindings (getdecls(), 1, 0);
poplevel (1, 0, 0); poplevel (1, 0, 0);
pop_momentary (); pop_momentary ();
......
...@@ -43,7 +43,12 @@ tree builtin_return_address_fndecl; ...@@ -43,7 +43,12 @@ tree builtin_return_address_fndecl;
#define TRY_NEW_EH #define TRY_NEW_EH
#endif #endif
#endif #endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) #ifdef _IBMR2
#ifndef __rs6000
#define __rs6000
#endif
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm)
#define TRY_NEW_EH #define TRY_NEW_EH
#endif #endif
#endif #endif
...@@ -123,6 +128,16 @@ expand_throw (exp) ...@@ -123,6 +128,16 @@ expand_throw (exp)
#else #else
/* Make 'label' the first numbered label of the current function */
void
make_first_label(label)
rtx label;
{
if (CODE_LABEL_NUMBER(label) < get_first_label_num())
set_new_first_and_last_label_num (CODE_LABEL_NUMBER(label),
max_label_num());
}
static int static int
doing_eh (do_warn) doing_eh (do_warn)
int do_warn; int do_warn;
...@@ -236,9 +251,16 @@ void ...@@ -236,9 +251,16 @@ void
exception_section () exception_section ()
{ {
#ifdef ASM_OUTPUT_SECTION_NAME #ifdef ASM_OUTPUT_SECTION_NAME
named_section (".gcc_except_table"); named_section (NULL_TREE, ".gcc_except_table");
#else
if (flag_pic)
data_section ();
else
#if defined(__rs6000)
data_section ();
#else #else
text_section (); readonly_data_section ();
#endif
#endif #endif
} }
...@@ -576,6 +598,10 @@ push_eh_entry (stack) ...@@ -576,6 +598,10 @@ push_eh_entry (stack)
entry->exception_handler_label = gen_label_rtx (); entry->exception_handler_label = gen_label_rtx ();
pop_rtl_from_perm (); pop_rtl_from_perm ();
LABEL_PRESERVE_P (entry->start_label) = 1;
LABEL_PRESERVE_P (entry->end_label) = 1;
LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
entry->finalization = NULL_TREE; entry->finalization = NULL_TREE;
node->entry = entry; node->entry = entry;
...@@ -794,9 +820,9 @@ init_exception_processing () ...@@ -794,9 +820,9 @@ init_exception_processing ()
saved_throw_value = gen_rtx (REG, Pmode, 5); saved_throw_value = gen_rtx (REG, Pmode, 5);
#endif #endif
#ifdef __rs6000 #ifdef __rs6000
saved_pc = gen_rtx (REG, Pmode, 12); saved_pc = gen_rtx (REG, Pmode, 13);
saved_throw_type = gen_rtx (REG, Pmode, 13); saved_throw_type = gen_rtx (REG, Pmode, 14);
saved_throw_value = gen_rtx (REG, Pmode, 14); saved_throw_value = gen_rtx (REG, Pmode, 15);
#endif #endif
#ifdef __hppa #ifdef __hppa
saved_pc = gen_rtx (REG, Pmode, 5); saved_pc = gen_rtx (REG, Pmode, 5);
...@@ -813,6 +839,11 @@ init_exception_processing () ...@@ -813,6 +839,11 @@ init_exception_processing ()
saved_throw_type = gen_rtx (REG, Pmode, 17); saved_throw_type = gen_rtx (REG, Pmode, 17);
saved_throw_value = gen_rtx (REG, Pmode, 18); saved_throw_value = gen_rtx (REG, Pmode, 18);
#endif #endif
#ifdef __arm
saved_pc = gen_rtx (REG, Pmode, 7);
saved_throw_type = gen_rtx (REG, Pmode, 8);
saved_throw_value = gen_rtx (REG, Pmode, 9);
#endif
new_eh_queue (&ehqueue); new_eh_queue (&ehqueue);
new_eh_queue (&eh_table_output_queue); new_eh_queue (&eh_table_output_queue);
new_eh_stack (&ehstack); new_eh_stack (&ehstack);
...@@ -958,7 +989,13 @@ expand_start_all_catch () ...@@ -958,7 +989,13 @@ expand_start_all_catch ()
entry->end_label = gen_label_rtx (); entry->end_label = gen_label_rtx ();
entry->exception_handler_label = gen_label_rtx (); entry->exception_handler_label = gen_label_rtx ();
entry->finalization = TerminateFunctionCall; entry->finalization = TerminateFunctionCall;
assemble_external (TREE_OPERAND (Terminate, 0));
pop_rtl_from_perm (); pop_rtl_from_perm ();
LABEL_PRESERVE_P (entry->start_label) = 1;
LABEL_PRESERVE_P (entry->end_label) = 1;
LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
emit_label (entry->end_label); emit_label (entry->end_label);
enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry)); enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
...@@ -969,6 +1006,7 @@ expand_start_all_catch () ...@@ -969,6 +1006,7 @@ expand_start_all_catch ()
/* Will this help us not stomp on it? */ /* Will this help us not stomp on it? */
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type)); emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value)); emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
make_first_label(throw_label);
emit_jump (throw_label); emit_jump (throw_label);
emit_label (entry->exception_handler_label); emit_label (entry->exception_handler_label);
expand_expr (entry->finalization, const0_rtx, VOIDmode, 0); expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
...@@ -992,6 +1030,7 @@ expand_end_all_catch () ...@@ -992,6 +1030,7 @@ expand_end_all_catch ()
emit_move_insn (saved_pc, gen_rtx (LABEL_REF, emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
Pmode, Pmode,
top_label_entry (&caught_return_label_stack))); top_label_entry (&caught_return_label_stack)));
make_first_label(throw_label);
emit_jump (throw_label); emit_jump (throw_label);
/* Find the start of the catch block. */ /* Find the start of the catch block. */
...@@ -1052,7 +1091,13 @@ expand_leftover_cleanups () ...@@ -1052,7 +1091,13 @@ expand_leftover_cleanups ()
entry.end_label = label; entry.end_label = label;
entry.exception_handler_label = gen_label_rtx (); entry.exception_handler_label = gen_label_rtx ();
entry.finalization = TerminateFunctionCall; entry.finalization = TerminateFunctionCall;
assemble_external (TREE_OPERAND (Terminate, 0));
pop_rtl_from_perm (); pop_rtl_from_perm ();
LABEL_PRESERVE_P (entry.start_label) = 1;
LABEL_PRESERVE_P (entry.end_label) = 1;
LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
emit_label (label); emit_label (label);
enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry)); enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
...@@ -1063,6 +1108,7 @@ expand_leftover_cleanups () ...@@ -1063,6 +1108,7 @@ expand_leftover_cleanups ()
/* Will this help us not stomp on it? */ /* Will this help us not stomp on it? */
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type)); emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value)); emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
make_first_label(throw_label);
emit_jump (throw_label); emit_jump (throw_label);
emit_label (entry.exception_handler_label); emit_label (entry.exception_handler_label);
expand_expr (entry.finalization, const0_rtx, VOIDmode, 0); expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
...@@ -1143,6 +1189,7 @@ expand_start_catch_block (declspecs, declarator) ...@@ -1143,6 +1189,7 @@ expand_start_catch_block (declspecs, declarator)
NULL_TREE)); NULL_TREE));
catch_match_fcall = build_function_call (CatchMatch, params); catch_match_fcall = build_function_call (CatchMatch, params);
call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0); call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
assemble_external (TREE_OPERAND (CatchMatch, 0));
return_value_rtx = return_value_rtx =
hard_function_value (integer_type_node, catch_match_fcall); hard_function_value (integer_type_node, catch_match_fcall);
...@@ -1192,6 +1239,7 @@ void expand_end_catch_block () ...@@ -1192,6 +1239,7 @@ void expand_end_catch_block ()
emit_move_insn (saved_pc, gen_rtx (LABEL_REF, emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
Pmode, Pmode,
top_label_entry (&caught_return_label_stack))); top_label_entry (&caught_return_label_stack)));
make_first_label(throw_label);
emit_jump (throw_label); emit_jump (throw_label);
/* No associated finalization. */ /* No associated finalization. */
entry.finalization = NULL_TREE; entry.finalization = NULL_TREE;
...@@ -1210,6 +1258,10 @@ void expand_end_catch_block () ...@@ -1210,6 +1258,10 @@ void expand_end_catch_block ()
entry.start_label = start_protect_label_rtx; entry.start_label = start_protect_label_rtx;
entry.end_label = end_protect_label_rtx; entry.end_label = end_protect_label_rtx;
LABEL_PRESERVE_P (entry.start_label) = 1;
LABEL_PRESERVE_P (entry.end_label) = 1;
LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
/* These set up a call to throw the caught exception into the outer /* These set up a call to throw the caught exception into the outer
context. */ context. */
enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry)); enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
...@@ -1279,6 +1331,7 @@ do_unwind (throw_label) ...@@ -1279,6 +1331,7 @@ do_unwind (throw_label)
gen_rtx (LABEL_REF, Pmode, throw_label)), NULL_TREE); gen_rtx (LABEL_REF, Pmode, throw_label)), NULL_TREE);
do_function_call (Unwind, params, NULL_TREE); do_function_call (Unwind, params, NULL_TREE);
assemble_external (TREE_OPERAND (Unwind, 0));
emit_barrier (); emit_barrier ();
#endif #endif
#if m88k #if m88k
...@@ -1304,9 +1357,18 @@ do_unwind (throw_label) ...@@ -1304,9 +1357,18 @@ do_unwind (throw_label)
(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0)))); (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
#endif #endif
#endif #endif
#ifdef __arm
if (flag_omit_frame_pointer)
sorry ("this implementation of exception handling requires a frame pointer");
emit_move_insn (stack_pointer_rtx,
gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -8)));
emit_move_insn (hard_frame_pointer_rtx,
gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -12)));
#endif
} }
/* is called from expand_excpetion_blocks () to generate the code in a function /* is called from expand_exception_blocks () to generate the code in a function
to "throw" if anything in the function needs to preform a throw. to "throw" if anything in the function needs to preform a throw.
expands "throw" as the following psuedo code: expands "throw" as the following psuedo code:
...@@ -1333,12 +1395,14 @@ expand_builtin_throw () ...@@ -1333,12 +1395,14 @@ expand_builtin_throw ()
rtx unwind_and_throw = gen_label_rtx (); rtx unwind_and_throw = gen_label_rtx ();
rtx goto_unwind_and_throw = gen_label_rtx (); rtx goto_unwind_and_throw = gen_label_rtx ();
make_first_label(throw_label);
emit_label (throw_label); emit_label (throw_label);
/* search for an exception handler for the saved_pc */ /* search for an exception handler for the saved_pc */
return_val_rtx = do_function_call (FirstExceptionMatch, return_val_rtx = do_function_call (FirstExceptionMatch,
tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE), tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE),
ptr_type_node); ptr_type_node);
assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
/* did we find one? */ /* did we find one? */
emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX, emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
...@@ -1354,9 +1418,15 @@ expand_builtin_throw () ...@@ -1354,9 +1418,15 @@ expand_builtin_throw ()
emit_label (gotta_rethrow_it); emit_label (gotta_rethrow_it);
/* call to __builtin_return_address () */ /* call to __builtin_return_address () */
#ifdef __arm
/* This replaces a 'call' to __builtin_return_address */
return_val_rtx = gen_reg_rtx (Pmode);
emit_move_insn (return_val_rtx, gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -4)));
#else
params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE); params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params); fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0); return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
#endif
/* did __builtin_return_address () return a valid address? */ /* did __builtin_return_address () return a valid address? */
emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX, emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
...@@ -1364,20 +1434,35 @@ expand_builtin_throw () ...@@ -1364,20 +1434,35 @@ expand_builtin_throw ()
emit_jump_insn (gen_beq (gotta_call_terminate)); emit_jump_insn (gen_beq (gotta_call_terminate));
#ifdef __arm
/* On the ARM, '__builtin_return_address', must have 4
subtracted from it. */
emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4)));
/* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit
mode, the condition codes must be masked out of the return value, or else
they will confuse BuiltinReturnAddress. This does not apply to ARM6 and
later processors when running in 32 bit mode. */
if (!TARGET_6)
emit_insn (gen_rtx (SET, SImode, return_val_rtx, gen_rtx (AND, SImode, return_val_rtx, GEN_INT (0x03fffffc))));
#else
#ifndef sparc #ifndef sparc
/* On the SPARC, __builtin_return_address is already -8, no need to /* On the SPARC, __builtin_return_address is already -8, no need to
subtract any more from it. */ subtract any more from it. */
emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1))); emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1)));
#endif #endif
#endif
/* yes it did */ /* yes it did */
emit_move_insn (saved_pc, return_val_rtx); emit_move_insn (saved_pc, return_val_rtx);
do_unwind (throw_label); do_unwind (throw_label);
make_first_label(throw_label);
emit_jump (throw_label); emit_jump (throw_label);
/* no it didn't --> therefore we need to call terminate */ /* no it didn't --> therefore we need to call terminate */
emit_label (gotta_call_terminate); emit_label (gotta_call_terminate);
do_function_call (Terminate, NULL_TREE, NULL_TREE); do_function_call (Terminate, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Terminate, 0));
} }
...@@ -1424,7 +1509,7 @@ expand_exception_blocks () ...@@ -1424,7 +1509,7 @@ expand_exception_blocks ()
1. Allocate space to save the current PC onto the stack. 1. Allocate space to save the current PC onto the stack.
2. Generate and emit a label and save its address into the 2. Generate and emit a label and save its address into the
newly allocate stack space since we can't save the pc directly. newly allocated stack space since we can't save the pc directly.
3. If this is the first call to throw in this function: 3. If this is the first call to throw in this function:
generate a label for the throw block generate a label for the throw block
4. jump to the throw block label. */ 4. jump to the throw block label. */
...@@ -1476,6 +1561,7 @@ expand_throw (exp) ...@@ -1476,6 +1561,7 @@ expand_throw (exp)
/* This part is easy, as we dont' have to do anything else. */ /* This part is easy, as we dont' have to do anything else. */
} }
make_first_label(throw_label);
emit_jump (throw_label); emit_jump (throw_label);
} }
......
...@@ -19,8 +19,10 @@ __headof__, HEADOF, NORID ...@@ -19,8 +19,10 @@ __headof__, HEADOF, NORID
__inline, SCSPEC, RID_INLINE __inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE __inline__, SCSPEC, RID_INLINE
__label__, LABEL, NORID __label__, LABEL, NORID
__signature__, AGGR, RID_SIGNATURE /* Extension */,
__signed, TYPESPEC, RID_SIGNED __signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED __signed__, TYPESPEC, RID_SIGNED
__sigof__, SIGOF, NORID /* Extension */,
__typeof, TYPEOF, NORID __typeof, TYPEOF, NORID
__typeof__, TYPEOF, NORID __typeof__, TYPEOF, NORID
__volatile, TYPE_QUAL, RID_VOLATILE __volatile, TYPE_QUAL, RID_VOLATILE
......
...@@ -2376,9 +2376,9 @@ add_friend (type, decl) ...@@ -2376,9 +2376,9 @@ add_friend (type, decl)
{ {
if (decl == TREE_VALUE (friends)) if (decl == TREE_VALUE (friends))
{ {
cp_pedwarn ("`%D' is already a friend of class `%T'", cp_warning ("`%D' is already a friend of class `%T'",
decl, type); decl, type);
cp_pedwarn_at ("previous friend declaration of `%D'", cp_warning_at ("previous friend declaration of `%D'",
TREE_VALUE (friends)); TREE_VALUE (friends));
return; return;
} }
...@@ -2948,12 +2948,15 @@ build_new (placement, decl, init, use_global_new) ...@@ -2948,12 +2948,15 @@ build_new (placement, decl, init, use_global_new)
else else
size = size_in_bytes (type); size = size_in_bytes (type);
if (true_type == void_type_node)
{
error ("invalid type for new: `void'");
return error_mark_node;
}
if (TYPE_SIZE (true_type) == 0) if (TYPE_SIZE (true_type) == 0)
{ {
if (true_type == void_type_node) incomplete_type_error (0, true_type);
error ("invalid type for new: `void'");
else
incomplete_type_error (0, true_type);
return error_mark_node; return error_mark_node;
} }
......
...@@ -403,6 +403,8 @@ void ...@@ -403,6 +403,8 @@ void
init_lex () init_lex ()
{ {
extern char *(*decl_printable_name) (); extern char *(*decl_printable_name) ();
extern int flag_no_gnu_keywords;
extern int flag_operator_names;
int i; int i;
...@@ -788,23 +790,21 @@ init_lex () ...@@ -788,23 +790,21 @@ init_lex ()
} }
#endif #endif
if (! (flag_gc || flag_rtti)) if (! (flag_gc || flag_rtti) || flag_no_gnu_keywords)
{ {
UNSET_RESERVED_WORD ("classof"); UNSET_RESERVED_WORD ("classof");
UNSET_RESERVED_WORD ("headof"); UNSET_RESERVED_WORD ("headof");
} }
if (! flag_handle_signatures) if (! flag_handle_signatures || flag_no_gnu_keywords)
{ {
/* Easiest way to not recognize signature /* Easiest way to not recognize signature
handling extensions... */ handling extensions... */
UNSET_RESERVED_WORD ("signature"); UNSET_RESERVED_WORD ("signature");
UNSET_RESERVED_WORD ("sigof"); UNSET_RESERVED_WORD ("sigof");
} }
if (flag_no_asm) if (flag_no_asm || flag_no_gnu_keywords)
UNSET_RESERVED_WORD ("asm");
if (flag_no_asm || flag_traditional)
UNSET_RESERVED_WORD ("typeof"); UNSET_RESERVED_WORD ("typeof");
if (!flag_ansi) if (! flag_operator_names)
{ {
/* These are new ANSI keywords that may break code. */ /* These are new ANSI keywords that may break code. */
UNSET_RESERVED_WORD ("and"); UNSET_RESERVED_WORD ("and");
...@@ -815,6 +815,8 @@ init_lex () ...@@ -815,6 +815,8 @@ init_lex ()
UNSET_RESERVED_WORD ("or"); UNSET_RESERVED_WORD ("or");
UNSET_RESERVED_WORD ("xor"); UNSET_RESERVED_WORD ("xor");
} }
if (! flag_traditional)
UNSET_RESERVED_WORD ("overload");
token_count = init_parse (); token_count = init_parse ();
interface_unknown = 1; interface_unknown = 1;
...@@ -4211,7 +4213,7 @@ real_yylex () ...@@ -4211,7 +4213,7 @@ real_yylex ()
goto tryagain; goto tryagain;
if (width < HOST_BITS_PER_INT if (width < HOST_BITS_PER_INT
&& (unsigned) c >= (1 << width)) && (unsigned) c >= (1 << width))
pedwarn ("escape sequence out of range for character"); warning ("escape sequence out of range for character");
#ifdef MAP_CHARACTER #ifdef MAP_CHARACTER
if (isprint (c)) if (isprint (c))
c = MAP_CHARACTER (c); c = MAP_CHARACTER (c);
...@@ -4328,7 +4330,7 @@ real_yylex () ...@@ -4328,7 +4330,7 @@ real_yylex ()
if (!wide_flag if (!wide_flag
&& TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
&& c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node))) && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
pedwarn ("escape sequence out of range for character"); warning ("escape sequence out of range for character");
} }
else if (c == '\n') else if (c == '\n')
{ {
...@@ -4483,7 +4485,7 @@ real_yylex () ...@@ -4483,7 +4485,7 @@ real_yylex ()
} }
else if ((c == '-') && (c1 == '>')) else if ((c == '-') && (c1 == '>'))
{ {
nextchar = skip_white_space (getch ()); nextchar = getch ();
if (nextchar == '*') if (nextchar == '*')
{ {
nextchar = -1; nextchar = -1;
...@@ -4510,11 +4512,22 @@ real_yylex () ...@@ -4510,11 +4512,22 @@ real_yylex ()
value = MIN_MAX; value = MIN_MAX;
nextchar = c1; nextchar = c1;
} }
if (flag_ansi) if (pedantic)
pedwarn ("use of `operator %s' is not standard C++", pedwarn ("use of `operator %s' is not standard C++",
token_buffer); token_buffer);
goto done; goto done;
} }
/* digraphs */
else if (c == '<' && c1 == '%')
{ value = '{'; goto done; }
else if (c == '<' && c1 == ':')
{ value = '['; goto done; }
else if (c == '%' && c1 == '>')
{ value = '}'; goto done; }
else if (c == '%' && c1 == ':')
{ value = '#'; goto done; }
else if (c == ':' && c1 == '>')
{ value = ']'; goto done; }
nextchar = c1; nextchar = c1;
token_buffer[1] = 0; token_buffer[1] = 0;
......
...@@ -123,6 +123,7 @@ extern int looking_for_template; ...@@ -123,6 +123,7 @@ 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;
extern tree got_object;
/* Pending language change. /* Pending language change.
Positive is push count, negative is pop count. */ Positive is push count, negative is pop count. */
......
...@@ -1246,7 +1246,8 @@ expr_no_commas: ...@@ -1246,7 +1246,8 @@ expr_no_commas:
| expr_no_commas '?' xexpr ':' expr_no_commas | expr_no_commas '?' xexpr ':' expr_no_commas
{ $$ = build_x_conditional_expr ($$, $3, $5); } { $$ = build_x_conditional_expr ($$, $3, $5); }
| expr_no_commas '=' expr_no_commas | expr_no_commas '=' expr_no_commas
{ $$ = build_modify_expr ($$, NOP_EXPR, $3); } { $$ = build_modify_expr ($$, NOP_EXPR, $3);
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
| expr_no_commas ASSIGN expr_no_commas | expr_no_commas ASSIGN expr_no_commas
{ register tree rval; { register tree rval;
if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3, if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
...@@ -1333,7 +1334,12 @@ primary: ...@@ -1333,7 +1334,12 @@ primary:
| string | string
{ $$ = combine_strings ($$); } { $$ = combine_strings ($$); }
| '(' expr ')' | '(' expr ')'
{ $$ = $2; } { char class = TREE_CODE_CLASS (TREE_CODE ($2));
if (class == 'e' || class == '1'
|| class == '2' || class == '<')
/* This inhibits warnings in truthvalue_conversion. */
C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK);
$$ = $2; }
| '(' error ')' | '(' error ')'
{ $$ = error_mark_node; } { $$ = error_mark_node; }
| '(' | '('
...@@ -1538,11 +1544,14 @@ primary: ...@@ -1538,11 +1544,14 @@ primary:
| overqualified_id LEFT_RIGHT | overqualified_id LEFT_RIGHT
{ $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); } { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
| object unqualified_id %prec UNARY | object unqualified_id %prec UNARY
{ $$ = build_component_ref ($$, $2, NULL_TREE, 1); } { got_object = NULL_TREE;
$$ = build_component_ref ($$, $2, NULL_TREE, 1); }
| object qualified_id %prec UNARY | object qualified_id %prec UNARY
{ $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); } { got_object = NULL_TREE;
$$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
| object unqualified_id '(' nonnull_exprlist ')' | object unqualified_id '(' nonnull_exprlist ')'
{ {
got_object = NULL_TREE;
#if 0 #if 0
/* This is a future direction of this code, but because /* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done build_x_function_call cannot always undo what is done
...@@ -1558,6 +1567,7 @@ primary: ...@@ -1558,6 +1567,7 @@ primary:
} }
| object unqualified_id LEFT_RIGHT | object unqualified_id LEFT_RIGHT
{ {
got_object = NULL_TREE;
#if 0 #if 0
/* This is a future direction of this code, but because /* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done build_x_function_call cannot always undo what is done
...@@ -1573,6 +1583,7 @@ primary: ...@@ -1573,6 +1583,7 @@ primary:
} }
| object qualified_id '(' nonnull_exprlist ')' | object qualified_id '(' nonnull_exprlist ')'
{ {
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
{ {
warning ("signature name in scope resolution ignored"); warning ("signature name in scope resolution ignored");
...@@ -1584,6 +1595,7 @@ primary: ...@@ -1584,6 +1595,7 @@ primary:
} }
| object qualified_id LEFT_RIGHT | object qualified_id LEFT_RIGHT
{ {
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
{ {
warning ("signature name in scope resolution ignored"); warning ("signature name in scope resolution ignored");
...@@ -1595,14 +1607,16 @@ primary: ...@@ -1595,14 +1607,16 @@ primary:
} }
/* p->int::~int() is valid -- 12.4 */ /* p->int::~int() is valid -- 12.4 */
| object '~' TYPESPEC LEFT_RIGHT | object '~' TYPESPEC LEFT_RIGHT
{ {
got_object = NULL_TREE;
if (TREE_CODE (TREE_TYPE ($1)) if (TREE_CODE (TREE_TYPE ($1))
!= TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3)))) != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))
cp_error ("`%E' is not of type `%T'", $1, $3); cp_error ("`%E' is not of type `%T'", $1, $3);
$$ = convert (void_type_node, $1); $$ = convert (void_type_node, $1);
} }
| object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT | object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT
{ {
got_object = NULL_TREE;
if ($2 != $5) if ($2 != $5)
cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5); cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5);
if (TREE_CODE (TREE_TYPE ($1)) if (TREE_CODE (TREE_TYPE ($1))
...@@ -1610,6 +1624,11 @@ primary: ...@@ -1610,6 +1624,11 @@ primary:
cp_error ("`%E' is not of type `%T'", $1, $2); cp_error ("`%E' is not of type `%T'", $1, $2);
$$ = convert (void_type_node, $1); $$ = convert (void_type_node, $1);
} }
| object error
{
got_object = NULL_TREE;
$$ = error_mark_node;
}
; ;
/* Not needed for now. /* Not needed for now.
...@@ -1690,9 +1709,11 @@ nodecls: ...@@ -1690,9 +1709,11 @@ nodecls:
; ;
object: primary '.' object: primary '.'
{ got_object = TREE_TYPE ($$); }
| primary POINTSAT | primary POINTSAT
{ {
$$ = build_x_arrow ($$); $$ = build_x_arrow ($$);
got_object = TREE_TYPE ($$);
} }
; ;
...@@ -3288,7 +3309,7 @@ simple_stmt: ...@@ -3288,7 +3309,7 @@ simple_stmt:
else if (success == 2) else if (success == 2)
{ {
cp_error ("duplicate case value `%E'", $2); cp_error ("duplicate case value `%E'", $2);
cp_error_at ("`%E' previously used here", duplicate); cp_error_at ("previously used here", duplicate);
} }
else if (success == 3) else if (success == 3)
warning ("case value out of range"); warning ("case value out of range");
......
...@@ -1257,6 +1257,8 @@ tsubst (t, args, nargs, in_decl) ...@@ -1257,6 +1257,8 @@ tsubst (t, args, nargs, in_decl)
type = newtype; type = newtype;
fnargs = copy_node (DECL_ARGUMENTS (t)); fnargs = copy_node (DECL_ARGUMENTS (t));
TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));
/* In this case we need "in-charge" flag saying whether /* In this case we need "in-charge" flag saying whether
this constructor is responsible for initialization this constructor is responsible for initialization
of virtual baseclasses or not. */ of virtual baseclasses or not. */
...@@ -1419,7 +1421,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1419,7 +1421,7 @@ tsubst (t, args, nargs, in_decl)
r = build_lang_decl (FUNCTION_DECL, r, type); r = build_lang_decl (FUNCTION_DECL, r, type);
DECL_ASSEMBLER_NAME (r) = a; DECL_ASSEMBLER_NAME (r) = a;
} }
else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r)) else if (TREE_STATIC (r))
{ {
/* This overrides the template version, use it. */ /* This overrides the template version, use it. */
return r; return r;
...@@ -1718,7 +1720,7 @@ instantiate_template (tmpl, targ_ptr) ...@@ -1718,7 +1720,7 @@ instantiate_template (tmpl, targ_ptr)
/* 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. */
if (DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl)) if (TREE_STATIC (fndecl))
{ {
SET_DECL_TEMPLATE_SPECIALIZATION (fndecl); SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
p = (struct pending_inline *)0; p = (struct pending_inline *)0;
...@@ -2448,7 +2450,7 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2448,7 +2450,7 @@ do_function_instantiation (declspecs, declarator, storage)
{ {
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn)); int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
tree *targs = (tree *) malloc (sizeof (tree) * ntparms); tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
int i, dummy; int i, dummy = 0;
i = type_unification (DECL_TEMPLATE_PARMS (fn), targs, i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
TYPE_ARG_TYPES (TREE_TYPE (fn)), TYPE_ARG_TYPES (TREE_TYPE (fn)),
TYPE_ARG_TYPES (TREE_TYPE (decl)), TYPE_ARG_TYPES (TREE_TYPE (decl)),
...@@ -2460,6 +2462,7 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2460,6 +2462,7 @@ do_function_instantiation (declspecs, declarator, storage)
else else
result = instantiate_template (fn, targs); result = instantiate_template (fn, targs);
} }
free (targs);
} }
} }
if (! result) if (! result)
......
...@@ -1089,18 +1089,29 @@ lookup_field (xbasetype, name, protect, want_type) ...@@ -1089,18 +1089,29 @@ lookup_field (xbasetype, name, protect, want_type)
entry = 0; entry = 0;
rval = lookup_field_1 (type, name); rval = lookup_field_1 (type, name);
if (rval || lookup_fnfields_here (type, name)>=0)
{
rval_binfo = basetype_path;
rval_binfo_h = rval_binfo;
}
if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
rval = NULL_TREE;
if (rval) if (rval || lookup_fnfields_here (type, name) >= 0)
{ {
if (protect) if (rval)
{
if (want_type)
{
if (TREE_CODE (rval) != TYPE_DECL)
{
rval = purpose_member (name, CLASSTYPE_TAGS (type));
if (rval)
rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
}
}
else
{
if (TREE_CODE (rval) == TYPE_DECL
&& lookup_fnfields_here (type, name) >= 0)
rval = NULL_TREE;
}
}
if (protect && rval)
{ {
if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval)) if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
this_v = compute_access (basetype_path, rval); this_v = compute_access (basetype_path, rval);
...@@ -1259,12 +1270,33 @@ lookup_field (xbasetype, name, protect, want_type) ...@@ -1259,12 +1270,33 @@ lookup_field (xbasetype, name, protect, want_type)
if (entry) if (entry)
TREE_VALUE (entry) = rval; TREE_VALUE (entry) = rval;
if (want_type && (rval == NULL_TREE || TREE_CODE (rval) != TYPE_DECL)) if (rval_binfo)
{ {
rval = NULL_TREE; type = BINFO_TYPE (rval_binfo);
errstr = 0;
if (rval)
{
if (want_type)
{
if (TREE_CODE (rval) != TYPE_DECL)
{
rval = purpose_member (name, CLASSTYPE_TAGS (type));
if (rval)
rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
}
}
else
{
if (TREE_CODE (rval) == TYPE_DECL
&& lookup_fnfields_here (type, name) >= 0)
rval = NULL_TREE;
}
}
} }
if (rval == NULL_TREE)
errstr = 0;
/* If this FIELD_DECL defines its own access level, deal with that. */ /* If this FIELD_DECL defines its own access level, deal with that. */
if (rval && errstr == 0 if (rval && errstr == 0
&& ((protect&1) || entry) && ((protect&1) || entry)
...@@ -1948,11 +1980,51 @@ get_matching_virtual (binfo, fndecl, dtorp) ...@@ -1948,11 +1980,51 @@ get_matching_virtual (binfo, fndecl, dtorp)
== TYPE_READONLY (instptr_type)) == TYPE_READONLY (instptr_type))
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3)) && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
{ {
if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE tree brettype = TREE_TYPE (TREE_TYPE (tmp));
&& ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1)) if (comptypes (brettype, drettype, 1))
/* OK */;
else if
(TREE_CODE (brettype) == TREE_CODE (drettype)
&& (TREE_CODE (brettype) == POINTER_TYPE
|| TREE_CODE (brettype) == REFERENCE_TYPE)
&& comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (brettype)),
TYPE_MAIN_VARIANT (TREE_TYPE (drettype)),
0))
/* covariant return type */
{
tree b = TREE_TYPE (brettype), d = TREE_TYPE (drettype);
if (TYPE_MAIN_VARIANT (b) != TYPE_MAIN_VARIANT (d))
{
tree binfo = get_binfo (b, d, 1);
if (binfo != error_mark_node
&& ! BINFO_OFFSET_ZEROP (binfo))
sorry ("adjusting pointers for covariant returns");
}
if (TYPE_READONLY (d) > TYPE_READONLY (b))
{
cp_error ("return type of `%#D' adds const", fndecl);
cp_error_at (" overriding definition as `%#D'",
tmp);
}
else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b))
{
cp_error ("return type of `%#D' adds volatile",
fndecl);
cp_error_at (" overriding definition as `%#D'",
tmp);
}
}
else if (IS_AGGR_TYPE_2 (brettype, drettype)
&& comptypes (brettype, drettype, 0))
{
error ("invalid covariant return type (must use pointer or reference)");
cp_error_at (" overriding `%#D'", tmp);
cp_error (" with `%#D'", fndecl);
}
else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
{ {
cp_error ("conflicting return type specified for virtual function `%#D'", fndecl); cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
cp_error_at ("overriding definition as `%#D'", tmp); cp_error_at (" overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype); SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
} }
break; break;
...@@ -2192,7 +2264,7 @@ dfs_walk (binfo, fn, qfn) ...@@ -2192,7 +2264,7 @@ dfs_walk (binfo, fn, qfn)
{ {
tree base_binfo = TREE_VEC_ELT (binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i);
if ((*qfn)(base_binfo)) if (qfn == 0 || (*qfn)(base_binfo))
{ {
if (fn == dfs_init_vbase_pointers) if (fn == dfs_init_vbase_pointers)
{ {
...@@ -2800,8 +2872,14 @@ dfs_pushdecls (binfo) ...@@ -2800,8 +2872,14 @@ dfs_pushdecls (binfo)
? DECL_CLASS_CONTEXT (value) ? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value); : DECL_CONTEXT (value);
if (context && (context == type if (context == type)
|| TYPE_DERIVES_FROM (context, type))) {
if (TREE_CODE (value) == TYPE_DECL
&& DECL_ARTIFICIAL (value))
value = fields;
/* else the old value wins */
}
else if (context && TYPE_DERIVES_FROM (context, type))
value = fields; value = fields;
else else
value = tree_cons (NULL_TREE, fields, value = tree_cons (NULL_TREE, fields,
...@@ -3210,3 +3288,24 @@ reinit_search_statistics () ...@@ -3210,3 +3288,24 @@ reinit_search_statistics ()
n_outer_fields_searched = 0; n_outer_fields_searched = 0;
n_contexts_saved = 0; n_contexts_saved = 0;
} }
static tree conversions;
static void
add_conversions (binfo)
tree binfo;
{
tree tmp = CLASSTYPE_FIRST_CONVERSION (BINFO_TYPE (binfo));
for (; tmp && IDENTIFIER_TYPENAME_P (DECL_NAME (tmp));
tmp = TREE_CHAIN (tmp))
conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
conversions);
}
tree
lookup_conversions (type)
tree type;
{
conversions = NULL_TREE;
dfs_walk (TYPE_BINFO (type), add_conversions, 0);
return conversions;
}
...@@ -242,6 +242,7 @@ int looking_for_template; ...@@ -242,6 +242,7 @@ int looking_for_template;
extern struct obstack *current_obstack, *saveable_obstack; extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope; tree got_scope;
tree got_object;
int int
yylex() yylex()
...@@ -316,7 +317,7 @@ yylex() ...@@ -316,7 +317,7 @@ yylex()
if (lastiddecl != trrr) if (lastiddecl != trrr)
{ {
lastiddecl = trrr; lastiddecl = trrr;
if (got_scope) if (got_scope || got_object)
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr); tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
} }
break; break;
...@@ -334,8 +335,11 @@ yylex() ...@@ -334,8 +335,11 @@ yylex()
lastiddecl = trrr; lastiddecl = trrr;
got_scope = NULL_TREE; got_scope = NULL_TREE;
/* and fall through to... */ /* and fall through to... */
case IDENTIFIER_DEFN:
case TYPENAME: case TYPENAME:
case TYPENAME_DEFN:
case PTYPENAME: case PTYPENAME:
case PTYPENAME_DEFN:
consume_token (); consume_token ();
if (looking_for_typename > 0) if (looking_for_typename > 0)
looking_for_typename--; looking_for_typename--;
......
...@@ -102,6 +102,11 @@ lvalue_p (ref) ...@@ -102,6 +102,11 @@ lvalue_p (ref)
case COMPOUND_EXPR: case COMPOUND_EXPR:
return lvalue_p (TREE_OPERAND (ref, 1)); return lvalue_p (TREE_OPERAND (ref, 1));
case MAX_EXPR:
case MIN_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1)));
} }
return 0; return 0;
...@@ -570,9 +575,13 @@ layout_vbasetypes (rec, max) ...@@ -570,9 +575,13 @@ layout_vbasetypes (rec, max)
BINFO_OFFSET (vbase_types) = offset; BINFO_OFFSET (vbase_types) = offset;
if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST) if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
const_size += MAX (BITS_PER_UNIT, {
TREE_INT_CST_LOW (TYPE_SIZE (basetype)) /* Every virtual baseclass takes a least a UNIT, so that we can
- TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype))); take it's address and get something different for each base. */
const_size += MAX (BITS_PER_UNIT,
TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
}
else if (var_size == 0) else if (var_size == 0)
var_size = TYPE_SIZE (basetype); var_size = TYPE_SIZE (basetype);
else else
...@@ -581,6 +590,15 @@ layout_vbasetypes (rec, max) ...@@ -581,6 +590,15 @@ layout_vbasetypes (rec, max)
vbase_types = TREE_CHAIN (vbase_types); vbase_types = TREE_CHAIN (vbase_types);
} }
if (const_size)
{
/* Because a virtual base might take a single byte above,
we have to re-adjust the total size to make sure it it
a multiple of the alignment. */
/* Give the whole object the alignment it wants. */
const_size = CEIL (const_size, record_align) * record_align;
}
/* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN /* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN
here, as that is for this class, without any virtual base classes. */ here, as that is for this class, without any virtual base classes. */
TYPE_ALIGN (rec) = record_align; TYPE_ALIGN (rec) = record_align;
......
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