aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-03-16 22:36:55 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-03-16 22:36:55 -0400
commit2df663ccedf750ffe5ac481b3fe2aaff0d985a7f (patch)
treeeffd0899444bec8cd82684550c9fc410b899aa0a /gcc/cp
parent95ffad49d5499e3de6fcd0d261fa3870755995c2 (diff)
downloadgcc-2df663ccedf750ffe5ac481b3fe2aaff0d985a7f.zip
gcc-2df663ccedf750ffe5ac481b3fe2aaff0d985a7f.tar.gz
gcc-2df663ccedf750ffe5ac481b3fe2aaff0d985a7f.tar.bz2
cp-tree.h (abstract_class_use): New enum.
* cp-tree.h (abstract_class_use): New enum. * typeck2.c (pending_abstract_type): Add use field. (abstract_virtuals_error_sfinae): Add overloads taking abstract_class_use instead of tree. * typeck.c (build_static_cast_1): Call it. * except.c (is_admissible_throw_operand_or_catch_parameter): Call it. * pt.c: Adjust calls. * decl.c (cp_finish_decl): Don't handle functions specially. (grokdeclarator): Always check return type. * init.c (build_new_1): Adjust call. From-SVN: r196735
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h15
-rw-r--r--gcc/cp/decl.c17
-rw-r--r--gcc/cp/except.c12
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/cp/typeck.c6
-rw-r--r--gcc/cp/typeck2.c84
8 files changed, 114 insertions, 39 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 20414dc..b57800e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
2013-03-16 Jason Merrill <jason@redhat.com>
+ * cp-tree.h (abstract_class_use): New enum.
+ * typeck2.c (pending_abstract_type): Add use field.
+ (abstract_virtuals_error_sfinae): Add overloads taking
+ abstract_class_use instead of tree.
+ * typeck.c (build_static_cast_1): Call it.
+ * except.c (is_admissible_throw_operand_or_catch_parameter): Call it.
+ * pt.c: Adjust calls.
+ * decl.c (cp_finish_decl): Don't handle functions specially.
+ (grokdeclarator): Always check return type.
+ * init.c (build_new_1): Adjust call.
+
DR 337
PR c++/17232
* pt.c (tsubst) [ARRAY_TYPE]: Use abstract_virtuals_error_sfinae.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d9496d2..53940a6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -463,6 +463,19 @@ typedef enum impl_conv_void {
ICV_THIRD_IN_FOR /* for increment expression */
} impl_conv_void;
+/* Possible invalid uses of an abstract class that might not have a
+ specific associated declaration. */
+typedef enum abstract_class_use {
+ ACU_UNKNOWN, /* unknown or decl provided */
+ ACU_CAST, /* cast to abstract class */
+ ACU_NEW, /* new-expression of abstract class */
+ ACU_THROW, /* throw-expression of abstract class */
+ ACU_CATCH, /* catch-parameter of abstract class */
+ ACU_ARRAY, /* array of abstract class */
+ ACU_RETURN, /* return type of abstract class */
+ ACU_PARM /* parameter type of abstract class */
+} abstract_class_use;
+
/* Macros for access to language-specific slots in an identifier. */
#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \
@@ -5983,7 +5996,9 @@ extern tree binfo_or_else (tree, tree);
extern void cxx_readonly_error (tree, enum lvalue_use);
extern void complete_type_check_abstract (tree);
extern int abstract_virtuals_error (tree, tree);
+extern int abstract_virtuals_error (abstract_class_use, tree);
extern int abstract_virtuals_error_sfinae (tree, tree, tsubst_flags_t);
+extern int abstract_virtuals_error_sfinae (abstract_class_use, tree, tsubst_flags_t);
extern tree store_init_value (tree, tree, vec<tree, va_gc>**, int);
extern void check_narrowing (tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0e66840..40152b1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6434,11 +6434,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
/* Check for abstractness of the type. Notice that there is no
need to strip array types here since the check for those types
is already done within create_array_type_for_decl. */
- if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
- abstract_virtuals_error (decl, TREE_TYPE (type));
- else
- abstract_virtuals_error (decl, type);
+ abstract_virtuals_error (decl, type);
if (TREE_TYPE (decl) == error_mark_node)
/* No initialization required. */
@@ -8656,6 +8652,7 @@ grokdeclarator (const cp_declarator *declarator,
bool template_type_arg = false;
bool template_parm_flag = false;
bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr);
+ source_location saved_loc = input_location;
const char *errmsg;
signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
@@ -9340,7 +9337,6 @@ grokdeclarator (const cp_declarator *declarator,
if (declspecs->std_attributes)
{
/* Apply the c++11 attributes to the type preceding them. */
- source_location saved_loc = input_location;
input_location = declspecs->locations[ds_std_attribute];
decl_attributes (&type, declspecs->std_attributes, 0);
input_location = saved_loc;
@@ -9428,11 +9424,10 @@ grokdeclarator (const cp_declarator *declarator,
error ("%qs declared as function returning an array", name);
return error_mark_node;
}
- /* When decl_context == NORMAL we emit a better error message
- later in abstract_virtuals_error. */
- if (decl_context == TYPENAME && ABSTRACT_CLASS_TYPE_P (type))
- error ("%qs declared as function returning an abstract "
- "class type", name);
+
+ input_location = declspecs->locations[ds_type_spec];
+ abstract_virtuals_error (ACU_RETURN, type);
+ input_location = saved_loc;
/* Pick up type qualifiers which should be applied to `this'. */
memfn_quals = declarator->u.function.qualifiers;
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 216ec10..52ba1cd 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -972,16 +972,8 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
/* 10.4/3 An abstract class shall not be used as a parameter type,
as a function return type or as type of an explicit
conversion. */
- else if (ABSTRACT_CLASS_TYPE_P (type))
- {
- if (is_throw)
- error ("expression %qE of abstract class type %qT cannot "
- "be used in throw-expression", expr, type);
- else
- error ("cannot declare catch parameter to be of abstract "
- "class type %qT", type);
- return false;
- }
+ else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type))
+ return false;
else if (!is_throw
&& TREE_CODE (type) == REFERENCE_TYPE
&& TYPE_REF_IS_RVALUE (type))
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 697f11f..679c47d 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2301,7 +2301,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
return error_mark_node;
}
- if (abstract_virtuals_error_sfinae (NULL_TREE, elt_type, complain))
+ if (abstract_virtuals_error_sfinae (ACU_NEW, elt_type, complain))
return error_mark_node;
is_initialized = (type_build_ctor_call (elt_type) || *init != NULL);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ce07fa4..edc2d0b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10851,7 +10851,7 @@ tsubst_arg_types (tree arg_types,
return error_mark_node;
}
/* DR 657. */
- if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
+ if (abstract_virtuals_error_sfinae (ACU_PARM, type, complain))
return error_mark_node;
/* Do array-to-pointer, function-to-pointer conversion, and ignore
@@ -10930,7 +10930,7 @@ tsubst_function_type (tree t,
return error_mark_node;
}
/* And DR 657. */
- if (abstract_virtuals_error_sfinae (NULL_TREE, return_type, complain))
+ if (abstract_virtuals_error_sfinae (ACU_RETURN, return_type, complain))
return error_mark_node;
/* Substitute the argument types. */
@@ -11654,7 +11654,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
}
- if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
+ if (abstract_virtuals_error_sfinae (ACU_ARRAY, type, complain))
return error_mark_node;
r = build_cplus_array_type (type, domain);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 96e0ad8..3ced858 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6238,6 +6238,12 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
if (TREE_CODE (type) == VOID_TYPE)
return convert_to_void (expr, ICV_CAST, complain);
+ /* [class.abstract]
+ An abstract class shall not be used ... as the type of an explicit
+ conversion. */
+ if (abstract_virtuals_error_sfinae (ACU_CAST, type, complain))
+ return error_mark_node;
+
/* [expr.static.cast]
An expression e can be explicitly converted to a type T using a
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index dc17776..3bac67c 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -141,6 +141,9 @@ struct GTY((chain_next ("%h.next"))) pending_abstract_type {
/* Type which will be checked for abstractness. */
tree type;
+ /* Kind of use in an unnamed declarator. */
+ abstract_class_use use;
+
/* Position of the declaration. This is only needed for IDENTIFIER_NODEs,
because DECLs already carry locus information. */
location_t locus;
@@ -181,6 +184,7 @@ pat_compare (const void* val1, const void* val2)
static GTY ((param_is (struct pending_abstract_type)))
htab_t abstract_pending_vars = NULL;
+static int abstract_virtuals_error_sfinae (tree, tree, abstract_class_use, tsubst_flags_t);
/* This function is called after TYPE is completed, and will check if there
are pending declarations for which we still need to verify the abstractness
@@ -231,7 +235,8 @@ complete_type_check_abstract (tree type)
location. Notice that this is only needed if the decl is an
IDENTIFIER_NODE. */
input_location = pat->locus;
- abstract_virtuals_error (pat->decl, pat->type);
+ abstract_virtuals_error_sfinae (pat->decl, pat->type, pat->use,
+ tf_warning_or_error);
pat = pat->next;
}
}
@@ -244,11 +249,13 @@ complete_type_check_abstract (tree type)
/* If TYPE has abstract virtual functions, issue an error about trying
to create an object of that type. DECL is the object declared, or
- NULL_TREE if the declaration is unavailable. Returns 1 if an error
- occurred; zero if all was well. */
+ NULL_TREE if the declaration is unavailable, in which case USE specifies
+ the kind of invalid use. Returns 1 if an error occurred; zero if
+ all was well. */
-int
-abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
+static int
+abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
+ tsubst_flags_t complain)
{
vec<tree, va_gc> *pure;
@@ -284,6 +291,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
pat = ggc_alloc_pending_abstract_type ();
pat->type = type;
pat->decl = decl;
+ pat->use = use;
pat->locus = ((decl && DECL_P (decl))
? DECL_SOURCE_LOCATION (decl)
: input_location);
@@ -312,8 +320,14 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
error ("cannot declare variable %q+D to be of abstract "
"type %qT", decl, type);
else if (TREE_CODE (decl) == PARM_DECL)
- error ("cannot declare parameter %q+D to be of abstract type %qT",
- decl, type);
+ {
+ if (DECL_NAME (decl))
+ error ("cannot declare parameter %q+D to be of abstract type %qT",
+ decl, type);
+ else
+ error ("cannot declare parameter to be of abstract type %qT",
+ type);
+ }
else if (TREE_CODE (decl) == FIELD_DECL)
error ("cannot declare field %q+D to be of abstract type %qT",
decl, type);
@@ -328,8 +342,34 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
else
error ("invalid abstract type for %q+D", decl);
}
- else
- error ("cannot allocate an object of abstract type %qT", type);
+ else switch (use)
+ {
+ case ACU_ARRAY:
+ error ("creating array of %qT, which is an abstract class type", type);
+ break;
+ case ACU_CAST:
+ error ("invalid cast to abstract class type %qT", type);
+ break;
+ case ACU_NEW:
+ error ("invalid new-expression of abstract class type %qT", type);
+ break;
+ case ACU_RETURN:
+ error ("invalid abstract return type %qT", type);
+ break;
+ case ACU_PARM:
+ error ("invalid abstract parameter type %qT", type);
+ break;
+ case ACU_THROW:
+ error ("expression of abstract class type %qT cannot "
+ "be used in throw-expression", type);
+ break;
+ case ACU_CATCH:
+ error ("cannot declare catch parameter to be of abstract "
+ "class type %qT", type);
+ break;
+ default:
+ error ("cannot allocate an object of abstract type %qT", type);
+ }
/* Only go through this once. */
if (pure->length ())
@@ -351,14 +391,24 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
again. */
pure->truncate (0);
}
- else
- inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
- " since type %qT has pure virtual functions",
- type);
return 1;
}
+int
+abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
+{
+ return abstract_virtuals_error_sfinae (decl, type, ACU_UNKNOWN, complain);
+}
+
+int
+abstract_virtuals_error_sfinae (abstract_class_use use, tree type,
+ tsubst_flags_t complain)
+{
+ return abstract_virtuals_error_sfinae (NULL_TREE, type, use, complain);
+}
+
+
/* Wrapper for the above function in the common case of wanting errors. */
int
@@ -367,6 +417,12 @@ abstract_virtuals_error (tree decl, tree type)
return abstract_virtuals_error_sfinae (decl, type, tf_warning_or_error);
}
+int
+abstract_virtuals_error (abstract_class_use use, tree type)
+{
+ return abstract_virtuals_error_sfinae (use, type, tf_warning_or_error);
+}
+
/* 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. DIAG_KIND indicates the
@@ -1733,7 +1789,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
return error_mark_node;
- if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
+ if (abstract_virtuals_error_sfinae (ACU_CAST, type, complain))
return error_mark_node;
/* [expr.type.conv]