/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
#include "timevar.h"
#include "tree-flow.h"
#include "pointer-set.h"
+#include "plugin.h"
-static tree grokparms (cp_parameter_declarator *, tree *);
+static tree grokparms (tree parmlist, tree *);
static const char *redeclaration_error_message (tree, tree);
static int decl_jump_unsafe (tree);
static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
int, int, tree);
static void record_unknown_type (tree, const char *);
-static tree builtin_function_1 (tree, tree);
+static tree builtin_function_1 (tree, tree, bool);
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,
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
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, tree *);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
static void save_function_data (tree);
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 tree cp_make_fname_decl (location_t, tree, int);
static void initialize_predefined_identifiers (void);
static tree check_special_function_return_type
(special_function_kind, tree, tree);
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
-struct named_label_use_entry GTY(())
-{
+struct GTY(()) named_label_use_entry {
struct named_label_use_entry *next;
/* The binding level to which this entry is *currently* attached.
This is initially the binding level in which the goto appeared,
we can clear out their names' definitions at the end of the
function, and so we can check the validity of jumps to these labels. */
-struct named_label_entry GTY(())
-{
+struct GTY(()) named_label_entry {
/* The decl itself. */
tree label_decl;
function, two inside the body of a function in a local class, etc.) */
int function_depth;
+/* To avoid unwanted recursion, finish_function defers all mark_used calls
+ encountered during its execution until it finishes. */
+bool defer_mark_used_calls;
+VEC(tree, gc) *deferred_mark_used_calls;
+
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
deprecated items. */
-
-enum deprecated_states {
- DEPRECATED_NORMAL,
- DEPRECATED_SUPPRESS
-};
-
-static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
\f
/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or
have pushed a statement list level. Pop that, create a new
BIND_EXPR for the block, and insert it into the stream. */
stmt = pop_stmt_list (current_binding_level->statement_list);
- stmt = c_build_bind_expr (block, stmt);
+ stmt = c_build_bind_expr (input_location, block, stmt);
add_stmt (stmt);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
-/* Insert BLOCK at the end of the list of subblocks of the
- current binding level. This is used when a BIND_EXPR is expanded,
- to handle the BLOCK node inside the BIND_EXPR. */
-
-void
-insert_block (tree block)
-{
- TREE_USED (block) = 1;
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
-}
-
/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
itself, calling F for each. The DATA is passed to F as well. */
{
tree decl;
- decl = build_decl (TYPE_DECL, name, type);
+ decl = build_decl (input_location, TYPE_DECL, name, type);
DECL_ARTIFICIAL (decl) = 1;
/* There are other implicit type declarations, like the one *within*
a class that allows you to write `S::S'. We must distinguish
{
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
- DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
+ DECL_LANG_SPECIFIC (decl)->u.base.u2sel = 1;
if (DECL_LANG_SPECIFIC (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
tree p1 = TYPE_ARG_TYPES (f1);
tree p2 = TYPE_ARG_TYPES (f2);
+ /* Specializations of different templates are different functions
+ even if they have the same type. */
+ tree t1 = (DECL_USE_TEMPLATE (newdecl)
+ ? DECL_TI_TEMPLATE (newdecl)
+ : NULL_TREE);
+ tree t2 = (DECL_USE_TEMPLATE (olddecl)
+ ? DECL_TI_TEMPLATE (olddecl)
+ : NULL_TREE);
+ if (t1 != t2)
+ return 0;
+
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
&& ! (DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl)))
return 0;
+#ifdef NO_IMPLICIT_EXTERN_C
+ /* A new declaration doesn't match a built-in one unless it
+ is also extern "C". */
+ if (DECL_BUILT_IN (olddecl)
+ && DECL_EXTERN_C_P (olddecl) && !DECL_EXTERN_C_P (newdecl))
+ return 0;
+#endif
+
if (TREE_CODE (f1) != TREE_CODE (f2))
return 0;
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
int new_defines_function = 0;
- tree new_template;
+ tree new_template_info;
if (newdecl == olddecl)
return olddecl;
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
- error (errmsg, newdecl);
+ error_at (DECL_SOURCE_LOCATION (newdecl), errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
? "%q+#D previously defined here"
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
{
/* Prototype decl follows defn w/o prototype. */
- warning (0, "prototype for %q+#D", newdecl);
- warning (0, "%Jfollows non-prototype definition here", olddecl);
+ warning_at (input_location, 0, "prototype for %q+#D", newdecl);
+ warning_at (DECL_SOURCE_LOCATION (olddecl), 0,
+ "follows non-prototype definition here");
}
else if ((TREE_CODE (olddecl) == FUNCTION_DECL
|| TREE_CODE (olddecl) == VAR_DECL)
= DECL_SOURCE_LOCATION (newdecl);
DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
- DECL_ARGUMENTS (old_result)
- = DECL_ARGUMENTS (new_result);
+ {
+ tree parm;
+ DECL_ARGUMENTS (old_result)
+ = DECL_ARGUMENTS (new_result);
+ for (parm = DECL_ARGUMENTS (old_result); parm;
+ parm = TREE_CHAIN (parm))
+ DECL_CONTEXT (parm) = old_result;
+ }
}
return olddecl;
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
+ /* Preserve function specific target and optimization options */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ {
+ if (DECL_FUNCTION_SPECIFIC_TARGET (olddecl)
+ && !DECL_FUNCTION_SPECIFIC_TARGET (newdecl))
+ DECL_FUNCTION_SPECIFIC_TARGET (newdecl)
+ = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
+
+ if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl)
+ && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
+ = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
+ }
+
/* Merge the initialization information. */
if (DECL_INITIAL (newdecl) == NULL_TREE
&& DECL_INITIAL (olddecl) != NULL_TREE)
{
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
- if (CAN_HAVE_FULL_LANG_DECL_P (newdecl)
- && DECL_LANG_SPECIFIC (newdecl)
- && DECL_LANG_SPECIFIC (olddecl))
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
/* Merge the storage class information. */
merge_weak (newdecl, olddecl);
- DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
+ if (DECL_ONE_ONLY (olddecl))
+ DECL_COMDAT_GROUP (newdecl) = DECL_COMDAT_GROUP (olddecl);
+
DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
- new_template = NULL_TREE;
+ new_template_info = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
bool new_redefines_gnu_inline = false;
}
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
+ DECL_ODR_USED (newdecl) |= DECL_ODR_USED (olddecl);
/* If the OLDDECL is an instantiation and/or specialization,
then the NEWDECL must be too. But, it may not yet be marked
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
- DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
- DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
- if (DECL_TEMPLATE_INFO (newdecl))
- new_template = DECL_TI_TEMPLATE (newdecl);
- DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl);
- olddecl_friend = DECL_FRIEND_P (olddecl);
- hidden_friend = (DECL_ANTICIPATED (olddecl)
- && DECL_HIDDEN_FRIEND_P (olddecl)
- && newdecl_is_friend);
- /* Only functions have DECL_BEFRIENDING_CLASSES. */
+ if (LANG_DECL_HAS_MIN (newdecl))
+ {
+ DECL_LANG_SPECIFIC (newdecl)->u.min.u2 =
+ DECL_LANG_SPECIFIC (olddecl)->u.min.u2;
+ if (DECL_TEMPLATE_INFO (newdecl))
+ new_template_info = DECL_TEMPLATE_INFO (newdecl);
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+ }
+ /* Only functions have these fields. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (newdecl))
{
+ DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+ olddecl_friend = DECL_FRIEND_P (olddecl);
+ hidden_friend = (DECL_ANTICIPATED (olddecl)
+ && DECL_HIDDEN_FRIEND_P (olddecl)
+ && newdecl_is_friend);
DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl));
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ tree parm;
+
+ /* Merge parameter attributes. */
+ tree oldarg, newarg;
+ for (oldarg = DECL_ARGUMENTS(olddecl),
+ newarg = DECL_ARGUMENTS(newdecl);
+ oldarg && newarg;
+ oldarg = TREE_CHAIN(oldarg), newarg = TREE_CHAIN(newarg)) {
+ DECL_ATTRIBUTES (newarg)
+ = (*targetm.merge_decl_attributes) (oldarg, newarg);
+ DECL_ATTRIBUTES (oldarg) = DECL_ATTRIBUTES (newarg);
+ }
+
if (DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_TEMPLATE_INSTANTIATION (newdecl))
{
should have exited above, returning 0. */
gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl));
- if (TREE_USED (olddecl))
+ if (DECL_ODR_USED (olddecl))
/* From [temp.expl.spec]:
If a template, a member template or the member of a class
/* Preserve abstractness on cloned [cd]tors. */
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
+ /* Update newdecl's parms to point at olddecl. */
+ for (parm = DECL_ARGUMENTS (newdecl); parm;
+ parm = TREE_CHAIN (parm))
+ DECL_CONTEXT (parm) = olddecl;
+
if (! types_match)
{
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
}
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
- /* Don't clear out the arguments if we're redefining a function. */
+ /* Don't clear out the arguments if we're just redeclaring a
+ function. */
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
&& DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
- warning (OPT_Wattributes, "%q+D: visibility attribute ignored "
- "because it", newdecl);
- warning (OPT_Wattributes, "%Jconflicts with previous "
- "declaration here", olddecl);
+ warning_at (input_location, OPT_Wattributes,
+ "%q+D: visibility attribute ignored because it", newdecl);
+ warning_at (DECL_SOURCE_LOCATION (olddecl), OPT_Wattributes,
+ "conflicts with previous declaration here");
}
/* Choose the declaration which specified visibility. */
if (DECL_VISIBILITY_SPECIFIED (olddecl))
ggc_free (DECL_LANG_SPECIFIC (olddecl));
}
- /* Merge the USED information. */
- if (TREE_USED (olddecl))
- TREE_USED (newdecl) = 1;
- else if (TREE_USED (newdecl))
- TREE_USED (olddecl) = 1;
+ /* Merge the USED information. */
+ if (TREE_USED (olddecl))
+ TREE_USED (newdecl) = 1;
+ else if (TREE_USED (newdecl))
+ TREE_USED (olddecl) = 1;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
sizeof (struct tree_function_decl) - sizeof (struct tree_decl_common));
- if (new_template)
+ if (new_template_info)
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
reregister_specialization (newdecl,
- new_template,
+ new_template_info,
olddecl);
}
else
void **slot;
tree decl;
- decl = build_decl (LABEL_DECL, id, void_type_node);
+ decl = build_decl (input_location, LABEL_DECL, id, void_type_node);
DECL_CONTEXT (decl) = current_function_decl;
DECL_MODE (decl) = VOIDmode;
static int
decl_jump_unsafe (tree decl)
{
+ /* [stmt.dcl]/3: A program that jumps from a point where a local variable
+ with automatic storage duration is not in scope to a point where it is
+ in scope is ill-formed unless the variable has scalar type, class type
+ with a trivial default constructor and a trivial destructor, a
+ cv-qualified version of one of these types, or an array of one of the
+ preceding types and is declared without an initializer (8.5). */
+ tree type = TREE_TYPE (decl);
+
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)
- || TREE_TYPE (decl) == error_mark_node)
+ || type == error_mark_node)
return 0;
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ type = strip_array_types (type);
+
+ if (type_has_nontrivial_default_init (TREE_TYPE (decl))
|| DECL_NONTRIVIALLY_INITIALIZED_P (decl))
return 2;
- if (pod_type_p (TREE_TYPE (decl)))
- return 0;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ return 1;
- /* The POD stuff is just pedantry; why should it matter if the class
- contains a field of pointer to member type? */
- return 1;
+ return 0;
}
/* A subroutine of check_previous_goto_1 to identify a branch to the user. */
else
permerror (input_location, "jump to case label");
if (locus)
- permerror (input_location, "%H from here", locus);
+ permerror (*locus, " from here");
}
/* Check that a single previously seen jump to a newly defined label
if (problem > 1)
error (" crosses initialization of %q+#D", new_decls);
else
- permerror (input_location, " enters scope of non-POD %q+#D", new_decls);
+ permerror (input_location, " enters scope of %q+#D which has "
+ "non-trivial destructor", new_decls);
}
if (b == level)
if (u > 1 && DECL_ARTIFICIAL (b))
{
/* Can't skip init of __exception_info. */
- error ("%J enters catch block", b);
+ error_at (DECL_SOURCE_LOCATION (b), " enters catch block");
saw_catch = true;
}
else if (u > 1)
error (" skips initialization of %q+#D", b);
else
- permerror (input_location, " enters scope of non-POD %q+#D", b);
+ permerror (input_location, " enters scope of %q+#D which has "
+ "non-trivial destructor", b);
}
if (ent->in_try_scope)
is a bad place for one. */
tree
-finish_case_label (tree low_value, tree high_value)
+finish_case_label (location_t loc, tree low_value, tree high_value)
{
tree cond, r;
struct cp_binding_level *p;
/* For templates, just add the case label; we'll do semantic
analysis at instantiation-time. */
- label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- return add_stmt (build_case_label (low_value, high_value, label));
+ label = build_decl (loc, LABEL_DECL, NULL_TREE, NULL_TREE);
+ return add_stmt (build_case_label (loc, low_value, high_value, label));
}
/* Find the condition on which this switch statement depends. */
if (!check_switch_goto (switch_stack->level))
return error_mark_node;
- r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond),
+ r = c_add_case_label (loc, switch_stack->cases, cond,
+ SWITCH_STMT_TYPE (switch_stack->switch_stmt),
low_value, high_value);
/* After labels, make any new cleanups in the function go into their
TYPENAME_IS_CLASS_P (t) = ti.class_p;
/* Build the corresponding TYPE_DECL. */
- d = build_decl (TYPE_DECL, name, t);
+ d = build_decl (input_location, TYPE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
gcc_assert (TYPE_P (context));
- /* When the CONTEXT is a dependent type, NAME could refer to a
- dependent base class of CONTEXT. So we cannot peek inside it,
- even if CONTEXT is a currently open scope. */
- if (dependent_type_p (context))
- return build_typename_type (context, name, fullname, tag_type);
-
if (!MAYBE_CLASS_TYPE_P (context))
{
if (complain & tf_error)
return error_mark_node;
}
+ /* When the CONTEXT is a dependent type, NAME could refer to a
+ dependent base class of CONTEXT. But look inside it anyway
+ if CONTEXT is a currently open scope, in case it refers to a
+ member of the current instantiation or a non-dependent base;
+ lookup will stop when we hit a dependent base. */
+ if (!dependent_scope_p (context))
+ /* We should only set WANT_TYPE when we're a nested typename type.
+ Then we can give better diagnostics if we find a non-type. */
+ t = lookup_field (context, name, 0, /*want_type=*/true);
+ else
+ t = NULL_TREE;
+
+ if (!t && dependent_type_p (context))
+ return build_typename_type (context, name, fullname, tag_type);
+
want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
- /* We should only set WANT_TYPE when we're a nested typename type.
- Then we can give better diagnostics if we find a non-type. */
- t = lookup_field (context, name, 0, /*want_type=*/true);
if (!t)
{
if (complain & tf_error)
SET_TYPE_STRUCTURAL_EQUALITY (t);
/* Build the corresponding TEMPLATE_DECL. */
- d = build_decl (TEMPLATE_DECL, name, t);
+ d = build_decl (input_location, TEMPLATE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
up built-in types by name. */
if (tname)
{
- tdecl = build_decl (TYPE_DECL, tname, type);
+ tdecl = build_decl (BUILTINS_LOCATION, TYPE_DECL, tname, type);
DECL_ARTIFICIAL (tdecl) = 1;
SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
{
if (!tdecl)
{
- tdecl = build_decl (TYPE_DECL, rname, type);
+ tdecl = build_decl (BUILTINS_LOCATION, TYPE_DECL, rname, type);
DECL_ARTIFICIAL (tdecl) = 1;
}
SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
{
tree type, decl;
if (size > 0)
- type = make_signed_type (size);
+ type = build_nonstandard_integer_type (size, 0);
else if (size > -32)
- { /* "__java_char" or ""__java_boolean". */
- type = make_unsigned_type (-size);
+ {
+ tree stype;
+ /* "__java_char" or ""__java_boolean". */
+ type = build_nonstandard_integer_type (-size, 1);
+ /* Get the signed type cached and attached to the unsigned type,
+ so it doesn't get garbage-collected at "random" times,
+ causing potential codegen differences out of different UIDs
+ and different alias set numbers. */
+ stype = build_nonstandard_integer_type (-size, 0);
+ TREE_CHAIN (type) = stype;
/*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/
}
else
{ /* "__java_float" or ""__java_double". */
- type = make_node (REAL_TYPE);
+ type = cxx_make_type (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
}
static void
record_unknown_type (tree type, const char* name)
{
- tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
+ tree decl = pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier (name), type));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
DECL_IGNORED_P (decl) = 1;
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
TYPE_SIZE (type) = TYPE_SIZE (void_type_node);
TYPE_ALIGN (type) = 1;
TYPE_USER_ALIGN (type) = 0;
- TYPE_MODE (type) = TYPE_MODE (void_type_node);
+ SET_TYPE_MODE (type, TYPE_MODE (void_type_node));
}
/* A string for which we should create an IDENTIFIER_NODE at
/* C++ extensions */
- unknown_type_node = make_node (UNKNOWN_TYPE);
+ unknown_type_node = cxx_make_type (UNKNOWN_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
- init_list_type_node = make_node (UNKNOWN_TYPE);
+ init_list_type_node = cxx_make_type (UNKNOWN_TYPE);
record_unknown_type (init_list_type_node, "init list");
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
- tree vfunc_type = make_node (FUNCTION_TYPE);
+ tree vfunc_type = cxx_make_type (FUNCTION_TYPE);
TREE_TYPE (vfunc_type) = integer_type_node;
TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
layout_type (vfunc_type);
abi_node = current_namespace;
pop_namespace ();
- global_type_node = make_node (LANG_TYPE);
+ global_type_node = cxx_make_type (LANG_TYPE);
record_unknown_type (global_type_node, "global type");
/* Now, C++. */
/* Perform other language dependent initializations. */
init_class_processing ();
init_rtti_processing ();
+ init_template_processing ();
if (flag_exceptions)
init_exception_processing ();
return init;
}
-/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
- decl, NAME is the initialization string and TYPE_DEP indicates whether
- NAME depended on the type of the function. We make use of that to detect
- __PRETTY_FUNCTION__ inside a template fn. This is being done
- lazily at the point of first use, so we mustn't push the decl now. */
+/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give
+ the decl, LOC is the location to give the decl, NAME is the
+ initialization string and TYPE_DEP indicates whether NAME depended
+ on the type of the function. We make use of that to detect
+ __PRETTY_FUNCTION__ inside a template fn. This is being done lazily
+ at the point of first use, so we mustn't push the decl now. */
static tree
-cp_make_fname_decl (tree id, int type_dep)
+cp_make_fname_decl (location_t loc, tree id, int type_dep)
{
const char *const name = (type_dep && processing_template_decl
? NULL : fname_as_string (type_dep));
tree type;
tree init = cp_fname_init (name, &type);
- tree decl = build_decl (VAR_DECL, id, type);
+ tree decl = build_decl (loc, VAR_DECL, id, type);
if (name)
free (CONST_CAST (char *, name));
}
static tree
-builtin_function_1 (tree decl, tree context)
+builtin_function_1 (tree decl, tree context, bool is_global)
{
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
retrofit_lang_decl (decl);
- /* All nesting of C++ functions is lexical; there is never a "static
- chain" in the sense of GNU C nested functions. */
- DECL_NO_STATIC_CHAIN (decl) = 1;
-
DECL_ARTIFICIAL (decl) = 1;
SET_OVERLOADED_OPERATOR_CODE (decl, ERROR_MARK);
SET_DECL_LANGUAGE (decl, lang_c);
DECL_CONTEXT (decl) = context;
- pushdecl (decl);
+ if (is_global)
+ pushdecl_top_level (decl);
+ else
+ pushdecl (decl);
/* A function in the user's namespace should have an explicit
declaration before it is used. Mark the built-in function as
{
tree decl2 = copy_node(decl);
push_namespace (std_identifier);
- builtin_function_1 (decl2, std_node);
+ builtin_function_1 (decl2, std_node, false);
+ pop_namespace ();
+ }
+
+ return builtin_function_1 (decl, NULL_TREE, false);
+}
+
+/* Like cxx_builtin_function, but guarantee the function is added to the global
+ scope. This is to allow function specific options to add new machine
+ dependent builtins when the target ISA changes via attribute((target(...)))
+ which saves space on program startup if the program does not use non-generic
+ ISAs. */
+
+tree
+cxx_builtin_function_ext_scope (tree decl)
+{
+
+ tree id = DECL_NAME (decl);
+ const char *name = IDENTIFIER_POINTER (id);
+ /* All builtins that don't begin with an '_' should additionally
+ go in the 'std' namespace. */
+ if (name[0] != '_')
+ {
+ tree decl2 = copy_node(decl);
+ push_namespace (std_identifier);
+ builtin_function_1 (decl2, std_node, true);
pop_namespace ();
}
- return builtin_function_1 (decl, NULL_TREE);
+ return builtin_function_1 (decl, NULL_TREE, true);
}
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
tree decl = TYPE_MAIN_DECL (t);
if (TREE_CODE (t) != UNION_TYPE)
- error ("%Jan anonymous struct cannot have function members", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "an anonymous struct cannot have function members");
else
- error ("%Jan anonymous union cannot have function members", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "an anonymous union cannot have function members");
}
/* Anonymous aggregates cannot have fields with ctors, dtors or complex
"and functions");
else if (saw_typedef)
warning (0, "%<typedef%> was ignored in this declaration");
+ else if (declspecs->specs[(int) ds_constexpr])
+ error ("%<constexpr> cannot be used for type declarations");
}
return declared_type;
tree
groktypename (cp_decl_specifier_seq *type_specifiers,
- const cp_declarator *declarator)
+ const cp_declarator *declarator,
+ bool is_template_arg)
{
tree attrs;
tree type;
+ enum decl_context context
+ = is_template_arg ? TEMPLATE_TYPE_ARG : TYPENAME;
attrs = type_specifiers->attributes;
type_specifiers->attributes = NULL_TREE;
- type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
+ type = grokdeclarator (declarator, type_specifiers, context, 0, &attrs);
if (attrs && type != error_mark_node)
{
if (CLASS_TYPE_P (type))
grokfield.) The DECL corresponding to the DECLARATOR is returned.
If an error occurs, the error_mark_node is returned instead.
- DECLSPECS are the decl-specifiers for the declaration. INITIALIZED is 1
- if an explicit initializer is present, or 2 for an explicitly defaulted
- function, or 3 for an explicitly deleted function, but 0 if this is a
- variable implicitly initialized via a default constructor. ATTRIBUTES
- and PREFIX_ATTRIBUTES are GNU attributes associated with this
- declaration. *PUSHED_SCOPE_P is set to the scope entered in this
- function, if any; if set, the caller is responsible for calling
- pop_scope. */
+ DECLSPECS are the decl-specifiers for the declaration. INITIALIZED is
+ SD_INITIALIZED if an explicit initializer is present, or SD_DEFAULTED
+ for an explicitly defaulted function, or SD_DELETED for an explicitly
+ deleted function, but 0 (SD_UNINITIALIZED) if this is a variable
+ implicitly initialized via a default constructor. ATTRIBUTES and
+ PREFIX_ATTRIBUTES are GNU attributes associated with this declaration.
+ *PUSHED_SCOPE_P is set to the scope entered in this function, if any; if
+ set, the caller is responsible for calling pop_scope. */
tree
start_decl (const cp_declarator *declarator,
return error_mark_node;
case FUNCTION_DECL:
- if (initialized == 3)
+ if (initialized == SD_DELETED)
/* We'll handle the rest of the semantics later, but we need to
set this now so it's visible to duplicate_decls. */
DECL_DELETED_FN (decl) = 1;
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
+ if (declspecs->specs[(int) ds_constexpr]
+ && !DECL_DECLARED_CONSTEXPR_P (field))
+ error ("%qD declared %<constexpr%> outside its class", field);
}
}
else
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
permerror (input_location, "declaration of %q#D outside of class is not definition",
decl);
+
+ if (!ensure_literal_type_for_constexpr_object (decl))
+ return error_mark_node;
}
was_public = TREE_PUBLIC (decl);
arrays which might be completed by the initialization. */
if (complete_p)
; /* A complete type is ok. */
+ else if (type_uses_auto (type))
+ ; /* An auto type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
error ("variable %q#D has initializer but incomplete type", decl);
}
else if (aggregate_definition_p && !complete_p)
{
- error ("aggregate %q#D has incomplete type and cannot be defined",
- decl);
+ if (type_uses_auto (type))
+ error ("declaration of %q#D has no initializer", decl);
+ else
+ error ("aggregate %q#D has incomplete type and cannot be defined",
+ decl);
/* Change the type so that assemble_variable will give
DECL an rtl we can live with: (mem (const_int 0)). */
type = TREE_TYPE (decl) = error_mark_node;
return NULL_TREE;
}
- if (TREE_CODE (init) == CONSTRUCTOR)
- {
- error ("ISO C++ forbids use of initializer list to "
- "initialize reference %qD", decl);
- return NULL_TREE;
- }
-
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, "initializer");
{
tree aggr_init, array, arrtype;
init = perform_implicit_conversion (type, init, tf_warning_or_error);
+ if (error_operand_p (init))
+ return error_mark_node;
+
aggr_init = TARGET_EXPR_INITIAL (init);
init = build2 (INIT_EXPR, type, decl, init);
{
/* The parser only allows identifiers as designated
initializers. */
- gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
- error ("name %qD used in a GNU-style designated "
- "initializer for an array", ce->index);
+ if (ce->index == error_mark_node)
+ error ("name used in a GNU-style designated "
+ "initializer for an array");
+ else
+ {
+ gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
+ error ("name %qD used in a GNU-style designated "
+ "initializer for an array", ce->index);
+ }
return false;
}
cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
- layout_decl (decl, 0);
+ relayout_decl (decl);
}
}
we have a weak definition, we must endeavor to create only one
instance of the variable at link-time. */
-static void
+void
maybe_commonize_var (tree decl)
{
/* Static data in a function with comdat linkage also has comdat
/* Don't mess with __FUNCTION__. */
&& ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
- /* Unfortunately, import_export_decl has not always been called
- before the function is processed, so we cannot simply check
- DECL_COMDAT. */
- && (DECL_COMDAT (DECL_CONTEXT (decl))
- || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
- || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
- && TREE_PUBLIC (DECL_CONTEXT (decl)))))
+ && vague_linkage_fn_p (DECL_CONTEXT (decl)))
{
if (flag_weak)
{
be merged. */
TREE_PUBLIC (decl) = 0;
DECL_COMMON (decl) = 0;
- warning (0, "sorry: semantics of inline function static "
- "data %q+#D are wrong (you'll wind up "
- "with multiple copies)", decl);
- warning (0, "%J you can work around this by removing "
- "the initializer",
- decl);
+ warning_at (input_location, 0,
+ "sorry: semantics of inline function static "
+ "data %q+#D are wrong (you'll wind up "
+ "with multiple copies)", decl);
+ warning_at (DECL_SOURCE_LOCATION (decl), 0,
+ " you can work around this by removing "
+ "the initializer");
}
}
}
{
tree type = TREE_TYPE (decl);
+ if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl)
+ && DECL_INITIAL (decl) == NULL)
+ error ("missing initializer for constexpr %qD", decl);
+
/* ``Unless explicitly declared extern, a const object does not have
external linkage and must be initialized. ($8.4; $12.1)'' ARM
7.1.6 */
- if (TREE_CODE (decl) == VAR_DECL
+ else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
a CONSTRUCTOR). TYPE is the type of the variable being initialized, D is the
iterator within the CONSTRUCTOR which points to the initializer to process.
FIRST_INITIALIZER_P is true if this is the first initializer of the
- CONSTRUCTOR node. */
+ outermost CONSTRUCTOR node. */
static tree
reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
{
tree init = d->cur->value;
+ if (error_operand_p (init))
+ return error_mark_node;
+
/* A non-aggregate type is always initialized with a single
initializer. */
if (!CP_AGGREGATE_TYPE_P (type))
initializer is considered for the initialization of the first
member of the subaggregate. */
if (TREE_CODE (init) != CONSTRUCTOR
- && can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL))
+ /* But don't try this for the first initializer, since that would be
+ looking through the outermost braces; A a2 = { a1 }; is not a
+ valid aggregate initialization. */
+ && !first_initializer_p
+ && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init))
+ || can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL)))
{
d->cur++;
return init;
decl);
init = build_tree_list (NULL_TREE, init);
}
- else if ((*targetm.vector_opaque_p) (type))
+ else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_VECTOR_OPAQUE (type))
{
error ("opaque vector types cannot be initialized");
init = error_mark_node;
return build_aggr_init_full_exprs (decl, init, flags);
else if (TREE_CODE (init) != TREE_VEC)
{
- init_code = store_init_value (decl, init);
+ init_code = store_init_value (decl, init, flags);
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
int was_readonly = 0;
bool var_definition_p = false;
int saved_processing_template_decl;
+ tree auto_node;
if (decl == error_mark_node)
return;
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
+ auto_node = type_uses_auto (type);
+ if (auto_node)
+ {
+ if (init == NULL_TREE)
+ {
+ error ("declaration of %q#D has no initializer", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ return;
+ }
+ if (TREE_CODE (init) == TREE_LIST)
+ init = build_x_compound_expr_from_list (init, "initializer");
+ if (describable_type (init))
+ {
+ type = TREE_TYPE (decl) = do_auto_deduction (type, init, auto_node);
+ if (type == error_mark_node)
+ return;
+ }
+ }
+
+ if (init && TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ tree clone;
+ if (init == ridpointers[(int)RID_DELETE])
+ {
+ /* FIXME check this is 1st decl. */
+ DECL_DELETED_FN (decl) = 1;
+ DECL_DECLARED_INLINE_P (decl) = 1;
+ DECL_INITIAL (decl) = error_mark_node;
+ FOR_EACH_CLONE (clone, decl)
+ {
+ DECL_DELETED_FN (clone) = 1;
+ DECL_DECLARED_INLINE_P (clone) = 1;
+ DECL_INITIAL (clone) = error_mark_node;
+ }
+ init = NULL_TREE;
+ }
+ else if (init == ridpointers[(int)RID_DEFAULT])
+ {
+ if (!defaultable_fn_p (decl))
+ {
+ error ("%qD cannot be defaulted", decl);
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+ else
+ {
+ DECL_DEFAULTED_FN (decl) = 1;
+ FOR_EACH_CLONE (clone, decl)
+ DECL_DEFAULTED_FN (clone) = 1;
+ }
+ }
+ }
+
if (processing_template_decl)
{
bool type_dependent_p;
DECL_INITIAL (decl) = NULL_TREE;
}
- if (init && init_const_expr_p)
+ if (init && init_const_expr_p && TREE_CODE (decl) == VAR_DECL)
{
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
if (TREE_CODE (decl) == VAR_DECL)
{
- /* Only PODs can have thread-local storage. Other types may require
- various kinds of non-trivial initialization. */
- if (DECL_THREAD_LOCAL_P (decl) && !pod_type_p (TREE_TYPE (decl)))
- error ("%qD cannot be thread-local because it has non-POD type %qT",
- decl, TREE_TYPE (decl));
+ /* Only variables with trivial initialization and destruction can
+ have thread-local storage. */
+ if (DECL_THREAD_LOCAL_P (decl)
+ && (type_has_nontrivial_default_init (TREE_TYPE (decl))
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ error ("%qD cannot be thread-local because it has non-trivial "
+ "type %qT", decl, TREE_TYPE (decl));
/* If this is a local variable that will need a mangled name,
register it now. We must do this before processing the
initializer for the variable, since the initialization might
type. */
else if (TREE_CODE (type) == ARRAY_TYPE)
layout_type (type);
+
+ if (!processing_template_decl
+ && TREE_STATIC (decl)
+ && !at_function_scope_p ()
+ && current_function_decl == NULL)
+ /* So decl is a global variable or a static member of a
+ non local class. Record the types it uses
+ so that we can decide later to emit debug info for them. */
+ record_types_used_by_current_var_decl (decl);
}
else if (TREE_CODE (decl) == FIELD_DECL
&& TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
{
if (init)
{
- if (init == ridpointers[(int)RID_DELETE])
+ if (init == ridpointers[(int)RID_DEFAULT])
{
- /* fixme check this is 1st decl */
- DECL_DELETED_FN (decl) = 1;
- DECL_DECLARED_INLINE_P (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node;
- }
- else if (init == ridpointers[(int)RID_DEFAULT])
- {
- if (!defaultable_fn_p (decl))
- error ("%qD cannot be defaulted", decl);
- else
- {
- /* An out-of-class default definition is defined at
- the point where it is explicitly defaulted. */
- DECL_DEFAULTED_FN (decl) = 1;
- if (DECL_INITIAL (decl) == error_mark_node)
- synthesize_method (decl);
- }
+ /* An out-of-class default definition is defined at
+ the point where it is explicitly defaulted. */
+ if (DECL_INITIAL (decl) == error_mark_node)
+ synthesize_method (decl);
}
else
error ("function %q#D is initialized like a variable", decl);
mark_decl_referenced (decl);
}
-/* This is here for a midend callback from c-common.c. */
-
-void
-finish_decl (tree decl, tree init, tree asmspec_tree)
-{
- cp_finish_decl (decl, init, /*init_const_expr_p=*/false, asmspec_tree, 0);
-}
-
/* Returns a declaration for a VAR_DECL as if:
extern "C" TYPE NAME;
tree decl;
push_to_top_level ();
- decl = build_decl (VAR_DECL, name, type);
+ decl = build_decl (input_location, VAR_DECL, name, type);
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
library), then it is possible that our declaration will be merged
with theirs by pushdecl. */
decl = pushdecl (decl);
- finish_decl (decl, NULL_TREE, NULL_TREE);
+ cp_finish_decl (decl, NULL_TREE, false, NULL_TREE, 0);
pop_from_top_level ();
return decl;
actually needed. It is unlikely that it will be inlined, since
it is only called via a function pointer, but we avoid unnecessary
emissions this way. */
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
DECL_INTERFACE_KNOWN (fndecl) = 1;
/* Build the parameter. */
if (use_cxa_atexit)
bool funcdef_flag,
int template_count,
tree in_namespace,
- tree* attrlist)
+ tree* attrlist,
+ location_t location)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+
+ /* If we have an explicit location, use it, otherwise use whatever
+ build_lang_decl used (probably input_location). */
+ if (location != UNKNOWN_LOCATION)
+ DECL_SOURCE_LOCATION (decl) = location;
+
if (TREE_CODE (type) == METHOD_TYPE)
{
tree parm;
parms = parm;
}
DECL_ARGUMENTS (decl) = parms;
+ for (t = parms; t; t = TREE_CHAIN (t))
+ DECL_CONTEXT (t) = decl;
/* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
{
case sfk_constructor:
case sfk_copy_constructor:
+ case sfk_move_constructor:
DECL_CONSTRUCTOR_P (decl) = 1;
break;
case sfk_destructor:
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
- if (publicp)
- {
- /* [basic.link]: A name with no linkage (notably, the name of a class
- or enumeration declared in a local scope) shall not be used to
- declare an entity with linkage.
-
- Only check this for public decls for now. See core 319, 389. */
- t = no_linkage_check (TREE_TYPE (decl),
- /*relaxed_p=*/false);
- if (t)
- {
- if (TYPE_ANONYMOUS_P (t))
- {
- if (DECL_EXTERN_C_P (decl))
- /* Allow this; it's pretty common in C. */;
- else
- {
- permerror (input_location, "non-local function %q#D uses anonymous type",
- decl);
- if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- permerror (input_location, "%q+#D does not refer to the unqualified "
- "type, so it is not used for linkage",
- TYPE_NAME (t));
- }
- }
- else
- permerror (input_location, "non-local function %q#D uses local type %qT", decl, t);
- }
- }
-
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
&& !grok_op_properties (decl, /*complain=*/true))
return NULL_TREE;
- if (ctype && decl_function_context (decl))
- DECL_NO_STATIC_CHAIN (decl) = 1;
-
if (funcdef_flag)
/* Make the init_value nonzero so pushdecl knows this is not
tentative. error_mark_node is replaced later with the BLOCK. */
|| TYPE_P (scope)))
decl = build_lang_decl (VAR_DECL, name, type);
else
- decl = build_decl (VAR_DECL, name, type);
+ decl = build_decl (input_location, VAR_DECL, name, type);
if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
set_decl_namespace (decl, explicit_scope, 0);
if (TREE_PUBLIC (decl))
{
- /* [basic.link]: A name with no linkage (notably, the name of a class
- or enumeration declared in a local scope) shall not be used to
- declare an entity with linkage.
-
- Only check this for public decls for now. */
- tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
- if (t)
- {
- if (TYPE_ANONYMOUS_P (t))
- {
- if (DECL_EXTERN_C_P (decl))
- /* Allow this; it's pretty common in C. */
- ;
- else
- {
- /* DRs 132, 319 and 389 seem to indicate types with
- no linkage can only be used to declare extern "C"
- entities. Since it's not always an error in the
- ISO C++ 90 Standard, we only issue a warning. */
- warning (0, "non-local variable %q#D uses anonymous type",
- decl);
- if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- warning (0, "%q+#D does not refer to the unqualified "
- "type, so it is not used for linkage",
- TYPE_NAME (t));
- }
- }
- else
- warning (0, "non-local variable %q#D uses local type %qT", decl, t);
- }
+ /* If the type of the decl has no linkage, make sure that we'll
+ notice that in mark_used. */
+ if (DECL_LANG_SPECIFIC (decl) == NULL
+ && TREE_PUBLIC (decl)
+ && !DECL_EXTERN_C_P (decl)
+ && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
+ retrofit_lang_decl (decl);
}
else
DECL_INTERFACE_KNOWN (decl) = 1;
/* ... and not really a class type. */
SET_CLASS_TYPE_P (t, 0);
- field = build_decl (FIELD_DECL, pfn_identifier, type);
+ field = build_decl (input_location, FIELD_DECL, pfn_identifier, type);
fields = field;
- field = build_decl (FIELD_DECL, delta_identifier, delta_type_node);
+ field = build_decl (input_location, FIELD_DECL, delta_identifier,
+ delta_type_node);
TREE_CHAIN (field) = fields;
fields = field;
/* If this is not the unqualified form of this pointer-to-member
type, set the TYPE_MAIN_VARIANT for this type to be the
unqualified type. Since they are actually RECORD_TYPEs that are
- not variants of each other, we must do this manually. */
+ not variants of each other, we must do this manually.
+ As we just built a new type there is no need to do yet another copy. */
if (cp_type_quals (type) != TYPE_UNQUALIFIED)
{
- t = build_qualified_type (t, cp_type_quals (type));
+ int type_quals = cp_type_quals (type);
+ TYPE_READONLY (t) = (type_quals & TYPE_QUAL_CONST) != 0;
+ TYPE_VOLATILE (t) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
+ TYPE_RESTRICT (t) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
TYPE_MAIN_VARIANT (t) = unqualified_variant;
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
TYPE_NEXT_VARIANT (unqualified_variant) = t;
error ("ISO C++ forbids in-class initialization of non-const "
"static member %qD",
decl);
- else if (!INTEGRAL_TYPE_P (type))
+ else if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
type = TREE_TYPE (size);
/* The array bound must be an integer type. */
- if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
+ if (!dependent_type_p (type) && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
{
if (name)
error ("size of array %qD has non-integral type %qT", name, type);
type = TREE_TYPE (size);
}
- if (value_dependent_expression_p (size))
+ /* We can only call value_dependent_expression_p on integral constant
+ expressions; the parser adds a dummy NOP_EXPR with TREE_SIDE_EFFECTS
+ set if this isn't one. */
+ if (processing_template_decl
+ && (TREE_SIDE_EFFECTS (size) || value_dependent_expression_p (size)))
{
- /* We cannot do any checking for a value-dependent SIZE. Just
- build the index type and mark that it requires structural
- equality checks. */
+ /* We cannot do any checking for a SIZE that isn't known to be
+ constant. Just build the index type and mark that it requires
+ structural equality checks. */
itype = build_index_type (build_min (MINUS_EXPR, sizetype,
size, integer_one_node));
+ if (!TREE_SIDE_EFFECTS (size))
+ {
+ TYPE_DEPENDENT_P (itype) = 1;
+ TYPE_DEPENDENT_P_VALID (itype) = 1;
+ }
SET_TYPE_STRUCTURAL_EQUALITY (itype);
return itype;
}
cp_build_binary_op will be appropriately folded. */
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
- itype = cp_build_binary_op (MINUS_EXPR,
+ itype = cp_build_binary_op (input_location,
+ MINUS_EXPR,
cp_convert (ssizetype, size),
cp_convert (ssizetype, integer_one_node),
tf_warning_or_error);
bool unsigned_p, signed_p, short_p, long_p, thread_p;
bool type_was_error_mark_node = false;
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
- bool set_no_warning = false;
+ bool template_type_arg = false;
+ bool constexpr_p = declspecs->specs[(int) ds_constexpr];
+ const char *errmsg;
signed_p = declspecs->specs[(int)ds_signed];
unsigned_p = declspecs->specs[(int)ds_unsigned];
funcdef_flag = true, decl_context = FIELD;
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
+ else if (decl_context == TEMPLATE_TYPE_ARG)
+ template_type_arg = true, decl_context = TYPENAME;
if (initialized > 1)
funcdef_flag = true;
}
type = TREE_OPERAND (decl, 0);
- name = IDENTIFIER_POINTER (constructor_name (type));
+ if (TYPE_P (type))
+ type = constructor_name (type);
+ name = identifier_to_locale (IDENTIFIER_POINTER (type));
dname = decl;
}
break;
{
error ("declarator-id missing; using reserved word %qD",
dname);
- name = IDENTIFIER_POINTER (dname);
+ name = identifier_to_locale (IDENTIFIER_POINTER (dname));
}
else if (!IDENTIFIER_TYPENAME_P (dname))
- name = IDENTIFIER_POINTER (dname);
+ name = identifier_to_locale (IDENTIFIER_POINTER (dname));
else
{
gcc_assert (flags == NO_SPECIAL);
ctor_return_type = TREE_TYPE (dname);
sfk = sfk_conversion;
if (is_typename_at_global_scope (dname))
- name = IDENTIFIER_POINTER (dname);
+ name = identifier_to_locale (IDENTIFIER_POINTER (dname));
else
name = "<invalid operator>";
}
suppress reports of deprecated items. */
if (type && TREE_DEPRECATED (type)
&& deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (type);
+ warn_deprecated_use (type, NULL_TREE);
if (type && TREE_CODE (type) == TYPE_DECL)
{
typedef_decl = type;
if (TREE_DEPRECATED (type)
&& DECL_ARTIFICIAL (typedef_decl)
&& deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (type);
+ warn_deprecated_use (type, NULL_TREE);
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
type_quals = TYPE_UNQUALIFIED;
if (declspecs->specs[(int)ds_const])
type_quals |= TYPE_QUAL_CONST;
+ /* A `constexpr' specifier used in an object declaration declares
+ the object as `const'. */
+ if (constexpr_p)
+ {
+ if (innermost_code == cdk_function)
+ ;
+ else if (declspecs->specs[(int)ds_const] != 0)
+ error ("both %<const%> and %<constexpr%> cannot be used here");
+ else
+ type_quals |= TYPE_QUAL_CONST;
+ }
if (declspecs->specs[(int)ds_volatile])
type_quals |= TYPE_QUAL_VOLATILE;
if (declspecs->specs[(int)ds_restrict])
|| storage_class == sc_extern
|| thread_p)
error ("storage class specifiers invalid in parameter declarations");
+
+ if (type_uses_auto (type))
+ {
+ error ("parameter declared %<auto%>");
+ type = error_mark_node;
+ }
+
+ /* Function parameters cannot be constexpr. If we saw one, moan
+ and pretend it wasn't there. */
+ if (constexpr_p)
+ {
+ error ("a parameter cannot be declared %<constexpr%>");
+ constexpr_p = 0;
+ }
}
/* Give error if `virtual' is used outside of class declaration. */
switch (TREE_CODE (unqualified_id))
{
case BIT_NOT_EXPR:
- unqualified_id
- = constructor_name (TREE_OPERAND (unqualified_id, 0));
+ unqualified_id = TREE_OPERAND (unqualified_id, 0);
+ if (TYPE_P (unqualified_id))
+ unqualified_id = constructor_name (unqualified_id);
break;
case IDENTIFIER_NODE:
/* We now know that the TYPE_QUALS don't apply to the
decl, but to its return type. */
type_quals = TYPE_UNQUALIFIED;
- set_no_warning = true;
+ }
+ errmsg = targetm.invalid_return_type (type);
+ if (errmsg)
+ {
+ error (errmsg);
+ type = integer_type_node;
}
/* Error about some types functions can't return. */
closest to the identifier. */
funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
+ /* Handle a late-specified return type. */
+ if (funcdecl_p)
+ {
+ if (type_uses_auto (type))
+ {
+ if (!declarator->u.function.late_return_type)
+ {
+ error ("%qs function uses %<auto%> type specifier without"
+ " late return type", name);
+ return error_mark_node;
+ }
+ else if (!is_auto (type))
+ {
+ error ("%qs function with late return type has"
+ " %qT as its type rather than plain %<auto%>",
+ name, type);
+ return error_mark_node;
+ }
+ }
+ else if (declarator->u.function.late_return_type)
+ {
+ error ("%qs function with late return type not declared"
+ " with %<auto%> type specifier", name);
+ return error_mark_node;
+ }
+ }
+ type = splice_late_return_type
+ (type, declarator->u.function.late_return_type);
+ if (type == error_mark_node)
+ return error_mark_node;
+
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
"class definition",
name);
}
+ else if (ctype && sfk == sfk_conversion)
+ {
+ if (explicitp == 1)
+ {
+ maybe_warn_cpp0x ("explicit conversion operators");
+ explicitp = 2;
+ }
+ }
+
+ /* It is not allowed to use `constexpr' in a function
+ declaration that is not a definition.
+ That is too strict, though. */
+ if (constexpr_p && !funcdef_flag)
+ {
+ error ("the %<constexpr%> specifier cannot be used in "
+ "a function declaration that is not a definition");
+ constexpr_p = false;
+ }
+
+ /* A constexpr non-static member function is implicitly const. */
+ if (constexpr_p && decl_context == FIELD && staticp == 0
+ && sfk != sfk_constructor && sfk != sfk_destructor)
+ memfn_quals |= TYPE_QUAL_CONST;
arg_types = grokparms (declarator->u.function.parameters,
&parms);
memfn_quals = TYPE_UNQUALIFIED;
}
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ && cp_type_quals (type) != TYPE_UNQUALIFIED)
+ error ("cannot declare %s to qualified function type %qT",
+ declarator->kind == cdk_reference ? "reference" : "pointer",
+ type);
+
if (declarator->kind == cdk_reference)
{
/* In C++0x, the type we are creating a reference to might be
return error_mark_node;
}
+ /* It is not permitted to define a member function outside ist
+ membership class as `constexpr'. */
+ if (constexpr_p)
+ error ("a constexpr function cannot be defined "
+ "outside of its class.");
+
if (TREE_CODE (sname) == IDENTIFIER_NODE
&& NEW_DELETE_OPNAME_P (sname))
/* Overloaded operator new and operator delete
if (decl_context == FIELD)
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
- decl = build_decl (TYPE_DECL, unqualified_id, type);
- if (id_declarator && declarator->u.id.qualifying_scope)
- error ("%Jtypedef name may not be a nested-name-specifier", decl);
+ decl = build_decl (input_location, TYPE_DECL, unqualified_id, type);
+ if (id_declarator && declarator->u.id.qualifying_scope) {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "typedef name may not be a nested-name-specifier");
+ TREE_TYPE (decl) = error_mark_node;
+ }
if (decl_context != FIELD)
{
&& TYPE_ANONYMOUS_P (type)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
- tree oldname = TYPE_NAME (type);
tree t;
/* Replace the anonymous name with the real name everywhere. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- if (TYPE_NAME (t) == oldname)
- TYPE_NAME (t) = decl;
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ {
+ debug_hooks->set_name (t, decl);
+ TYPE_NAME (t) = decl;
+ }
+ }
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
= TYPE_IDENTIFIER (type);
+ /* Adjust linkage now that we aren't anonymous anymore. */
+ set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
+ determine_visibility (TYPE_MAIN_DECL (type));
+
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
}
}
else if (memfn_quals)
{
- if (ctype == NULL_TREE)
- {
- if (TREE_CODE (type) != METHOD_TYPE)
- error ("invalid qualifiers on non-member function type");
- else
- ctype = TYPE_METHOD_BASETYPE (type);
- }
+ if (ctype == NULL_TREE
+ && TREE_CODE (type) == METHOD_TYPE)
+ ctype = TYPE_METHOD_BASETYPE (type);
+
if (ctype)
type = build_memfn_type (type, ctype, memfn_quals);
+ /* Core issue #547: need to allow this in template type args. */
+ else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
+ type = cp_build_qualified_type (type, memfn_quals);
+ else
+ error ("invalid qualifiers on non-member function type");
}
return type;
/* Check that the name used for a destructor makes sense. */
if (sfk == sfk_destructor)
{
+ tree uqname = id_declarator->u.id.unqualified_name;
+
if (!ctype)
{
gcc_assert (friendp);
error ("expected qualified name in friend declaration "
- "for destructor %qD",
- id_declarator->u.id.unqualified_name);
+ "for destructor %qD", uqname);
return error_mark_node;
}
- if (!same_type_p (TREE_OPERAND
- (id_declarator->u.id.unqualified_name, 0),
- ctype))
+ if (!check_dtor_name (ctype, TREE_OPERAND (uqname, 0)))
{
error ("declaration of %qD as member of %qT",
- id_declarator->u.id.unqualified_name, ctype);
+ uqname, ctype);
return error_mark_node;
}
+ if (constexpr_p)
+ error ("a destructor cannot be %<constexpr%>");
}
else if (sfk == sfk_constructor && friendp)
{
parms,
unqualified_id,
virtualp, flags, memfn_quals, raises,
- friendp ? -1 : 0, friendp, publicp, inlinep,
+ friendp ? -1 : 0, friendp, publicp,
+ inlinep || constexpr_p,
sfk,
- funcdef_flag, template_count, in_namespace, attrlist);
+ funcdef_flag, template_count, in_namespace,
+ attrlist, declarator->id_loc);
if (decl == NULL_TREE)
return error_mark_node;
#if 0
is called a converting constructor. */
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
- else if (DECL_CONSTRUCTOR_P (decl))
- {
- /* A constructor with no parms is not a conversion.
- Ignore any compiler-added parms. */
- tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
-
- if (arg_types == void_list_node)
- DECL_NONCONVERTING_P (decl) = 1;
- }
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
virtualp, flags, memfn_quals, raises,
friendp ? -1 : 0, friendp, 1, 0, sfk,
funcdef_flag, template_count, in_namespace,
- attrlist);
+ attrlist,
+ declarator->id_loc);
if (decl == NULL_TREE)
return error_mark_node;
}
decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags,
funcdef_flag);
+ DECL_DECLARED_CONSTEXPR_P (decl) = constexpr_p;
return decl;
}
else
}
else
{
- decl = build_decl (FIELD_DECL, unqualified_id, type);
+ if (constexpr_p)
+ error ("non-static data member %qE declared %<constexpr%>",
+ unqualified_id);
+ decl = build_decl (input_location,
+ FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !unqualified_id)
TREE_NO_WARNING (decl) = 1;
"declared out of global scope", name);
}
+ if (ctype != NULL_TREE
+ && TREE_CODE (ctype) != NAMESPACE_DECL && !MAYBE_CLASS_TYPE_P (ctype))
+ {
+ error ("%q#T is not a class or a namespace", ctype);
+ ctype = NULL_TREE;
+ }
+
if (ctype == NULL_TREE)
{
if (virtualp)
error ("virtual non-class function %qs", name);
virtualp = 0;
}
+ else if (sfk == sfk_constructor
+ || sfk == sfk_destructor)
+ {
+ error (funcdef_flag
+ ? "%qs defined in a non-class scope"
+ : "%qs declared in a non-class scope", name);
+ sfk = sfk_none;
+ }
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
&& !NEW_DELETE_OPNAME_P (original_name))
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, memfn_quals, raises,
1, friendp,
- publicp, inlinep, sfk, funcdef_flag,
- template_count, in_namespace, attrlist);
+ publicp, inlinep || constexpr_p, sfk, funcdef_flag,
+ template_count, in_namespace, attrlist,
+ declarator->id_loc);
if (decl == NULL_TREE)
return error_mark_node;
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
+ /* Don't forget constexprness. */
+ if (VAR_OR_FUNCTION_DECL_P (decl))
+ DECL_DECLARED_CONSTEXPR_P (decl) = constexpr_p;
+
/* Record constancy and volatility on the DECL itself . There's
no need to do this when processing a template; we'll do this
for the instantiated declaration based on the type of DECL. */
if (!processing_template_decl)
cp_apply_type_quals_to_decl (type_quals, decl);
- if (set_no_warning)
- TREE_NO_WARNING (decl) = 1;
-
return decl;
}
}
return arg;
}
+/* Returns a deprecated type used within TYPE, or NULL_TREE if none. */
+
+static tree
+type_is_deprecated (tree type)
+{
+ enum tree_code code;
+ if (TREE_DEPRECATED (type))
+ return type;
+ if (TYPE_NAME (type)
+ && TREE_DEPRECATED (TYPE_NAME (type)))
+ return type;
+
+ code = TREE_CODE (type);
+
+ if (code == POINTER_TYPE || code == REFERENCE_TYPE
+ || code == OFFSET_TYPE || code == FUNCTION_TYPE
+ || code == METHOD_TYPE || code == ARRAY_TYPE)
+ return type_is_deprecated (TREE_TYPE (type));
+
+ if (TYPE_PTRMEMFUNC_P (type))
+ return type_is_deprecated
+ (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+
+ return NULL_TREE;
+}
+
/* Decode the list of parameter types for a function type.
Given the list of things declared inside the parens,
return a list of types.
*PARMS is set to the chain of PARM_DECLs created. */
static tree
-grokparms (cp_parameter_declarator *first_parm, tree *parms)
+grokparms (tree parmlist, tree *parms)
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
- int ellipsis = !first_parm || first_parm->ellipsis_p;
- cp_parameter_declarator *parm;
+ tree parm;
int any_error = 0;
- struct pointer_set_t *unique_decls = pointer_set_create ();
- for (parm = first_parm; parm != NULL; parm = parm->next)
+ for (parm = parmlist; parm != NULL_TREE; parm = TREE_CHAIN (parm))
{
tree type = NULL_TREE;
- tree init = parm->default_argument;
- tree attrs;
- tree decl;
+ tree init = TREE_PURPOSE (parm);
+ tree decl = TREE_VALUE (parm);
+ const char *errmsg;
- if (parm == no_parameters)
+ if (parm == void_list_node)
break;
- attrs = parm->decl_specifiers.attributes;
- parm->decl_specifiers.attributes = NULL_TREE;
- decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
- PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
- if (attrs)
- cplus_decl_attributes (&decl, attrs, 0);
-
type = TREE_TYPE (decl);
if (VOID_TYPE_P (type))
{
if (same_type_p (type, void_type_node)
&& DECL_SELF_REFERENCE_P (type)
- && !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
+ && !DECL_NAME (decl) && !result && TREE_CHAIN (parm) == void_list_node)
/* this is a parmlist of `(void)', which is ok. */
break;
cxx_incomplete_type_error (decl, type);
init = NULL_TREE;
}
+ if (type != error_mark_node
+ && (errmsg = targetm.invalid_parameter_type (type)))
+ {
+ error (errmsg);
+ type = error_mark_node;
+ TREE_TYPE (decl) = error_mark_node;
+ }
+
if (type != error_mark_node)
{
+ if (deprecated_state != DEPRECATED_SUPPRESS)
+ {
+ tree deptype = type_is_deprecated (type);
+ if (deptype)
+ warn_deprecated_use (deptype, NULL_TREE);
+ }
+
/* Top-level qualifiers on the parameters are
ignored for function types. */
type = cp_build_qualified_type (type, 0);
if (TREE_CODE (decl) == PARM_DECL
&& FUNCTION_PARAMETER_PACK_P (decl)
- && parm->next)
+ && TREE_CHAIN (parm)
+ && TREE_CHAIN (parm) != void_list_node)
error ("parameter packs must be at the end of the parameter list");
- if (DECL_NAME (decl))
- {
- if (pointer_set_contains (unique_decls, DECL_NAME (decl)))
- error ("multiple parameters named %qE", DECL_NAME (decl));
- else
- pointer_set_insert (unique_decls, DECL_NAME (decl));
- }
-
TREE_CHAIN (decl) = decls;
decls = decl;
result = tree_cons (init, type, result);
}
decls = nreverse (decls);
result = nreverse (result);
- if (!ellipsis)
+ if (parm)
result = chainon (result, void_list_node);
*parms = decls;
- pointer_set_destroy (unique_decls);
return result;
}
/* Remember any special properties of member function DECL. */
+#define DECL_DEFAULTED_IN_CLASS_P(DECL) \
+ (DECL_DEFAULTED_FN (DECL) \
+ && (DECL_ARTIFICIAL (DECL) || DECL_INITIALIZED_IN_CLASS_P (DECL)))
+
void
grok_special_member_properties (tree decl)
{
are no other parameters or else all other parameters have
default arguments. */
TYPE_HAS_INIT_REF (class_type) = 1;
- if (!DECL_DEFAULTED_FN (decl))
+ if (!DECL_DEFAULTED_IN_CLASS_P (decl))
TYPE_HAS_COMPLEX_INIT_REF (class_type) = 1;
if (ctor > 1)
TYPE_HAS_CONST_INIT_REF (class_type) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
- TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
+ {
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
+ if (TREE_CODE (decl) == TEMPLATE_DECL
+ || !DECL_DEFAULTED_IN_CLASS_P (decl))
+ TYPE_HAS_COMPLEX_DFLT (class_type) = 1;
+ }
else if (is_list_ctor (decl))
TYPE_HAS_LIST_CTOR (class_type) = 1;
}
if (assop)
{
TYPE_HAS_ASSIGN_REF (class_type) = 1;
- if (!DECL_DEFAULTED_FN (decl))
+ if (!DECL_DEFAULTED_IN_CLASS_P (decl))
TYPE_HAS_COMPLEX_ASSIGN_REF (class_type) = 1;
if (assop != 1)
TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
BINFO_OFFSET (binfo) = size_zero_node;
BINFO_TYPE (binfo) = ref;
+ /* Apply base-class info set up to the variants of this type. */
+ fixup_type_variants (ref);
+
if (max_bases)
{
BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, max_bases);
\f
/* Begin compiling the definition of an enumeration type.
- NAME is its name.
+ NAME is its name,
+
+ UNDERLYING_TYPE is the type that will be used as the storage for
+ the enumeration type. This should be NULL_TREE if no storage type
+ was specified.
+
+ SCOPED_ENUM_P is true if this is a scoped enumeration type.
+
Returns the type object, as yet incomplete.
Also records info about it so that build_enumerator
may be used to declare the individual values as they are read. */
tree
-start_enum (tree name)
+start_enum (tree name, tree underlying_type, bool scoped_enum_p)
{
tree enumtype;
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
{
- error ("multiple definition of %q#T", enumtype);
- error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype));
+ error_at (input_location, "multiple definition of %q#T", enumtype);
+ error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
+ "previous definition here");
/* Clear out TYPE_VALUES, and start again. */
TYPE_VALUES (enumtype) = NULL_TREE;
}
if (enumtype == error_mark_node)
name = make_anon_name ();
- enumtype = make_node (ENUMERAL_TYPE);
+ enumtype = cxx_make_type (ENUMERAL_TYPE);
enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
}
+ if (enumtype == error_mark_node)
+ return enumtype;
+
+ if (scoped_enum_p)
+ {
+ SET_SCOPED_ENUM_P (enumtype, 1);
+ begin_scope (sk_scoped_enum, enumtype);
+
+ /* [C++0x dcl.enum]p5:
+
+ If not explicitly specified, the underlying type of a scoped
+ enumeration type is int. */
+ if (!underlying_type)
+ underlying_type = integer_type_node;
+ }
+
+ if (underlying_type)
+ {
+ if (CP_INTEGRAL_TYPE_P (underlying_type))
+ {
+ TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (underlying_type);
+ TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (underlying_type);
+ TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type);
+ TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type);
+ SET_TYPE_MODE (enumtype, TYPE_MODE (underlying_type));
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
+ TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
+ TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
+ TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type);
+ ENUM_UNDERLYING_TYPE (enumtype) = underlying_type;
+ }
+ else if (!dependent_type_p (underlying_type))
+ error ("underlying type %<%T%> of %<%T%> must be an integral type",
+ underlying_type, enumtype);
+ }
+
return enumtype;
}
{
tree values;
tree decl;
- tree value;
tree minnode;
tree maxnode;
+ tree value;
tree t;
bool unsignedp;
bool use_short_enum;
int lowprec;
int highprec;
int precision;
- integer_type_kind itk;
+ unsigned int itk;
tree underlying_type = NULL_TREE;
+ bool fixed_underlying_type_p
+ = ENUM_UNDERLYING_TYPE (enumtype) != NULL_TREE;
/* We built up the VALUES in reverse order. */
TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
TREE_TYPE (TREE_VALUE (values)) = enumtype;
if (at_function_scope_p ())
add_stmt (build_min (TAG_DEFN, enumtype));
+ if (SCOPED_ENUM_P (enumtype))
+ finish_scope ();
return;
}
minnode = maxnode = NULL_TREE;
for (values = TYPE_VALUES (enumtype);
- values;
- values = TREE_CHAIN (values))
- {
- decl = TREE_VALUE (values);
-
- /* [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;
-
- /* Update the minimum and maximum values, if appropriate. */
- value = DECL_INITIAL (decl);
- if (value == error_mark_node)
- value = integer_zero_node;
- /* 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;
- }
+ values;
+ values = TREE_CHAIN (values))
+ {
+ decl = TREE_VALUE (values);
+
+ /* [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;
+
+ /* Update the minimum and maximum values, if appropriate. */
+ value = DECL_INITIAL (decl);
+ if (value == error_mark_node)
+ value = integer_zero_node;
+ /* 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;
+ }
}
else
/* [dcl.enum]
-
+
If the enumerator-list is empty, the underlying type is as if
the enumeration had a single enumerator with value 0. */
minnode = maxnode = integer_zero_node;
/* Compute the number of bits require to represent all values of the
enumeration. We must do this before the type of MINNODE and
- MAXNODE are transformed, since min_precision relies on the
- TREE_TYPE of the value it is passed. */
+ MAXNODE are transformed, since tree_int_cst_min_precision relies
+ on the TREE_TYPE of the value it is passed. */
unsignedp = tree_int_cst_sgn (minnode) >= 0;
- lowprec = min_precision (minnode, unsignedp);
- highprec = min_precision (maxnode, unsignedp);
+ lowprec = tree_int_cst_min_precision (minnode, unsignedp);
+ highprec = tree_int_cst_min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
- /* Determine the underlying type of the enumeration.
+ if (!fixed_underlying_type_p)
+ {
+ /* Determine the underlying type of the enumeration.
- [dcl.enum]
+ [dcl.enum]
- The underlying type of an enumeration is an integral type that
- can represent all the enumerator values defined in the
- enumeration. It is implementation-defined which integral type is
- used as the underlying type for an enumeration except that the
- underlying type shall not be larger than int unless the value of
- an enumerator cannot fit in an int or unsigned int.
+ The underlying type of an enumeration is an integral type that
+ can represent all the enumerator values defined in the
+ enumeration. It is implementation-defined which integral type is
+ used as the underlying type for an enumeration except that the
+ underlying type shall not be larger than int unless the value of
+ an enumerator cannot fit in an int or unsigned int.
- We use "int" or an "unsigned int" as the underlying type, even if
- a smaller integral type would work, unless the user has
- explicitly requested that we use the smallest possible type. The
- user can request that for all enumerations with a command line
- flag, or for just one enumeration with an attribute. */
+ We use "int" or an "unsigned int" as the underlying type, even if
+ a smaller integral type would work, unless the user has
+ explicitly requested that we use the smallest possible type. The
+ user can request that for all enumerations with a command line
+ flag, or for just one enumeration with an attribute. */
- use_short_enum = flag_short_enums
- || lookup_attribute ("packed", TYPE_ATTRIBUTES (enumtype));
+ use_short_enum = flag_short_enums
+ || lookup_attribute ("packed", TYPE_ATTRIBUTES (enumtype));
- for (itk = (use_short_enum ? itk_char : itk_int);
- itk != itk_none;
- itk++)
- {
- underlying_type = integer_types[itk];
- if (TYPE_PRECISION (underlying_type) >= precision
- && TYPE_UNSIGNED (underlying_type) == unsignedp)
- break;
- }
- if (itk == itk_none)
- {
- /* DR 377
+ for (itk = (use_short_enum ? itk_char : itk_int);
+ itk != itk_none;
+ itk++)
+ {
+ underlying_type = integer_types[itk];
+ if (TYPE_PRECISION (underlying_type) >= precision
+ && TYPE_UNSIGNED (underlying_type) == unsignedp)
+ break;
+ }
+ if (itk == itk_none)
+ {
+ /* DR 377
+
+ IF no integral type can represent all the enumerator values, the
+ enumeration is ill-formed. */
+ error ("no integral type can represent all of the enumerator values "
+ "for %qT", enumtype);
+ precision = TYPE_PRECISION (long_long_integer_type_node);
+ underlying_type = integer_types[itk_unsigned_long_long];
+ }
- IF no integral type can represent all the enumerator values, the
- enumeration is ill-formed. */
- error ("no integral type can represent all of the enumerator values "
- "for %qT", enumtype);
- precision = TYPE_PRECISION (long_long_integer_type_node);
- underlying_type = integer_types[itk_unsigned_long_long];
+ /* [dcl.enum]
+
+ The value of sizeof() applied to an enumeration type, an object
+ of an enumeration type, or an enumerator, is the value of sizeof()
+ applied to the underlying type. */
+ TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type);
+ TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type);
+ SET_TYPE_MODE (enumtype, TYPE_MODE (underlying_type));
+ TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
+ TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
+ TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type);
+
+ /* Set the underlying type of the enumeration type to the
+ computed enumeration type, restricted to the enumerator
+ values. */
+ ENUM_UNDERLYING_TYPE (enumtype)
+ = build_distinct_type_copy (underlying_type);
+ set_min_and_max_values_for_integral_type
+ (ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
}
+ else
+ underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
/* Compute the minimum and maximum values for the type.
underlying type in the range bmin to bmax, where bmin and bmax are,
respectively, the smallest and largest values of the smallest bit-
field that can store emin and emax. */
-
+
/* The middle-end currently assumes that types with TYPE_PRECISION
narrower than their underlying type are suitably zero or sign
extended to fill their mode. g++ doesn't make these guarantees.
Until the middle-end can represent such paradoxical types, we
set the TYPE_PRECISION to the width of the underlying type. */
TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
-
+
set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
-
- /* [dcl.enum]
-
- The value of sizeof() applied to an enumeration type, an object
- of an enumeration type, or an enumerator, is the value of sizeof()
- applied to the underlying type. */
- TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type);
- TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type);
- TYPE_MODE (enumtype) = TYPE_MODE (underlying_type);
- TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
- TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
- TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type);
-
+
/* Convert each of the enumerators to the type of the underlying
type of the enumeration. */
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
decl = TREE_VALUE (values);
saved_location = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
- value = perform_implicit_conversion (underlying_type,
- DECL_INITIAL (decl),
- tf_warning_or_error);
+ if (fixed_underlying_type_p)
+ /* If the enumeration type has a fixed underlying type, we
+ already checked all of the enumerator values. */
+ value = DECL_INITIAL (decl);
+ else
+ value = perform_implicit_conversion (underlying_type,
+ DECL_INITIAL (decl),
+ tf_warning_or_error);
input_location = saved_location;
/* Do not clobber shared ints. */
TREE_TYPE (value) = enumtype;
DECL_INITIAL (decl) = value;
- TREE_VALUE (values) = value;
}
/* Fix up all variant types of this enum type. */
TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (enumtype);
TYPE_SIZE (t) = TYPE_SIZE (enumtype);
TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (enumtype);
- TYPE_MODE (t) = TYPE_MODE (enumtype);
+ SET_TYPE_MODE (t, TYPE_MODE (enumtype));
TYPE_PRECISION (t) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (t) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype);
TYPE_UNSIGNED (t) = TYPE_UNSIGNED (enumtype);
+ ENUM_UNDERLYING_TYPE (t) = ENUM_UNDERLYING_TYPE (enumtype);
}
+ /* Finish up the scope of a scoped enumeration. */
+ if (SCOPED_ENUM_P (enumtype))
+ finish_scope ();
+
/* Finish debugging output for this type. */
rest_of_type_compilation (enumtype, namespace_bindings_p ());
}
tree prev_value;
bool overflowed;
- /* The next value is the previous value plus one. We can
- safely assume that the previous value is an INTEGER_CST.
+ /* The next value is the previous value plus one.
add_double doesn't know the type of the target expression,
so we must check with int_fits_type_p as well. */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
- overflowed = add_double (TREE_INT_CST_LOW (prev_value),
- TREE_INT_CST_HIGH (prev_value),
- 1, 0, &lo, &hi);
- value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
- overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
-
- if (overflowed)
+ if (error_operand_p (prev_value))
+ value = error_mark_node;
+ else
{
- error ("overflow in enumeration values at %qD", name);
- value = error_mark_node;
+ overflowed = add_double (TREE_INT_CST_LOW (prev_value),
+ TREE_INT_CST_HIGH (prev_value),
+ 1, 0, &lo, &hi);
+ value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
+ overflowed
+ |= !int_fits_type_p (value, TREE_TYPE (prev_value));
+
+ if (overflowed)
+ {
+ error ("overflow in enumeration values at %qD", name);
+ value = error_mark_node;
+ }
}
}
else
/* Remove no-op casts from the value. */
STRIP_TYPE_NOPS (value);
+
+ /* If the underlying type of the enum is fixed, check whether
+ the enumerator values fits in the underlying type. If it
+ does not fit, the program is ill-formed [C++0x dcl.enum]. */
+ if (ENUM_UNDERLYING_TYPE (enumtype)
+ && value
+ && TREE_CODE (value) == INTEGER_CST
+ && !int_fits_type_p (value, ENUM_UNDERLYING_TYPE (enumtype)))
+ {
+ error ("enumerator value %E is too large for underlying type %<%T%>",
+ value, ENUM_UNDERLYING_TYPE (enumtype));
+
+ /* Silently convert the value so that we can continue. */
+ value = perform_implicit_conversion (ENUM_UNDERLYING_TYPE (enumtype),
+ value, tf_none);
+ }
}
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
/* Build the actual enumeration constant. Note that the enumeration
- constants have the type of their initializers until the
- enumeration is complete:
-
- [ dcl.enum ]
-
- Following the closing brace of an enum-specifier, each enumer-
- ator has the type of its enumeration. Prior to the closing
- brace, the type of each enumerator is the type of its
- initializing value.
-
- In finish_enum we will reset the type. Of course, if we're
- processing a template, there may be no value. */
+ constants have the underlying type of the enum (if it is fixed)
+ or the type of their initializer (if the underlying type of the
+ enum is not fixed):
+
+ [ C++0x dcl.enum ]
+
+ If the underlying type is fixed, the type of each enumerator
+ prior to the closing brace is the underlying type; if the
+ initializing value of an enumerator cannot be represented by
+ the underlying type, the program is ill-formed. If the
+ underlying type is not fixed, the type of each enumerator is
+ the type of its initializing value.
+
+ If the underlying type is not fixed, it will be computed by
+ finish_enum and we will reset the type of this enumerator. Of
+ course, if we're processing a template, there may be no value. */
type = value ? TREE_TYPE (value) : NULL_TREE;
if (context && context == current_class_type)
else
/* It's a global enum, or it's local to a function. (Note local to
a function could mean local to a class method. */
- decl = build_decl (CONST_DECL, name, type);
+ decl = build_decl (input_location, CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
TREE_CONSTANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
- if (context && context == current_class_type)
+ if (context && context == current_class_type && !SCOPED_ENUM_P (enumtype))
/* In something like `struct S { enum E { i = 7 }; };' we put `i'
on the TYPE_FIELDS list for `S'. (That's so that you can say
things like `S::i' later.) */
TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype));
}
+/* Look for an enumerator with the given NAME within the enumeration
+ type ENUMTYPE. This routine is used primarily for qualified name
+ lookup into an enumerator in C++0x, e.g.,
+
+ enum class Color { Red, Green, Blue };
+
+ Color color = Color::Red;
+
+ Returns the value corresponding to the enumerator, or
+ NULL_TREE if no such enumerator was found. */
+tree
+lookup_enumerator (tree enumtype, tree name)
+{
+ tree e;
+ gcc_assert (enumtype && TREE_CODE (enumtype) == ENUMERAL_TYPE);
+
+ e = purpose_member (name, TYPE_VALUES (enumtype));
+ return e? TREE_VALUE (e) : NULL_TREE;
+}
+
\f
/* We're defining DECL. Make sure that it's type is OK. */
/* In a function definition, arg types must be complete. */
require_complete_types_for_parms (current_function_parms);
+ /* constexpr functions must have literal argument types and
+ literal return type. */
+ validate_constexpr_fundecl (decl);
+
if (dependent_type_p (return_type))
return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type)
{
tree resdecl;
- resdecl = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+ resdecl = build_decl (input_location, RESULT_DECL, 0, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
DECL_RESULT (decl1) = resdecl;
|| (DECL_CONSTRUCTOR_P (decl1)
&& targetm.cxx.cdtor_returns_this ()))
{
- cdtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ cdtor_label = build_decl (input_location,
+ LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (cdtor_label) = current_function_decl;
}
tree decl1;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+ if (decl1 == error_mark_node)
+ return 0;
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
- return 0;
+ {
+ error ("invalid function declaration");
+ return 0;
+ }
if (DECL_MAIN_P (decl1))
/* main must return int. grokfndecl should have corrected it
&& (! TYPE_FOR_JAVA (current_class_type)))
{
/* Any return from a constructor will end up here. */
- add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
+ add_stmt (build_stmt (input_location, LABEL_EXPR, cdtor_label));
val = DECL_ARGUMENTS (current_function_decl);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object. */
- exprstmt = build_stmt (RETURN_EXPR, val);
+ exprstmt = build_stmt (input_location, RETURN_EXPR, val);
add_stmt (exprstmt);
}
}
/* Any return from a destructor will end up here; that way all base
and member cleanups will be run when the function returns. */
- add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
+ add_stmt (build_stmt (input_location, LABEL_EXPR, cdtor_label));
/* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object. */
- exprstmt = build_stmt (RETURN_EXPR, val);
+ exprstmt = build_stmt (input_location, RETURN_EXPR, val);
add_stmt (exprstmt);
}
}
if (fndecl == NULL_TREE)
return error_mark_node;
+ gcc_assert (!defer_mark_used_calls);
+ defer_mark_used_calls = true;
+
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
&& DECL_VIRTUAL_P (fndecl)
&& !processing_template_decl)
if (!processing_template_decl)
{
struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
+ invoke_plugin_callbacks (PLUGIN_CXX_CP_PRE_GENERICIZE, fndecl);
cp_genericize (fndecl);
/* Clear out the bits we don't need. */
f->x_current_class_ptr = NULL;
f->x_return_value = NULL;
f->bindings = NULL;
f->extern_decl_map = NULL;
-
- /* Handle attribute((warn_unused_result)). Relies on gimple input. */
- c_warn_unused_result (gimple_body (fndecl));
}
/* Clear out the bits we don't need. */
local_names = NULL;
cxx_pop_function_context and then reset via pop_function_context. */
current_function_decl = NULL_TREE;
+ defer_mark_used_calls = false;
+ if (deferred_mark_used_calls)
+ {
+ unsigned int i;
+ tree decl;
+
+ for (i = 0; VEC_iterate (tree, deferred_mark_used_calls, i, decl); i++)
+ mark_used (decl);
+ VEC_free (tree, gc, deferred_mark_used_calls);
+ }
+
return fndecl;
}
\f
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (cp_decl_specifier_seq *declspecs,
- const cp_declarator *declarator, tree attrlist)
+grokmethod (cp_decl_specifier_seq *declspecs,
+ const cp_declarator *declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
&attrlist);
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DECL_NO_INLINE_WARNING_P (fndecl) = 1;
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
}
}
- finish_decl (fndecl, NULL_TREE, NULL_TREE);
-
- /* Make a place for the parms. */
- begin_scope (sk_function_parms, fndecl);
+ cp_finish_decl (fndecl, NULL_TREE, false, NULL_TREE, 0);
DECL_IN_AGGR_P (fndecl) = 1;
return fndecl;
}
-
-/* Go through the motions of finishing a function definition.
- We don't compile this method until after the whole class has
- been processed.
-
- FINISH_METHOD must return something that looks as though it
- came from GROKFIELD (since we are defining a method, after all).
-
- This is called after parsing the body of the function definition.
- STMTS is the chain of statements that makes up the function body.
-
- DECL is the ..._DECL that `start_method' provided. */
-
-tree
-finish_method (tree decl)
-{
- tree fndecl = decl;
- tree old_initial;
-
- tree link;
-
- if (decl == void_type_node)
- return decl;
-
- old_initial = DECL_INITIAL (fndecl);
-
- /* Undo the level for the parms (from start_method).
- This is like poplevel, but it causes nothing to be
- saved. Saving information here confuses symbol-table
- output routines. Besides, this information will
- be correctly output when this method is actually
- compiled. */
-
- /* Clear out the meanings of the local variables of this level;
- also record in each decl which block it belongs to. */
-
- for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
- {
- if (DECL_NAME (link) != NULL_TREE)
- pop_binding (DECL_NAME (link), link);
- gcc_assert (TREE_CODE (link) != FUNCTION_DECL);
- DECL_CONTEXT (link) = NULL_TREE;
- }
-
- poplevel (0, 0, 0);
-
- DECL_INITIAL (fndecl) = old_initial;
-
- /* We used to check if the context of FNDECL was different from
- current_class_type as another way to get inside here. This didn't work
- for String.cc in libg++. */
- if (DECL_FRIEND_P (fndecl))
- {
- VEC_safe_push (tree, gc, CLASSTYPE_INLINE_FRIENDS (current_class_type),
- fndecl);
- decl = void_type_node;
- }
-
- return decl;
-}
\f
/* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that
call = build_delete (TREE_TYPE (addr), addr,
sfk_complete_destructor, flags, 0);
if (cleanup)
- cleanup = build_compound_expr (cleanup, call);
+ cleanup = build_compound_expr (input_location, cleanup, call);
else
cleanup = call;
}
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
+ case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
default: return TS_CP_GENERIC;
}
}
/* Return the COMDAT group into which DECL should be placed. */
-const char *
+tree
cxx_comdat_group (tree decl)
{
tree name;
name = DECL_ASSEMBLER_NAME (decl);
}
- return IDENTIFIER_POINTER (name);
+ return name;
}
#include "gt-cp-decl.h"