aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--gcc/testsuite/g++.dg/template/qualttp20.C2
-rw-r--r--libstdc++-v3/ChangeLog8
-rw-r--r--libstdc++-v3/include/tr1_impl/type_traits46
11 files changed, 112 insertions, 43 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)
{
diff --git a/gcc/testsuite/g++.dg/template/qualttp20.C b/gcc/testsuite/g++.dg/template/qualttp20.C
index d65fd1b..f42981b5 100644
--- a/gcc/testsuite/g++.dg/template/qualttp20.C
+++ b/gcc/testsuite/g++.dg/template/qualttp20.C
@@ -17,7 +17,7 @@ struct AS
template <typename T> struct B1 : T
{
typedef typename T::L __restrict__ r;// { dg-error "'__restrict__' qualifiers cannot" "" }
- typedef typename T::myT __restrict__ p;// { dg-error "ignoring '__restrict__'" }
+ typedef typename T::myT __restrict__ p;
// The following are DR 295 dependent
typedef typename T::myT volatile *myvolatile;
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 6b47446..1bcfc0b 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,11 @@
+2009-03-31 Jason Merrill <jason@redhat.com>
+
+ PR libstdc++/39310
+ * include/tr1_impl/type_traits (is_function): Add partial
+ specializations with function cv-quals.
+ (__is_function_helper): Remove.
+ (is_member_pointer): Don't define in terms of is_member_*_pointer.
+
2009-03-30 Ian Lance Taylor <iant@google.com>
* include/backward/hashtable.h (clear): Return quickly if the
diff --git a/libstdc++-v3/include/tr1_impl/type_traits b/libstdc++-v3/include/tr1_impl/type_traits
index cb0ad44..0672c39 100644
--- a/libstdc++-v3/include/tr1_impl/type_traits
+++ b/libstdc++-v3/include/tr1_impl/type_traits
@@ -224,24 +224,34 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
: public integral_constant<bool, __is_class(_Tp)>
{ };
+ /// is_function
template<typename>
- struct __is_function_helper
+ struct is_function
: public false_type { };
-
template<typename _Res, typename... _ArgTypes>
- struct __is_function_helper<_Res(_ArgTypes...)>
+ struct is_function<_Res(_ArgTypes...)>
: public true_type { };
-
template<typename _Res, typename... _ArgTypes>
- struct __is_function_helper<_Res(_ArgTypes......)>
+ struct is_function<_Res(_ArgTypes......)>
+ : public true_type { };
+ template<typename _Res, typename... _ArgTypes>
+ struct is_function<_Res(_ArgTypes...) const>
+ : public true_type { };
+ template<typename _Res, typename... _ArgTypes>
+ struct is_function<_Res(_ArgTypes......) const>
+ : public true_type { };
+ template<typename _Res, typename... _ArgTypes>
+ struct is_function<_Res(_ArgTypes...) volatile>
+ : public true_type { };
+ template<typename _Res, typename... _ArgTypes>
+ struct is_function<_Res(_ArgTypes......) volatile>
+ : public true_type { };
+ template<typename _Res, typename... _ArgTypes>
+ struct is_function<_Res(_ArgTypes...) const volatile>
+ : public true_type { };
+ template<typename _Res, typename... _ArgTypes>
+ struct is_function<_Res(_ArgTypes......) const volatile>
: public true_type { };
-
- /// is_function
- template<typename _Tp>
- struct is_function
- : public integral_constant<bool, (__is_function_helper<typename
- remove_cv<_Tp>::type>::value)>
- { };
// composite type traits [4.5.2].
@@ -287,10 +297,14 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
/// is_member_pointer
template<typename _Tp>
- struct is_member_pointer
- : public integral_constant<bool,
- (is_member_object_pointer<_Tp>::value
- || is_member_function_pointer<_Tp>::value)>
+ struct __is_member_pointer_helper
+ : public false_type { };
+ _DEFINE_SPEC(2, __is_member_pointer_helper, _Tp _Cp::*, true)
+
+ template<typename _Tp>
+ struct is_member_pointer
+ : public integral_constant<bool, (__is_member_pointer_helper<
+ typename remove_cv<_Tp>::type>::value)>
{ };
// type properties [4.5.3].