re PR c++/37806 (CV-qualifiers on function typedef's are inconsistently accepted depending on typedef scope)

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.

        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.

From-SVN: r145365
This commit is contained in:
Jason Merrill 2009-03-31 14:31:17 -04:00 committed by Jason Merrill
parent a3c4975267
commit 0d9c089222
11 changed files with 116 additions and 47 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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
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;

View File

@ -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 */
};

View File

@ -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,16 +653,18 @@ 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;
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)

View File

@ -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.

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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

View File

@ -224,24 +224,34 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
: public integral_constant<bool, __is_class(_Tp)>
{ };
template<typename>
struct __is_function_helper
: public false_type { };
template<typename _Res, typename... _ArgTypes>
struct __is_function_helper<_Res(_ArgTypes...)>
: public true_type { };
template<typename _Res, typename... _ArgTypes>
struct __is_function_helper<_Res(_ArgTypes......)>
: public true_type { };
/// is_function
template<typename _Tp>
template<typename>
struct is_function
: public integral_constant<bool, (__is_function_helper<typename
remove_cv<_Tp>::type>::value)>
{ };
: public false_type { };
template<typename _Res, typename... _ArgTypes>
struct is_function<_Res(_ArgTypes...)>
: public true_type { };
template<typename _Res, typename... _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 { };
// composite type traits [4.5.2].
@ -286,11 +296,15 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
: public integral_constant<bool, !is_fundamental<_Tp>::value> { };
/// is_member_pointer
template<typename _Tp>
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_object_pointer<_Tp>::value
|| is_member_function_pointer<_Tp>::value)>
: public integral_constant<bool, (__is_member_pointer_helper<
typename remove_cv<_Tp>::type>::value)>
{ };
// type properties [4.5.3].