summaryrefslogtreecommitdiffstats
path: root/contrib/gcc
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-05-09 22:39:46 +0000
committerobrien <obrien@FreeBSD.org>2002-05-09 22:39:46 +0000
commit3519dd389b0bb7b94381bca2620e4cec76ed73c4 (patch)
treeebf2588df8638f4c6b467bf2a62a50daadc0cc56 /contrib/gcc
parent37ab630335eab350f04644d69007ed62cea157f4 (diff)
downloadFreeBSD-src-3519dd389b0bb7b94381bca2620e4cec76ed73c4.zip
FreeBSD-src-3519dd389b0bb7b94381bca2620e4cec76ed73c4.tar.gz
Merge rev 1.2 (printf format error fixes) in its 1.8 form into Gcc 3.1 pre.
Diffstat (limited to 'contrib/gcc')
-rw-r--r--contrib/gcc/cp/decl.c746
1 files changed, 405 insertions, 341 deletions
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c
index 04b92c4..72ebd55 100644
--- a/contrib/gcc/cp/decl.c
+++ b/contrib/gcc/cp/decl.c
@@ -48,15 +48,11 @@ Boston, MA 02111-1307, USA. */
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
+#include "c-pragma.h"
#include "diagnostic.h"
extern const struct attribute_spec *lang_attribute_table;
-#ifndef BOOL_TYPE_SIZE
-/* `bool' has size and alignment `1', on all platforms. */
-#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE
-#endif
-
#ifndef HOST_PTR_PRINTF_FORMAT
#define HOST_PTR_PRINTF_FORMAT HOST_PTR_PRINTF
#endif
@@ -90,11 +86,14 @@ static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
enum overload_flags, tree,
tree, int, int, int, int, int, int, tree));
static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree));
+static tree follow_tag_typedef PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree,
struct binding_level *, int));
static void set_identifier_type_value_with_scope
PARAMS ((tree, tree, struct binding_level *));
static void record_unknown_type PARAMS ((tree, const char *));
+static tree builtin_function_1 PARAMS ((const char *, tree, tree, int,
+ enum built_in_class, const char *));
static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
@@ -404,10 +403,6 @@ struct binding_level
/* The binding level which this one is contained in (inherits from). */
struct binding_level *level_chain;
- /* List of decls in `names' that have incomplete
- structure or union types. */
- tree incomplete;
-
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ISO-conforming code, but might
be referenced in ARM-era code. These are stored in a
@@ -490,6 +485,12 @@ static struct binding_level *global_binding_level;
static int keep_next_level_flag;
+/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or
+ UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
+ time the VAR_DECL was declared, the type was incomplete. */
+
+static tree incomplete_vars;
+
#if defined(DEBUG_CP_BINDING_LEVELS)
static int binding_depth = 0;
static int is_class_level = 0;
@@ -851,7 +852,6 @@ pushlevel (tag_transparent)
newlevel = make_binding_level ();
push_binding_level (newlevel, tag_transparent, keep_next_level_flag);
- GNU_xref_start_scope ((size_t) newlevel);
keep_next_level_flag = 0;
}
@@ -1310,11 +1310,6 @@ poplevel (keep, reverse, functionbody)
rather than the end. This hack is no longer used. */
my_friendly_assert (keep == 0 || keep == 1, 0);
- GNU_xref_end_scope ((size_t) current_binding_level,
- (size_t) current_binding_level->level_chain,
- current_binding_level->parm_flag,
- current_binding_level->keep);
-
if (current_binding_level->keep == 1)
keep = 1;
@@ -1736,11 +1731,6 @@ poplevel_class ()
shadowed = TREE_CHAIN (shadowed))
pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
- GNU_xref_end_scope ((size_t) class_binding_level,
- (size_t) class_binding_level->level_chain,
- class_binding_level->parm_flag,
- class_binding_level->keep);
-
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
#if defined(DEBUG_CP_BINDING_LEVELS)
@@ -1974,7 +1964,6 @@ mark_binding_level (arg)
ggc_mark_tree (lvl->shadowed_labels);
ggc_mark_tree (lvl->blocks);
ggc_mark_tree (lvl->this_class);
- ggc_mark_tree (lvl->incomplete);
ggc_mark_tree (lvl->dead_vars_from_for);
}
}
@@ -2012,8 +2001,6 @@ print_binding_level (lvl)
int i = 0, len;
fprintf (stderr, " blocks=");
fprintf (stderr, HOST_PTR_PRINTF_FORMAT, HOST_PTR_PRINTF_TYPE lvl->blocks);
- fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d",
- list_length (lvl->incomplete), lvl->parm_flag, lvl->keep);
if (lvl->tag_transparent)
fprintf (stderr, " tag-transparent");
if (lvl->more_cleanups_ok)
@@ -2414,7 +2401,6 @@ mark_saved_scope (arg)
ggc_mark_tree (t->x_previous_class_type);
ggc_mark_tree (t->x_previous_class_values);
ggc_mark_tree (t->x_saved_tree);
- ggc_mark_tree (t->incomplete);
ggc_mark_tree (t->lookups);
mark_stmt_tree (&t->x_stmt_tree);
@@ -2520,6 +2506,7 @@ maybe_push_to_top_level (pseudo)
s->bindings = b;
s->need_pop_function_context = need_pop;
s->function_decl = current_function_decl;
+ s->last_parms = last_function_parms;
scope_chain = s;
current_function_decl = NULL_TREE;
@@ -2561,6 +2548,7 @@ pop_from_top_level ()
if (s->need_pop_function_context)
pop_function_context_from (NULL_TREE);
current_function_decl = s->function_decl;
+ last_function_parms = s->last_parms;
free (s);
}
@@ -3162,6 +3150,10 @@ duplicate_decls (newdecl, olddecl)
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
+ /* Avoid warnings redeclaring anticipated built-ins. */
+ if (DECL_ANTICIPATED (olddecl))
+ return 0;
+
/* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a
bad choice of name. */
@@ -3189,7 +3181,10 @@ duplicate_decls (newdecl, olddecl)
}
else if (!types_match)
{
- if ((DECL_EXTERN_C_P (newdecl)
+ /* Avoid warnings redeclaring anticipated built-ins. */
+ if (DECL_ANTICIPATED (olddecl))
+ ; /* Do nothing yet. */
+ else if ((DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl))
|| compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
@@ -3210,6 +3205,9 @@ duplicate_decls (newdecl, olddecl)
else
/* Discard the old built-in function. */
return 0;
+
+ /* Replace the old RTL to avoid problems with inlining. */
+ SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
@@ -3224,9 +3222,6 @@ duplicate_decls (newdecl, olddecl)
will be banished. */
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
- COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (newdecl),
- newdecl);
}
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
@@ -3364,6 +3359,7 @@ duplicate_decls (newdecl, olddecl)
&& namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl);
+ return 0;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE
@@ -3409,13 +3405,10 @@ duplicate_decls (newdecl, olddecl)
if (1 == simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)))
{
- if (pedantic)
- {
- pedwarn ("default argument given for parameter %d of `%#D'",
- i, newdecl);
- cp_pedwarn_at ("after previous specification in `%#D'",
- olddecl);
- }
+ pedwarn ("default argument given for parameter %d of `%#D'",
+ i, newdecl);
+ cp_pedwarn_at ("after previous specification in `%#D'",
+ olddecl);
}
else
{
@@ -3438,6 +3431,18 @@ duplicate_decls (newdecl, olddecl)
}
}
+ /* Do not merge an implicit typedef with an explicit one. In:
+
+ class A;
+ ...
+ typedef class A A __attribute__ ((foo));
+
+ the attribute should apply only to the typedef. */
+ if (TREE_CODE (olddecl) == TYPE_DECL
+ && (DECL_IMPLICIT_TYPEDEF_P (olddecl)
+ || DECL_IMPLICIT_TYPEDEF_P (newdecl)))
+ return 0;
+
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
@@ -3504,6 +3509,7 @@ duplicate_decls (newdecl, olddecl)
except for any that we copy here from the old type. */
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
+ decl_attributes (&newdecl, DECL_ATTRIBUTES (newdecl), 0);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
@@ -3535,16 +3541,16 @@ duplicate_decls (newdecl, olddecl)
tree newtype;
/* Merge the data types specified in the two decls. */
- newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+ newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
- /* If common_type produces a non-typedef type, just use the old type. */
+ /* If merge_types produces a non-typedef type, just use the old type. */
if (TREE_CODE (newdecl) == TYPE_DECL
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
- /* Do this after calling `common_type' so that default
+ /* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
@@ -3608,15 +3614,23 @@ duplicate_decls (newdecl, olddecl)
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
- /* Keep the old rtl since we can safely use it. */
- COPY_DECL_RTL (olddecl, newdecl);
-
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_LIMIT_STACK (newdecl)
|= DECL_NO_LIMIT_STACK (olddecl);
+ /* Keep the old RTL. */
+ COPY_DECL_RTL (olddecl, newdecl);
+ }
+ else if (TREE_CODE (newdecl) == VAR_DECL
+ && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
+ {
+ /* Keep the old RTL. We cannot keep the old RTL if the old
+ declaration was for an incomplete object and the new
+ declaration is not since many attributes of the RTL will
+ change. */
+ COPY_DECL_RTL (olddecl, newdecl);
}
}
/* If cannot merge, then use the new type and qualifiers,
@@ -3635,7 +3649,8 @@ duplicate_decls (newdecl, olddecl)
}
/* Merge the storage class information. */
- DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+ merge_weak (newdecl, olddecl);
+
DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
@@ -4251,22 +4266,8 @@ pushdecl (x)
if (TREE_CODE (x) == FUNCTION_DECL)
check_default_args (x);
- /* Keep count of variables in this level with incomplete type. */
- if (TREE_CODE (x) == VAR_DECL
- && TREE_TYPE (x) != error_mark_node
- && ((!COMPLETE_TYPE_P (TREE_TYPE (x))
- && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
- /* RTTI TD entries are created while defining the type_info. */
- || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
- && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
- {
- if (namespace_bindings_p ())
- namespace_scope_incomplete
- = tree_cons (NULL_TREE, x, namespace_scope_incomplete);
- else
- current_binding_level->incomplete
- = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
- }
+ if (TREE_CODE (x) == VAR_DECL)
+ maybe_register_incomplete_var (x);
}
if (need_new_binding)
@@ -5310,6 +5311,47 @@ storetags (tags)
current_binding_level->tags = tags;
}
+/* Return the type that should be used when TYPE's name is preceded
+ by a tag such as 'struct' or 'union', or null if the name cannot
+ be used in this way.
+
+ For example, when processing the third line of:
+
+ struct A;
+ typedef struct A A;
+ struct A;
+
+ lookup of A will find the typedef. Given A's typedef, this function
+ will return the type associated with "struct A". For the tag to be
+ anything other than TYPE, TYPE must be a typedef whose original type
+ has the same name and context as TYPE itself.
+
+ It is not valid for a typedef of an anonymous type to be used with
+ an explicit tag:
+
+ typedef struct { ... } B;
+ struct B;
+
+ Return null for this case. */
+
+static tree
+follow_tag_typedef (type)
+ tree type;
+{
+ tree original;
+
+ original = original_type (type);
+ if (! TYPE_NAME (original))
+ return NULL_TREE;
+ if (TYPE_IDENTIFIER (original) == TYPE_IDENTIFIER (type)
+ && (CP_DECL_CONTEXT (TYPE_NAME (original))
+ == CP_DECL_CONTEXT (TYPE_NAME (type)))
+ && !(CLASS_TYPE_P (original) && TYPE_WAS_ANONYMOUS (original)))
+ return original;
+ else
+ return NULL_TREE;
+}
+
/* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name.
Searches binding levels from BINDING_LEVEL up to the global level.
@@ -5361,18 +5403,23 @@ lookup_tag (form, name, binding_level, thislevel_only)
else
old = BINDING_TYPE (old);
- /* If it has an original type, it is a typedef, and we
- should not return it. */
- if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
- old = NULL_TREE;
- if (old && TREE_CODE (old) != form
- && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL))
+ if (old)
{
- error ("`%#D' redeclared as %C", old, form);
- return NULL_TREE;
+ /* We've found something at this binding level. If it is
+ a typedef, extract the tag it refers to. Lookup fails
+ if the typedef doesn't refer to a taggable type. */
+ old = follow_tag_typedef (old);
+ if (!old)
+ return NULL_TREE;
+ if (TREE_CODE (old) != form
+ && (form == ENUMERAL_TYPE
+ || TREE_CODE (old) == ENUMERAL_TYPE))
+ {
+ error ("`%#D' redeclared as %C", old, form);
+ return NULL_TREE;
+ }
+ return old;
}
- if (old)
- return old;
if (thislevel_only || tail == global_namespace)
return NULL_TREE;
}
@@ -5382,14 +5429,12 @@ lookup_tag (form, name, binding_level, thislevel_only)
if (TREE_PURPOSE (tail) == name)
{
enum tree_code code = TREE_CODE (TREE_VALUE (tail));
- /* Should tighten this up; it'll probably permit
- UNION_TYPE and a struct template, for example. */
+
if (code != form
- && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL))
+ && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
{
/* Definition isn't the kind we were looking for. */
- error ("`%#D' redeclared as %C", TREE_VALUE (tail),
- form);
+ error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
return NULL_TREE;
}
return TREE_VALUE (tail);
@@ -5511,7 +5556,7 @@ lookup_namespace_name (namespace, name)
/*in_decl=*/NULL_TREE,
/*context=*/NULL_TREE,
/*entering_scope=*/0,
- /*complain=*/1);
+ tf_error | tf_warning);
else if (DECL_FUNCTION_TEMPLATE_P (val)
|| TREE_CODE (val) == OVERLOAD)
val = lookup_template_function (val,
@@ -5527,7 +5572,12 @@ lookup_namespace_name (namespace, name)
/* If we have a single function from a using decl, pull it out. */
if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
val = OVL_FUNCTION (val);
- return val;
+
+ /* Ignore built-in functions that haven't been prototyped yet. */
+ if (!val || !DECL_P(val)
+ || !DECL_LANG_SPECIFIC(val)
+ || !DECL_ANTICIPATED (val))
+ return val;
}
error ("`%D' undeclared in namespace `%D'", name, namespace);
@@ -5630,12 +5680,15 @@ build_typename_type (context, name, fullname, base_type)
/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type,
unless an error occurs, in which case error_mark_node is returned.
- If COMPLAIN zero, don't complain about any errors that occur. */
+ If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
+ set, we return that, rather than the _TYPE it corresponds to, in
+ other cases we look through the type decl. If TF_ERROR is set,
+ complain about errors, otherwise be quiet. */
tree
make_typename_type (context, name, complain)
tree context, name;
- int complain;
+ tsubst_flags_t complain;
{
tree fullname;
@@ -5674,7 +5727,7 @@ make_typename_type (context, name, complain)
{
/* We can get here from typename_sub0 in the explicit_template_type
expansion. Just fail. */
- if (complain)
+ if (complain & tf_error)
error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
@@ -5690,7 +5743,7 @@ make_typename_type (context, name, complain)
tmpl = lookup_field (context, name, 0, 0);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
- if (complain)
+ if (complain & tf_error)
error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
@@ -5700,7 +5753,7 @@ make_typename_type (context, name, complain)
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
/*entering_scope=*/0,
- /*complain=*/1);
+ tf_error | tf_warning);
}
else
{
@@ -5708,14 +5761,29 @@ make_typename_type (context, name, complain)
if (!IS_AGGR_TYPE (context))
{
- if (complain)
+ if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
t = lookup_field (context, name, 0, 1);
if (t)
- return TREE_TYPE (t);
+ {
+ if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+ t = TREE_TYPE (t);
+ if (IMPLICIT_TYPENAME_P (t))
+ {
+ /* Lookup found an implicit typename that we had
+ injected into the current scope. Doing things
+ properly would have located the exact same type,
+ so there is no error here. We must remove the
+ implicitness so that we do not warn about it. */
+ t = copy_node (t);
+ TREE_TYPE (t) = NULL_TREE;
+ }
+
+ return t;
+ }
}
}
@@ -5723,7 +5791,7 @@ make_typename_type (context, name, complain)
there now or its never going to be. */
if (!uses_template_parms (context))
{
- if (complain)
+ if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
@@ -5734,7 +5802,9 @@ make_typename_type (context, name, complain)
/* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
unless an error occurs, in which case error_mark_node is returned.
- If COMPLAIN zero, don't complain about any errors that occur. */
+ If we locate a TYPE_DECL, we return that, rather than the _TYPE it
+ corresponds to. If COMPLAIN zero, don't complain about any errors
+ that occur. */
tree
make_unbound_class_template (context, name, complain)
@@ -5797,14 +5867,6 @@ select_decl (binding, flags)
tree val;
val = BINDING_VALUE (binding);
- /* When we implicitly declare some builtin entity, we mark it
- DECL_ANTICIPATED, so that we know to ignore it until it is
- really declared. */
- if (val && DECL_P (val)
- && DECL_LANG_SPECIFIC (val)
- && DECL_ANTICIPATED (val))
- return NULL_TREE;
-
if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
@@ -5854,9 +5916,21 @@ unqualified_namespace_lookup (name, flags, spacesp)
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
val = binding_for_name (name, scope);
- /* Initialize binding for this context. */
- BINDING_VALUE (b) = BINDING_VALUE (val);
- BINDING_TYPE (b) = BINDING_TYPE (val);
+ /* Ignore anticipated built-in functions. */
+ if (val && BINDING_VALUE (val)
+ && DECL_P (BINDING_VALUE (val))
+ && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
+ && DECL_ANTICIPATED (BINDING_VALUE (val)))
+ {
+ BINDING_VALUE (b) = NULL_TREE;
+ BINDING_TYPE (b) = NULL_TREE;
+ }
+ else
+ {
+ /* Initialize binding for this context. */
+ BINDING_VALUE (b) = BINDING_VALUE (val);
+ BINDING_TYPE (b) = BINDING_TYPE (val);
+ }
/* Add all _DECLs seen through local using-directives. */
for (level = current_binding_level;
@@ -6446,12 +6520,6 @@ cxx_init_decl_processing ()
flag_inline_functions = 0;
}
- /* In C++, we never create builtin functions whose name does not
- begin with `__'. Users should be using headers to get prototypes
- in C++. It would be nice if we could warn when `-fbuiltin' is
- used explicitly, but we do not have that information. */
- flag_no_builtin = 1;
-
/* Initially, C. */
current_lang_name = lang_name_c;
@@ -6649,6 +6717,7 @@ cxx_init_decl_processing ()
ggc_add_tree_root (&current_lang_name, 1);
ggc_add_tree_root (&static_aggregates, 1);
ggc_add_tree_root (&free_bindings, 1);
+ ggc_add_tree_root (&incomplete_vars, 1);
}
/* Generate an initializer for a function naming variable from
@@ -6716,10 +6785,9 @@ cp_make_fname_decl (id, type_dep)
return decl;
}
-/* Entry point for the benefit of c_common_nodes_and_builtins.
-
- Make a definition for a builtin function named NAME and whose data type
- is TYPE. TYPE should be a function type with argument types.
+/* Make a definition for a builtin function named NAME in the current
+ namespace, whose data type is TYPE and whose context is CONTEXT.
+ TYPE should be a function type with argument types.
CLASS and CODE tell later passes how to compile calls to this function.
See tree.h for possible values.
@@ -6727,10 +6795,11 @@ cp_make_fname_decl (id, type_dep)
If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
the name to be called if we can't opencode the function. */
-tree
-builtin_function (name, type, code, class, libname)
+static tree
+builtin_function_1 (name, type, context, code, class, libname)
const char *name;
tree type;
+ tree context;
int code;
enum built_in_class class;
const char *libname;
@@ -6738,19 +6807,13 @@ builtin_function (name, type, code, class, libname)
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = code;
+ DECL_CONTEXT (decl) = context;
- my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
+ /* The return builtins leave the current function. */
+ if (code == BUILT_IN_RETURN || code == BUILT_IN_EH_RETURN)
+ TREE_THIS_VOLATILE (decl) = 1;
- /* All builtins that don't begin with an `_' should go in the `std'
- namespace. */
- if (name[0] != '_')
- {
- push_namespace (std_identifier);
- DECL_CONTEXT (decl) = std_node;
- }
pushdecl (decl);
- if (name[0] != '_')
- pop_namespace ();
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
we cannot change DECL_ASSEMBLER_NAME until we have installed this
@@ -6770,6 +6833,39 @@ builtin_function (name, type, code, class, libname)
return decl;
}
+/* Entry point for the benefit of c_common_nodes_and_builtins.
+
+ Make a defintion for a builtin function named NAME and whose data type
+ is TYPE. TYPE should be a function type with argument types. This
+ function places the anticipated declaration in the global namespace
+ and additionally in the std namespace if appropriate.
+
+ CLASS and CODE tell later passes how to compile calls to this function.
+ See tree.h for possible values.
+
+ If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
+ the name to be called if we can't opencode the function. */
+
+tree
+builtin_function (name, type, code, class, libname)
+ const char *name;
+ tree type;
+ int code;
+ enum built_in_class class;
+ const char *libname;
+{
+ /* All builtins that don't begin with an '_' should additionally
+ go in the 'std' namespace. */
+ if (name[0] != '_')
+ {
+ push_namespace (std_identifier);
+ builtin_function_1 (name, type, std_node, code, class, libname);
+ pop_namespace ();
+ }
+
+ return builtin_function_1 (name, type, NULL_TREE, code, class, libname);
+}
+
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
function. Not called directly. */
@@ -7267,6 +7363,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
/* Set attributes here so if duplicate decl, will have proper attributes. */
cplus_decl_attributes (&decl, attributes, 0);
+ /* If #pragma weak was used, mark the decl weak now. */
+ if (current_binding_level == global_binding_level)
+ maybe_apply_pragma_weak (decl);
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
@@ -7399,7 +7499,7 @@ start_decl_1 (decl)
if ((! processing_template_decl || ! uses_template_parms (type))
&& !COMPLETE_TYPE_P (complete_type (type)))
{
- error ("aggregate `%#D' has incomplete type and cannot be initialized",
+ error ("aggregate `%#D' has incomplete type and cannot be defined",
decl);
/* Change the type so that assemble_variable will give
DECL an rtl we can live with: (mem (const_int 0)). */
@@ -7877,8 +7977,9 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
&& toplev
&& !TREE_PUBLIC (decl))
{
- /* Fool with the linkage according to #pragma interface. */
- if (!interface_unknown)
+ /* Fool with the linkage of static consts according to #pragma
+ interface. */
+ if (!interface_unknown && !TREE_PUBLIC (decl))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = interface_only;
@@ -7886,6 +7987,9 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
defer_p = 1;
}
+ /* Likewise for template instantiations. */
+ else if (DECL_COMDAT (decl))
+ defer_p = 1;
/* If we're deferring the variable, we only need to make RTL if
there's an ASMSPEC. Otherwise, we'll lazily create it later when
@@ -8038,8 +8142,7 @@ destroy_local_var (decl)
cleanup = maybe_build_cleanup (decl);
/* Record the cleanup required for this declaration. */
- if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node
- && cleanup)
+ if (DECL_SIZE (decl) && cleanup)
finish_decl_cleanup (decl, cleanup);
}
@@ -8073,8 +8176,10 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
}
/* If a name was specified, get the string. */
+ if (current_binding_level == global_binding_level)
+ asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
- asmspec = TREE_STRING_POINTER (asmspec_tree);
+ asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init && TREE_CODE (init) == NAMESPACE_DECL)
{
@@ -8139,7 +8244,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
set_identifier_type_value (DECL_NAME (decl), type);
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
- GNU_xref_decl (current_function_decl, decl);
/* If we have installed this as the canonical typedef for this
type, and that type has not been defined yet, delay emitting
@@ -8180,8 +8284,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
init = check_initializer (decl, init);
maybe_deduce_size_from_array_init (decl, init);
- GNU_xref_decl (current_function_decl, decl);
-
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
reference temp is added before the DECL_STMT for the reference itself. */
@@ -8515,7 +8617,9 @@ register_dtor_fn (decl)
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
- args = tree_cons (NULL_TREE, get_dso_handle_node (), NULL_TREE);
+ args = tree_cons (NULL_TREE,
+ build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
+ NULL_TREE);
args = tree_cons (NULL_TREE, null_pointer_node, args);
args = tree_cons (NULL_TREE, cleanup, args);
}
@@ -9626,15 +9730,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree spec;
tree type = NULL_TREE;
int longlong = 0;
- int constp;
- int restrictp;
- int volatilep;
int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
int extern_langp = 0;
+ tree dependant_name = NULL_TREE;
tree typedef_decl = NULL_TREE;
const char *name;
@@ -9876,11 +9978,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
|| TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
- error ("`%T::%D' is not a valid declarator", cname,
- TREE_OPERAND (decl, 1));
- error (" perhaps you want `typename %T::%D' to make it a type",
- cname, TREE_OPERAND (decl, 1));
- return void_type_node;
+ /* This might be declaring a member of a template
+ parm to be a friend. */
+ ctype = cname;
+ dependant_name = TREE_OPERAND (decl, 1);
}
else if (ctype == NULL_TREE)
ctype = cname;
@@ -10092,7 +10193,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
}
- /* C++ aggregate types. */
else if (TREE_CODE (id) == TYPE_DECL)
{
if (type)
@@ -10102,6 +10202,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
type = TREE_TYPE (id);
TREE_VALUE (spec) = type;
+ typedef_decl = id;
}
goto found;
}
@@ -10116,10 +10217,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else
{
type = TREE_TYPE (t);
-#if 0
- /* See the code below that used this. */
- decl_attr = DECL_ATTRIBUTES (id);
-#endif
typedef_decl = t;
}
}
@@ -10130,6 +10227,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
found: ;
}
+#if 0
+ /* See the code below that used this. */
+ if (typedef_decl)
+ decl_attr = DECL_ATTRIBUTES (typedef_decl);
+#endif
typedef_type = type;
/* No type at all: default to `int', and set DEFAULTED_INT
@@ -10176,7 +10278,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = integer_type_node;
}
- if (type && TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+ if (type && IMPLICIT_TYPENAME_P (type))
{
/* The implicit typename extension is deprecated and will be
removed. Warn about its use now. */
@@ -10333,26 +10435,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_complex_type (type);
}
- if (sfk == sfk_conversion
- && (RIDBIT_SETP (RID_CONST, specbits)
- || RIDBIT_SETP (RID_VOLATILE, specbits)
- || RIDBIT_SETP (RID_RESTRICT, specbits)))
+ type_quals = TYPE_UNQUALIFIED;
+ if (RIDBIT_SETP (RID_CONST, specbits))
+ type_quals |= TYPE_QUAL_CONST;
+ if (RIDBIT_SETP (RID_VOLATILE, specbits))
+ type_quals |= TYPE_QUAL_VOLATILE;
+ if (RIDBIT_SETP (RID_RESTRICT, specbits))
+ type_quals |= TYPE_QUAL_RESTRICT;
+ if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
error ("qualifiers are not allowed on declaration of `operator %T'",
ctor_return_type);
- /* Set CONSTP if this declaration is `const', whether by
- explicit specification or via a typedef.
- Likewise for VOLATILEP. */
-
- constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type);
- restrictp =
- !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type);
- volatilep =
- !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type);
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- type = cp_build_qualified_type (type, type_quals);
+ type_quals |= cp_type_quals (type);
+ type = cp_build_qualified_type_real
+ (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
+ ? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
+ /* We might have ignored or rejected some of the qualifiers. */
+ type_quals = cp_type_quals (type);
+
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
@@ -10372,6 +10472,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
friendp = RIDBIT_SETP (RID_FRIEND, specbits);
RIDBIT_RESET (RID_FRIEND, specbits);
+ if (dependant_name && !friendp)
+ {
+ error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
+ return void_type_node;
+ }
+
/* Warn if two storage classes are given. Default to `auto'. */
if (RIDBIT_ANY_SET (specbits))
@@ -10839,21 +10945,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
register tree typemodlist;
int erred = 0;
-
- constp = 0;
- volatilep = 0;
- restrictp = 0;
+ int constp = 0;
+ int volatilep = 0;
+ int restrictp = 0;
+
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
tree qualifier = TREE_VALUE (typemodlist);
if (qualifier == ridpointers[(int) RID_CONST])
- constp++;
+ {
+ constp++;
+ type_quals |= TYPE_QUAL_CONST;
+ }
else if (qualifier == ridpointers[(int) RID_VOLATILE])
- volatilep++;
+ {
+ volatilep++;
+ type_quals |= TYPE_QUAL_VOLATILE;
+ }
else if (qualifier == ridpointers[(int) RID_RESTRICT])
- restrictp++;
+ {
+ restrictp++;
+ type_quals |= TYPE_QUAL_RESTRICT;
+ }
else if (!erred)
{
erred = 1;
@@ -10866,20 +10981,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
pedwarn ("duplicate `volatile'");
if (restrictp > 1)
pedwarn ("duplicate `restrict'");
-
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- if (TREE_CODE (declarator) == ADDR_EXPR
- && (constp || volatilep))
- {
- if (constp)
- pedwarn ("discarding `const' applied to a reference");
- if (volatilep)
- pedwarn ("discarding `volatile' applied to a reference");
- type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
- }
type = cp_build_qualified_type (type, type_quals);
+ type_quals = cp_type_quals (type);
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
@@ -10923,7 +11026,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
- type = tsubst (type, args, /*complain=*/1, NULL_TREE);
+ type = tsubst (type, args, tf_error | tf_warning,
+ NULL_TREE);
}
/* This pop_nested_class corresponds to the
@@ -11122,7 +11226,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ RIDBIT_RESET (RID_MUTABLE, specbits);
}
}
@@ -11175,6 +11279,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type)
+ /* Don't do this if there are attributes. */
+ && (!attrlist || !*attrlist)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
tree oldname = TYPE_NAME (type);
@@ -11233,16 +11339,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Detect the case of an array type of unspecified size
which came, as such, direct from a typedef name.
- We must copy the type, so that each identifier gets
- a distinct type, so that each identifier's size can be
- controlled separately by its own initializer. */
+ We must copy the type, so that the array's domain can be
+ individually set by the object's initializer. */
- if (type != 0 && typedef_type != 0
- && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
+ if (type && typedef_type
+ && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
- {
- type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type));
- }
+ type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
/* Detect where we're using a typedef of function type to declare a
function. last_function_parms will not be set, so we must create
@@ -11309,9 +11412,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
/* Only try to do this stuff if we didn't already give up. */
if (type != integer_type_node)
{
- /* DR 209. The friendly class does not need to be accessible
- in the scope of the class granting friendship. */
- skip_type_access_control ();
+ decl_type_access_control (TYPE_NAME (type));
/* A friendly class? */
if (current_class_type)
@@ -11573,33 +11674,32 @@ friend declaration requires class-key, i.e. `friend %#T'",
if (friendp)
{
/* Friends are treated specially. */
- tree t = NULL_TREE;
-
- /* DR 209. The friend does not need to be accessible at this
- point. */
- skip_type_access_control ();
-
if (ctype == current_class_type)
warning ("member functions are implicitly friends of their class");
-
- if (decl && DECL_NAME (decl))
- {
- if (template_class_depth (current_class_type) == 0)
- {
- decl = check_explicit_specialization
- (declarator, decl,
- template_count, 2 * (funcdef_flag != 0) + 4);
- if (decl == error_mark_node)
- return error_mark_node;
- }
-
- t = do_friend (ctype, declarator, decl,
- last_function_parms, *attrlist, flags, quals,
- funcdef_flag);
- }
- if (t && funcdef_flag)
- return t;
- return void_type_node;
+ else
+ {
+ tree t = NULL_TREE;
+ if (decl && DECL_NAME (decl))
+ {
+ if (template_class_depth (current_class_type) == 0)
+ {
+ decl
+ = check_explicit_specialization
+ (declarator, decl,
+ template_count, 2 * (funcdef_flag != 0) + 4);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
+
+ t = do_friend (ctype, declarator, decl,
+ last_function_parms, *attrlist,
+ flags, quals, funcdef_flag);
+ }
+ if (t && funcdef_flag)
+ return t;
+
+ return void_type_node;
+ }
}
/* Structure field. It may not be a function, except for C++ */
@@ -12598,10 +12698,12 @@ grok_op_properties (decl, friendp)
/* Effective C++ rule 23. */
if (warn_ecpp
&& arity == 2
+ && !DECL_ASSIGNMENT_OPERATOR_P (decl)
&& (operator_code == PLUS_EXPR
|| operator_code == MINUS_EXPR
|| operator_code == TRUNC_DIV_EXPR
- || operator_code == MULT_EXPR)
+ || operator_code == MULT_EXPR
+ || operator_code == TRUNC_MOD_EXPR)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
warning ("`%D' should return by value", decl);
@@ -12663,7 +12765,6 @@ xref_tag (code_type_node, name, globalize)
enum tree_code code;
register tree ref, t;
struct binding_level *b = current_binding_level;
- int got_type = 0;
tree attributes = NULL_TREE;
tree context = NULL_TREE;
@@ -12700,7 +12801,6 @@ xref_tag (code_type_node, name, globalize)
{
t = name;
name = TYPE_IDENTIFIER (t);
- got_type = 1;
}
else
t = IDENTIFIER_TYPE_VALUE (name);
@@ -12745,18 +12845,20 @@ xref_tag (code_type_node, name, globalize)
{
if (t)
{
+ ref = follow_tag_typedef (t);
+
/* [dcl.type.elab] If the identifier resolves to a
typedef-name or a template type-parameter, the
elaborated-type-specifier is ill-formed. */
- if (t != TYPE_MAIN_VARIANT (t)
- || (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t)))
- pedwarn ("using typedef-name `%D' after `%s'",
- TYPE_NAME (t), tag_name (tag_code));
+ if (!ref)
+ {
+ pedwarn ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (t), tag_name (tag_code));
+ ref = t;
+ }
else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
error ("using template type parameter `%T' after `%s'",
- t, tag_name (tag_code));
-
- ref = t;
+ t, tag_name (tag_code));
}
else
ref = lookup_tag (code, name, b, 0);
@@ -12877,19 +12979,6 @@ xref_tag (code_type_node, name, globalize)
redeclare_class_template (ref, current_template_parms);
}
- /* Until the type is defined, tentatively accept whatever
- structure tag the user hands us. */
- if (!COMPLETE_TYPE_P (ref)
- && ref != current_class_type
- /* Have to check this, in case we have contradictory tag info. */
- && IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
- {
- if (tag_code == class_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 1;
- else if (tag_code == record_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 0;
- }
-
TYPE_ATTRIBUTES (ref) = attributes;
return ref;
@@ -12923,7 +13012,8 @@ xref_tag_from_type (old, id, globalize)
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
- tree name, ref;
+ tree name ATTRIBUTE_UNUSED;
+ tree ref;
tree binfo;
{
/* In the declaration `A : X, Y, ... Z' we mark all the types
@@ -12994,8 +13084,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
continue;
}
- GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
-
/* This code replaces similar code in layout_basetypes.
We put the complete_type first for implicit `typename'. */
if (!COMPLETE_TYPE_P (basetype)
@@ -13133,10 +13221,6 @@ start_enum (name)
pushtag (name, enumtype, 0);
}
- if (current_class_type)
- TREE_ADDRESSABLE (b->tags) = 1;
-
- GNU_xref_decl (current_function_decl, enumtype);
return enumtype;
}
@@ -13382,10 +13466,7 @@ build_enumerator (name, value, enumtype)
things like `S::i' later.) */
finish_member_declaration (decl);
else
- {
- pushdecl (decl);
- GNU_xref_decl (current_function_decl, decl);
- }
+ pushdecl (decl);
/* Add this enumeration constant to the list for this type. */
TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype));
@@ -13509,7 +13590,14 @@ start_function (declspecs, declarator, attrs, flags)
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
- if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
+ if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
+ return 0;
+
+ cplus_decl_attributes (&decl1, attrs, 0);
+
+ /* If #pragma weak was used, mark the decl weak now. */
+ if (current_binding_level == global_binding_level)
+ maybe_apply_pragma_weak (decl1);
fntype = TREE_TYPE (decl1);
@@ -13623,19 +13711,16 @@ start_function (declspecs, declarator, attrs, flags)
/* Build the return declaration for the function. */
restype = TREE_TYPE (fntype);
- if (!processing_template_decl)
+ /* Promote the value to int before returning it. */
+ if (c_promoting_integer_type_p (restype))
+ restype = type_promotes_to (restype);
+ if (DECL_RESULT (decl1) == NULL_TREE)
{
- if (!DECL_RESULT (decl1))
- {
- DECL_RESULT (decl1)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- c_apply_type_quals_to_decl (cp_type_quals (restype),
- DECL_RESULT (decl1));
- }
+ DECL_RESULT (decl1)
+ = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+ c_apply_type_quals_to_decl (cp_type_quals (restype),
+ DECL_RESULT (decl1));
}
- else
- /* Just use `void'. Nobody will ever look at this anyhow. */
- DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, void_type_node);
/* Initialize RTL machinery. We cannot do this until
CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
@@ -13796,20 +13881,6 @@ start_function (declspecs, declarator, attrs, flags)
pushlevel (0);
current_binding_level->parm_flag = 1;
- cplus_decl_attributes (&decl1, attrs, 0);
-
- /* Promote the value to int before returning it. */
- if (c_promoting_integer_type_p (restype))
- restype = type_promotes_to (restype);
-
- if (DECL_RESULT (decl1) == NULL_TREE)
- {
- DECL_RESULT (decl1)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype);
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype);
- }
-
++function_depth;
if (DECL_DESTRUCTOR_P (decl1))
@@ -14015,10 +14086,6 @@ begin_destructor_body ()
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
-
- /* And insert cleanups for our bases and members so that they
- will be properly destroyed if we throw. */
- push_base_cleanups ();
}
/* At the end of every destructor we generate code to delete the object if
@@ -14029,6 +14096,9 @@ finish_destructor_body ()
{
tree exprstmt;
+ /* And perform cleanups for our bases and members. */
+ perform_base_cleanups ();
+
/* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
{
@@ -14256,6 +14326,19 @@ finish_function (flags)
if (!processing_template_decl && calls_setjmp_p (fndecl))
DECL_UNINLINABLE (fndecl) = 1;
+ /* Complain if there's just no return statement. */
+ if (warn_return_type
+ && !processing_template_decl
+ && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
+ && !current_function_returns_value && !current_function_returns_null
+ /* Don't complain if we abort or throw. */
+ && !current_function_returns_abnormally
+ && !DECL_NAME (DECL_RESULT (fndecl))
+ /* Normally, with -Wreturn-type, flow will complain. Unless we're an
+ inline function, as we might never be compiled separately. */
+ && DECL_INLINE (fndecl))
+ warning ("no return statement in function returning non-void");
+
/* Clear out memory we no longer need. */
free_after_parsing (cfun);
/* Since we never call rest_of_compilation, we never clear
@@ -14416,11 +14499,6 @@ finish_method (decl)
DECL_CONTEXT (link) = NULL_TREE;
}
- GNU_xref_end_scope ((size_t) current_binding_level,
- (size_t) current_binding_level->level_chain,
- current_binding_level->parm_flag,
- current_binding_level->keep);
-
poplevel (0, 0, 0);
DECL_INITIAL (fndecl) = old_initial;
@@ -14438,72 +14516,58 @@ finish_method (decl)
return decl;
}
-/* Called when a new struct TYPE is defined.
- If this structure or union completes the type of any previous
- variable declaration, lay it out and output its rtl. */
+
+/* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that
+ we can lay it out later, when and if its type becomes complete. */
void
-hack_incomplete_structures (type)
- tree type;
+maybe_register_incomplete_var (var)
+ tree var;
{
- tree *list;
- struct binding_level *level;
+ my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
- if (!type) /* Don't do this for class templates. */
- return;
-
- if (namespace_bindings_p ())
+ /* Keep track of variables with incomplete types. */
+ if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
+ && DECL_EXTERNAL (var))
{
- level = 0;
- list = &namespace_scope_incomplete;
- }
- else
- {
- level = innermost_nonclass_level ();
- list = &level->incomplete;
+ tree inner_type = TREE_TYPE (var);
+
+ while (TREE_CODE (inner_type) == ARRAY_TYPE)
+ inner_type = TREE_TYPE (inner_type);
+ inner_type = TYPE_MAIN_VARIANT (inner_type);
+
+ if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
+ /* RTTI TD entries are created while defining the type_info. */
+ || (TYPE_LANG_SPECIFIC (inner_type)
+ && TYPE_BEING_DEFINED (inner_type)))
+ incomplete_vars = tree_cons (inner_type, var, incomplete_vars);
}
+}
- while (1)
- {
- while (*list)
- {
- tree decl = TREE_VALUE (*list);
- if ((decl && TREE_TYPE (decl) == type)
- || (TREE_TYPE (decl)
- && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (decl)) == type))
- {
- int toplevel = toplevel_bindings_p ();
- if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (decl)) == type)
- layout_type (TREE_TYPE (decl));
- layout_decl (decl, 0);
- rest_of_decl_compilation (decl, NULL, toplevel, 0);
- if (! toplevel)
- {
- tree cleanup;
- expand_decl (decl);
- cleanup = maybe_build_cleanup (decl);
- expand_decl_init (decl);
- if (! expand_decl_cleanup (decl, cleanup))
- error ("parser lost in parsing declaration of `%D'",
- decl);
- }
- *list = TREE_CHAIN (*list);
- }
- else
- list = &TREE_CHAIN (*list);
- }
+/* Called when a class type (given by TYPE) is defined. If there are
+ any existing VAR_DECLs whose type hsa been completed by this
+ declaration, update them now. */
+
+void
+complete_vars (type)
+ tree type;
+{
+ tree *list = &incomplete_vars;
- /* Keep looking through artificial binding levels generated
- for local variables. */
- if (level && level->keep == 2)
+ my_friendly_assert (CLASS_TYPE_P (type), 20020406);
+ while (*list)
+ {
+ if (same_type_p (type, TREE_PURPOSE (*list)))
{
- level = level->level_chain;
- list = &level->incomplete;
+ tree var = TREE_VALUE (*list);
+ /* Complete the type of the variable. The VAR_DECL itself
+ will be laid out in expand_expr. */
+ complete_type (TREE_TYPE (var));
+ /* Remove this entry from the list. */
+ *list = TREE_CHAIN (*list);
}
else
- break;
+ list = &TREE_CHAIN (*list);
}
}
@@ -14544,7 +14608,7 @@ maybe_build_cleanup (decl)
return rval;
}
- return 0;
+ return NULL_TREE;
}
/* When a stmt has been parsed, this function is called. */
OpenPOWER on IntegriCloud