aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/typeck2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/typeck2.c')
-rw-r--r--gcc/cp/typeck2.c162
1 files changed, 74 insertions, 88 deletions
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e4d7e3eb0a2..750aa3c94bf 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -182,24 +182,30 @@ abstract_virtuals_error (decl, type)
/* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known)
- and TYPE is the type that was invalid. If WARN_ONLY is nonzero, a
- warning is printed, otherwise an error is printed. */
+ and TYPE is the type that was invalid. DIAG_TYPE indicates the
+ type of diagnostic: 0 for an error, 1 for a warning, 2 for a
+ pedwarn. */
void
-cxx_incomplete_type_diagnostic (value, type, warn_only)
+cxx_incomplete_type_diagnostic (value, type, diag_type)
tree value;
tree type;
- int warn_only;
+ int diag_type;
{
int decl = 0;
void (*p_msg) PARAMS ((const char *, ...));
void (*p_msg_at) PARAMS ((const char *, ...));
- if (warn_only)
+ if (diag_type == 1)
{
p_msg = warning;
p_msg_at = cp_warning_at;
}
+ else if (diag_type == 2)
+ {
+ p_msg = pedwarn;
+ p_msg_at = cp_pedwarn_at;
+ }
else
{
p_msg = error;
@@ -314,12 +320,6 @@ store_init_value (decl, init)
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
-#if 0
- /* This breaks arrays, and should not have any effect for other decls. */
- /* Take care of C++ business up here. */
- type = TYPE_MAIN_VARIANT (type);
-#endif
-
if (IS_AGGR_TYPE (type))
{
if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
@@ -331,35 +331,6 @@ store_init_value (decl, init)
error ("constructor syntax used, but no constructor declared for type `%T'", type);
init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
}
-#if 0
- if (TREE_CODE (init) == CONSTRUCTOR)
- {
- tree field;
-
- /* Check that we're really an aggregate as ARM 8.4.1 defines it. */
- if (CLASSTYPE_N_BASECLASSES (type))
- cp_error_at ("initializer list construction invalid for derived class object `%D'", decl);
- if (CLASSTYPE_VTBL_PTR (type))
- cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl);
- if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- error ("due to the presence of a constructor");
- }
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
- for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
- if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
- }
-#endif
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_TYPE (init) != unknown_type_node)
@@ -396,15 +367,8 @@ store_init_value (decl, init)
/* End of special C++ code. */
- /* We might have already run this bracketed initializer through
- digest_init. Don't do so again. */
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)
- && TREE_TYPE (init)
- && TYPE_MAIN_VARIANT (TREE_TYPE (init)) == TYPE_MAIN_VARIANT (type))
- value = init;
- else
- /* Digest the specified initializer into an expression. */
- value = digest_init (type, init, (tree *) 0);
+ /* Digest the specified initializer into an expression. */
+ value = digest_init (type, init, (tree *) 0);
/* Store the expression if valid; else report error. */
@@ -451,27 +415,6 @@ store_init_value (decl, init)
return NULL_TREE;
}
-/* Same as store_init_value, but used for known-to-be-valid static
- initializers. Used to introduce a static initializer even in data
- structures that may require dynamic initialization. */
-
-tree
-force_store_init_value (decl, init)
- tree decl, init;
-{
- tree type = TREE_TYPE (decl);
- int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type);
-
- TYPE_NEEDS_CONSTRUCTING (type) = 0;
-
- init = store_init_value (decl, init);
- if (init)
- abort ();
-
- TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing;
-
- return init;
-}
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
@@ -489,8 +432,7 @@ digest_init (type, init, tail)
enum tree_code code = TREE_CODE (type);
tree element = NULL_TREE;
tree old_tail_contents = NULL_TREE;
- /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
- tree node which has no TREE_TYPE. */
+ /* Nonzero if INIT is a braced grouping. */
int raw_constructor;
/* By default, assume we use one element from a list.
@@ -508,7 +450,7 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == ERROR_MARK)
/* __PRETTY_FUNCTION__'s initializer is a bogus expression inside
- a template function. This gets substituted during instantiation. */
+ a template function. This gets substituted during instantiation. */
return init;
/* We must strip the outermost array type when completing the type,
@@ -521,10 +463,8 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type)
- return init;
-
- raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
+ raw_constructor = (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init));
if (raw_constructor
&& CONSTRUCTOR_ELTS (init) != 0
@@ -785,7 +725,8 @@ process_init_constructor (type, init, elts)
next1 = digest_init (TREE_TYPE (type), next1, 0);
}
else if (! zero_init_p (TREE_TYPE (type)))
- next1 = build_forced_zero_init (TREE_TYPE (type));
+ next1 = build_zero_init (TREE_TYPE (type),
+ /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -834,7 +775,7 @@ process_init_constructor (type, init, elts)
continue;
}
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (tail)
@@ -889,8 +830,7 @@ process_init_constructor (type, init, elts)
{
if (TREE_READONLY (field))
error ("uninitialized const member `%D'", field);
- else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
- && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
+ else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
error ("member `%D' with uninitialized const fields",
field);
else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
@@ -903,7 +843,8 @@ process_init_constructor (type, init, elts)
warning ("missing initializer for member `%D'", field);
if (! zero_init_p (TREE_TYPE (field)))
- next1 = build_forced_zero_init (TREE_TYPE (field));
+ next1 = build_zero_init (TREE_TYPE (field),
+ /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -927,8 +868,7 @@ process_init_constructor (type, init, elts)
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
- while (field && (DECL_NAME (field) == 0
- || TREE_CODE (field) != FIELD_DECL))
+ while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */
@@ -1002,6 +942,8 @@ process_init_constructor (type, init, elts)
return error_mark_node;
result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members));
+ if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE)
+ complete_array_type (type, result, /*do_default=*/0);
if (init)
TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init);
if (allconstant) TREE_CONSTANT (result) = 1;
@@ -1345,6 +1287,7 @@ add_exception_specifier (list, spec, complain)
int ok;
tree core = spec;
int is_ptr;
+ int diag_type = -1; /* none */
if (spec == error_mark_node)
return list;
@@ -1366,7 +1309,15 @@ add_exception_specifier (list, spec, complain)
else if (processing_template_decl)
ok = 1;
else
- ok = COMPLETE_TYPE_P (complete_type (core));
+ {
+ ok = 1;
+ /* 15.4/1 says that types in an exception specifier must be complete,
+ but it seems more reasonable to only require this on definitions
+ and calls. So just give a pedwarn at this point; we will give an
+ error later if we hit one of those two cases. */
+ if (!COMPLETE_TYPE_P (complete_type (core)))
+ diag_type = 2; /* pedwarn */
+ }
if (ok)
{
@@ -1378,13 +1329,17 @@ add_exception_specifier (list, spec, complain)
if (!probe)
list = tree_cons (NULL_TREE, spec, list);
}
- else if (complain)
- cxx_incomplete_type_error (NULL_TREE, core);
+ else
+ diag_type = 0; /* error */
+
+ if (diag_type >= 0 && complain)
+ cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
+
return list;
}
/* Combine the two exceptions specifier lists LIST and ADD, and return
- their union. */
+ their union. */
tree
merge_exception_specifiers (list, add)
@@ -1418,3 +1373,34 @@ merge_exception_specifiers (list, add)
}
return list;
}
+
+/* Subroutine of build_call. Ensure that each of the types in the
+ exception specification is complete. Technically, 15.4/1 says that
+ they need to be complete when we see a declaration of the function,
+ but we should be able to get away with only requiring this when the
+ function is defined or called. See also add_exception_specifier. */
+
+void
+require_complete_eh_spec_types (fntype, decl)
+ tree fntype, decl;
+{
+ tree raises;
+ /* Don't complain about calls to op new. */
+ if (decl && DECL_ARTIFICIAL (decl))
+ return;
+ for (raises = TYPE_RAISES_EXCEPTIONS (fntype); raises;
+ raises = TREE_CHAIN (raises))
+ {
+ tree type = TREE_VALUE (raises);
+ if (type && !COMPLETE_TYPE_P (type))
+ {
+ if (decl)
+ error
+ ("call to function `%D' which throws incomplete type `%#T'",
+ decl, type);
+ else
+ error ("call to function which throws incomplete type `%#T'",
+ decl);
+ }
+ }
+}