-/* Process declarations and variables for C compiler.
+/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002 Free Software Foundation, Inc.
+ 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Process declarations and symbol lookup for C front end.
+/* Process declarations and symbol lookup for C++ front end.
Also constructs types; the standard scalar types at initialization,
and structure, union, array and enum types when they are declared. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "except.h"
#include "toplev.h"
#include "hashtab.h"
-#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
#include "c-pragma.h"
#include "diagnostic.h"
#include "debug.h"
-
-static tree grokparms PARAMS ((tree));
-static const char *redeclaration_error_message PARAMS ((tree, tree));
-
-static void push_binding_level PARAMS ((struct cp_binding_level *, int,
- int));
-static void pop_binding_level PARAMS ((void));
-static void suspend_binding_level PARAMS ((void));
-static void resume_binding_level PARAMS ((struct cp_binding_level *));
-static struct cp_binding_level *make_binding_level PARAMS ((void));
-static void declare_namespace_level PARAMS ((void));
-static int decl_jump_unsafe PARAMS ((tree));
-static void storedecls PARAMS ((tree));
-static void require_complete_types_for_parms PARAMS ((tree));
-static int ambi_op_p PARAMS ((enum tree_code));
-static int unary_op_p PARAMS ((enum tree_code));
-static tree store_bindings PARAMS ((tree, tree));
-static tree lookup_tag_reverse PARAMS ((tree, tree));
-static tree lookup_name_real PARAMS ((tree, int, int, int));
-static void push_local_name PARAMS ((tree));
-static void warn_extern_redeclared_static PARAMS ((tree, tree));
-static tree grok_reference_init PARAMS ((tree, tree, tree));
-static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
- enum overload_flags, tree,
- tree, int, int, int, int, int, int, tree));
-static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree));
-static tree follow_tag_typedef PARAMS ((tree));
-static tree lookup_tag PARAMS ((enum tree_code, tree,
- struct cp_binding_level *, int));
+#include "timevar.h"
+
+static tree grokparms (tree);
+static const char *redeclaration_error_message (tree, tree);
+
+static void push_binding_level (struct cp_binding_level *, int,
+ int);
+static void pop_binding_level (void);
+static void suspend_binding_level (void);
+static void resume_binding_level (struct cp_binding_level *);
+static struct cp_binding_level *make_binding_level (void);
+static void declare_namespace_level (void);
+static int decl_jump_unsafe (tree);
+static void storedecls (tree);
+static void require_complete_types_for_parms (tree);
+static int ambi_op_p (enum tree_code);
+static int unary_op_p (enum tree_code);
+static cxx_saved_binding *store_bindings (tree, cxx_saved_binding *);
+static tree lookup_tag_reverse (tree, tree);
+static void push_local_name (tree);
+static void warn_extern_redeclared_static (tree, tree);
+static tree grok_reference_init (tree, tree, tree);
+static tree grokfndecl (tree, tree, tree, tree, int,
+ enum overload_flags, tree,
+ tree, int, int, int, int, int, int, tree);
+static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
+static tree follow_tag_typedef (tree);
+static tree lookup_tag (enum tree_code, tree,
+ struct cp_binding_level *, int);
static void set_identifier_type_value_with_scope
- PARAMS ((tree, tree, struct cp_binding_level *));
-static void record_unknown_type PARAMS ((tree, const char *));
-static tree builtin_function_1 PARAMS ((const char *, tree, tree, int,
- enum built_in_class, const char *,
- tree));
-static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
-static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
-static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
- int));
-static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct cp_binding_level*));
-static void check_for_uninitialized_const_var PARAMS ((tree));
-static hashval_t typename_hash PARAMS ((const void *));
-static int typename_compare PARAMS ((const void *, const void *));
-static void push_binding PARAMS ((tree, tree, struct cp_binding_level*));
-static int add_binding PARAMS ((tree, tree));
-static void pop_binding PARAMS ((tree, tree));
-static tree local_variable_p_walkfn PARAMS ((tree *, int *, void *));
-static tree find_binding PARAMS ((tree, tree));
-static tree select_decl PARAMS ((tree, int));
-static int lookup_flags PARAMS ((int, int));
-static tree qualify_lookup PARAMS ((tree, int));
-static tree record_builtin_java_type PARAMS ((const char *, int));
-static const char *tag_name PARAMS ((enum tag_types code));
-static void find_class_binding_level PARAMS ((void));
-static struct cp_binding_level *innermost_nonclass_level PARAMS ((void));
-static void warn_about_implicit_typename_lookup PARAMS ((tree, tree));
-static int walk_namespaces_r PARAMS ((tree, walk_namespaces_fn, void *));
-static int walk_globals_r PARAMS ((tree, void *));
-static int walk_vtables_r PARAMS ((tree, void*));
-static void add_decl_to_level PARAMS ((tree, struct cp_binding_level *));
-static tree make_label_decl PARAMS ((tree, int));
-static void use_label PARAMS ((tree));
-static void check_previous_goto_1 PARAMS ((tree, struct cp_binding_level *, tree,
- const char *, int));
-static void check_previous_goto PARAMS ((struct named_label_use_list *));
-static void check_switch_goto PARAMS ((struct cp_binding_level *));
-static void check_previous_gotos PARAMS ((tree));
-static void pop_label PARAMS ((tree, tree));
-static void pop_labels PARAMS ((tree));
-static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
-static void layout_var_decl PARAMS ((tree));
-static void maybe_commonize_var PARAMS ((tree));
+ (tree, tree, struct cp_binding_level *);
+static void record_unknown_type (tree, const char *);
+static tree builtin_function_1 (const char *, tree, tree, int,
+ enum built_in_class, const char *,
+ tree);
+static tree build_library_fn_1 (tree, enum tree_code, tree);
+static int member_function_or_else (tree, tree, enum overload_flags);
+static void bad_specifiers (tree, const char *, int, int, int, int,
+ int);
+static tree maybe_process_template_type_declaration
+ (tree, int, struct cp_binding_level*);
+static void check_for_uninitialized_const_var (tree);
+static hashval_t typename_hash (const void *);
+static int typename_compare (const void *, const void *);
+static void push_binding (tree, tree, struct cp_binding_level*);
+static int add_binding (tree, tree);
+static void pop_binding (tree, tree);
+static tree local_variable_p_walkfn (tree *, int *, void *);
+static tree select_decl (cxx_binding *, int);
+static int lookup_flags (int, int);
+static tree qualify_lookup (tree, int);
+static tree record_builtin_java_type (const char *, int);
+static const char *tag_name (enum tag_types code);
+static void find_class_binding_level (void);
+static struct cp_binding_level *innermost_nonclass_level (void);
+static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
+static int walk_globals_r (tree, void*);
+static int walk_vtables_r (tree, void*);
+static void add_decl_to_level (tree, struct cp_binding_level *);
+static tree make_label_decl (tree, int);
+static void use_label (tree);
+static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
+ const char *, int);
+static void check_previous_goto (struct named_label_use_list *);
+static void check_switch_goto (struct cp_binding_level *);
+static void check_previous_gotos (tree);
+static void pop_label (tree, tree);
+static void pop_labels (tree);
+static void maybe_deduce_size_from_array_init (tree, tree);
+static void layout_var_decl (tree);
+static void maybe_commonize_var (tree);
static tree check_initializer (tree, tree, int);
-static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
-static void save_function_data PARAMS ((tree));
-static void check_function_type PARAMS ((tree, tree));
-static void begin_constructor_body PARAMS ((void));
-static void finish_constructor_body PARAMS ((void));
-static void begin_destructor_body PARAMS ((void));
-static void finish_destructor_body PARAMS ((void));
-static tree create_array_type_for_decl PARAMS ((tree, tree, tree));
-static tree get_atexit_node PARAMS ((void));
-static tree get_dso_handle_node PARAMS ((void));
-static tree start_cleanup_fn PARAMS ((void));
-static void end_cleanup_fn PARAMS ((void));
-static tree cp_make_fname_decl PARAMS ((tree, int));
-static void initialize_predefined_identifiers PARAMS ((void));
-static tree check_special_function_return_type
- PARAMS ((special_function_kind, tree, tree));
-static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
-static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
-static void store_parm_decls PARAMS ((tree));
-static int cp_missing_noreturn_ok_p PARAMS ((tree));
+static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
+static void save_function_data (tree);
+static void check_function_type (tree, tree);
+static void begin_constructor_body (void);
+static void finish_constructor_body (void);
+static void begin_destructor_body (void);
+static void finish_destructor_body (void);
+static tree create_array_type_for_decl (tree, tree, tree);
+static tree get_atexit_node (void);
+static tree get_dso_handle_node (void);
+static tree start_cleanup_fn (void);
+static void end_cleanup_fn (void);
+static tree cp_make_fname_decl (tree, int);
+static void initialize_predefined_identifiers (void);
+static tree check_special_function_return_type
+ (special_function_kind, tree, tree);
+static tree push_cp_library_fn (enum tree_code, tree);
+static tree build_cp_library_fn (tree, enum tree_code, tree);
+static void store_parm_decls (tree);
+static int cp_missing_noreturn_ok_p (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
static tree reshape_init (tree, tree *);
+static tree build_typename_type (tree, tree, tree);
#if defined (DEBUG_BINDING_LEVELS)
-static void indent PARAMS ((void));
+static void indent (void);
#endif
/* Erroneous argument lists can use this *IFF* they do not modify it. */
static GTY(()) tree global_type_node;
-/* Expect only namespace names now. */
-static int only_namespace_names;
-
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
/* A chain of NAMESPACE_DECL nodes. */
tree namespaces;
+ /* An array of static functions and variables (for namespaces only) */
+ varray_type static_decls;
+
/* A chain of VTABLE_DECL nodes. */
tree vtables;
/* The binding level currently in effect. */
#define current_binding_level \
- (cfun && cp_function_chain->bindings \
- ? cp_function_chain->bindings \
- : scope_chain->bindings)
+ (*(cfun && cp_function_chain->bindings \
+ ? &cp_function_chain->bindings \
+ : &scope_chain->bindings))
/* The binding level of the current class, if any. */
static int is_class_level = 0;
static void
-indent ()
+indent (void)
{
register unsigned i;
}
#endif /* defined(DEBUG_BINDING_LEVELS) */
-static tree pushdecl_with_scope PARAMS ((tree, struct cp_binding_level *));
+static tree pushdecl_with_scope (tree, struct cp_binding_level *);
static void
-push_binding_level (newlevel, tag_transparent, keep)
- struct cp_binding_level *newlevel;
- int tag_transparent, keep;
+push_binding_level (struct cp_binding_level *newlevel,
+ int tag_transparent,
+ int keep)
{
/* Add this level to the front of the chain (stack) of levels that
are active. */
CLASS_BINDING_LEVEL appropriately. */
static void
-find_class_binding_level ()
+find_class_binding_level (void)
{
struct cp_binding_level *level = current_binding_level;
}
static void
-pop_binding_level ()
+pop_binding_level (void)
{
if (global_binding_level)
{
}
static void
-suspend_binding_level ()
+suspend_binding_level (void)
{
if (class_binding_level)
current_binding_level = class_binding_level;
}
static void
-resume_binding_level (b)
- struct cp_binding_level *b;
+resume_binding_level (struct cp_binding_level* b)
{
/* Resuming binding levels is meant only for namespaces,
and those cannot nest into classes. */
static
struct cp_binding_level *
-make_binding_level ()
+make_binding_level (void)
{
/* NOSTRICT */
return (struct cp_binding_level *) ggc_alloc (sizeof (struct cp_binding_level));
/* Nonzero if we are currently in the global binding level. */
int
-global_bindings_p ()
+global_bindings_p (void)
{
return current_binding_level == global_binding_level;
}
/* Return the innermost binding level that is not for a class scope. */
static struct cp_binding_level *
-innermost_nonclass_level ()
+innermost_nonclass_level (void)
{
struct cp_binding_level *b;
also include a class whose context is toplevel. */
int
-toplevel_bindings_p ()
+toplevel_bindings_p (void)
{
struct cp_binding_level *b = innermost_nonclass_level ();
such a class, etc. */
int
-namespace_bindings_p ()
+namespace_bindings_p (void)
{
struct cp_binding_level *b = innermost_nonclass_level ();
or not to create a BLOCK. */
void
-keep_next_level (keep)
- int keep;
+keep_next_level (int keep)
{
keep_next_level_flag = keep;
}
/* Nonzero if the current level needs to have a BLOCK made. */
int
-kept_level_p ()
+kept_level_p (void)
{
return (current_binding_level->blocks != NULL_TREE
|| current_binding_level->keep
}
static void
-declare_namespace_level ()
+declare_namespace_level (void)
{
current_binding_level->namespace_p = 1;
}
parameters. */
int
-template_parm_scope_p ()
+template_parm_scope_p (void)
{
return current_binding_level->template_parms_p;
}
explicit scope qualifications. */
tmpl_spec_kind
-current_tmpl_spec_kind (n_class_scopes)
- int n_class_scopes;
+current_tmpl_spec_kind (int n_class_scopes)
{
int n_template_parm_scopes = 0;
int seen_specialization_p = 0;
}
void
-set_class_shadows (shadows)
- tree shadows;
+set_class_shadows (tree shadows)
{
class_binding_level->class_shadowed = shadows;
}
not for that of tags. */
void
-pushlevel (tag_transparent)
- int tag_transparent;
+pushlevel (int tag_transparent)
{
struct cp_binding_level *newlevel;
scope, create a new binding level. */
void
-maybe_push_cleanup_level (type)
- tree type;
+maybe_push_cleanup_level (tree type)
{
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
&& current_binding_level->more_cleanups_ok == 0)
created. */
void
-begin_scope (sk)
- scope_kind sk;
+begin_scope (scope_kind sk)
{
pushlevel (0);
switch (sk)
{
+ case sk_block:
+ break;
+
+ case sk_try:
+ current_binding_level->is_try_scope = 1;
+ break;
+
+ case sk_catch:
+ current_binding_level->is_catch_scope = 1;
+ break;
+
+ case sk_for:
+ current_binding_level->is_for_scope = 1;
+ break;
+
case sk_template_spec:
current_binding_level->template_spec_p = 1;
/* Fall through. */
/* Exit the current scope. */
void
-finish_scope ()
+finish_scope (void)
{
poplevel (0, 0, 0);
}
-void
-note_level_for_for ()
-{
- current_binding_level->is_for_scope = 1;
-}
-
-/* Record that the current binding level represents a try block. */
-
-void
-note_level_for_try ()
-{
- current_binding_level->is_try_scope = 1;
-}
-
-/* Record that the current binding level represents a catch block. */
-
-void
-note_level_for_catch ()
-{
- current_binding_level->is_catch_scope = 1;
-}
-
-/* For a binding between a name and an entity at a block scope,
- this is the `struct cp_binding_level' for the block. */
-#define BINDING_LEVEL(NODE) \
- (((struct tree_binding*)(NODE))->scope.level)
-
-/* A free list of CPLUS_BINDING nodes, connected by their
- TREE_CHAINs. */
-
-static GTY((deletable (""))) tree free_bindings;
-
/* 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 cp_binding_level* level;
+push_binding (tree id, tree decl, cxx_scope* level)
{
- tree binding;
-
- if (free_bindings)
- {
- binding = free_bindings;
- free_bindings = TREE_CHAIN (binding);
- }
- else
- binding = make_node (CPLUS_BINDING);
+ cxx_binding *binding = cxx_binding_make (decl, NULL);
/* Now, fill in the binding information. */
- BINDING_VALUE (binding) = decl;
- BINDING_TYPE (binding) = NULL_TREE;
- BINDING_LEVEL (binding) = level;
+ binding->previous = IDENTIFIER_BINDING (id);
+ BINDING_SCOPE (binding) = level;
INHERITED_VALUE_BINDING_P (binding) = 0;
LOCAL_BINDING_P (binding) = (level != class_binding_level);
- BINDING_HAS_LEVEL_P (binding) = 1;
/* And put it on the front of the list of bindings for ID. */
- TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
IDENTIFIER_BINDING (id) = binding;
}
responsibility of the caller to check that inserting this name is
valid here. Returns nonzero if the new binding was successful. */
static int
-add_binding (id, decl)
- tree id;
- tree decl;
+add_binding (tree id, tree decl)
{
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
int ok = 1;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
/* The new name is the type name. */
BINDING_TYPE (binding) = decl;
ok = 0;
}
- return ok;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
}
/* Add DECL to the list of things declared in B. */
static void
-add_decl_to_level (decl, b)
- tree decl;
- struct cp_binding_level *b;
+add_decl_to_level (tree decl,
+ struct cp_binding_level* b)
{
if (TREE_CODE (decl) == NAMESPACE_DECL
&& !DECL_NAMESPACE_ALIAS (decl))
TREE_CHAIN (decl) = b->names;
b->names = decl;
b->names_size++;
+
+ /* If appropriate, add decl to separate list of statics */
+ if (b->namespace_p)
+ if ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
+ VARRAY_PUSH_TREE (b->static_decls, decl);
}
}
through a using-declaration. */
void
-push_local_binding (id, decl, flags)
- tree id;
- tree decl;
- int flags;
+push_local_binding (tree id, tree decl, int flags)
{
struct cp_binding_level *b;
binding was successful. */
int
-push_class_binding (id, decl)
- tree id;
- tree decl;
+push_class_binding (tree id, tree decl)
{
int result = 1;
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
tree context;
+ timevar_push (TV_NAME_LOOKUP);
/* Note that we declared this value so that we can issue an error if
this is an invalid redeclaration of a name already used for some
other purpose. */
note_name_declared_in_class (id, decl);
- if (binding && BINDING_LEVEL (binding) == class_binding_level)
+ if (binding && BINDING_SCOPE (binding) == class_binding_level)
/* Supplement the existing binding. */
result = add_binding (id, decl);
else
binding = IDENTIFIER_BINDING (id);
if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST)
{
- /* Any implicit typename must be from a base-class. The
- context for an implicit typename declaration is always
- the derived class in which the lookup was done, so the checks
- based on the context of DECL below will not trigger. */
- if (IMPLICIT_TYPENAME_TYPE_DECL_P (decl))
- INHERITED_VALUE_BINDING_P (binding) = 1;
+ if (TREE_CODE (decl) == OVERLOAD)
+ context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
else
{
- if (TREE_CODE (decl) == OVERLOAD)
- context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
- else
- {
- my_friendly_assert (DECL_P (decl), 0);
- context = context_for_name_lookup (decl);
- }
-
- if (is_properly_derived_from (current_class_type, context))
- INHERITED_VALUE_BINDING_P (binding) = 1;
- else
- INHERITED_VALUE_BINDING_P (binding) = 0;
+ my_friendly_assert (DECL_P (decl), 0);
+ context = context_for_name_lookup (decl);
}
+
+ if (is_properly_derived_from (current_class_type, context))
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+ else
+ INHERITED_VALUE_BINDING_P (binding) = 0;
}
else if (BINDING_VALUE (binding) == decl)
/* We only encounter a TREE_LIST when push_class_decls detects an
in this class. */
INHERITED_VALUE_BINDING_P (binding) = 1;
- return result;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
}
/* Remove the binding for DECL which should be the innermost binding
for ID. */
static void
-pop_binding (id, decl)
- tree id;
- tree decl;
+pop_binding (tree id, tree decl)
{
- tree binding;
+ cxx_binding *binding;
if (id == NULL_TREE)
/* It's easiest to write the loops that call this function without
binding = IDENTIFIER_BINDING (id);
/* The name should be bound. */
- my_friendly_assert (binding != NULL_TREE, 0);
+ my_friendly_assert (binding != NULL, 0);
/* The DECL will be either the ordinary binding or the type
binding for this identifier. Remove that 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);
+ IDENTIFIER_BINDING (id) = binding->previous;
/* Add it to the free list. */
- TREE_CHAIN (binding) = free_bindings;
- free_bindings = binding;
+ cxx_binding_free (binding);
- /* Clear the BINDING_LEVEL so the garbage collector doesn't walk
+ /* Clear the BINDING_SCOPE so the garbage collector doesn't walk
it. */
- BINDING_LEVEL (binding) = NULL;
+ BINDING_SCOPE (binding) = NULL;
}
}
in a valid manner, and issue any appropriate warnings or errors. */
static void
-pop_label (label, old_value)
- tree label;
- tree old_value;
+pop_label (tree label, tree old_value)
{
if (!processing_template_decl && doing_semantic_analysis_p ())
{
function. */
static void
-pop_labels (block)
- tree block;
+pop_labels (tree block)
{
struct named_label_list *link;
them into the BLOCK. */
tree
-poplevel (keep, reverse, functionbody)
- int keep;
- int reverse;
- int functionbody;
+poplevel (int keep, int reverse, int functionbody)
{
register tree link;
/* The chain of decls was accumulated in reverse order.
tree decl;
int leaving_for_scope;
+ timevar_push (TV_NAME_LOOKUP);
if (cfun && !doing_semantic_analysis_p ())
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
my_friendly_assert (current_binding_level->parm_flag != 2,
19990916);
/* 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
+ ended. We only use the new rules if flag_new_for_scope is
nonzero. */
leaving_for_scope
= current_binding_level->is_for_scope && flag_new_for_scope == 1;
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
&& DECL_NAME (link))
{
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
tree ns_binding;
if (!outer_binding)
ns_binding = NULL_TREE;
if (outer_binding
- && (BINDING_LEVEL (outer_binding)
+ && (BINDING_SCOPE (outer_binding)
== current_binding_level->level_chain))
/* We have something like:
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;
+ /* Although we don't pop the cxx_binding, we do clear
+ its BINDING_SCOPE since the level is going away now. */
+ BINDING_SCOPE (IDENTIFIER_BINDING (DECL_NAME (link))) = 0;
}
}
else
block = poplevel (keep, reverse, functionbody);
}
- return block;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
/* Delete the node BLOCK from the current binding level.
so that the block can be reinserted where appropriate. */
void
-delete_block (block)
- tree block;
+delete_block (tree block)
{
tree t;
if (current_binding_level->blocks == block)
to handle the BLOCK node inside the BIND_EXPR. */
void
-insert_block (block)
- tree block;
+insert_block (tree block)
{
TREE_USED (block) = 1;
current_binding_level->blocks
(the one we are currently in). */
void
-set_block (block)
- tree block ATTRIBUTE_UNUSED;
+set_block (tree block ATTRIBUTE_UNUSED )
{
/* The RTL expansion machinery requires us to provide this callback,
but it is not applicable in function-at-a-time mode. */
/* Do a pushlevel for class declarations. */
void
-pushlevel_class ()
+pushlevel_class (void)
{
register struct cp_binding_level *newlevel;
/* ...and a poplevel for class declarations. */
void
-poplevel_class ()
+poplevel_class (void)
{
register struct cp_binding_level *level = class_binding_level;
tree shadowed;
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (level != 0, 354);
/* If we're leaving a toplevel class, don't bother to do the setting
shadowed;
shadowed = TREE_CHAIN (shadowed))
{
- tree t;
-
- t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
- while (t && BINDING_LEVEL (t) != b)
- t = TREE_CHAIN (t);
+ cxx_binding *binding;
+
+ binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+ while (binding && BINDING_SCOPE (binding) != b)
+ binding = binding->previous;
- if (t)
+ if (binding)
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
- = BINDING_VALUE (t);
+ = BINDING_VALUE (binding);
}
}
else
#endif /* defined(DEBUG_BINDING_LEVELS) */
pop_binding_level ();
+ timevar_pop (TV_NAME_LOOKUP);
}
/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
for any names in enclosing classes. */
void
-clear_identifier_class_values ()
+clear_identifier_class_values (void)
{
tree t;
/* Returns nonzero if T is a virtual function table. */
int
-vtable_decl_p (t, data)
- tree t;
- void *data ATTRIBUTE_UNUSED;
+vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED )
{
return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
}
functions. */
int
-vtype_decl_p (t, data)
- tree t;
- void *data ATTRIBUTE_UNUSED;
+vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED )
{
return (TREE_CODE (t) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
/* Return the declarations that are members of the namespace NS. */
tree
-cp_namespace_decls (ns)
- tree ns;
+cp_namespace_decls (tree ns)
{
return NAMESPACE_LEVEL (ns)->names;
}
to F returns a nonzero value, return a nonzero value. */
static int
-walk_vtables_r (namespace, data)
- tree namespace;
- void *data;
+walk_vtables_r (tree namespace, void* data)
{
struct walk_globals_data* wgd = (struct walk_globals_data *) data;
walk_globals_fn f = wgd->f;
/* Walk the vtable declarations. Whenever one is found for which P
returns nonzero, call F with its address. If any call to F
returns a nonzero value, return a nonzero value. */
-int
-walk_vtables (p, f, data)
- walk_globals_pred p;
- walk_globals_fn f;
- void *data;
+bool
+walk_vtables (walk_globals_pred p, walk_globals_fn f, void *data)
{
struct walk_globals_data wgd;
wgd.p = p;
itself, calling F for each. The DATA is passed to F as well. */
static int
-walk_namespaces_r (namespace, f, data)
- tree namespace;
- walk_namespaces_fn f;
- void *data;
+walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)
{
int result = 0;
tree current = NAMESPACE_LEVEL (namespace)->namespaces;
F as well. */
int
-walk_namespaces (f, data)
- walk_namespaces_fn f;
- void *data;
+walk_namespaces (walk_namespaces_fn f, void* data)
{
return walk_namespaces_r (global_namespace, f, data);
}
to F returns a nonzero value, return a nonzero value. */
static int
-walk_globals_r (namespace, data)
- tree namespace;
- void *data;
+walk_globals_r (tree namespace, void* data)
{
struct walk_globals_data* wgd = (struct walk_globals_data *) data;
walk_globals_pred p = wgd->p;
}
/* Walk the global declarations. Whenever one is found for which P
- returns nonzero, call F with its address. If any call to F
- returns a nonzero value, return a nonzero value. */
+ returns true, call F with its address. If any call to F
+ returns true, return true. */
-int
-walk_globals (p, f, data)
- walk_globals_pred p;
- walk_globals_fn f;
- void *data;
+bool
+walk_globals (walk_globals_pred p, walk_globals_fn f, void *data)
{
struct walk_globals_data wgd;
wgd.p = p;
wrapup_global_declarations for this NAMESPACE. */
int
-wrapup_globals_for_namespace (namespace, data)
- tree namespace;
- void *data;
+wrapup_globals_for_namespace (tree namespace, void* data)
{
- tree globals = cp_namespace_decls (namespace);
- int len = NAMESPACE_LEVEL (namespace)->names_size;
- tree *vec = (tree *) alloca (sizeof (tree) * len);
- int i;
- int result;
- tree decl;
+ struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
+ varray_type statics = level->static_decls;
+ tree *vec = &VARRAY_TREE (statics, 0);
+ int len = VARRAY_ACTIVE_SIZE (statics);
int last_time = (data != 0);
- if (last_time && namespace == global_namespace)
- /* Let compile_file handle the global namespace. */
- return 0;
-
- /* Process the decls in reverse order--earliest first.
- Put them into VEC from back to front, then take out from front. */
- for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[len - i - 1] = decl;
-
if (last_time)
{
check_global_declarations (vec, len);
}
/* Write out any globals that need to be output. */
- result = wrapup_global_declarations (vec, len);
-
- return result;
+ return wrapup_global_declarations (vec, len);
}
\f
static int no_print_builtins = 0;
void
-print_binding_level (lvl)
- struct cp_binding_level *lvl;
+print_binding_level (struct cp_binding_level* lvl)
{
tree t;
int i = 0, len;
fprintf (stderr, " blocks=");
- fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) lvl->blocks);
if (lvl->tag_transparent)
fprintf (stderr, " tag-transparent");
if (lvl->more_cleanups_ok)
}
void
-print_other_binding_stack (stack)
- struct cp_binding_level *stack;
+print_other_binding_stack (struct cp_binding_level *stack)
{
struct cp_binding_level *level;
for (level = stack; level != global_binding_level; level = level->level_chain)
{
fprintf (stderr, "binding level ");
- fprintf (stderr, HOST_PTR_PRINTF, level);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) level);
fprintf (stderr, "\n");
print_binding_level (level);
}
}
void
-print_binding_stack ()
+print_binding_stack (void)
{
struct cp_binding_level *b;
fprintf (stderr, "current_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) current_binding_level);
fprintf (stderr, "\nclass_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, class_binding_level);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) class_binding_level);
fprintf (stderr, "\nglobal_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, global_binding_level);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) global_binding_level);
fprintf (stderr, "\n");
if (class_binding_level)
{
/* Namespace binding access routines: The namespace_bindings field of
the identifier is polymorphic, with three possible values:
- NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node
- indicating the BINDING_VALUE of global_namespace. */
-
-/* Check whether the a binding for the name to scope is known.
- Assumes that the bindings of the name are already a list
- of bindings. Returns the binding found, or NULL_TREE. */
-
-static tree
-find_binding (name, scope)
- tree name;
- tree scope;
-{
- tree iter, prev = NULL_TREE;
-
- scope = ORIGINAL_NAMESPACE (scope);
-
- for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
- iter = TREE_CHAIN (iter))
- {
- my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
- if (BINDING_SCOPE (iter) == scope)
- {
- /* Move binding found to the front of the list, so
- subsequent lookups will find it faster. */
- if (prev)
- {
- TREE_CHAIN (prev) = TREE_CHAIN (iter);
- TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
- IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
- }
- return iter;
- }
- prev = iter;
- }
- return NULL_TREE;
-}
-
-/* Always returns a binding for name in scope. If the
- namespace_bindings is not a list, convert it to one first.
- If no binding is found, make a new one. */
-
-tree
-binding_for_name (name, scope)
- tree name;
- tree scope;
-{
- tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- tree result;
-
- scope = ORIGINAL_NAMESPACE (scope);
-
- if (b && TREE_CODE (b) != CPLUS_BINDING)
- {
- /* Get rid of optimization for global scope. */
- IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
- BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
- b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- }
- if (b && (result = find_binding (name, scope)))
- return result;
- /* Not found, make a new one. */
- result = make_node (CPLUS_BINDING);
- TREE_CHAIN (result) = b;
- IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
- BINDING_SCOPE (result) = scope;
- BINDING_TYPE (result) = NULL_TREE;
- BINDING_VALUE (result) = NULL_TREE;
- return result;
-}
-
-/* Return the binding value for name in scope, considering that
- namespace_binding may or may not be a list of CPLUS_BINDINGS. */
-
-tree
-namespace_binding (name, scope)
- tree name;
- tree scope;
-{
- tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b == NULL_TREE)
- return NULL_TREE;
- if (scope == NULL_TREE)
- scope = global_namespace;
- if (TREE_CODE (b) != CPLUS_BINDING)
- return (scope == global_namespace) ? b : NULL_TREE;
- name = find_binding (name,scope);
- if (name == NULL_TREE)
- return name;
- return BINDING_VALUE (name);
-}
-
-/* Set the binding value for name in scope. If modifying the binding
- of global_namespace is attempted, try to optimize it. */
-
-void
-set_namespace_binding (name, scope, val)
- tree name;
- tree scope;
- tree val;
-{
- tree b;
-
- if (scope == NULL_TREE)
- scope = global_namespace;
-
- if (scope == global_namespace)
- {
- b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
- {
- IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
- return;
- }
- }
- b = binding_for_name (name, scope);
- BINDING_VALUE (b) = val;
-}
+ NULL_TREE, a list of "cxx_binding"s. */
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
select a name that is unique to this compilation unit. */
void
-push_namespace (name)
- tree name;
+push_namespace (tree name)
{
tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
int global = 0;
+
+ timevar_push (TV_NAME_LOOKUP);
+
if (!global_namespace)
{
/* This must be ::. */
pushlevel (0);
declare_namespace_level ();
NAMESPACE_LEVEL (d) = current_binding_level;
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
+ name != std_identifier ? 10 : 200,
+ "Static declarations");
}
}
else
do_using_directive (d);
/* Enter the name space. */
current_namespace = d;
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Pop from the scope of the current namespace. */
void
-pop_namespace ()
+pop_namespace (void)
{
my_friendly_assert (current_namespace != global_namespace, 20010801);
current_namespace = CP_DECL_CONTEXT (current_namespace);
nested within another namespace. */
void
-push_nested_namespace (ns)
- tree ns;
+push_nested_namespace (tree ns)
{
if (ns == global_namespace)
push_to_top_level ();
entered with push_nested_namespace. */
void
-pop_nested_namespace (ns)
- tree ns;
+pop_nested_namespace (tree ns)
{
+ timevar_push (TV_NAME_LOOKUP);
while (ns != global_namespace)
{
pop_namespace ();
}
pop_from_top_level ();
+ timevar_pop (TV_NAME_LOOKUP);
}
\f
+/* Allocate storage for saving a C++ binding. */
+#define cxx_saved_binding_make() \
+ (ggc_alloc (sizeof (cxx_saved_binding)))
+
+struct cxx_saved_binding GTY(())
+{
+ /* Link that chains saved C++ bindings for a given name into a stack. */
+ cxx_saved_binding *previous;
+ /* The name of the current binding. */
+ tree identifier;
+ /* The binding we're saving. */
+ cxx_binding *binding;
+ tree class_value;
+ tree real_type_value;
+};
+
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
local-value slots of all identifiers, so that only the global values
scope isn't enough, because more binding levels may be pushed. */
struct saved_scope *scope_chain;
-static tree
-store_bindings (names, old_bindings)
- tree names, old_bindings;
+static cxx_saved_binding *
+store_bindings (tree names, cxx_saved_binding *old_bindings)
{
tree t;
- tree search_bindings = old_bindings;
+ cxx_saved_binding *search_bindings = old_bindings;
+ timevar_push (TV_NAME_LOOKUP);
for (t = names; t; t = TREE_CHAIN (t))
{
- tree binding, t1, id;
+ tree id;
+ cxx_saved_binding *saved;
+ cxx_saved_binding *t1;
if (TREE_CODE (t) == TREE_LIST)
id = TREE_PURPOSE (t);
|| !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
- for (t1 = search_bindings; t1; t1 = TREE_CHAIN (t1))
- if (TREE_VEC_ELT (t1, 0) == id)
+ for (t1 = search_bindings; t1; t1 = t1->previous)
+ if (t1->identifier == id)
goto skip_it;
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
- binding = make_tree_vec (4);
- TREE_VEC_ELT (binding, 0) = id;
- TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
- TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_BINDING (id) = NULL_TREE;
+ saved = cxx_saved_binding_make ();
+ saved->previous = old_bindings;
+ saved->identifier = id;
+ saved->binding = IDENTIFIER_BINDING (id);
+ saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
+ saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
+ IDENTIFIER_BINDING (id) = NULL;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
- TREE_CHAIN (binding) = old_bindings;
- old_bindings = binding;
+ old_bindings = saved;
skip_it:
;
}
- return old_bindings;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
}
void
-maybe_push_to_top_level (pseudo)
- int pseudo;
+maybe_push_to_top_level (int pseudo)
{
struct saved_scope *s;
struct cp_binding_level *b;
- tree old_bindings;
+ cxx_saved_binding *old_bindings;
int need_pop;
+ timevar_push (TV_NAME_LOOKUP);
s = (struct saved_scope *) ggc_alloc_cleared (sizeof (struct saved_scope));
b = scope_chain ? current_binding_level : 0;
else
need_pop = 0;
- old_bindings = NULL_TREE;
+ old_bindings = NULL;
if (scope_chain && previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
s->need_pop_function_context = need_pop;
s->function_decl = current_function_decl;
s->last_parms = last_function_parms;
+ s->check_access = flag_access_control;
scope_chain = s;
current_function_decl = NULL_TREE;
VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
current_lang_name = lang_name_cplusplus;
current_namespace = global_namespace;
+ timevar_pop (TV_NAME_LOOKUP);
}
void
-push_to_top_level ()
+push_to_top_level (void)
{
maybe_push_to_top_level (0);
}
void
-pop_from_top_level ()
+pop_from_top_level (void)
{
struct saved_scope *s = scope_chain;
- tree t;
+ cxx_saved_binding *saved;
+ timevar_push (TV_NAME_LOOKUP);
/* Clear out class-level bindings cache. */
if (previous_class_type)
invalidate_class_lookup_cache ();
current_lang_base = 0;
scope_chain = s->prev;
- for (t = s->old_bindings; t; t = TREE_CHAIN (t))
+ for (saved = s->old_bindings; saved; saved = saved->previous)
{
- tree id = TREE_VEC_ELT (t, 0);
+ tree id = saved->identifier;
- SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
- IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
+ IDENTIFIER_BINDING (id) = saved->binding;
+ IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
+ SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
}
/* If we were in the middle of compiling a function, restore our
pop_function_context_from (NULL_TREE);
current_function_decl = s->function_decl;
last_function_parms = s->last_parms;
+ timevar_pop (TV_NAME_LOOKUP);
}
\f
/* Push a definition of struct, union or enum tag "name".
the type that ID maps to. */
static void
-set_identifier_type_value_with_scope (id, type, b)
- tree id;
- tree type;
- struct cp_binding_level *b;
+set_identifier_type_value_with_scope (tree id,
+ tree type,
+ struct cp_binding_level* b)
{
if (!b->namespace_p)
{
}
else
{
- tree binding = binding_for_name (id, current_namespace);
+ cxx_binding *binding =
+ binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
BINDING_TYPE (binding) = type;
/* Store marker instead of real type. */
type = global_type_node;
/* As set_identifier_type_value_with_scope, but using current_binding_level. */
void
-set_identifier_type_value (id, type)
- tree id;
- tree type;
+set_identifier_type_value (tree id, tree type)
{
set_identifier_type_value_with_scope (id, type, current_binding_level);
}
/* Return the type associated with id. */
tree
-identifier_type_value (id)
- tree id;
+identifier_type_value (tree id)
{
+ timevar_push (TV_NAME_LOOKUP);
/* There is no type with that name, anywhere. */
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
/* This is not the type marker, but the real thing. */
if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
- return REAL_IDENTIFIER_TYPE_VALUE (id);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
/* Have to search for it. It must be on the global level, now.
- Ask lookup_name not to return non-types. */
- id = lookup_name_real (id, 2, 1, 0);
+ Ask lookup_name not to return non-types. */
+ id = lookup_name_real (id, 2, 1, 0, LOOKUP_COMPLAIN);
if (id)
- return TREE_TYPE (id);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* Pop off extraneous binding levels left over due to syntax errors.
We don't pop past namespaces, as they might be valid. */
void
-pop_everything ()
+pop_everything (void)
{
#ifdef DEBUG_BINDING_LEVELS
fprintf (stderr, "XXX entering pop_everything ()\n");
processing. */
static tree
-maybe_process_template_type_declaration (type, globalize, b)
- tree type;
- int globalize;
- struct cp_binding_level* b;
+maybe_process_template_type_declaration (tree type,
+ int globalize,
+ struct cp_binding_level* b)
{
tree decl = TYPE_NAME (type);
the TYPE_DECL for TYPE. */
tree
-create_implicit_typedef (name, type)
- tree name;
- tree type;
+create_implicit_typedef (tree name, tree type)
{
tree decl;
/* Remember a local name for name-mangling purposes. */
static void
-push_local_name (decl)
- tree decl;
+push_local_name (tree decl)
{
size_t i, nelts;
tree t, name;
+ timevar_push (TV_NAME_LOOKUP);
if (!local_names)
VARRAY_TREE_INIT (local_names, 8, "local_names");
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
+ timevar_pop (TV_NAME_LOOKUP);
return;
}
}
VARRAY_PUSH_TREE (local_names, decl);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push a tag name NAME for struct/class/union/enum type TYPE.
The latter is needed for implicit declarations. */
void
-pushtag (name, type, globalize)
- tree name, type;
- int globalize;
+pushtag (tree name, tree type, int globalize)
{
register struct cp_binding_level *b;
+ timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
while (b->tag_transparent
|| (b->parm_flag == 2
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Counter used to create anonymous type names. */
-static int anon_cnt = 0;
+static GTY(()) int anon_cnt;
/* Return an IDENTIFIER which can be used as a name for
anonymous structs and unions. */
tree
-make_anon_name ()
+make_anon_name (void)
{
char buf[32];
This keeps dbxout from getting confused. */
void
-clear_anon_tags ()
+clear_anon_tags (void)
{
register struct cp_binding_level *b;
register tree tags;
`const int&'. */
int
-decls_match (newdecl, olddecl)
- tree newdecl, olddecl;
+decls_match (tree newdecl, tree olddecl)
{
int types_match;
the user's control. */
static void
-warn_extern_redeclared_static (newdecl, olddecl)
- tree newdecl, olddecl;
+warn_extern_redeclared_static (tree newdecl, tree olddecl)
{
static const char *const explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
Otherwise, return 0. */
int
-duplicate_decls (newdecl, olddecl)
- tree newdecl, olddecl;
+duplicate_decls (tree newdecl, tree olddecl)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning_with_decl (newdecl,
- "function `%s' redeclared as inline");
- warning_with_decl (olddecl,
- "previous declaration of function `%s' with attribute noinline");
+ warning ("%Hfunction '%D' redeclared as inline",
+ &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ warning ("%Hprevious declaration of '%D' with attribute noinline",
+ &DECL_SOURCE_LOCATION (olddecl), olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warning_with_decl (newdecl,
- "function `%s' redeclared with attribute noinline");
- warning_with_decl (olddecl,
- "previous declaration of function `%s' was inline");
+ warning ("%Hfunction '%D' redeclared with attribute noinline",
+ &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ warning ("%Hprevious declaration of '%D' was inline",
+ &DECL_SOURCE_LOCATION (olddecl), olddecl);
}
}
/* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
+ /* Even if the types match, prefer the new declarations type
+ for anitipated built-ins, for exception lists, etc... */
+ else if (DECL_ANTICIPATED (olddecl))
+ TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
{
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
- DECL_TEMPLATE_PARMS (olddecl)))
+ DECL_TEMPLATE_PARMS (olddecl))
+ /* Template functions can be disambiguated by
+ return type. */
+ && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+ TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
- DECL_NO_LIMIT_STACK (newdecl)
- |= DECL_NO_LIMIT_STACK (olddecl);
+ DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
+ TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+ TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+ TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
+ DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+ DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl));
- DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
+ /* DECL_THUNKS is only valid for virtual functions,
+ otherwise it is a DECL_FRIEND_CONTEXT. */
+ if (DECL_VIRTUAL_P (newdecl))
+ DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
}
}
{
/* If newdecl is not a specialization, then it is not a
template-related function at all. And that means that we
- shoud have exited above, returning 0. */
+ should have exited above, returning 0. */
my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
0);
to agree with what X says. */
tree
-pushdecl (x)
- tree x;
+pushdecl (tree x)
{
register tree t;
register tree name;
int need_new_binding;
+ timevar_push (TV_NAME_LOOKUP);
/* We shouldn't be calling pushdecl when we're generating RTL for a
function that we already did semantic analysis on previously. */
my_friendly_assert (!cfun || doing_semantic_analysis_p (),
/* Check for duplicate params. */
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|| DECL_FUNCTION_TEMPLATE_P (x))
TREE_TYPE (x));
/* Throw away the redeclaration. */
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (duplicate_decls (x, t))
{
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (DECL_MAIN_P (x))
{
error ("as `%D'", x);
/* We don't try to push this declaration since that
causes a crash. */
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
}
{
t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x)
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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
t = push_overloaded_decl (x, PUSH_GLOBAL);
if (t == x)
add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* If declaring a type as a typedef, copy the type (unless we're
&& t != NULL_TREE)
&& (TREE_CODE (x) == TYPE_DECL
|| TREE_CODE (x) == VAR_DECL
+ || TREE_CODE (x) == ALIAS_DECL
|| TREE_CODE (x) == NAMESPACE_DECL
|| TREE_CODE (x) == CONST_DECL
|| TREE_CODE (x) == TEMPLATE_DECL))
if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
/* Inline decls shadow nothing. */
&& !DECL_FROM_INLINE (x)
- && TREE_CODE (oldlocal) == PARM_DECL)
+ && TREE_CODE (oldlocal) == PARM_DECL
+ /* Don't check the `this' parameter. */
+ && !DECL_ARTIFICIAL (oldlocal))
{
bool err = false;
them there. */
struct cp_binding_level *b = current_binding_level->level_chain;
+ /* Skip the ctor/dtor cleanup level. */
+ b = b->level_chain;
+
/* ARM $8.3 */
if (b->parm_flag == 1)
{
}
if (warn_shadow && !err)
- shadow_warning ("a parameter", name, oldlocal);
+ shadow_warning (SW_PARAM,
+ IDENTIFIER_POINTER (name), oldlocal);
}
/* Maybe warn if shadowing something else. */
IDENTIFIER_POINTER (name));
else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL)
- shadow_warning ("a previous local", name, oldlocal);
+ shadow_warning (SW_LOCAL,
+ IDENTIFIER_POINTER (name), oldlocal);
else if (oldglobal != NULL_TREE
&& TREE_CODE (oldglobal) == VAR_DECL)
/* XXX shadow warnings in outer-more namespaces */
- shadow_warning ("a global declaration", name, oldglobal);
+ shadow_warning (SW_GLOBAL,
+ IDENTIFIER_POINTER (name), oldglobal);
}
}
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
: current_binding_level);
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the
caller to set DECL_CONTEXT properly. */
static tree
-pushdecl_with_scope (x, level)
- tree x;
- struct cp_binding_level *level;
+pushdecl_with_scope (tree x, struct cp_binding_level* level)
{
register struct cp_binding_level *b;
tree function_decl = current_function_decl;
+ timevar_push (TV_NAME_LOOKUP);
current_function_decl = NULL_TREE;
if (level->parm_flag == 2)
{
current_binding_level = b;
}
current_function_decl = function_decl;
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Like pushdecl, only it places X in the current namespace,
if appropriate. */
tree
-pushdecl_namespace_level (x)
- tree x;
+pushdecl_namespace_level (tree x)
{
register struct cp_binding_level *b = current_binding_level;
register tree t;
+ timevar_push (TV_NAME_LOOKUP);
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
/* Now, the type_shadowed stack may screw us. Munge it so it does
*ptr = newval;
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
if appropriate. */
tree
-pushdecl_top_level (x)
- tree x;
+pushdecl_top_level (tree x)
{
+ timevar_push (TV_NAME_LOOKUP);
push_to_top_level ();
x = pushdecl_namespace_level (x);
pop_from_top_level ();
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Make the declaration of X appear in CLASS scope. */
void
-pushdecl_class_level (x)
- tree x;
+pushdecl_class_level (tree x)
{
tree name;
+ timevar_push (TV_NAME_LOOKUP);
/* Get the name of X. */
if (TREE_CODE (x) == OVERLOAD)
name = DECL_NAME (get_first_fn (x));
for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
pushdecl_class_level (f);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Enter DECL into the symbol table, if that's appropriate. Returns
DECL, or a modified version thereof. */
tree
-maybe_push_decl (decl)
- tree decl;
+maybe_push_decl (tree decl)
{
tree type = TREE_TYPE (decl);
under the name NAME. */
void
-push_class_level_binding (name, x)
- tree name;
- tree x;
+push_class_level_binding (tree name, tree x)
{
- tree binding;
+ cxx_binding *binding;
+ timevar_push (TV_NAME_LOOKUP);
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
- return;
+ {
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
+ }
/* Make sure that this new member does not have the same name
as a template parameter. */
INHERITED_VALUE_BINDING_P (binding) = 0;
TREE_TYPE (shadow) = x;
IDENTIFIER_CLASS_VALUE (name) = x;
+ timevar_pop (TV_NAME_LOOKUP);
return;
}
}
what to pop later. */
TREE_TYPE (class_binding_level->class_shadowed) = x;
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Insert another USING_DECL into the current binding level, returning
scope, a using decl might extend any previous bindings). */
tree
-push_using_decl (scope, name)
- tree scope;
- tree name;
+push_using_decl (tree scope, tree name)
{
tree decl;
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
break;
if (decl)
- return namespace_bindings_p () ? decl : NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ namespace_bindings_p () ? decl : NULL_TREE);
decl = build_lang_decl (USING_DECL, name, void_type_node);
DECL_INITIAL (decl) = scope;
TREE_CHAIN (decl) = current_binding_level->usings;
current_binding_level->usings = decl;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Add namespace to using_directives. Return NULL_TREE if nothing was
TREE_LIST otherwise. */
tree
-push_using_directive (used)
- tree used;
+push_using_directive (tree used)
{
tree ud = current_binding_level->using_directives;
tree iter, ancestor;
+ timevar_push (TV_NAME_LOOKUP);
/* Check if we already have this. */
if (purpose_member (used, ud) != NULL_TREE)
- return NULL_TREE;
-
- /* Recursively add all namespaces used. */
- for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
- push_using_directive (TREE_PURPOSE (iter));
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
ancestor = namespace_ancestor (current_decl_namespace (), used);
ud = current_binding_level->using_directives;
ud = tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
- return ud;
+
+ /* Recursively add all namespaces used. */
+ for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+ push_using_directive (TREE_PURPOSE (iter));
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ud);
}
/* DECL is a FUNCTION_DECL for a non-member function, which may have
it's always DECL (and never something that's not a _DECL). */
tree
-push_overloaded_decl (decl, flags)
- tree decl;
- int flags;
+push_overloaded_decl (tree decl, int flags)
{
tree name = DECL_NAME (decl);
tree old;
tree new_binding;
int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
+ timevar_push (TV_NAME_LOOKUP);
if (doing_global)
old = namespace_binding (name, DECL_CONTEXT (decl));
else
decl, fn);
if (duplicate_decls (decl, fn))
- return fn;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
}
}
else if (old == error_mark_node)
{
cp_error_at ("previous non-function declaration `%#D'", old);
error ("conflicts with function declaration `%#D'", decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
}
{
tree *d;
- for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+ for (d = &BINDING_SCOPE (IDENTIFIER_BINDING (name))->names;
*d;
d = &TREE_CHAIN (*d))
if (*d == old
*d = tree_cons (NULL_TREE, new_binding,
TREE_CHAIN (*d));
- /* And update the CPLUS_BINDING node. */
+ /* And update the cxx_binding node. */
BINDING_VALUE (IDENTIFIER_BINDING (name))
= new_binding;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* We should always find a previous binding in this case. */
push_local_binding (name, new_binding, flags);
}
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
\f
/* Generate an implicit declaration for identifier FUNCTIONID
as a function of type int (). Print a warning if appropriate. */
tree
-implicitly_declare (functionid)
- tree functionid;
+implicitly_declare (tree functionid)
{
register tree decl;
where the identifier should go. */
static const char *
-redeclaration_error_message (newdecl, olddecl)
- tree newdecl, olddecl;
+redeclaration_error_message (tree newdecl, tree olddecl)
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
/* Create a new label, named ID. */
static tree
-make_label_decl (id, local_p)
- tree id;
- int local_p;
+make_label_decl (tree id, int local_p)
{
tree decl;
this use is valid. */
static void
-use_label (decl)
- tree decl;
+use_label (tree decl)
{
if (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
labels, and complain about them at the end of a function.) */
tree
-lookup_label (id)
- tree id;
+lookup_label (tree id)
{
tree decl;
struct named_label_list *ent;
+ timevar_push (TV_NAME_LOOKUP);
/* You can't use labels at global scope. */
if (current_function_decl == NULL_TREE)
{
error ("label `%s' referenced outside of any function",
IDENTIFIER_POINTER (id));
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* See if we've already got this label. */
decl = IDENTIFIER_LABEL_VALUE (id);
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
/* Now fill in the information we didn't have before. */
ent->label_decl = decl;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Declare a local label named ID. */
tree
-declare_local_label (id)
- tree id;
+declare_local_label (tree id)
{
tree decl;
DECL. Returns 2 if it's also a real problem. */
static int
-decl_jump_unsafe (decl)
- tree decl;
+decl_jump_unsafe (tree decl)
{
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
return 0;
context; FILE and LINE are the source position of the jump or 0. */
static void
-check_previous_goto_1 (decl, level, names, file, line)
- tree decl;
- struct cp_binding_level *level;
- tree names;
- const char *file;
- int line;
+check_previous_goto_1 (tree decl,
+ struct cp_binding_level* level,
+ tree names,
+ const char* file,
+ int line)
{
int identified = 0;
int saw_eh = 0;
}
static void
-check_previous_goto (use)
- struct named_label_use_list *use;
+check_previous_goto (struct named_label_use_list* use)
{
check_previous_goto_1 (use->label_decl, use->binding_level,
use->names_in_scope, use->filename_o_goto,
}
static void
-check_switch_goto (level)
- struct cp_binding_level *level;
+check_switch_goto (struct cp_binding_level* level)
{
check_previous_goto_1 (NULL_TREE, level, level->names, NULL, 0);
}
are OK. Called by define_label. */
static void
-check_previous_gotos (decl)
- tree decl;
+check_previous_gotos (tree decl)
{
struct named_label_use_list **usep;
finish_goto_stmt. */
void
-check_goto (decl)
- tree decl;
+check_goto (tree decl)
{
int identified = 0;
tree bad;
Otherwise return 0. */
tree
-define_label (filename, line, name)
- const char *filename;
- int line;
- tree name;
+define_label (const char* filename, int line, tree name)
{
tree decl = lookup_label (name);
struct named_label_list *ent;
register struct cp_binding_level *p;
+ timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
break;
if (DECL_INITIAL (decl) != NULL_TREE)
{
error ("duplicate label `%D'", decl);
- return 0;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
else
{
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct cp_switch
SWITCH_STMT is the switch statement being parsed. */
void
-push_switch (switch_stmt)
- tree switch_stmt;
+push_switch (tree switch_stmt)
{
struct cp_switch *p
= (struct cp_switch *) xmalloc (sizeof (struct cp_switch));
}
void
-pop_switch ()
+pop_switch (void)
{
struct cp_switch *cs;
is a bad place for one. */
tree
-finish_case_label (low_value, high_value)
- tree low_value;
- tree high_value;
+finish_case_label (tree low_value, tree high_value)
{
tree cond, r;
register struct cp_binding_level *p;
cond = TREE_VALUE (cond);
r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
- if (r == error_mark_node)
- r = NULL_TREE;
check_switch_goto (switch_stack->level);
store the result back using `storedecls' or you will lose. */
tree
-getdecls ()
+getdecls (void)
{
return current_binding_level->names;
}
/* Return the list of type-tags (for structs, etc) of the current level. */
tree
-gettags ()
+gettags (void)
{
return current_binding_level->tags;
}
after they are modified in the light of any missing parameters. */
static void
-storedecls (decls)
- tree decls;
+storedecls (tree decls)
{
current_binding_level->names = decls;
}
/* Similarly, store the list of tags of the current level. */
void
-storetags (tags)
- tree tags;
+storetags (tree tags)
{
current_binding_level->tags = tags;
}
Return null for this case. */
static tree
-follow_tag_typedef (type)
- tree type;
+follow_tag_typedef (tree type)
{
tree original;
/* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name.
- Searches binding levels from BINDING_LEVEL up to the global level.
+ Searches binding levels from BINDING_SCOPE up to the global level.
If THISLEVEL_ONLY is nonzero, searches only the specified context
(but skips any tag-transparent contexts to find one that is
meaningful for tags).
reported. */
static tree
-lookup_tag (form, name, binding_level, thislevel_only)
- enum tree_code form;
- tree name;
- struct cp_binding_level *binding_level;
- int thislevel_only;
+lookup_tag (enum tree_code form, tree name,
+ struct cp_binding_level* binding_level, int thislevel_only)
{
register struct cp_binding_level *level;
/* Nonzero if, we should look past a template parameter level, even
if THISLEVEL_ONLY. */
int allow_template_parms_p = 1;
+ timevar_push (TV_NAME_LOOKUP);
for (level = binding_level; level; level = level->level_chain)
{
register tree tail;
/* There's no need for error checking here, because
anon names are unique throughout the compilation. */
if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
- return TREE_VALUE (tail);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (tail));
}
else if (level->namespace_p)
/* Do namespace lookup. */
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
- tree old = binding_for_name (name, tail);
+ cxx_binding *binding =
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (tail), name);
+ tree old;
/* If we just skipped past a template parameter level,
even though THISLEVEL_ONLY, and we find a template
class declaration, then we use the _TYPE node for the
template. See the example below. */
if (thislevel_only && !allow_template_parms_p
- && old && BINDING_VALUE (old)
- && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
- old = TREE_TYPE (BINDING_VALUE (old));
- else
- old = BINDING_TYPE (old);
+ && binding && BINDING_VALUE (binding)
+ && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
+ old = TREE_TYPE (BINDING_VALUE (binding));
+ else if (binding)
+ old = BINDING_TYPE (binding);
+ else
+ old = NULL_TREE;
if (old)
{
if the typedef doesn't refer to a taggable type. */
old = follow_tag_typedef (old);
if (!old)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
|| TREE_CODE (old) == ENUMERAL_TYPE))
{
error ("`%#D' redeclared as %C", old, form);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
- return old;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
}
if (thislevel_only || tail == global_namespace)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
else
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
/* Definition isn't the kind we were looking for. */
error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
- return TREE_VALUE (tail);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (tail));
}
}
if (thislevel_only && ! level->tag_transparent)
continue;
}
else
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
-#if 0
-void
-set_current_level_tags_transparency (tags_transparent)
- int tags_transparent;
-{
- current_binding_level->tag_transparent = tags_transparent;
-}
-#endif
-
/* Given a type, find the tag that was defined for it and return the tag name.
Otherwise return 0. However, the value can never be 0
in the cases in which this is used.
done when replacing anonymous tags with real tag names. */
static tree
-lookup_tag_reverse (type, name)
- tree type;
- tree name;
+lookup_tag_reverse (tree type, tree name)
{
register struct cp_binding_level *level;
+ timevar_push (TV_NAME_LOOKUP);
for (level = current_binding_level; level; level = level->level_chain)
{
register tree tail;
{
if (name)
TREE_PURPOSE (tail) = name;
- return TREE_PURPOSE (tail);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_PURPOSE (tail));
}
}
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
\f
/* Look up NAME in the NAMESPACE. */
tree
-lookup_namespace_name (namespace, name)
- tree namespace, name;
+lookup_namespace_name (tree namespace, tree name)
{
tree val;
tree template_id = NULL_TREE;
+ cxx_binding binding;
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
if (TREE_CODE (name) == NAMESPACE_DECL)
/* This happens for A::B<int> when B is a namespace. */
- return name;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
else if (TREE_CODE (name) == TEMPLATE_DECL)
{
/* This happens for A::B where B is a template, and there are no
template arguments. */
error ("invalid use of `%D'", name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
namespace = ORIGINAL_NAMESPACE (namespace);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
- val = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (name, namespace, val, 0))
- return error_mark_node;
+ cxx_binding_clear (&binding);
+ if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- if (BINDING_VALUE (val))
+ if (binding.value)
{
- val = BINDING_VALUE (val);
+ val = binding.value;
if (template_id)
{
{
error ("`%D::%D' is not a template",
namespace, name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
if (!val || !DECL_P(val)
|| !DECL_LANG_SPECIFIC(val)
|| !DECL_ANTICIPATED (val))
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
error ("`%D' undeclared in namespace `%D'", name, namespace);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
static hashval_t
-typename_hash (k)
- const void * k;
+typename_hash (const void* k)
{
hashval_t hash;
tree t = (tree) k;
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
static int
-typename_compare (k1, k2)
- const void * k1;
- const void * k2;
+typename_compare (const void * k1, const void * k2)
{
tree t1;
tree t2;
static GTY ((param_is (union tree_node))) htab_t typename_htab;
tree
-build_typename_type (context, name, fullname, base_type)
- tree context;
- tree name;
- tree fullname;
- tree base_type;
+build_typename_type (tree context, tree name, tree fullname)
{
tree t;
tree d;
t = make_aggr_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);
complain about errors, otherwise be quiet. */
tree
-make_typename_type (context, name, complain)
- tree context, name;
- tsubst_flags_t complain;
+make_typename_type (tree context, tree name, tsubst_flags_t complain)
{
tree fullname;
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
- tmpl = lookup_field (context, name, 0, 0);
+ tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
return error_mark_node;
}
- if (complain & tf_parsing)
- type_access_control (context, tmpl);
- else
- enforce_access (context, tmpl);
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ perform_or_defer_access_check (context, tmpl);
+ else
+ enforce_access (context, tmpl);
+ }
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
return error_mark_node;
}
- t = lookup_field (context, name, 0, 1);
+ t = lookup_field (context, name, 0, true);
if (t)
{
if (TREE_CODE (t) != TYPE_DECL)
return error_mark_node;
}
- if (complain & tf_parsing)
- type_access_control (context, t);
- else
- enforce_access (context, t);
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ perform_or_defer_access_check (context, t);
+ else
+ enforce_access (context, t);
+ }
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
- if (IMPLICIT_TYPENAME_P (t))
- {
- /* Lookup found an implicit typename that we had
- injected into the current scope. Doing things
- properly would have located the exact same type,
- so there is no error here. We must remove the
- implicitness so that we do not warn about it. */
- t = copy_node (t);
- TREE_TYPE (t) = NULL_TREE;
- }
return t;
}
return error_mark_node;
}
- return build_typename_type (context, name, fullname, NULL_TREE);
+ return build_typename_type (context, name, fullname);
}
/* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
that occur. */
tree
-make_unbound_class_template (context, name, complain)
- tree context, name;
- int complain;
+make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
{
tree t;
tree d;
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
- tmpl = lookup_field (context, name, 0, 0);
+ tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
- if (complain)
+ if (complain & tf_error)
error ("no class template named `%#T' in `%#T'", name, context);
return error_mark_node;
}
- if (complain & tf_parsing)
- type_access_control (context, tmpl);
- else
- enforce_access (context, tmpl);
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ perform_or_defer_access_check (context, tmpl);
+ else
+ enforce_access (context, tmpl);
+ }
return tmpl;
}
/* Select the right _DECL from multiple choices. */
static tree
-select_decl (binding, flags)
- tree binding;
- int flags;
+select_decl (cxx_binding *binding, int flags)
{
tree val;
val = BINDING_VALUE (binding);
+ timevar_push (TV_NAME_LOOKUP);
if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
if (val && TREE_CODE (val) == NAMESPACE_DECL)
- return val;
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* If we could have a type and
|| !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Unscoped lookup of a global: iterate over current namespaces,
of the namespaces we've considered in it. */
tree
-unqualified_namespace_lookup (name, flags, spacesp)
- tree name;
- int flags;
- tree *spacesp;
+unqualified_namespace_lookup (tree name, int flags, tree* spacesp)
{
- tree b = make_node (CPLUS_BINDING);
tree initial = current_decl_namespace ();
tree scope = initial;
tree siter;
struct cp_binding_level *level;
tree val = NULL_TREE;
+ cxx_binding binding;
+ timevar_push (TV_NAME_LOOKUP);
+ cxx_binding_clear (&binding);
if (spacesp)
*spacesp = NULL_TREE;
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
+ cxx_binding *b =
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
if (spacesp)
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
- val = binding_for_name (name, scope);
/* Ignore anticipated built-in functions. */
- if (val && BINDING_VALUE (val)
- && DECL_P (BINDING_VALUE (val))
- && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
- && DECL_ANTICIPATED (BINDING_VALUE (val)))
- {
- BINDING_VALUE (b) = NULL_TREE;
- BINDING_TYPE (b) = NULL_TREE;
- }
- else
+ if (b && BINDING_VALUE (b)
+ && DECL_P (BINDING_VALUE (b))
+ && DECL_LANG_SPECIFIC (BINDING_VALUE (b))
+ && DECL_ANTICIPATED (BINDING_VALUE (b)))
+ /* Keep binding cleared. */;
+ else if (b)
{
/* Initialize binding for this context. */
- BINDING_VALUE (b) = BINDING_VALUE (val);
- BINDING_TYPE (b) = BINDING_TYPE (val);
+ binding.value = BINDING_VALUE (b);
+ binding.type = BINDING_TYPE (b);
}
/* Add all _DECLs seen through local using-directives. */
for (level = current_binding_level;
!level->namespace_p;
level = level->level_chain)
- if (!lookup_using_namespace (name, b, level->using_directives,
+ if (!lookup_using_namespace (name, &binding, level->using_directives,
scope, flags, spacesp))
/* Give up because of error. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
/* Add all _DECLs seen through global using-directives. */
/* XXX local and global using lists should work equally. */
siter = initial;
while (1)
{
- if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
+ if (!lookup_using_namespace (name, &binding,
+ DECL_NAMESPACE_USING (siter),
scope, flags, spacesp))
/* Give up because of error. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
- val = select_decl (b, flags);
+ val = select_decl (&binding, flags);
if (scope == global_namespace)
break;
}
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Combine prefer_type and namespaces_only into flags. */
static int
-lookup_flags (prefer_type, namespaces_only)
- int prefer_type, namespaces_only;
+lookup_flags (int prefer_type, int namespaces_only)
{
if (namespaces_only)
return LOOKUP_PREFER_NAMESPACES;
ignore it or not. Subroutine of lookup_name_real. */
static tree
-qualify_lookup (val, flags)
- tree val;
- int flags;
+qualify_lookup (tree val, int flags)
{
if (val == NULL_TREE)
return val;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val;
- if ((flags & LOOKUP_PREFER_TYPES)
- && (TREE_CODE (val) == TYPE_DECL
- || ((flags & LOOKUP_TEMPLATES_EXPECTED)
- && DECL_CLASS_TEMPLATE_P (val))))
+ if ((flags & LOOKUP_PREFER_TYPES) && TREE_CODE (val) == TYPE_DECL)
return val;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return NULL_TREE;
return val;
}
-/* Any other BINDING overrides an implicit TYPENAME. Warn about
- that. */
+/* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL
+ or a class TYPE). If IS_TYPE_P is TRUE, then ignore non-type
+ bindings.
-static void
-warn_about_implicit_typename_lookup (typename, binding)
- tree typename;
- tree binding;
-{
- tree subtype = TREE_TYPE (TREE_TYPE (typename));
- tree name = DECL_NAME (typename);
+ Returns a DECL (or OVERLOAD, or BASELINK) representing the
+ declaration found. */
- if (! (TREE_CODE (binding) == TEMPLATE_DECL
- && CLASSTYPE_TEMPLATE_INFO (subtype)
- && CLASSTYPE_TI_TEMPLATE (subtype) == binding)
- && ! (TREE_CODE (binding) == TYPE_DECL
- && same_type_p (TREE_TYPE (binding), subtype)))
+tree
+lookup_qualified_name (tree scope, tree name, bool is_type_p, int flags)
+{
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
{
- warning ("lookup of `%D' finds `%#D'",
- name, binding);
- warning (" instead of `%D' from dependent base class",
- typename);
- warning (" (use `typename %T::%D' if that's what you meant)",
- constructor_name (current_class_type), name);
+ cxx_binding binding;
+
+ cxx_binding_clear (&binding);
+ flags |= LOOKUP_COMPLAIN;
+ if (is_type_p)
+ flags |= LOOKUP_PREFER_TYPES;
+ if (!qualified_lookup_using_namespace (name, scope, &binding, flags))
+ return NULL_TREE;
+ return select_decl (&binding, flags);
}
+ else
+ return lookup_member (scope, name, 0, is_type_p);
}
/* Check to see whether or not DECL is a variable that would have been
If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
- If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs.
If NONCLASS is nonzero, we don't look for the NAME in class scope,
using IDENTIFIER_CLASS_VALUE. */
-static tree
-lookup_name_real (name, prefer_type, nonclass, namespaces_only)
- tree name;
- int prefer_type, nonclass, namespaces_only;
+tree
+lookup_name_real (tree name, int prefer_type, int nonclass,
+ int namespaces_only, int flags)
{
- tree t;
+ cxx_binding *iter;
tree val = NULL_TREE;
- int yylex = 0;
- tree from_obj = NULL_TREE;
- int flags;
- int val_is_implicit_typename = 0;
- /* Hack: copy flag set by parser, if set. */
- if (only_namespace_names)
- namespaces_only = 1;
-
- if (prefer_type == -2)
+ timevar_push (TV_NAME_LOOKUP);
+ /* Conversion operators are handled specially because ordinary
+ unqualified name lookup will not find template conversion
+ operators. */
+ if (IDENTIFIER_TYPENAME_P (name))
{
- extern int looking_for_typename;
- tree type = NULL_TREE;
+ struct cp_binding_level *level;
- yylex = 1;
- prefer_type = looking_for_typename;
-
- flags = lookup_flags (prefer_type, namespaces_only);
- /* If the next thing is '<', class templates are types. */
- if (looking_for_template)
- flags |= LOOKUP_TEMPLATES_EXPECTED;
-
- if (got_scope)
- type = got_scope;
- else if (got_object != error_mark_node)
- type = got_object;
-
- if (type)
+ for (level = current_binding_level;
+ level && !level->namespace_p;
+ level = level->level_chain)
{
- if (type == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
- type = TREE_TYPE (type);
-
- if (TYPE_P (type))
- type = complete_type (type);
-
- if (TREE_CODE (type) == VOID_TYPE)
- type = global_namespace;
- if (TREE_CODE (type) == NAMESPACE_DECL)
- {
- val = make_node (CPLUS_BINDING);
- flags |= LOOKUP_COMPLAIN;
- if (!qualified_lookup_using_namespace (name, type, val, flags))
- return NULL_TREE;
- val = select_decl (val, flags);
- }
- else if (! IS_AGGR_TYPE (type)
- || TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (type) == TYPENAME_TYPE)
- /* Someone else will give an error about this if needed. */
- val = NULL_TREE;
- else if (type == current_class_type)
- val = IDENTIFIER_CLASS_VALUE (name);
- else
- {
- val = lookup_member (type, name, 0, prefer_type);
- if (!uses_template_parms (type))
- type_access_control (type, val);
-
- /* Restore the containing TYPENAME_TYPE if we looked
- through it before. */
- if (got_scope && got_scope != type
- && val && TREE_CODE (val) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (val)) == TYPENAME_TYPE)
- {
- val = TREE_TYPE (val);
- val = build_typename_type (got_scope, name,
- TYPENAME_TYPE_FULLNAME (val),
- TREE_TYPE (val));
- val = TYPE_STUB_DECL (val);
- }
- }
+ tree class_type;
+ tree operators;
+
+ /* A conversion operator can only be declared in a class
+ scope. */
+ if (level->parm_flag != 2)
+ continue;
+
+ /* Lookup the conversion operator in the class. */
+ class_type = level->this_class;
+ operators = lookup_fnfields (class_type, name, /*protect=*/0);
+ if (operators)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, operators);
}
- else
- val = NULL_TREE;
- if (got_scope)
- goto done;
- else if (got_object && val)
- {
- from_obj = val;
- val = NULL_TREE;
- }
- }
- else
- {
- flags = lookup_flags (prefer_type, namespaces_only);
- /* If we're not parsing, we need to complain. */
- flags |= LOOKUP_COMPLAIN;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
+ flags |= lookup_flags (prefer_type, namespaces_only);
+
/* First, look in non-namespace scopes. */
if (current_class_type == NULL_TREE)
nonclass = 1;
- for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
+ for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
{
tree binding;
- if (!LOCAL_BINDING_P (t) && nonclass)
+ if (!LOCAL_BINDING_P (iter) && 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 (t), flags))
- binding = BINDING_VALUE (t);
+ if (qualify_lookup (BINDING_VALUE (iter), flags))
+ binding = BINDING_VALUE (iter);
else if ((flags & LOOKUP_PREFER_TYPES)
- && qualify_lookup (BINDING_TYPE (t), flags))
- binding = BINDING_TYPE (t);
+ && qualify_lookup (BINDING_TYPE (iter), flags))
+ binding = BINDING_TYPE (iter);
else
binding = NULL_TREE;
- /* Handle access control on types from enclosing or base classes. */
- if (binding && ! yylex
- && BINDING_LEVEL (t) && BINDING_LEVEL (t)->parm_flag == 2)
- type_access_control (BINDING_LEVEL (t)->this_class, binding);
-
- if (binding
- && (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
+ if (binding)
{
- if (val_is_implicit_typename && !yylex)
- warn_about_implicit_typename_lookup (val, binding);
val = binding;
- val_is_implicit_typename
- = IMPLICIT_TYPENAME_TYPE_DECL_P (val);
- if (!val_is_implicit_typename)
- break;
+ break;
}
}
/* Now lookup in namespace scopes. */
- if (!val || val_is_implicit_typename)
+ if (!val)
{
- t = unqualified_namespace_lookup (name, flags, 0);
+ tree t = unqualified_namespace_lookup (name, flags, 0);
if (t)
- {
- if (val_is_implicit_typename && !yylex)
- warn_about_implicit_typename_lookup (val, t);
- val = t;
- }
+ val = t;
}
- done:
if (val)
{
- /* This should only warn about types used in qualified-ids. */
- if (from_obj && from_obj != val)
- {
- if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
- && TREE_CODE (val) == TYPE_DECL
- && ! same_type_p (TREE_TYPE (from_obj), TREE_TYPE (val)))
- pedwarn ("\
-lookup of `%D' in the scope of `%#T' (`%#D') \
-does not match lookup in the current scope (`%#D')",
- name, got_object, from_obj, val);
-
- /* We don't change val to from_obj if got_object depends on
- template parms because that breaks implicit typename for
- destructor calls. */
- if (! uses_template_parms (got_object))
- val = from_obj;
- }
-
/* 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);
}
- else if (from_obj)
- val = from_obj;
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
tree
-lookup_name_nonclass (name)
- tree name;
+lookup_name_nonclass (tree name)
{
- return lookup_name_real (name, 0, 1, 0);
+ return lookup_name_real (name, 0, 1, 0, LOOKUP_COMPLAIN);
}
tree
-lookup_function_nonclass (name, args)
- tree name;
- tree args;
+lookup_function_nonclass (tree name, tree args)
{
return lookup_arg_dependent (name, lookup_name_nonclass (name), args);
}
tree
-lookup_name_namespace_only (name)
- tree name;
+lookup_name (tree name, int prefer_type)
{
- /* type-or-namespace, nonclass, namespace_only */
- return lookup_name_real (name, 1, 1, 1);
-}
-
-tree
-lookup_name (name, prefer_type)
- tree name;
- int prefer_type;
-{
- return lookup_name_real (name, prefer_type, 0, 0);
+ return lookup_name_real (name, prefer_type, 0, 0, LOOKUP_COMPLAIN);
}
/* Similar to `lookup_name' but look only in the innermost non-class
binding level. */
tree
-lookup_name_current_level (name)
- tree name;
+lookup_name_current_level (tree name)
{
struct cp_binding_level *b;
tree t = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
{
while (1)
{
- if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
- return IDENTIFIER_VALUE (name);
+ if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Like lookup_name_current_level, but for types. */
tree
-lookup_type_current_level (name)
- tree name;
+lookup_type_current_level (tree name)
{
register tree t = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (! current_binding_level->namespace_p, 980716);
if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
while (1)
{
if (purpose_member (name, b->type_shadowed))
- return REAL_IDENTIFIER_TYPE_VALUE (name);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ REAL_IDENTIFIER_TYPE_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
else
}
}
- return t;
-}
-
-void
-begin_only_namespace_names ()
-{
- only_namespace_names = 1;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
-void
-end_only_namespace_names ()
-{
- only_namespace_names = 0;
-}
\f
/* Push the declarations of builtin types into the namespace.
RID_INDEX is the index of the builtin type
up the builtin type. TYPE is the _TYPE node for the builtin type. */
void
-record_builtin_type (rid_index, name, type)
- enum rid rid_index;
- const char *name;
- tree type;
+record_builtin_type (enum rid rid_index,
+ const char* name,
+ tree type)
{
tree rname = NULL_TREE, tname = NULL_TREE;
tree tdecl = NULL_TREE;
if (name)
tname = get_identifier (name);
- TYPE_BUILT_IN (type) = 1;
-
if (tname)
{
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
* otherwise it is the negative of the size of one of the other types. */
static tree
-record_builtin_java_type (name, size)
- const char *name;
- int size;
+record_builtin_java_type (const char* name, int size)
{
tree type, decl;
if (size > 0)
/* Push a type into the namespace so that the back-ends ignore it. */
static void
-record_unknown_type (type, name)
- tree type;
- const char *name;
+record_unknown_type (tree type, 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. */
/* Create all the predefined identifiers. */
static void
-initialize_predefined_identifiers ()
+initialize_predefined_identifiers (void)
{
const predefined_identifier *pid;
Make definitions for built-in primitive functions. */
void
-cxx_init_decl_processing ()
+cxx_init_decl_processing (void)
{
tree void_ftype;
tree void_ftype_ptr;
NAMESPACE_LEVEL (global_namespace) = global_binding_level;
declare_namespace_level ();
+ VARRAY_TREE_INIT (global_binding_level->static_decls,
+ 200,
+ "Static declarations");
+
/* Create the `std' namespace. */
push_namespace (std_identifier);
std_node = current_namespace;
ERROR_MARK node which should be replaced later. */
tree
-cp_fname_init (name)
- const char *name;
+cp_fname_init (const char* name)
{
tree domain = NULL_TREE;
tree type;
lazily at the point of first use, so we musn't push the decl now. */
static tree
-cp_make_fname_decl (id, type_dep)
- tree id;
- int type_dep;
+cp_make_fname_decl (tree id, int type_dep)
{
const char *const name = (type_dep && processing_template_decl
? NULL : fname_as_string (type_dep));
tree init = cp_fname_init (name);
tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
- /* As we don't push the decl here, we must set the context. */
+ /* As we're using pushdecl_with_scope, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
DECL_PRETTY_FUNCTION_P (decl) = type_dep;
TREE_USED (decl) = 1;
+ if (current_function_decl)
+ {
+ struct cp_binding_level *b = current_binding_level;
+ while (b->level_chain->parm_flag == 0)
+ b = b->level_chain;
+ pushdecl_with_scope (decl, b);
+ }
+
cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
return decl;
list. */
static tree
-builtin_function_1 (name, type, context, code, class, libname, attrs)
- const char *name;
- tree type;
- tree context;
- int code;
- enum built_in_class class;
- const char *libname;
- tree attrs;
+builtin_function_1 (const char* name,
+ tree type,
+ tree context,
+ int code,
+ enum built_in_class class,
+ const char* libname,
+ tree attrs)
{
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
list. */
tree
-builtin_function (name, type, code, class, libname, attrs)
- const char *name;
- tree type;
- int code;
- enum built_in_class class;
- const char *libname;
- tree attrs;
+builtin_function (const char* name,
+ tree type,
+ int code,
+ enum built_in_class class,
+ const char* libname,
+ tree attrs)
{
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
function. Not called directly. */
static tree
-build_library_fn_1 (name, operator_code, type)
- tree name;
- enum tree_code operator_code;
- tree type;
+build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
{
tree fn = build_lang_decl (FUNCTION_DECL, name, type);
DECL_EXTERNAL (fn) = 1;
callers should unset TREE_NOTHROW. */
tree
-build_library_fn (name, type)
- tree name;
- tree type;
+build_library_fn (tree name, tree type)
{
return build_library_fn_1 (name, ERROR_MARK, type);
}
/* Returns the _DECL for a library function with C++ linkage. */
static tree
-build_cp_library_fn (name, operator_code, type)
- tree name;
- enum tree_code operator_code;
- tree type;
+build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
{
tree fn = build_library_fn_1 (name, operator_code, type);
TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
IDENTIFIER_NODE. */
tree
-build_library_fn_ptr (name, type)
- const char *name;
- tree type;
+build_library_fn_ptr (const char* name, tree type)
{
return build_library_fn (get_identifier (name), type);
}
IDENTIFIER_NODE. */
tree
-build_cp_library_fn_ptr (name, type)
- const char *name;
- tree type;
+build_cp_library_fn_ptr (const char* name, tree type)
{
return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
}
be able to find it via IDENTIFIER_GLOBAL_VALUE. */
tree
-push_library_fn (name, type)
- tree name, type;
+push_library_fn (tree name, tree type)
{
tree fn = build_library_fn (name, type);
pushdecl_top_level (fn);
will be found by normal lookup. */
static tree
-push_cp_library_fn (operator_code, type)
- enum tree_code operator_code;
- tree type;
+push_cp_library_fn (enum tree_code operator_code, tree type)
{
tree fn = build_cp_library_fn (ansi_opname (operator_code),
operator_code,
a FUNCTION_TYPE. */
tree
-push_void_library_fn (name, parmtypes)
- tree name, parmtypes;
+push_void_library_fn (tree name, tree parmtypes)
{
tree type = build_function_type (void_type_node, parmtypes);
return push_library_fn (name, type);
and does not return. Used for __throw_foo and the like. */
tree
-push_throw_library_fn (name, type)
- tree name, type;
+push_throw_library_fn (tree name, tree type)
{
tree fn = push_library_fn (name, type);
TREE_THIS_VOLATILE (fn) = 1;
attributes. */
void
-cxx_insert_default_attributes (decl)
- tree decl;
+cxx_insert_default_attributes (tree decl)
{
if (!DECL_EXTERN_C_FUNCTION_P (decl))
return;
union type.) */
void
-fixup_anonymous_aggr (t)
- tree t;
+fixup_anonymous_aggr (tree t)
{
tree *q;
}
/* Make sure that a declaration with no declarator is well-formed, i.e.
- just defines a tagged type or anonymous union.
+ just declares a tagged type or anonymous union.
- Returns the type defined, if any. */
+ Returns the type declared; or NULL_TREE if none. */
tree
-check_tag_decl (declspecs)
- tree declspecs;
+check_tag_decl (tree declspecs)
{
int found_type = 0;
int saw_friend = 0;
int saw_typedef = 0;
tree ob_modifier = NULL_TREE;
register tree link;
- register tree t = NULL_TREE;
+ /* If a class, struct, or enum type is declared by the DECLSPECS
+ (i.e, if a class-specifier, enum-specifier, or non-typename
+ elaborated-type-specifier appears in the DECLSPECS),
+ DECLARED_TYPE is set to the corresponding type. */
+ tree declared_type = NULL_TREE;
+ bool error_p = false;
for (link = declspecs; link; link = TREE_CHAIN (link))
{
- register tree value = TREE_VALUE (link);
+ tree value = TREE_VALUE (link);
if (TYPE_P (value)
|| TREE_CODE (value) == TYPE_DECL
|| TREE_CODE (value) == ENUMERAL_TYPE))
{
my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
- t = value;
+ declared_type = value;
}
}
else if (value == ridpointers[(int) RID_TYPEDEF])
|| value == ridpointers[(int) RID_EXPLICIT]
|| value == ridpointers[(int) RID_THREAD])
ob_modifier = value;
+ else if (value == error_mark_node)
+ error_p = true;
}
if (found_type > 1)
error ("multiple types in one declaration");
- if (t == NULL_TREE && ! saw_friend)
+ if (declared_type == NULL_TREE && ! saw_friend && !error_p)
pedwarn ("declaration does not declare anything");
-
/* Check for an anonymous union. */
- else if (t && IS_AGGR_TYPE_CODE (TREE_CODE (t))
- && TYPE_ANONYMOUS_P (t))
+ else if (declared_type && IS_AGGR_TYPE_CODE (TREE_CODE (declared_type))
+ && TYPE_ANONYMOUS_P (declared_type))
{
/* 7/3 In a simple-declaration, the optional init-declarator-list
can be omitted only when declaring a class (clause 9) or
return NULL_TREE;
}
/* Anonymous unions are objects, so they can have specifiers. */;
- SET_ANON_AGGR_TYPE_P (t);
+ SET_ANON_AGGR_TYPE_P (declared_type);
- if (TREE_CODE (t) != UNION_TYPE && pedantic && ! in_system_header)
+ if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
+ && !in_system_header)
pedwarn ("ISO C++ prohibits anonymous structs");
}
ob_modifier);
}
- return t;
+ return declared_type;
}
/* Called when a declaration is seen that contains no names to declare.
Otherwise, it is an error.
C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions. */
+ complain for anonymous unions.
-void
-shadow_tag (declspecs)
- tree declspecs;
+ Returns the TYPE declared -- or NULL_TREE if none. */
+
+tree
+shadow_tag (tree declspecs)
{
tree t = check_tag_decl (declspecs);
- if (t)
- maybe_process_partial_specialization (t);
+ if (!t)
+ return NULL_TREE;
+
+ 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 (t && ANON_AGGR_TYPE_P (t))
+ if (ANON_AGGR_TYPE_P (t))
{
fixup_anonymous_aggr (t);
finish_anon_union (decl);
}
}
+
+ return t;
}
\f
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (typename)
- tree typename;
+groktypename (tree typename)
{
tree specs, attrs;
tree type;
grokfield and not through here. */
tree
-start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
- tree declarator, declspecs;
- int initialized;
- tree attributes, prefix_attributes;
+start_decl (tree declarator,
+ tree declspecs,
+ int initialized,
+ tree attributes,
+ tree prefix_attributes)
{
tree decl;
register tree type, tem;
tree context;
-#if 0
- /* See code below that used this. */
- int init_written = initialized;
-#endif
-
/* This should only be done once on the top most decl. */
if (have_extern_spec)
{
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
- warning_with_decl (decl,
- "inline function `%s' given attribute noinline");
+ warning ("%Hinline function '%D' given attribute noinline",
+ &DECL_SOURCE_LOCATION (decl), decl);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
- push_nested_class (context, 2);
+ push_nested_class (context);
if (TREE_CODE (decl) == VAR_DECL)
{
- tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
+ tree field = lookup_field (context, DECL_NAME (decl), 0, false);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
error ("`%#D' is not a static member of `%#T'", decl, context);
else
{
if (DECL_CONTEXT (field) != context)
{
- pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
- DECL_CONTEXT (field), DECL_NAME (decl),
- context, DECL_NAME (decl));
+ if (!same_type_p (DECL_CONTEXT (field), context))
+ pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
+ DECL_CONTEXT (field), DECL_NAME (decl),
+ context, DECL_NAME (decl));
DECL_CONTEXT (decl) = DECL_CONTEXT (field);
}
/* Static data member are tricky; an in-class initialization
wrong semantics. If we say -fno-conserve-space, we want this to
produce errors about redefs; to do this we force variables into the
data segment. */
- DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
+ DECL_COMMON (tem) = ((TREE_CODE (tem) != VAR_DECL
+ || !DECL_THREAD_LOCAL (tem))
+ && (flag_conserve_space || ! TREE_PUBLIC (tem)));
#endif
if (! processing_template_decl)
}
void
-start_decl_1 (decl)
- tree decl;
+start_decl_1 (tree decl)
{
tree type = TREE_TYPE (decl);
int initialized = (DECL_INITIAL (decl) != NULL_TREE);
Quotes on semantics can be found in ARM 8.4.3. */
static tree
-grok_reference_init (decl, type, init)
- tree decl, type, init;
+grok_reference_init (tree decl, tree type, tree init)
{
tree tmp;
return NULL_TREE;
}
- if (init == error_mark_node)
- return NULL_TREE;
-
if (TREE_CODE (init) == CONSTRUCTOR)
{
error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
- tmp = convert_to_reference
- (type, init, CONV_IMPLICIT,
- LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
- decl);
+ tmp = initialize_reference (type, init, decl);
if (tmp == error_mark_node)
return NULL_TREE;
situation we're in, update DECL accordingly. */
static void
-maybe_deduce_size_from_array_init (decl, init)
- tree decl;
- tree init;
+maybe_deduce_size_from_array_init (tree decl, tree init)
{
tree type = TREE_TYPE (decl);
any appropriate error messages regarding the layout. */
static void
-layout_var_decl (decl)
- tree decl;
+layout_var_decl (tree decl)
{
tree type = TREE_TYPE (decl);
#if 0
instance of the variable at link-time. */
static void
-maybe_commonize_var (decl)
- tree decl;
+maybe_commonize_var (tree decl)
{
/* Static data in a function with comdat linkage also has comdat
linkage. */
/* Issue an error message if DECL is an uninitialized const variable. */
static void
-check_for_uninitialized_const_var (decl)
- tree decl;
+check_for_uninitialized_const_var (tree decl)
{
tree type = TREE_TYPE (decl);
old_init_value = (TREE_CODE (*initp) == TREE_LIST
? TREE_VALUE (*initp) : old_init);
+ /* For some parse errors, OLD_INIT_VALUE may be NULL. */
+ if (!old_init_value)
+ {
+ my_friendly_assert (TREE_CODE (old_init) == TREE_LIST, 20021202);
+ TREE_VALUE (old_init) = error_mark_node;
+ return old_init;
+ }
+
/* If the initializer is brace-enclosed, pull initializers from the
enclosed elements. Advance past the brace-enclosed initializer
now. */
else
{
/* Build a CONSTRUCTOR to hold the contents of the aggregate. */
- new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ new_init = build_constructor (type, NULL_TREE);
TREE_HAS_CONSTRUCTOR (new_init) = 1;
if (CLASS_TYPE_P (type))
{
/* Loop through the initializable fields, gathering
initializers. */
+ /* FIXME support non-trivial labeled initializers. */
while (*initp && field)
{
tree field_init;
initializer for the first member of the union. */
if (TREE_CODE (type) == UNION_TYPE)
break;
- if (TREE_PURPOSE (field_init))
- field = TREE_PURPOSE (field_init);
field = next_initializable_field (TREE_CHAIN (field));
}
}
scalar, so just don't call it. */
if (CP_AGGREGATE_TYPE_P (type))
init = reshape_init (type, &init);
+
+ if ((*targetm.vector_opaque_p) (type))
+ {
+ error ("opaque vector types cannot be initialized");
+ init = error_mark_node;
+ }
}
/* If DECL has an array type without a specific bound, deduce the
/* If DECL is not a local variable, give it RTL. */
static void
-make_rtl_for_nonlocal_decl (decl, init, asmspec)
- tree decl;
- tree init;
- const char *asmspec;
+make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
{
int toplev = toplevel_bindings_p ();
int defer_p;
declaration into the surrounding scope. */
void
-maybe_inject_for_scope_var (decl)
- tree decl;
+maybe_inject_for_scope_var (tree decl)
{
+ timevar_push (TV_NAME_LOOKUP);
if (!DECL_NAME (decl))
- return;
+ {
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
+ }
/* Declarations of __FUNCTION__ and its ilk appear magically when
the variable is first used. If that happens to be inside a
for-loop, we don't want to do anything special. */
if (DECL_PRETTY_FUNCTION_P (decl))
- return;
+ {
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
+ }
if (current_binding_level->is_for_scope)
{
Otherwise, we need to preserve the temp slot for decl to last
into the outer binding level. */
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
- if (outer_binding && BINDING_LEVEL (outer_binding) == outer
- && (TREE_CODE (BINDING_VALUE (outer_binding))
- == VAR_DECL)
+ if (outer_binding && BINDING_SCOPE (outer_binding) == outer
+ && (TREE_CODE (BINDING_VALUE (outer_binding)) == VAR_DECL)
&& DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
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));
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Generate code to initialize DECL (a local variable). */
static void
-initialize_local_var (decl, init)
- tree decl;
- tree init;
+initialize_local_var (tree decl, tree init)
{
tree type = TREE_TYPE (decl);
if the (init) syntax was used. */
void
-cp_finish_decl (decl, init, asmspec_tree, flags)
- tree decl, init;
- tree asmspec_tree;
- int flags;
+cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
{
register tree type;
tree ttype = NULL_TREE;
necessary zero-initialization has already been performed. */
if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
+ /*nelts=*/NULL_TREE,
/*static_storage_p=*/true);
/* Remember that the initialization for this variable has
taken place. */
/* This is here for a midend callback from c-common.c */
void
-finish_decl (decl, init, asmspec_tree)
- tree decl, init;
- tree asmspec_tree;
+finish_decl (tree decl, tree init, tree asmspec_tree)
{
cp_finish_decl (decl, init, asmspec_tree, 0);
}
variables. */
tree
-declare_global_var (name, type)
- tree name;
- tree type;
+declare_global_var (tree name, tree type)
{
tree decl;
`__cxa_atexit' function specified in the IA64 C++ ABI. */
static tree
-get_atexit_node ()
+get_atexit_node (void)
{
tree atexit_fndecl;
tree arg_types;
/* Returns the __dso_handle VAR_DECL. */
static tree
-get_dso_handle_node ()
+get_dso_handle_node (void)
{
if (dso_handle_node)
return dso_handle_node;
to destroy some particular variable. */
static tree
-start_cleanup_fn ()
+start_cleanup_fn (void)
{
static int counter = 0;
int old_interface_only = interface_only;
/* Finish the cleanup function begun by start_cleanup_fn. */
static void
-end_cleanup_fn ()
+end_cleanup_fn (void)
{
expand_body (finish_function (0));
static storage duration. */
void
-register_dtor_fn (decl)
- tree decl;
+register_dtor_fn (tree decl)
{
tree cleanup;
tree compound_stmt;
tree args;
tree fcall;
-
int saved_flag_access_control;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
will make the back-end think that nested functions are in use,
which causes confusion. */
saved_flag_access_control = flag_access_control;
- flag_access_control = 0;
+ scope_chain->check_access = flag_access_control = 0;
fcall = build_cleanup (decl);
- flag_access_control = saved_flag_access_control;
+ scope_chain->check_access = flag_access_control = saved_flag_access_control;
/* Create the body of the anonymous function. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
and destruction of DECL. */
static void
-expand_static_init (decl, init)
- tree decl;
- tree init;
+expand_static_init (tree decl, tree init)
{
tree oldstatic;
/* Finish the declaration of a catch-parameter. */
tree
-start_handler_parms (declspecs, declarator)
- tree declspecs;
- tree declarator;
+start_handler_parms (tree declspecs, tree declarator)
{
tree decl;
if (declspecs)
2 if there was no information (in which case assume 0 if DO_DEFAULT). */
int
-complete_array_type (type, initial_value, do_default)
- tree type, initial_value;
- int do_default;
+complete_array_type (tree type, tree initial_value, int do_default)
{
register tree maxindex = NULL_TREE;
int value = 0;
message to print in that case. Otherwise, quietly return 1. */
static int
-member_function_or_else (ctype, cur_type, flags)
- tree ctype, cur_type;
- enum overload_flags flags;
+member_function_or_else (tree ctype, tree cur_type, enum overload_flags flags)
{
if (ctype && ctype != cur_type)
{
This is for ARM $7.1.2. */
static void
-bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
- tree object;
- const char *type;
- int virtualp, quals, friendp, raises, inlinep;
+bad_specifiers (tree object,
+ const char* type,
+ int virtualp,
+ int quals,
+ int inlinep,
+ int friendp,
+ int raises)
{
if (virtualp)
error ("`%D' declared as a `virtual' %s", object, type);
applicable error messages. */
static tree
-grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
- raises, check, friendp, publicp, inlinep, funcdef_flag,
- template_count, in_namespace)
- tree ctype, type;
- tree declarator;
- tree orig_declarator;
- int virtualp;
- enum overload_flags flags;
- tree quals, raises;
- int check, friendp, publicp, inlinep, funcdef_flag, template_count;
- tree in_namespace;
+grokfndecl (tree ctype,
+ tree type,
+ tree declarator,
+ tree orig_declarator,
+ int virtualp,
+ enum overload_flags flags,
+ tree quals,
+ tree raises,
+ int check,
+ int friendp,
+ int publicp,
+ int inlinep,
+ int funcdef_flag,
+ int template_count,
+ tree in_namespace)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
+ DID_INLINE_FUNC (decl) = 0;
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
/* We inline functions that are explicitly declared inline, or, when
the user explicitly asks us to, all functions. */
- if (DECL_DECLARED_INLINE_P (decl) || flag_inline_trees == 2)
+ if (DECL_DECLARED_INLINE_P (decl))
DECL_INLINE (decl) = 1;
+ if (flag_inline_trees == 2 && !DECL_INLINE (decl))
+ {
+ DID_INLINE_FUNC (decl) = 1;
+ DECL_INLINE (decl) = 1;
+ }
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
}
}
- if (has_default_arg)
- add_defarg_fn (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. */
if (check < 0)
return decl;
- if (flags == NO_SPECIAL && ctype && constructor_name (ctype) == declarator)
+ if (flags == NO_SPECIAL && ctype && constructor_name_p (declarator, ctype))
DECL_CONSTRUCTOR_P (decl) = 1;
/* Function gets the ugly name, field gets the nice one. This call
if (old_decl)
{
+ bool ok;
+
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
- if (!duplicate_decls (decl, old_decl))
- error ("no `%#D' member function declared in class `%T'",
- decl, ctype);
+ push_scope (ctype);
+ ok = duplicate_decls (decl, old_decl);
+ pop_scope (ctype);
+ if (!ok)
+ {
+ error ("no `%#D' member function declared in class `%T'",
+ decl, ctype);
+ return NULL_TREE;
+ }
return old_decl;
}
}
the innermost enclosings scope. */
static tree
-grokvardecl (type, name, specbits_in, initialized, constp, scope)
- tree type;
- tree name;
- RID_BIT_TYPE *specbits_in;
- int initialized;
- int constp;
- tree scope;
+grokvardecl (tree type,
+ tree name,
+ RID_BIT_TYPE * specbits_in,
+ int initialized,
+ int constp,
+ tree scope)
{
tree decl;
RID_BIT_TYPE specbits;
TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
-build_ptrmemfunc_type (type)
- tree type;
+build_ptrmemfunc_type (tree type)
{
- tree fields[4];
+ tree field, fields;
tree t;
tree unqualified_variant = NULL_TREE;
/* ... and not really an aggregate. */
SET_IS_AGGR_TYPE (t, 0);
- fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
- fields[1] = build_decl (FIELD_DECL, delta_identifier,
- delta_type_node);
- finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
+ field = build_decl (FIELD_DECL, pfn_identifier, type);
+ fields = field;
+
+ field = build_decl (FIELD_DECL, delta_identifier, delta_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
/* Zap out the name so that the back-end will give us the debugging
information for this anonymous RECORD_TYPE. */
otherwise. */
int
-check_static_variable_definition (decl, type)
- tree decl;
- tree type;
+check_static_variable_definition (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
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)
+ if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
{
error ("invalid in-class initialization of static data member of non-integral type `%T'",
- type);
+ 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
name of the thing being declared. */
tree
-compute_array_index_type (name, size)
- tree name;
- tree size;
+compute_array_index_type (tree name, tree size)
{
tree itype;
&& TREE_OPERAND (size, 0) == current_class_type)
{
tree t = lookup_field (current_class_type,
- TREE_OPERAND (size, 1), 0, 0);
+ TREE_OPERAND (size, 1), 0, false);
if (t)
size = t;
}
return build_index_type (itype);
}
+/* Returns the scope (if any) in which the entity declared by
+ DECLARATOR will be located. If the entity was declared with an
+ unqualified name, NULL_TREE is returned. */
+
+tree
+get_scope_of_declarator (tree declarator)
+{
+ if (!declarator)
+ return NULL_TREE;
+
+ switch (TREE_CODE (declarator))
+ {
+ case CALL_EXPR:
+ case ARRAY_REF:
+ case INDIRECT_REF:
+ case ADDR_EXPR:
+ /* For any of these, the main declarator is the first operand. */
+ return get_scope_of_declarator (TREE_OPERAND
+ (declarator, 0));
+
+ case SCOPE_REF:
+ /* For a pointer-to-member, continue descending. */
+ if (TREE_CODE (TREE_OPERAND (declarator, 1))
+ == INDIRECT_REF)
+ return get_scope_of_declarator (TREE_OPERAND
+ (declarator, 1));
+ /* Otherwise, if the declarator-id is a SCOPE_REF, the scope in
+ which the declaration occurs is the first operand. */
+ return TREE_OPERAND (declarator, 0);
+
+ case TREE_LIST:
+ /* Attributes to be applied. The declarator is TREE_VALUE. */
+ return get_scope_of_declarator (TREE_VALUE (declarator));
+
+ default:
+ /* Otherwise, we have a declarator-id which is not a qualified
+ name; the entity will be declared in the current scope. */
+ return NULL_TREE;
+ }
+}
+
/* Returns an ARRAY_TYPE for an array with SIZE elements of the
indicated TYPE. If non-NULL, NAME is the NAME of the declaration
with this type. */
static tree
-create_array_type_for_decl (name, type, size)
- tree name;
- tree type;
- tree size;
+create_array_type_for_decl (tree name, tree type, tree size)
{
tree itype = NULL_TREE;
const char* error_msg;
special functions. */
static tree
-check_special_function_return_type (sfk, type, optype)
- special_function_kind sfk;
- tree type;
- tree optype;
+check_special_function_return_type (special_function_kind sfk,
+ tree type,
+ tree optype)
{
switch (sfk)
{
return type;
}
-/* Given declspecs and a declarator,
- determine the name and type of the object declared
- and construct a ..._DECL node for it.
- (In one case we can return a ..._TYPE node instead.
- For invalid input we sometimes return 0.)
+/* Given declspecs and a declarator (abstract or otherwise), determine
+ the name and type of the object declared and construct a DECL node
+ for it.
DECLSPECS is a chain of tree_list nodes whose value fields
are the storage classes and type specifiers.
if there are none; *ATTRLIST may be modified if attributes from inside
the declarator should be applied to the declaration.
- In the TYPENAME case, DECLARATOR is really an abstract declarator.
- It may also be so in the PARM case, for a prototype where the
- argument type is specified but not the name.
-
- This function is where the complicated C meanings of `static'
- and `extern' are interpreted.
-
- For C++, if there is any monkey business to do, the function which
- calls this one must do it, i.e., prepending instance variables,
- renaming overloaded function names, etc.
-
- Note that for this C++, it is an error to define a method within a class
- which does not belong to that class.
-
- Except in the case where SCOPE_REFs are implicitly known (such as
- methods within a class being redundantly qualified),
- declarations which involve SCOPE_REFs are returned as SCOPE_REFs
- (class_name::decl_name). The caller must also deal with this.
+ When this function is called, scoping variables (such as
+ CURRENT_CLASS_TYPE) should reflect the scope in which the
+ declaration occurs, not the scope in which the new declaration will
+ be placed. For example, on:
- If a constructor or destructor is seen, and the context is FIELD,
- then the type gains the attribute TREE_HAS_x. If such a declaration
- is erroneous, NULL_TREE is returned.
+ void S::f() { ... }
- QUALS is used only for FUNCDEF and MEMFUNCDEF cases. For a member
- function, these are the qualifiers to give to the `this' pointer. We
- apply TYPE_QUAL_RESTRICT to the this ptr, not the object.
-
- May return void_type_node if the declarator turned out to be a friend.
- See grokfield for details. */
+ when grokdeclarator is called for `S::f', the CURRENT_CLASS_TYPE
+ should not be `S'. */
tree
-grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
- tree declspecs;
- tree declarator;
- enum decl_context decl_context;
- int initialized;
- tree *attrlist;
+grokdeclarator (tree declarator,
+ tree declspecs,
+ enum decl_context decl_context,
+ int initialized,
+ tree* attrlist)
{
RID_BIT_TYPE specbits;
int nclasses = 0;
/* See the code below that used this. */
tree decl_attr = NULL_TREE;
#endif
- /* Set this to error_mark_node for FIELD_DECLs we could not handle properly.
- All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */
- tree init = NULL_TREE;
/* Keep track of what sort of function is being processed
so that we can warn about default return values, or explicit
int template_count = 0;
tree in_namespace = NULL_TREE;
tree returned_attrs = NULL_TREE;
+ tree scope = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
my_friendly_assert (flags == NO_SPECIAL, 152);
flags = DTOR_FLAG;
sfk = sfk_destructor;
- if (TREE_CODE (name) == TYPE_DECL)
+ if (TYPE_P (name))
TREE_OPERAND (decl, 0) = name = constructor_name (name);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
if (ctype == NULL_TREE)
}
else
{
- tree t = constructor_name (current_class_name);
+ tree t = constructor_name (current_class_type);
if (t != name)
rename = t;
}
break;
case CALL_EXPR:
- if (parmlist_is_exprlist (CALL_DECLARATOR_PARMS (decl)))
- {
- /* This is actually a variable declaration using
- constructor syntax. We need to call start_decl and
- cp_finish_decl so we can get the variable
- initialized... */
-
- tree attributes;
-
- if (decl_context != NORMAL)
- {
- error ("variable declaration is not allowed here");
- return error_mark_node;
- }
-
- *next = TREE_OPERAND (decl, 0);
- init = CALL_DECLARATOR_PARMS (decl);
-
- if (attrlist)
- {
- attributes = *attrlist;
- }
- else
- {
- attributes = NULL_TREE;
- }
-
- decl = start_decl (declarator, declspecs, 1,
- attributes, NULL_TREE);
- decl_type_access_control (decl);
- if (decl)
- {
- /* Look for __unused__ attribute */
- if (TREE_USED (TREE_TYPE (decl)))
- TREE_USED (decl) = 1;
- finish_decl (decl, init, NULL_TREE);
- }
- else
- error ("invalid declarator");
- return NULL_TREE;
- }
innermost_code = TREE_CODE (decl);
if (decl_context == FIELD && ctype == NULL_TREE)
ctype = current_class_type;
decl = *next;
if (ctype != NULL_TREE
&& decl != NULL_TREE && flags != DTOR_FLAG
- && decl == constructor_name (ctype))
+ && constructor_name_p (decl, ctype))
{
sfk = sfk_constructor;
ctor_return_type = ctype;
{
ctype = NULL_TREE;
in_namespace = TREE_OPERAND (decl, 0);
- TREE_OPERAND (decl, 0) = NULL_TREE;
}
else if (! is_aggr_type (cname, 1))
- TREE_OPERAND (decl, 0) = NULL_TREE;
+ ctype = NULL_TREE;
/* Must test TREE_OPERAND (decl, 1), in case user gives
us `typedef (class::memfunc)(int); memfunc *memfuncptr;' */
else if (TREE_OPERAND (decl, 1)
else if (ctype == NULL_TREE)
ctype = cname;
else if (TREE_COMPLEXITY (decl) == current_class_depth)
- TREE_OPERAND (decl, 0) = ctype;
+ ;
else
{
if (! UNIQUELY_DERIVED_FROM_P (cname, ctype))
{
error ("type `%T' is not derived from type `%T'",
cname, ctype);
- TREE_OPERAND (decl, 0) = NULL_TREE;
+ ctype = NULL_TREE;
}
else
ctype = cname;
}
+ /* It is valid to write:
+
+ class C { void f(); };
+ typedef C D;
+ void D::f();
+
+ The standard is not clear about whether `typedef const C D' is
+ legal; as of 2002-09-15 the committee is considering
+ that question. EDG 3.0 allows that syntax.
+ Therefore, we do as well. */
+ if (ctype)
+ ctype = TYPE_MAIN_VARIANT (ctype);
+ /* Update the declarator so that when we process it
+ again the correct type is present. */
+ TREE_OPERAND (decl, 0) = ctype;
+
if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
&& constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)),
ctype))
if (ctype)
{
if (TREE_CODE (decl) == IDENTIFIER_NODE
- && constructor_name (ctype) == decl)
+ && constructor_name_p (decl, ctype))
{
sfk = sfk_constructor;
ctor_return_type = ctype;
else if (RIDBIT_SETP (i, specbits))
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- /* Diagnose "__thread extern". Recall that this list
- is in the reverse order seen in the text. */
- if (i == (int)RID_THREAD)
+ /* Diagnose "__thread extern" or "__thread static". */
+ if (RIDBIT_SETP (RID_THREAD, specbits))
{
- if (RIDBIT_SETP (RID_EXTERN, specbits))
+ if (i == (int)RID_EXTERN)
error ("`__thread' before `extern'");
- if (RIDBIT_SETP (RID_STATIC, specbits))
+ else if (i == (int)RID_STATIC)
error ("`__thread' before `static'");
}
type = integer_type_node;
}
- if (type && IMPLICIT_TYPENAME_P (type))
- {
- /* The implicit typename extension is deprecated and will be
- removed. Warn about its use now. */
- warning ("`%T' is implicitly a typename", type);
- cp_deprecated ("implicit typename");
-
- /* Now remove its implicitness, so that we don't warn again.
- For instance this might be a typedef, and we do not want to
- warn on uses of the typedef itself. Simply clearing the
- TREE_TYPE is insufficient. */
- type = copy_node (type);
- TREE_TYPE (type) = NULL_TREE;
- }
-
ctype = NULL_TREE;
/* Now process the modifiers that were specified
if (nclasses > 0 && friendp)
error ("storage class specifiers invalid in friend function declarations");
+ scope = get_scope_of_declarator (declarator);
+
/* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an abstract declarator). */
tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
- ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
quals = NULL_TREE;
}
}
if (ctype && sfk == sfk_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
- if (ctype && constructor_name (ctype) == dname)
+ if (ctype && constructor_name_p (dname, ctype))
{
/* We are within a class's scope. If our declarator name
is the same as the class name, and we are defining
/* ANSI says that `const int foo ();'
does not make the function foo const. */
type = build_function_type (type, arg_types);
-
- {
- tree t;
- for (t = arg_types; t; t = TREE_CHAIN (t))
- if (TREE_PURPOSE (t)
- && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
- {
- add_defarg_fn (type);
- break;
- }
- }
}
break;
if (TREE_CODE (sname) == BIT_NOT_EXPR)
sname = TREE_OPERAND (sname, 0);
- if (TREE_COMPLEXITY (declarator) == 0)
- /* This needs to be here, in case we are called
- multiple times. */ ;
- else if (TREE_COMPLEXITY (declarator) == -1)
- /* Namespace member. */
- pop_decl_namespace ();
- else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
- /* Don't fall out into global scope. Hides real bug? --eichin */ ;
- else if (!TREE_OPERAND (declarator, 0)
- || !IS_AGGR_TYPE_CODE
- (TREE_CODE (TREE_OPERAND (declarator, 0))))
- ;
- else if (TREE_COMPLEXITY (declarator) == current_class_depth)
- {
- /* Resolve any TYPENAME_TYPEs from the decl-specifier-seq
- that refer to ctype. They couldn't be resolved earlier
- because we hadn't pushed into the class yet.
- Example: resolve 'B<T>::type' in
- 'B<typename B<T>::type> B<T>::f () { }'. */
- if (current_template_parms
- && uses_template_parms (type)
- && uses_template_parms (current_class_type))
- {
- tree args = current_template_args ();
- type = tsubst (type, args, tf_error | tf_warning,
- NULL_TREE);
- }
-
- /* This pop_nested_class corresponds to the
- push_nested_class used to push into class scope for
- parsing the argument list of a function decl, in
- qualified_id. */
- pop_nested_class ();
- TREE_COMPLEXITY (declarator) = current_class_depth;
- }
- else
- abort ();
-
if (TREE_OPERAND (declarator, 0) == NULL_TREE)
{
/* We had a reference to a global decl, or
{
error ("cannot declare member function `%T::%s' within `%T'",
ctype, name, current_class_type);
- return void_type_node;
+ return error_mark_node;
}
}
else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
type = error_mark_node;
}
- if (decl_context == FIELD
+ if ((decl_context == FIELD || decl_context == PARM)
&& !processing_template_decl
&& variably_modified_type_p (type))
{
- error ("data member may not have variably modified type `%T'", type);
+ if (decl_context == FIELD)
+ error ("data member may not have variably modified type `%T'", type);
+ else
+ error ("parameter may not have variably modified type `%T'", type);
type = error_mark_node;
}
if (decl_context == FIELD)
{
- if (declarator == constructor_name (current_class_type))
+ if (constructor_name_p (declarator, current_class_type))
pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type);
else
{
decl = build_decl (TYPE_DECL, declarator, type);
+ if (in_namespace || ctype)
+ cp_error_at ("typedef name may not be a nested-name-specifier",
+ decl);
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
}
type with external linkage have external linkage. */
}
- if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
- {
- cp_error_at ("typedef name may not be class-qualified", decl);
- return NULL_TREE;
- }
- else if (quals)
+ if (quals)
{
if (ctype == NULL_TREE)
{
/* Only try to do this stuff if we didn't already give up. */
if (type != integer_type_node)
{
- decl_type_access_control (TYPE_NAME (type));
-
/* A friendly class? */
if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
return void_type_node;
}
- /* 9.2p13 [class.mem] */
- if (declarator == constructor_name (current_class_type)
- /* The standard does not allow non-static data members
- here either, but we agreed at the 10/99 meeting
- to change that in TC 1 so that they are allowed in
- classes with no user-defined constructors. */
- && staticp)
- pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
- declarator);
-
if (staticp)
{
+ /* [class.mem] forbids static data members with the
+ same name as the enclosing class. Non-static data
+ members are checked in check_field_decls. */
+ if (constructor_name_p (declarator, current_class_type))
+ pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
+ declarator);
+
/* C++ allows static class members. All other work
for this is done by grokfield. */
decl = build_lang_decl (VAR_DECL, declarator, type);
}
}
\f
-/* Tell if a parmlist/exprlist looks like an exprlist or a parmlist.
- An empty exprlist is a parmlist. An exprlist which
- contains only identifiers at the global level
- is a parmlist. Otherwise, it is an exprlist. */
-
-int
-parmlist_is_exprlist (exprs)
- tree exprs;
-{
- if (exprs == NULL_TREE || TREE_PARMLIST (exprs))
- return 0;
-
- if (toplevel_bindings_p ())
- {
- /* At the global level, if these are all identifiers,
- then it is a parmlist. */
- while (exprs)
- {
- if (TREE_CODE (TREE_VALUE (exprs)) != IDENTIFIER_NODE)
- return 1;
- exprs = TREE_CHAIN (exprs);
- }
- return 0;
- }
- return 1;
-}
-
/* 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;
+require_complete_types_for_parms (tree parms)
{
for (; parms; parms = TREE_CHAIN (parms))
{
/* grokparms will have already issued an error */
TREE_TYPE (parms) = error_mark_node;
else if (complete_type_or_else (TREE_TYPE (parms), parms))
- layout_decl (parms, 0);
+ {
+ layout_decl (parms, 0);
+ DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
+ }
else
TREE_TYPE (parms) = error_mark_node;
}
/* Returns nonzero if T is a local variable. */
int
-local_variable_p (t)
- tree t;
+local_variable_p (tree t)
{
if ((TREE_CODE (t) == VAR_DECL
/* A VAR_DECL with a context that is a _TYPE is a static data
containing them is duplicated.) */
int
-nonstatic_local_decl_p (t)
- tree t;
+nonstatic_local_decl_p (tree t)
{
return ((local_variable_p (t) && !TREE_STATIC (t))
|| TREE_CODE (t) == LABEL_DECL
function. */
static tree
-local_variable_p_walkfn (tp, walk_subtrees, data)
- tree *tp;
- int *walk_subtrees ATTRIBUTE_UNUSED;
- void *data ATTRIBUTE_UNUSED;
+local_variable_p_walkfn (tree* tp,
+ int* walk_subtrees ATTRIBUTE_UNUSED ,
+ void* data ATTRIBUTE_UNUSED )
{
return ((local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
? *tp : NULL_TREE);
DECL, if there is no DECL available. */
tree
-check_default_argument (decl, arg)
- tree decl;
- tree arg;
+check_default_argument (tree decl, tree arg)
{
tree var;
tree decl_type;
Also set last_function_parms to the chain of PARM_DECLs. */
static tree
-grokparms (first_parm)
- tree first_parm;
+grokparms (tree first_parm)
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
operator. */
int
-copy_fn_p (d)
- tree d;
+copy_fn_p (tree d)
{
tree args;
tree arg_type;
/* Remember any special properties of member function DECL. */
-void grok_special_member_properties (decl)
- tree decl;
+void grok_special_member_properties (tree decl)
{
if (!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))
; /* Not special. */
if the class has a constructor of the form X(X). */
int
-grok_ctor_properties (ctype, decl)
- tree ctype, decl;
+grok_ctor_properties (tree ctype, tree decl)
{
int ctor_parm = copy_fn_p (decl);
/* An operator with this code is unary, but can also be binary. */
static int
-ambi_op_p (code)
- enum tree_code code;
+ambi_op_p (enum tree_code code)
{
return (code == INDIRECT_REF
|| code == ADDR_EXPR
/* An operator with this name can only be unary. */
static int
-unary_op_p (code)
- enum tree_code code;
+unary_op_p (enum tree_code code)
{
return (code == TRUTH_NOT_EXPR
|| code == BIT_NOT_EXPR
/* Do a little sanity-checking on how they declared their operator. */
void
-grok_op_properties (decl, friendp)
- tree decl;
- int friendp;
+grok_op_properties (tree decl, int friendp)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree argtype;
}
\f
static const char *
-tag_name (code)
- enum tag_types code;
+tag_name (enum tag_types code)
{
switch (code)
{
}
}
+/* Name lookup in an elaborated-type-specifier (after the keyword
+ indicated by TAG_CODE) has found TYPE. If the
+ elaborated-type-specifier is invalid, issue a diagnostic and return
+ error_mark_node; otherwise, return TYPE itself. */
+
+static tree
+check_elaborated_type_specifier (enum tag_types tag_code,
+ tree type)
+{
+ tree t;
+
+ t = follow_tag_typedef (type);
+
+ /* [dcl.type.elab] If the identifier resolves to a typedef-name or a
+ template type-parameter, the elaborated-type-specifier is
+ ill-formed. */
+ if (!t)
+ {
+ error ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (type), tag_name (tag_code));
+ t = error_mark_node;
+ }
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ {
+ error ("using template type parameter `%T' after `%s'",
+ type, tag_name (tag_code));
+ t = error_mark_node;
+ }
+
+ return t;
+}
+
/* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
switch (tag_code)
{
case record_type:
{
if (t)
{
- ref = follow_tag_typedef (t);
-
- /* [dcl.type.elab] If the identifier resolves to a
- typedef-name or a template type-parameter, the
- elaborated-type-specifier is ill-formed. */
- if (!ref)
- {
- pedwarn ("using typedef-name `%D' after `%s'",
- TYPE_NAME (t), tag_name (tag_code));
- ref = t;
- }
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- error ("using template type parameter `%T' after `%s'",
- t, tag_name (tag_code));
+ ref = check_elaborated_type_specifier (tag_code, t);
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
ref = lookup_tag (code, name, b, 0);
template, so we want this type. */
ref = DECL_TEMPLATE_RESULT (ref);
- if (ref && TREE_CODE (ref) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (ref)) == code)
- ref = TREE_TYPE (ref);
+ if (ref && TREE_CODE (ref) == TYPE_DECL)
+ {
+ ref = check_elaborated_type_specifier (tag_code,
+ TREE_TYPE (ref));
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ if (ref && TREE_CODE (ref) != code)
+ ref = NULL_TREE;
+ }
else
ref = NULL_TREE;
}
TYPE_ATTRIBUTES (ref) = attributes;
- return ref;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
}
tree
-xref_tag_from_type (old, id, globalize)
- tree old, id;
- int globalize;
+xref_tag_from_type (tree old, tree id, int globalize)
{
enum tag_types tag_kind;
}
/* REF is a type (named NAME), for which we have just seen some
- baseclasses. BINFO is a list of those baseclasses; the
+ baseclasses. BASE_LIST 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,
+ the base-class. TREE_VIA_VIRTUAL indicates virtual
+ inheritance. CODE_TYPE_NODE indicates whether REF is a class,
struct, or union. */
void
-xref_basetypes (ref, binfo)
- tree ref;
- tree binfo;
+xref_basetypes (tree ref, tree base_list)
{
/* 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;
+ tree *basep;
- int i, len;
+ int i;
enum tag_types tag_code;
if (TREE_CODE (ref) == UNION_TYPE)
tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
- len = list_length (binfo);
-
/* 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));
+ basep = &base_list;
+ while (*basep)
+ {
+ tree basetype = TREE_VALUE (*basep);
+ if (!(processing_template_decl && uses_template_parms (basetype))
+ && !complete_type_or_else (basetype, NULL))
+ /* An incomplete type. Remove it from the list. */
+ *basep = TREE_CHAIN (*basep);
+ else
+ basep = &TREE_CHAIN (*basep);
+ }
SET_CLASSTYPE_MARKED (ref);
- BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
-
- for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
- {
- /* The base of a derived struct is public by default. */
- int via_public
- = (TREE_PURPOSE (binfo) == access_public_node
- || TREE_PURPOSE (binfo) == access_public_virtual_node
- || (tag_code != class_type
- && (TREE_PURPOSE (binfo) == access_default_node
- || TREE_PURPOSE (binfo) == access_default_virtual_node)));
- int via_protected
- = (TREE_PURPOSE (binfo) == access_protected_node
- || TREE_PURPOSE (binfo) == access_protected_virtual_node);
- int via_virtual
- = (TREE_PURPOSE (binfo) == access_private_virtual_node
- || TREE_PURPOSE (binfo) == access_protected_virtual_node
- || TREE_PURPOSE (binfo) == access_public_virtual_node
- || TREE_PURPOSE (binfo) == access_default_virtual_node);
- tree basetype = TREE_VALUE (binfo);
- tree base_binfo;
-
- if (basetype && TREE_CODE (basetype) == TYPE_DECL)
- basetype = TREE_TYPE (basetype);
- if (!basetype
- || (TREE_CODE (basetype) != RECORD_TYPE
- && TREE_CODE (basetype) != TYPENAME_TYPE
- && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
- && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
- {
- error ("base type `%T' fails to be a struct or class type",
- TREE_VALUE (binfo));
- continue;
- }
-
- /* This code replaces similar code in layout_basetypes.
- We put the complete_type first for implicit `typename'. */
- if (!COMPLETE_TYPE_P (basetype)
- && ! (current_template_parms && uses_template_parms (basetype)))
- {
- error ("base class `%T' has incomplete type", basetype);
- continue;
- }
- else
+ i = list_length (base_list);
+ if (i)
+ {
+ tree binfo = TYPE_BINFO (ref);
+ tree binfos = make_tree_vec (i);
+ tree accesses = make_tree_vec (i);
+
+ BINFO_BASETYPES (binfo) = binfos;
+ BINFO_BASEACCESSES (binfo) = accesses;
+
+ for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
{
+ tree access = TREE_PURPOSE (base_list);
+ int via_virtual = TREE_VIA_VIRTUAL (base_list);
+ tree basetype = TREE_VALUE (base_list);
+ tree base_binfo;
+
+ if (access == access_default_node)
+ /* The base of a derived struct is public by default. */
+ access = (tag_code == class_type
+ ? access_private_node : access_public_node);
+
+ if (basetype && TREE_CODE (basetype) == TYPE_DECL)
+ basetype = TREE_TYPE (basetype);
+ if (!basetype
+ || (TREE_CODE (basetype) != RECORD_TYPE
+ && TREE_CODE (basetype) != TYPENAME_TYPE
+ && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
+ {
+ error ("base type `%T' fails to be a struct or class type",
+ basetype);
+ continue;
+ }
+
if (CLASSTYPE_MARKED (basetype))
{
if (basetype == ref)
error ("duplicate base type `%T' invalid", basetype);
continue;
}
-
+
if (TYPE_FOR_JAVA (basetype)
&& (current_lang_depth () == 0))
TYPE_FOR_JAVA (ref) = 1;
-
- /* Note that the BINFO records which describe individual
- inheritances are *not* shared in the lattice! They
- cannot be shared because a given baseclass may be
- inherited with different `accessibility' by different
- derived classes. (Each BINFO record describing an
- individual inheritance contains flags which say what
- the `accessibility' of that particular inheritance is.) */
-
- base_binfo
- = make_binfo (size_zero_node, basetype,
- CLASS_TYPE_P (basetype)
- ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
- CLASS_TYPE_P (basetype)
- ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
-
+
+ if (CLASS_TYPE_P (basetype))
+ {
+ base_binfo = TYPE_BINFO (basetype);
+ /* This flag will be in the binfo of the base type, we must
+ clear it after copying the base binfos. */
+ BINFO_DEPENDENT_BASE_P (base_binfo)
+ = dependent_type_p (basetype);
+ }
+ else
+ base_binfo = make_binfo (size_zero_node, basetype,
+ NULL_TREE, NULL_TREE);
+
TREE_VEC_ELT (binfos, i) = base_binfo;
- TREE_VIA_PUBLIC (base_binfo) = via_public;
- TREE_VIA_PROTECTED (base_binfo) = via_protected;
+ TREE_VEC_ELT (accesses, i) = access;
+ /* This flag will be in the binfo of the base type, we must
+ clear it after copying the base binfos. */
TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
- BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
-
- /* We need to unshare the binfos now so that lookups during class
- definition work. */
- unshare_base_binfos (base_binfo);
-
+
SET_CLASSTYPE_MARKED (basetype);
-
+
/* We are free to modify these bits because they are meaningless
at top level, and BASETYPE is a top-level type. */
if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
/* Converting to a virtual base class requires looking
- up the offset of the virtual base. */
+ up the offset of the virtual base. */
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
}
-
+
if (CLASS_TYPE_P (basetype))
{
TYPE_HAS_NEW_OPERATOR (ref)
TYPE_USES_MULTIPLE_INHERITANCE (ref)
|= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
/* Likewise, if converting to a base of the base may require
- code, then we may need to generate code to convert to a
- base as well. */
+ code, then we may need to generate code to convert to a
+ base as well. */
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
|= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
}
-
- i += 1;
+ i++;
+ }
+ if (i)
+ TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
+ else
+ BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
+
+ if (i > 1)
+ {
+ TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
+ /* If there is more than one non-empty they cannot be at the same
+ address. */
+ TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
}
}
- if (i)
- TREE_VEC_LENGTH (binfos) = i;
- else
- BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
-
- if (i > 1)
+
+ /* Copy the base binfos, collect the virtual bases and set the
+ inheritance order chain. */
+ copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
+ CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
+
+ /* Unmark all the types. */
+ while (i--)
{
- TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
- /* If there is more than one non-empty they cannot be at the same
- address. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+ tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));
+
+ CLEAR_CLASSTYPE_MARKED (basetype);
+ if (CLASS_TYPE_P (basetype))
+ {
+ TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;
+ BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;
+ }
}
-
- /* Unmark all the types. */
- while (--i >= 0)
- 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. */
- get_vbase_types (ref);
}
\f
may be used to declare the individual values as they are read. */
tree
-start_enum (name)
- tree name;
+start_enum (tree name)
{
register tree enumtype = NULL_TREE;
struct cp_binding_level *b = current_binding_level;
ENUMTYPE is the type object and VALUES a list of name-value pairs. */
void
-finish_enum (enumtype)
- tree enumtype;
+finish_enum (tree enumtype)
{
tree pair;
tree minnode;
/* We built up the VALUES in reverse order. */
TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
- /* [dcl.enum]
-
- Following the closing brace of an enum-specifier, each
- enumerator has the type of its enumeration. Prior to the
- closing brace, the type of each enumerator is the type of
- its initializing value. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
-
- /* For an enum defined in a template, all further processing is
- postponed until the template is instantiated. */
+ /* For an enum defined in a template, just set the type of the values;
+ all further processing is postponed until the template is
+ instantiated. We need to set the type so that tsubst of a CONST_DECL
+ works. */
if (processing_template_decl)
{
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+ TREE_TYPE (TREE_VALUE (pair)) = enumtype;
if (at_function_scope_p ())
add_stmt (build_min (TAG_DEFN, enumtype));
return;
}
- /* Figure out what the minimum and maximum values of the enumerators
- are. */
if (TYPE_VALUES (enumtype))
{
minnode = maxnode = NULL_TREE;
- for (pair = TYPE_VALUES (enumtype);
- pair;
- pair = TREE_CHAIN (pair))
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
{
- tree value;
+ tree decl = TREE_VALUE (pair);
+ tree value = DECL_INITIAL (decl);
- value = DECL_INITIAL (TREE_VALUE (pair));
+ /* [dcl.enum]: Following the closing brace of an enum-specifier,
+ each enumerator has the type of its enumeration. Prior to the
+ closing brace, the type of each enumerator is the type of its
+ initializing value. */
+ TREE_TYPE (decl) = enumtype;
+ /* Figure out what the minimum and maximum values of the
+ enumerators are. */
if (!minnode)
minnode = maxnode = value;
else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
+
+ /* Set the TREE_TYPE for the values as well. That's so that when
+ we call decl_constant_value we get an entity of the right type
+ (but with the constant value). But first make a copy so we
+ don't clobber shared INTEGER_CSTs. */
+ if (TREE_TYPE (value) != enumtype)
+ {
+ value = DECL_INITIAL (decl) = copy_node (value);
+ TREE_TYPE (value) = enumtype;
+ }
+
+ /* In addition, transform the TYPE_VALUES list to contain the
+ values, rather than the CONST_DECLs for them. */
+ TREE_VALUE (pair) = value;
}
}
else
highprec = min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
- /* Set the TREE_TYPE for the values as well. That's so that when we
- call decl_constant_value we get an entity of the right type (but
- with the constant value). In addition, transform the TYPE_VALUES
- list to contain the values, rather than the CONST_DECLs for them. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
- {
- tree value = DECL_INITIAL (TREE_VALUE (pair));
-
- TREE_TYPE (value) = enumtype;
- TREE_VALUE (pair) = value;
- }
-
/* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
TYPE_SIZE (enumtype) = NULL_TREE;
TYPE_PRECISION (enumtype) = precision;
Assignment of sequential values by default is handled here. */
void
-build_enumerator (name, value, enumtype)
- tree name;
- tree value;
- tree enumtype;
+build_enumerator (tree name, tree value, tree enumtype)
{
tree decl;
tree context;
tree type;
- tree values;
/* Remove no-op casts from the value. */
if (value)
}
/* Default based on previous value. */
- if (value == NULL_TREE && ! processing_template_decl)
+ if (value == NULL_TREE)
{
tree prev_value;
}
/* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-#if 0
- /* To fix MAX_VAL enum consts. (bkoz) */
- TREE_TYPE (value) = integer_type_node;
-#endif
+ STRIP_TYPE_NOPS (value);
}
- /* We always have to copy here; not all INTEGER_CSTs are unshared.
- Even in other cases, we will later (in finish_enum) be setting
- the type of VALUE. But, we don't need to make a copy if this
- VALUE is one of the enumeration constants for this same
- enumeration type. */
- for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
- if (TREE_VALUE (values) == value)
- break;
- /* If we didn't break out of the loop, then we do need a copy. */
- if (!values && value)
- value = copy_node (value);
-
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
+ TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
- TREE_READONLY (decl) = 1;
if (context && context == current_class_type)
/* In something like `struct S { enum E { i = 7 }; };' we put `i'
/* We're defining DECL. Make sure that it's type is OK. */
static void
-check_function_type (decl, current_function_parms)
- tree decl;
- tree current_function_parms;
+check_function_type (tree decl, tree current_function_parms)
{
tree fntype = TREE_TYPE (decl);
tree return_type = complete_type (TREE_TYPE (fntype));
applied to it with the argument list [1, 2]. */
int
-start_function (declspecs, declarator, attrs, flags)
- tree declspecs, declarator, attrs;
- int flags;
+start_function (tree declspecs, tree declarator, tree attrs, int flags)
{
tree decl1;
tree ctype = NULL_TREE;
if (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
- warning_with_decl (decl1,
- "inline function `%s' given attribute noinline");
+ warning ("%Hinline function '%D' given attribute noinline",
+ &DECL_SOURCE_LOCATION (decl1), decl1);
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
/* This is a constructor, we must ensure that any default args
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
if (ctype)
- push_nested_class (ctype, 1);
+ push_nested_class (ctype);
else if (DECL_STATIC_FUNCTION_P (decl1))
- push_nested_class (DECL_CONTEXT (decl1), 2);
+ push_nested_class (DECL_CONTEXT (decl1));
/* Now that we have entered the scope of the class, we must restore
the bindings for any template parameters surrounding DECL1, if it
/* Start the statement-tree, start the tree now. */
begin_stmt_tree (&DECL_SAVED_TREE (decl1));
+ /* Don't double-count statements in templates. */
+ DECL_NUM_STMTS (decl1) = 0;
+
/* Let the user know we're compiling this function. */
announce_function (decl1);
Also install to binding contour return value identifier, if any. */
static void
-store_parm_decls (current_function_parms)
- tree current_function_parms;
+store_parm_decls (tree current_function_parms)
{
register tree fndecl = current_function_decl;
register tree parm;
when we want to generate RTL later we know what to do. */
static void
-save_function_data (decl)
- tree decl;
+save_function_data (tree decl)
{
struct language_function *f;
fully-constructed bases and members. */
static void
-begin_constructor_body ()
+begin_constructor_body (void)
{
}
members. */
static void
-finish_constructor_body ()
+finish_constructor_body (void)
{
}
vtable pointers and cleanups for bases and members. */
static void
-begin_destructor_body ()
+begin_destructor_body (void)
{
tree if_stmt;
tree compound_stmt;
necessary. Do that now. */
static void
-finish_destructor_body ()
+finish_destructor_body (void)
{
tree exprstmt;
In other functions, this isn't necessary, but it doesn't hurt. */
tree
-begin_function_body ()
+begin_function_body (void)
{
tree stmt;
main() would also need to return 0. */
void
-finish_function_body (compstmt)
- tree compstmt;
+finish_function_body (tree compstmt)
{
/* Close the block. */
finish_compound_stmt (0, compstmt);
after the class definition is complete.) */
tree
-finish_function (flags)
- int flags;
+finish_function (int flags)
{
register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
if (fndecl == NULL_TREE)
return error_mark_node;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+ && DECL_VIRTUAL_P (fndecl)
+ && !processing_template_decl)
+ {
+ tree fnclass = DECL_CONTEXT (fndecl);
+ if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
+ keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
+ }
+
nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
/* If we're saving up tree structure, tie off the function now. */
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ /* If this function can't throw any exceptions, remember that. */
+ if (!processing_template_decl
+ && !cp_function_chain->can_throw
+ && !flag_non_call_exceptions)
+ TREE_NOTHROW (fndecl) = 1;
+
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
if (current_function_return_value)
{
tree r = current_function_return_value;
- /* This is only worth doing for fns that return in memory--and
- simpler, since we don't have to worry about promoted modes. */
+ tree outer;
+
if (r != error_mark_node
- && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+ /* This is only worth doing for fns that return in memory--and
+ simpler, since we don't have to worry about promoted modes. */
+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))
+ /* Only allow this for variables declared in the outer scope of
+ the function so we know that their lifetime always ends with a
+ return; see g++.dg/opt/nrv6.C. We could be more flexible if
+ we were to do this optimization in tree-ssa. */
+ /* Skip the artificial function body block. */
+ && (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))),
+ chain_member (r, BLOCK_VARS (outer))))
{
+
DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
nullify_returns_r, r);
/* Complain if there's just no return statement. */
if (warn_return_type
- && !processing_template_decl
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
&& !current_function_returns_value && !current_function_returns_null
/* Don't complain if we abort or throw. */
&& !DECL_NAME (DECL_RESULT (fndecl))
/* Normally, with -Wreturn-type, flow will complain. Unless we're an
inline function, as we might never be compiled separately. */
- && DECL_INLINE (fndecl))
+ && (DECL_INLINE (fndecl) || processing_template_decl))
warning ("no return statement in function returning non-void");
/* Clear out memory we no longer need. */
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (declspecs, declarator, attrlist)
- tree declarator, declspecs, attrlist;
+start_method (tree declspecs, tree declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
&attrlist);
- /* Something too ugly to handle. */
- if (fndecl == NULL_TREE)
- return NULL_TREE;
+ if (fndecl == error_mark_node)
+ return error_mark_node;
+
+ if (fndecl == NULL || TREE_CODE (fndecl) != FUNCTION_DECL)
+ {
+ error ("invalid member function declaration");
+ return error_mark_node;
+ }
if (attrlist)
cplus_decl_attributes (&fndecl, attrlist, 0);
if (fndecl == void_type_node)
return fndecl;
- if (TREE_CODE (fndecl) != FUNCTION_DECL)
- /* Not a function, tell parser to report parse error. */
- return NULL_TREE;
-
if (DECL_IN_AGGR_P (fndecl))
{
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DID_INLINE_FUNC (fndecl) = 0;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
DECL is the ..._DECL that `start_method' provided. */
tree
-finish_method (decl)
- tree decl;
+finish_method (tree decl)
{
register tree fndecl = decl;
tree old_initial;
we can lay it out later, when and if its type becomes complete. */
void
-maybe_register_incomplete_var (var)
- tree var;
+maybe_register_incomplete_var (tree var)
{
my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
declaration, update them now. */
void
-complete_vars (type)
- tree type;
+complete_vars (tree type)
{
tree *list = &incomplete_vars;
here. */
tree
-cxx_maybe_build_cleanup (decl)
- tree decl;
+cxx_maybe_build_cleanup (tree decl)
{
tree type = TREE_TYPE (decl);
/* When a stmt has been parsed, this function is called. */
void
-finish_stmt ()
+finish_stmt (void)
{
/* Always assume this statement was not an expression statement. If
it actually was an expression statement, its our callers
but turned out to be static. Update it accordingly. */
void
-revert_static_member_fn (decl)
- tree decl;
+revert_static_member_fn (tree decl)
{
tree tmp;
tree function = TREE_TYPE (decl);
function. */
void
-cxx_push_function_context (f)
- struct function *f;
+cxx_push_function_context (struct function * f)
{
struct language_function *p
= ((struct language_function *)
compiling the function. */
void
-cxx_pop_function_context (f)
- struct function *f;
+cxx_pop_function_context (struct function * f)
{
f->language = 0;
}
one of the language-independent trees. */
enum cp_tree_node_structure_enum
-cp_tree_node_structure (t)
- union lang_tree_node *t;
+cp_tree_node_structure (union lang_tree_node * t)
{
switch (TREE_CODE (&t->generic))
{
- case DEFAULT_ARG: return TS_CP_IDENTIFIER;
+ case DEFAULT_ARG: return TS_CP_DEFAULT_ARG;
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
- case CPLUS_BINDING: return TS_CP_BINDING;
case OVERLOAD: return TS_CP_OVERLOAD;
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
case PTRMEM_CST: return TS_CP_PTRMEM;
+ case BASELINK: return TS_CP_BASELINK;
case WRAPPER: return TS_CP_WRAPPER;
- case SRCLOC: return TS_CP_SRCLOC;
default: return TS_CP_GENERIC;
}
}
the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++. */
tree
-identifier_global_value (t)
- tree t;
+identifier_global_value (tree t)
{
return IDENTIFIER_GLOBAL_VALUE (t);
}
/* Build the void_list_node (void_type_node having been created). */
tree
-build_void_list_node ()
+build_void_list_node (void)
{
tree t = build_tree_list (NULL_TREE, void_type_node);
TREE_PARMLIST (t) = 1;
}
static int
-cp_missing_noreturn_ok_p (decl)
- tree decl;
+cp_missing_noreturn_ok_p (tree decl)
{
/* A missing noreturn is ok for the `main' function. */
return DECL_MAIN_P (decl);