/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 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 (cp_parameter_declarator *, tree *);
+static tree grokparms (tree parmlist, tree *);
static const char *redeclaration_error_message (tree, tree);
static int decl_jump_unsafe (tree);
static tree 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 int walk_namespaces_r (tree, walk_namespaces_fn, void *);
static void maybe_deduce_size_from_array_init (tree, tree);
static void layout_var_decl (tree);
-static void maybe_commonize_var (tree);
static tree check_initializer (tree, tree, int, tree *);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
static void save_function_data (tree);
+static 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. */
-struct named_label_use_entry GTY(())
-{
+struct GTY(()) named_label_use_entry {
struct named_label_use_entry *next;
/* The binding level to which this entry is *currently* attached.
This is initially the binding level in which the goto appeared,
we can clear out their names' definitions at the end of the
function, and so we can check the validity of jumps to these labels. */
-struct named_label_entry GTY(())
-{
+struct GTY(()) named_label_entry {
/* The decl itself. */
tree label_decl;
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;
function, two inside the body of a function in a local class, etc.) */
int function_depth;
+/* To avoid unwanted recursion, finish_function defers all mark_used calls
+ encountered during its execution until it finishes. */
+bool defer_mark_used_calls;
+VEC(tree, gc) *deferred_mark_used_calls;
+
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
deprecated items. */
+enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
-enum deprecated_states {
- DEPRECATED_NORMAL,
- DEPRECATED_SUPPRESS
-};
+\f
+/* A list of VAR_DECLs whose type was incomplete at the time the
+ variable was declared. */
-static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+typedef struct GTY(()) incomplete_var_d {
+ tree decl;
+ tree incomplete_type;
+} incomplete_var;
-\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. */
+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);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
-/* Insert BLOCK at the end of the list of subblocks of the
- current binding level. This is used when a BIND_EXPR is expanded,
- to handle the BLOCK node inside the BIND_EXPR. */
-
-void
-insert_block (tree block)
-{
- TREE_USED (block) = 1;
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
-}
-
/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
itself, calling F for each. The DATA is passed to F as well. */
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)
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
- error (errmsg, newdecl);
+ error_at (DECL_SOURCE_LOCATION (newdecl), errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
? "%q+#D previously defined here"
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
{
/* Prototype decl follows defn w/o prototype. */
- warning (0, "prototype for %q+#D", newdecl);
- warning (0, "%Jfollows non-prototype definition here", olddecl);
+ warning_at (input_location, 0, "prototype for %q+#D", newdecl);
+ warning_at (DECL_SOURCE_LOCATION (olddecl), 0,
+ "follows non-prototype definition here");
}
else if ((TREE_CODE (olddecl) == FUNCTION_DECL
|| TREE_CODE (olddecl) == VAR_DECL)
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_SOURCE_LOCATION (newdecl);
DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
- DECL_ARGUMENTS (old_result)
- = DECL_ARGUMENTS (new_result);
+ {
+ tree parm;
+ DECL_ARGUMENTS (old_result)
+ = DECL_ARGUMENTS (new_result);
+ for (parm = DECL_ARGUMENTS (old_result); parm;
+ parm = DECL_CHAIN (parm))
+ DECL_CONTEXT (parm) = old_result;
+ }
}
return olddecl;
{
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)
{
+ tree parm;
+
+ /* Merge parameter attributes. */
+ tree oldarg, newarg;
+ for (oldarg = DECL_ARGUMENTS(olddecl),
+ newarg = DECL_ARGUMENTS(newdecl);
+ oldarg && newarg;
+ oldarg = DECL_CHAIN(oldarg), newarg = DECL_CHAIN(newarg)) {
+ DECL_ATTRIBUTES (newarg)
+ = (*targetm.merge_decl_attributes) (oldarg, newarg);
+ DECL_ATTRIBUTES (oldarg) = DECL_ATTRIBUTES (newarg);
+ }
+
if (DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_TEMPLATE_INSTANTIATION (newdecl))
{
should have exited above, returning 0. */
gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl));
- if (TREE_USED (olddecl))
+ if (DECL_ODR_USED (olddecl))
/* From [temp.expl.spec]:
If a template, a member template or the member of a class
/* Preserve abstractness on cloned [cd]tors. */
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
+ /* Update newdecl's parms to point at olddecl. */
+ for (parm = DECL_ARGUMENTS (newdecl); parm;
+ parm = DECL_CHAIN (parm))
+ DECL_CONTEXT (parm) = olddecl;
+
if (! types_match)
{
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
}
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
- /* Don't clear out the arguments if we're redefining a function. */
+ /* Don't clear out the arguments if we're just redeclaring a
+ function. */
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
&& DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
- warning (OPT_Wattributes, "%q+D: visibility attribute ignored "
- "because it", newdecl);
- warning (OPT_Wattributes, "%Jconflicts with previous "
- "declaration here", olddecl);
+ warning_at (input_location, OPT_Wattributes,
+ "%q+D: visibility attribute ignored because it", newdecl);
+ warning_at (DECL_SOURCE_LOCATION (olddecl), OPT_Wattributes,
+ "conflicts with previous declaration here");
}
/* Choose the declaration which specified visibility. */
if (DECL_VISIBILITY_SPECIFIED (olddecl))
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, TREE_TYPE (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);
/* After labels, make any new cleanups in the function go into their
TYPENAME_IS_CLASS_P (t) = ti.class_p;
/* Build the corresponding TYPE_DECL. */
- d = build_decl (TYPE_DECL, name, t);
+ d = build_decl (input_location, TYPE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
gcc_assert (TYPE_P (context));
- /* When the CONTEXT is a dependent type, NAME could refer to a
- dependent base class of CONTEXT. So we cannot peek inside it,
- even if CONTEXT is a currently open scope. */
- if (dependent_type_p (context))
- return build_typename_type (context, name, fullname, tag_type);
-
if (!MAYBE_CLASS_TYPE_P (context))
{
if (complain & tf_error)
return error_mark_node;
}
+ /* When the CONTEXT is a dependent type, NAME could refer to a
+ dependent base class of CONTEXT. But look inside it anyway
+ if CONTEXT is a currently open scope, in case it refers to a
+ member of the current instantiation or a non-dependent base;
+ lookup will stop when we hit a dependent base. */
+ if (!dependent_scope_p (context))
+ /* We should only set WANT_TYPE when we're a nested typename type.
+ Then we can give better diagnostics if we find a non-type. */
+ t = lookup_field (context, name, 2, /*want_type=*/true);
+ else
+ t = NULL_TREE;
+
+ 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;
- /* We should only set WANT_TYPE when we're a nested typename type.
- Then we can give better diagnostics if we find a non-type. */
- t = lookup_field (context, name, 0, /*want_type=*/true);
if (!t)
{
if (complain & tf_error)
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);
{
tree type, decl;
if (size > 0)
- type = make_signed_type (size);
+ type = build_nonstandard_integer_type (size, 0);
else if (size > -32)
- { /* "__java_char" or ""__java_boolean". */
- type = make_unsigned_type (-size);
+ {
+ tree stype;
+ /* "__java_char" or ""__java_boolean". */
+ type = build_nonstandard_integer_type (-size, 1);
+ /* Get the signed type cached and attached to the unsigned type,
+ so it doesn't get garbage-collected at "random" times,
+ causing potential codegen differences out of different UIDs
+ and different alias set numbers. */
+ stype = build_nonstandard_integer_type (-size, 0);
+ TREE_CHAIN (type) = stype;
/*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/
}
else
static void
record_unknown_type (tree type, const char* name)
{
- tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
+ tree decl = pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier (name), type));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
DECL_IGNORED_P (decl) = 1;
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
TYPE_SIZE (type) = TYPE_SIZE (void_type_node);
TYPE_ALIGN (type) = 1;
TYPE_USER_ALIGN (type) = 0;
- TYPE_MODE (type) = TYPE_MODE (void_type_node);
+ SET_TYPE_MODE (type, TYPE_MODE (void_type_node));
}
/* A string for which we should create an IDENTIFIER_NODE at
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
groktypename (cp_decl_specifier_seq *type_specifiers,
- const cp_declarator *declarator)
+ const cp_declarator *declarator,
+ bool is_template_arg)
{
tree attrs;
tree type;
+ enum decl_context context
+ = is_template_arg ? TEMPLATE_TYPE_ARG : TYPENAME;
attrs = type_specifiers->attributes;
type_specifiers->attributes = NULL_TREE;
- type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
+ type = grokdeclarator (declarator, type_specifiers, context, 0, &attrs);
if (attrs && type != error_mark_node)
{
if (CLASS_TYPE_P (type))
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;
}
{
/* The parser only allows identifiers as designated
initializers. */
- gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
- error ("name %qD used in a GNU-style designated "
- "initializer for an array", ce->index);
+ if (ce->index == error_mark_node)
+ error ("name used in a GNU-style designated "
+ "initializer for an array");
+ else
+ {
+ gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
+ error ("name %qD used in a GNU-style designated "
+ "initializer for an array", ce->index);
+ }
return false;
}
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;
}
cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
- layout_decl (decl, 0);
+ relayout_decl (decl);
}
}
/* 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;
}
}
we have a weak definition, we must endeavor to create only one
instance of the variable at link-time. */
-static void
+void
maybe_commonize_var (tree decl)
{
/* Static data in a function with comdat linkage also has comdat
/* Don't mess with __FUNCTION__. */
&& ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
- /* Unfortunately, import_export_decl has not always been called
- before the function is processed, so we cannot simply check
- DECL_COMDAT. */
- && (DECL_COMDAT (DECL_CONTEXT (decl))
- || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
- || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
- && TREE_PUBLIC (DECL_CONTEXT (decl)))))
+ && vague_linkage_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 ((*targetm.vector_opaque_p) (type))
+ else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_VECTOR_OPAQUE (type))
{
error ("opaque vector types cannot be initialized");
init = error_mark_node;
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);
+ init_code = store_init_value (decl, init, flags);
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
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;
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
auto_node = type_uses_auto (type);
- if (auto_node && !type_dependent_expression_p (init))
+ if (auto_node)
{
- type = TREE_TYPE (decl) = do_auto_deduction (type, init, auto_node);
- if (type == error_mark_node)
- return;
+ tree d_init;
+ if (init == NULL_TREE)
+ {
+ error ("declaration of %q#D has no initializer", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ return;
+ }
+ 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, 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_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)
DECL_INITIAL (decl) = NULL_TREE;
}
- if (init && init_const_expr_p)
- {
- 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 (init)
{
- 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;
- }
- else if (init == ridpointers[(int)RID_DEFAULT])
+ if (init == ridpointers[(int)RID_DEFAULT])
{
- if (!defaultable_fn_p (decl))
- error ("%qD cannot be defaulted", decl);
- else
- {
- /* An out-of-class default definition is defined at
- the point where it is explicitly defaulted. */
- DECL_DEFAULTED_FN (decl) = 1;
- if (DECL_INITIAL (decl) == error_mark_node)
- synthesize_method (decl);
- }
+ /* An out-of-class default definition is defined at
+ the point where it is explicitly defaulted. */
+ if (DECL_INITIAL (decl) == error_mark_node)
+ synthesize_method (decl);
}
else
error ("function %q#D is initialized like a variable", decl);
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 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);
+ 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";
}
actually needed. It is unlikely that it will be inlined, since
it is only called via a function pointer, but we avoid unnecessary
emissions this way. */
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
DECL_INTERFACE_KNOWN (fndecl) = 1;
/* Build the parameter. */
if (use_cxa_atexit)
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
bool funcdef_flag,
int template_count,
tree in_namespace,
- tree* attrlist)
+ tree* attrlist,
+ location_t location)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+
+ /* If we have an explicit location, use it, otherwise use whatever
+ build_lang_decl used (probably input_location). */
+ if (location != UNKNOWN_LOCATION)
+ DECL_SOURCE_LOCATION (decl) = location;
+
if (TREE_CODE (type) == METHOD_TYPE)
{
tree parm;
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 = DECL_CHAIN (t))
+ DECL_CONTEXT (t) = decl;
/* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
{
case sfk_constructor:
case sfk_copy_constructor:
+ case sfk_move_constructor:
DECL_CONSTRUCTOR_P (decl) = 1;
break;
case sfk_destructor:
}
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))
error ("ISO C++ forbids in-class initialization of non-const "
"static member %qD",
decl);
- else if (!INTEGRAL_TYPE_P (type))
+ else if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
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_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);
+ }
}
- if (value_dependent_expression_p (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; treat non-constant expressions as dependent, too. */
+ if (processing_template_decl
+ && (dependent_type_p (type)
+ || !TREE_CONSTANT (size) || value_dependent_expression_p (size)))
{
- /* We cannot do any checking for a value-dependent SIZE. Just
- build the index type and mark that it requires structural
- equality checks. */
+ /* We cannot do any checking for a SIZE that isn't known to be
+ constant. Just build the index type and mark that it requires
+ structural equality checks. */
itype = build_index_type (build_min (MINUS_EXPR, sizetype,
size, integer_one_node));
+ 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",
cp_build_binary_op will be appropriately folded. */
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
- itype = cp_build_binary_op (MINUS_EXPR,
+ itype = cp_build_binary_op (input_location,
+ MINUS_EXPR,
cp_convert (ssizetype, size),
cp_convert (ssizetype, integer_one_node),
tf_warning_or_error);
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];
unsigned_p = declspecs->specs[(int)ds_unsigned];
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)
funcdef_flag = true, decl_context = FIELD;
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
+ else if (decl_context == TEMPLATE_TYPE_ARG)
+ template_type_arg = true, decl_context = TYPENAME;
+ else if (decl_context == TPARM)
+ template_parm_flag = true, decl_context = PARM;
if (initialized > 1)
funcdef_flag = true;
}
type = TREE_OPERAND (decl, 0);
- name = IDENTIFIER_POINTER (constructor_name (type));
+ if (TYPE_P (type))
+ type = constructor_name (type);
+ name = identifier_to_locale (IDENTIFIER_POINTER (type));
dname = decl;
}
break;
{
error ("declarator-id missing; using reserved word %qD",
dname);
- name = IDENTIFIER_POINTER (dname);
+ name = identifier_to_locale (IDENTIFIER_POINTER (dname));
}
else if (!IDENTIFIER_TYPENAME_P (dname))
- name = IDENTIFIER_POINTER (dname);
+ name = identifier_to_locale (IDENTIFIER_POINTER (dname));
else
{
gcc_assert (flags == NO_SPECIAL);
ctor_return_type = TREE_TYPE (dname);
sfk = sfk_conversion;
if (is_typename_at_global_scope (dname))
- name = IDENTIFIER_POINTER (dname);
+ name = identifier_to_locale (IDENTIFIER_POINTER (dname));
else
name = "<invalid operator>";
}
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)
suppress reports of deprecated items. */
if (type && TREE_DEPRECATED (type)
&& deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (type);
+ warn_deprecated_use (type, NULL_TREE);
if (type && TREE_CODE (type) == TYPE_DECL)
{
typedef_decl = type;
if (TREE_DEPRECATED (type)
&& DECL_ARTIFICIAL (typedef_decl)
&& deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (type);
+ warn_deprecated_use (type, NULL_TREE);
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
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 ("storage class specifiers invalid in parameter declarations");
+
+ if (type_uses_auto (type))
+ {
+ error ("parameter declared %<auto%>");
+ type = error_mark_node;
+ }
+
+ /* Function parameters cannot be constexpr. If we saw one, moan
+ and pretend it wasn't there. */
+ if (constexpr_p)
+ {
+ error ("a parameter cannot be declared %<constexpr%>");
+ constexpr_p = 0;
+ }
}
/* Give error if `virtual' is used outside of class declaration. */
switch (TREE_CODE (unqualified_id))
{
case BIT_NOT_EXPR:
- unqualified_id
- = constructor_name (TREE_OPERAND (unqualified_id, 0));
+ unqualified_id = TREE_OPERAND (unqualified_id, 0);
+ if (TYPE_P (unqualified_id))
+ unqualified_id = constructor_name (unqualified_id);
break;
case IDENTIFIER_NODE:
/* We now know that the TYPE_QUALS don't apply to the
decl, but to its return type. */
type_quals = TYPE_UNQUALIFIED;
- set_no_warning = true;
+ }
+ errmsg = targetm.invalid_return_type (type);
+ if (errmsg)
+ {
+ error (errmsg);
+ type = integer_type_node;
}
/* Error about some types functions can't return. */
/* Pick up the exception specifications. */
raises = declarator->u.function.exception_specification;
+ /* Say it's a definition only for the CALL_EXPR
+ closest to the identifier. */
+ funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
+
/* Handle a late-specified return type. */
+ if (funcdecl_p)
+ {
+ if (type_uses_auto (type))
+ {
+ if (!declarator->u.function.late_return_type)
+ {
+ error ("%qs function uses %<auto%> type specifier without"
+ " late return type", name);
+ return error_mark_node;
+ }
+ else if (!is_auto (type))
+ {
+ error ("%qs function with late return type has"
+ " %qT as its type rather than plain %<auto%>",
+ name, type);
+ return error_mark_node;
+ }
+ }
+ else if (declarator->u.function.late_return_type)
+ {
+ error ("%qs function with late return type not declared"
+ " with %<auto%> type specifier", name);
+ return error_mark_node;
+ }
+ }
type = splice_late_return_type
(type, declarator->u.function.late_return_type);
if (type == error_mark_node)
return error_mark_node;
- /* Say it's a definition only for the CALL_EXPR
- closest to the identifier. */
- funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
-
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
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);
}
+ else if (ctype && sfk == sfk_conversion)
+ {
+ if (explicitp == 1)
+ {
+ maybe_warn_cpp0x (CPP0X_EXPLICIT_CONVERSION);
+ explicitp = 2;
+ }
+ }
arg_types = grokparms (declarator->u.function.parameters,
&parms);
&& (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
+ && 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);
- if (id_declarator && declarator->u.id.qualifying_scope)
- error ("%Jtypedef name may not be a nested-name-specifier", decl);
+ decl = build_decl (input_location, TYPE_DECL, unqualified_id, type);
+ if (id_declarator && declarator->u.id.qualifying_scope) {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "typedef name may not be a nested-name-specifier");
+ TREE_TYPE (decl) = error_mark_node;
+ }
if (decl_context != FIELD)
{
&& TYPE_ANONYMOUS_P (type)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
- tree oldname = TYPE_NAME (type);
tree t;
/* Replace the anonymous name with the real name everywhere. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- if (TYPE_NAME (t) == oldname)
- TYPE_NAME (t) = decl;
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ /* 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))
TYPE_WAS_ANONYMOUS (type) = 1;
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
= TYPE_IDENTIFIER (type);
+ /* Adjust linkage now that we aren't anonymous anymore. */
+ set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
+ determine_visibility (TYPE_MAIN_DECL (type));
+
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
}
|| (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;
}
}
}
else if (memfn_quals)
{
- if (ctype == NULL_TREE)
- {
- if (TREE_CODE (type) != METHOD_TYPE)
- error ("invalid qualifiers on non-member function type");
- else
- ctype = TYPE_METHOD_BASETYPE (type);
- }
+ if (ctype == NULL_TREE
+ && TREE_CODE (type) == METHOD_TYPE)
+ ctype = TYPE_METHOD_BASETYPE (type);
+
if (ctype)
type = build_memfn_type (type, ctype, memfn_quals);
+ /* Core issue #547: need to allow this in template type args. */
+ else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
+ type = apply_memfn_quals (type, memfn_quals);
+ else
+ error ("invalid qualifiers on non-member function type");
}
return 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. */
if (sfk == sfk_destructor)
{
+ tree uqname = id_declarator->u.id.unqualified_name;
+
if (!ctype)
{
gcc_assert (friendp);
error ("expected qualified name in friend declaration "
- "for destructor %qD",
- id_declarator->u.id.unqualified_name);
+ "for destructor %qD", uqname);
return error_mark_node;
}
- if (!same_type_p (TREE_OPERAND
- (id_declarator->u.id.unqualified_name, 0),
- ctype))
+ if (!check_dtor_name (ctype, TREE_OPERAND (uqname, 0)))
{
error ("declaration of %qD as member of %qT",
- id_declarator->u.id.unqualified_name, ctype);
+ uqname, ctype);
return error_mark_node;
}
+ if (constexpr_p)
+ {
+ error ("a destructor cannot be %<constexpr%>");
+ 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);
+ funcdef_flag, template_count, in_namespace,
+ attrlist, declarator->id_loc);
if (decl == NULL_TREE)
return error_mark_node;
#if 0
is called a converting constructor. */
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
- else if (DECL_CONSTRUCTOR_P (decl))
- {
- /* A constructor with no parms is not a conversion.
- Ignore any compiler-added parms. */
- tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
-
- if (arg_types == void_list_node)
- DECL_NONCONVERTING_P (decl) = 1;
- }
- }
- else if (TREE_CODE (type) == METHOD_TYPE)
- {
- /* 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);
- if (decl == NULL_TREE)
- return error_mark_node;
}
else if (!staticp && !dependent_type_p (type)
&& !COMPLETE_TYPE_P (complete_type (type))
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);
}
"declared out of global scope", name);
}
+ if (ctype != NULL_TREE
+ && TREE_CODE (ctype) != NAMESPACE_DECL && !MAYBE_CLASS_TYPE_P (ctype))
+ {
+ error ("%q#T is not a class or a namespace", ctype);
+ ctype = NULL_TREE;
+ }
+
if (ctype == NULL_TREE)
{
if (virtualp)
error ("virtual non-class function %qs", name);
virtualp = 0;
}
+ else if (sfk == sfk_constructor
+ || sfk == sfk_destructor)
+ {
+ error (funcdef_flag
+ ? "%qs defined in a non-class scope"
+ : "%qs declared in a non-class scope", name);
+ sfk = sfk_none;
+ }
}
- else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
- && !NEW_DELETE_OPNAME_P (original_name))
- 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,
- template_count, in_namespace, attrlist);
+ publicp, inlinep | (2 * constexpr_p), sfk,
+ funcdef_flag,
+ template_count, in_namespace, attrlist,
+ declarator->id_loc);
if (decl == NULL_TREE)
return error_mark_node;
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;
return arg;
}
+/* Returns a deprecated type used within TYPE, or NULL_TREE if none. */
+
+static tree
+type_is_deprecated (tree type)
+{
+ enum tree_code code;
+ if (TREE_DEPRECATED (type))
+ return type;
+ if (TYPE_NAME (type)
+ && TREE_DEPRECATED (TYPE_NAME (type)))
+ return type;
+
+ /* 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
+ || code == OFFSET_TYPE || code == FUNCTION_TYPE
+ || code == METHOD_TYPE || code == ARRAY_TYPE)
+ return type_is_deprecated (TREE_TYPE (type));
+
+ if (TYPE_PTRMEMFUNC_P (type))
+ return type_is_deprecated
+ (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type))));
+
+ return NULL_TREE;
+}
+
/* Decode the list of parameter types for a function type.
Given the list of things declared inside the parens,
return a list of types.
*PARMS is set to the chain of PARM_DECLs created. */
static tree
-grokparms (cp_parameter_declarator *first_parm, tree *parms)
+grokparms (tree parmlist, tree *parms)
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
- int ellipsis = !first_parm || first_parm->ellipsis_p;
- cp_parameter_declarator *parm;
+ tree parm;
int any_error = 0;
- struct pointer_set_t *unique_decls = pointer_set_create ();
- for (parm = first_parm; parm != NULL; parm = parm->next)
+ for (parm = parmlist; parm != NULL_TREE; parm = TREE_CHAIN (parm))
{
tree type = NULL_TREE;
- tree init = parm->default_argument;
- tree attrs;
- tree decl;
+ tree init = TREE_PURPOSE (parm);
+ tree decl = TREE_VALUE (parm);
+ const char *errmsg;
- if (parm == no_parameters)
+ if (parm == void_list_node)
break;
- attrs = parm->decl_specifiers.attributes;
- parm->decl_specifiers.attributes = NULL_TREE;
- decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
- PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
- if (attrs)
- cplus_decl_attributes (&decl, attrs, 0);
-
type = TREE_TYPE (decl);
if (VOID_TYPE_P (type))
{
if (same_type_p (type, void_type_node)
&& DECL_SELF_REFERENCE_P (type)
- && !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
+ && !DECL_NAME (decl) && !result && TREE_CHAIN (parm) == void_list_node)
/* this is a parmlist of `(void)', which is ok. */
break;
cxx_incomplete_type_error (decl, type);
init = NULL_TREE;
}
+ if (type != error_mark_node
+ && (errmsg = targetm.invalid_parameter_type (type)))
+ {
+ error (errmsg);
+ type = error_mark_node;
+ TREE_TYPE (decl) = error_mark_node;
+ }
+
if (type != error_mark_node)
{
+ if (deprecated_state != DEPRECATED_SUPPRESS)
+ {
+ tree deptype = type_is_deprecated (type);
+ if (deptype)
+ warn_deprecated_use (deptype, NULL_TREE);
+ }
+
/* Top-level qualifiers on the parameters are
ignored for function types. */
type = cp_build_qualified_type (type, 0);
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)
if (TREE_CODE (decl) == PARM_DECL
&& FUNCTION_PARAMETER_PACK_P (decl)
- && parm->next)
+ && TREE_CHAIN (parm)
+ && TREE_CHAIN (parm) != void_list_node)
error ("parameter packs must be at the end of the parameter list");
- if (DECL_NAME (decl))
- {
- if (pointer_set_contains (unique_decls, DECL_NAME (decl)))
- error ("multiple parameters named %qE", DECL_NAME (decl));
- else
- pointer_set_insert (unique_decls, DECL_NAME (decl));
- }
-
- TREE_CHAIN (decl) = decls;
+ DECL_CHAIN (decl) = decls;
decls = decl;
result = tree_cons (init, type, result);
}
decls = nreverse (decls);
result = nreverse (result);
- if (!ellipsis)
+ if (parm)
result = chainon (result, void_list_node);
*parms = decls;
- pointer_set_destroy (unique_decls);
return result;
}
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;
+ {
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
+ 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);
BINFO_OFFSET (binfo) = size_zero_node;
BINFO_TYPE (binfo) = ref;
+ /* Apply base-class info set up to the variants of this type. */
+ fixup_type_variants (ref);
+
if (max_bases)
{
BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, max_bases);
}
\f
+/* 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 (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);
- 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;
- integer_type_kind 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 min_precision relies on the
- TREE_TYPE of the value it is passed. */
- unsignedp = tree_int_cst_sgn (minnode) >= 0;
- lowprec = min_precision (minnode, unsignedp);
- highprec = min_precision (maxnode, unsignedp);
- 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);
- 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);
- 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
{
tree prev_value;
bool overflowed;
- /* The next value is the previous value plus one. We can
- safely assume that the previous value is an INTEGER_CST.
+ /* The next value is the previous value plus one.
add_double doesn't know the type of the target expression,
so we must check with int_fits_type_p as well. */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
- overflowed = add_double (TREE_INT_CST_LOW (prev_value),
- TREE_INT_CST_HIGH (prev_value),
- 1, 0, &lo, &hi);
- value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
- overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
-
- if (overflowed)
+ if (error_operand_p (prev_value))
+ value = error_mark_node;
+ else
{
- error ("overflow in enumeration values at %qD", name);
- value = error_mark_node;
+ overflowed = add_double (TREE_INT_CST_LOW (prev_value),
+ TREE_INT_CST_HIGH (prev_value),
+ 1, 0, &lo, &hi);
+ value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
+ overflowed
+ |= !int_fits_type_p (value, TREE_TYPE (prev_value));
+
+ if (overflowed)
+ {
+ error ("overflow in enumeration values at %qD", name);
+ value = error_mark_node;
+ }
}
}
else
/* Silently convert the value so that we can continue. */
value = perform_implicit_conversion (ENUM_UNDERLYING_TYPE (enumtype),
value, tf_none);
- if (value == error_mark_node)
- value = NULL_TREE;
}
}
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, TYPE_MAIN_VARIANT (restype));
+ resdecl = build_decl (input_location, RESULT_DECL, 0, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
DECL_RESULT (decl1) = resdecl;
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;
}
tree decl1;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+ if (decl1 == error_mark_node)
+ return 0;
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
- return 0;
+ {
+ error ("invalid function declaration");
+ return 0;
+ }
if (DECL_MAIN_P (decl1))
/* main must return int. grokfndecl should have corrected it
{
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 (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);
- }
+ if (c_dialect_objc ())
+ objc_finish_function ();
+
+ gcc_assert (!defer_mark_used_calls);
+ defer_mark_used_calls = true;
+
+ 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_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_EACH_VEC_ELT (tree, deferred_mark_used_calls, i, decl)
+ mark_used (decl);
+ VEC_free (tree, gc, deferred_mark_used_calls);
+ }
return fndecl;
}
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (cp_decl_specifier_seq *declspecs,
- const cp_declarator *declarator, tree attrlist)
+grokmethod (cp_decl_specifier_seq *declspecs,
+ const cp_declarator *declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
&attrlist);
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DECL_NO_INLINE_WARNING_P (fndecl) = 1;
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
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);
-
- /* 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"