Hi,
if I understand correctly the existing uses of tf_ignore_bad_quals, in
order to correctly implement the resolution of CWG 1510, thus accept the
testcases, we have to handle decltypes like references and template type
arguments, thus make sure cp_build_qualified_type_real is called with |
tf_ignore_bad_quals. The template case seems easy and I figured out a
simple one-liner, in tsubst; the non-template case seems more tricky,
because grokdeclarator sees just a reference, doesn't have the
information that the type is coming from a decltype fully handled the
first and only time through finish_decltype_type: in the tentative patch
I resorted to an additional flag in cp_decl_specifier_seq... Patch
passes testing, anyway.
Thanks,
Paolo.
////////////////////
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 217407)
+++ cp/cp-tree.h (working copy)
@@ -4933,6 +4933,8 @@ typedef struct cp_decl_specifier_seq {
BOOL_BITFIELD explicit_char_p : 1;
/* True iff ds_thread is set for __thread, not thread_local. */
BOOL_BITFIELD gnu_thread_keyword_p : 1;
+ /* True iff the type is a decltype. */
+ BOOL_BITFIELD decltype_p : 1;
} cp_decl_specifier_seq;
/* The various kinds of declarators. */
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 217407)
+++ cp/decl.c (working copy)
@@ -9421,7 +9421,8 @@ grokdeclarator (const cp_declarator *declarator,
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
- (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
+ (type, type_quals, ((((typedef_decl && !DECL_ARTIFICIAL (typedef_decl))
+ || declspecs->decltype_p)
? tf_ignore_bad_quals : 0) | tf_warning_or_error));
/* We might have ignored or rejected some of the qualifiers. */
type_quals = cp_type_quals (type);
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 217407)
+++ cp/parser.c (working copy)
@@ -14903,9 +14903,15 @@ cp_parser_simple_type_specifier (cp_parser* parser
{
type = token->u.value;
if (decl_specs)
- cp_parser_set_decl_spec_type (decl_specs, type,
- token,
- /*type_definition_p=*/false);
+ {
+ cp_parser_set_decl_spec_type (decl_specs, type,
+ token,
+ /*type_definition_p=*/false);
+ /* Remember that we are handling a decltype in order to
+ correctly implement the resolution of CWG 1510 when
+ its argument isn't instantiation dependent. */
+ decl_specs->decltype_p = true;
+ }
cp_lexer_consume_token (parser->lexer);
return type;
}
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 217407)
+++ cp/pt.c (working copy)
@@ -12462,7 +12462,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
- complain);
+ complain | tf_ignore_bad_quals);
}
case UNDERLYING_TYPE:
Index: testsuite/g++.dg/cpp0x/decltype61.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype61.C (revision 0)
+++ testsuite/g++.dg/cpp0x/decltype61.C (working copy)
@@ -0,0 +1,20 @@
+// DR 1510, PR c++/60420
+// { dg-do compile { target c++11 } }
+
+struct MyIter
+{
+ int& operator*();
+};
+
+void foo(MyIter begin)
+{
+ auto x = [](const decltype(*begin)) { };
+}
+
+template<typename Iterator>
+void bar(Iterator begin)
+{
+ auto x = [](const decltype(*begin)) { };
+}
+
+template void bar<MyIter>(MyIter);