/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
static int ambi_op_p (enum tree_code);
static int unary_op_p (enum tree_code);
static void push_local_name (tree);
-static tree grok_reference_init (tree, tree, tree, tree *, int);
+static tree grok_reference_init (tree, tree, tree, int);
static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
int, int, tree);
static int check_static_variable_definition (tree, tree);
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 tree check_initializer (tree, tree, int, tree *);
+static tree check_initializer (tree, tree, int, VEC(tree,gc) **);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
static void save_function_data (tree);
static void copy_type_enum (tree , tree);
interested in their types. */
return 0;
+ gcc_assert (DECL_P (newdecl));
+
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
|| TREE_TYPE (olddecl) == error_mark_node)
return error_mark_node;
+ if (UDLIT_OPER_P (DECL_NAME (newdecl))
+ && UDLIT_OPER_P (DECL_NAME (olddecl)))
+ {
+ if (TREE_CODE (newdecl) == TEMPLATE_DECL
+ && TREE_CODE (olddecl) != TEMPLATE_DECL
+ && check_raw_literal_operator (olddecl))
+ error ("literal operator template %q+D conflicts with"
+ " raw literal operator %qD", newdecl, olddecl);
+ else if (TREE_CODE (newdecl) != TEMPLATE_DECL
+ && TREE_CODE (olddecl) == TEMPLATE_DECL
+ && check_raw_literal_operator (newdecl))
+ error ("raw literal operator %q+D conflicts with"
+ " literal operator template %qD", newdecl, olddecl);
+ }
+
if (DECL_P (olddecl)
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
&& DECL_ANTICIPATED (olddecl)
&& TREE_NOTHROW (newdecl)
- && !TREE_NOTHROW (olddecl)
- && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
- && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
- && types_match)
- TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+ && !TREE_NOTHROW (olddecl))
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (olddecl);
+ tree tmpdecl = builtin_decl_explicit (fncode);
+ if (tmpdecl && tmpdecl != olddecl && types_match)
+ TREE_NOTHROW (tmpdecl) = 1;
+ }
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
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"
- : "%q+#D previously declared here", olddecl);
+ ? G_("%q+#D previously defined here")
+ : G_("%q+#D previously declared here"), olddecl);
return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
/* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
/* Don't warn about friends, let add_friend take care of it. */
- && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl)))
+ && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl))
+ /* Don't warn about declaration followed by specialization. */
+ && (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
+ || DECL_TEMPLATE_SPECIALIZATION (olddecl)))
{
warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
/* If we're keeping the built-in definition, keep the rtl,
regardless of declaration matches. */
COPY_DECL_RTL (olddecl, newdecl);
+ if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+ switch (fncode)
+ {
+ /* If a compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with the
+ expected semantics. */
+ case BUILT_IN_STPCPY:
+ if (builtin_decl_explicit_p (fncode))
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ break;
+ }
+ }
}
DECL_RESULT (newdecl) = DECL_RESULT (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. */
+ /* Likewise for DECL_ALIGN, DECL_USER_ALIGN and DECL_PACKED. */
+ if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
+ {
+ DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+ DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
+ }
DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl);
if (TREE_CODE (newdecl) == FIELD_DECL)
DECL_PACKED (olddecl) = DECL_PACKED (newdecl);
tree new_decls, old_decls = (b == level ? names : NULL_TREE);
for (new_decls = b->names; new_decls != old_decls;
- new_decls = DECL_CHAIN (new_decls))
+ new_decls = (DECL_P (new_decls) ? DECL_CHAIN (new_decls)
+ : TREE_CHAIN (new_decls)))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
define_label (location_t location, tree name)
{
tree ret;
- timevar_start (TV_NAME_LOOKUP);
+ bool running = timevar_cond_start (TV_NAME_LOOKUP);
ret = define_label_1 (location, name);
- timevar_stop (TV_NAME_LOOKUP);
+ timevar_cond_stop (TV_NAME_LOOKUP, running);
return ret;
}
if (!t)
{
if (complain & tf_error)
- error (want_template ? "no class template named %q#T in %q#T"
- : "no type named %q#T in %q#T", name, context);
+ error (want_template ? G_("no class template named %q#T in %q#T")
+ : G_("no type named %q#T in %q#T"), name, context);
return error_mark_node;
}
return error_mark_node;
}
- if (want_template && !DECL_CLASS_TEMPLATE_P (t))
+ if (want_template && !DECL_TYPE_TEMPLATE_P (t))
{
if (complain & tf_error)
error ("%<typename %T::%D%> names %q#T, which is not a class template",
if (tmpl && TREE_CODE (tmpl) == TYPE_DECL)
tmpl = maybe_get_template_decl_from_type_decl (tmpl);
- if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+ if (!tmpl || !DECL_TYPE_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
error ("no class template named %q#T in %q#T", name, context);
current_lang_name = lang_name_cplusplus;
{
- tree newattrs;
+ tree newattrs, extvisattr;
tree newtype, deltype;
tree ptr_ftype_sizetype;
tree new_eh_spec;
/* Ensure attribs.c is initialized. */
init_attributes ();
- newattrs
- = build_tree_list (get_identifier ("alloc_size"),
- build_tree_list (NULL_TREE, integer_one_node));
+ extvisattr = build_tree_list (get_identifier ("externally_visible"),
+ NULL_TREE);
+ newattrs = tree_cons (get_identifier ("alloc_size"),
+ build_tree_list (NULL_TREE, integer_one_node),
+ extvisattr);
newtype = cp_build_type_attribute_variant (ptr_ftype_sizetype, newattrs);
newtype = build_exception_variant (newtype, new_eh_spec);
- deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
+ deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
+ deltype = build_exception_variant (deltype, 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);
operator_code,
type);
pushdecl (fn);
+ if (flag_tm)
+ apply_tm_attr (fn, get_identifier ("transaction_safe"));
return fn;
}
error_p = true;
if (declared_type == NULL_TREE && ! saw_friend && !error_p)
permerror (input_location, "declaration does not declare anything");
+ else if (declared_type != NULL_TREE && type_uses_auto (declared_type))
+ {
+ error ("%<auto%> can only be specified for variables "
+ "or function declarations");
+ return error_mark_node;
+ }
/* Check for an anonymous union. */
else if (declared_type && RECORD_OR_UNION_CODE_P (TREE_CODE (declared_type))
&& TYPE_ANONYMOUS_P (declared_type))
error ("%<constexpr%> cannot be used for type declarations");
}
+ if (declspecs->attributes && declared_type)
+ {
+ location_t loc = input_location;
+ if (!CLASS_TYPE_P (declared_type)
+ || !CLASSTYPE_TEMPLATE_INSTANTIATION (declared_type))
+ /* For a non-template class, use the name location; for a template
+ class (an explicit instantiation), use the current location. */
+ input_location = location_of (declared_type);
+ warning (0, "attribute ignored in declaration of %q#T", declared_type);
+ warning (0, "attribute for %q#T must follow the %qs keyword",
+ declared_type, class_key_or_enum_as_string (declared_type));
+ input_location = loc;
+ }
+
return declared_type;
}
if (!t)
return NULL_TREE;
- if (declspecs->attributes)
- {
- warning (0, "attribute ignored in declaration of %q+#T", t);
- warning (0, "attribute for %q+#T must follow the %qs keyword",
- t, class_key_or_enum_as_string (t));
-
- }
-
if (maybe_process_partial_specialization (t) == error_mark_node)
return NULL_TREE;
deleted function, but 0 (SD_UNINITIALIZED) if this is a variable
implicitly initialized via a default constructor. ATTRIBUTES and
PREFIX_ATTRIBUTES are GNU attributes associated with this declaration.
- *PUSHED_SCOPE_P is set to the scope entered in this function, if any; if
- set, the caller is responsible for calling pop_scope. */
+
+ The scope represented by the context of the returned DECL is pushed
+ (if it is not the global namespace) and is assigned to
+ *PUSHED_SCOPE_P. The caller is then responsible for calling
+ pop_scope on *PUSHED_SCOPE_P if it is set. */
tree
start_decl (const cp_declarator *declarator,
}
/* If #pragma weak was used, mark the decl weak now. */
- maybe_apply_pragma_weak (decl);
+ if (!processing_template_decl)
+ maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
Quotes on semantics can be found in ARM 8.4.3. */
static tree
-grok_reference_init (tree decl, tree type, tree init, tree *cleanup,
- int flags)
+grok_reference_init (tree decl, tree type, tree init, int flags)
{
- tree tmp;
-
if (init == NULL_TREE)
{
if ((DECL_LANG_SPECIFIC (decl) == 0
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, flags,
- tf_warning_or_error);
- if (DECL_DECLARED_CONSTEXPR_P (decl))
- {
- tmp = cxx_constant_value (tmp);
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
- = reduced_constant_expression_p (tmp);
- }
-
- if (tmp == error_mark_node)
- return NULL_TREE;
- else if (tmp == NULL_TREE)
- {
- error ("cannot initialize %qT from %qT", type, TREE_TYPE (init));
- return NULL_TREE;
- }
-
- if (TREE_STATIC (decl) && !TREE_CONSTANT (tmp))
- return tmp;
-
- DECL_INITIAL (decl) = tmp;
-
- return NULL_TREE;
-}
-
-/* Subroutine of check_initializer. We're initializing a DECL of
- std::initializer_list<T> TYPE from a braced-init-list INIT, and need to
- extend the lifetime of the underlying array to match that of the decl,
- just like for reference initialization. CLEANUP is as for
- grok_reference_init. */
-
-static tree
-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);
- if (error_operand_p (init))
- return error_mark_node;
-
- aggr_init = TARGET_EXPR_INITIAL (init);
- array = CONSTRUCTOR_ELT (aggr_init, 0)->value;
- arrtype = TREE_TYPE (array);
- STRIP_NOPS (array);
- gcc_assert (TREE_CODE (array) == ADDR_EXPR);
- array = TREE_OPERAND (array, 0);
- /* If the array is constant, finish_compound_literal already made it a
- static variable and we don't need to do anything here. */
- if (decl && TREE_CODE (array) == TARGET_EXPR)
- {
- tree var = set_up_extended_ref_temp (decl, array, cleanup, array_init);
- var = build_address (var);
- var = convert (arrtype, var);
- CONSTRUCTOR_ELT (aggr_init, 0)->value = var;
- }
- return init;
+ return initialize_reference (type, init, flags,
+ tf_warning_or_error);
}
/* Designated initializers in arrays are not supported in GNU C++.
/* Handle designated initializers, as an extension. */
if (d->cur->index)
{
+ if (TREE_CODE (d->cur->index) == INTEGER_CST)
+ {
+ if (complain & tf_error)
+ error ("%<[%E] =%> used in a GNU-style designated initializer"
+ " for class %qT", d->cur->index, type);
+ return error_mark_node;
+ }
+
field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
if (!field || TREE_CODE (field) != FIELD_DECL)
return new_init;
}
+/* Subroutine of reshape_init_r. We're in a context where C99 initializer
+ designators are not valid; either complain or return true to indicate
+ that reshape_init_r should return error_mark_node. */
+
+static bool
+has_designator_problem (reshape_iter *d, tsubst_flags_t complain)
+{
+ if (d->cur->index)
+ {
+ if (complain & tf_error)
+ error ("C99 designator %qE outside aggregate initializer",
+ d->cur->index);
+ else
+ return true;
+ }
+ return false;
+}
+
/* Subroutine of reshape_init, which processes a single initializer (part of
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.
if (error_operand_p (init))
return error_mark_node;
+ if (first_initializer_p && !CP_AGGREGATE_TYPE_P (type)
+ && has_designator_problem (d, complain))
+ return error_mark_node;
+
if (TREE_CODE (type) == COMPLEX_TYPE)
{
/* A complex type can be initialized from one or two initializers,
VEC(constructor_elt, gc) *v = 0;
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, d->cur->value);
+ if (has_designator_problem (d, complain))
+ return error_mark_node;
d->cur++;
init = build_constructor (init_list_type_node, v);
}
array types (one value per array element). */
if (TREE_CODE (str_init) == STRING_CST)
{
+ if (has_designator_problem (d, complain))
+ return error_mark_node;
d->cur++;
return str_init;
}
build_aggr_init_full_exprs (tree decl, tree init, int flags)
{
- int saved_stmts_are_full_exprs_p = 0;
- if (building_stmt_list_p ())
- {
- saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
- current_stmt_tree ()->stmts_are_full_exprs_p = 1;
- }
- init = build_aggr_init (decl, init, flags, tf_warning_or_error);
- if (building_stmt_list_p ())
- current_stmt_tree ()->stmts_are_full_exprs_p =
- saved_stmts_are_full_exprs_p;
- return init;
+ gcc_assert (stmts_are_full_exprs_p ());
+ return build_aggr_init (decl, init, flags, tf_warning_or_error);
}
/* Verify INIT (the initializer for DECL), and record the
evaluated dynamically to initialize DECL. */
static tree
-check_initializer (tree decl, tree init, int flags, tree *cleanup)
+check_initializer (tree decl, tree init, int flags, VEC(tree,gc) **cleanups)
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
}
else if (!COMPLETE_TYPE_P (type))
{
- error ("%qD has incomplete type", decl);
+ error ("%q#D has incomplete type", decl);
TREE_TYPE (decl) = error_mark_node;
return NULL_TREE;
}
}
else if (!init && DECL_REALLY_EXTERN (decl))
;
- else if (TREE_CODE (type) == REFERENCE_TYPE)
- init = grok_reference_init (decl, type, init, cleanup, flags);
- else if (init || type_build_ctor_call (type))
+ else if (init || type_build_ctor_call (type)
+ || TREE_CODE (type) == REFERENCE_TYPE)
{
- if (!init)
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ init = grok_reference_init (decl, type, init, flags);
+ flags |= LOOKUP_ALREADY_DIGESTED;
+ }
+ else if (!init)
check_for_uninitialized_const_var (decl);
/* Do not reshape constructors of vectors (they don't need to be
reshaped. */
else if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (is_std_init_list (type))
- init = build_init_list_var_init (decl, type, init,
- &extra_init, cleanup);
+ {
+ init = perform_implicit_conversion (type, init,
+ tf_warning_or_error);
+ flags |= LOOKUP_ALREADY_DIGESTED;
+ }
else if (TYPE_NON_AGGREGATE_CLASS (type))
{
/* Don't reshape if the class has constructors. */
else
{
init = reshape_init (type, init, tf_warning_or_error);
- if (cxx_dialect >= cxx0x && SCALAR_TYPE_P (type))
+ if (SCALAR_TYPE_P (type))
check_narrowing (type, init);
}
}
if (type == error_mark_node)
return NULL_TREE;
- if (type_build_ctor_call (type)
- || (CLASS_TYPE_P (type)
- && !(init && BRACE_ENCLOSED_INITIALIZER_P (init))))
+ if ((type_build_ctor_call (type) || CLASS_TYPE_P (type))
+ && !(flags & LOOKUP_ALREADY_DIGESTED)
+ && !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
+ && CP_AGGREGATE_TYPE_P (type)))
{
init_code = build_aggr_init_full_exprs (decl, init, flags);
if (init && TREE_CODE (init) != TREE_VEC)
{
- init_code = store_init_value (decl, init, flags);
+ /* In aggregate initialization of a variable, each element
+ initialization is a full-expression because there is no
+ enclosing expression. */
+ gcc_assert (stmts_are_full_exprs_p ());
+
+ init_code = store_init_value (decl, init, cleanups, flags);
+
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
static tree
wrap_cleanups_r (tree *stmt_p, int *walk_subtrees, void *data)
{
- if (TYPE_P (*stmt_p))
+ /* Stop at types or full-expression boundaries. */
+ if (TYPE_P (*stmt_p)
+ || TREE_CODE (*stmt_p) == CLEANUP_POINT_EXPR)
{
*walk_subtrees = 0;
return NULL_TREE;
tree asmspec_tree, int flags)
{
tree type;
- tree cleanup;
+ VEC(tree,gc) *cleanups = NULL;
const char *asmspec = NULL;
int was_readonly = 0;
bool var_definition_p = false;
if (type == error_mark_node)
return;
- /* Assume no cleanup is required. */
- cleanup = NULL_TREE;
-
/* If a name was specified, get the string. */
if (at_namespace_scope_p ())
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
/* This variable seems to be a non-dependent constant, so process
its initializer. If check_initializer returns non-null the
initialization wasn't constant after all. */
- tree init_code = check_initializer (decl, init, flags, &cleanup);
+ tree init_code;
+ cleanups = make_tree_vector ();
+ init_code = check_initializer (decl, init, flags, &cleanups);
if (init_code == NULL_TREE)
init = NULL_TREE;
+ release_tree_vector (cleanups);
}
else if (!DECL_PRETTY_FUNCTION_P (decl))
/* Deduce array size even if the initializer is dependent. */
error ("Java object %qD not allocated with %<new%>", decl);
init = NULL_TREE;
}
- init = check_initializer (decl, init, flags, &cleanup);
+ cleanups = make_tree_vector ();
+ init = check_initializer (decl, init, flags, &cleanups);
/* Thread-local storage cannot be dynamically initialized. */
if (DECL_THREAD_LOCAL_P (decl) && init)
{
/* If a CLEANUP_STMT was created to destroy a temporary bound to a
reference, insert it in the statement-tree now. */
- if (cleanup)
- push_cleanup (decl, cleanup, false);
+ if (cleanups)
+ {
+ unsigned i; tree t;
+ FOR_EACH_VEC_ELT (tree, cleanups, i, t)
+ push_cleanup (decl, t, false);
+ release_tree_vector (cleanups);
+ }
if (was_readonly)
TREE_READONLY (decl) = 1;
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))
&& !grok_op_properties (decl, /*complain=*/true))
return NULL_TREE;
+ else if (UDLIT_OPER_P (DECL_NAME (decl)))
+ {
+ bool long_long_unsigned_p;
+ bool long_double_p;
+ const char *suffix = NULL;
+ /* [over.literal]/6: Literal operators shall not have C linkage. */
+ if (DECL_LANGUAGE (decl) == lang_c)
+ {
+ error ("literal operator with C linkage");
+ return NULL_TREE;
+ }
+
+ if (DECL_NAMESPACE_SCOPE_P (decl))
+ {
+ if (!check_literal_operator_args (decl, &long_long_unsigned_p,
+ &long_double_p))
+ {
+ error ("%qD has invalid argument list", decl);
+ return NULL_TREE;
+ }
+
+ suffix = UDLIT_OP_SUFFIX (DECL_NAME (decl));
+ if (long_long_unsigned_p)
+ {
+ if (cpp_interpret_int_suffix (suffix, strlen (suffix)))
+ warning (0, "integer suffix %<%s%>"
+ " shadowed by implementation", suffix);
+ }
+ else if (long_double_p)
+ {
+ if (cpp_interpret_float_suffix (suffix, strlen (suffix)))
+ warning (0, "floating point suffix %<%s%>"
+ " shadowed by implementation", suffix);
+ }
+ }
+ else
+ {
+ error ("%qD must be a non-member function", decl);
+ return NULL_TREE;
+ }
+ }
if (funcdef_flag)
/* Make the init_value nonzero so pushdecl knows this is not
error ("definition of implicitly-declared %qD", old_decl);
return NULL_TREE;
}
+ else if (DECL_DEFAULTED_FN (old_decl))
+ {
+ error ("definition of explicitly-defaulted %q+D", decl);
+ error ("%q+#D explicitly defaulted here", old_decl);
+ return NULL_TREE;
+ }
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
return 0;
else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
- if (literal_type_p (type))
+ if (!COMPLETE_TYPE_P (type))
+ error ("in-class initialization of static data member %q#D of "
+ "incomplete type", decl);
+ else if (literal_type_p (type))
permerror (input_location,
"%<constexpr%> needed for in-class initialization of "
"static data member %q#D of non-integral type", decl);
return error_mark_node;
}
+ if (dname
+ && TREE_CODE (dname) == IDENTIFIER_NODE
+ && UDLIT_OPER_P (dname)
+ && innermost_code != cdk_function)
+ {
+ error ("declaration of %qD as non-function", dname);
+ return error_mark_node;
+ }
+
if (dname && IDENTIFIER_OPNAME_P (dname))
{
if (declspecs->specs[(int)ds_typedef])
if (!declarator->u.function.late_return_type)
{
error ("%qs function uses %<auto%> type specifier without"
- " late return type", name);
+ " trailing return type", name);
return error_mark_node;
}
else if (!is_auto (type))
{
- error ("%qs function with late return type has"
+ error ("%qs function with trailing 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);
+ if (cxx_dialect < cxx0x)
+ /* Not using maybe_warn_cpp0x because this should
+ always be an error. */
+ error ("trailing return type only available with "
+ "-std=c++11 or -std=gnu++11");
+ else
+ error ("%qs function with trailing return type not "
+ "declared with %<auto%> type specifier", name);
return error_mark_node;
}
}
virtual. A constructor may not be static. */
if (staticp == 2)
error ((flags == DTOR_FLAG)
- ? "destructor cannot be static member function"
- : "constructor cannot be static member function");
+ ? G_("destructor cannot be static member function")
+ : G_("constructor cannot be static member function"));
if (memfn_quals)
{
error ((flags == DTOR_FLAG)
- ? "destructors may not be cv-qualified"
- : "constructors may not be cv-qualified");
+ ? G_("destructors may not be cv-qualified")
+ : G_("constructors may not be cv-qualified"));
memfn_quals = TYPE_UNQUALIFIED;
}
&& (!friendp || funcdef_flag))
{
error (funcdef_flag
- ? "cannot define member function %<%T::%s%> within %<%T%>"
- : "cannot declare member function %<%T::%s%> within %<%T%>",
+ ? G_("cannot define member function %<%T::%s%> "
+ "within %<%T%>")
+ : G_("cannot declare member function %<%T::%s%> "
+ "within %<%T%>"),
ctype, name, current_class_type);
return error_mark_node;
}
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
+ if (declspecs->specs[(int)ds_alias])
+ /* Acknowledge that this was written:
+ `using analias = atype;'. */
+ TYPE_DECL_ALIAS_P (decl) = 1;
+
return decl;
}
}
else if (decl_context == FIELD)
{
+ if (!staticp && type_uses_auto (type))
+ {
+ error ("non-static data member declared %<auto%>");
+ type = error_mark_node;
+ }
+
/* The C99 flexible array extension. */
if (!staticp && TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
}
if (initialized)
- /* An attempt is being made to initialize a non-static
- member. This is new in C++11. */
- maybe_warn_cpp0x (CPP0X_NSDMI);
+ {
+ /* An attempt is being made to initialize a non-static
+ member. This is new in C++11. */
+ maybe_warn_cpp0x (CPP0X_NSDMI);
+
+ /* If this has been parsed with static storage class, but
+ errors forced staticp to be cleared, ensure NSDMI is
+ not present. */
+ if (declspecs->storage_class == sc_static)
+ DECL_INITIAL (decl) = error_mark_node;
+ }
}
bad_specifiers (decl, BSP_FIELD, virtualp,
|| sfk == sfk_destructor)
{
error (funcdef_flag
- ? "%qs defined in a non-class scope"
- : "%qs declared in a non-class scope", name);
+ ? G_("%qs defined in a non-class scope")
+ : G_("%qs declared in a non-class scope"), name);
sfk = sfk_none;
}
}
local_variable_p_walkfn (tree *tp, int *walk_subtrees,
void *data ATTRIBUTE_UNUSED)
{
- if (local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
+ /* Check DECL_NAME to avoid including temporaries. We don't check
+ DECL_ARTIFICIAL because we do want to complain about 'this'. */
+ if (local_variable_p (*tp) && DECL_NAME (*tp))
return *tp;
else if (TYPE_P (*tp))
*walk_subtrees = 0;
return NULL_TREE;
}
-
/* Check that ARG, which is a default-argument expression for a
parameter DECL, is valid. Returns ARG, or ERROR_MARK_NODE, if
something goes wrong. DECL may also be a _TYPE node, rather than a
return error_mark_node;
}
+ if (warn_zero_as_null_pointer_constant
+ && c_inhibit_evaluation_warnings == 0
+ && (POINTER_TYPE_P (decl_type) || TYPE_PTR_TO_MEMBER_P (decl_type))
+ && null_ptr_cst_p (arg)
+ && !NULLPTR_TYPE_P (TREE_TYPE (arg)))
+ {
+ warning (OPT_Wzero_as_null_pointer_constant,
+ "zero as null pointer constant");
+ return nullptr_node;
+ }
+
/* [dcl.fct.default]
Local variables shall not be used in default argument
var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
if (var)
{
- error ("default argument %qE uses local variable %qD", arg, var);
+ if (DECL_NAME (var) == this_identifier)
+ permerror (input_location, "default argument %qE uses %qD", arg, var);
+ else
+ error ("default argument %qE uses local variable %qD", arg, var);
return error_mark_node;
}
{
tree type;
+ if (decl == error_mark_node)
+ return error_mark_node;
+
/* In the case of:
struct S { struct S *p; };
type, tag_name (tag_code));
return error_mark_node;
}
+ /* Accept bound template template parameters. */
+ else if (allow_template_p
+ && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ ;
/* [dcl.type.elab]
- If the identifier resolves to a typedef-name or a template
- type-parameter, the elaborated-type-specifier is ill-formed.
+ If the identifier resolves to a typedef-name or the
+ simple-template-id resolves to an alias template
+ specialization, the elaborated-type-specifier is ill-formed.
In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when
&& !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type)
{
- error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
- error ("%q+D has a previous declaration here", decl);
+ if (alias_template_specialization_p (type))
+ error ("using alias template specialization %qT after %qs",
+ type, tag_name (tag_code));
+ else
+ error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
+ inform (DECL_SOURCE_LOCATION (decl),
+ "%qD has a previous declaration here", decl);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
TYPE_FOR_JAVA (ref) = 1;
base_binfo = NULL_TREE;
- if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
+ if (CLASS_TYPE_P (basetype) && !dependent_scope_p (basetype))
{
base_binfo = TYPE_BINFO (basetype);
/* The original basetype could have been a typedef'd type. */
BINFO_BASE_ACCESS_APPEND (binfo, access);
}
- if (VEC_space (tree, CLASSTYPE_VBASECLASSES (ref), 1))
- /* If we have space in the vbase vector, we must have shared at
+ if (VEC_length (tree, CLASSTYPE_VBASECLASSES (ref)) < max_vbases)
+ /* If we didn't get max_vbases vbases, we must have shared at
least one of them, and are therefore diamond shaped. */
CLASSTYPE_DIAMOND_SHAPED_P (ref) = 1;
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);
+ tree t;
+ for (t = dst; t; t = TYPE_NEXT_VARIANT (t))
+ {
+ TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (src);
+ TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (src);
+ TYPE_SIZE (t) = TYPE_SIZE (src);
+ TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (src);
+ SET_TYPE_MODE (dst, TYPE_MODE (src));
+ TYPE_PRECISION (t) = TYPE_PRECISION (src);
+ TYPE_ALIGN (t) = TYPE_ALIGN (src);
+ TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (src);
+ TYPE_UNSIGNED (t) = TYPE_UNSIGNED (src);
+ }
}
/* Begin compiling the definition of an enumeration type.
*is_new = true;
}
prevtype = enumtype;
- enumtype = cxx_make_type (ENUMERAL_TYPE);
- enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
+
+ /* Do not push the decl more than once, unless we need to
+ compare underlying types at instantiation time */
+ if (!enumtype
+ || TREE_CODE (enumtype) != ENUMERAL_TYPE
+ || (underlying_type
+ && dependent_type_p (underlying_type))
+ || (ENUM_UNDERLYING_TYPE (enumtype)
+ && dependent_type_p (ENUM_UNDERLYING_TYPE (enumtype))))
+ {
+ enumtype = cxx_make_type (ENUMERAL_TYPE);
+ enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
+ }
+ else
+ enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current,
+ false);
+
if (enumtype == error_mark_node)
return error_mark_node;
return;
}
- /* Here there should not be any variants of this type. */
+ /* If this is a forward declaration, there should not be any variants,
+ though we can get a variant in the middle of an enum-specifier with
+ wacky code like 'enum E { e = sizeof(const E*) };' */
gcc_assert (enumtype == TYPE_MAIN_VARIANT (enumtype)
- && !TYPE_NEXT_VARIANT (enumtype));
+ && (TYPE_VALUES (enumtype)
+ || !TYPE_NEXT_VARIANT (enumtype)));
}
/* Build and install a CONST_DECL for an enumeration constant of the
{
value = cxx_constant_value (value);
- if (TREE_CODE (value) == INTEGER_CST
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)))
+ if (TREE_CODE (value) != INTEGER_CST
+ || ! INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)))
{
- value = perform_integral_promotions (value);
- }
- else
- {
- error ("enumerator value for %qD is not an integer constant", name);
+ error ("enumerator value for %qD is not an integer constant",
+ name);
value = NULL_TREE;
}
}
f->base.x_stmt_tree.x_cur_stmt_list = NULL;
f->bindings = NULL;
f->x_local_names = NULL;
+ f->base.local_typedefs = NULL;
}
cleanup = call;
}
+ /* build_delete sets the location of the destructor call to the
+ current location, even though the destructor is going to be
+ called later, at the end of the current scope. This can lead to
+ a "jumpy" behaviour for users of debuggers when they step around
+ the end of the block. So let's unset the location of the
+ destructor call instead. */
+ if (cleanup != NULL && EXPR_P (cleanup))
+ SET_EXPR_LOCATION (cleanup, UNKNOWN_LOCATION);
return cleanup;
}
+
\f
/* When a stmt has been parsed, this function is called. */
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO;
+ case USERDEF_LITERAL: return TS_CP_USERDEF_LITERAL;
default: return TS_CP_GENERIC;
}
}