aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c114
1 files changed, 70 insertions, 44 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 454e1ef901e..b9c59af6cc7 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -964,11 +964,18 @@ add_binding (tree id, tree decl)
type to which it already refers. */
ok = 0;
/* There can be two block-scope declarations of the same variable,
- so long as they are `extern' declarations. */
+ so long as they are `extern' declarations. However, there cannot
+ be two declarations of the same static data member:
+
+ [class.mem]
+
+ A member shall not be declared twice in the
+ member-specification. */
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
&& DECL_EXTERNAL (decl)
- && DECL_EXTERNAL (BINDING_VALUE (binding)))
+ && DECL_EXTERNAL (BINDING_VALUE (binding))
+ && !DECL_CLASS_SCOPE_P (decl))
{
duplicate_decls (decl, BINDING_VALUE (binding));
ok = 0;
@@ -4143,24 +4150,47 @@ pushdecl_namespace_level (tree x)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
-/* Like pushdecl, only it places X in the global scope if appropriate. */
+/* Like pushdecl, only it places X in the global scope if appropriate.
+ Calls cp_finish_decl to register the variable, initializing it with
+ *INIT, if INIT is non-NULL. */
-tree
-pushdecl_top_level (tree x)
+static tree
+pushdecl_top_level_1 (tree x, tree *init)
{
timevar_push (TV_NAME_LOOKUP);
push_to_top_level ();
x = pushdecl_namespace_level (x);
+ if (init)
+ cp_finish_decl (x, *init, NULL_TREE, 0);
pop_from_top_level ();
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
+/* Like pushdecl, only it places X in the global scope if appropriate. */
+
+tree
+pushdecl_top_level (tree x)
+{
+ return pushdecl_top_level_1 (x, NULL);
+}
+
+/* Like pushdecl, only it places X in the global scope if
+ appropriate. Calls cp_finish_decl to register the variable,
+ initializing it with INIT. */
+
+tree
+pushdecl_top_level_and_finish (tree x, tree init)
+{
+ return pushdecl_top_level_1 (x, &init);
+}
+
/* Make the declaration of X appear in CLASS scope. */
-void
+bool
pushdecl_class_level (tree x)
{
tree name;
+ bool is_valid = true;
timevar_push (TV_NAME_LOOKUP);
/* Get the name of X. */
@@ -4171,7 +4201,7 @@ pushdecl_class_level (tree x)
if (name)
{
- push_class_level_binding (name, x);
+ is_valid = push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
set_identifier_type_value (name, TREE_TYPE (x));
}
@@ -4183,9 +4213,16 @@ pushdecl_class_level (tree x)
tree f;
for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
- pushdecl_class_level (f);
+ {
+ push_srcloc (DECL_SOURCE_FILE (f), DECL_SOURCE_LINE (f));
+ if (!pushdecl_class_level (f))
+ is_valid = false;
+ pop_srcloc ();
+ }
}
timevar_pop (TV_NAME_LOOKUP);
+
+ return is_valid;
}
/* Enter DECL into the symbol table, if that's appropriate. Returns
@@ -4217,21 +4254,19 @@ maybe_push_decl (tree decl)
return pushdecl (decl);
}
-/* Make the declaration(s) of X appear in CLASS scope
- under the name NAME. */
+/* Make the declaration(s) of X appear in CLASS scope under the name
+ NAME. Returns true if the binding is valid. */
-void
+bool
push_class_level_binding (tree name, tree x)
{
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)
- {
- timevar_pop (TV_NAME_LOOKUP);
- return;
- }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
/* Make sure that this new member does not have the same name
as a template parameter. */
@@ -4281,8 +4316,7 @@ push_class_level_binding (tree name, tree x)
INHERITED_VALUE_BINDING_P (binding) = 0;
TREE_TYPE (shadow) = x;
IDENTIFIER_CLASS_VALUE (name) = x;
- timevar_pop (TV_NAME_LOOKUP);
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
}
}
@@ -4296,8 +4330,10 @@ push_class_level_binding (tree name, tree x)
/* Record the value we are binding NAME to so that we can know
what to pop later. */
TREE_TYPE (class_binding_level->class_shadowed) = x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
}
- timevar_pop (TV_NAME_LOOKUP);
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
}
/* Insert another USING_DECL into the current binding level, returning
@@ -5384,7 +5420,7 @@ build_typename_type (tree context, tree name, tree fullname)
{
tree t;
tree d;
- PTR *e;
+ void **e;
if (typename_htab == NULL)
{
@@ -5489,7 +5525,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
}
if (complain & tf_error)
- perform_or_defer_access_check (context, tmpl);
+ perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
@@ -5519,7 +5555,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
}
if (complain & tf_error)
- perform_or_defer_access_check (context, t);
+ perform_or_defer_access_check (TYPE_BINFO (context), t);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
@@ -5576,7 +5612,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
}
if (complain & tf_error)
- perform_or_defer_access_check (context, tmpl);
+ perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
return tmpl;
}
@@ -7903,6 +7939,7 @@ static void
initialize_local_var (tree decl, tree init)
{
tree type = TREE_TYPE (decl);
+ tree cleanup;
my_friendly_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == RESULT_DECL,
@@ -7952,17 +7989,9 @@ initialize_local_var (tree decl, tree init)
}
/* Generate a cleanup, if necessary. */
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- {
- tree cleanup;
-
- /* Compute the cleanup. */
- cleanup = cxx_maybe_build_cleanup (decl);
-
- /* Record the cleanup required for this declaration. */
- if (DECL_SIZE (decl) && cleanup)
- finish_decl_cleanup (decl, cleanup);
- }
+ cleanup = cxx_maybe_build_cleanup (decl);
+ if (DECL_SIZE (decl) && cleanup)
+ finish_decl_cleanup (decl, cleanup);
}
/* Finish processing of a declaration;
@@ -7991,6 +8020,8 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
return;
}
+ my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);
+
/* If a name was specified, get the string. */
if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
@@ -8031,8 +8062,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
if (processing_template_decl)
{
/* Add this declaration to the statement-tree. */
- if (at_function_scope_p ()
- && TREE_CODE (decl) != RESULT_DECL)
+ if (at_function_scope_p ())
add_decl_stmt (decl);
if (init && DECL_INITIAL (decl))
@@ -8089,8 +8119,6 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
- else if (TREE_CODE (decl) == RESULT_DECL)
- init = check_initializer (decl, init, flags);
else if (TREE_CODE (decl) == VAR_DECL)
{
/* Only PODs can have thread-local storage. Other types may require
@@ -8146,9 +8174,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
reference temp is added before the DECL_STMT for the reference itself. */
- if (building_stmt_tree ()
- && at_function_scope_p ()
- && TREE_CODE (decl) != RESULT_DECL)
+ if (at_function_scope_p ())
add_decl_stmt (decl);
if (TREE_CODE (decl) == VAR_DECL)
@@ -8157,8 +8183,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
/* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union.
If not, it will get done when the type is completed. */
- if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == RESULT_DECL)
+ if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
if (TREE_CODE (decl) == VAR_DECL)
maybe_commonize_var (decl);
@@ -8461,6 +8486,7 @@ register_dtor_fn (tree decl)
/* Call atexit with the cleanup function. */
cxx_mark_addressable (cleanup);
+ mark_used (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
@@ -8883,7 +8909,7 @@ grokfndecl (tree ctype,
the user explicitly asks us to, all functions. */
if (DECL_DECLARED_INLINE_P (decl))
DECL_INLINE (decl) = 1;
- if (flag_inline_trees == 2 && !DECL_INLINE (decl))
+ if (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag)
{
DID_INLINE_FUNC (decl) = 1;
DECL_INLINE (decl) = 1;
@@ -12346,7 +12372,7 @@ grok_op_properties (tree decl, int friendp)
&& DERIVED_FROM_P (t, current_class_type))
what = "a base class";
- if (what)
+ if (what && warn_conversion)
warning ("conversion to %s%s will never use a type conversion operator",
ref ? "a reference to " : "", what);
}