aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c511
1 files changed, 296 insertions, 215 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 4d912cdf897..ebff32f9e02 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -46,15 +46,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
-
static tree grokparms PARAMS ((tree));
static const char *redeclaration_error_message PARAMS ((tree, tree));
@@ -81,11 +77,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,
@@ -395,10 +394,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
@@ -481,6 +476,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;
@@ -1954,7 +1955,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);
}
}
@@ -1992,8 +1992,6 @@ print_binding_level (lvl)
int i = 0, len;
fprintf (stderr, " blocks=");
fprintf (stderr, HOST_PTR_PRINTF, 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)
@@ -2394,7 +2392,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);
@@ -2500,6 +2497,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;
@@ -2541,6 +2539,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);
}
@@ -3142,6 +3141,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. */
@@ -3169,7 +3172,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))))
@@ -3190,6 +3196,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))
@@ -3204,9 +3213,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))
@@ -3416,6 +3422,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);
@@ -3514,16 +3532,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))
@@ -3587,15 +3605,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,
@@ -3614,7 +3640,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);
@@ -4230,22 +4257,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)
@@ -5289,6 +5302,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.
@@ -5340,18 +5394,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;
}
@@ -5361,14 +5420,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);
@@ -5506,7 +5563,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);
@@ -5700,6 +5762,17 @@ make_typename_type (context, name, complain)
{
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;
}
}
@@ -5785,14 +5858,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. */
@@ -5842,9 +5907,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;
@@ -6434,12 +6511,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;
@@ -6637,6 +6708,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
@@ -6704,10 +6776,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.
@@ -6715,10 +6786,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;
@@ -6726,23 +6798,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;
/* The return builtins leave the current function. */
if (code == BUILT_IN_RETURN || code == BUILT_IN_EH_RETURN)
TREE_THIS_VOLATILE (decl) = 1;
- my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
-
- /* 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
@@ -6762,6 +6824,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. */
@@ -7259,6 +7354,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)
@@ -7391,7 +7490,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)). */
@@ -7869,8 +7968,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;
@@ -7878,6 +7978,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
@@ -8030,8 +8133,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);
}
@@ -8065,8 +8167,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)
{
@@ -8504,7 +8608,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);
}
@@ -11164,6 +11270,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);
@@ -11295,9 +11403,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)
@@ -11559,33 +11665,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++ */
@@ -12584,10 +12689,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);
@@ -12649,7 +12756,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;
@@ -12686,7 +12792,6 @@ xref_tag (code_type_node, name, globalize)
{
t = name;
name = TYPE_IDENTIFIER (t);
- got_type = 1;
}
else
t = IDENTIFIER_TYPE_VALUE (name);
@@ -12731,18 +12836,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);
@@ -12863,19 +12970,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;
@@ -13118,9 +13212,6 @@ start_enum (name)
pushtag (name, enumtype, 0);
}
- if (current_class_type)
- TREE_ADDRESSABLE (b->tags) = 1;
-
return enumtype;
}
@@ -13495,6 +13586,10 @@ start_function (declspecs, declarator, attrs, flags)
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);
restype = TREE_TYPE (fntype);
@@ -13982,10 +14077,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
@@ -13996,6 +14087,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))
{
@@ -14224,15 +14318,16 @@ finish_function (flags)
DECL_UNINLINABLE (fndecl) = 1;
/* Complain if there's just no return statement. */
- if (!processing_template_decl
+ if (warn_return_type
+ && !processing_template_decl
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
&& !current_function_returns_value && !current_function_returns_null
- && !DECL_NAME (DECL_RESULT (fndecl))
/* Don't complain if we abort or throw. */
&& !current_function_returns_abnormally
- /* If we have -Wreturn-type, let flow complain. Unless we're an
+ && !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. */
- && (!warn_return_type || DECL_INLINE (fndecl)))
+ && DECL_INLINE (fndecl))
warning ("no return statement in function returning non-void");
/* Clear out memory we no longer need. */
@@ -14412,72 +14507,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 ())
- {
- level = 0;
- list = &namespace_scope_incomplete;
- }
- else
+ /* Keep track of variables with incomplete types. */
+ if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
+ && DECL_EXTERNAL (var))
{
- 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. */
- /* Keep looking through artificial binding levels generated
- for local variables. */
- if (level && level->keep == 2)
+void
+complete_vars (type)
+ tree type;
+{
+ tree *list = &incomplete_vars;
+
+ 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);
}
}
@@ -14518,7 +14599,7 @@ maybe_build_cleanup (decl)
return rval;
}
- return 0;
+ return NULL_TREE;
}
/* When a stmt has been parsed, this function is called. */