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.c2873
1 files changed, 1789 insertions, 1084 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9ecb9846cf8..d8fdfe3b537 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1,5 +1,5 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
+#include "../hash.h"
#include "ggc.h"
#define obstack_chunk_alloc xmalloc
@@ -135,8 +136,7 @@ static struct stack_level *decl_stack;
static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
-static char *redeclaration_error_message PROTO((tree, tree));
-static tree push_overloaded_decl PROTO((tree, int));
+static const char *redeclaration_error_message PROTO((tree, tree));
static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *));
@@ -146,10 +146,8 @@ static void pop_binding_level PROTO((void));
static void suspend_binding_level PROTO((void));
static void resume_binding_level PROTO((struct binding_level *));
static struct binding_level *make_binding_level PROTO((void));
-static int namespace_bindings_p PROTO((void));
-static void mark_binding_level PROTO((void *));
static void declare_namespace_level PROTO((void));
-static void signal_catch PROTO((int));
+static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
static void storedecls PROTO((tree));
static void storetags PROTO((tree));
static void require_complete_types_for_parms PROTO((tree));
@@ -171,15 +169,27 @@ static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int));
static void set_identifier_type_value_with_scope
PROTO((tree, tree, struct binding_level *));
-static void set_identifier_local_value_with_scope
- PROTO((tree, tree, struct binding_level *));
-static void record_builtin_type PROTO((enum rid, char *, tree));
-static void record_unknown_type PROTO((tree, char *));
-static int member_function_or_else PROTO((tree, tree, char *));
-static void bad_specifiers PROTO((tree, char *, int, int, int, int,
+static void record_builtin_type PROTO((enum rid, const char *, tree));
+static void record_unknown_type PROTO((tree, const char *));
+static int member_function_or_else PROTO((tree, tree, const char *));
+static void bad_specifiers PROTO((tree, const char *, int, int, int, int,
int));
static void lang_print_error_function PROTO((char *));
static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
+static void check_for_uninitialized_const_var PROTO((tree));
+static unsigned long typename_hash PROTO((hash_table_key));
+static boolean typename_compare PROTO((hash_table_key, hash_table_key));
+static void push_binding PROTO((tree, tree, struct binding_level*));
+static void add_binding PROTO((tree, tree));
+static void pop_binding PROTO((tree, tree));
+static tree local_variable_p PROTO((tree));
+static tree find_binding PROTO((tree, tree));
+static tree select_decl PROTO((tree, int));
+static tree unqualified_namespace_lookup PROTO((tree, int));
+static int lookup_flags PROTO((int, int));
+static tree qualify_lookup PROTO((tree, int));
+static tree record_builtin_java_type PROTO((const char *, int));
+static const char *tag_name PROTO((enum tag_types code));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -519,11 +529,6 @@ int current_function_returns_null;
tree current_function_return_value;
-/* Set to nonzero by `grokdeclarator' for a function
- whose return type is defaulted, if warnings for this are desired. */
-
-static int warn_about_return_type;
-
/* Nonzero means give `double' the same size as `float'. */
extern int flag_short_double;
@@ -617,7 +622,10 @@ push_decl_level (stack, obstack)
to catch class-local declarations. It is otherwise nonexistent.
Also there may be binding levels that catch cleanups that must be
- run when exceptions occur. */
+ run when exceptions occur. Thus, to see whether a name is bound in
+ the current scope, it is not enough to look in the
+ CURRENT_BINDING_LEVEL. You should use lookup_name_current_level
+ instead. */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
@@ -626,7 +634,8 @@ struct binding_level
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order
- supplied. */
+ supplied. There may be OVERLOADs on this list, too, but they
+ are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names;
/* A list of structure, union and enum definitions, for looking up
@@ -646,16 +655,17 @@ struct binding_level
VALUE the common ancestor with this binding_level's namespace. */
tree using_directives;
- /* For each level, a list of shadowed outer-level local definitions
- to be restored when this level is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* Same, for IDENTIFIER_CLASS_VALUE. */
+ /* If this binding level is the binding level for a class, then
+ class_shadowed is a TREE_LIST. The TREE_PURPOSE of each node
+ is the name of an entity bound in the class; the TREE_VALUE is
+ the IDENTIFIER_CLASS_VALUE before we entered the class. Thus,
+ when leaving class scope, we can restore the
+ IDENTIFIER_CLASS_VALUE by walking this list. The TREE_TYPE is
+ the DECL bound by this name in the class. */
tree class_shadowed;
- /* Same, for IDENTIFIER_TYPE_VALUE. */
+ /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
+ is used for all binding levels. */
tree type_shadowed;
/* For each level (except not the global one),
@@ -676,7 +686,8 @@ struct binding_level
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ANSI-conforming code, but might
- be referenced in ARM-era code. */
+ be referenced in ARM-era code. These are stored in a
+ TREE_LIST; the TREE_VALUE is the actual declaration. */
tree dead_vars_from_for;
/* 1 for the level that holds the parameters of a function.
@@ -929,7 +940,7 @@ toplevel_bindings_p ()
/* Nonzero if this is a namespace scope. */
-static int
+int
namespace_bindings_p ()
{
return current_binding_level->namespace_p;
@@ -1045,6 +1056,184 @@ pushlevel_temporary (tag_transparent)
expand_start_bindings (0);
}
+/* For a binding between a name and an entity at a block scope,
+ this is the `struct binding_level' for the block. */
+#define BINDING_LEVEL(NODE) \
+ (((struct tree_binding*)NODE)->scope.level)
+
+/* These are currently unused, but permanent, CPLUS_BINDING nodes.
+ They are kept here because they are allocated from the permanent
+ obstack and cannot be easily freed. */
+static tree free_binding_nodes;
+
+/* Make DECL the innermost binding for ID. The LEVEL is the binding
+ level at which this declaration is being bound. */
+
+static void
+push_binding (id, decl, level)
+ tree id;
+ tree decl;
+ struct binding_level* level;
+{
+ tree binding;
+
+ if (!free_binding_nodes)
+ {
+ /* There are no free nodes, so we must build one here. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ binding = make_node (CPLUS_BINDING);
+ pop_obstacks ();
+ }
+ else
+ {
+ /* There are nodes on the free list. Grab the first one. */
+ binding = free_binding_nodes;
+
+ /* And update the free list. */
+ free_binding_nodes = TREE_CHAIN (free_binding_nodes);
+ }
+
+ /* Now, fill in the binding information. */
+ BINDING_VALUE (binding) = decl;
+ BINDING_TYPE (binding) = NULL_TREE;
+ BINDING_LEVEL (binding) = level;
+ LOCAL_BINDING_P (binding) = (level != class_binding_level);
+
+ /* And put it on the front of the ilst of bindings for ID. */
+ TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
+ IDENTIFIER_BINDING (id) = binding;
+}
+
+/* ID is already bound in the current scope. But, DECL is an
+ additional binding for ID in the same scope. This is the `struct
+ stat' hack whereby a non-typedef class-name or enum-name can be
+ bound at the same level as some other kind of entity. It's the
+ responsibility of the caller to check that inserting this name is
+ legal here. */
+static void
+add_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree binding = IDENTIFIER_BINDING (id);
+
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+ /* The new name is the type name. */
+ BINDING_TYPE (binding) = decl;
+ else
+ {
+ /* The old name must be the type name. It was placed in
+ IDENTIFIER_VALUE because it was thought, at the point it
+ was declared, to be the only entity with such a name. */
+ my_friendly_assert (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding)),
+ 0);
+
+ /* Move the type name into the type slot; it is now hidden by
+ the new binding. */
+ BINDING_TYPE (binding) = BINDING_VALUE (binding);
+ BINDING_VALUE (binding) = decl;
+ }
+}
+
+/* Bind DECL to ID in the current_binding_level.
+ If PUSH_USING is set in FLAGS, we know that DECL doesn't really belong
+ to this binding level, that it got here through a using-declaration. */
+
+void
+push_local_binding (id, decl, flags)
+ tree id;
+ tree decl;
+ int flags;
+{
+ tree d = decl;
+
+ if (lookup_name_current_level (id))
+ /* Supplement the existing binding. */
+ add_binding (id, d);
+ else
+ /* Create a new binding. */
+ push_binding (id, d, current_binding_level);
+
+ if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING))
+ /* We must put the OVERLOAD into a TREE_LIST since the
+ TREE_CHAIN of an OVERLOAD is already used. Similarly for
+ decls that got here through a using-declaration. */
+ decl = build_tree_list (NULL_TREE, decl);
+
+ /* And put DECL on the list of things declared by the current
+ binding level. */
+ TREE_CHAIN (decl) = current_binding_level->names;
+ current_binding_level->names = decl;
+}
+
+/* Bind DECL to ID in the class_binding_level. */
+
+void
+push_class_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ if (IDENTIFIER_BINDING (id)
+ && BINDING_LEVEL (IDENTIFIER_BINDING (id)) == class_binding_level)
+ /* Supplement the existing binding. */
+ add_binding (id, decl);
+ else
+ /* Create a new binding. */
+ push_binding (id, decl, class_binding_level);
+
+ /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
+ class-level declaration. Note that we do not use DECL here
+ because of the possibility of the `struct stat' hack; if DECL is
+ a class-name or enum-name we might prefer a field-name, or some
+ such. */
+ IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
+}
+
+/* Remove the binding for DECL which should be the innermost binding
+ for ID. */
+
+static void
+pop_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree binding;
+
+ if (id == NULL_TREE)
+ /* It's easiest to write the loops that call this function without
+ checking whether or not the entities involved have names. We
+ get here for such an entity. */
+ return;
+
+ /* Get the innermost binding for ID. */
+ binding = IDENTIFIER_BINDING (id);
+
+ /* The name should be bound. */
+ my_friendly_assert (binding != NULL_TREE, 0);
+
+ /* The DECL will be either the ordinary binding or the type
+ binding for this identifier. Remove that binding. */
+ if (BINDING_VALUE (binding) == decl)
+ BINDING_VALUE (binding) = NULL_TREE;
+ else if (BINDING_TYPE (binding) == decl)
+ BINDING_TYPE (binding) = NULL_TREE;
+ else
+ my_friendly_abort (0);
+
+ if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
+ {
+ /* We're completely done with the innermost binding for this
+ identifier. Unhook it from the list of bindings. */
+ IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+ /* And place it on the free list. */
+ TREE_CHAIN (binding) = free_binding_nodes;
+ free_binding_nodes = binding;
+ }
+}
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
@@ -1053,12 +1242,6 @@ pushlevel_temporary (tag_transparent)
and create a "block" (a BLOCK node) for the level
to record its declarations and subblocks for symbol table output.
- If KEEP == 2, this level's subblocks go to the front,
- not the back of the current binding level. This happens,
- for instance, when code for constructors and destructors
- need to generate code at the end of a function which must
- be moved up to the front of the function.
-
If FUNCTIONBODY is nonzero, this level is the body of a function,
so create a block as if KEEP were set and also clear out all
label names.
@@ -1084,6 +1267,18 @@ poplevel (keep, reverse, functionbody)
tree block = NULL_TREE;
tree decl;
int block_previously_created;
+ int leaving_for_scope;
+
+ if (current_binding_level->parm_flag == 2
+ || current_binding_level->class_shadowed)
+ /* We should not be using poplevel to pop a class binding level.
+ Use poplevel_class instead. */
+ my_friendly_abort (0);
+
+ /* We used to use KEEP == 2 to indicate that the new block should go
+ at the beginning of the list of blocks at this binding level,
+ rather than the end. This hack is no longer used. */
+ my_friendly_assert (keep == 0 || keep == 1, 0);
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
@@ -1143,9 +1338,8 @@ poplevel (keep, reverse, functionbody)
if (decls || tags || subblocks)
{
if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
- {
- warning ("internal compiler error: debugging info corrupted");
- }
+ warning ("internal compiler error: debugging info corrupted");
+
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
@@ -1164,7 +1358,8 @@ poplevel (keep, reverse, functionbody)
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = subblocks;
- /* Otherwise, for a new block, install a new BLOCK_END_NOTE value. */
+ /* Otherwise, for a new block, install a new BLOCK_END_NOTE
+ value. */
remember_end_note (block);
}
}
@@ -1175,92 +1370,123 @@ poplevel (keep, reverse, functionbody)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
- /* Clear out the meanings of the local variables of this level. */
+ /* We still support the old for-scope rules, whereby the variables
+ in a for-init statement were in scope after the for-statement
+ ended. We only use the new rules in flag_new_for_scope is
+ nonzero. */
+ leaving_for_scope
+ = current_binding_level->is_for_scope && flag_new_for_scope == 1;
- if (current_binding_level->is_for_scope && flag_new_for_scope == 1)
+ /* Remove declarations for all the DECLs in this level. */
+ for (link = decls; link; link = TREE_CHAIN (link))
{
- struct binding_level *outer = current_binding_level->level_chain;
- for (link = decls; link; link = TREE_CHAIN (link))
+ if (leaving_for_scope && TREE_CODE (link) == VAR_DECL)
{
- if (TREE_CODE (link) == VAR_DECL)
- DECL_DEAD_FOR_LOCAL (link) = 1;
- else
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
- }
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ tree ns_binding;
- /* Save declarations made in a 'for' statement so we can support pre-ANSI
- 'for' scoping semantics. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- {
- tree id = TREE_PURPOSE (link);
- tree decl = IDENTIFIER_LOCAL_VALUE (id);
+ if (!outer_binding)
+ ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
+ else
+ ns_binding = NULL_TREE;
- if (decl && DECL_DEAD_FOR_LOCAL (decl))
+ if (outer_binding
+ && (BINDING_LEVEL (outer_binding)
+ == current_binding_level->level_chain))
+ /* We have something like:
+
+ int i;
+ for (int i; ;);
+
+ and we are leaving the `for' scope. There's no reason to
+ keep the binding of the inner `i' in this case. */
+ pop_binding (DECL_NAME (link), link);
+ else if ((outer_binding
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == TYPE_DECL))
+ || (ns_binding
+ && TREE_CODE (ns_binding) == TYPE_DECL))
+ /* Here, we have something like:
+
+ typedef int I;
+
+ void f () {
+ for (int I; ;);
+ }
+
+ We must pop the for-scope binding so we know what's a
+ type and what isn't. */
+ pop_binding (DECL_NAME (link), link);
+ else
{
- /* In this case keep the dead for-decl visible,
- but remember what (if anything) it shadowed. */
- DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link);
- TREE_CHAIN (decl) = outer->dead_vars_from_for;
- outer->dead_vars_from_for = decl;
+ /* Mark this VAR_DECL as dead so that we can tell we left it
+ there only for backward compatibility. */
+ DECL_DEAD_FOR_LOCAL (link) = 1;
+
+ /* Keep track of what should of have happenned when we
+ popped the binding. */
+ if (outer_binding && BINDING_VALUE (outer_binding))
+ DECL_SHADOWED_FOR_VAR (link)
+ = BINDING_VALUE (outer_binding);
+
+ /* Add it to the list of dead variables in the next
+ outermost binding to that we can remove these when we
+ leave that binding. */
+ current_binding_level->level_chain->dead_vars_from_for
+ = tree_cons (NULL_TREE, link,
+ current_binding_level->level_chain->
+ dead_vars_from_for);
+
+ /* Although we don't pop the CPLUS_BINDING, we do clear
+ its BINDING_LEVEL since the level is going away now. */
+ BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
+ = 0;
}
- else
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link);
}
- }
- else /* Not special for scope. */
- {
- for (link = decls; link; link = TREE_CHAIN (link))
+ else
{
- if (DECL_NAME (link) != NULL_TREE)
- {
- /* If the ident. was used or addressed via a local extern decl,
- don't forget that fact. */
- if (DECL_EXTERNAL (link))
- {
- if (TREE_USED (link))
- TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1;
- if (TREE_ADDRESSABLE (link))
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
- }
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
- }
+ /* Remove the binding. */
+ decl = link;
+ if (TREE_CODE (decl) == TREE_LIST)
+ decl = TREE_VALUE (decl);
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ pop_binding (DECL_NAME (decl), decl);
+ else if (TREE_CODE (decl) == OVERLOAD)
+ pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
+ else
+ my_friendly_abort (0);
}
+ }
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
- /* We first restore the regular decls and *then* the dead_vars_from_for
- to handle this case:
-
- int i; // i#1
- {
- for (int i; ; ) { ...} // i#2
- int i; // i#3
- } // we are here
+ /* Remove declarations for any `for' variables from inner scopes
+ that we kept around. */
+ for (link = current_binding_level->dead_vars_from_for;
+ link; link = TREE_CHAIN (link))
+ pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
- In this case, we want remove the binding for i#3, restoring
- that of i#2. Then we want to remove the binding for i#2,
- and restore that of i#1. */
+ /* Restore the IDENTIFIER_TYPE_VALUEs. */
+ for (link = current_binding_level->type_shadowed;
+ link; link = TREE_CHAIN (link))
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
+
+ /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
+ list if a `using' declaration put them there. The debugging
+ back-ends won't understand OVERLOAD, so we remove them here.
+ Because the BLOCK_VARS are (temporarily) shared with
+ CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
+ popped all the bindings. */
+ if (block)
+ {
+ tree* d;
- link = current_binding_level->dead_vars_from_for;
- for (; link != NULL_TREE; link = TREE_CHAIN (link))
+ for (d = &BLOCK_VARS (block); *d; )
{
- tree id = DECL_NAME (link);
- if (IDENTIFIER_LOCAL_VALUE (id) == link)
- IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link);
+ if (TREE_CODE (*d) == TREE_LIST)
+ *d = TREE_CHAIN (*d);
+ else
+ d = &TREE_CHAIN (*d);
}
-
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
}
/* If the level being exited is the top level of a function,
@@ -1335,14 +1561,8 @@ poplevel (keep, reverse, functionbody)
must be carried forward so they will later become subblocks
of something else. */
else if (subblocks)
- {
- if (keep == 2)
- current_binding_level->blocks
- = chainon (subblocks, current_binding_level->blocks);
- else
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, subblocks);
- }
+ current_binding_level->blocks
+ = chainon (current_binding_level->blocks, subblocks);
/* Take care of compiler's internal binding structures. */
if (tmp == 2)
@@ -1429,9 +1649,7 @@ pushlevel_class ()
free_binding_level = free_binding_level->level_chain;
}
else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
@@ -1466,8 +1684,6 @@ poplevel_class (force)
my_friendly_assert (level != 0, 354);
decl_stack = pop_stack_level (decl_stack);
- for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
/* If we're leaving a toplevel class, don't bother to do the setting
of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot
shouldn't even be used when current_class_type isn't set, and second,
@@ -1490,6 +1706,12 @@ poplevel_class (force)
shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
+ /* Remove the bindings for all of the class-level declarations. */
+ for (shadowed = level->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
+
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
class_binding_level->parm_flag,
@@ -1620,15 +1842,6 @@ print_binding_level (lvl)
if (i)
fprintf (stderr, "\n");
}
- if (lvl->shadowed)
- {
- fprintf (stderr, " shadowed:");
- for (t = lvl->shadowed; t; t = TREE_CHAIN (t))
- {
- fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- fprintf (stderr, "\n");
- }
if (lvl->class_shadowed)
{
fprintf (stderr, " class-shadowed:");
@@ -1917,6 +2130,10 @@ cat_namespace_levels()
/* The nested namespaces appear in the names list of their ancestors. */
for (current = last; current; current = TREE_CHAIN (current))
{
+ /* Catch simple infinite loops. */
+ if (TREE_CHAIN (current) == current)
+ my_friendly_abort (990126);
+
if (TREE_CODE (current) != NAMESPACE_DECL
|| DECL_NAMESPACE_ALIAS (current))
continue;
@@ -2001,9 +2218,11 @@ store_bindings (names, old_bindings)
else
id = DECL_NAME (t);
- if (!id
- || (!IDENTIFIER_LOCAL_VALUE (id)
- && !IDENTIFIER_CLASS_VALUE (id)))
+ if (!id
+ /* Note that we may have an IDENTIFIER_CLASS_VALUE even when
+ we have no IDENTIFIER_BINDING if we have left the class
+ scope, but cached the class-level declarations. */
+ || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
@@ -2017,9 +2236,9 @@ store_bindings (names, old_bindings)
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id;
TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
+ TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
+ IDENTIFIER_BINDING (id) = NULL_TREE;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
TREE_CHAIN (binding) = old_bindings;
@@ -2143,16 +2362,16 @@ pop_from_top_level ()
current_saved_scope = s->prev;
for (t = s->old_bindings; t; )
{
+ tree save = t;
tree id = TREE_VEC_ELT (t, 0);
if (id)
{
SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
+ IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
}
t = TREE_CHAIN (t);
}
- s->old_bindings = NULL_TREE;
current_namespace = s->old_namespace;
current_class_name = s->class_name;
current_class_type = s->class_type;
@@ -2230,26 +2449,6 @@ set_identifier_type_value (id, type)
set_identifier_type_value_with_scope (id, type, inner_binding_level);
}
-static void
-set_identifier_local_value_with_scope (id, val, b)
- tree id, val;
- struct binding_level *b;
-{
- tree oldlocal;
- my_friendly_assert (! b->namespace_p, 980716);
-
- oldlocal = IDENTIFIER_LOCAL_VALUE (id);
- b->shadowed = tree_cons (id, oldlocal, b->shadowed);
- IDENTIFIER_LOCAL_VALUE (id) = val;
-}
-
-void
-set_identifier_local_value (id, val)
- tree id, val;
-{
- set_identifier_local_value_with_scope (id, val, current_binding_level);
-}
-
/* Return the type associated with id. */
tree
@@ -2301,7 +2500,7 @@ pop_everything ()
Returns the TYPE_DECL for TYPE, which may have been altered by this
processing. */
-static tree
+static tree
maybe_process_template_type_declaration (type, globalize, b)
tree type;
int globalize;
@@ -2568,8 +2767,15 @@ decls_match (newdecl, olddecl)
{
int types_match;
- if (TREE_CODE (newdecl) == FUNCTION_DECL
- && TREE_CODE (olddecl) == FUNCTION_DECL)
+ if (newdecl == olddecl)
+ return 1;
+
+ if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
+ /* If the two DECLs are not even the same kind of thing, we're not
+ interested in their types. */
+ return 0;
+
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
@@ -2604,7 +2810,7 @@ decls_match (newdecl, olddecl)
return 0;
}
- if (comptypes (TREE_TYPE (f1), TREE_TYPE (f2), 1))
+ if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
&& p2 == NULL_TREE)
@@ -2620,13 +2826,12 @@ decls_match (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
else
- types_match = compparms (p1, p2, 3);
+ types_match = compparms (p1, p2);
}
else
types_match = 0;
}
- else if (TREE_CODE (newdecl) == TEMPLATE_DECL
- && TREE_CODE (olddecl) == TEMPLATE_DECL)
+ else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
@@ -2648,7 +2853,8 @@ decls_match (newdecl, olddecl)
types_match = 0;
else
types_match = comptypes (TREE_TYPE (newdecl),
- TREE_TYPE (olddecl), 1);
+ TREE_TYPE (olddecl),
+ COMPARE_REDECLARATION);
}
return types_match;
@@ -2670,9 +2876,9 @@ warn_extern_redeclared_static (newdecl, olddecl)
{
tree name;
- static char *explicit_extern_static_warning
+ static const char *explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
- static char *implicit_extern_static_warning
+ static const char *implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
if (TREE_CODE (newdecl) == TYPE_DECL)
@@ -2808,6 +3014,11 @@ duplicate_decls (newdecl, olddecl)
}
else if (!types_match)
{
+ if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl))
+ /* These are certainly not duplicate declarations; they're
+ from different scopes. */
+ return 0;
+
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
/* The name of a class template may not be declared to refer to
@@ -2823,7 +3034,7 @@ duplicate_decls (newdecl, olddecl)
else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
- TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))), 3)
+ TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
{
@@ -2842,7 +3053,7 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration `%#D' here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
- TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 3))
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@@ -2892,7 +3103,7 @@ duplicate_decls (newdecl, olddecl)
return 1;
else
{
- char *errmsg = redeclaration_error_message (newdecl, olddecl);
+ const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
cp_error (errmsg, newdecl);
@@ -3041,9 +3252,6 @@ duplicate_decls (newdecl, olddecl)
DECL_TEMPLATE_RESULT (olddecl)))
cp_error ("invalid redeclaration of %D", newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
- DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
- if (DECL_TEMPLATE_INFO (newdecl))
- DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
@@ -3095,7 +3303,7 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (newtype != canonical_type_variant (oldtype)
+ if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
@@ -3170,17 +3378,22 @@ duplicate_decls (newdecl, olddecl)
DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ DECL_TEMPLATE_INSTANTIATED (newdecl)
+ |= DECL_TEMPLATE_INSTANTIATED (olddecl);
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
- if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
- {
- DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
- DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
- }
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
+
+ /* Only functions have DECL_BEFRIENDING_CLASSES. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (newdecl))
+ DECL_BEFRIENDING_CLASSES (newdecl)
+ = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+ DECL_BEFRIENDING_CLASSES (olddecl));
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3244,6 +3457,8 @@ duplicate_decls (newdecl, olddecl)
regardless of declaration matches. */
DECL_RTL (newdecl) = DECL_RTL (olddecl);
}
+ else
+ DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl)))
@@ -3384,23 +3599,30 @@ pushdecl (x)
{
register tree t;
register tree name = DECL_ASSEMBLER_NAME (x);
- register struct binding_level *b = current_binding_level;
-
- if (current_function_decl && x != current_function_decl
- /* A local declaration for a function doesn't constitute nesting. */
- && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
- /* Don't change DECL_CONTEXT of virtual methods. */
- && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
- && ! DECL_CONTEXT (x))
- DECL_CONTEXT (x) = current_function_decl;
- if (!DECL_CONTEXT (x))
- DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
+ int need_new_binding = 1;
+
+ if (DECL_TEMPLATE_PARM_P (x))
+ /* Template parameters have no context; they are not X::T even
+ when declared within a class or namespace. */
+ ;
+ else
+ {
+ if (current_function_decl && x != current_function_decl
+ /* A local declaration for a function doesn't constitute
+ nesting. */
+ && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
+ /* Don't change DECL_CONTEXT of virtual methods. */
+ && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
+ && !DECL_CONTEXT (x))
+ DECL_CONTEXT (x) = current_function_decl;
+ if (!DECL_CONTEXT (x))
+ DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
+ }
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
- || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM
- || TREE_CODE (x) == TEMPLATE_TEMPLATE_PARM)
+ || TREE_CODE (x) == NAMESPACE_DECL)
name = DECL_NAME (x);
if (name)
@@ -3514,14 +3736,30 @@ pushdecl (x)
}
}
+ check_template_shadow (x);
+
+ /* If this is a function conjured up by the backend, massage it
+ so it looks friendly. */
+ if (TREE_CODE (x) == FUNCTION_DECL
+ && ! DECL_LANG_SPECIFIC (x))
+ {
+ retrofit_lang_decl (x);
+ DECL_LANGUAGE (x) = lang_c;
+ }
+
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
- t = push_overloaded_decl (x, 1);
+ t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
+ if (!namespace_bindings_p ())
+ /* We do not need to create a binding for this name;
+ push_overloaded_decl will have already done so if
+ necessary. */
+ need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
- return push_overloaded_decl (x, 0);
+ return push_overloaded_decl (x, PUSH_GLOBAL);
/* If declaring a type as a typedef, copy the type (unless we're
at line 0), and install this TYPE_DECL as the new type's typedef
@@ -3555,7 +3793,9 @@ pushdecl (x)
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
- set_identifier_type_value_with_scope (DECL_NAME (x), type, b);
+ set_identifier_type_value_with_scope (DECL_NAME (x), type,
+ current_binding_level);
+
}
/* Multiple external decls of the same identifier ought to match.
@@ -3578,7 +3818,7 @@ pushdecl (x)
if (decl
/* If different sort of thing, we already gave an error. */
&& TREE_CODE (decl) == TREE_CODE (x)
- && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1))
+ && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
{
cp_pedwarn ("type mismatch with previous external decl", x);
cp_pedwarn_at ("previous external decl of `%#D'", decl);
@@ -3596,11 +3836,8 @@ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- /* Don't install an artificial TYPE_DECL if we already have
- another _DECL with that name. */
- if (TREE_CODE (x) != TYPE_DECL
- || t == NULL_TREE
- || ! DECL_ARTIFICIAL (x))
+ if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && t != NULL_TREE))
{
if (TREE_CODE (x) == FUNCTION_DECL)
my_friendly_assert
@@ -3635,25 +3872,29 @@ pushdecl (x)
else
{
/* Here to install a non-global value. */
- tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
+ tree oldlocal = IDENTIFIER_VALUE (name);
tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
- /* Don't install an artificial TYPE_DECL if we already have
- another _DECL with that name. */
- if (TREE_CODE (x) != TYPE_DECL
- || t == NULL_TREE
- || ! DECL_ARTIFICIAL (x))
- set_identifier_local_value_with_scope (name, x, b);
+ if (need_new_binding)
+ {
+ push_local_binding (name, x, 0);
+ /* Because push_local_binding will hook X on to the
+ current_binding_level's name list, we don't want to
+ do that again below. */
+ need_new_binding = 0;
+ }
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
- set_identifier_type_value_with_scope (name, TREE_TYPE (x), b);
+ set_identifier_type_value_with_scope (name, TREE_TYPE (x),
+ current_binding_level);
/* Clear out any TYPE_DECL shadowed by a namespace so that
we won't think this is a type. The C struct hack doesn't
go through namespaces. */
if (TREE_CODE (x) == NAMESPACE_DECL)
- set_identifier_type_value_with_scope (name, NULL_TREE, b);
+ set_identifier_type_value_with_scope (name, NULL_TREE,
+ current_binding_level);
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
@@ -3679,9 +3920,7 @@ pushdecl (x)
&& oldglobal == NULL_TREE
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
- {
- TREE_PUBLIC (name) = 1;
- }
+ TREE_PUBLIC (name) = 1;
if (DECL_FROM_INLINE (x))
/* Inline decls shadow nothing. */;
@@ -3702,7 +3941,8 @@ pushdecl (x)
if (b->parm_flag == 1)
cp_error ("declaration of `%#D' shadows a parameter", name);
}
- else if (warn_shadow && oldlocal != NULL_TREE && b->is_for_scope
+ else if (warn_shadow && oldlocal != NULL_TREE
+ && current_binding_level->is_for_scope
&& !DECL_DEAD_FOR_LOCAL (oldlocal))
{
warning ("variable `%s' shadows local",
@@ -3716,7 +3956,7 @@ pushdecl (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
- char *warnstring = NULL;
+ const char *warnstring = NULL;
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter";
@@ -3733,16 +3973,6 @@ pushdecl (x)
if (warnstring)
warning (warnstring, IDENTIFIER_POINTER (name));
}
- /* Check to see if decl redeclares a template parameter. */
- if (oldlocal && (current_class_type || current_function_decl)
- && current_template_parms)
- {
- if (decl_template_parm_p (oldlocal))
- {
- cp_error ("re-using name of template parameter `%T' in this scope", name);
- cp_error_at (" previously declared here `%#D'", oldlocal);
- }
- }
}
if (TREE_CODE (x) == FUNCTION_DECL)
@@ -3756,15 +3986,20 @@ pushdecl (x)
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (TREE_TYPE (x)))))
- b->incomplete = tree_cons (NULL_TREE, x, b->incomplete);
+ current_binding_level->incomplete
+ = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
}
- /* Put decls on list in reverse order.
- We will reverse them later if necessary. */
- TREE_CHAIN (x) = b->names;
- b->names = x;
- if (! (b != global_binding_level || TREE_PERMANENT (x)))
- my_friendly_abort (124);
+ if (need_new_binding)
+ {
+ /* Put decls on list in reverse order.
+ We will reverse them later if necessary. */
+ TREE_CHAIN (x) = current_binding_level->names;
+ current_binding_level->names = x;
+ if (! (current_binding_level != global_binding_level
+ || TREE_PERMANENT (x)))
+ my_friendly_abort (124);
+ }
return x;
}
@@ -3878,8 +4113,8 @@ pushdecl_class_level (x)
Types, enums, and static vars are checked here; other
members are checked in finish_struct. */
tree icv = IDENTIFIER_CLASS_VALUE (name);
- tree ilv = IDENTIFIER_LOCAL_VALUE (name);
+ /* This should match check_member_decl_is_same_in_complete_scope. */
if (icv && icv != x
&& flag_optional_diags
/* Don't complain about inherited names. */
@@ -3893,24 +4128,12 @@ pushdecl_class_level (x)
icv);
}
- /* Check to see if decl redeclares a template parameter. */
- if (ilv && ! decls_match (ilv, x)
- && (current_class_type || current_function_decl)
- && current_template_parms)
- {
- if (decl_template_parm_p (ilv))
- {
- cp_error ("re-using name of template parameter `%T' in this scope", name);
- cp_error_at (" previously declared here `%#D'", ilv);
- }
- }
+ check_template_shadow (x);
}
push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
- {
- set_identifier_type_value (name, TREE_TYPE (x));
- }
+ set_identifier_type_value (name, TREE_TYPE (x));
}
}
@@ -3950,16 +4173,21 @@ push_class_level_binding (name, x)
if (!class_binding_level)
return;
- if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
- && purpose_member (name, class_binding_level->class_shadowed))
- return;
-
+ /* If this declaration shadows a declaration from an enclosing
+ class, then we will need to restore IDENTIFIER_CLASS_VALUE when
+ we leave this class. Record the shadowed declaration here. */
maybe_push_cache_obstack ();
class_binding_level->class_shadowed
- = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
- class_binding_level->class_shadowed);
+ = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+ class_binding_level->class_shadowed);
+ TREE_TYPE (class_binding_level->class_shadowed)
+ = x;
pop_obstacks ();
- IDENTIFIER_CLASS_VALUE (name) = x;
+
+ /* Put the binding on the stack of bindings for the identifier, and
+ update IDENTIFIER_CLASS_VALUE. */
+ push_class_binding (name, x);
+
obstack_ptr_grow (&decl_obstack, x);
}
@@ -4014,31 +4242,38 @@ push_using_directive (used)
return ud;
}
-/* DECL is a FUNCTION_DECL which may have other definitions already in
- place. We get around this by making the value of the identifier point
- to a list of all the things that want to be referenced by that name. It
- is then up to the users of that name to decide what to do with that
- list.
+/* DECL is a FUNCTION_DECL for a non-member function, which may have
+ other definitions already in place. We get around this by making
+ the value of the identifier point to a list of all the things that
+ want to be referenced by that name. It is then up to the users of
+ that name to decide what to do with that list.
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way.
+ FLAGS is a bitwise-or of the following values:
+ PUSH_LOCAL: Bind DECL in the current scope, rather than at
+ namespace scope.
+ PUSH_USING: DECL is being pushed as the result of a using
+ declaration.
+
The value returned may be a previous declaration if we guessed wrong
about what language DECL should belong to (C or C++). Otherwise,
it's always DECL (and never something that's not a _DECL). */
-static tree
-push_overloaded_decl (decl, forgettable)
+tree
+push_overloaded_decl (decl, flags)
tree decl;
- int forgettable;
+ int flags;
{
- tree orig_name = DECL_NAME (decl);
+ tree name = DECL_NAME (decl);
tree old;
- int doing_global = (namespace_bindings_p () || ! forgettable);
+ tree new_binding;
+ int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
if (doing_global)
{
- old = namespace_binding (orig_name, DECL_CONTEXT (decl));
+ old = namespace_binding (name, DECL_CONTEXT (decl));
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
@@ -4049,16 +4284,7 @@ push_overloaded_decl (decl, forgettable)
}
}
else
- {
- old = IDENTIFIER_LOCAL_VALUE (orig_name);
-
- if (! purpose_member (orig_name, current_binding_level->shadowed))
- {
- current_binding_level->shadowed
- = tree_cons (orig_name, old, current_binding_level->shadowed);
- old = NULL_TREE;
- }
- }
+ old = lookup_name_current_level (name);
if (old)
{
@@ -4076,9 +4302,19 @@ push_overloaded_decl (decl, forgettable)
tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
- if (decl == OVL_CURRENT (tmp)
- || duplicate_decls (decl, OVL_CURRENT (tmp)))
- return OVL_CURRENT (tmp);
+ {
+ tree fn = OVL_CURRENT (tmp);
+
+ if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
+ && !(flags & PUSH_USING)
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ TYPE_ARG_TYPES (TREE_TYPE (decl))))
+ cp_error ("`%#D' conflicts with previous using declaration `%#D'",
+ decl, fn);
+
+ if (duplicate_decls (decl, fn))
+ return fn;
+ }
}
else
{
@@ -4091,17 +4327,57 @@ push_overloaded_decl (decl, forgettable)
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
if (old && TREE_CODE (old) != OVERLOAD)
- old = ovl_cons (old, NULL_TREE);
- old = ovl_cons (decl, old);
+ new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
+ else
+ new_binding = ovl_cons (decl, old);
+ if (flags & PUSH_USING)
+ OVL_USED (new_binding) = 1;
}
else
- /* orig_name is not ambiguous. */
- old = decl;
+ /* NAME is not ambiguous. */
+ new_binding = decl;
if (doing_global)
- set_namespace_binding (orig_name, current_namespace, old);
+ set_namespace_binding (name, current_namespace, new_binding);
else
- IDENTIFIER_LOCAL_VALUE (orig_name) = old;
+ {
+ /* We only create an OVERLOAD if there was a previous binding at
+ this level, or if decl is a template. In the former case, we
+ need to remove the old binding and replace it with the new
+ binding. We must also run through the NAMES on the binding
+ level where the name was bound to update the chain. */
+
+ if (TREE_CODE (new_binding) == OVERLOAD && old)
+ {
+ tree *d;
+
+ for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+ *d;
+ d = &TREE_CHAIN (*d))
+ if (*d == old
+ || (TREE_CODE (*d) == TREE_LIST
+ && TREE_VALUE (*d) == old))
+ {
+ if (TREE_CODE (*d) == TREE_LIST)
+ /* Just replace the old binding with the new. */
+ TREE_VALUE (*d) = new_binding;
+ else
+ /* Build a TREE_LIST to wrap the OVERLOAD. */
+ *d = build_tree_list (NULL_TREE, new_binding);
+
+ /* And update the CPLUS_BINDING node. */
+ BINDING_VALUE (IDENTIFIER_BINDING (name))
+ = new_binding;
+ return decl;
+ }
+
+ /* We should always find a previous binding in this case. */
+ my_friendly_abort (0);
+ }
+
+ /* Install the new binding. */
+ push_local_binding (name, new_binding, flags);
+ }
return decl;
}
@@ -4157,7 +4433,7 @@ implicitly_declare (functionid)
Otherwise return an error message format string with a %s
where the identifier should go. */
-static char *
+static const char *
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
@@ -4166,7 +4442,7 @@ redeclaration_error_message (newdecl, olddecl)
/* Because C++ can put things into name space for free,
constructs like "typedef struct foo { ... } foo"
would look like an erroneous redeclaration. */
- if (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
+ if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return 0;
else
return "redefinition of `%#D'";
@@ -4396,9 +4672,8 @@ define_label (filename, line, name)
and they should be cleaned up
by the time we get to the label. */
&& ! DECL_ARTIFICIAL (new_decls)
- && ((DECL_INITIAL (new_decls) != NULL_TREE
- && DECL_INITIAL (new_decls) != error_mark_node)
- || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
+ && !(DECL_INITIAL (new_decls) == NULL_TREE
+ && pod_type_p (TREE_TYPE (new_decls))))
{
if (! identified)
{
@@ -4408,8 +4683,13 @@ define_label (filename, line, name)
" from here");
identified = 1;
}
- cp_error_at (" crosses initialization of `%#D'",
- new_decls);
+ if (DECL_INITIAL (new_decls)
+ || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))
+ cp_error_at (" crosses initialization of `%#D'",
+ new_decls);
+ else
+ cp_error_at (" enters scope of non-POD `%#D'",
+ new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
@@ -4807,9 +5087,18 @@ lookup_namespace_name (namespace, name)
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
- /* This happens for A::B<int> when B is a namespace. */
if (TREE_CODE (name) == NAMESPACE_DECL)
+ /* This happens for A::B<int> when B is a namespace. */
return name;
+ else if (TREE_CODE (name) == TEMPLATE_DECL)
+ {
+ /* This happens for A::B where B is a template, and there are no
+ template arguments. */
+ cp_error ("invalid use of `%D'", name);
+ return error_mark_node;
+ }
+
+ namespace = ORIGINAL_NAMESPACE (namespace);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
@@ -4831,11 +5120,111 @@ lookup_namespace_name (namespace, name)
return error_mark_node;
}
+/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
+
+static unsigned long
+typename_hash (k)
+ hash_table_key k;
+{
+ unsigned long hash;
+ tree t;
+
+ t = (tree) k;
+ hash = (((unsigned long) TYPE_CONTEXT (t))
+ ^ ((unsigned long) DECL_NAME (TYPE_NAME (t))));
+
+ return hash;
+}
+
+/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
+
+static boolean
+typename_compare (k1, k2)
+ hash_table_key k1;
+ hash_table_key k2;
+{
+ tree t1;
+ tree t2;
+ tree d1;
+ tree d2;
+
+ t1 = (tree) k1;
+ t2 = (tree) k2;
+ d1 = TYPE_NAME (t1);
+ d2 = TYPE_NAME (t2);
+
+ return (DECL_NAME (d1) == DECL_NAME (d2)
+ && same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2))
+ && ((TREE_TYPE (t1) != NULL_TREE)
+ == (TREE_TYPE (t2) != NULL_TREE))
+ && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+ && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+}
+
+/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
+ the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
+ is non-NULL, this type is being created by the implicit typename
+ extension, and BASE_TYPE is a type named `t' in some base class of
+ `T' which depends on template parameters.
+
+ Returns the new TYPENAME_TYPE. */
+
+tree
+build_typename_type (context, name, fullname, base_type)
+ tree context;
+ tree name;
+ tree fullname;
+ tree base_type;
+{
+ tree t;
+ tree d;
+ struct hash_entry* e;
+
+ static struct hash_table ht;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ if (!ht.table
+ && !hash_table_init (&ht, &hash_newfunc, &typename_hash,
+ &typename_compare))
+ fatal ("virtual memory exhausted");
+
+ /* Build the TYPENAME_TYPE. */
+ t = make_lang_type (TYPENAME_TYPE);
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ TYPENAME_TYPE_FULLNAME (t) = fullname;
+ TREE_TYPE (t) = base_type;
+
+ /* Build the corresponding TYPE_DECL. */
+ d = build_decl (TYPE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+
+ /* See if we already have this type. */
+ e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
+ if (e)
+ {
+ /* This will free not only TREE_TYPE, but the lang-specific data
+ and the TYPE_DECL as well. */
+ obstack_free (&permanent_obstack, t);
+ t = (tree) e->key;
+ }
+ else
+ /* Insert the type into the table. */
+ hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
+
+ pop_obstacks ();
+
+ return t;
+}
+
tree
make_typename_type (context, name)
tree context, name;
{
- tree t, d;
+ tree t;
tree fullname;
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
@@ -4871,52 +5260,33 @@ make_typename_type (context, name)
if (IS_AGGR_TYPE (context))
t = lookup_field (context, name, 0, 0);
else
- t = NULL_TREE;
-
- if (t == NULL_TREE || TREE_CODE (t) != TEMPLATE_DECL
- || TREE_CODE (DECL_RESULT (t)) != TYPE_DECL)
{
cp_error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
- return lookup_template_class (t, TREE_OPERAND (fullname, 1),
- NULL_TREE, context,
- /*entering_scope=*/0);
+ if (t && DECL_CLASS_TEMPLATE_P (t))
+ return lookup_template_class (t, TREE_OPERAND (fullname, 1),
+ NULL_TREE, context,
+ /*entering_scope=*/0);
}
else
{
if (IS_AGGR_TYPE (context))
t = lookup_field (context, name, 0, 1);
else
- t = NULL_TREE;
-
- if (t == NULL_TREE)
{
cp_error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
- return TREE_TYPE (t);
+ if (t)
+ return TREE_TYPE (t);
}
}
-
- if (processing_template_decl)
- push_obstacks (&permanent_obstack, &permanent_obstack);
- t = make_lang_type (TYPENAME_TYPE);
- TYPENAME_TYPE_FULLNAME (t) = fullname;
- d = build_decl (TYPE_DECL, name, t);
- if (processing_template_decl)
- pop_obstacks ();
-
- TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- TYPE_NAME (TREE_TYPE (d)) = d;
- TYPE_STUB_DECL (TREE_TYPE (d)) = d;
- DECL_CONTEXT (d) = FROB_CONTEXT (context);
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
-
- return t;
+
+ return build_typename_type (context, name, fullname, NULL_TREE);
}
/* Select the right _DECL from multiple choices. */
@@ -4944,7 +5314,8 @@ select_decl (binding, flags)
val = TYPE_STUB_DECL (BINDING_TYPE (binding));
/* Don't return non-types if we really prefer types. */
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
- && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
+ && (TREE_CODE (val) != TEMPLATE_DECL
+ || !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
return val;
@@ -4981,7 +5352,7 @@ unqualified_namespace_lookup (name, flags)
if (!lookup_using_namespace (name, b, level->using_directives,
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
/* Add all _DECLs seen through global using-directives. */
/* XXX local and global using lists should work equally. */
@@ -4991,7 +5362,7 @@ unqualified_namespace_lookup (name, flags)
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
@@ -5063,7 +5434,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
- tree locval, classval;
int flags;
/* Hack: copy flag set by parser, if set. */
@@ -5079,8 +5449,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
prefer_type = looking_for_typename;
flags = lookup_flags (prefer_type, namespaces_only);
- /* During parsing, we need to complain. */
- flags |= LOOKUP_COMPLAIN;
/* If the next thing is '<', class templates are types. */
if (looking_for_template)
flags |= LOOKUP_TEMPLATES_EXPECTED;
@@ -5154,112 +5522,98 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
from_obj = val;
}
else
- flags = lookup_flags (prefer_type, namespaces_only);
-
- locval = classval = NULL_TREE;
-
- if (! namespace_bindings_p ())
- locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
-
- /* In C++ class fields are between local and global scope,
- just before the global scope. */
- if (current_class_type && ! nonclass)
{
- classval = IDENTIFIER_CLASS_VALUE (name);
- if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
- /* Try to find values from base classes if we are presently
- defining a type. We are presently only interested in
- TYPE_DECLs. */
- classval = lookup_field (current_class_type, name, 0, 1);
-
- /* Add implicit 'typename' to types from template bases. lookup_field
- will do this for us. If classval is actually from an enclosing
- scope, lookup_nested_field will get it for us. */
- else if (processing_template_decl
- && classval && TREE_CODE (classval) == TYPE_DECL
- && ! currently_open_class (DECL_CONTEXT (classval))
- && uses_template_parms (current_class_type))
- classval = lookup_field (current_class_type, name, 0, 1);
-
- /* yylex() calls this with -2, since we should never start digging for
- the nested name at the point where we haven't even, for example,
- created the COMPONENT_REF or anything like that. */
- if (classval == NULL_TREE)
- classval = lookup_nested_field (name, ! yylex);
-
- classval = qualify_lookup (classval, flags);
+ flags = lookup_flags (prefer_type, namespaces_only);
+ /* If we're not parsing, we need to complain. */
+ flags |= LOOKUP_COMPLAIN;
}
- if (locval && classval)
+ /* First, look in non-namespace scopes. */
+ for (val = IDENTIFIER_BINDING (name); val; val = TREE_CHAIN (val))
{
- if (current_scope () == current_function_decl
- && ! hack_decl_function_context (current_function_decl))
- /* Not in a nested function. */
- val = locval;
- else
+ if (!LOCAL_BINDING_P (val) && nonclass)
+ /* We're not looking for class-scoped bindings, so keep going. */
+ continue;
+
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (qualify_lookup (BINDING_VALUE (val), flags))
{
- /* This is incredibly horrible. The whole concept of
- IDENTIFIER_LOCAL_VALUE / IDENTIFIER_CLASS_VALUE /
- IDENTIFIER_GLOBAL_VALUE needs to be scrapped for local
- classes. */
- tree lctx = hack_decl_function_context (locval);
- tree cctx = hack_decl_function_context (classval);
-
- if (lctx == current_scope ())
- val = locval;
- else if (lctx == cctx)
- val = classval;
- else
- /* I don't know which is right; let's just guess for now. */
- val = locval;
+ val = BINDING_VALUE (val);
+ break;
+ }
+ else if ((flags & LOOKUP_PREFER_TYPES)
+ && qualify_lookup (BINDING_TYPE (val), flags))
+ {
+ val = BINDING_TYPE (val);
+ break;
}
}
- else if (locval)
- val = locval;
- else if (classval)
- val = classval;
- else
- val = unqualified_namespace_lookup (name, flags);
- /* Any other name takes precedence over an implicit typename. Warn the
- user about this potentially confusing lookup. */
- if (classval && TREE_CODE (val) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (val)) == TYPENAME_TYPE
- && TREE_TYPE (TREE_TYPE (val)))
+ /* If VAL is a type from a dependent base, we're not really supposed
+ to be able to see it; the fact that we can is the "implicit
+ typename" extension. We call lookup_field here to turn VAL into
+ a TYPE_DECL for a TYPENAME_TYPE. */
+ if (processing_template_decl && val
+ && val == IDENTIFIER_CLASS_VALUE (name)
+ && TREE_CODE (val) == TYPE_DECL
+ && !currently_open_class (DECL_CONTEXT (val))
+ && uses_template_parms (current_class_type))
+ val = lookup_field (current_class_type, name, 0, 1);
+
+ /* We don't put names from baseclasses onto the IDENTIFIER_BINDING
+ list when we're defining a type. It would probably be simpler to
+ do this, but we don't. So, we must lookup names from base
+ classes explicitly. */
+ if (!val && !nonclass
+ && current_class_type && TYPE_BEING_DEFINED (current_class_type))
+ val = qualify_lookup (lookup_field (current_class_type, name, 0, 0),
+ flags);
+
+ /* The name might be from an enclosing class of the current scope. */
+ if (!val && !nonclass && current_class_type)
+ val = qualify_lookup (lookup_nested_field (name, !yylex), flags);
+
+ /* If we found a type from a dependent base class (using the
+ implicit typename extension) make sure that there's not some
+ global name which should be chosen instead. */
+ if (val && TREE_CODE (val) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
{
- if (locval == NULL_TREE)
- locval = unqualified_namespace_lookup (name, flags);
+ tree global_val;
+
+ /* Any other name takes precedence over an implicit typename. Warn the
+ user about this potentially confusing lookup. */
+ global_val = unqualified_namespace_lookup (name, flags);
- if (locval && val != locval)
+ if (global_val)
{
tree subtype;
- val = locval;
-
- /* To avoid redundant warnings, only warn when lexing, and the
- decls are significantly different. */
- subtype = TREE_TYPE (TREE_TYPE (classval));
- if (yylex
- && ! (TREE_CODE (locval) == TEMPLATE_DECL
+ /* Only warn when not lexing; we don't want to warn if they
+ use this name as a declarator. */
+ subtype = TREE_TYPE (TREE_TYPE (val));
+ if (! yylex
+ && ! (TREE_CODE (global_val) == TEMPLATE_DECL
&& CLASSTYPE_TEMPLATE_INFO (subtype)
- && CLASSTYPE_TI_TEMPLATE (subtype) == locval)
- && ! (TREE_CODE (locval) == TYPE_DECL
- && comptypes (TREE_TYPE (locval), subtype, 1)))
+ && CLASSTYPE_TI_TEMPLATE (subtype) == global_val)
+ && ! (TREE_CODE (global_val) == TYPE_DECL
+ && same_type_p (TREE_TYPE (global_val), subtype)))
{
- static int explained;
-
- cp_warning ("lookup of `%D' finds `%#D'", name, locval);
- cp_warning
- (" instead of `%D' from dependent base class", classval);
- if (! explained)
- {
- explained = 1;
- cp_warning (" (use `typename %D' if that's what you meant)",
- classval);
- }
+ cp_warning ("lookup of `%D' finds `%#D'", name, global_val);
+ cp_warning (" instead of `%D' from dependent base class",
+ val);
+ cp_warning (" (use `typename %T::%D' if that's what you meant)",
+ constructor_name (current_class_type), name);
}
+
+ /* Use the global value instead of the implicit typename. */
+ val = global_val;
}
}
+ else if (!val)
+ /* No local, or class-scoped binding. Look for a namespace-scope
+ declaration. */
+ val = unqualified_namespace_lookup (name, flags);
done:
if (val)
@@ -5284,17 +5638,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
val = from_obj;
}
- if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
- || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
- ;
- /* Caller wants a class-or-namespace-name. */
- else if (prefer_type == 1 && TREE_CODE (val) == NAMESPACE_DECL)
- ;
- else if (IDENTIFIER_HAS_TYPE_VALUE (name))
- val = TYPE_MAIN_DECL (IDENTIFIER_TYPE_VALUE (name));
- else if (TREE_TYPE (val) == error_mark_node)
- val = error_mark_node;
-
/* 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);
@@ -5352,13 +5695,16 @@ lookup_name_current_level (name)
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
t = TREE_VALUE (t);
}
- else if (IDENTIFIER_LOCAL_VALUE (name) != NULL_TREE)
+ else if (IDENTIFIER_BINDING (name)
+ && LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
{
struct binding_level *b = current_binding_level;
+
while (1)
{
- if (purpose_member (name, b->shadowed))
- return IDENTIFIER_LOCAL_VALUE (name);
+ if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
+ return IDENTIFIER_VALUE (name);
+
if (b->keep == 2)
b = b->level_chain;
else
@@ -5452,7 +5798,7 @@ static int builtin_type_tdescs_len, builtin_type_tdescs_max;
static void
record_builtin_type (rid_index, name, type)
enum rid rid_index;
- char *name;
+ const char *name;
tree type;
{
tree rname = NULL_TREE, tname = NULL_TREE;
@@ -5495,7 +5841,7 @@ record_builtin_type (rid_index, name, type)
static tree
record_builtin_java_type (name, size)
- char *name;
+ const char *name;
int size;
{
tree type, decl;
@@ -5524,7 +5870,7 @@ record_builtin_java_type (name, size)
static void
record_unknown_type (type, name)
tree type;
- char *name;
+ const char *name;
{
tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
@@ -5542,7 +5888,7 @@ static void
push_overloaded_decl_1 (x)
tree x;
{
- push_overloaded_decl (x, 0);
+ push_overloaded_decl (x, PUSH_GLOBAL);
}
#ifdef __GNUC__
@@ -5575,6 +5921,8 @@ init_decl_processing ()
tree temp;
tree array_domain_type;
tree vb_off_identifier = NULL_TREE;
+ /* Function type `char *(char *, char *)' and similar ones */
+ tree string_ftype_ptr_ptr, int_ftype_string_string;
tree sizetype_endlink;
tree ptr_ftype, ptr_ftype_unsigned, ptr_ftype_sizetype;
tree void_ftype, void_ftype_int, void_ftype_ptr;
@@ -5594,6 +5942,8 @@ init_decl_processing ()
if (flag_strict_prototype == 2)
flag_strict_prototype = pedantic;
+ if (! flag_permissive && ! pedantic)
+ flag_pedantic_errors = 1;
strict_prototypes_lang_c = flag_strict_prototype;
@@ -5606,7 +5956,6 @@ init_decl_processing ()
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
-#ifndef __CYGWIN32__
/* Because most segmentation signals can be traced back into user
code, catch them and at least give the user a chance of working
around compiler bugs. */
@@ -5628,13 +5977,6 @@ init_decl_processing ()
#ifdef SIGBUS
signal (SIGBUS, signal_catch);
#endif
-#else /* ndef __CYGWIN32__ */
- /* Cygwin32 cannot handle catching signals other than
- SIGABRT yet. We hope this will cease to be the case soon. */
-#ifdef SIGABRT
- signal (SIGABRT, signal_catch);
-#endif
-#endif /* ndef __CYGWIN32__ */
gcc_obstack_init (&decl_obstack);
@@ -5682,6 +6024,9 @@ init_decl_processing ()
: make_unsigned_type (CHAR_TYPE_SIZE));
record_builtin_type (RID_CHAR, "char", char_type_node);
+ /* `signed' is the same as `int' */
+ record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node);
+
long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
record_builtin_type (RID_LONG, "long int", long_integer_type_node);
@@ -5731,8 +6076,10 @@ init_decl_processing ()
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
+#endif
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
@@ -5741,8 +6088,10 @@ init_decl_processing ()
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
+#endif
float_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -5838,7 +6187,8 @@ init_decl_processing ()
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
- = build_pointer_type (build_type_variant (char_type_node, 1, 0));
+ = build_pointer_type (build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
#endif
@@ -5868,7 +6218,8 @@ init_decl_processing ()
ptr_type_node = build_pointer_type (void_type_node);
const_ptr_type_node
- = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+ = build_pointer_type (build_qualified_type (void_type_node,
+ TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
#endif
@@ -6197,14 +6548,15 @@ init_decl_processing ()
DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
TREE_UNSIGNED (fields[3]) = 0;
TREE_CHAIN (fields[2]) = fields[3];
- vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
+ vtable_entry_type = build_qualified_type (vtable_entry_type,
+ TYPE_QUAL_CONST);
}
record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
vtbl_type_node
- = build_array_type (vtable_entry_type, NULL_TREE);
+ = build_cplus_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
- vtbl_type_node = cp_build_type_variant (vtbl_type_node, 1, 0);
+ vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
layout_type (vtbl_ptr_type_node);
@@ -6243,7 +6595,8 @@ init_decl_processing ()
TREE_UNSIGNED (fields[5]) = 0;
TREE_CHAIN (fields[4]) = fields[5];
- sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0);
+ sigtable_entry_type = build_qualified_type (sigtable_entry_type,
+ TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
@@ -6272,7 +6625,8 @@ init_decl_processing ()
(void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
- auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
+ global_delete_fndecl
+ = auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN);
}
@@ -6375,11 +6729,11 @@ lang_print_error_function (file)
tree
define_function (name, type, function_code, pfn, library_name)
- char *name;
+ const char *name;
tree type;
enum built_in_function function_code;
void (*pfn) PROTO((tree));
- char *library_name;
+ const char *library_name;
{
tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
@@ -6426,7 +6780,6 @@ fixup_anonymous_union (t)
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0;
- TYPE_HAS_ASSIGNMENT (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
/* Splice the implicitly generated functions out of the TYPE_METHODS
@@ -6446,41 +6799,39 @@ fixup_anonymous_union (t)
error ("an anonymous union cannot have function members");
}
-/* Called when a declaration is seen that contains no names to declare.
- If its type is a reference to a structure, union or enum inherited
- from a containing scope, shadow that tag name for the current scope
- with a forward reference.
- If its type defines a new named structure or union
- or defines an enum, it is valid but we need not do anything here.
- Otherwise, it is an error.
+/* Make sure that a declaration with no declarator is well-formed, i.e.
+ just defines a tagged type or anonymous union.
- C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions. */
+ Returns the type defined, if any. */
-void
-shadow_tag (declspecs)
+tree
+check_tag_decl (declspecs)
tree declspecs;
{
- int found_tag = 0;
+ int found_type = 0;
tree ob_modifier = NULL_TREE;
register tree link;
- register enum tree_code code, ok_code = ERROR_MARK;
register tree t = NULL_TREE;
for (link = declspecs; link; link = TREE_CHAIN (link))
{
register tree value = TREE_VALUE (link);
- code = TREE_CODE (value);
- if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
+ if (TYPE_P (value))
{
- my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+ ++found_type;
- maybe_process_partial_specialization (value);
-
- t = value;
- ok_code = code;
- found_tag++;
+ if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
+ {
+ my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+ t = value;
+ }
+ }
+ else if (value == ridpointers[(int) RID_FRIEND])
+ {
+ if (current_class_type == NULL_TREE
+ || current_scope () != current_class_type)
+ ob_modifier = value;
}
else if (value == ridpointers[(int) RID_STATIC]
|| value == ridpointers[(int) RID_EXTERN]
@@ -6488,21 +6839,75 @@ shadow_tag (declspecs)
|| value == ridpointers[(int) RID_REGISTER]
|| value == ridpointers[(int) RID_INLINE]
|| value == ridpointers[(int) RID_VIRTUAL]
+ || value == ridpointers[(int) RID_CONST]
+ || value == ridpointers[(int) RID_VOLATILE]
|| value == ridpointers[(int) RID_EXPLICIT])
ob_modifier = value;
}
+ if (found_type > 1)
+ error ("multiple types in one declaration");
+
+ /* Inside a class, we might be in a friend or access declaration.
+ Until we have a good way of detecting the latter, don't warn. */
+ if (t == NULL_TREE && ! current_class_type)
+ pedwarn ("declaration does not declare anything");
+
+ /* Check for an anonymous union. We're careful
+ accessing TYPE_IDENTIFIER because some built-in types, like
+ pointer-to-member types, do not have TYPE_NAME. */
+ else if (t && TREE_CODE (t) == UNION_TYPE
+ && TYPE_NAME (t)
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ {
+ /* Anonymous unions are objects, so they can have specifiers. */;
+ SET_ANON_UNION_TYPE_P (t);
+ }
+
+ else if (ob_modifier)
+ {
+ if (ob_modifier == ridpointers[(int) RID_INLINE]
+ || ob_modifier == ridpointers[(int) RID_VIRTUAL])
+ cp_error ("`%D' can only be specified for functions", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_FRIEND])
+ cp_error ("`%D' can only be specified inside a class", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
+ cp_error ("`%D' can only be specified for constructors",
+ ob_modifier);
+ else
+ cp_error ("`%D' can only be specified for objects and functions",
+ ob_modifier);
+ }
+
+ return t;
+}
+
+/* Called when a declaration is seen that contains no names to declare.
+ If its type is a reference to a structure, union or enum inherited
+ from a containing scope, shadow that tag name for the current scope
+ with a forward reference.
+ If its type defines a new named structure or union
+ or defines an enum, it is valid but we need not do anything here.
+ Otherwise, it is an error.
+
+ C++: may have to grok the declspecs to learn about static,
+ complain for anonymous unions. */
+
+void
+shadow_tag (declspecs)
+ tree declspecs;
+{
+ tree t = check_tag_decl (declspecs);
+
+ if (t)
+ maybe_process_partial_specialization (t);
+
/* This is where the variables in an anonymous union are
declared. An anonymous union declaration looks like:
union { ... } ;
because there is no declarator after the union, the parser
sends that declaration here. */
- if (ok_code == UNION_TYPE
- && t != NULL_TREE
- && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (TYPE_NAME (t)))
- || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
+ if (t && ANON_UNION_TYPE_P (t))
{
fixup_anonymous_union (t);
@@ -6513,29 +6918,6 @@ shadow_tag (declspecs)
finish_anon_union (decl);
}
}
- else
- {
- /* Anonymous unions are objects, that's why we only check for
- inappropriate specifiers in this branch. */
-
- if (ob_modifier)
- {
- if (ob_modifier == ridpointers[(int) RID_INLINE]
- || ob_modifier == ridpointers[(int) RID_VIRTUAL])
- cp_error ("`%D' can only be specified for functions", ob_modifier);
- else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
- cp_error ("`%D' can only be specified for constructors",
- ob_modifier);
- else
- cp_error ("`%D' can only be specified for objects and functions",
- ob_modifier);
- }
-
- if (found_tag == 0)
- cp_error ("abstract declarator used as declaration");
- else if (found_tag > 1)
- pedwarn ("multiple types in one declaration");
- }
}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
@@ -6602,6 +6984,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return NULL_TREE;
+
/* Don't lose if destructors must be executed at file-level. */
if (! processing_template_decl && TREE_STATIC (decl)
&& TYPE_NEEDS_DESTRUCTOR (complete_type (type))
@@ -6704,6 +7089,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
{
+ pushclass (context, 2);
+
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
@@ -6740,13 +7127,21 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
DECL_IN_AGGR_P (decl) = 0;
if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
|| CLASSTYPE_USE_TEMPLATE (context))
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ {
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ /* [temp.expl.spec] An explicit specialization of a static data
+ member of a template is a definition if the declaration
+ includes an initializer; otherwise, it is a declaration.
+
+ We check for processing_specialization so this only applies
+ to the new specialization syntax. */
+ if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization)
+ DECL_EXTERNAL (decl) = 1;
+ }
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
cp_pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
-
- pushclass (context, 2);
}
#ifdef SET_DEFAULT_DECL_ATTRIBUTES
@@ -6838,6 +7233,9 @@ start_decl_1 (decl)
tree type = TREE_TYPE (decl);
int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+ if (type == error_mark_node)
+ return;
+
/* If this type of object needs a cleanup, and control may
jump past it, make a new binding level so that it is cleaned
up only when it is initialized first. */
@@ -6852,9 +7250,7 @@ start_decl_1 (decl)
{
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (type == error_mark_node)
- ; /* Don't complain again. */
- else if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+ if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
@@ -6954,10 +7350,6 @@ grok_reference_init (decl, type, init)
return;
}
- if (TREE_TYPE (init) && TREE_CODE (TREE_TYPE (init)) == UNKNOWN_TYPE)
- /* decay_conversion is probably wrong for references to functions. */
- init = decay_conversion (instantiate_type (TREE_TYPE (type), init, 1));
-
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
@@ -7038,6 +7430,25 @@ obscure_complex_init (decl, init)
return init;
}
+/* Issue an error message if DECL is an uninitialized const variable. */
+
+static void
+check_for_uninitialized_const_var (decl)
+ tree decl;
+{
+ tree type = TREE_TYPE (decl);
+
+ /* ``Unless explicitly declared extern, a const object does not have
+ external linkage and must be initialized. ($8.4; $12.1)'' ARM
+ 7.1.6 */
+ if (TREE_CODE (decl) == VAR_DECL
+ && TREE_CODE (type) != REFERENCE_TYPE
+ && CP_TYPE_CONST_P (type)
+ && !TYPE_NEEDS_CONSTRUCTING (type)
+ && !DECL_INITIAL (decl))
+ cp_error ("uninitialized const `%D'", decl);
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@@ -7094,6 +7505,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
init = NULL_TREE;
}
+ if (current_class_type
+ && DECL_REAL_CONTEXT (decl) == current_class_type
+ && TYPE_BEING_DEFINED (current_class_type)
+ && (DECL_INITIAL (decl) || init))
+ DECL_DEFINED_IN_CLASS_P (decl) = 1;
+
if (TREE_CODE (decl) == VAR_DECL
&& DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
@@ -7120,6 +7537,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
return;
}
+ if (TYPE_HAS_MUTABLE_P (type))
+ TREE_READONLY (decl) = 0;
+
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
@@ -7238,7 +7658,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0);
- else if (TREE_CODE (init) == CONSTRUCTOR)
+ else if (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
@@ -7279,32 +7700,16 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
decl);
}
- if (TREE_CODE (decl) == VAR_DECL
- && !DECL_INITIAL (decl)
- && !TYPE_NEEDS_CONSTRUCTING (type)
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- cp_error ("uninitialized const `%D'", decl);
+ check_for_uninitialized_const_var (decl);
if (TYPE_SIZE (type) != NULL_TREE
&& TYPE_NEEDS_CONSTRUCTING (type))
init = obscure_complex_init (decl, NULL_TREE);
- }
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_CODE (type) != REFERENCE_TYPE
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- {
- /* ``Unless explicitly declared extern, a const object does not have
- external linkage and must be initialized. ($8.4; $12.1)'' ARM 7.1.6
- However, if it's `const int foo = 1; const int foo;', don't complain
- about the second decl, since it does have an initializer before.
- We deliberately don't complain about arrays, because they're
- supposed to be initialized by a constructor. */
- if (! DECL_INITIAL (decl)
- && TREE_CODE (type) != ARRAY_TYPE
- && (!pedantic || !current_class_type))
- cp_error ("uninitialized const `%#D'", decl);
- }
+ }
+ else
+ check_for_uninitialized_const_var (decl);
+
/* For top-level declaration, the initial value was read in
the temporary obstack. MAXINDEX, rtl, etc. to be made below
must go in the permanent obstack; but don't discard the
@@ -7480,31 +7885,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_LANG_SPECIFIC (decl)
&& DECL_COMDAT (decl))
- {
- /* Dynamically initialized vars go into common. */
- if (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
- DECL_COMMON (decl) = 1;
- else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
- {
- DECL_COMMON (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node;
- }
- else
- {
- /* Statically initialized vars are weak or comdat, if
- supported. */
- if (flag_weak)
- make_decl_one_only (decl);
- else
- {
- /* We can't do anything useful; leave vars for explicit
- instantiation. */
- DECL_EXTERNAL (decl) = 1;
- DECL_NOT_REALLY_EXTERN (decl) = 0;
- }
- }
- }
+ /* Set it up again; we might have set DECL_INITIAL since the
+ last time. */
+ comdat_linkage (decl);
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
make_decl_rtl (decl, NULL_PTR, toplev);
@@ -7652,7 +8035,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (current_binding_level->is_for_scope)
{
- struct binding_level *outer = current_binding_level->level_chain;
+ struct binding_level *outer
+ = current_binding_level->level_chain;
/* Check to see if the same name is already bound at
the outer level, either because it was directly declared,
@@ -7664,36 +8048,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
Otherwise, we need to preserve the temp slot for decl
to last into the outer binding level. */
- int handling_dead_for_vars = 0;
- tree link = outer->names;
- for (; ; link = TREE_CHAIN (link))
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+
+ if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == VAR_DECL)
+ && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
- if (link == NULL && handling_dead_for_vars == 0)
- {
- link = outer->dead_vars_from_for;
- handling_dead_for_vars = 1;
- }
- if (link == NULL)
- {
- if (DECL_IN_MEMORY_P (decl))
- preserve_temp_slots (DECL_RTL (decl));
- break;
- }
- if (DECL_NAME (link) == DECL_NAME (decl))
- {
- if (handling_dead_for_vars)
- {
- tree shadowing
- = purpose_member (DECL_NAME (decl),
- current_binding_level->shadowed);
- if (shadowing && TREE_VALUE (shadowing) == link)
- TREE_VALUE (shadowing)
- = DECL_SHADOWED_FOR_VAR (link);
- }
- current_binding_level->is_for_scope = 0;
- break;
- }
+ BINDING_VALUE (outer_binding)
+ = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
+ current_binding_level->is_for_scope = 0;
}
+ else if (DECL_IN_MEMORY_P (decl))
+ preserve_temp_slots (DECL_RTL (decl));
}
expand_start_target_temps ();
@@ -7815,6 +8183,9 @@ expand_static_init (decl, init)
{
tree oldstatic = value_member (decl, static_aggregates);
+ /* If at_eof is 2, we're too late. */
+ my_friendly_assert (at_eof <= 1, 990323);
+
if (oldstatic)
{
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
@@ -7828,14 +8199,39 @@ expand_static_init (decl, init)
/* Remember this information until end of file. */
push_obstacks (&permanent_obstack, &permanent_obstack);
- /* Emit code to perform this initialization but once. */
+ /* Emit code to perform this initialization but once. This code
+ looks like:
+
+ static int temp = 0;
+ if (!temp) {
+ // Do initialization.
+ temp = 1;
+ // Register variable for destruction at end of program.
+ }
+
+ Note that the `temp' variable is only set to 1 *after* the
+ initialization is complete. This ensures that an exception,
+ thrown during the construction, will cause the variable to
+ reinitialized when we pass through this code again, as per:
+
+ [stmt.dcl]
+
+ If the initialization exits by throwing an exception, the
+ initialization is not complete, so it will be tried again
+ the next time control enters the declaration.
+
+ In theory, this process should be thread-safe, too; multiple
+ threads should not be able to initialize the variable more
+ than once. We don't yet attempt to ensure thread-safety. */
temp = get_temp_name (integer_type_node, 1);
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
+
+ /* Begin the conditional initialization. */
expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node, 1), 0);
expand_start_target_temps ();
- expand_assignment (temp, integer_one_node, 0, 0);
+ /* Do the initialization itself. */
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| (init && TREE_CODE (init) == TREE_LIST))
{
@@ -7845,9 +8241,17 @@ expand_static_init (decl, init)
else if (init)
expand_assignment (decl, init, 0, 0);
- /* Cleanup any temporaries needed for the initial value. */
+ /* Set TEMP to 1. */
+ expand_assignment (temp, integer_one_node, 0, 0);
+
+ /* Cleanup any temporaries needed for the initial value. If
+ destroying one of the temporaries causes an exception to be
+ thrown, then the object itself has still been fully
+ constructed. */
expand_end_target_temps ();
+ /* Use atexit to register a function for destroying this static
+ variable. */
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{
tree cleanup, fcall;
@@ -7871,14 +8275,19 @@ expand_static_init (decl, init)
build_function_type (void_type_node,
pfvlist),
NOT_BUILT_IN, NULL_PTR);
- assemble_external (atexit_fndecl);
+ mark_used (atexit_fndecl);
Atexit = default_conversion (atexit_fndecl);
pop_lang_context ();
pop_obstacks ();
}
+ /* Call build_cleanup before we enter the anonymous function
+ so that any access checks will be done relative to the
+ current scope, rather than the scope of the anonymous
+ function. */
+ fcall = build_cleanup (decl);
cleanup = start_anon_func ();
- expand_expr_stmt (build_cleanup (decl));
+ expand_expr_stmt (fcall);
end_anon_func ();
mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
@@ -7949,6 +8358,8 @@ complete_array_type (type, initial_value, do_default)
/* Make an error message unless that happened already. */
if (initial_value != error_mark_node)
value = 1;
+ else
+ initial_value = NULL_TREE;
/* Prevent further error messages. */
maxindex = build_int_2 (0, 0);
@@ -7996,7 +8407,7 @@ complete_array_type (type, initial_value, do_default)
static int
member_function_or_else (ctype, cur_type, string)
tree ctype, cur_type;
- char *string;
+ const char *string;
{
if (ctype && ctype != cur_type)
{
@@ -8014,7 +8425,7 @@ member_function_or_else (ctype, cur_type, string)
static void
bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
tree object;
- char *type;
+ const char *type;
int virtualp, quals, friendp, raises, inlinep;
{
if (virtualp)
@@ -8042,7 +8453,7 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
CHECK is 1 if we must find this method in CTYPE, 0 if we should
not look, and -1 if we should not call `grokclassfn' at all.
- Returns `error_mark_node' if something goes wrong, after issuing
+ Returns `NULL_TREE' if something goes wrong, after issuing
applicable error messages. */
static tree
@@ -8078,9 +8489,23 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
- /* This decl is not from the current namespace. */
+ /* If this decl has namespace scope, set that up. */
if (in_namespace)
- set_decl_namespace (decl, in_namespace);
+ set_decl_namespace (decl, in_namespace, friendp);
+ else if (publicp && ! ctype)
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+
+ /* `main' and builtins have implicit 'C' linkage. */
+ if ((MAIN_NAME_P (declarator)
+ || (IDENTIFIER_LENGTH (declarator) > 10
+ && IDENTIFIER_POINTER (declarator)[0] == '_'
+ && IDENTIFIER_POINTER (declarator)[1] == '_'
+ && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
+ && current_lang_name == lang_name_cplusplus
+ && ctype == NULL_TREE
+ /* NULL_TREE means global namespace. */
+ && DECL_CONTEXT (decl) == NULL_TREE)
+ DECL_LANGUAGE (decl) = lang_c;
/* Should probably propagate const out from type to decl I bet (mrs). */
if (staticp)
@@ -8092,8 +8517,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype)
DECL_CLASS_CONTEXT (decl) = ctype;
- if (ctype == NULL_TREE && MAIN_NAME_P (declarator))
+ if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
+ if (processing_template_decl)
+ error ("cannot declare `main' to be a template");
if (inlinep)
error ("cannot declare `main' to be inline");
else if (! publicp)
@@ -8102,8 +8529,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
publicp = 1;
}
- /* Members of anonymous types have no linkage; make them internal. */
- if (ctype && ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype)))
+ /* Members of anonymous types and local classes have no linkage; make
+ them internal. */
+ if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype))
+ || hack_decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
if (publicp)
@@ -8117,7 +8546,13 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (t)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
- cp_pedwarn ("non-local function `%#D' uses anonymous type", decl);
+ {
+ if (DECL_LANGUAGE (decl) == lang_c)
+ /* Allow this; it's pretty common in C. */;
+ else
+ cp_pedwarn ("non-local function `%#D' uses anonymous type",
+ decl);
+ }
else
cp_pedwarn ("non-local function `%#D' uses local type `%T'",
decl, t);
@@ -8170,7 +8605,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
/* Something like `template <class T> friend void f<T>()'. */
cp_error ("template-id `%D' in declaration of primary template",
orig_declarator);
- return error_mark_node;
+ return NULL_TREE;
}
/* A friend declaration of the form friend void f<>(). Record
@@ -8183,6 +8618,17 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
}
}
+ /* Plain overloading: will not be grok'd by grokclassfn. */
+ if (! ctype && ! processing_template_decl
+ && DECL_LANGUAGE (decl) != lang_c
+ && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
+ set_mangled_name_for_decl (decl);
+
+ if (funcdef_flag)
+ /* Make the init_value nonzero so pushdecl knows this is not
+ tentative. error_mark_node is replaced later with the BLOCK. */
+ DECL_INITIAL (decl) = error_mark_node;
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
@@ -8207,7 +8653,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
if (decl == error_mark_node)
- return error_mark_node;
+ return NULL_TREE;
if ((! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
@@ -8223,23 +8669,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
return tmp;
}
if (! grok_ctor_properties (ctype, decl))
- return error_mark_node;
-
- if (check == 0 && ! current_function_decl)
- {
- /* Assembler names live in the global namespace. */
- tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
- if (tmp == NULL_TREE)
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- cp_error ("inconsistent declarations for `%D'", decl);
- else
- {
- duplicate_decls (decl, tmp);
- decl = tmp;
- }
- make_decl_rtl (decl, NULL_PTR, 1);
- }
+ return NULL_TREE;
}
else
{
@@ -8256,7 +8686,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
if (decl == error_mark_node)
- return error_mark_node;
+ return NULL_TREE;
if (ctype != NULL_TREE
&& (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
@@ -8279,8 +8709,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp)
{
+ /* Attempt to merge the declarations. This can fail, in
+ the case of some illegal specialization declarations. */
if (!duplicate_decls (decl, tmp))
- my_friendly_abort (892);
+ cp_error ("no `%#D' member function declared in class `%T'",
+ decl, ctype);
return tmp;
}
}
@@ -8288,37 +8721,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype == NULL_TREE || check)
return decl;
- /* Now install the declaration of this function so that others may
- find it (esp. its DECL_FRIENDLIST). Don't do this for local class
- methods, though. */
- if (! current_function_decl)
- {
- if (!DECL_TEMPLATE_SPECIALIZATION (decl))
- {
- /* We don't do this for specializations since the
- equivalent checks will be done later. Also, at this
- point the DECL_ASSEMBLER_NAME is not yet fully
- accurate. */
-
- /* FIXME: this should only need to look at
- IDENTIFIER_GLOBAL_VALUE. */
- tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
- if (tmp == NULL_TREE)
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- cp_error ("inconsistent declarations for `%D'", decl);
- else
- {
- duplicate_decls (decl, tmp);
- decl = tmp;
- }
- }
+ if (attrlist)
+ cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
+ TREE_VALUE (attrlist));
+ make_decl_rtl (decl, NULL_PTR, 1);
- if (attrlist)
- cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
- TREE_VALUE (attrlist));
- make_decl_rtl (decl, NULL_PTR, 1);
- }
if (virtualp)
{
DECL_VIRTUAL_P (decl) = 1;
@@ -8357,16 +8764,27 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
}
else
{
- tree context = in_namespace ? in_namespace : current_namespace;
+ tree context;
+
+ if (in_namespace)
+ context = in_namespace;
+ else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
+ context = current_namespace;
+ else
+ context = NULL_TREE;
+
decl = build_decl (VAR_DECL, declarator, complete_type (type));
- if (context != global_namespace && namespace_bindings_p ()
- && current_lang_name != lang_name_c)
- DECL_ASSEMBLER_NAME (decl) = build_static_name (context,
- declarator);
+
+ if (context)
+ set_decl_namespace (decl, context, 0);
+
+ context = DECL_CONTEXT (decl);
+ if (declarator && context && current_lang_name != lang_name_c)
+ DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator);
}
if (in_namespace)
- set_decl_namespace (decl, in_namespace);
+ set_decl_namespace (decl, in_namespace, 0);
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
@@ -8418,7 +8836,8 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
return decl;
}
-/* Create a canonical pointer to member function type. */
+/* Create and return a canonical pointer to member function type, for
+ TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
build_ptrmemfunc_type (type)
@@ -8438,7 +8857,7 @@ build_ptrmemfunc_type (type)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
u = make_lang_type (UNION_TYPE);
- IS_AGGR_TYPE (u) = 0;
+ SET_IS_AGGR_TYPE (u, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
delta_type_node);
@@ -8450,7 +8869,7 @@ build_ptrmemfunc_type (type)
/* Let the front-end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
/* ... and not really an aggregate. */
- IS_AGGR_TYPE (t) = 0;
+ SET_IS_AGGR_TYPE (t, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
delta_type_node);
@@ -8530,6 +8949,41 @@ build_ptrmemfunc_type (type)
enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
+/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
+ Check to see that the definition is valid. Issue appropriate error
+ messages. Return 1 if the definition is particularly bad, or 0
+ otherwise. */
+
+int
+check_static_variable_definition (decl, type)
+ tree decl;
+ tree type;
+{
+ /* Motion 10 at San Diego: If a static const integral data member is
+ initialized with an integral constant expression, the initializer
+ may appear either in the declaration (within the class), or in
+ the definition, but not both. If it appears in the class, the
+ member is a member constant. The file-scope definition is always
+ required. */
+ if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ cp_error ("in-class initialization of static data member of non-integral type `%T'",
+ type);
+ /* If we just return the declaration, crashes will sometimes
+ occur. We therefore return void_type_node, as if this was a
+ friend declaration, to cause callers to completely ignore
+ this declaration. */
+ return 1;
+ }
+ else if (!CP_TYPE_CONST_P (type))
+ cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+ decl);
+ else if (pedantic && !INTEGRAL_TYPE_P (type))
+ cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+
+ return 0;
+}
+
tree
grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declspecs;
@@ -8544,7 +8998,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
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;
@@ -8577,6 +9033,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
+ tree inner_attrs;
+ int ignore_attrs;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@@ -8598,6 +9056,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
decl = *next;
switch (TREE_CODE (decl))
{
+ case TREE_LIST:
+ /* For attributes. */
+ next = &TREE_VALUE (decl);
+ break;
+
case COND_EXPR:
ctype = NULL_TREE;
next = &TREE_OPERAND (decl, 0);
@@ -8665,10 +9128,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
init = TREE_OPERAND (decl, 1);
decl = start_decl (declarator, declspecs, 1, NULL_TREE, NULL_TREE);
- /* Look for __unused__ attribute */
- if (TREE_USED (TREE_TYPE (decl)))
- TREE_USED (decl) = 1;
- finish_decl (decl, init, NULL_TREE);
+ if (decl)
+ {
+ /* Look for __unused__ attribute */
+ if (TREE_USED (TREE_TYPE (decl)))
+ TREE_USED (decl) = 1;
+ finish_decl (decl, init, NULL_TREE);
+ }
+ else
+ cp_error ("invalid declarator");
return 0;
}
innermost_code = TREE_CODE (decl);
@@ -9045,24 +9513,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else
{
- if (funcdef_flag)
- {
- if (warn_return_type
- && return_type == return_normal)
- /* Save warning until we know what is really going on. */
- warn_about_return_type = 1;
- }
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
- pedwarn ("ANSI C++ forbids typedef which does not specify a type");
- else if (innermost_code != CALL_EXPR || pedantic
- || (warn_return_type && return_type == return_normal))
- {
- if (innermost_code == CALL_EXPR)
- cp_pedwarn ("return-type of `%D' defaults to `int'", dname);
- else
- cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
- dname);
- }
+ /* We handle `main' specially here, because 'main () { }' is so
+ common. With no options, it is allowed. With -Wreturn-type,
+ it is a warning. It is only an error with -pedantic-errors. */
+ int is_main = (funcdef_flag
+ && MAIN_NAME_P (dname)
+ && ctype == NULL_TREE
+ && in_namespace == NULL_TREE
+ && current_namespace == global_namespace);
+
+ if (in_system_header)
+ /* Allow it, sigh. */;
+ else if (pedantic || ! is_main)
+ cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
+ dname);
+ else if (warn_return_type)
+ cp_warning ("ANSI C++ forbids declaration `%D' with no type",
+ dname);
+
type = integer_type_node;
}
}
@@ -9078,7 +9546,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (return_type == return_conversion)
{
- if (comptypes (type, ctor_return_type, 1) == 0)
+ if (!same_type_p (type, ctor_return_type))
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
@@ -9099,8 +9567,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
RIDBIT_RESET (RID_LONG, specbits);
- type = build_type_variant (long_double_type_node, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
+ type = build_qualified_type (long_double_type_node,
+ CP_TYPE_QUALS (type));
}
/* Check all other uses of type modifiers. */
@@ -9222,17 +9690,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (return_type == return_conversion
&& (RIDBIT_SETP (RID_CONST, specbits)
- || RIDBIT_SETP (RID_VOLATILE, specbits)))
- cp_error ("`operator %T' cannot be cv-qualified",
+ || RIDBIT_SETP (RID_VOLATILE, specbits)
+ || RIDBIT_SETP (RID_RESTRICT, specbits)))
+ cp_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) + TYPE_READONLY (type);
- volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
- type = cp_build_type_variant (type, constp, 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);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
@@ -9252,6 +9727,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
friendp = RIDBIT_SETP (RID_FRIEND, specbits);
RIDBIT_RESET (RID_FRIEND, specbits);
+ /* $7.1.2, Function specifiers */
+ if (friendp && explicitp)
+ error ("only declarations of constructors can be `explicit'");
+
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (decl_context == PARM)
@@ -9309,16 +9788,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& IS_SIGNATURE (current_class_type)
&& RIDBIT_NOTSETP (RID_TYPEDEF, specbits))
{
- if (constp)
- {
- error ("`const' specified for signature member function `%s'", name);
- constp = 0;
- }
- if (volatilep)
+ if (type_quals != TYPE_UNQUALIFIED)
{
- error ("`volatile' specified for signature member function `%s'",
- name);
- volatilep = 0;
+ error ("type qualifiers specified for signature member function `%s'", name);
+ type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
@@ -9405,7 +9878,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
- if (! constp)
+ if (!(type_quals & TYPE_QUAL_CONST))
warning ("`%s' initialized and declared `extern'", name);
}
else
@@ -9427,6 +9900,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
+ inner_attrs = NULL_TREE;
+ ignore_attrs = 0;
+
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
@@ -9473,8 +9949,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
quals = NULL_TREE;
}
}
+
+ /* See the comment for the TREE_LIST case, below. */
+ if (ignore_attrs)
+ ignore_attrs = 0;
+ else if (inner_attrs)
+ {
+ decl_attributes (type, inner_attrs, NULL_TREE);
+ inner_attrs = NULL_TREE;
+ }
+
switch (TREE_CODE (declarator))
{
+ case TREE_LIST:
+ {
+ /* We encode a declarator with embedded attributes using
+ a TREE_LIST. The attributes apply to the declarator
+ directly inside them, so we have to skip an iteration
+ before applying them to the type. If the declarator just
+ inside is the declarator-id, we apply the attrs to the
+ decl itself. */
+ inner_attrs = TREE_PURPOSE (declarator);
+ ignore_attrs = 1;
+ declarator = TREE_VALUE (declarator);
+ }
+ break;
+
case ARRAY_REF:
{
register tree itype = NULL_TREE;
@@ -9528,6 +10028,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (size == error_mark_node)
type = error_mark_node;
+ else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
+ {
+ /* [dcl.array]
+
+ the constant expressions that specify the bounds of
+ the arrays can be omitted only for the first member
+ of the sequence. */
+ cp_error ("declaration of `%D' as multidimensional array",
+ dname);
+ cp_error ("must have bounds for all dimensions except the first");
+ type = error_mark_node;
+ }
if (type == error_mark_node)
continue;
@@ -9546,10 +10058,25 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
size = TREE_OPERAND (size, 0);
- /* If this involves a template parameter, it'll be
- constant, but we don't know what the value is yet. */
+ /* If this involves a template parameter, it will be a
+ constant at instantiation time, but we don't know
+ what the value is yet. Even if no template
+ parameters are involved, we may an expression that
+ is not a constant; we don't even simplify `1 + 2'
+ when processing a template. */
if (processing_template_decl)
{
+ /* Resolve a qualified reference to an enumerator or
+ static const data member of ours. */
+ if (TREE_CODE (size) == SCOPE_REF
+ && TREE_OPERAND (size, 0) == current_class_type)
+ {
+ tree t = lookup_field (current_class_type,
+ TREE_OPERAND (size, 1), 0, 0);
+ if (t)
+ size = t;
+ }
+
itype = make_node (INTEGER_TYPE);
TYPE_MIN_VALUE (itype) = size_zero_node;
TYPE_MAX_VALUE (itype) = build_min
@@ -9558,7 +10085,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
+ && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
cp_error ("size of array `%D' has non-integer type",
dname);
@@ -9641,9 +10169,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
- /* We now know that constp and volatilep don't apply to the
+ /* We now know that the TYPE_QUALS don't apply to the
decl, but to its return type. */
- constp = volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
/* Warn about some types functions can't return. */
@@ -9851,9 +10379,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Merge any constancy or volatility into the target type
for the pointer. */
- /* We now know that constp and volatilep don't apply to the
- decl, but to the target of the pointer. */
- constp = volatilep = 0;
+ /* We now know that the TYPE_QUALS don't apply to the decl,
+ but to the target of the pointer. */
+ type_quals = TYPE_UNQUALIFIED;
if (IS_SIGNATURE (type))
{
@@ -9878,8 +10406,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type);
type = build_signature_pointer_type (type);
}
- constp = 0;
- volatilep = 0;
}
else if (TREE_CODE (declarator) == ADDR_EXPR)
{
@@ -9889,9 +10415,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
- {
- type = build_ptrmemfunc_type (build_pointer_type (type));
- }
+ type = build_ptrmemfunc_type (build_pointer_type (type));
else
type = build_pointer_type (type);
@@ -9902,25 +10426,37 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
register tree typemodlist;
int erred = 0;
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
- if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+ tree qualifier = TREE_VALUE (typemodlist);
+
+ if (qualifier == ridpointers[(int) RID_CONST])
constp++;
- else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+ else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++;
+ else if (qualifier == ridpointers[(int) RID_RESTRICT])
+ restrictp++;
else if (!erred)
{
erred = 1;
- error ("invalid type modifier within %s declarator",
- TREE_CODE (declarator) == ADDR_EXPR
- ? "reference" : "pointer");
+ error ("invalid type modifier within pointer declarator");
}
}
if (constp > 1)
pedwarn ("duplicate `const'");
if (volatilep > 1)
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))
{
@@ -9928,9 +10464,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
pedwarn ("discarding `const' applied to a reference");
if (volatilep)
pedwarn ("discarding `volatile' applied to a reference");
- constp = volatilep = 0;
+ type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
- type = cp_build_type_variant (type, constp, volatilep);
+ type = cp_build_qualified_type (type, type_quals);
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
@@ -9974,7 +10510,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
- type = tsubst (type, args, NULL_TREE);
+ type = tsubst (type, args, /*complain=*/1, NULL_TREE);
}
/* This pop_nested_class corresponds to the
@@ -9999,7 +10535,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype = TREE_OPERAND (declarator, 0);
t = ctype;
- while (t != NULL_TREE)
+ while (t != NULL_TREE && CLASS_TYPE_P (t))
{
if (CLASSTYPE_TEMPLATE_INFO (t) &&
!CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
@@ -10115,6 +10651,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
+ /* See the comment for the TREE_LIST case, above. */
+ if (inner_attrs)
+ {
+ if (! ignore_attrs)
+ decl_attributes (type, inner_attrs, NULL_TREE);
+ else if (attrlist)
+ TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
+ else
+ attrlist = build_decl_list (NULL_TREE, inner_attrs);
+ }
+
if (explicitp == 1)
{
error ("only constructors can be declared `explicit'");
@@ -10127,7 +10674,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
- if (constp)
+ if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
@@ -10139,6 +10686,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
+ if (declarator == NULL_TREE
+ || TREE_CODE (declarator) == IDENTIFIER_NODE
+ || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
+ && (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)))
+ /* OK */;
+ else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ {
+ cp_error ("template-id `%D' used as a declarator", declarator);
+ declarator = dname;
+ }
+ else
+ my_friendly_abort (990210);
+
if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
{
tree decl;
@@ -10150,7 +10711,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (decl_context == FIELD)
{
- if (declarator == current_class_name)
+ if (declarator == constructor_name (current_class_type))
cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type);
@@ -10193,6 +10754,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
+ /* If this is a typedef within a template class, the nested
+ type is a (non-primary) template. The name for the
+ template needs updating as well. */
+ if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type))
+ DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
+ = TYPE_IDENTIFIER (type);
+
/* XXX Temporarily set the scope.
When returning, start_decl expects it as NULL_TREE,
and will then then set it using pushdecl. */
@@ -10264,19 +10832,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* Note that the grammar rejects storage classes
in typenames, fields or parameters. */
- if (constp || volatilep)
+ if (type_quals != TYPE_UNQUALIFIED)
{
if (IS_SIGNATURE (type))
- error ("`const' or `volatile' specified with signature type");
+ error ("type qualifiers specified for signature type");
+ type_quals = TYPE_UNQUALIFIED;
}
/* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp)
{
- if (volatilep)
+ if (type_quals != TYPE_UNQUALIFIED)
{
- cp_error ("`volatile' specified for friend class declaration");
- volatilep = 0;
+ cp_error ("type qualifiers specified for friend class declaration");
+ type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
@@ -10356,7 +10925,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* Transfer const-ness of array into that of type pointed to. */
type = build_pointer_type (TREE_TYPE (type));
- volatilep = constp = 0;
+ type_quals = TYPE_UNQUALIFIED;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (type);
@@ -10374,7 +10943,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (decl_context == PARM)
{
- decl = build_decl (PARM_DECL, declarator, complete_type (type));
+ decl = build_decl (PARM_DECL, declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10404,7 +10973,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
are error_mark_node, for example. */
decl = NULL_TREE;
}
- else if (in_namespace)
+ else if (in_namespace && !friendp)
{
/* Something like struct S { int N::j; }; */
cp_error ("invalid use of `::'");
@@ -10474,7 +11043,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
virtualp, flags, quals, raises, attrlist,
friendp ? -1 : 0, friendp, publicp, inlinep,
funcdef_flag, template_count, in_namespace);
- if (decl == NULL_TREE || decl == error_mark_node)
+ if (decl == NULL_TREE)
return decl;
#if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */
@@ -10482,8 +11051,37 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
decl = build_decl_attribute_variant (decl, decl_machine_attr);
#endif
+ /* [class.conv.ctor]
+
+ A constructor declared without the function-specifier
+ explicit that can be called with a single parameter
+ specifies a conversion from the type of its first
+ parameter to the type of its class. Such a constructor
+ is called a converting constructor. */
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
+ else if (DECL_CONSTRUCTOR_P (decl))
+ {
+ /* The constructor can be called with exactly one
+ parameter if there is at least one parameter, and
+ any subsequent parameters have default arguments.
+ We don't look at the first parameter, which is
+ really just the `this' parameter for the new
+ object. */
+ tree arg_types =
+ TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)));
+
+ /* Skip the `in_chrg' argument too, if present. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (decl)))
+ arg_types = TREE_CHAIN (arg_types);
+
+ if (arg_types == void_list_node
+ || (arg_types
+ && TREE_CHAIN (arg_types)
+ && TREE_CHAIN (arg_types) != void_list_node
+ && !TREE_PURPOSE (TREE_CHAIN (arg_types))))
+ DECL_NONCONVERTING_P (decl) = 1;
+ }
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
@@ -10582,47 +11180,36 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
the rest of the compiler does not correctly
handle the initialization unless the member is
static so we make it static below. */
- cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
- constp ? "const member" : "member",
+ cp_pedwarn ("ANSI C++ forbids initialization of member `%D'",
declarator);
cp_pedwarn ("making `%D' static", declarator);
staticp = 1;
}
- /* Motion 10 at San Diego: If a static const integral data
- member is initialized with an integral constant
- expression, the initializer may appear either in the
- declaration (within the class), or in the definition,
- but not both. If it appears in the class, the member is
- a member constant. The file-scope definition is always
- required. */
- if (CLASS_TYPE_P (type)
- || TREE_CODE (type) == REFERENCE_TYPE)
- {
- cp_error ("in-class initialization of static data member of non-integral type `%T'",
- type);
- /* If we just return the declaration, crashes will
- sometimes occur. We therefore return
- void_type_node, as if this was a friend
- declaration, to cause callers to completely
- ignore this declaration. */
- return void_type_node;
- }
- else if (!constp)
- cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
- declarator);
- else if (pedantic && ! INTEGRAL_TYPE_P (type)
- && !uses_template_parms (type))
- cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", declarator, type);
+ if (uses_template_parms (type))
+ /* We'll check at instantiation time. */
+ ;
+ else if (check_static_variable_definition (declarator,
+ type))
+ /* If we just return the declaration, crashes
+ will sometimes occur. We therefore return
+ void_type_node, as if this was a friend
+ declaration, to cause callers to completely
+ ignore this declaration. */
+ return void_type_node;
}
+ /* 9.2p13 [class.mem] */
+ if (declarator == constructor_name (current_class_type)
+ /* Divergence from the standard: In extern "C", we
+ allow non-static data members here, because C does
+ and /usr/include/netinet/in.h uses that. */
+ && (staticp || ! in_system_header))
+ cp_pedwarn ("ANSI C++ forbids data member `%D' with same name as enclosing class",
+ declarator);
+
if (staticp)
{
- /* ANSI C++ Apr '95 wp 9.2 */
- if (declarator == current_class_name)
- cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class",
- declarator);
-
/* C++ allows static class members.
All other work for this is done by grokfield.
This VAR_DCL is built by build_lang_field_decl.
@@ -10685,18 +11272,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
error ("virtual non-class function `%s'", name);
virtualp = 0;
}
-
- if (current_lang_name == lang_name_cplusplus
- && ! processing_template_decl
- && ! MAIN_NAME_P (original_name)
- && ! (IDENTIFIER_LENGTH (original_name) > 10
- && IDENTIFIER_POINTER (original_name)[0] == '_'
- && IDENTIFIER_POINTER (original_name)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
- /* Plain overloading: will not be grok'd by grokclassfn. */
- if (name_mangling_version < 1
- || TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
- declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
type = build_cplus_method_type (ctype, TREE_TYPE (type),
@@ -10715,16 +11290,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (decl == NULL_TREE)
return NULL_TREE;
- /* Among other times, could occur from check_explicit_specialization
- returning an error_mark_node. */
- if (decl == error_mark_node)
- return error_mark_node;
-
- if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
- && (! DECL_USE_TEMPLATE (decl) ||
- name_mangling_version < 1))
- DECL_ASSEMBLER_NAME (decl) = declarator;
-
if (staticp == 1)
{
int illegal_static = 0;
@@ -10756,7 +11321,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* An uninitialized decl with `extern' is a reference. */
decl = grokvardecl (type, declarator, &specbits,
- initialized, constp, in_namespace);
+ initialized,
+ (type_quals & TYPE_QUAL_CONST) != 0,
+ in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10801,14 +11368,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. */
-
- if (constp)
- TREE_READONLY (decl) = TREE_CODE (type) != REFERENCE_TYPE;
- if (volatilep)
- {
- TREE_SIDE_EFFECTS (decl) = 1;
- TREE_THIS_VOLATILE (decl) = 1;
- }
+ /* FIXME: Disallow `restrict' pointer-to-member declarations. */
+ c_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
@@ -10841,18 +11402,14 @@ parmlist_is_exprlist (exprs)
return 1;
}
-/* Subroutine of `grokparms'. In a fcn definition, arg types must
- be complete.
-
- C++: also subroutine of `start_function'. */
+/* Subroutine of start_function. Ensure that each of the parameter
+ types (as listed in PARMS) is complete, as is required for a
+ function definition. */
static void
require_complete_types_for_parms (parms)
tree parms;
{
- if (processing_template_decl)
- return;
-
while (parms)
{
tree type = TREE_TYPE (parms);
@@ -10865,35 +11422,110 @@ require_complete_types_for_parms (parms)
error ("parameter has incomplete type");
TREE_TYPE (parms) = error_mark_node;
}
-#if 0
- /* If the arg types are incomplete in a declaration,
- they must include undefined tags.
- These tags can never be defined in the scope of the declaration,
- so the types can never be completed,
- and no call can be compiled successfully. */
- /* This is not the right behavior for C++, but not having
- it is also probably wrong. */
else
- {
- /* Now warn if is a pointer to an incomplete type. */
- while (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- type = TYPE_MAIN_VARIANT (type);
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- if (DECL_NAME (parm) != NULL_TREE)
- warning ("parameter `%s' points to incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- else
- warning ("parameter points to incomplete type");
- }
- }
-#endif
+ layout_decl (parms, 0);
+
parms = TREE_CHAIN (parms);
}
}
+/* Returns DECL if DECL is a local variable (or parameter). Returns
+ NULL_TREE otherwise. */
+
+static tree
+local_variable_p (t)
+ tree t;
+{
+ if ((TREE_CODE (t) == VAR_DECL
+ /* A VAR_DECL with a context that is a _TYPE is a static data
+ member. */
+ && !TYPE_P (CP_DECL_CONTEXT (t))
+ /* Any other non-local variable must be at namespace scope. */
+ && TREE_CODE (CP_DECL_CONTEXT (t)) != NAMESPACE_DECL)
+ || (TREE_CODE (t) == PARM_DECL))
+ return t;
+
+ return NULL_TREE;
+}
+
+/* Check that ARG, which is a default-argument expression for a
+ parameter DECL, is legal. Returns ARG, or ERROR_MARK_NODE, if
+ something goes wrong. DECL may also be a _TYPE node, rather than a
+ DECL, if there is no DECL available. */
+
+tree
+check_default_argument (decl, arg)
+ tree decl;
+ tree arg;
+{
+ tree var;
+ tree decl_type;
+
+ if (TREE_CODE (arg) == DEFAULT_ARG)
+ /* We get a DEFAULT_ARG when looking at an in-class declaration
+ with a default argument. Ignore the argument for now; we'll
+ deal with it after the class is complete. */
+ return arg;
+
+ if (processing_template_decl || uses_template_parms (arg))
+ /* We don't do anything checking until instantiation-time. Note
+ that there may be uninstantiated arguments even for an
+ instantiated function, since default arguments are not
+ instantiated until they are needed. */
+ return arg;
+
+ if (TYPE_P (decl))
+ {
+ decl_type = decl;
+ decl = NULL_TREE;
+ }
+ else
+ decl_type = TREE_TYPE (decl);
+
+ if (arg == error_mark_node
+ || decl == error_mark_node
+ || TREE_TYPE (arg) == error_mark_node
+ || decl_type == error_mark_node)
+ /* Something already went wrong. There's no need to check
+ further. */
+ return error_mark_node;
+
+ /* [dcl.fct.default]
+
+ A default argument expression is implicitly converted to the
+ parameter type. */
+ if (!TREE_TYPE (arg)
+ || !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
+ {
+ if (decl)
+ cp_error ("default argument for `%#D' has type `%T'",
+ decl, TREE_TYPE (arg));
+ else
+ cp_error ("default argument for paramter of type `%T' has type `%T'",
+ decl_type, TREE_TYPE (arg));
+
+ return error_mark_node;
+ }
+
+ /* [dcl.fct.default]
+
+ Local variables shall not be used in default argument
+ expressions.
+
+ The keyword `this' shall not be used in a default argument of a
+ member function. */
+ var = search_tree (arg, local_variable_p);
+ if (var)
+ {
+ cp_error ("default argument `%E' uses local variable `%D'",
+ arg, var);
+ return error_mark_node;
+ }
+
+ /* All is well. */
+ return arg;
+}
+
/* Decode the list of parameter types for a function type.
Given the list of things declared inside the parens,
return a list of types.
@@ -10986,7 +11618,7 @@ grokparms (first_parm, funcdef_flag)
TREE_PURPOSE (decl),
PARM, init != NULL_TREE,
NULL_TREE);
- if (! decl)
+ if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
/* Top-level qualifiers on the parameters are
@@ -11071,43 +11703,10 @@ grokparms (first_parm, funcdef_flag)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
#endif
- if (!any_error)
+ if (!any_error && init)
{
- if (init)
- {
- any_init++;
- if (TREE_CODE (init) == SAVE_EXPR)
- PARM_DECL_EXPR (init) = 1;
- else if (processing_template_decl)
- ;
- /* Unparsed default arg from in-class decl. */
- else if (TREE_CODE (init) == DEFAULT_ARG)
- ;
- else if (TREE_CODE (init) == VAR_DECL
- || TREE_CODE (init) == PARM_DECL)
- {
- if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
- {
- /* ``Local variables may not be used in default
- argument expressions.'' dpANSI C++ 8.2.6 */
- /* If extern int i; within a function is not
- considered a local variable, then this code is
- wrong. */
- cp_error ("local variable `%D' may not be used as a default argument", init);
- any_error = 1;
- }
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- }
- else
- init = require_instantiated_type (type, init, integer_zero_node);
- if (! processing_template_decl
- && init != error_mark_node
- && TREE_CODE (init) != DEFAULT_ARG
- && ! can_convert_arg (type, TREE_TYPE (init), init))
- cp_pedwarn ("invalid type `%T' for default argument to `%#D'",
- TREE_TYPE (init), decl);
- }
+ any_init++;
+ init = check_default_argument (decl, init);
}
else
init = NULL_TREE;
@@ -11152,10 +11751,6 @@ grokparms (first_parm, funcdef_flag)
last_function_parms = decls;
- /* In a fcn definition, arg types must be complete. */
- if (funcdef_flag > 0)
- require_complete_types_for_parms (last_function_parms);
-
return result;
}
@@ -11220,19 +11815,45 @@ grok_ctor_properties (ctype, decl)
parmtype = TREE_VALUE (parmtypes);
}
+ /* [class.copy]
+
+ A non-template constructor for class X is a copy constructor if
+ its first parameter is of type X&, const X&, volatile X& or const
+ volatile X&, and either there are no other parameters or else all
+ other parameters have default arguments. */
if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
TYPE_HAS_INIT_REF (ctype) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
+ if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_INIT_REF (ctype) = 1;
}
+ /* [class.copy]
+
+ A declaration of a constructor for a class X is ill-formed if its
+ first parameter is of type (optionally cv-qualified) X and either
+ there are no other parameters or else all other parameters have
+ default arguments.
+
+ We *don't* complain about member template instantiations that
+ have this form, though; they can occur as we try to decide what
+ constructor to use during overload resolution. Since overload
+ resolution will never prefer such a constructor to the
+ non-template copy constructor (which is either explicitly or
+ implicitly defined), there's no need to worry about their
+ existence. Theoretically, they should never even be
+ instantiated, but that's hard to forestall. */
else if (TYPE_MAIN_VARIANT (parmtype) == ctype
- && TREE_CHAIN (parmtypes) != NULL_TREE
- && TREE_CHAIN (parmtypes) == void_list_node)
+ && (TREE_CHAIN (parmtypes) == NULL_TREE
+ || TREE_CHAIN (parmtypes) == void_list_node
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
@@ -11269,7 +11890,7 @@ unary_op_p (name)
return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
|| name == ansi_opname [(int) BIT_NOT_EXPR]
|| name == ansi_opname [(int) COMPONENT_REF]
- || OPERATOR_TYPENAME_P (name));
+ || IDENTIFIER_TYPENAME_P (name));
}
/* Do a little sanity-checking on how they declared their operator. */
@@ -11288,8 +11909,16 @@ grok_op_properties (decl, virtualp, friendp)
if (! friendp)
{
- if (name == ansi_opname[(int) MODIFY_EXPR])
- TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
+ /* [class.copy]
+
+ A user-declared copy assignment operator X::operator= is a
+ non-static non-template member function of class X with
+ exactly one parameter of type X, X&, const X&, volatile X& or
+ const volatile X&. */
+ if (name == ansi_opname[(int) MODIFY_EXPR]
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
+ ;
else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
else if (name == ansi_opname[(int) ARRAY_REF])
@@ -11352,7 +11981,7 @@ grok_op_properties (decl, virtualp, friendp)
an enumeration, or a reference to an enumeration. 13.4.0.6 */
if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
- if (OPERATOR_TYPENAME_P (name)
+ if (IDENTIFIER_TYPENAME_P (name)
|| name == ansi_opname[(int) CALL_EXPR]
|| name == ansi_opname[(int) MODIFY_EXPR]
|| name == ansi_opname[(int) COMPONENT_REF]
@@ -11398,7 +12027,7 @@ grok_op_properties (decl, virtualp, friendp)
else if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
- char *what = 0;
+ const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
@@ -11432,7 +12061,7 @@ grok_op_properties (decl, virtualp, friendp)
{
TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
if (TREE_CODE (parmtype) != REFERENCE_TYPE
- || TYPE_READONLY (TREE_TYPE (parmtype)))
+ || CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
}
}
@@ -11452,7 +12081,7 @@ grok_op_properties (decl, virtualp, friendp)
if ((name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR])
&& ! processing_template_decl
- && TREE_VALUE (TREE_CHAIN (argtypes)) != integer_type_node)
+ && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
cp_error ("postfix `%D' must take `int' as its argument",
@@ -11484,14 +12113,14 @@ grok_op_properties (decl, virtualp, friendp)
if (list_length (argtypes) == 2)
{
if (TREE_CODE (ret) != REFERENCE_TYPE
- || !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
- arg, 1))
+ || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
+ arg))
cp_warning ("prefix `%D' should return `%T'", decl,
build_reference_type (arg));
}
else
{
- if (!comptypes (TYPE_MAIN_VARIANT (ret), arg, 1))
+ if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
cp_warning ("postfix `%D' should return `%T'", decl, arg);
}
}
@@ -11553,6 +12182,27 @@ grok_op_properties (decl, virtualp, friendp)
}
}
+static const char *
+tag_name (code)
+ enum tag_types code;
+{
+ switch (code)
+ {
+ case record_type:
+ return "struct";
+ case class_type:
+ return "class";
+ case union_type:
+ return "union ";
+ case enum_type:
+ return "enum";
+ case signature_type:
+ return "signature";
+ default:
+ my_friendly_abort (981122);
+ }
+}
+
/* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
@@ -11622,19 +12272,9 @@ xref_tag (code_type_node, name, globalize)
if (! globalize)
{
- if (t && (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM))
- {
- cp_error ("redeclaration of template type-parameter `%T'", name);
- cp_error_at (" previously declared here `%#D'",
- TEMPLATE_TYPE_DECL (t));
- }
- if (t && TYPE_CONTEXT (t) && got_type)
- ref = t;
- else
- /* If we know we are defining this tag, only look it up in
- this scope and don't try to find it as a type. */
- ref = lookup_tag (code, name, b, 1);
+ /* If we know we are defining this tag, only look it up in
+ this scope and don't try to find it as a type. */
+ ref = lookup_tag (code, name, b, 1);
}
else
{
@@ -11667,7 +12307,12 @@ xref_tag (code_type_node, name, globalize)
else
{
if (t)
- ref = t;
+ {
+ if (t != TYPE_MAIN_VARIANT (t))
+ cp_pedwarn ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (t), tag_name (tag_code));
+ ref = t;
+ }
else
ref = lookup_tag (code, name, b, 0);
@@ -11825,6 +12470,12 @@ xref_tag_from_type (old, id, globalize)
return xref_tag (code_type_node, id, globalize);
}
+/* REF is a type (named NAME), for which we have just seen some
+ baseclasses. BINFO is a list of those baseclasses; the
+ TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
+ the base-class. CODE_TYPE_NODE indicates whether REF is a class,
+ struct, or union. */
+
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
@@ -11834,6 +12485,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
/* In the declaration `A : X, Y, ... Z' we mark all the types
(A, X, Y, ..., Z) so we can check for duplicates. */
tree binfos;
+ tree base;
+
int i, len;
enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
@@ -11846,6 +12499,13 @@ xref_basetypes (code_type_node, name, ref, binfo)
len = list_length (binfo);
push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
+ /* First, make sure that any templates in base-classes are
+ instantiated. This ensures that if we call ourselves recursively
+ we do not get confused about which classes are marked and which
+ are not. */
+ for (base = binfo; base; base = TREE_CHAIN (base))
+ complete_type (TREE_VALUE (base));
+
SET_CLASSTYPE_MARKED (ref);
BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
@@ -11884,16 +12544,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
-#if 1
/* This code replaces similar code in layout_basetypes.
We put the complete_type first for implicit `typename'. */
- if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
+ if (TYPE_SIZE (basetype) == NULL_TREE
&& ! (current_template_parms && uses_template_parms (basetype)))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
}
-#endif
else
{
if (CLASSTYPE_MARKED (basetype))
@@ -11917,9 +12575,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
individual inheritance contains flags which say what
the `accessibility' of that particular inheritance is.) */
- base_binfo = make_binfo (integer_zero_node, basetype,
- TYPE_BINFO_VTABLE (basetype),
- TYPE_BINFO_VIRTUALS (basetype));
+ base_binfo
+ = make_binfo (integer_zero_node, basetype,
+ CLASS_TYPE_P (basetype)
+ ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
+ CLASS_TYPE_P (basetype)
+ ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
TREE_VEC_ELT (binfos, i) = base_binfo;
TREE_VIA_PUBLIC (base_binfo) = via_public;
@@ -11941,8 +12602,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
- TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
- TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ if (CLASS_TYPE_P (basetype))
+ {
+ TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ }
+
i += 1;
}
}
@@ -11954,8 +12619,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
if (i > 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
else if (i == 1)
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
+ {
+ tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, 0));
+
+ if (CLASS_TYPE_P (basetype))
+ TYPE_USES_MULTIPLE_INHERITANCE (ref)
+ = TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+ }
+
if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
@@ -11964,6 +12635,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
+ /* Now that we know all the base-classes, set up the list of virtual
+ bases. */
+ CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref);
+
pop_obstacks ();
}
@@ -11983,11 +12658,7 @@ start_enum (name)
/* We are wasting space here and putting these on the permanent_obstack so
that typeid(local enum) will work correctly. */
-#if 0
- if (processing_template_decl && current_function_decl)
-#endif
-
- end_temporary_allocation ();
+ push_obstacks (&permanent_obstack, &permanent_obstack);
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
@@ -12089,61 +12760,58 @@ finish_enum (enumtype)
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
- {
- add_tree (build_min (TAG_DEFN, enumtype));
- resume_temporary_allocation ();
- }
- return enumtype;
+ add_tree (build_min (TAG_DEFN, enumtype));
}
+ else
+ {
+ int unsignedp = tree_int_cst_sgn (minnode) >= 0;
+ int lowprec = min_precision (minnode, unsignedp);
+ int highprec = min_precision (maxnode, unsignedp);
+ int precision = MAX (lowprec, highprec);
+ tree tem;
- {
- int unsignedp = tree_int_cst_sgn (minnode) >= 0;
- int lowprec = min_precision (minnode, unsignedp);
- int highprec = min_precision (maxnode, unsignedp);
- int precision = MAX (lowprec, highprec);
-
- TYPE_SIZE (enumtype) = NULL_TREE;
-
- /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
+ TYPE_SIZE (enumtype) = NULL_TREE;
- TYPE_PRECISION (enumtype) = precision;
- if (unsignedp)
- fixup_unsigned_type (enumtype);
- else
- fixup_signed_type (enumtype);
+ /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
- if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
- /* Use the width of the narrowest normal C type which is wide enough. */
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
- (precision, 1));
- else
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+ TYPE_PRECISION (enumtype) = precision;
+ if (unsignedp)
+ fixup_unsigned_type (enumtype);
+ else
+ fixup_signed_type (enumtype);
- TYPE_SIZE (enumtype) = 0;
- layout_type (enumtype);
- }
+ if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
+ /* Use the width of the narrowest normal C type which is wide
+ enough. */
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
+ (precision, 1));
+ else
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
- {
- register tree tem;
+ TYPE_SIZE (enumtype) = 0;
+ layout_type (enumtype);
- /* Fix up all variant types of this enum type. */
- for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
- tem = TYPE_NEXT_VARIANT (tem))
- {
- TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
- TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
- TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
- TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
- TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
- TYPE_MODE (tem) = TYPE_MODE (enumtype);
- TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
- TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
- TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
- }
- }
+ /* Fix up all variant types of this enum type. */
+ for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
+ tem = TYPE_NEXT_VARIANT (tem))
+ {
+ TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
+ TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
+ TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
+ TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+ TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
+ TYPE_MODE (tem) = TYPE_MODE (enumtype);
+ TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
+ TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+ TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+ }
- /* Finish debugging output for this type. */
- rest_of_type_compilation (enumtype, namespace_bindings_p ());
+ /* Finish debugging output for this type. */
+ rest_of_type_compilation (enumtype, namespace_bindings_p ());
+ }
+
+ /* In start_enum we pushed obstacks. Here, we must pop them. */
+ pop_obstacks ();
return enumtype;
}
@@ -12257,6 +12925,15 @@ static int function_depth;
they describe the function's name and the type it returns,
but twisted together in a fashion that parallels the syntax of C.
+ If PRE_PARSED_P is non-zero then DECLARATOR is really the DECL for
+ the function we are about to process; DECLSPECS are ignored. For
+ example, we set PRE_PARSED_P when processing the definition of
+ inline function that was defined in-class; the definition is
+ actually processed when the class is complete. In this case,
+ PRE_PARSED_P is 2. We also set PRE_PARSED_P when instanting the
+ body of a template function, and when constructing thunk functions
+ and such; in these cases PRE_PARSED_P is 1.
+
This function creates a binding context for the function body
as well as setting up the FUNCTION_DECL in current_function_decl.
@@ -12293,7 +12970,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
/* Assume, until we see it does. */
current_function_returns_value = 0;
current_function_returns_null = 0;
- warn_about_return_type = 0;
named_labels = 0;
shadowed_labels = 0;
current_function_assigns_this = 0;
@@ -12358,17 +13034,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
doing_friend = 1;
}
- /* In a fcn definition, arg types must be complete. */
- require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
-
- /* In case some arg types were completed since the declaration was
- parsed, fix up the decls. */
- {
- tree t = DECL_ARGUMENTS (decl1);
- for (; t; t = TREE_CHAIN (t))
- layout_decl (t, 0);
- }
-
last_function_parms = DECL_ARGUMENTS (decl1);
last_function_parm_tags = NULL_TREE;
}
@@ -12382,8 +13047,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
fntype = TREE_TYPE (decl1);
restype = TREE_TYPE (fntype);
- if (IS_AGGR_TYPE (restype) && ! TYPE_PTRMEMFUNC_P (restype)
- && ! CLASSTYPE_GOT_SEMICOLON (restype))
+ if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
{
cp_error ("semicolon missing after declaration of `%#T'", restype);
shadow_tag (build_expr_list (NULL_TREE, restype));
@@ -12409,7 +13073,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
pedwarn ("return type for `main' changed to `int'");
TREE_TYPE (decl1) = fntype = default_function_type;
}
- warn_about_return_type = 0;
}
}
@@ -12419,16 +13082,37 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
+ announce_function (decl1);
+
+ /* Set up current_class_type, and enter the scope of the class, if
+ appropriate. */
+ if (ctype)
+ push_nested_class (ctype, 1);
+ else if (DECL_STATIC_FUNCTION_P (decl1))
+ push_nested_class (DECL_CONTEXT (decl1), 2);
+
+ /* Now that we have entered the scope of the class, we must restore
+ the bindings for any template parameters surrounding DECL1, if it
+ is an inline member template. (Order is important; consider the
+ case where a template parameter has the same name as a field of
+ the class.) It is not until after this point that
+ PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly. */
+ if (pre_parsed_p == 2)
+ maybe_begin_member_template_processing (decl1);
+
+ /* We are now in the scope of the function being defined. */
current_function_decl = decl1;
+
/* Save the parm names or decls from this function's declarator
where store_parm_decls will find them. */
current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags;
- announce_function (decl1);
-
if (! processing_template_decl)
{
+ /* In a function definition, arg types must be complete. */
+ require_complete_types_for_parms (current_function_parms);
+
if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
{
cp_error ("return-type `%#T' is an incomplete type",
@@ -12449,8 +13133,10 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
TYPE_ARG_TYPES (TREE_TYPE (decl1)));
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
- TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype));
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype));
+ TREE_READONLY (DECL_RESULT (decl1))
+ = CP_TYPE_CONST_P (TREE_TYPE (fntype));
+ TREE_THIS_VOLATILE (DECL_RESULT (decl1))
+ = CP_TYPE_VOLATILE_P (TREE_TYPE (fntype));
}
if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
@@ -12458,9 +13144,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
- if (warn_about_return_type)
- pedwarn ("return-type defaults to `int'");
-
/* Effective C++ rule 15. See also c_expand_return. */
if (warn_ecpp
&& DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
@@ -12472,20 +13155,13 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
DECL_INITIAL (decl1) = error_mark_node;
#ifdef SET_DEFAULT_DECL_ATTRIBUTES
- SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
+ SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
#endif
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
- /* Set up current_class_type, and enter the scope of the class, if
- appropriate. */
- if (ctype)
- push_nested_class (ctype, 1);
- else if (DECL_STATIC_FUNCTION_P (decl1))
- push_nested_class (DECL_CONTEXT (decl1), 2);
-
/* We must call push_template_decl after current_class_type is set
up. (If we are processing inline definitions after exiting a
class scope, current_class_type will be NULL_TREE until set above
@@ -12532,21 +13208,40 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
}
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
- It doesn't matter whether it's inline or not. */
+ This only affects inlines and template instantiations. */
else if (interface_unknown == 0
&& (! DECL_TEMPLATE_INSTANTIATION (decl1)
|| flag_alt_external_templates))
{
if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
- DECL_EXTERNAL (decl1)
- = (interface_only
- || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
+ {
+ DECL_EXTERNAL (decl1)
+ = (interface_only
+ || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
+
+ /* For WIN32 we also want to put these in linkonce sections. */
+ maybe_make_one_only (decl1);
+ }
else
DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
+ else if (interface_unknown && interface_only
+ && (! DECL_TEMPLATE_INSTANTIATION (decl1)
+ || flag_alt_external_templates))
+ {
+ /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
+ interface, we will have interface_only set but not
+ interface_known. In that case, we don't want to use the normal
+ heuristics because someone will supply a #pragma implementation
+ elsewhere, and deducing it here would produce a conflict. */
+ comdat_linkage (decl1);
+ DECL_EXTERNAL (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ DECL_DEFER_OUTPUT (decl1) = 1;
+ }
else
{
/* This is a definition, not a reference.
@@ -12592,13 +13287,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
{
- int i = suspend_momentary ();
+ int i;
+
+ if (! hack_decl_function_context (decl1))
+ temporary_allocation ();
+ i = suspend_momentary ();
- /* Fool build_indirect_ref. */
+ /* Normally, build_indirect_ref returns
+ current_class_ref whenever current_class_ptr is
+ dereferenced. This time, however, we want it to
+ *create* current_class_ref, so we temporarily clear
+ current_class_ptr to fool it. */
current_class_ptr = NULL_TREE;
current_class_ref = build_indirect_ref (t, NULL_PTR);
current_class_ptr = t;
+
resume_momentary (i);
+ if (! hack_decl_function_context (decl1))
+ end_temporary_allocation ();
}
else
/* We're having a signature pointer here. */
@@ -12607,9 +13313,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
}
}
else
- {
- current_class_ptr = current_class_ref = NULL_TREE;
- }
+ current_class_ptr = current_class_ref = NULL_TREE;
pushlevel (0);
current_binding_level->parm_flag = 1;
@@ -12634,8 +13338,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
{
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (restype);
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype);
+ TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype);
+ TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype);
}
/* Allocate further tree nodes temporarily during compilation
@@ -12712,9 +13416,6 @@ store_parm_decls ()
/* Initialize RTL machinery. */
init_function_start (fndecl, input_filename, lineno);
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
- declare_function_name ();
-
/* Create a binding level for the parms. */
expand_start_bindings (0);
@@ -12800,8 +13501,11 @@ store_parm_decls ()
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
+ /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
+ declare_function_name ();
+
/* Initialize the RTL code for the function. */
- DECL_SAVED_INSNS (fndecl) = 0;
+ DECL_SAVED_INSNS (fndecl) = NULL_RTX;
if (! processing_template_decl)
expand_function_start (fndecl, parms_have_cleanups);
@@ -12910,26 +13614,34 @@ store_return_init (return_id, init)
This is called after parsing the body of the function definition.
LINENO is the current line number.
- C++: CALL_POPLEVEL is non-zero if an extra call to poplevel
- (and expand_end_bindings) must be made to take care of the binding
- contour for the base initializers. This is only relevant for
- constructors.
+ FLAGS is a bitwise or of the following values:
+ 1 - CALL_POPLEVEL
+ An extra call to poplevel (and expand_end_bindings) must be
+ made to take care of the binding contour for the base
+ initializers. This is only relevant for constructors.
+ 2 - INCLASS_INLINE
+ We just finished processing the body of an in-class inline
+ function definition. (This processing will have taken place
+ after the class definition is complete.)
NESTED is nonzero if we were in the middle of compiling another function
when we started on this one. */
void
-finish_function (lineno, call_poplevel, nested)
+finish_function (lineno, flags, nested)
int lineno;
- int call_poplevel;
+ int flags;
int nested;
{
register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
- rtx tmp_last_parm_insn, insns;
+ rtx last_parm_insn, insns;
/* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE;
tree decls = NULL_TREE;
+ int call_poplevel = (flags & 1) != 0;
+ int inclass_inline = (flags & 2) != 0;
+ int in_template;
/* When we get some parse errors, we can end up without a
current_function_decl, so cope. */
@@ -13029,7 +13741,8 @@ finish_function (lineno, call_poplevel, nested)
pointer to represent the type of our base class. */
/* This side-effect makes call to `build_delete' generate the
- code we have to have at the end of this destructor. */
+ code we have to have at the end of this destructor.
+ `build_delete' will set the flag again. */
TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
/* These are two cases where we cannot delegate deletion. */
@@ -13088,8 +13801,6 @@ finish_function (lineno, call_poplevel, nested)
expand_end_cond ();
}
- TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
-
virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */
@@ -13123,7 +13834,7 @@ finish_function (lineno, call_poplevel, nested)
/* End of destructor. */
expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0);
- poplevel (2, 0, 0); /* XXX change to 1 */
+ poplevel (getdecls () != NULL_TREE, 0, 0);
/* Back to the top of destructor. */
/* Don't execute destructor code if `this' is NULL. */
@@ -13160,13 +13871,13 @@ finish_function (lineno, call_poplevel, nested)
insns = get_insns ();
end_sequence ();
- tmp_last_parm_insn = get_first_nonparm_insn ();
- if (tmp_last_parm_insn == NULL_RTX)
- tmp_last_parm_insn = get_last_insn ();
+ last_parm_insn = get_first_nonparm_insn ();
+ if (last_parm_insn == NULL_RTX)
+ last_parm_insn = get_last_insn ();
else
- tmp_last_parm_insn = previous_insn (tmp_last_parm_insn);
+ last_parm_insn = previous_insn (last_parm_insn);
- emit_insns_after (insns, tmp_last_parm_insn);
+ emit_insns_after (insns, last_parm_insn);
if (! ok_to_optimize_dtor)
expand_end_cond ();
@@ -13336,6 +14047,20 @@ finish_function (lineno, call_poplevel, nested)
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
}
+
+ /* If we're processing a template, squirrel away the definition
+ until we do an instantiation. */
+ if (processing_template_decl)
+ {
+ --minimal_parse_mode;
+ DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
+ /* We have to save this value here in case
+ maybe_end_member_template_processing decides to pop all the
+ template parameters. */
+ in_template = 1;
+ }
+ else
+ in_template = 0;
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
@@ -13344,6 +14069,13 @@ finish_function (lineno, call_poplevel, nested)
my_friendly_abort (122);
poplevel (1, 0, 1);
+ /* If this is a in-class inline definition, we may have to pop the
+ bindings for the template parameters that we added in
+ maybe_begin_member_template_processing when start_function was
+ called. */
+ if (inclass_inline)
+ maybe_end_member_template_processing ();
+
/* Reset scope for C++: if we were in the scope of a class,
then when we finish this function, we are not longer so.
This cannot be done until we know for sure that no more
@@ -13362,7 +14094,7 @@ finish_function (lineno, call_poplevel, nested)
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
- if (! processing_template_decl)
+ if (!in_template)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
@@ -13446,16 +14178,10 @@ finish_function (lineno, call_poplevel, nested)
/* Free all the tree nodes making up this function. */
/* Switch back to allocating nodes permanently
until we start another function. */
- if (processing_template_decl)
- {
- --minimal_parse_mode;
- DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
- }
-
if (! nested)
permanent_allocation (1);
- if (DECL_SAVED_INSNS (fndecl) == 0)
+ if (DECL_SAVED_INSNS (fndecl) == NULL_RTX)
{
tree t;
@@ -13486,8 +14212,6 @@ finish_function (lineno, call_poplevel, nested)
}
/* Create the FUNCTION_DECL for a function definition.
- LINE1 is the line number that the definition absolutely begins on.
- LINE2 is the line number that the name of the function appears on.
DECLSPECS and DECLARATOR are the parts of the declaration;
they describe the return type and the name of the function,
but twisted together in a fashion that parallels the syntax of C.
@@ -13509,11 +14233,11 @@ finish_function (lineno, call_poplevel, nested)
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (declspecs, declarator)
- tree declarator, declspecs;
+start_method (declspecs, declarator, attrlist)
+ tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
- NULL_TREE);
+ attrlist);
/* Something too ugly to handle. */
if (fndecl == NULL_TREE)
@@ -13542,6 +14266,8 @@ start_method (declspecs, declarator)
return void_type_node;
}
+ check_template_shadow (fndecl);
+
DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline)
@@ -13623,23 +14349,11 @@ finish_method (decl)
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
+ pop_binding (DECL_NAME (link), link);
my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE;
}
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
-
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag,
@@ -13720,7 +14434,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
tree decl, auto_delete;
{
tree type = TREE_TYPE (decl);
- if (TYPE_NEEDS_DESTRUCTOR (type))
+ if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
{
int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
@@ -13797,38 +14511,30 @@ cplus_expand_expr_stmt (exp)
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
- if (TREE_TYPE (exp) == unknown_type_node)
+ exp = require_complete_type_in_void (exp);
+
+ if (TREE_CODE (exp) == FUNCTION_DECL)
{
- if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
- error ("address of overloaded function with no contextual type information");
- else if (TREE_CODE (exp) == COMPONENT_REF)
- warning ("useless reference to a member function name, did you forget the ()?");
+ cp_warning ("reference, not call, to function `%D'", exp);
+ warning ("at this point in file");
}
- else
- {
- if (TREE_CODE (exp) == FUNCTION_DECL)
- {
- cp_warning ("reference, not call, to function `%D'", exp);
- warning ("at this point in file");
- }
#if 0
- /* We should do this eventually, but right now this causes regex.o from
- libg++ to miscompile, and tString to core dump. */
- exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+ /* We should do this eventually, but right now this causes regex.o from
+ libg++ to miscompile, and tString to core dump. */
+ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
#endif
- /* Strip unused implicit INDIRECT_REFs of references. */
- if (TREE_CODE (exp) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
- exp = TREE_OPERAND (exp, 0);
+ /* Strip unused implicit INDIRECT_REFs of references. */
+ if (TREE_CODE (exp) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
+ exp = TREE_OPERAND (exp, 0);
- /* If we don't do this, we end up down inside expand_expr
- trying to do TYPE_MODE on the ERROR_MARK, and really
- go outside the bounds of the type. */
- if (exp != error_mark_node)
- expand_expr_stmt (break_out_cleanups (exp));
- }
+ /* If we don't do this, we end up down inside expand_expr
+ trying to do TYPE_MODE on the ERROR_MARK, and really
+ go outside the bounds of the type. */
+ if (exp != error_mark_node)
+ expand_expr_stmt (break_out_cleanups (exp));
/* Clean up any pending cleanups. This happens when a function call
returns a cleanup-needing value that nobody uses. */
@@ -13874,15 +14580,14 @@ revert_static_member_fn (decl, fn, argtypes)
tree function = fn ? *fn : TREE_TYPE (*decl);
tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
- if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (args))))
- cp_error ("static member function `%#D' declared const", *decl);
- if (TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (args))))
- cp_error ("static member function `%#D' declared volatile", *decl);
+ if (CP_TYPE_QUALS (TREE_TYPE (TREE_VALUE (args)))
+ != TYPE_UNQUALIFIED)
+ cp_error ("static member function `%#D' declared with type qualifiers",
+ *decl);
args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args);
- tmp = build_type_variant (tmp, TYPE_READONLY (function),
- TYPE_VOLATILE (function));
+ tmp = build_qualified_type (tmp, CP_TYPE_QUALS (function));
tmp = build_exception_variant (tmp,
TYPE_RAISES_EXCEPTIONS (function));
TREE_TYPE (*decl) = tmp;
@@ -13906,12 +14611,12 @@ struct language_function
{
int returns_value;
int returns_null;
- int warn_about_return_type;
int assigns_this;
int just_assigned_this;
int parms_stored;
int temp_name_counter;
tree named_labels;
+ struct named_label_list *named_label_uses;
tree shadowed_labels;
tree ctor_label;
tree dtor_label;
@@ -13941,10 +14646,10 @@ push_cp_function_context (f)
f->language = p;
p->named_labels = named_labels;
+ p->named_label_uses = named_label_uses;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
- p->warn_about_return_type = warn_about_return_type;
p->binding_level = current_binding_level;
p->ctor_label = ctor_label;
p->dtor_label = dtor_label;
@@ -13979,10 +14684,10 @@ pop_cp_function_context (f)
TREE_VALUE (link));
named_labels = p->named_labels;
+ named_label_uses = p->named_label_uses;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
- warn_about_return_type = p->warn_about_return_type;
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;