/* 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, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
-#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
+#include "tree-iterator.h"
#include "tree-inline.h"
#include "decl.h"
+#include "intl.h"
#include "output.h"
-#include "except.h"
#include "toplev.h"
#include "hashtab.h"
#include "tm_p.h"
#include "target.h"
-#include "c-common.h"
-#include "c-pragma.h"
+#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
+#include "c-family/c-pragma.h"
#include "diagnostic.h"
#include "intl.h"
#include "debug.h"
#include "timevar.h"
-#include "tree-flow.h"
#include "pointer-set.h"
+#include "splay-tree.h"
#include "plugin.h"
+/* Possible cases of bad specifiers type used by bad_specifiers. */
+enum bad_spec_place {
+ BSP_VAR, /* variable */
+ BSP_PARM, /* parameter */
+ BSP_TYPE, /* type */
+ BSP_FIELD /* field */
+};
+
static tree grokparms (tree parmlist, tree *);
static const char *redeclaration_error_message (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 void bad_specifiers (tree, enum bad_spec_place, int, int, int, int,
int);
static void check_for_uninitialized_const_var (tree);
static hashval_t typename_hash (const void *);
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 void copy_type_enum (tree , tree);
static void check_function_type (tree, tree);
static void finish_constructor_body (void);
static void begin_destructor_body (void);
static void finish_destructor_body (void);
+static void record_key_method_defined (tree);
static tree create_array_type_for_decl (tree, tree, tree);
static tree get_atexit_node (void);
static tree get_dso_handle_node (void);
static tree start_cleanup_fn (void);
static void end_cleanup_fn (void);
-static tree cp_make_fname_decl (tree, int);
+static 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);
static void store_parm_decls (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
-static tree next_initializable_field (tree);
/* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
/* -- end of C++ */
-/* A node for the integer constants 2, and 3. */
+/* A node for the integer constant 2. */
-tree integer_two_node, integer_three_node;
+tree integer_two_node;
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
defined, or the inner scope popped. These are the decls that will
be skipped when jumping to the label. */
tree names_in_scope;
- /* A tree list of all decls from all binding levels that would be
+ /* A vector of all decls from all binding levels that would be
crossed by a backward branch to the label. */
- tree bad_decls;
+ VEC(tree,gc) *bad_decls;
/* A list of uses of the label, before the label is defined. */
struct named_label_use_entry *uses;
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
\f
-/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or
- UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
- time the VAR_DECL was declared, the type was incomplete. */
+/* A list of VAR_DECLs whose type was incomplete at the time the
+ variable was declared. */
+
+typedef struct GTY(()) incomplete_var_d {
+ tree decl;
+ tree incomplete_type;
+} incomplete_var;
+
+DEF_VEC_O(incomplete_var);
+DEF_VEC_ALLOC_O(incomplete_var,gc);
-static GTY(()) tree incomplete_vars;
+static GTY(()) VEC(incomplete_var,gc) *incomplete_vars;
\f
/* Returns the kind of template specialization we are currently
processing, given that it's declaration contained N_CLASS_SCOPES
/* Put the labels into the "variables" of the top-level block,
so debugger can see them. */
- TREE_CHAIN (ent->label_decl) = BLOCK_VARS (block);
+ DECL_CHAIN (ent->label_decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = ent->label_decl;
htab_clear_slot (named_labels, slot);
{
tree decl;
- for (decl = ent->names_in_scope; decl; decl = TREE_CHAIN (decl))
+ /* ENT->NAMES_IN_SCOPE may contain a mixture of DECLs and
+ TREE_LISTs representing OVERLOADs, so be careful. */
+ for (decl = ent->names_in_scope; decl; decl = (DECL_P (decl)
+ ? DECL_CHAIN (decl)
+ : TREE_CHAIN (decl)))
if (decl_jump_unsafe (decl))
- ent->bad_decls = tree_cons (NULL, decl, ent->bad_decls);
+ VEC_safe_push (tree, gc, ent->bad_decls, decl);
ent->binding_level = obl;
ent->names_in_scope = obl->names;
return 1;
}
+/* Saved errorcount to avoid -Wunused-but-set-{parameter,variable} warnings
+ when errors were reported, except for -Werror-unused-but-set-*. */
+static int unused_but_set_errorcount;
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
/* The chain of decls was accumulated in reverse order.
Put it into forward order, just for cleanliness. */
tree decls;
- int tmp = functionbody;
- int real_functionbody;
tree subblocks;
tree block;
tree decl;
int leaving_for_scope;
scope_kind kind;
+ unsigned ix;
+ cp_label_binding *label_bind;
timevar_push (TV_NAME_LOOKUP);
restart:
gcc_assert (current_binding_level->kind != sk_class);
- real_functionbody = (current_binding_level->kind == sk_cleanup
- ? ((functionbody = 0), tmp) : functionbody);
+ if (current_binding_level->kind == sk_cleanup)
+ functionbody = 0;
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
gcc_assert (!VEC_length(cp_class_binding,
= current_binding_level->kind == sk_for && flag_new_for_scope == 1;
/* Before we remove the declarations first check for unused variables. */
- if (warn_unused_variable
+ if ((warn_unused_variable || warn_unused_but_set_variable)
&& !processing_template_decl)
for (decl = getdecls (); decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == VAR_DECL
- && ! TREE_USED (decl)
+ && (! TREE_USED (decl) || !DECL_READ_P (decl))
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
- warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+ {
+ if (! TREE_USED (decl))
+ warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+ else if (DECL_CONTEXT (decl) == current_function_decl
+ && TREE_TYPE (decl) != error_mark_node
+ && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
+ && errorcount == unused_but_set_errorcount
+ && (!CLASS_TYPE_P (TREE_TYPE (decl))
+ || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ {
+ warning (OPT_Wunused_but_set_variable,
+ "variable %q+D set but not used", decl);
+ unused_but_set_errorcount = errorcount;
+ }
+ }
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
/* Add it to the list of dead variables in the next
outermost binding to that we can remove these when we
leave that binding. */
- current_binding_level->level_chain->dead_vars_from_for
- = tree_cons (NULL_TREE, link,
- current_binding_level->level_chain->
- dead_vars_from_for);
+ VEC_safe_push (tree, gc,
+ current_binding_level->level_chain->dead_vars_from_for,
+ link);
/* Although we don't pop the cxx_binding, we do clear
its SCOPE since the scope is going away now. */
/* Remove declarations for any `for' variables from inner scopes
that we kept around. */
- for (link = current_binding_level->dead_vars_from_for;
- link; link = TREE_CHAIN (link))
- pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
+ FOR_EACH_VEC_ELT_REVERSE (tree, current_binding_level->dead_vars_from_for,
+ ix, decl)
+ pop_binding (DECL_NAME (decl), decl);
/* Restore the IDENTIFIER_TYPE_VALUEs. */
for (link = current_binding_level->type_shadowed;
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
/* Restore the IDENTIFIER_LABEL_VALUEs for local labels. */
- for (link = current_binding_level->shadowed_labels;
- link;
- link = TREE_CHAIN (link))
- pop_local_label (TREE_VALUE (link), TREE_PURPOSE (link));
+ FOR_EACH_VEC_ELT_REVERSE (cp_label_binding,
+ current_binding_level->shadowed_labels,
+ ix, label_bind)
+ pop_local_label (label_bind->label, label_bind->prev_value);
/* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
list if a `using' declaration put them there. The debugging
if (TREE_CODE (*d) == TREE_LIST)
*d = TREE_CHAIN (*d);
else
- d = &TREE_CHAIN (*d);
+ d = &DECL_CHAIN (*d);
}
}
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);
}
result |= (*f) (name_space, data);
- for (; current; current = TREE_CHAIN (current))
+ for (; current; current = DECL_CHAIN (current))
result |= walk_namespaces_r (current, f, data);
return result;
{
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
amongst these. */
SET_DECL_IMPLICIT_TYPEDEF_P (decl);
TYPE_NAME (type) = decl;
+ TYPE_STUB_DECL (type) = decl;
return decl;
}
{
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_IS_BUILTIN (olddecl)
+ && DECL_EXTERN_C_P (olddecl) && !DECL_EXTERN_C_P (newdecl))
+ return 0;
+#endif
+
if (TREE_CODE (f1) != TREE_CODE (f2))
return 0;
void
warn_extern_redeclared_static (tree newdecl, tree olddecl)
{
- tree name;
-
if (TREE_CODE (newdecl) == TYPE_DECL
|| TREE_CODE (newdecl) == TEMPLATE_DECL
|| TREE_CODE (newdecl) == CONST_DECL
&& DECL_ARTIFICIAL (olddecl))
return;
- name = DECL_ASSEMBLER_NAME (newdecl);
permerror (input_location, "%qD was declared %<extern%> and later %<static%>", newdecl);
permerror (input_location, "previous declaration of %q+D", olddecl);
}
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
&& ! DECL_IS_BUILTIN (old_decl)
&& flag_exceptions
- && !comp_except_specs (new_exceptions, old_exceptions,
- /*exact=*/true))
+ && !comp_except_specs (new_exceptions, old_exceptions, ce_normal))
{
- error ("declaration of %qF throws different exceptions", new_decl);
+ error ("declaration of %qF has a different exception specifier",
+ new_decl);
error ("from previous declaration %q+F", old_decl);
}
}
+/* Return true if OLD_DECL and NEW_DECL agree on constexprness.
+ Otherwise issue diagnostics. */
+
+static bool
+validate_constexpr_redeclaration (tree old_decl, tree new_decl)
+{
+ old_decl = STRIP_TEMPLATE (old_decl);
+ new_decl = STRIP_TEMPLATE (new_decl);
+ if (!VAR_OR_FUNCTION_DECL_P (old_decl)
+ || !VAR_OR_FUNCTION_DECL_P (new_decl))
+ return true;
+ if (DECL_DECLARED_CONSTEXPR_P (old_decl)
+ == DECL_DECLARED_CONSTEXPR_P (new_decl))
+ return true;
+ if (TREE_CODE (old_decl) == FUNCTION_DECL && DECL_BUILT_IN (old_decl))
+ {
+ /* Hide a built-in declaration. */
+ DECL_DECLARED_CONSTEXPR_P (old_decl)
+ = DECL_DECLARED_CONSTEXPR_P (new_decl);
+ return true;
+ }
+ error ("redeclaration %qD differs in %<constexpr%>", new_decl);
+ error ("from previous declaration %q+D", old_decl);
+ return false;
+}
+
#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \
&& lookup_attribute ("gnu_inline", \
DECL_ATTRIBUTES (fn)))
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;
bad choice of name. */
if (! TREE_PUBLIC (newdecl))
{
- warning (OPT_Wshadow, "shadowing %s function %q#D",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ warning (OPT_Wshadow,
+ DECL_BUILT_IN (olddecl)
+ ? G_("shadowing built-in function %q#D")
+ : G_("shadowing library function %q#D"), olddecl);
/* Discard the old built-in function. */
return NULL_TREE;
}
olddecl);
}
else
- warning (OPT_Wshadow, "shadowing %s function %q#D",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ warning (OPT_Wshadow,
+ DECL_BUILT_IN (olddecl)
+ ? G_("shadowing built-in function %q#D")
+ : G_("shadowing library function %q#D"), olddecl);
}
else
/* Discard the old built-in function. */
/* Even if the types match, prefer the new declarations type for
built-ins which have not been explicitly declared, for
exception lists, etc... */
- else if (DECL_ANTICIPATED (olddecl))
+ else if (DECL_IS_BUILTIN (olddecl))
{
tree type = TREE_TYPE (newdecl);
tree attribs = (*targetm.merge_type_attributes)
&& 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)
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
+ if (!validate_constexpr_redeclaration (olddecl, newdecl))
+ return error_mark_node;
+
/* We have committed to returning 1 at this point. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_ARGUMENTS (old_result)
= DECL_ARGUMENTS (new_result);
for (parm = DECL_ARGUMENTS (old_result); parm;
- parm = TREE_CHAIN (parm))
+ parm = DECL_CHAIN (parm))
DECL_CONTEXT (parm) = old_result;
}
}
{
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 (DECL_VIRTUAL_P (newdecl))
DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
}
+ /* Only variables have this field. */
+ else if (TREE_CODE (newdecl) == VAR_DECL
+ && VAR_HAD_UNKNOWN_BOUND (olddecl))
+ SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
for (oldarg = DECL_ARGUMENTS(olddecl),
newarg = DECL_ARGUMENTS(newdecl);
oldarg && newarg;
- oldarg = TREE_CHAIN(oldarg), newarg = TREE_CHAIN(newarg)) {
+ oldarg = DECL_CHAIN(oldarg), newarg = DECL_CHAIN(newarg)) {
DECL_ATTRIBUTES (newarg)
= (*targetm.merge_decl_attributes) (oldarg, newarg);
DECL_ATTRIBUTES (oldarg) = DECL_ATTRIBUTES (newarg);
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
/* Update newdecl's parms to point at olddecl. */
for (parm = DECL_ARGUMENTS (newdecl); parm;
- parm = TREE_CHAIN (parm))
+ parm = DECL_CHAIN (parm))
DECL_CONTEXT (parm) = olddecl;
if (! types_match)
&& 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))
SET_DECL_INIT_PRIORITY (olddecl, DECL_INIT_PRIORITY (newdecl));
DECL_HAS_INIT_PRIORITY_P (olddecl) = 1;
}
+ /* Likewise for DECL_USER_ALIGN and DECL_PACKED. */
+ DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl);
+ if (TREE_CODE (newdecl) == FIELD_DECL)
+ DECL_PACKED (olddecl) = DECL_PACKED (newdecl);
/* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced
with that from NEWDECL below. */
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) == VAR_DECL)
+ {
+ if (DECL_READ_P (olddecl))
+ DECL_READ_P (newdecl) = 1;
+ else if (DECL_READ_P (newdecl))
+ DECL_READ_P (olddecl) = 1;
+ }
+ if (DECL_PRESERVE_P (olddecl))
+ DECL_PRESERVE_P (newdecl) = 1;
+ else if (DECL_PRESERVE_P (newdecl))
+ DECL_PRESERVE_P (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
if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return NULL;
else
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)
&& ! decls_match (olddecl, newdecl))
- return "%qD conflicts with used function";
+ return G_("%qD conflicts with used function");
/* We'll complain about linkage mismatches in
warn_extern_redeclared_static. */
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
- return "%q#D not declared in class";
+ return G_("%q#D not declared in class");
else if (!GNU_INLINE_P (olddecl)
|| GNU_INLINE_P (newdecl))
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
}
if (DECL_DECLARED_INLINE_P (olddecl) && DECL_DECLARED_INLINE_P (newdecl))
if (olda != newa)
{
if (newa)
- return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline with "
+ "%<gnu_inline%> attribute");
else
- return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline without "
+ "%<gnu_inline%> attribute");
}
}
{
if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
&& COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
return NULL;
}
ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
if (DECL_INITIAL (nt) && DECL_INITIAL (ot)
&& (!GNU_INLINE_P (ot) || GNU_INLINE_P (nt)))
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
if (DECL_DECLARED_INLINE_P (ot) && DECL_DECLARED_INLINE_P (nt))
{
if (olda != newa)
{
if (newa)
- return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline with "
+ "%<gnu_inline%> attribute");
else
- return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline without "
+ "%<gnu_inline%> attribute");
}
}
&& !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl),
/*is_primary=*/1, /*is_partial=*/0,
/*is_friend_decl=*/2))
- return "redeclaration of friend %q#D may not have default template arguments";
+ return G_("redeclaration of friend %q#D "
+ "may not have default template arguments");
return NULL;
}
/* Only variables can be thread-local, and all declarations must
agree on this property. */
if (DECL_THREAD_LOCAL_P (newdecl))
- return "thread-local declaration of %q#D follows "
- "non-thread-local declaration";
+ return G_("thread-local declaration of %q#D follows "
+ "non-thread-local declaration");
else
- return "non-thread-local declaration of %q#D follows "
- "thread-local declaration";
+ return G_("non-thread-local declaration of %q#D follows "
+ "thread-local declaration");
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
is invalid. */
if ((TREE_CODE (newdecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (newdecl))
|| (TREE_CODE (olddecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (olddecl)))
- return "redeclaration of %q#D";
+ return G_("redeclaration of %q#D");
/* If at least one declaration is a reference, there is no
conflict. For example:
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return NULL;
/* Reject two definitions. */
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
}
else
{
/* Reject two definitions, and reject a definition
together with an external reference. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
- return "redeclaration of %q#D";
+ return G_("redeclaration of %q#D");
return NULL;
}
}
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;
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
IDENTIFIER_LABEL_VALUE before the new label is declared. */
- ent = GGC_CNEW (struct named_label_entry);
+ ent = ggc_alloc_cleared_named_label_entry ();
ent->label_decl = decl;
slot = htab_find_slot (named_labels, ent, INSERT);
tree
declare_local_label (tree id)
{
- tree decl, shadow;
+ tree decl;
+ cp_label_binding *bind;
/* Add a new entry to the SHADOWED_LABELS list so that when we leave
this scope we can restore the old value of IDENTIFIER_TYPE_VALUE. */
- shadow = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
- current_binding_level->shadowed_labels);
- current_binding_level->shadowed_labels = shadow;
+ bind = VEC_safe_push (cp_label_binding, gc,
+ current_binding_level->shadowed_labels, NULL);
+ bind->prev_value = IDENTIFIER_LABEL_VALUE (id);
decl = make_label_decl (id, /*local_p=*/1);
- TREE_VALUE (shadow) = decl;
+ bind->label = decl;
return decl;
}
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
tree new_decls, old_decls = (b == level ? names : NULL_TREE);
for (new_decls = b->names; new_decls != old_decls;
- new_decls = TREE_CHAIN (new_decls))
+ new_decls = DECL_CHAIN (new_decls))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
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)
struct named_label_entry *ent, dummy;
bool saw_catch = false, identified = false;
tree bad;
+ unsigned ix;
/* We can't know where a computed goto is jumping.
So we assume that it's OK. */
&& ent->uses->names_in_scope == current_binding_level->names)
return;
- new_use = GGC_NEW (struct named_label_use_entry);
+ new_use = ggc_alloc_named_label_use_entry ();
new_use->binding_level = current_binding_level;
new_use->names_in_scope = current_binding_level->names;
new_use->o_goto_locus = input_location;
}
if (ent->in_try_scope || ent->in_catch_scope
- || ent->in_omp_scope || ent->bad_decls)
+ || ent->in_omp_scope || !VEC_empty (tree, ent->bad_decls))
{
permerror (input_location, "jump to label %q+D", decl);
permerror (input_location, " from here");
identified = true;
}
- for (bad = ent->bad_decls; bad; bad = TREE_CHAIN (bad))
+ FOR_EACH_VEC_ELT (tree, ent->bad_decls, ix, bad)
{
- tree b = TREE_VALUE (bad);
- int u = decl_jump_unsafe (b);
+ int u = decl_jump_unsafe (bad);
- if (u > 1 && DECL_ARTIFICIAL (b))
+ if (u > 1 && DECL_ARTIFICIAL (bad))
{
/* Can't skip init of __exception_info. */
- error ("%J enters catch block", b);
+ error_at (DECL_SOURCE_LOCATION (bad), " enters catch block");
saw_catch = true;
}
else if (u > 1)
- error (" skips initialization of %q+#D", b);
+ error (" skips initialization of %q+#D", bad);
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", bad);
}
if (ent->in_try_scope)
location_t switch_location;
/* Emit warnings as needed. */
- if (EXPR_HAS_LOCATION (cs->switch_stmt))
- switch_location = EXPR_LOCATION (cs->switch_stmt);
- else
- switch_location = input_location;
+ switch_location = EXPR_LOC_OR_HERE (cs->switch_stmt);
if (!processing_template_decl)
c_do_switch_warnings (cs->cases, switch_location,
SWITCH_STMT_TYPE (cs->switch_stmt),
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,
+ if (low_value)
+ low_value = cxx_constant_value (low_value);
+ if (high_value)
+ high_value = cxx_constant_value (high_value);
+
+ r = c_add_case_label (loc, switch_stack->cases, cond,
SWITCH_STMT_TYPE (switch_stack->switch_stmt),
low_value, high_value);
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);
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);
+ t = lookup_field (context, name, 2, /*want_type=*/true);
else
t = NULL_TREE;
- if (!t && dependent_type_p (context))
+ if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context))
return build_typename_type (context, name, fullname, tag_type);
want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
return error_mark_node;
}
+ /* Pull out the template from an injected-class-name (or multiple). */
+ if (want_template)
+ t = maybe_get_template_decl_from_type_decl (t);
+
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ if (complain & tf_error)
+ {
+ error ("lookup of %qT in %qT is ambiguous", name, context);
+ print_candidates (t);
+ }
+ return error_mark_node;
+ }
+
if (want_template && !DECL_CLASS_TEMPLATE_P (t))
{
if (complain & tf_error)
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t, t);
+ /* If we are currently parsing a template and if T is a typedef accessed
+ through CONTEXT then we need to remember and check access of T at
+ template instantiation time. */
+ add_typedef_to_current_template_for_access_check (t, context, input_location);
+
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context,
if (MAYBE_CLASS_TYPE_P (context))
tmpl = lookup_field (context, name, 0, false);
+ if (tmpl && TREE_CODE (tmpl) == TYPE_DECL)
+ tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
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);
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;
tree void_ftype;
tree void_ftype_ptr;
- build_common_tree_nodes (flag_signed_char, false);
+ build_common_tree_nodes (flag_signed_char);
/* Create all the identifiers we need. */
initialize_predefined_identifiers ();
gcc_assert (global_namespace == NULL_TREE);
global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
void_type_node);
+ DECL_CONTEXT (global_namespace) = build_translation_unit_decl (NULL_TREE);
TREE_PUBLIC (global_namespace) = 1;
begin_scope (sk_namespace, global_namespace);
java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
integer_two_node = build_int_cst (NULL_TREE, 2);
- integer_three_node = build_int_cst (NULL_TREE, 3);
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
truthvalue_type_node = boolean_type_node;
truthvalue_true_node = boolean_true_node;
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
+ noexcept_true_spec = build_tree_list (boolean_true_node, NULL_TREE);
+ noexcept_false_spec = build_tree_list (boolean_false_node, NULL_TREE);
#if 0
record_builtin_type (RID_MAX, NULL, string_type_node);
vtable_index_type = ptrdiff_type_node;
vtt_parm_type = build_pointer_type (const_ptr_type_node);
- void_ftype = build_function_type (void_type_node, void_list_node);
- void_ftype_ptr = build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node,
- void_list_node));
+ void_ftype = build_function_type_list (void_type_node, NULL_TREE);
+ void_ftype_ptr = build_function_type_list (void_type_node,
+ ptr_type_node, NULL_TREE);
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
/* C++ extensions */
- unknown_type_node = make_node (UNKNOWN_TYPE);
+ unknown_type_node = make_node (LANG_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 = make_node (LANG_TYPE);
record_unknown_type (init_list_type_node, "init list");
{
vtbl_type_node
= build_cplus_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
- vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
+ vtbl_type_node = cp_build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, NULL, vtbl_type_node);
vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
layout_type (vtbl_ptr_type_node);
current_lang_name = lang_name_cplusplus;
{
- tree bad_alloc_id;
- tree bad_alloc_type_node;
- tree bad_alloc_decl;
tree newtype, deltype;
tree ptr_ftype_sizetype;
-
- push_namespace (std_identifier);
- bad_alloc_id = get_identifier ("bad_alloc");
- bad_alloc_type_node = make_class_type (RECORD_TYPE);
- TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
- bad_alloc_decl
- = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
- DECL_CONTEXT (bad_alloc_decl) = current_namespace;
- TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl;
- pop_namespace ();
+ tree new_eh_spec;
ptr_ftype_sizetype
- = build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- size_type_node,
- void_list_node));
- newtype = build_exception_variant
- (ptr_ftype_sizetype, add_exception_specifier
- (NULL_TREE, bad_alloc_type_node, -1));
+ = build_function_type_list (ptr_type_node, size_type_node, NULL_TREE);
+ if (cxx_dialect == cxx98)
+ {
+ tree bad_alloc_id;
+ tree bad_alloc_type_node;
+ tree bad_alloc_decl;
+
+ push_namespace (std_identifier);
+ bad_alloc_id = get_identifier ("bad_alloc");
+ bad_alloc_type_node = make_class_type (RECORD_TYPE);
+ TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
+ bad_alloc_decl
+ = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
+ DECL_CONTEXT (bad_alloc_decl) = current_namespace;
+ pop_namespace ();
+
+ new_eh_spec
+ = add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1);
+ }
+ else
+ new_eh_spec = noexcept_false_spec;
+
+ newtype = build_exception_variant (ptr_ftype_sizetype, new_eh_spec);
deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
push_cp_library_fn (NEW_EXPR, newtype);
push_cp_library_fn (VEC_NEW_EXPR, newtype);
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
push_cp_library_fn (VEC_DELETE_EXPR, deltype);
+
+ nullptr_type_node = make_node (NULLPTR_TYPE);
+ TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
+ TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode));
+ TYPE_UNSIGNED (nullptr_type_node) = 1;
+ TYPE_PRECISION (nullptr_type_node) = GET_MODE_BITSIZE (ptr_mode);
+ SET_TYPE_MODE (nullptr_type_node, Pmode);
+ record_builtin_type (RID_MAX, "decltype(nullptr)", nullptr_type_node);
+ nullptr_node = build_int_cst (nullptr_type_node, 0);
}
abort_fndecl
/* Perform other language dependent initializations. */
init_class_processing ();
init_rtti_processing ();
+ init_template_processing ();
if (flag_exceptions)
init_exception_processing ();
init = build_string (length + 1, name);
}
- type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
+ type = cp_build_qualified_type (char_type_node, TYPE_QUAL_CONST);
type = build_cplus_array_type (type, domain);
*type_p = type;
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));
if (current_function_decl)
{
struct cp_binding_level *b = current_binding_level;
+ if (b->kind == sk_function_parms)
+ return error_mark_node;
while (b->level_chain->kind != sk_function_parms)
b = b->level_chain;
pushdecl_with_scope (decl, b, /*is_friend=*/false);
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);
/* Wipe out memory of synthesized methods. */
TYPE_HAS_USER_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
- TYPE_HAS_INIT_REF (t) = 0;
- TYPE_HAS_CONST_INIT_REF (t) = 0;
- TYPE_HAS_ASSIGN_REF (t) = 0;
- TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
+ TYPE_HAS_COPY_CTOR (t) = 0;
+ TYPE_HAS_CONST_COPY_CTOR (t) = 0;
+ TYPE_HAS_COPY_ASSIGN (t) = 0;
+ TYPE_HAS_CONST_COPY_ASSIGN (t) = 0;
/* Splice the implicitly generated functions out of the TYPE_METHODS
list. */
if (DECL_ARTIFICIAL (*q))
*q = TREE_CHAIN (*q);
else
- q = &TREE_CHAIN (*q);
+ q = &DECL_CHAIN (*q);
}
/* ISO C++ 9.5.3. Anonymous unions may not have function members. */
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
{
tree field, type;
- for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
type = TREE_TYPE (field);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
error ("member %q+#D with destructor not allowed "
"in anonymous aggregate", field);
- if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
+ if (TYPE_HAS_COMPLEX_COPY_ASSIGN (type))
error ("member %q+#D with copy assignment operator "
"not allowed in anonymous aggregate", field);
}
"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 *pushed_scope_p)
{
tree decl;
- tree type;
tree context;
bool was_public;
int flags;
+ bool alias;
*pushed_scope_p = NULL_TREE;
|| decl == error_mark_node)
return error_mark_node;
- type = TREE_TYPE (decl);
-
- context = DECL_CONTEXT (decl);
-
- if (context)
- {
- *pushed_scope_p = push_scope (context);
-
- /* We are only interested in class contexts, later. */
- if (TREE_CODE (context) == NAMESPACE_DECL)
- context = NULL_TREE;
- }
+ context = CP_DECL_CONTEXT (decl);
+ if (context != global_namespace)
+ *pushed_scope_p = push_scope (context);
if (initialized)
/* Is it valid for this decl to have an initializer at all?
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
}
+ alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)) != 0;
+
+ if (alias && TREE_CODE (decl) == FUNCTION_DECL)
+ record_key_method_defined (decl);
/* If this is a typedef that names the class for linkage purposes
(7.1.3p8), apply any attributes directly to the type. */
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning (0, "inline function %q+D given attribute noinline", decl);
- if (context && COMPLETE_TYPE_P (complete_type (context)))
+ if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
{
if (TREE_CODE (decl) == VAR_DECL)
{
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
DECL_EXTERNAL (decl) = 1;
}
- if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
+ if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)
+ /* Aliases are definitions. */
+ && !alias)
permerror (input_location, "declaration of %q#D outside of class is not definition",
decl);
}
/* This is a const variable with implicit 'static'. Set
DECL_THIS_STATIC so we can tell it from variables that are
!TREE_PUBLIC because of the anonymous namespace. */
- gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
+ gcc_assert (CP_TYPE_CONST_P (TREE_TYPE (decl)) || errorcount);
DECL_THIS_STATIC (decl) = 1;
}
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");
+ init = build_x_compound_expr_from_list (init, ELK_INIT,
+ tf_warning_or_error);
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
- tmp = initialize_reference (type, init, decl, cleanup);
+ tmp = initialize_reference (type, init, decl, cleanup, tf_warning_or_error);
if (tmp == error_mark_node)
return NULL_TREE;
grok_reference_init. */
static tree
-build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
+build_init_list_var_init (tree decl, tree type, tree init, tree *array_init,
+ tree *cleanup)
{
tree aggr_init, array, arrtype;
init = perform_implicit_conversion (type, init, tf_warning_or_error);
- aggr_init = TARGET_EXPR_INITIAL (init);
- init = build2 (INIT_EXPR, type, decl, init);
+ if (error_operand_p (init))
+ return error_mark_node;
+ aggr_init = TARGET_EXPR_INITIAL (init);
array = AGGR_INIT_EXPR_ARG (aggr_init, 1);
arrtype = TREE_TYPE (array);
STRIP_NOPS (array);
static variable and we don't need to do anything here. */
if (decl && TREE_CODE (array) == TARGET_EXPR)
{
- tree subinit;
- tree var = set_up_extended_ref_temp (decl, array, cleanup, &subinit);
+ tree var = set_up_extended_ref_temp (decl, array, cleanup, array_init);
var = build_address (var);
var = convert (arrtype, var);
AGGR_INIT_EXPR_ARG (aggr_init, 1) = var;
- init = build2 (COMPOUND_EXPR, TREE_TYPE (init), subinit, init);
}
return init;
}
VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initializer);
constructor_elt *ce;
HOST_WIDE_INT i;
- for (i = 0;
- VEC_iterate (constructor_elt, v, i, ce);
- ++i)
+ FOR_EACH_VEC_ELT (constructor_elt, v, i, ce)
if (!check_array_designated_initializer (ce))
failure = 1;
}
/* An automatic variable with an incomplete type: that is an error.
Don't talk about array types here, since we took care of that
message in grokdeclarator. */
- error ("storage size of %qD isn't known", decl);
+ error ("storage size of %qD isn%'t known", decl);
TREE_TYPE (decl) = error_mark_node;
}
#if 0
constant_expression_warning (DECL_SIZE (decl));
else
{
- error ("storage size of %qD isn't constant", decl);
+ error ("storage size of %qD isn%'t constant", decl);
TREE_TYPE (decl) = error_mark_node;
}
}
/* 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_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");
}
}
}
static void
check_for_uninitialized_const_var (tree decl)
{
- tree type = TREE_TYPE (decl);
+ tree type = strip_array_types (TREE_TYPE (decl));
/* ``Unless explicitly declared extern, a const object does not have
external linkage and must be initialized. ($8.4; $12.1)'' ARM
if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
- && !TYPE_NEEDS_CONSTRUCTING (type)
+ && (!TYPE_NEEDS_CONSTRUCTING (type)
+ || !type_has_user_provided_default_constructor (type))
&& !DECL_INITIAL (decl))
- error ("uninitialized const %qD", decl);
-}
+ {
+ permerror (DECL_SOURCE_LOCATION (decl),
+ "uninitialized const %qD", decl);
+ if (CLASS_TYPE_P (type)
+ && !type_has_user_provided_default_constructor (type))
+ {
+ tree defaulted_ctor;
+
+ inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+ "%q#T has no user-provided default constructor", type);
+ defaulted_ctor = in_class_defaulted_default_constructor (type);
+ if (defaulted_ctor)
+ inform (DECL_SOURCE_LOCATION (defaulted_ctor),
+ "constructor is not user-provided because it is "
+ "explicitly defaulted in the class body");
+ }
+ }
+}
\f
/* Structure holding the current initializer being processed by reshape_init.
CUR is a pointer to the current element being processed, END is a pointer
initialized. If there are no more such fields, the return value
will be NULL. */
-static tree
+tree
next_initializable_field (tree field)
{
while (field
&& (TREE_CODE (field) != FIELD_DECL
|| (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
|| DECL_ARTIFICIAL (field)))
- field = TREE_CHAIN (field);
+ field = DECL_CHAIN (field);
return field;
}
reshape_init_vector (tree type, reshape_iter *d)
{
tree max_index = NULL_TREE;
- tree rtype;
gcc_assert (TREE_CODE (type) == VECTOR_TYPE);
return value;
}
- /* For a vector, the representation type is a struct
- containing a single member which is an array of the
- appropriate size. */
- rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
- if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
- max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype)));
+ /* For a vector, we initialize it as an array of the appropriate size. */
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ max_index = size_int (TYPE_VECTOR_SUBPARTS (type) - 1);
return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
}
field_init = reshape_init_r (TREE_TYPE (field), d,
/*first_initializer_p=*/false);
+ if (field_init == error_mark_node)
+ return error_mark_node;
+
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, field_init);
/* [dcl.init.aggr]
if (TREE_CODE (type) == UNION_TYPE)
break;
- field = next_initializable_field (TREE_CHAIN (field));
+ field = next_initializable_field (DECL_CHAIN (field));
}
return new_init;
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)
init = error_mark_node;
}
else
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
}
d->cur++;
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;
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
+ tree extra_init = NULL_TREE;
+ tree core_type;
/* Things that are going to be initialized need to have complete
type. */
{
if (init_len == 0)
{
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
init = build_zero_init (type, NULL_TREE, false);
}
else if (init_len != 1)
gcc_assert (init != NULL_TREE);
init = NULL_TREE;
}
- else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
+ else if (!init && DECL_REALLY_EXTERN (decl))
+ ;
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
init = grok_reference_init (decl, type, init, cleanup);
- else if (init)
+ else if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
+ if (!init)
+ check_for_uninitialized_const_var (decl);
/* Do not reshape constructors of vectors (they don't need to be
reshaped. */
- if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ else if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (is_std_init_list (type))
- return build_init_list_var_init (decl, type, init, cleanup);
+ init = build_init_list_var_init (decl, type, init,
+ &extra_init, cleanup);
else if (TYPE_NON_AGGREGATE_CLASS (type))
{
/* Don't reshape if the class has constructors. */
error ("in C++98 %qD must be initialized by constructor, "
"not by %<{...}%>",
decl);
- init = build_tree_list (NULL_TREE, init);
}
else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_VECTOR_OPAQUE (type))
{
if (TYPE_NEEDS_CONSTRUCTING (type)
|| (CLASS_TYPE_P (type)
- && !BRACE_ENCLOSED_INITIALIZER_P (init)))
- return build_aggr_init_full_exprs (decl, init, flags);
- else if (TREE_CODE (init) != TREE_VEC)
+ && !(init && BRACE_ENCLOSED_INITIALIZER_P (init))))
+ {
+ init_code = build_aggr_init_full_exprs (decl, init, flags);
+
+ /* If this is a constexpr initializer, expand_default_init will
+ have returned an INIT_EXPR rather than a CALL_EXPR. In that
+ case, pull the initializer back out and pass it down into
+ store_init_value. */
+ while (TREE_CODE (init_code) == EXPR_STMT
+ || TREE_CODE (init_code) == CONVERT_EXPR)
+ init_code = TREE_OPERAND (init_code, 0);
+ if (TREE_CODE (init_code) == INIT_EXPR)
+ {
+ init = TREE_OPERAND (init_code, 1);
+ init_code = NULL_TREE;
+ /* Don't call digest_init; it's unnecessary and will complain
+ about aggregate initialization of non-aggregate classes. */
+ flags |= LOOKUP_ALREADY_DIGESTED;
+ }
+ else if (DECL_DECLARED_CONSTEXPR_P (decl))
+ {
+ /* Declared constexpr, but no suitable initializer; massage
+ init appropriately so we can pass it into store_init_value
+ for the error. */
+ if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
+ init = finish_compound_literal (type, init);
+ else if (CLASS_TYPE_P (type)
+ && (!init || TREE_CODE (init) == TREE_LIST))
+ {
+ init = build_functional_cast (type, init, tf_none);
+ if (init != error_mark_node)
+ TARGET_EXPR_DIRECT_INIT_P (init) = true;
+ }
+ init_code = NULL_TREE;
+ }
+ else
+ init = NULL_TREE;
+ }
+
+ if (init && TREE_CODE (init) != TREE_VEC)
{
init_code = store_init_value (decl, init, flags);
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
init = NULL;
}
}
- else if (DECL_EXTERNAL (decl))
- ;
- else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- return build_aggr_init_full_exprs (decl, init, flags);
- else if (MAYBE_CLASS_TYPE_P (type))
+ else
{
- tree core_type = strip_array_types (type);
-
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- error ("structure %qD with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- error ("structure %qD with uninitialized reference members", decl);
+ if (CLASS_TYPE_P (core_type = strip_array_types (type))
+ && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+ || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
+ diagnose_uninitialized_cst_or_ref_member (core_type, /*using_new=*/false,
+ /*complain=*/true);
check_for_uninitialized_const_var (decl);
}
- else
- check_for_uninitialized_const_var (decl);
if (init && init != error_mark_node)
init_code = build2 (INIT_EXPR, type, decl, init);
+ if (extra_init)
+ init_code = add_stmt_to_compound (extra_init, init_code);
+
+ if (init_code && DECL_IN_AGGR_P (decl))
+ {
+ static int explained = 0;
+
+ if (cxx_dialect < cxx0x)
+ error ("initializer invalid for static member with constructor");
+ else
+ error ("non-constant in-class initialization invalid for static "
+ "member %qD", decl);
+ if (!explained)
+ {
+ error ("(an out of class initialization is required)");
+ explained = 1;
+ }
+ }
+
return init_code;
}
/* Compute and store the initial value. */
already_used = TREE_USED (decl) || TREE_USED (type);
+ if (TREE_USED (type))
+ DECL_READ_P (decl) = 1;
/* Generate a cleanup, if necessary. */
cleanup = cxx_maybe_build_cleanup (decl);
/* DECL is a VAR_DECL for a compiler-generated variable with static
storage duration (like a virtual table) whose initializer is a
- compile-time constant. INIT must be either a TREE_LIST of values,
- or a CONSTRUCTOR. Initialize the variable and provide it to the
+ compile-time constant. Initialize the variable and provide it to the
back end. */
void
-initialize_artificial_var (tree decl, tree init)
+initialize_artificial_var (tree decl, VEC(constructor_elt,gc) *v)
{
+ tree init;
gcc_assert (DECL_ARTIFICIAL (decl));
- if (TREE_CODE (init) == TREE_LIST)
- init = build_constructor_from_list (TREE_TYPE (decl), init);
+ init = build_constructor (TREE_TYPE (decl), v);
gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
DECL_INITIAL (decl) = init;
DECL_INITIALIZED_P (decl) = 1;
auto_node = type_uses_auto (type);
if (auto_node)
{
+ tree d_init;
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))
+ d_init = init;
+ if (TREE_CODE (d_init) == TREE_LIST)
+ d_init = build_x_compound_expr_from_list (d_init, ELK_INIT,
+ tf_warning_or_error);
+ d_init = resolve_nondeduced_context (d_init);
+ if (describable_type (d_init))
{
- type = TREE_TYPE (decl) = do_auto_deduction (type, init, auto_node);
+ type = TREE_TYPE (decl) = do_auto_deduction (type, d_init,
+ auto_node);
if (type == error_mark_node)
return;
}
}
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ validate_constexpr_fundecl (decl);
+
+ else if (!ensure_literal_type_for_constexpr_object (decl))
+ DECL_DECLARED_CONSTEXPR_P (decl) = 0;
+
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
+ if (defaultable_fn_check (decl))
DECL_DEFAULTED_FN (decl) = 1;
+ else
+ DECL_INITIAL (decl) = NULL_TREE;
}
}
-
+
+ if (init && TREE_CODE (decl) == VAR_DECL)
+ {
+ DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
+ /* FIXME we rely on TREE_CONSTANT below; basing that on
+ init_const_expr_p is probably wrong for C++0x. */
+ if (init_const_expr_p)
+ {
+ /* Set these flags now for C++98 templates. We'll update the
+ flags in store_init_value for instantiations and C++0x. */
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+ if (decl_maybe_constant_var_p (decl))
+ TREE_CONSTANT (decl) = 1;
+ }
+ }
+
if (processing_template_decl)
{
bool type_dependent_p;
DECL_INITIAL (decl) = NULL_TREE;
}
- 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))
- TREE_CONSTANT (decl) = 1;
- }
-
/* Generally, initializers in templates are expanded when the
- template is instantiated. But, if DECL is an integral
- constant static data member, then it can be used in future
- integral constant expressions, and its value must be
- available. */
+ template is instantiated. But, if DECL is a variable constant
+ then it can be used in future constant expressions, so its value
+ must be available. */
if (!(init
&& DECL_CLASS_SCOPE_P (decl)
- && DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+ /* We just set TREE_CONSTANT appropriately; see above. */
+ && TREE_CONSTANT (decl)
&& !type_dependent_p
+ /* FIXME non-value-dependent constant expression */
&& !value_dependent_init_p (init)))
{
if (init)
&& !COMPLETE_TYPE_P (TREE_TYPE (decl)))
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
- rest_of_decl_compilation (decl, DECL_CONTEXT (decl) == NULL_TREE,
+ rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl),
at_eof);
goto finish_end;
}
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
if (DECL_FUNCTION_SCOPE_P (decl)
&& TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl))
- push_local_name (decl);
+ {
+ push_local_name (decl);
+ if (DECL_CONSTRUCTOR_P (current_function_decl)
+ || DECL_DESTRUCTOR_P (current_function_decl))
+ /* Normally local_decls is populated during GIMPLE lowering,
+ but [cd]tors are never actually compiled directly. We need
+ to put statics on the list so we can deal with the label
+ address extension. */
+ add_local_decl (cfun, decl);
+ }
+
/* Convert the initializer to the type of DECL, if we have not
already initialized DECL. */
if (!DECL_INITIALIZED_P (decl)
error ("Java object %qD not allocated with %<new%>", decl);
init = NULL_TREE;
}
- if (init)
- {
- DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
- if (init_const_expr_p)
- {
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
- if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
- TREE_CONSTANT (decl) = 1;
- }
- }
init = check_initializer (decl, init, flags, &cleanup);
/* Thread-local storage cannot be dynamically initialized. */
if (DECL_THREAD_LOCAL_P (decl) && init)
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 (was_readonly)
TREE_READONLY (decl) = 1;
-
- /* If this was marked 'used', be sure it will be output. */
- if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- mark_decl_referenced (decl);
-}
-
-/* This is here for a midend callback from c-common.c. */
-
-void
-finish_decl (tree decl, tree init, tree origtype ATTRIBUTE_UNUSED,
- 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:
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, NULL_TREE);
+ cp_finish_decl (decl, NULL_TREE, false, NULL_TREE, 0);
pop_from_top_level ();
return decl;
static tree
get_atexit_fn_ptr_type (void)
{
- tree arg_types;
tree fn_type;
if (!atexit_fn_ptr_type_node)
{
+ tree arg_type;
if (flag_use_cxa_atexit
&& !targetm.cxx.use_atexit_for_cxa_atexit ())
/* The parameter to "__cxa_atexit" is "void (*)(void *)". */
- arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ arg_type = ptr_type_node;
else
/* The parameter to "atexit" is "void (*)(void)". */
- arg_types = void_list_node;
+ arg_type = NULL_TREE;
- fn_type = build_function_type (void_type_node, arg_types);
+ fn_type = build_function_type_list (void_type_node,
+ arg_type, NULL_TREE);
atexit_fn_ptr_type_node = build_pointer_type (fn_type);
}
get_atexit_node (void)
{
tree atexit_fndecl;
- tree arg_types;
tree fn_type;
tree fn_ptr_type;
const char *name;
int __cxa_atexit (void (*)(void *), void *, void *)
- We build up the argument types and then then function type
+ We build up the argument types and then the function type
itself. */
+ tree argtype0, argtype1, argtype2;
use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
/* First, build the pointer-to-function type for the first
argument. */
fn_ptr_type = get_atexit_fn_ptr_type ();
/* Then, build the rest of the argument types. */
- arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ argtype2 = ptr_type_node;
if (use_aeabi_atexit)
{
- arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
- arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
+ argtype1 = fn_ptr_type;
+ argtype0 = ptr_type_node;
}
else
{
- arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
- arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+ argtype1 = ptr_type_node;
+ argtype0 = fn_ptr_type;
}
/* And the final __cxa_atexit type. */
- fn_type = build_function_type (integer_type_node, arg_types);
+ fn_type = build_function_type_list (integer_type_node,
+ argtype0, argtype1, argtype2,
+ NULL_TREE);
fn_ptr_type = build_pointer_type (fn_type);
if (use_aeabi_atexit)
name = "__aeabi_atexit";
int atexit (void (*)());
- We build up the argument types and then then function type
+ We build up the argument types and then the function type
itself. */
fn_ptr_type = get_atexit_fn_ptr_type ();
- arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node);
/* Build the final atexit type. */
- fn_type = build_function_type (integer_type_node, arg_types);
+ fn_type = build_function_type_list (integer_type_node,
+ fn_ptr_type, NULL_TREE);
name = "atexit";
}
parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl;
TREE_USED (parmdecl) = 1;
+ DECL_READ_P (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
{
tree cleanup;
tree compound_stmt;
- tree args;
tree fcall;
tree type;
bool use_dtor;
+ tree arg0, arg1 = NULL_TREE, arg2 = NULL_TREE;
type = TREE_TYPE (decl);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
in, and, in general, it's cheaper to pass NULL than any
other value. */
addr = null_pointer_node;
- args = tree_cons (NULL_TREE,
- cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
- tf_warning_or_error),
- NULL_TREE);
+ arg2 = cp_build_addr_expr (get_dso_handle_node (),
+ tf_warning_or_error);
if (targetm.cxx.use_aeabi_atexit ())
{
- args = tree_cons (NULL_TREE, cleanup, args);
- args = tree_cons (NULL_TREE, addr, args);
+ arg1 = cleanup;
+ arg0 = addr;
}
else
{
- args = tree_cons (NULL_TREE, addr, args);
- args = tree_cons (NULL_TREE, cleanup, args);
+ arg1 = addr;
+ arg0 = cleanup;
}
}
else
- args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- return cp_build_function_call (get_atexit_node (), args,
- tf_warning_or_error);
+ arg0 = cleanup;
+ return cp_build_function_call_nary (get_atexit_node (), tf_warning_or_error,
+ arg0, arg1, arg2, NULL_TREE);
}
/* DECL is a VAR_DECL with static storage duration. INIT, if present,
gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (TREE_STATIC (decl));
- /* Some variables require no initialization. */
+ /* Some variables require no dynamic initialization. */
if (!init
- && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
abort_fn = get_identifier ("__cxa_guard_abort");
if (!get_global_value_if_present (acquire_fn, &acquire_fn))
{
- tree argtypes = tree_cons (NULL_TREE, TREE_TYPE (guard_addr),
- void_list_node);
- tree vfntype = build_function_type (void_type_node, argtypes);
+ tree vfntype = build_function_type_list (void_type_node,
+ TREE_TYPE (guard_addr),
+ NULL_TREE);
acquire_fn = push_library_fn
- (acquire_fn, build_function_type (integer_type_node, argtypes),
+ (acquire_fn, build_function_type_list (integer_type_node,
+ TREE_TYPE (guard_addr),
+ NULL_TREE),
NULL_TREE);
release_fn = push_library_fn (release_fn, vfntype, NULL_TREE);
abort_fn = push_library_fn (abort_fn, vfntype, NULL_TREE);
static void
bad_specifiers (tree object,
- const char* type,
+ enum bad_spec_place type,
int virtualp,
int quals,
int inlinep,
int friendp,
int raises)
{
- if (virtualp)
- error ("%qD declared as a %<virtual%> %s", object, type);
- if (inlinep)
- error ("%qD declared as an %<inline%> %s", object, type);
- if (quals)
- error ("%<const%> and %<volatile%> function specifiers on "
- "%qD invalid in %s declaration",
- object, type);
+ switch (type)
+ {
+ case BSP_VAR:
+ if (virtualp)
+ error ("%qD declared as a %<virtual%> variable", object);
+ if (inlinep)
+ error ("%qD declared as an %<inline%> variable", object);
+ if (quals)
+ error ("%<const%> and %<volatile%> function specifiers on "
+ "%qD invalid in variable declaration", object);
+ break;
+ case BSP_PARM:
+ if (virtualp)
+ error ("%qD declared as a %<virtual%> parameter", object);
+ if (inlinep)
+ error ("%qD declared as an %<inline%> parameter", object);
+ if (quals)
+ error ("%<const%> and %<volatile%> function specifiers on "
+ "%qD invalid in parameter declaration", object);
+ break;
+ case BSP_TYPE:
+ if (virtualp)
+ error ("%qD declared as a %<virtual%> type", object);
+ if (inlinep)
+ error ("%qD declared as an %<inline%> type", object);
+ if (quals)
+ error ("%<const%> and %<volatile%> function specifiers on "
+ "%qD invalid in type declaration", object);
+ break;
+ case BSP_FIELD:
+ if (virtualp)
+ error ("%qD declared as a %<virtual%> field", object);
+ if (inlinep)
+ error ("%qD declared as an %<inline%> field", object);
+ if (quals)
+ error ("%<const%> and %<volatile%> function specifiers on "
+ "%qD invalid in field declaration", object);
+ break;
+ default:
+ gcc_unreachable();
+ }
if (friendp)
error ("%q+D declared as a friend", object);
if (raises
{
tree parm;
parm = build_this_parm (type, quals);
- TREE_CHAIN (parm) = parms;
+ DECL_CHAIN (parm) = parms;
parms = parm;
}
DECL_ARGUMENTS (decl) = parms;
- for (t = parms; t; t = TREE_CHAIN (t))
+ for (t = parms; t; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = decl;
/* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
{
case sfk_constructor:
case sfk_copy_constructor:
+ case sfk_move_constructor:
DECL_CONSTRUCTOR_P (decl) = 1;
break;
case sfk_destructor:
}
gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
|| TREE_CODE (fns) == OVERLOAD);
- DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
+ DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
if (in_namespace)
set_decl_namespace (decl, in_namespace, friendp);
else if (!ctype)
- DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_decl_namespace ());
/* `main' and builtins have implicit 'C' linkage. */
if ((MAIN_NAME_P (declarator)
&& strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
&& current_lang_name == lang_name_cplusplus
&& ctype == NULL_TREE
- /* NULL_TREE means global namespace. */
- && DECL_CONTEXT (decl) == NULL_TREE)
+ && DECL_FILE_SCOPE_P (decl))
SET_DECL_LANGUAGE (decl, lang_c);
/* Should probably propagate const out from type to decl I bet (mrs). */
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
- if (publicp)
+ if (publicp && cxx_dialect == cxx98)
{
/* [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. */
+ DR 757 relaxes this restriction for C++0x. */
t = no_linkage_check (TREE_TYPE (decl),
/*relaxed_p=*/false);
if (t)
/* Allow this; it's pretty common in C. */;
else
{
- permerror (input_location, "non-local function %q#D uses anonymous type",
- decl);
+ permerror (input_location, "anonymous type with no linkage "
+ "used to declare function %q#D with linkage",
+ 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",
}
}
else
- permerror (input_location, "non-local function %q#D uses local type %qT", decl, t);
+ permerror (input_location, "type %qT with no linkage used to "
+ "declare function %q#D with linkage", t, decl);
}
}
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
+ if (inlinep & 2)
+ DECL_DECLARED_CONSTEXPR_P (decl) = true;
DECL_EXTERNAL (decl) = 1;
if (quals && TREE_CODE (type) == FUNCTION_TYPE)
&& !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. */
/* An explicit "extern" specifier indicates a namespace-scope
variable. */
if (declspecs->storage_class == sc_extern)
- scope = current_namespace;
+ scope = current_decl_namespace ();
else if (!at_function_scope_p ())
scope = current_scope ();
}
|| 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 (declspecs->specs[(int)ds_thread])
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
+ /* If the type of the decl has no linkage, make sure that we'll
+ notice that in mark_used. */
+ if (cxx_dialect > cxx98
+ && decl_linkage (decl) != lk_none
+ && DECL_LANG_SPECIFIC (decl) == NULL
+ && !DECL_EXTERN_C_P (decl)
+ && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
+ retrofit_lang_decl (decl);
+
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);
+ DR 757 relaxes this restriction for C++0x. */
+ tree t = (cxx_dialect > cxx98 ? NULL_TREE
+ : 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);
+ warning (0, "anonymous type with no linkage used to declare "
+ "variable %q#D with linkage", 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",
}
}
else
- warning (0, "non-local variable %q#D uses local type %qT", decl, t);
+ warning (0, "type %qT with no linkage used to declare variable "
+ "%q#D with linkage", t, decl);
}
}
else
/* ... 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);
- TREE_CHAIN (field) = fields;
+ field = build_decl (input_location, FIELD_DECL, delta_identifier,
+ delta_type_node);
+ DECL_CHAIN (field) = fields;
fields = field;
finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
/* 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;
{
if (TREE_CODE (member_type) == METHOD_TYPE)
{
- tree arg_types;
-
- arg_types = TYPE_ARG_TYPES (member_type);
- class_type = (cp_build_qualified_type
- (class_type,
- cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)))));
- member_type
- = build_method_type_directly (class_type,
- TREE_TYPE (member_type),
- TREE_CHAIN (arg_types));
+ cp_cv_quals quals = type_memfn_quals (member_type);
+ member_type = build_memfn_type (member_type, class_type, quals);
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
else
int
check_static_variable_definition (tree decl, tree type)
{
+ /* If DECL is declared constexpr, we'll do the appropriate checks
+ in check_initializer. */
+ if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
+ return 0;
+ else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ {
+ if (literal_type_p (type))
+ error ("%<constexpr%> needed for in-class initialization of static "
+ "data member %q#D of non-integral type", decl);
+ else
+ error ("in-class initialization of static data member %q#D of "
+ "non-literal type", decl);
+ return 1;
+ }
+
/* Motion 10 at San Diego: If a static const integral data member is
initialized with an integral constant expression, the initializer
may appear either in the declaration (within the class), or in
error ("invalid in-class initialization of static data member "
"of non-integral type %qT",
type);
- /* If we just return the declaration, crashes will sometimes
- occur. We therefore return void_type_node, as if this were a
- friend declaration, to cause callers to completely ignore
- this declaration. */
return 1;
}
else if (!CP_TYPE_CONST_P (type))
name of the thing being declared. */
tree
-compute_array_index_type (tree name, tree size)
+compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
{
tree type;
tree itype;
+ tree osize = size;
tree abi_1_itype = NULL_TREE;
if (error_operand_p (size))
return error_mark_node;
type = TREE_TYPE (size);
- /* The array bound must be an integer type. */
- if (!dependent_type_p (type) && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+ /* type_dependent_expression_p? */
+ if (!dependent_type_p (type))
{
- if (name)
- error ("size of array %qD has non-integral type %qT", name, type);
+ mark_rvalue_use (size);
+
+ if (cxx_dialect < cxx0x && TREE_CODE (size) == NOP_EXPR
+ && TREE_SIDE_EFFECTS (size))
+ /* In C++98, we mark a non-constant array bound with a magic
+ NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */;
else
- error ("size of array has non-integral type %qT", type);
- size = integer_one_node;
- type = TREE_TYPE (size);
+ {
+ size = fold_non_dependent_expr (size);
+
+ if (CLASS_TYPE_P (type)
+ && CLASSTYPE_LITERAL_P (type))
+ {
+ size = build_expr_type_conversion (WANT_INT, size, true);
+ if (size == error_mark_node)
+ return error_mark_node;
+ type = TREE_TYPE (size);
+ }
+
+ size = maybe_constant_value (size);
+ }
+
+ if (error_operand_p (size))
+ return error_mark_node;
+
+ /* The array bound must be an integer type. */
+ if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+ {
+ if (!(complain & tf_error))
+ return error_mark_node;
+ if (name)
+ error ("size of array %qD has non-integral type %qT", name, type);
+ else
+ error ("size of array has non-integral type %qT", type);
+ size = integer_one_node;
+ type = TREE_TYPE (size);
+ }
}
+ /* A type is dependent if it is...an array type constructed from any
+ dependent type or whose size is specified by a constant expression
+ that is value-dependent. */
/* 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. */
+ expressions; treat non-constant expressions as dependent, too. */
if (processing_template_decl
- && (TREE_SIDE_EFFECTS (size) || value_dependent_expression_p (size)))
+ && (dependent_type_p (type)
+ || !TREE_CONSTANT (size) || value_dependent_expression_p (size)))
{
/* 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;
- }
+ TYPE_DEPENDENT_P (itype) = 1;
+ TYPE_DEPENDENT_P_VALID (itype) = 1;
SET_TYPE_STRUCTURAL_EQUALITY (itype);
return itype;
}
would have, but with TYPE_CANONICAL set to the "right"
value that the current ABI would provide. */
abi_1_itype = build_index_type (build_min (MINUS_EXPR, sizetype,
- size, integer_one_node));
-
- /* The size might be the result of a cast. */
- STRIP_TYPE_NOPS (size);
-
- /* It might be a const variable or enumeration constant. */
- size = integral_constant_value (size);
+ osize, integer_one_node));
/* Normally, the array-bound will be a constant. */
if (TREE_CODE (size) == INTEGER_CST)
/* An array must have a positive number of elements. */
if (INT_CST_LT (size, integer_zero_node))
{
+ if (!(complain & tf_error))
+ return error_mark_node;
if (name)
error ("size of array %qD is negative", name);
else
error ("size of array is negative");
size = integer_one_node;
}
- /* As an extension we allow zero-sized arrays. We always allow
- them in system headers because glibc uses them. */
- else if (integer_zerop (size) && !in_system_header)
+ /* As an extension we allow zero-sized arrays. */
+ else if (integer_zerop (size))
{
- if (name)
+ if (!(complain & tf_error))
+ /* We must fail if performing argument deduction (as
+ indicated by the state of complain), so that
+ another substitution can be found. */
+ return error_mark_node;
+ else if (in_system_header)
+ /* Allow them in system headers because glibc uses them. */;
+ else if (name)
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array %qD", name);
else
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array");
}
}
- else if (TREE_CONSTANT (size))
+ else if (TREE_CONSTANT (size)
+ /* We don't allow VLAs at non-function scopes, or during
+ tentative template substitution. */
+ || !at_function_scope_p () || !(complain & tf_error))
{
+ if (!(complain & tf_error))
+ return error_mark_node;
/* `(int) &fn' is not a valid array bound. */
if (name)
error ("size of array %qD is not an integral constant-expression",
else if (TREE_CODE (itype) == INTEGER_CST
&& TREE_OVERFLOW (itype))
{
+ if (!(complain & tf_error))
+ return error_mark_node;
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
}
{
tree t = build_index_type (itype);
TYPE_CANONICAL (abi_1_itype) = TYPE_CANONICAL (t);
- return abi_1_itype;
+ itype = abi_1_itype;
}
else
- return build_index_type (itype);
+ itype = build_index_type (itype);
+
+ /* If the index type were dependent, we would have returned early, so
+ remember that it isn't. */
+ TYPE_DEPENDENT_P (itype) = 0;
+ TYPE_DEPENDENT_P_VALID (itype) = 1;
+ return itype;
}
/* Returns the scope (if any) in which the entity declared by
create_array_type_for_decl (tree name, tree type, tree size)
{
tree itype = NULL_TREE;
- const char* error_msg;
/* If things have already gone awry, bail now. */
if (type == error_mark_node || size == error_mark_node)
return error_mark_node;
- /* Assume that everything will go OK. */
- error_msg = NULL;
-
- /* There are some types which cannot be array elements. */
+ /* If there are some types which cannot be array elements,
+ issue an error-message and return. */
switch (TREE_CODE (type))
{
case VOID_TYPE:
- error_msg = "array of void";
- break;
+ if (name)
+ error ("declaration of %qD as array of void", name);
+ else
+ error ("creating array of void");
+ return error_mark_node;
case FUNCTION_TYPE:
- error_msg = "array of functions";
- break;
+ if (name)
+ error ("declaration of %qD as array of functions", name);
+ else
+ error ("creating array of functions");
+ return error_mark_node;
case REFERENCE_TYPE:
- error_msg = "array of references";
- break;
+ if (name)
+ error ("declaration of %qD as array of references", name);
+ else
+ error ("creating array of references");
+ return error_mark_node;
case METHOD_TYPE:
- error_msg = "array of function members";
- break;
-
- default:
- break;
- }
-
- /* If something went wrong, issue an error-message and return. */
- if (error_msg)
- {
if (name)
- error ("declaration of %qD as %s", name, error_msg);
+ error ("declaration of %qD as array of function members", name);
else
- error ("creating %s", error_msg);
-
+ error ("creating array of function members");
return error_mark_node;
+
+ default:
+ break;
}
/* [dcl.array]
/* Figure out the index type for the array. */
if (size)
- itype = compute_array_index_type (name, size);
+ itype = compute_array_index_type (name, size, tf_warning_or_error);
/* [dcl.array]
T is called the array element type; this type shall not be [...] an
try to parse.
PARM for a parameter declaration (either within a function prototype
or before a function body). Make a PARM_DECL, or return void_type_node.
+ TPARM for a template parameter declaration.
CATCHPARM for a parameter declaration before a catch clause.
TYPENAME if for a typename (in a cast or sizeof).
Don't make a DECL node; just return the ..._TYPE node.
FIELD for a struct or union field; make a FIELD_DECL.
BITFIELD for a field with specified width.
+
INITIALIZED is as for start_decl.
ATTRLIST is a pointer to the list of attributes, which may be NULL
{
tree type = NULL_TREE;
int longlong = 0;
+ int explicit_int128 = 0;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
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 template_parm_flag = false;
+ bool constexpr_p = declspecs->specs[(int) ds_constexpr];
const char *errmsg;
signed_p = declspecs->specs[(int)ds_signed];
short_p = declspecs->specs[(int)ds_short];
long_p = declspecs->specs[(int)ds_long];
longlong = declspecs->specs[(int)ds_long] >= 2;
+ explicit_int128 = declspecs->explicit_int128_p;
thread_p = declspecs->specs[(int)ds_thread];
if (decl_context == FUNCDEF)
bitfield = 1, decl_context = FIELD;
else if (decl_context == TEMPLATE_TYPE_ARG)
template_type_arg = true, decl_context = TYPENAME;
+ else if (decl_context == TPARM)
+ template_parm_flag = true, decl_context = PARM;
if (initialized > 1)
funcdef_flag = true;
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
+ if (constexpr_p && declspecs->specs[(int)ds_typedef])
+ {
+ error ("%<constexpr%> cannot appear in a typedef declaration");
+ return error_mark_node;
+ }
+
/* If there were multiple types specified in the decl-specifier-seq,
issue an error message. */
if (declspecs->multiple_types_p)
common. With no options, it is allowed. With -Wreturn-type,
it is a warning. It is only an error with -pedantic-errors. */
is_main = (funcdef_flag
- && dname && MAIN_NAME_P (dname)
+ && dname && TREE_CODE (dname) == IDENTIFIER_NODE
+ && MAIN_NAME_P (dname)
&& ctype == NULL_TREE
&& in_namespace == NULL_TREE
&& current_namespace == global_namespace);
if (long_p && !longlong && TYPE_MAIN_VARIANT (type) == double_type_node)
{
long_p = false;
- type = build_qualified_type (long_double_type_node,
- cp_type_quals (type));
+ type = cp_build_qualified_type (long_double_type_node,
+ cp_type_quals (type));
}
/* Check all other uses of type modifiers. */
error ("%<signed%> and %<unsigned%> specified together for %qs", name);
else if (longlong && TREE_CODE (type) != INTEGER_TYPE)
error ("%<long long%> invalid for %qs", name);
+ else if (explicit_int128 && TREE_CODE (type) != INTEGER_TYPE)
+ error ("%<__int128%> invalid for %qs", name);
else if (long_p && TREE_CODE (type) == REAL_TYPE)
error ("%<long%> invalid for %qs", name);
else if (short_p && TREE_CODE (type) == REAL_TYPE)
error ("%<short%> invalid for %qs", name);
else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
error ("%<long%> or %<short%> invalid for %qs", name);
+ else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
+ error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
else if ((long_p || short_p) && explicit_char)
error ("%<long%> or %<short%> specified with char for %qs", name);
else if (long_p && short_p)
else
{
ok = 1;
- if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
+ if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
{
pedwarn (input_location, OPT_pedantic,
"long, short, signed or unsigned used invalidly for %qs",
if (flag_pedantic_errors)
ok = 0;
}
+ if (explicit_int128)
+ {
+ if (int128_integer_type_node == NULL_TREE)
+ {
+ error ("%<__int128%> is not supported by this target");
+ ok = 0;
+ }
+ else if (pedantic)
+ {
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ does not support %<__int128%> for %qs",
+ name);
+ if (flag_pedantic_errors)
+ ok = 0;
+ }
+ }
}
/* Discard the type modifiers if they are invalid. */
long_p = false;
short_p = false;
longlong = 0;
+ explicit_int128 = false;
}
}
&& TREE_CODE (type) == INTEGER_TYPE
&& !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
- if (longlong)
+ if (explicit_int128)
+ type = int128_unsigned_type_node;
+ else if (longlong)
type = long_long_unsigned_type_node;
else if (long_p)
type = long_unsigned_type_node;
}
else if (signed_p && type == char_type_node)
type = signed_char_type_node;
+ else if (explicit_int128)
+ type = int128_integer_type_node;
else if (longlong)
type = long_long_integer_type_node;
else if (long_p)
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
"complex short int". */
-
- else if (defaulted_int && ! longlong
+ else if (defaulted_int && ! longlong && ! explicit_int128
&& ! (long_p || short_p || signed_p || unsigned_p))
type = complex_double_type_node;
else if (type == integer_type_node)
error ("qualifiers are not allowed on declaration of %<operator %T%>",
ctor_return_type);
- if (TREE_CODE (type) == FUNCTION_TYPE
- && type_quals != TYPE_UNQUALIFIED)
- {
- /* This was an error in C++98 (cv-qualifiers cannot be added to
- a function type), but DR 295 makes the code well-formed by
- dropping the extra qualifiers. */
- if (pedantic)
- {
- tree bad_type = build_qualified_type (type, type_quals);
- pedwarn (input_location, OPT_pedantic,
- "ignoring %qV qualifiers added to function type %qT",
- bad_type, type);
- }
- type_quals = TYPE_UNQUALIFIED;
- }
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
error ("typedef declaration invalid in parameter declaration");
return error_mark_node;
}
+ else if (template_parm_flag && storage_class != sc_none)
+ {
+ error ("storage class specified for template parameter %qs", name);
+ return error_mark_node;
+ }
else if (storage_class == sc_static
|| storage_class == sc_extern
|| thread_p)
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. */
/* 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)
else if (friendp)
{
if (initialized)
- error ("can't initialize friend function %qs", name);
+ error ("can%'t initialize friend function %qs", name);
if (virtualp)
{
/* Cannot be both friend and virtual. */
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
- error ("can't define friend function %qs in a local "
+ error ("can%'t define friend function %qs in a local "
"class definition",
name);
}
{
if (explicitp == 1)
{
- maybe_warn_cpp0x ("explicit conversion operators");
+ maybe_warn_cpp0x (CPP0X_EXPLICIT_CONVERSION);
explicitp = 2;
}
}
&& (TREE_CODE (type) == FUNCTION_TYPE
|| (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
{
- memfn_quals |= cp_type_quals (type);
+ memfn_quals |= type_memfn_quals (type);
type = build_memfn_type (type,
declarator->u.pointer.class_type,
memfn_quals);
+ if (type == error_mark_node)
+ return error_mark_node;
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_memfn_quals (type) != TYPE_UNQUALIFIED)
+ error (declarator->kind == cdk_reference
+ ? G_("cannot declare reference to qualified function type %qT")
+ : G_("cannot declare pointer to qualified function type %qT"),
type);
+ /* When the pointed-to type involves components of variable size,
+ care must be taken to ensure that the size evaluation code is
+ emitted early enough to dominate all the possible later uses
+ and late enough for the variables on which it depends to have
+ been assigned.
+
+ This is expected to happen automatically when the pointed-to
+ type has a name/declaration of it's own, but special attention
+ is required if the type is anonymous.
+
+ We handle the NORMAL and FIELD contexts here by inserting a
+ dummy statement that just evaluates the size at a safe point
+ and ensures it is not deferred until e.g. within a deeper
+ conditional context (c++/43555).
+
+ We expect nothing to be needed here for PARM or TYPENAME.
+ Evaluating the size at this point for TYPENAME would
+ actually be incorrect, as we might be in the middle of an
+ expression with side effects on the pointed-to type size
+ "arguments" prior to the pointer declaration point and the
+ size evaluation could end up prior to the side effects. */
+
+ if (!TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && at_function_scope_p ()
+ && variably_modified_type_p (type, NULL_TREE))
+ finish_expr_stmt (TYPE_SIZE (type));
+
if (declarator->kind == cdk_reference)
{
/* In C++0x, the type we are creating a reference to might be
}
}
+ /* A `constexpr' specifier used in an object declaration declares
+ the object as `const'. */
+ if (constexpr_p && innermost_code != cdk_function)
+ {
+ if (type_quals & TYPE_QUAL_CONST)
+ error ("both %<const%> and %<constexpr%> cannot be used here");
+ if (type_quals & TYPE_QUAL_VOLATILE)
+ error ("both %<volatile%> and %<constexpr%> cannot be used here");
+ type_quals |= TYPE_QUAL_CONST;
+ type = cp_build_qualified_type (type, type_quals);
+ }
+
if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
&& TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE)
return error_mark_node;
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- tree sname = declarator->u.id.unqualified_name;
-
if (current_class_type
&& (!friendp || funcdef_flag))
{
ctype, name, current_class_type);
return error_mark_node;
}
-
- if (TREE_CODE (sname) == IDENTIFIER_NODE
- && NEW_DELETE_OPNAME_P (sname))
- /* Overloaded operator new and operator delete
- are always static functions. */
- ;
- else
- type = build_memfn_type (type, ctype, memfn_quals);
}
else if (declspecs->specs[(int)ds_typedef]
&& current_class_type)
}
}
+ if (ctype == NULL_TREE && decl_context == FIELD && friendp == 0)
+ ctype = current_class_type;
+
+ /* A constexpr non-static member function is implicitly const. */
+ if (constexpr_p && ctype && staticp == 0
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && sfk != sfk_constructor && sfk != sfk_destructor)
+ memfn_quals |= TYPE_QUAL_CONST;
+
/* Now TYPE has the actual type. */
if (returned_attrs)
function type. */
if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
{
- type = cp_build_qualified_type (type, memfn_quals);
+ type = apply_memfn_quals (type, memfn_quals);
/* We have now dealt with these qualifiers. */
memfn_quals = TYPE_UNQUALIFIED;
if (decl_context == FIELD)
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
- decl = build_decl (TYPE_DECL, unqualified_id, type);
+ decl = build_decl (input_location, TYPE_DECL, unqualified_id, type);
if (id_declarator && declarator->u.id.qualifying_scope) {
- error ("%Jtypedef name may not be a nested-name-specifier", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "typedef name may not be a nested-name-specifier");
TREE_TYPE (decl) = error_mark_node;
}
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
- {
- debug_hooks->set_name (t, decl);
- TYPE_NAME (t) = decl;
- }
+ /* We do not rename the debug info representing the
+ anonymous tagged type because the standard says in
+ [dcl.typedef] that the naming applies only for
+ linkage purposes. */
+ /*debug_hooks->set_name (t, decl);*/
+ TYPE_NAME (t) = decl;
}
if (TYPE_LANG_SPECIFIC (type))
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. */
}
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- bad_specifiers (decl, "type", virtualp,
+ bad_specifiers (decl, BSP_TYPE, virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
tree decls = NULL_TREE;
tree args;
- for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args))
+ for (args = TYPE_ARG_TYPES (type);
+ args && args != void_list_node;
+ args = TREE_CHAIN (args))
{
tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args));
- TREE_CHAIN (decl) = decls;
+ DECL_CHAIN (decl) = decls;
decls = decl;
}
{
/* A cv-qualifier-seq shall only be part of the function type
for a non-static member function. [8.3.5/4 dcl.fct] */
- if (cp_type_quals (type) != TYPE_UNQUALIFIED
+ if (type_memfn_quals (type) != TYPE_UNQUALIFIED
&& (current_class_type == NULL_TREE || staticp) )
{
error (staticp
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
- memfn_quals |= cp_type_quals (type);
+ memfn_quals |= type_memfn_quals (type);
+ type_quals = TYPE_UNQUALIFIED;
}
}
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);
+ type = apply_memfn_quals (type, memfn_quals);
else
error ("invalid qualifiers on non-member function type");
}
type = build_pointer_type (type);
}
+ if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
+ && !NEW_DELETE_OPNAME_P (unqualified_id))
+ type = build_memfn_type (type, ctype, memfn_quals);
+
{
tree decl;
{
decl = cp_build_parm_decl (unqualified_id, type);
- bad_specifiers (decl, "parameter", virtualp,
+ bad_specifiers (decl, BSP_PARM, virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
if (!staticp && TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
- tree itype = compute_array_index_type (dname, integer_zero_node);
+ tree itype = compute_array_index_type (dname, integer_zero_node,
+ tf_warning_or_error);
type = build_cplus_array_type (TREE_TYPE (type), itype);
}
error ("invalid use of %<::%>");
return error_mark_node;
}
- else if (TREE_CODE (type) == FUNCTION_TYPE)
+ else if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
{
int publicp = 0;
tree function_context;
if (friendp == 0)
{
- if (ctype == NULL_TREE)
- ctype = current_class_type;
-
- if (ctype == NULL_TREE)
+ /* This should never happen in pure C++ (the check
+ could be an assert). It could happen in
+ Objective-C++ if someone writes invalid code that
+ uses a function declaration for an instance
+ variable or property (instance variables and
+ properties are parsed as FIELD_DECLs, but they are
+ part of an Objective-C class, not a C++ class).
+ That code is invalid and is caught by this
+ check. */
+ if (!ctype)
{
- error ("can't make %qD into a method -- not in a class",
+ error ("declaration of function %qD in invalid context",
unqualified_id);
return error_mark_node;
}
virtualp = 0;
}
}
- else if (staticp < 2)
- type = build_memfn_type (type, ctype, memfn_quals);
}
/* Check that the name used for a destructor makes sense. */
uqname, ctype);
return error_mark_node;
}
+ if (constexpr_p)
+ {
+ error ("a destructor cannot be %<constexpr%>");
+ return error_mark_node;
+ }
}
- else if (sfk == sfk_constructor && friendp)
+ else if (sfk == sfk_constructor && friendp && !ctype)
{
error ("expected qualified name in friend declaration "
"for constructor %qD",
parms,
unqualified_id,
virtualp, flags, memfn_quals, raises,
- friendp ? -1 : 0, friendp, publicp, inlinep,
+ friendp ? -1 : 0, friendp, publicp,
+ inlinep | (2 * constexpr_p),
sfk,
funcdef_flag, template_count, in_namespace,
attrlist, declarator->id_loc);
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
}
- else if (TREE_CODE (type) == METHOD_TYPE)
- {
- /* We only get here for friend declarations of
- members of other classes. */
- /* All method decls are public, so tell grokfndecl to set
- TREE_PUBLIC, also. */
- decl = grokfndecl (ctype, type,
- TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
- ? unqualified_id : dname,
- parms,
- unqualified_id,
- virtualp, flags, memfn_quals, raises,
- friendp ? -1 : 0, friendp, 1, 0, sfk,
- funcdef_flag, template_count, in_namespace,
- attrlist,
- declarator->id_loc);
- if (decl == NULL_TREE)
- return error_mark_node;
- }
else if (!staticp && !dependent_type_p (type)
&& !COMPLETE_TYPE_P (complete_type (type))
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
return error_mark_node;
}
+ DECL_DECLARED_CONSTEXPR_P (decl) = constexpr_p;
decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags,
funcdef_flag);
the rest of the compiler does not correctly
handle the initialization unless the member is
static so we make it static below. */
- permerror (input_location, "ISO C++ forbids initialization of member %qD",
- unqualified_id);
- permerror (input_location, "making %qD static", unqualified_id);
- staticp = 1;
+ if (cxx_dialect >= cxx0x)
+ {
+ sorry ("non-static data member initializers");
+ }
+ else
+ {
+ permerror (input_location, "ISO C++ forbids initialization of member %qD",
+ unqualified_id);
+ permerror (input_location, "making %qD static", unqualified_id);
+ staticp = 1;
+ }
}
if (uses_template_parms (type))
/* We'll check at instantiation time. */
;
+ else if (constexpr_p)
+ /* constexpr has the same requirements. */
+ ;
else if (check_static_variable_definition (unqualified_id,
type))
/* If we just return the declaration, crashes
}
else
{
- decl = build_decl (FIELD_DECL, unqualified_id, type);
+ if (constexpr_p)
+ {
+ error ("non-static data member %qE declared %<constexpr%>",
+ unqualified_id);
+ constexpr_p = false;
+ }
+ decl = build_decl (input_location,
+ FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !unqualified_id)
TREE_NO_WARNING (decl) = 1;
}
}
- bad_specifiers (decl, "field", virtualp,
+ bad_specifiers (decl, BSP_FIELD, virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
sfk = sfk_none;
}
}
- else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
- && !NEW_DELETE_OPNAME_P (original_name))
- type = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, memfn_quals, raises,
1, friendp,
- publicp, inlinep, sfk, funcdef_flag,
+ publicp, inlinep | (2 * constexpr_p), sfk,
+ funcdef_flag,
template_count, in_namespace, attrlist,
declarator->id_loc);
if (decl == NULL_TREE)
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
- bad_specifiers (decl, "variable", virtualp,
+ bad_specifiers (decl, BSP_VAR, virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
storage_class = sc_none;
}
}
+ else if (constexpr_p && DECL_EXTERNAL (decl))
+ error ("declaration of constexpr variable %qD is not a definition",
+ decl);
}
if (storage_class == sc_extern && initialized && !funcdef_flag)
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
+ /* Don't forget constexprness. */
+ if (constexpr_p)
+ DECL_DECLARED_CONSTEXPR_P (decl) = true;
+
/* 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;
}
}
static void
require_complete_types_for_parms (tree parms)
{
- for (; parms; parms = TREE_CHAIN (parms))
+ for (; parms; parms = DECL_CHAIN (parms))
{
if (dependent_type_p (TREE_TYPE (parms)))
continue;
&& TREE_DEPRECATED (TYPE_NAME (type)))
return type;
+ /* Do warn about using typedefs to a deprecated class. */
+ if (TAGGED_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type))
+ return type_is_deprecated (TYPE_MAIN_VARIANT (type));
+
code = TREE_CODE (type);
if (code == POINTER_TYPE || code == REFERENCE_TYPE
t = TREE_TYPE (t);
}
if (TREE_CODE (t) == ARRAY_TYPE)
- error ("parameter %qD includes %s to array of unknown "
- "bound %qT",
- decl, ptr ? "pointer" : "reference", t);
+ error (ptr
+ ? G_("parameter %qD includes pointer to array of "
+ "unknown bound %qT")
+ : G_("parameter %qD includes reference to array of "
+ "unknown bound %qT"),
+ decl, t);
}
if (any_error)
&& TREE_CHAIN (parm) != void_list_node)
error ("parameter packs must be at the end of the parameter list");
- TREE_CHAIN (decl) = decls;
+ DECL_CHAIN (decl) = decls;
decls = decl;
result = tree_cons (init, type, result);
}
0 if D is not a copy constructor or copy assignment
operator.
1 if D is a copy constructor or copy assignment operator whose
- first parameter is a reference to const qualified T.
- 2 if D is a copy constructor or copy assignment operator whose
first parameter is a reference to non-const qualified T.
+ 2 if D is a copy constructor or copy assignment operator whose
+ first parameter is a reference to const qualified T.
This function can be used as a predicate. Positive values indicate
a copy constructor and nonzero values indicate a copy assignment
X&, volatile X& or const volatile X&, and either there
are no other parameters or else all other parameters have
default arguments. */
- TYPE_HAS_INIT_REF (class_type) = 1;
- if (!DECL_DEFAULTED_FN (decl))
- TYPE_HAS_COMPLEX_INIT_REF (class_type) = 1;
+ TYPE_HAS_COPY_CTOR (class_type) = 1;
+ if (user_provided_p (decl))
+ TYPE_HAS_COMPLEX_COPY_CTOR (class_type) = 1;
if (ctor > 1)
- TYPE_HAS_CONST_INIT_REF (class_type) = 1;
+ TYPE_HAS_CONST_COPY_CTOR (class_type) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
{
TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
- if (TREE_CODE (decl) == TEMPLATE_DECL || !DECL_DEFAULTED_FN (decl))
+ if (user_provided_p (decl))
TYPE_HAS_COMPLEX_DFLT (class_type) = 1;
}
+ else if (move_fn_p (decl) && user_provided_p (decl))
+ TYPE_HAS_COMPLEX_MOVE_CTOR (class_type) = 1;
else if (is_list_ctor (decl))
TYPE_HAS_LIST_CTOR (class_type) = 1;
+
+ if (DECL_DECLARED_CONSTEXPR_P (decl)
+ && !copy_fn_p (decl) && !move_fn_p (decl))
+ TYPE_HAS_CONSTEXPR_CTOR (class_type) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
if (assop)
{
- TYPE_HAS_ASSIGN_REF (class_type) = 1;
- if (!DECL_DEFAULTED_FN (decl))
- TYPE_HAS_COMPLEX_ASSIGN_REF (class_type) = 1;
+ TYPE_HAS_COPY_ASSIGN (class_type) = 1;
+ if (user_provided_p (decl))
+ TYPE_HAS_COMPLEX_COPY_ASSIGN (class_type) = 1;
if (assop != 1)
- TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
+ TYPE_HAS_CONST_COPY_ASSIGN (class_type) = 1;
}
+ else if (move_fn_p (decl) && user_provided_p (decl))
+ TYPE_HAS_COMPLEX_MOVE_ASSIGN (class_type) = 1;
}
+ /* Destructors are handled in check_methods. */
}
/* Check a constructor DECL has the correct form. Complains
{
tree t = TREE_TYPE (name);
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
- const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (TREE_CODE (t) == VOID_TYPE)
- what = "void";
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to void "
+ "will never use a type conversion operator")
+ : G_("conversion to void "
+ "will never use a type conversion operator"));
else if (class_type)
{
if (t == class_type)
- what = "the same type";
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to the same type "
+ "will never use a type conversion operator")
+ : G_("conversion to the same type "
+ "will never use a type conversion operator"));
/* Don't force t to be complete here. */
else if (MAYBE_CLASS_TYPE_P (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, class_type))
- what = "a base class";
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to a base class "
+ "will never use a type conversion operator")
+ : G_("conversion to a base class "
+ "will never use a type conversion operator"));
}
- if (what)
- warning (OPT_Wconversion, "conversion to %s%s will never use a type "
- "conversion operator",
- ref ? "a reference to " : "", what);
}
if (operator_code == COND_EXPR)
elaborated type specifier is the implicit typedef created when
the type is declared. */
else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type)
{
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
/* The binfo slot should be empty, unless this is an (ill-formed)
redefinition. */
- gcc_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref));
+ if (TYPE_BINFO (ref) && !TYPE_SIZE (ref))
+ {
+ error ("redefinition of %q#T", ref);
+ return false;
+ }
+
gcc_assert (TYPE_MAIN_VARIANT (ref) == ref);
binfo = make_tree_binfo (max_bases);
}
\f
+/* Copies the enum-related properties from type SRC to type DST.
+ Used with the underlying type of an enum and the enum itself. */
+static void
+copy_type_enum (tree dst, tree src)
+{
+ TYPE_MIN_VALUE (dst) = TYPE_MIN_VALUE (src);
+ TYPE_MAX_VALUE (dst) = TYPE_MAX_VALUE (src);
+ TYPE_SIZE (dst) = TYPE_SIZE (src);
+ TYPE_SIZE_UNIT (dst) = TYPE_SIZE_UNIT (src);
+ SET_TYPE_MODE (dst, TYPE_MODE (src));
+ TYPE_PRECISION (dst) = TYPE_PRECISION (src);
+ TYPE_ALIGN (dst) = TYPE_ALIGN (src);
+ TYPE_USER_ALIGN (dst) = TYPE_USER_ALIGN (src);
+ TYPE_UNSIGNED (dst) = TYPE_UNSIGNED (src);
+}
+
/* Begin compiling the definition of an enumeration type.
NAME is its name,
+ if ENUMTYPE is not NULL_TREE then the type has alredy been found.
+
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.
+ if IS_NEW is not NULL, gets TRUE iff a new type is created.
+
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, tree underlying_type, bool scoped_enum_p)
+start_enum (tree name, tree enumtype, tree underlying_type,
+ bool scoped_enum_p, bool *is_new)
{
- tree enumtype;
-
+ tree prevtype = NULL_TREE;
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ if (is_new)
+ *is_new = false;
+ /* [C++0x dcl.enum]p5:
+
+ If not explicitly specified, the underlying type of a scoped
+ enumeration type is int. */
+ if (!underlying_type && scoped_enum_p)
+ underlying_type = integer_type_node;
+
+ if (underlying_type)
+ underlying_type = cv_unqualified (underlying_type);
+
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
forward reference. */
+ if (!enumtype)
+ enumtype = lookup_and_check_tag (enum_type, name,
+ /*tag_scope=*/ts_current,
+ /*template_header_p=*/false);
- enumtype = lookup_and_check_tag (enum_type, name,
- /*tag_scope=*/ts_current,
- /*template_header_p=*/false);
-
- if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
+ /* In case of a template_decl, the only check that should be deferred
+ to instantiation time is the comparison of underlying types. */
+ if (enumtype && TREE_CODE (enumtype) == ENUMERAL_TYPE)
{
- error ("multiple definition of %q#T", enumtype);
- error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype));
- /* Clear out TYPE_VALUES, and start again. */
- TYPE_VALUES (enumtype) = NULL_TREE;
+ if (scoped_enum_p != SCOPED_ENUM_P (enumtype))
+ {
+ error_at (input_location, "scoped/unscoped mismatch "
+ "in enum %q#T", enumtype);
+ error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
+ "previous definition here");
+ enumtype = error_mark_node;
+ }
+ else if (ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) != !! underlying_type)
+ {
+ error_at (input_location, "underlying type mismatch "
+ "in enum %q#T", enumtype);
+ error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
+ "previous definition here");
+ enumtype = error_mark_node;
+ }
+ else if (underlying_type && ENUM_UNDERLYING_TYPE (enumtype)
+ && !dependent_type_p (underlying_type)
+ && !dependent_type_p (ENUM_UNDERLYING_TYPE (enumtype))
+ && !same_type_p (underlying_type,
+ ENUM_UNDERLYING_TYPE (enumtype)))
+ {
+ error_at (input_location, "different underlying type "
+ "in enum %q#T", enumtype);
+ error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)),
+ "previous definition here");
+ underlying_type = NULL_TREE;
+ }
}
- else
+
+ if (!enumtype || TREE_CODE (enumtype) != ENUMERAL_TYPE
+ || processing_template_decl)
{
/* In case of error, make a dummy enum to allow parsing to
continue. */
if (enumtype == error_mark_node)
- name = make_anon_name ();
+ {
+ name = make_anon_name ();
+ enumtype = NULL_TREE;
+ }
- enumtype = make_node (ENUMERAL_TYPE);
+ /* enumtype may be an ENUMERAL_TYPE if this is a redefinition
+ of an opaque enum, or an opaque enum of an already defined
+ enumeration (C++0x only).
+ In any other case, it'll be NULL_TREE. */
+ if (!enumtype)
+ {
+ if (is_new)
+ *is_new = true;
+ }
+ prevtype = enumtype;
+ 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 (enumtype == error_mark_node)
+ return error_mark_node;
- If not explicitly specified, the underlying type of a scoped
- enumeration type is int. */
- if (!underlying_type)
- underlying_type = integer_type_node;
+ /* The enum is considered opaque until the opening '{' of the
+ enumerator list. */
+ SET_OPAQUE_ENUM_P (enumtype, true);
+ ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) = !! underlying_type;
}
+ SET_SCOPED_ENUM_P (enumtype, scoped_enum_p);
+
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);
+ copy_type_enum (enumtype, underlying_type);
ENUM_UNDERLYING_TYPE (enumtype) = underlying_type;
}
+ else if (dependent_type_p (underlying_type))
+ ENUM_UNDERLYING_TYPE (enumtype) = underlying_type;
else
error ("underlying type %<%T%> of %<%T%> must be an integral type",
underlying_type, enumtype);
}
- return enumtype;
+ /* If into a template class, the returned enum is always the first
+ declaration (opaque or not) seen. This way all the references to
+ this type will be to the same declaration. The following ones are used
+ only to check for definition errors. */
+ if (prevtype && processing_template_decl)
+ return prevtype;
+ else
+ return enumtype;
}
/* After processing and defining all the values of an enumeration type,
- install their decls in the enumeration type and finish it off.
- ENUMTYPE is the type object and VALUES a list of name-value pairs. */
+ install their decls in the enumeration type.
+ ENUMTYPE is the type object. */
void
-finish_enum (tree enumtype)
+finish_enum_value_list (tree enumtype)
{
tree values;
+ tree underlying_type;
tree decl;
- tree minnode;
- tree maxnode;
tree value;
+ tree minnode, maxnode;
tree t;
- bool unsignedp;
- bool use_short_enum;
- int lowprec;
- int highprec;
- int precision;
- unsigned int itk;
- tree underlying_type = NULL_TREE;
+
bool fixed_underlying_type_p
= ENUM_UNDERLYING_TYPE (enumtype) != NULL_TREE;
values;
values = TREE_CHAIN (values))
TREE_TYPE (TREE_VALUE (values)) = enumtype;
- if (at_function_scope_p ())
- add_stmt (build_min (TAG_DEFN, enumtype));
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 tree_int_cst_min_precision relies
- on the TREE_TYPE of the value it is passed. */
- unsignedp = tree_int_cst_sgn (minnode) >= 0;
- lowprec = tree_int_cst_min_precision (minnode, unsignedp);
- highprec = tree_int_cst_min_precision (maxnode, unsignedp);
- precision = MAX (lowprec, highprec);
-
if (!fixed_underlying_type_p)
{
+ /* 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 tree_int_cst_min_precision relies
+ on the TREE_TYPE of the value it is passed. */
+ bool unsignedp = tree_int_cst_sgn (minnode) >= 0;
+ int lowprec = tree_int_cst_min_precision (minnode, unsignedp);
+ int highprec = tree_int_cst_min_precision (maxnode, unsignedp);
+ int precision = MAX (lowprec, highprec);
+ unsigned int itk;
+ bool use_short_enum;
+
/* Determine the underlying type of the enumeration.
[dcl.enum]
itk++)
{
underlying_type = integer_types[itk];
- if (TYPE_PRECISION (underlying_type) >= precision
+ if (underlying_type != NULL_TREE
+ && TYPE_PRECISION (underlying_type) >= precision
&& TYPE_UNSIGNED (underlying_type) == unsignedp)
break;
}
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) = copy_node (underlying_type);
- set_min_and_max_values_for_integral_type
+ copy_type_enum (enumtype, underlying_type);
+
+ /* Compute the minimum and maximum values for the type.
+
+ [dcl.enum]
+
+ For an enumeration where emin is the smallest enumerator and emax
+ is the largest, the values of the enumeration are the values of the
+ 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. Similarly, it assumes that the front
+ end assures that a value of a particular type must be within
+ TYPE_MIN_VALUE and TYPE_MAX_VALUE.
+
+ We used to set these fields based on bmin and bmax, but that led
+ to invalid assumptions like optimizing away bounds checking. So
+ now we just set the TYPE_PRECISION, TYPE_MIN_VALUE, and
+ TYPE_MAX_VALUE to the values for the mode above and only restrict
+ the ENUM_UNDERLYING_TYPE for the benefit of diagnostics. */
+ ENUM_UNDERLYING_TYPE (enumtype)
+ = build_distinct_type_copy (underlying_type);
+ TYPE_PRECISION (ENUM_UNDERLYING_TYPE (enumtype)) = precision;
+ set_min_and_max_values_for_integral_type
(ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
+
+ /* If -fstrict-enums, still constrain TYPE_MIN/MAX_VALUE. */
+ if (flag_strict_enums)
+ set_min_and_max_values_for_integral_type (enumtype, precision,
+ unsignedp);
}
else
underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
- /* Compute the minimum and maximum values for the type.
-
- [dcl.enum]
-
- For an enumeration where emin is the smallest enumerator and emax
- is the largest, the values of the enumeration are the values of the
- 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);
-
/* 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))
/* Fix up all variant types of this enum type. */
for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
- {
- TYPE_VALUES (t) = TYPE_VALUES (enumtype);
- TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (enumtype);
- TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (enumtype);
- TYPE_SIZE (t) = TYPE_SIZE (enumtype);
- TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (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 ();
+ TYPE_VALUES (t) = TYPE_VALUES (enumtype);
/* Finish debugging output for this type. */
rest_of_type_compilation (enumtype, namespace_bindings_p ());
}
+/* Finishes the enum type. This is called only the first time an
+ enumeration is seen, be it opaque or odinary.
+ ENUMTYPE is the type object. */
+
+void
+finish_enum (tree enumtype)
+{
+ if (processing_template_decl)
+ {
+ if (at_function_scope_p ())
+ add_stmt (build_min (TAG_DEFN, enumtype));
+ return;
+ }
+
+ /* Here there should not be any variants of this type. */
+ gcc_assert (enumtype == TYPE_MAIN_VARIANT (enumtype)
+ && !TYPE_NEXT_VARIANT (enumtype));
+}
+
/* Build and install a CONST_DECL for an enumeration constant of the
enumeration type ENUMTYPE whose NAME and VALUE (if any) are provided.
+ LOC is the location of NAME.
Assignment of sequential values by default is handled here. */
void
-build_enumerator (tree name, tree value, tree enumtype)
+build_enumerator (tree name, tree value, tree enumtype, location_t loc)
{
tree decl;
tree context;
/* Validate and default VALUE. */
if (value != NULL_TREE)
{
- value = integral_constant_value (value);
+ value = cxx_constant_value (value);
if (TREE_CODE (value) == INTEGER_CST)
{
value = perform_integral_promotions (value);
- constant_expression_warning (value);
}
else
{
if (context && context == current_class_type)
/* This enum declaration is local to the class. We need the full
lang_decl so that we can record DECL_CLASS_CONTEXT, for example. */
- decl = build_lang_decl (CONST_DECL, name, type);
+ decl = build_lang_decl_loc (loc, CONST_DECL, name, 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);
-
+ a function could mean local to a class method. */
+ decl = build_decl (loc, 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.) */
}
\f
-/* We're defining DECL. Make sure that it's type is OK. */
+/* We're defining DECL. Make sure that its type is OK. */
static void
check_function_type (tree decl, tree current_function_parms)
TREE_CHAIN (args));
else
fntype = build_function_type (void_type_node, args);
- TREE_TYPE (decl)
+ fntype
= build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)));
+ fntype = (cp_build_type_attribute_variant
+ (fntype, TYPE_ATTRIBUTES (TREE_TYPE (decl))));
+ TREE_TYPE (decl) = fntype;
}
else
abstract_virtuals_error (decl, TREE_TYPE (fntype));
{
tree resdecl;
- resdecl = build_decl (RESULT_DECL, 0, restype);
+ resdecl = build_decl (input_location, RESULT_DECL, 0, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
DECL_RESULT (decl1) = resdecl;
with any previous declarations; if the original declaration
has a linkage specification, that specification applies to
the definition as well, and may affect the mangled name. */
- if (!DECL_CONTEXT (decl1))
+ if (DECL_FILE_SCOPE_P (decl1))
maybe_apply_pragma_weak (decl1);
}
+ /* constexpr functions must have literal argument types and
+ literal return type. */
+ validate_constexpr_fundecl (decl1);
+
/* Reset this in case the call to pushdecl changed it. */
current_function_decl = decl1;
/* Initialize the language data structures. Whenever we start
a new function, we destroy temporaries in the usual way. */
- cfun->language = GGC_CNEW (struct language_function);
+ cfun->language = ggc_alloc_cleared_language_function ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
current_binding_level = bl;
gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
cp_function_chain->x_current_class_ref
- = cp_build_indirect_ref (t, NULL, tf_warning_or_error);
+ = cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
cp_function_chain->x_current_class_ptr = t;
/* Constructors and destructors need to know whether they're "in
charge" of initializing virtual base classes. */
- t = TREE_CHAIN (t);
+ t = DECL_CHAIN (t);
if (DECL_HAS_IN_CHARGE_PARM_P (decl1))
{
current_in_charge_parm = t;
- t = TREE_CHAIN (t);
+ t = DECL_CHAIN (t);
}
if (DECL_HAS_VTT_PARM_P (decl1))
{
if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
- && ! DECL_INTERFACE_KNOWN (decl1)
- /* Don't try to defer nested functions for now. */
- && ! decl_function_context (decl1))
+ && ! DECL_INTERFACE_KNOWN (decl1))
DECL_DEFER_OUTPUT (decl1) = 1;
else
DECL_INTERFACE_KNOWN (decl1) = 1;
|| (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;
}
{
return (flag_exceptions && flag_enforce_eh_specs
&& !processing_template_decl
- && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))
+ && !type_throw_all_p (TREE_TYPE (fn))
/* We insert the EH_SPEC_BLOCK only in the original
function; then, it is copied automatically to the
clones. */
for (parm = specparms; parm; parm = next)
{
- next = TREE_CHAIN (parm);
+ next = DECL_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
if (DECL_NAME (parm) == NULL_TREE
gcc_assert (!DECL_PENDING_INLINE_P (decl));
/* Make a copy. */
- f = GGC_NEW (struct language_function);
+ f = ggc_alloc_language_function ();
memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
&& (! 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);
}
}
return block;
}
+/* If FNDECL is a class's key method, add the class to the list of
+ keyed classes that should be emitted. */
+
+static void
+record_key_method_defined (tree fndecl)
+{
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+ && DECL_VIRTUAL_P (fndecl)
+ && !processing_template_decl)
+ {
+ tree fnclass = DECL_CONTEXT (fndecl);
+ if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
+ keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
+ }
+}
+
+/* Subroutine of finish_function.
+ Save the body of constexpr functions for possible
+ future compile time evaluation. */
+
+static void
+maybe_save_function_definition (tree fun)
+{
+ if (!processing_template_decl
+ && DECL_DECLARED_CONSTEXPR_P (fun)
+ && !DECL_CLONED_FUNCTION_P (fun))
+ register_constexpr_fundef (fun, DECL_SAVED_TREE (fun));
+}
+
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition.
tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
int inclass_inline = (flags & 2) != 0;
- int nested;
/* When we get some parse errors, we can end up without a
current_function_decl, so cope. */
if (fndecl == NULL_TREE)
return error_mark_node;
+ if (c_dialect_objc ())
+ objc_finish_function ();
+
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)
- {
- tree fnclass = DECL_CONTEXT (fndecl);
- if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
- keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
- }
+ record_key_method_defined (fndecl);
- nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
/* TREE_READONLY (fndecl) = 1;
if (!processing_template_decl
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions
- && !DECL_REPLACEABLE_P (fndecl))
+ && !decl_replaceable_p (fndecl))
TREE_NOTHROW (fndecl) = 1;
/* This must come after expand_function_end because cleanups might
of curly braces for a function. */
gcc_assert (stmts_are_full_exprs_p ());
+ /* Save constexpr function body before it gets munged by
+ the NRV transformation. */
+ maybe_save_function_definition (fndecl);
+
/* Set up the named return value optimization, if we can. Candidate
variables are selected in check_return_expr. */
if (current_function_return_value)
&& !current_function_returns_value && !current_function_returns_null
/* Don't complain if we abort or throw. */
&& !current_function_returns_abnormally
+ /* Don't complain if we are declared noreturn. */
+ && !TREE_THIS_VOLATILE (fndecl)
&& !DECL_NAME (DECL_RESULT (fndecl))
&& !TREE_NO_WARNING (fndecl)
/* Structor return values (if any) are set by the compiler. */
info for the epilogue. */
cfun->function_end_locus = input_location;
+ /* Complain about parameters that are only set, but never otherwise used. */
+ if (warn_unused_but_set_parameter
+ && !processing_template_decl
+ && errorcount == unused_but_set_errorcount
+ && !DECL_CLONED_FUNCTION_P (fndecl))
+ {
+ tree decl;
+
+ for (decl = DECL_ARGUMENTS (fndecl);
+ decl;
+ decl = DECL_CHAIN (decl))
+ if (TREE_USED (decl)
+ && TREE_CODE (decl) == PARM_DECL
+ && !DECL_READ_P (decl)
+ && DECL_NAME (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !TREE_NO_WARNING (decl)
+ && !DECL_IN_SYSTEM_HEADER (decl)
+ && TREE_TYPE (decl) != error_mark_node
+ && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
+ && (!CLASS_TYPE_P (TREE_TYPE (decl))
+ || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ warning (OPT_Wunused_but_set_parameter,
+ "parameter %q+D set but not used", decl);
+ unused_but_set_errorcount = errorcount;
+ }
+
/* Genericize before inlining. */
if (!processing_template_decl)
{
struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
- invoke_plugin_callbacks (PLUGIN_CXX_CP_PRE_GENERICIZE, fndecl);
+ invoke_plugin_callbacks (PLUGIN_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;
--function_depth;
/* Clean up. */
- if (! nested)
- /* Let the error reporting routines know that we're outside a
- function. For a nested function, this value is used in
- cxx_pop_function_context and then reset via pop_function_context. */
- current_function_decl = NULL_TREE;
+ 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++)
+ FOR_EACH_VEC_ELT (tree, deferred_mark_used_calls, i, decl)
mark_used (decl);
VEC_free (tree, gc, deferred_mark_used_calls);
}
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);
if (! DECL_FRIEND_P (fndecl))
{
- if (TREE_CHAIN (fndecl))
+ if (DECL_CHAIN (fndecl))
{
fndecl = copy_node (fndecl);
TREE_CHAIN (fndecl) = NULL_TREE;
}
}
- finish_decl (fndecl, NULL_TREE, 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
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (inner_type)
&& TYPE_BEING_DEFINED (inner_type)))
- incomplete_vars = tree_cons (inner_type, var, incomplete_vars);
+ {
+ incomplete_var *iv
+ = VEC_safe_push (incomplete_var, gc, incomplete_vars, NULL);
+ iv->decl = var;
+ iv->incomplete_type = inner_type;
+ }
}
}
void
complete_vars (tree type)
{
- tree *list = &incomplete_vars;
+ unsigned ix;
+ incomplete_var *iv;
- gcc_assert (CLASS_TYPE_P (type));
- while (*list)
+ for (ix = 0; VEC_iterate (incomplete_var, incomplete_vars, ix, iv); )
{
- if (same_type_p (type, TREE_PURPOSE (*list)))
+ if (same_type_p (type, iv->incomplete_type))
{
- tree var = TREE_VALUE (*list);
+ tree var = iv->decl;
tree type = TREE_TYPE (var);
/* Complete the type of the variable. The VAR_DECL itself
will be laid out in expand_expr. */
complete_type (type);
cp_apply_type_quals_to_decl (cp_type_quals (type), var);
/* Remove this entry from the list. */
- *list = TREE_CHAIN (*list);
+ VEC_unordered_remove (incomplete_var, incomplete_vars, ix);
}
else
- list = &TREE_CHAIN (*list);
+ ix++;
}
/* Check for pending declarations which may have abstract type. */
fn = lookup_name (id);
arg = build_address (decl);
mark_used (decl);
- cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
- arg),
- tf_warning_or_error);
+ cleanup = cp_build_function_call_nary (fn, tf_warning_or_error,
+ arg, NULL_TREE);
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
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;
}
{
}
+/* Return the FUNCTION_TYPE that corresponds to MEMFNTYPE, which can be a
+ FUNCTION_DECL, METHOD_TYPE, FUNCTION_TYPE, pointer or reference to
+ METHOD_TYPE or FUNCTION_TYPE, or pointer to member function. */
+
+tree
+static_fn_type (tree memfntype)
+{
+ tree fntype;
+ tree args;
+
+ if (TYPE_PTRMEMFUNC_P (memfntype))
+ memfntype = TYPE_PTRMEMFUNC_FN_TYPE (memfntype);
+ if (POINTER_TYPE_P (memfntype)
+ || TREE_CODE (memfntype) == FUNCTION_DECL)
+ memfntype = TREE_TYPE (memfntype);
+ if (TREE_CODE (memfntype) == FUNCTION_TYPE)
+ return memfntype;
+ gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
+ args = TYPE_ARG_TYPES (memfntype);
+ fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
+ fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype));
+ fntype = (cp_build_type_attribute_variant
+ (fntype, TYPE_ATTRIBUTES (memfntype)));
+ fntype = (build_exception_variant
+ (fntype, TYPE_RAISES_EXCEPTIONS (memfntype)));
+ return fntype;
+}
+
/* DECL was originally constructed as a non-static member function,
but turned out to be static. Update it accordingly. */
void
revert_static_member_fn (tree decl)
{
- tree tmp;
- tree function = TREE_TYPE (decl);
- tree args = TYPE_ARG_TYPES (function);
+ TREE_TYPE (decl) = static_fn_type (decl);
- if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
- != TYPE_UNQUALIFIED)
+ if (cp_type_quals (TREE_TYPE (decl)) != TYPE_UNQUALIFIED)
error ("static member function %q#D declared with type qualifiers", decl);
- args = TREE_CHAIN (args);
- tmp = build_function_type (TREE_TYPE (function), args);
- tmp = build_qualified_type (tmp, cp_type_quals (function));
- tmp = build_exception_variant (tmp,
- TYPE_RAISES_EXCEPTIONS (function));
- TREE_TYPE (decl) = tmp;
if (DECL_ARGUMENTS (decl))
- DECL_ARGUMENTS (decl) = TREE_CHAIN (DECL_ARGUMENTS (decl));
+ DECL_ARGUMENTS (decl) = DECL_CHAIN (DECL_ARGUMENTS (decl));
DECL_STATIC_FUNCTION_P (decl) = 1;
}
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;
+ case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO;
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"