aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c32
-rw-r--r--gcc/cp/decl.h1
-rw-r--r--gcc/cp/error.c19
-rw-r--r--gcc/cp/parser.c25
-rw-r--r--gcc/cp/tree.c3
-rw-r--r--gcc/cp/typeck.c3
8 files changed, 73 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 033a8f1..95079f1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,19 @@
2009-03-31 Jason Merrill <jason@redhat.com>
+ PR c++/37806
+ * typeck.c (cp_apply_type_quals_to_decl): Don't apply any quals
+ to a typedef.
+ * tree.c (cp_build_qualified_type_real): Don't apply restrict to a
+ function type.
+ * decl.h (enum decl_context): Add TEMPLATE_TYPE_ARG.
+ * decl.c (groktypename): Add is_template_arg parameter.
+ (grokdeclarator): Allow function cv-quals on a template type arg.
+ * parser.c (cp_parser_new_type_id, cp_parser_type_id): Add
+ is_template_arg argument in calls to groktypename.
+ * cp-tree.h: Adjust prototype.
+ * error.c (dump_type_prefix, dump_type_suffix): Fix plain
+ FUNCTION_TYPE printing.
+
* mangle.c (write_expression): Mangle dependent name as
source-name.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4fc86c3..9878d9d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4328,7 +4328,7 @@ extern tree push_void_library_fn (tree, tree);
extern tree push_throw_library_fn (tree, tree);
extern tree check_tag_decl (cp_decl_specifier_seq *);
extern tree shadow_tag (cp_decl_specifier_seq *);
-extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *);
+extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *, bool);
extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
extern void start_decl_1 (tree, bool);
extern bool check_array_initializer (tree, tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b16ae26..6537c50 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3967,13 +3967,16 @@ shadow_tag (cp_decl_specifier_seq *declspecs)
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))
@@ -7603,6 +7606,7 @@ grokdeclarator (const cp_declarator *declarator,
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;
signed_p = declspecs->specs[(int)ds_signed];
unsigned_p = declspecs->specs[(int)ds_unsigned];
@@ -7617,6 +7621,8 @@ grokdeclarator (const cp_declarator *declarator,
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;
if (initialized > 1)
funcdef_flag = true;
@@ -8476,6 +8482,12 @@ grokdeclarator (const cp_declarator *declarator,
memfn_quals = TYPE_UNQUALIFIED;
}
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ && cp_type_quals (type) != TYPE_UNQUALIFIED)
+ error ("cannot declare %s to qualified function type %qT",
+ declarator->kind == cdk_reference ? "reference" : "pointer",
+ type);
+
if (declarator->kind == cdk_reference)
{
/* In C++0x, the type we are creating a reference to might be
@@ -8948,15 +8960,17 @@ grokdeclarator (const cp_declarator *declarator,
}
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 = cp_build_qualified_type (type, memfn_quals);
+ else
+ error ("invalid qualifiers on non-member function type");
}
return type;
diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h
index b070be0..d6e3c83 100644
--- a/gcc/cp/decl.h
+++ b/gcc/cp/decl.h
@@ -27,6 +27,7 @@ enum decl_context
FIELD, /* Declaration inside struct or union */
BITFIELD, /* Likewise but with specified width */
TYPENAME, /* Typename (inside cast or sizeof) */
+ TEMPLATE_TYPE_ARG, /* Almost the same as TYPENAME */
MEMFUNCDEF /* Member function definition */
};
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 161fa55..7d3756e 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -550,7 +550,8 @@ dump_type_prefix (tree t, int flags)
tree sub = TREE_TYPE (t);
dump_type_prefix (sub, flags);
- if (TREE_CODE (sub) == ARRAY_TYPE)
+ if (TREE_CODE (sub) == ARRAY_TYPE
+ || TREE_CODE (sub) == FUNCTION_TYPE)
{
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
@@ -585,12 +586,10 @@ dump_type_prefix (tree t, int flags)
pp_base (cxx_pp)->padding = pp_before;
break;
- /* Can only be reached through function pointer -- this would not be
- correct if FUNCTION_DECLs used it. */
+ /* This can be reached without a pointer when dealing with
+ templates, e.g. std::is_function. */
case FUNCTION_TYPE:
dump_type_prefix (TREE_TYPE (t), flags);
- pp_maybe_space (cxx_pp);
- pp_cxx_left_paren (cxx_pp);
break;
case METHOD_TYPE:
@@ -654,17 +653,19 @@ dump_type_suffix (tree t, int flags)
case POINTER_TYPE:
case REFERENCE_TYPE:
case OFFSET_TYPE:
- if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+ if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
pp_cxx_right_paren (cxx_pp);
dump_type_suffix (TREE_TYPE (t), flags);
break;
- /* Can only be reached through function pointer. */
case FUNCTION_TYPE:
case METHOD_TYPE:
{
tree arg;
- pp_cxx_right_paren (cxx_pp);
+ if (TREE_CODE (t) == METHOD_TYPE)
+ /* Can only be reached through a pointer. */
+ pp_cxx_right_paren (cxx_pp);
arg = TYPE_ARG_TYPES (t);
if (TREE_CODE (t) == METHOD_TYPE)
arg = TREE_CHAIN (arg);
@@ -677,7 +678,7 @@ dump_type_suffix (tree t, int flags)
pp_cxx_cv_qualifier_seq
(cxx_pp, TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))));
else
- pp_cxx_cv_qualifier_seq(cxx_pp, t);
+ pp_cxx_cv_qualifier_seq (cxx_pp, t);
dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
dump_type_suffix (TREE_TYPE (t), flags);
break;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index eacf5e9..28f47c8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1732,6 +1732,10 @@ static tree cp_parser_declarator_id
(cp_parser *, bool);
static tree cp_parser_type_id
(cp_parser *);
+static tree cp_parser_template_type_arg
+ (cp_parser *);
+static tree cp_parser_type_id_1
+ (cp_parser *, bool);
static void cp_parser_type_specifier_seq
(cp_parser *, bool, cp_decl_specifier_seq *);
static tree cp_parser_parameter_declaration_clause
@@ -5772,7 +5776,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
new_declarator = NULL;
}
- type = groktypename (&type_specifier_seq, new_declarator);
+ type = groktypename (&type_specifier_seq, new_declarator, false);
return type;
}
@@ -10544,7 +10548,7 @@ cp_parser_template_argument (cp_parser* parser)
Therefore, we try a type-id first. */
cp_parser_parse_tentatively (parser);
- argument = cp_parser_type_id (parser);
+ argument = cp_parser_template_type_arg (parser);
/* If there was no error parsing the type-id but the next token is a
'>>', our behavior depends on which dialect of C++ we're
parsing. In C++98, we probably found a typo for '> >'. But there
@@ -10732,7 +10736,7 @@ cp_parser_template_argument (cp_parser* parser)
was the only alternative that matched (albeit with a '>' after
it). We can assume it's just a typo from the user, and a
diagnostic will then be issued. */
- return cp_parser_type_id (parser);
+ return cp_parser_template_type_arg (parser);
}
/* Parse an explicit-instantiation.
@@ -13766,7 +13770,7 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
Returns the TYPE specified. */
static tree
-cp_parser_type_id (cp_parser* parser)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
{
cp_decl_specifier_seq type_specifier_seq;
cp_declarator *abstract_declarator;
@@ -13795,7 +13799,18 @@ cp_parser_type_id (cp_parser* parser)
return error_mark_node;
}
- return groktypename (&type_specifier_seq, abstract_declarator);
+ return groktypename (&type_specifier_seq, abstract_declarator,
+ is_template_arg);
+}
+
+static tree cp_parser_type_id (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, false);
+}
+
+static tree cp_parser_template_type_arg (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, true);
}
/* Parse a type-specifier-seq.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 2287f11..b4b977e 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -852,11 +852,10 @@ cp_build_qualified_type_real (tree type,
}
/* A restrict-qualified type must be a pointer (or reference)
- to object or incomplete type, or a function type. */
+ to object or incomplete type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TYPENAME_TYPE
- && TREE_CODE (type) != FUNCTION_TYPE
&& !POINTER_TYPE_P (type))
{
bad_quals |= TYPE_QUAL_RESTRICT;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3788a7e..fe791f3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7239,6 +7239,9 @@ cp_apply_type_quals_to_decl (int type_quals, tree decl)
if (type == error_mark_node)
return;
+ if (TREE_CODE (decl) == TYPE_DECL)
+ return;
+
if (TREE_CODE (type) == FUNCTION_TYPE
&& type_quals != TYPE_UNQUALIFIED)
{