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:
parent
a3c4975267
commit
0d9c089222
11 changed files with 116 additions and 47 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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].
|
||||
|
||||
|
@ -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].
|
||||
|
|
Loading…
Add table
Reference in a new issue