Re: [PATCH 3/3] Support dumping type bindings in lambda diagnostics.

2013-08-27 Thread Adam Butcher

Hi Jason,

Was just about to compose a mail to gcc-patches...  Been busy, then 
ill, now just about ready to submit a new set of diffs.


On 27.08.2013 17:47, Jason Merrill wrote:


This patch doesn't seem to depend on the others; go ahead and apply 
it.


Okay.  As it stands, it means that you get an additional 'const' in 
diagnostics for lambda's not declared 'mutable'.  I didn't think this to 
be necessarily a bad thing (distinguishing between 'mutable' and 'plain' 
lambdas and pointing at the cause for possible user error attempting to 
write to by-value captures) but it's probably contentious.  Do you want 
me to ditch the 'const' output prior to pushing?


Cheers,
Adam



[PATCH 1/4] Support lambda templates.

2013-08-27 Thread Adam Butcher
* parser.c (cp_parser_lambda_declarator_opt): Accept template parameter
list with std=c++1y or std=gnu++1y.
(cp_parser_lambda_body): Don't call 'expand_or_defer_fn' for lambda call
operator template to avoid adding template result to symbol table.
* lambda.c (lambda_function): Return template result if call operator is
a template.
(maybe_add_lambda_conv_op): Support conversion of a non-capturing lambda
template to a function pointer.
* decl2.c (check_member_template): Don't reject lambda call operator
template in local [lambda] class.
* pt.c (instantiate_class_template_1): Don't instantiate lambda call
operator template when instantiating lambda class.
---
 gcc/cp/decl2.c  |  5 ++--
 gcc/cp/lambda.c | 87 -
 gcc/cp/parser.c | 40 --
 gcc/cp/pt.c |  4 ++-
 4 files changed, 110 insertions(+), 26 deletions(-)

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d5d2912..ac9dbd7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -507,8 +507,9 @@ check_member_template (tree tmpl)
   || (TREE_CODE (decl) == TYPE_DECL
  && MAYBE_CLASS_TYPE_P (TREE_TYPE (decl
 {
-  /* The parser rejects template declarations in local classes.  */
-  gcc_assert (!current_function_decl);
+  /* The parser rejects template declarations in local classes
+(with the exception of generic lambdas).  */
+  gcc_assert (!current_function_decl || LAMBDA_FUNCTION_P (decl));
   /* The parser rejects any use of virtual in a function template.  */
   gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
&& DECL_VIRTUAL_P (decl)));
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index a53e692..e9bc7c5 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -196,7 +196,7 @@ lambda_function (tree lambda)
  /*protect=*/0, /*want_type=*/false,
  tf_warning_or_error);
   if (lambda)
-lambda = BASELINK_FUNCTIONS (lambda);
+lambda = STRIP_TEMPLATE (get_first_fn (lambda));
   return lambda;
 }
 
@@ -759,6 +759,10 @@ maybe_add_lambda_conv_op (tree type)
   if (processing_template_decl)
 return;
 
+  bool generic_lambda_p
+= (DECL_TEMPLATE_INFO (callop)
+&& DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop);
+
   if (DECL_INITIAL (callop) == NULL_TREE)
 {
   /* If the op() wasn't instantiated due to errors, give up.  */
@@ -766,7 +770,54 @@ maybe_add_lambda_conv_op (tree type)
   return;
 }
 
-  stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
+  tree fn_result = TREE_TYPE (TREE_TYPE (callop));
+  tree fn_args = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
+
+  if (generic_lambda_p)
+{
+  /* Construct the dependent member call for the static member function
+'_FUN' and remove 'auto' from its return type to allow for simple
+implementation of the conversion operator.  */
+
+  tree instance = build_nop (type, null_pointer_node);
+  argvec = make_tree_vector ();
+  for (arg = fn_args; arg; arg = DECL_CHAIN (arg))
+   {
+ mark_exp_read (arg);
+ vec_safe_push (argvec, convert_from_reference (arg));
+   }
+
+  tree objfn = build_min (COMPONENT_REF, NULL_TREE,
+ instance, DECL_NAME (callop), NULL_TREE);
+  call = build_nt_call_vec (objfn, argvec);
+
+  if (type_uses_auto (fn_result))
+   {
+ ++processing_template_decl;
+ fn_result = finish_decltype_type
+   (call, /*id_expression_or_member_access_p=*/false,
+tf_warning_or_error);
+ --processing_template_decl;
+   }
+}
+  else
+{
+  arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)),
+   null_pointer_node);
+  argvec = make_tree_vector ();
+  argvec->quick_push (arg);
+  for (arg = fn_args; arg; arg = DECL_CHAIN (arg))
+   {
+ mark_exp_read (arg);
+ vec_safe_push (argvec, arg);
+   }
+  call = build_call_a (callop, argvec->length (), argvec->address ());
+  CALL_FROM_THUNK_P (call) = 1;
+  if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
+   call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
+}
+
+  stattype = build_function_type (fn_result,
  FUNCTION_ARG_CHAIN (callop));
 
   /* First build up the conversion op.  */
@@ -794,6 +845,9 @@ maybe_add_lambda_conv_op (tree type)
   if (nested)
 DECL_INTERFACE_KNOWN (fn) = 1;
 
+  if (generic_lambda_p)
+fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
+
   add_method (type, fn, NULL_TREE);
 
   /* Generic thunk code fails for varargs; we'll complain in mark_used if
@@ -820,8 +874,8 @@ maybe_add_lambda_conv_op (tree type)
   DECL_NOT_REALLY_EXTERN (fn) = 1;
   DECL_DECLARED_INLINE_P (fn) = 1;
   DECL_STATIC_FUNCTION

Re: Lambda templates and implicit function templates.

2013-08-27 Thread Adam Butcher
Hi Jason,

Here's an updated patch set.  The fully_implicit_function_template_p
field has been moved into cp_parser and the other comments addressed.

I've done some testing with parameter packs also.  They work okay with
the explicit template parameter syntax for lambdas.

Unfortunately, due to errors being thrown 'early' in grokdeclarator, I
haven't been able to get 'auto...' (or reference/qualified variants)
working yet.  I think I need to defer processing the parameter pack
internals of grokdeclarator until I have the synthesized template
parameter (or generate one on the fly in-place --- but that's
returning to the old 'on-demand' implementation which we moved away
from).

I don't know if it's the correct thing to do but the implementation
currently omits the conversion to function pointer operator if the
argument list contains a parameter pack.

One other thing, assuming the 'auto...' syntax can be made to work,
bug 41933 needs to be resolved for the expansion returned by the
generic lambda in N3690 5.1.2.5 to compile.  Currently (transforming
the 'auto&&...' to an explicit ' T&&...') appears to
yield the bug.

In particular I get:
  error: expansion pattern ‘ts’ contains no argument packs
  sorry, unimplemented: use of ‘type_pack_expansion’ in template

   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41933#c8

You look to have done some work on it.  Any direction as to where to
go from there?  If the solution requires reworking variadics somehow
might that perhaps alleviate my problems implementing 'auto...'?
Wishful thinking probably!

Cheers,
Adam


Patch summary (4):
  Support lambda templates.
  Don't generate lambda conversion op if arglist has parameter pack.
  Support dumping type bindings in lambda diagnostics.
  Support using 'auto' in a function parameter list to introduce an
implicit template parameter.

 gcc/cp/cp-tree.h|   2 +
 gcc/cp/decl.c   |   7 +-
 gcc/cp/decl2.c  |   5 +-
 gcc/cp/error.c  |  22 +++---
 gcc/cp/lambda.c | 115 ++-
 gcc/cp/parser.c | 222 +---
 gcc/cp/parser.h |   6 ++
 gcc/cp/pt.c |  39 +
 gcc/cp/type-utils.h |  56 +
 9 files changed, 413 insertions(+), 61 deletions(-)
 create mode 100644 gcc/cp/type-utils.h

-- 
1.8.4



[PATCH 2/4] Don't generate lambda conversion op if arglist has parameter pack.

2013-08-27 Thread Adam Butcher
* lambda.c (maybe_add_lambda_conv_op): Optimize argvec building and
early out if CALLOP contains a function parameter pack.
---
 gcc/cp/lambda.c | 60 ++---
 1 file changed, 44 insertions(+), 16 deletions(-)

diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index e9bc7c5..4d76f82 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -770,8 +770,51 @@ maybe_add_lambda_conv_op (tree type)
   return;
 }
 
+  argvec = make_tree_vector ();
+
+  /* Non-template conversion operators are defined directly.  Templates are
+ deferred.  In the non-template case, the nullptr instance of the stateless
+ lambda type is added to ARGVEC for build_call_a.  In the template case it
+ is bound via build_min.  */
+  if (!generic_lambda_p)
+{
+  arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)),
+   null_pointer_node);
+  argvec->quick_push (arg);
+}
+
+  /* Copy CALLOP's argument list (as per 'copy_list') as FN_ARGS in order to
+ declare the static member function "_FUN" below.  For each arg append to
+ ARGVEC (converting from reference in the template call op case).  Early 
out
+ if a parameter pack is found; conversion to function pointer is not
+ supported in this case.  */
+  tree fn_args = NULL_TREE;
+  {
+tree src = DECL_CHAIN (DECL_ARGUMENTS (callop));
+tree tgt;
+
+while (src)
+  {
+   if (FUNCTION_PARAMETER_PACK_P (src))
+ return;
+
+   if (!fn_args)
+ fn_args = tgt = copy_node (src);
+   else
+ {
+   TREE_CHAIN (tgt) = copy_node (src);
+   tgt = TREE_CHAIN (tgt);
+ }
+
+   mark_exp_read (tgt);
+   vec_safe_push (argvec,
+  generic_lambda_p ? convert_from_reference (tgt) : tgt);
+
+   src = TREE_CHAIN (src);
+  }
+  }
+
   tree fn_result = TREE_TYPE (TREE_TYPE (callop));
-  tree fn_args = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
 
   if (generic_lambda_p)
 {
@@ -780,12 +823,6 @@ maybe_add_lambda_conv_op (tree type)
 implementation of the conversion operator.  */
 
   tree instance = build_nop (type, null_pointer_node);
-  argvec = make_tree_vector ();
-  for (arg = fn_args; arg; arg = DECL_CHAIN (arg))
-   {
- mark_exp_read (arg);
- vec_safe_push (argvec, convert_from_reference (arg));
-   }
 
   tree objfn = build_min (COMPONENT_REF, NULL_TREE,
  instance, DECL_NAME (callop), NULL_TREE);
@@ -802,15 +839,6 @@ maybe_add_lambda_conv_op (tree type)
 }
   else
 {
-  arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)),
-   null_pointer_node);
-  argvec = make_tree_vector ();
-  argvec->quick_push (arg);
-  for (arg = fn_args; arg; arg = DECL_CHAIN (arg))
-   {
- mark_exp_read (arg);
- vec_safe_push (argvec, arg);
-   }
   call = build_call_a (callop, argvec->length (), argvec->address ());
   CALL_FROM_THUNK_P (call) = 1;
   if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
-- 
1.8.4



[PATCH 3/4] Support dumping type bindings in lambda diagnostics.

2013-08-27 Thread Adam Butcher
* error.c (dump_function_decl): Use standard diagnostic flow to dump a
lambda diagnostic, albeit without stating the function name or
duplicating the parameter spec (which is dumped as part of the type).
---
 gcc/cp/error.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c82a0ce..27ff962 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1380,14 +1380,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
   vec *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-{
-  /* A lambda's signature is essentially its "type", so defer.  */
-  gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-  dump_type (pp, DECL_CONTEXT (t), flags);
-  return;
-}
+  bool lambda_p = false;
 
   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1449,16 +1442,23 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   else if (cname)
 {
   dump_type (pp, cname, flags);
-  pp_cxx_colon_colon (pp);
+  if (LAMBDA_TYPE_P (cname))
+   lambda_p = true;
+  else
+   pp_cxx_colon_colon (pp);
 }
   else
 dump_scope (pp, CP_DECL_CONTEXT (t), flags);
 
-  dump_function_name (pp, t, flags);
+  /* A lambda's signature is essentially its "type", which has already been
+ dumped.  */
+  if (!lambda_p)
+dump_function_name (pp, t, flags);
 
   if (!(flags & TFF_NO_FUNCTION_ARGUMENTS))
 {
-  dump_parameters (pp, parmtypes, flags);
+  if (!lambda_p)
+   dump_parameters (pp, parmtypes, flags);
 
   if (TREE_CODE (fntype) == METHOD_TYPE)
{
-- 
1.8.4



[PATCH 4/4] Support using 'auto' in a function parameter list to introduce an implicit template parameter.

2013-08-27 Thread Adam Butcher
* cp-tree.h (type_uses_auto_or_concept): Declare.
(is_auto_or_concept): Declare.
* decl.c (grokdeclarator): Allow 'auto' parameters with -std=gnu++1y or
-std=c++1y.
* type-utils.h: New header defining ...
(find_type_usage): ... this new template based on pt.c (type_uses_auto)
for searching a type tree given a predicate.
* pt.c (type_uses_auto): Reimplement via type-utils.h (find_type_usage).
(is_auto_or_concept): New function.
(type_uses_auto_or_concept): New function.
* parser.h (struct cp_parser): Add fully_implicit_function_template_p.
* parser.c (cp_parser_new): Initialize 
fully_implicit_function_template_p.
(cp_parser_lambda_expression): Copy and restore value of
fully_implicit_function_template_p as per other parser fields.
(cp_parser_parameter_declaration_list): Count generic
parameters and call ...
(add_implicit_template_parms): ... this new function to synthesize them
with help from type-utils.h (find_type_usage), ...
(tree_type_is_auto_or_concept): ... this new static function and ...
(make_generic_type_name): ... this new static function.
(cp_parser_direct_declarator): Account for implicit template parameters.
(cp_parser_lambda_declarator_opt): Finish fully implicit template if
necessary by calling ...
(finish_fully_implicit_template): ... this new function.
(cp_parser_member_declaration): Likewise.
(cp_parser_function_definition_after_declarator): Likewise.
---
 gcc/cp/cp-tree.h|   2 +
 gcc/cp/decl.c   |   7 +-
 gcc/cp/parser.c | 182 ++--
 gcc/cp/parser.h |   6 ++
 gcc/cp/pt.c |  35 +-
 gcc/cp/type-utils.h |  56 
 6 files changed, 264 insertions(+), 24 deletions(-)
 create mode 100644 gcc/cp/type-utils.h

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 876a72a..8d4ac94 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5453,10 +5453,12 @@ extern tree make_auto   (void);
 extern tree make_decltype_auto (void);
 extern tree do_auto_deduction  (tree, tree, tree);
 extern tree type_uses_auto (tree);
+extern tree type_uses_auto_or_concept  (tree);
 extern void append_type_to_template_for_access_check (tree, tree, tree,
  location_t);
 extern tree splice_late_return_type(tree, tree);
 extern bool is_auto(const_tree);
+extern bool is_auto_or_concept (const_tree);
 extern tree process_template_parm  (tree, location_t, tree, 
 bool, bool);
 extern tree end_template_parm_list (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 4076a24..df44a6e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10325,9 +10325,12 @@ grokdeclarator (const cp_declarator *declarator,
   if (ctype || in_namespace)
error ("cannot use %<::%> in parameter declaration");
 
-  if (type_uses_auto (type))
+  if (type_uses_auto (type) && cxx_dialect < cxx1y)
{
- error ("parameter declared %");
+ pedwarn (location_of (type), 0,
+  "use of % in parameter declaration "
+  "only available with "
+  "-std=c++1y or -std=gnu++1y");
  type = error_mark_node;
}
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 1f0c2c2..7147bfa 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "plugin.h"
 #include "tree-pretty-print.h"
 #include "parser.h"
+#include "type-utils.h"
 
 
 /* The lexer.  */
@@ -2063,6 +2064,11 @@ static vec 
*cp_parser_initializer_list
 static bool cp_parser_ctor_initializer_opt_and_function_body
   (cp_parser *, bool);
 
+static tree add_implicit_template_parms
+  (cp_parser *, size_t, tree);
+static tree finish_fully_implicit_template
+  (cp_parser *, tree);
+
 /* Classes [gram.class] */
 
 static tree cp_parser_class_name
@@ -3385,6 +3391,9 @@ cp_parser_new (void)
   /* No template parameters apply.  */
   parser->num_template_parameter_lists = 0;
 
+  /* Not declaring an implicit function template.  */
+  parser->fully_implicit_function_template_p = false;
+
   return parser;
 }
 
@@ -8549,10 +8558,12 @@ cp_parser_lambda_expression (cp_parser* parser)
 = parser->num_template_parameter_lists;
 unsigned char in_statement = parser->in_statement;
 bool in_switch_statement_p = parser->in_switch_statement_p;
+bool fully_implicit_function_template_p = 
parser->fully_implicit_function_template_p;
 
 parser->num_template_parameter_lists = 0;
 parser->in_statement = 0;
 parser->in_switch_statement_p = false;
+parser->fully_implicit_func

[PATCH] Support dumping type bindings and 'mutable' qualifier in lambda diagnostics.

2013-08-28 Thread Adam Butcher
* error.c (dump_function_decl): Use standard diagnostic flow to dump a
lambda diagnostic, albeit without stating the function name or
duplicating the parameter spec (which is dumped as part of the type).
Rather than qualifying the diagnostic with 'const' for plain lambdas,
qualify with 'mutable' if non-const.
---
Okay to commit?
---
 gcc/cp/error.c | 27 +++
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c82a0ce..a8ca269 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1380,14 +1380,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
   vec *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-{
-  /* A lambda's signature is essentially its "type", so defer.  */
-  gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-  dump_type (pp, DECL_CONTEXT (t), flags);
-  return;
-}
+  bool lambda_p = false;
 
   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1449,21 +1442,31 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   else if (cname)
 {
   dump_type (pp, cname, flags);
-  pp_cxx_colon_colon (pp);
+  if (LAMBDA_TYPE_P (cname))
+   lambda_p = true;
+  else
+   pp_cxx_colon_colon (pp);
 }
   else
 dump_scope (pp, CP_DECL_CONTEXT (t), flags);
 
-  dump_function_name (pp, t, flags);
+  /* A lambda's signature is essentially its "type", which has already been
+ dumped.  */
+  if (!lambda_p)
+dump_function_name (pp, t, flags);
 
   if (!(flags & TFF_NO_FUNCTION_ARGUMENTS))
 {
-  dump_parameters (pp, parmtypes, flags);
+  if (!lambda_p)
+   dump_parameters (pp, parmtypes, flags);
 
   if (TREE_CODE (fntype) == METHOD_TYPE)
{
  pp->padding = pp_before;
- pp_cxx_cv_qualifier_seq (pp, class_of_this_parm (fntype));
+ if (!lambda_p)
+   pp_cxx_cv_qualifier_seq (pp, class_of_this_parm (fntype));
+ else if (!(TYPE_QUALS (class_of_this_parm (fntype)) & 
TYPE_QUAL_CONST))
+   pp_c_ws_string (pp, "mutable");
  dump_ref_qualifier (pp, fntype, flags);
}
 
-- 
1.8.4



[PATCH] Support dumping type bindings and 'mutable' qualifier in lambda diagnostics.

2013-08-29 Thread Adam Butcher
* error.c (dump_lambda_function): New function, dependent on ...
(maybe_dump_template_bindings): ... this new function, factored out of
...
(dump_function_decl): ... here.  Updated to early-out with call to
dump_lambda_function after determining template bindings.
---
Reworked as requested.  Okay to commit?
---
 gcc/cp/error.c | 60 ++
 1 file changed, 39 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c82a0ce..1edfa0b 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1363,6 +1363,39 @@ find_typenames (tree t)
   return ft.typenames;
 }
 
+static void
+maybe_dump_template_bindings (cxx_pretty_printer *pp,
+ tree t, tree template_parms, tree template_args,
+ int flags)
+{
+  if (template_parms != NULL_TREE && template_args != NULL_TREE
+  && !(flags & TFF_NO_TEMPLATE_BINDINGS))
+{
+  vec *typenames = find_typenames (t);
+  pp_cxx_whitespace (pp);
+  pp_cxx_left_bracket (pp);
+  pp_cxx_ws_string (pp, M_("with"));
+  pp_cxx_whitespace (pp);
+  dump_template_bindings (pp, template_parms, template_args, typenames);
+  pp_cxx_right_bracket (pp);
+}
+}
+
+static void
+dump_lambda_function (cxx_pretty_printer *pp,
+ tree fn, tree template_parms, tree template_args,
+ int flags)
+{
+  /* A lambda's signature is essentially its "type".  */
+  dump_type (pp, DECL_CONTEXT (fn), flags);
+  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & TYPE_QUAL_CONST))
+{
+  pp->padding = pp_before;
+  pp_c_ws_string (pp, "mutable");
+}
+  maybe_dump_template_bindings (pp, fn, template_parms, template_args, flags);
+}
+
 /* Pretty print a function decl. There are several ways we want to print a
function declaration. The TFF_ bits in FLAGS tells us how to behave.
As error can only apply the '#' flag once to give 0 and 1 for V, there
@@ -1379,15 +1412,6 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
-  vec *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-{
-  /* A lambda's signature is essentially its "type", so defer.  */
-  gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-  dump_type (pp, DECL_CONTEXT (t), flags);
-  return;
-}
 
   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1409,10 +1433,13 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
{
  template_parms = DECL_TEMPLATE_PARMS (tmpl);
  t = tmpl;
- typenames = find_typenames (t);
}
 }
 
+  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
+return dump_lambda_function (pp, t, template_parms, template_args,
+flags);
+
   fntype = TREE_TYPE (t);
   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
 
@@ -1476,17 +1503,8 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   if (show_return)
dump_type_suffix (pp, TREE_TYPE (fntype), flags);
 
-  /* If T is a template instantiation, dump the parameter binding.  */
-  if (template_parms != NULL_TREE && template_args != NULL_TREE
- && !(flags & TFF_NO_TEMPLATE_BINDINGS))
-   {
- pp_cxx_whitespace (pp);
- pp_cxx_left_bracket (pp);
- pp_cxx_ws_string (pp, M_("with"));
- pp_cxx_whitespace (pp);
- dump_template_bindings (pp, template_parms, template_args, typenames);
- pp_cxx_right_bracket (pp);
-   }
+  maybe_dump_template_bindings (pp, t, template_parms, template_args,
+   flags);
 }
   else if (template_args)
 {
-- 
1.8.4



Re: [PATCH] Support dumping type bindings and 'mutable' qualifier in lambda diagnostics.

2013-08-29 Thread Adam Butcher

On 29.08.2013 16:25, Gabriel Dos Reis wrote:
On Thu, Aug 29, 2013 at 9:20 AM, Adam Butcher  
wrote:
* error.c (dump_lambda_function): New function, dependent on 
...
(maybe_dump_template_bindings): ... this new function, 
factored out of

...
(dump_function_decl): ... here.  Updated to early-out with 
call to

dump_lambda_function after determining template bindings.
---
Reworked as requested.  Okay to commit?


Document the new functions.
Use pp->translate_string ("with") instead of
pp_cxx_ws_string (pp, M_("with")).

Done.  In documenting 'maybe_dump_template_bindings' and reviewing it 
again I'm not sure it's got the right name.  It wraps 
'dump_template_bindings' in "[with " and "]".  So it does more than just 
filter a call to 'dump_template_bindings'.


Any suggestions?  What do you think of 'maybe_dump_with_clause' or 
something similar?


Cheers,
Adam



Thanks,
-- Gaby



+static void
+maybe_dump_template_bindings (cxx_pretty_printer *pp,
+ tree t, tree template_parms, tree 
template_args,

+ int flags)
+{
+  if (template_parms != NULL_TREE && template_args != NULL_TREE
+  && !(flags & TFF_NO_TEMPLATE_BINDINGS))
+{
+  vec *typenames = find_typenames (t);
+  pp_cxx_whitespace (pp);
+  pp_cxx_left_bracket (pp);
+  pp_cxx_ws_string (pp, M_("with"));
+  pp_cxx_whitespace (pp);
+  dump_template_bindings (pp, template_parms, template_args, 
typenames);

+  pp_cxx_right_bracket (pp);
+}
+}
+
+static void
+dump_lambda_function (cxx_pretty_printer *pp,
+ tree fn, tree template_parms, tree 
template_args,

+ int flags)
+{
+  /* A lambda's signature is essentially its "type".  */
+  dump_type (pp, DECL_CONTEXT (fn), flags);
+  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & 
TYPE_QUAL_CONST))

+{
+  pp->padding = pp_before;
+  pp_c_ws_string (pp, "mutable");
+}
+  maybe_dump_template_bindings (pp, fn, template_parms, 
template_args, flags);

+}
+
 /* Pretty print a function decl. There are several ways we want to 
print a
function declaration. The TFF_ bits in FLAGS tells us how to 
behave.
As error can only apply the '#' flag once to give 0 and 1 for V, 
there
@@ -1379,15 +1412,6 @@ dump_function_decl (cxx_pretty_printer *pp, 
tree t, int flags)
   int show_return = flags & TFF_RETURN_TYPE || flags & 
TFF_DECL_SPECIFIERS;

   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
-  vec *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-{
-  /* A lambda's signature is essentially its "type", so defer.  
*/

-  gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-  dump_type (pp, DECL_CONTEXT (t), flags);
-  return;
-}

   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1409,10 +1433,13 @@ dump_function_decl (cxx_pretty_printer *pp, 
tree t, int flags)

{
  template_parms = DECL_TEMPLATE_PARMS (tmpl);
  t = tmpl;
- typenames = find_typenames (t);
}
 }

+  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
+return dump_lambda_function (pp, t, template_parms, 
template_args,

+flags);
+
   fntype = TREE_TYPE (t);
   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);

@@ -1476,17 +1503,8 @@ dump_function_decl (cxx_pretty_printer *pp, 
tree t, int flags)

   if (show_return)
dump_type_suffix (pp, TREE_TYPE (fntype), flags);

-  /* If T is a template instantiation, dump the parameter 
binding.  */

-  if (template_parms != NULL_TREE && template_args != NULL_TREE
- && !(flags & TFF_NO_TEMPLATE_BINDINGS))
-   {
- pp_cxx_whitespace (pp);
- pp_cxx_left_bracket (pp);
- pp_cxx_ws_string (pp, M_("with"));
- pp_cxx_whitespace (pp);
- dump_template_bindings (pp, template_parms, template_args, 
typenames);

- pp_cxx_right_bracket (pp);
-   }
+  maybe_dump_template_bindings (pp, t, template_parms, 
template_args,

+   flags);
 }
   else if (template_args)
 {
--
1.8.4





Re: [PATCH] Support dumping type bindings and 'mutable' qualifier in lambda diagnostics.

2013-08-29 Thread Adam Butcher
* error.c (dump_lambda_function): New function, dependent on ...
(maybe_dump_with_clause): ... this new function, factored out of ...
(subst_to_string): ... here and ...
(dump_function_decl): ... here.  Updated to early-out with call to
dump_lambda_function after determining template bindings.
---
Hi Gaby,

On 29.08.2013 18:04, Adam Butcher wrote:
> On 29.08.2013 16:25, Gabriel Dos Reis wrote:
> >
> > Document the new functions.
> > Use pp->translate_string ("with") instead of
> > pp_cxx_ws_string (pp, M_("with")).
> >
> Done.  In documenting 'maybe_dump_template_bindings' and reviewing
> it again I'm not sure it's got the right name.  It wraps
> 'dump_template_bindings' in "[with " and "]".  So it does more than
> just filter a call to 'dump_template_bindings'.
>
> Any suggestions?  What do you think of 'maybe_dump_with_clause' or
> something similar?
>
Here's a diff with the name change (though I'm not all that happy with
it) and the docs.

I've also reimplemented subst_to_string in terms of the new function
as it was duplicating much of the code from dump_function_decl (the
only downside of this is some unnecessary tests in the subst_to_string
case but I think they should get optimized away if it were inlined --
we're dealing with diagnostics formatting here anyway so performance
is probably not a big factor).

Cheers,
Adam
---
 gcc/cp/error.c | 73 --
 1 file changed, 46 insertions(+), 27 deletions(-)

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c82a0ce..3d1e173 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1363,6 +1363,47 @@ find_typenames (tree t)
   return ft.typenames;
 }
 
+/* Output the "[with ...]" clause for a template instantiation T iff
+   TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be NULL if
+   formatting a deduction/substitution diagnostic rather than an
+   instantiation.  */
+
+static void
+maybe_dump_with_clause (cxx_pretty_printer *pp,
+   tree t, tree template_parms, tree template_args,
+   int flags)
+{
+  if (template_parms != NULL_TREE && template_args != NULL_TREE
+  && !(flags & TFF_NO_TEMPLATE_BINDINGS))
+{
+  vec *typenames = t ? find_typenames (t) : NULL;
+  pp_cxx_whitespace (pp);
+  pp_cxx_left_bracket (pp);
+  pp->translate_string ("with");
+  pp_cxx_whitespace (pp);
+  dump_template_bindings (pp, template_parms, template_args, typenames);
+  pp_cxx_right_bracket (pp);
+}
+}
+
+/* Dump the lambda function FN including its 'mutable' qualifier and any
+   template bindings.  */
+
+static void
+dump_lambda_function (cxx_pretty_printer *pp,
+ tree fn, tree template_parms, tree template_args,
+ int flags)
+{
+  /* A lambda's signature is essentially its "type".  */
+  dump_type (pp, DECL_CONTEXT (fn), flags);
+  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & TYPE_QUAL_CONST))
+{
+  pp->padding = pp_before;
+  pp_c_ws_string (pp, "mutable");
+}
+  maybe_dump_with_clause (pp, fn, template_parms, template_args, flags);
+}
+
 /* Pretty print a function decl. There are several ways we want to print a
function declaration. The TFF_ bits in FLAGS tells us how to behave.
As error can only apply the '#' flag once to give 0 and 1 for V, there
@@ -1379,15 +1420,6 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
-  vec *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-{
-  /* A lambda's signature is essentially its "type", so defer.  */
-  gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-  dump_type (pp, DECL_CONTEXT (t), flags);
-  return;
-}
 
   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1409,10 +1441,12 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
{
  template_parms = DECL_TEMPLATE_PARMS (tmpl);
  t = tmpl;
- typenames = find_typenames (t);
}
 }
 
+  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
+return dump_lambda_function (pp, t, template_parms, template_args, flags);
+
   fntype = TREE_TYPE (t);
   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
 
@@ -1476,17 +1510,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   if (show_return)
dump_type_suffix (pp, TREE_TYPE (fntype), flags);
 
-  /* If T is a template instantiat

[PATCH, committed] Support dumping type bindings and 'mutable' qualifier in lambda diagnostics.

2013-08-29 Thread Adam Butcher
From: abutcher 

* error.c (dump_lambda_function): New function, dependent on ...
(dump_substitution): ... this new function, factored out of ...
(subst_to_string): ... here and ...
(dump_function_decl): ... here.  Updated to early-out with call to
dump_lambda_function after determining template bindings.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202087 
138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog |  8 +++
 gcc/cp/error.c   | 73 +++-
 2 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bf49198..f848b81 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2013-08-29  Adam Butcher  
+
+   * error.c (dump_lambda_function): New function, dependent on ...
+   (dump_substitution): ... this new function, factored out of ...
+   (subst_to_string): ... here and ...
+   (dump_function_decl): ... here.  Updated to early-out with call to
+   dump_lambda_function after determining template bindings.
+
 2013-08-28  Paolo Carlini  
 
PR c++/58255
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c82a0ce..af71000 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1363,6 +1363,47 @@ find_typenames (tree t)
   return ft.typenames;
 }
 
+/* Output the "[with ...]" clause for a template instantiation T iff
+   TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be NULL if
+   formatting a deduction/substitution diagnostic rather than an
+   instantiation.  */
+
+static void
+dump_substitution (cxx_pretty_printer *pp,
+   tree t, tree template_parms, tree template_args,
+   int flags)
+{
+  if (template_parms != NULL_TREE && template_args != NULL_TREE
+  && !(flags & TFF_NO_TEMPLATE_BINDINGS))
+{
+  vec *typenames = t ? find_typenames (t) : NULL;
+  pp_cxx_whitespace (pp);
+  pp_cxx_left_bracket (pp);
+  pp->translate_string ("with");
+  pp_cxx_whitespace (pp);
+  dump_template_bindings (pp, template_parms, template_args, typenames);
+  pp_cxx_right_bracket (pp);
+}
+}
+
+/* Dump the lambda function FN including its 'mutable' qualifier and any
+   template bindings.  */
+
+static void
+dump_lambda_function (cxx_pretty_printer *pp,
+ tree fn, tree template_parms, tree template_args,
+ int flags)
+{
+  /* A lambda's signature is essentially its "type".  */
+  dump_type (pp, DECL_CONTEXT (fn), flags);
+  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & TYPE_QUAL_CONST))
+{
+  pp->padding = pp_before;
+  pp_c_ws_string (pp, "mutable");
+}
+  dump_substitution (pp, fn, template_parms, template_args, flags);
+}
+
 /* Pretty print a function decl. There are several ways we want to print a
function declaration. The TFF_ bits in FLAGS tells us how to behave.
As error can only apply the '#' flag once to give 0 and 1 for V, there
@@ -1379,15 +1420,6 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
-  vec *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-{
-  /* A lambda's signature is essentially its "type", so defer.  */
-  gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-  dump_type (pp, DECL_CONTEXT (t), flags);
-  return;
-}
 
   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1409,10 +1441,12 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
{
  template_parms = DECL_TEMPLATE_PARMS (tmpl);
  t = tmpl;
- typenames = find_typenames (t);
}
 }
 
+  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
+return dump_lambda_function (pp, t, template_parms, template_args, flags);
+
   fntype = TREE_TYPE (t);
   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
 
@@ -1476,17 +1510,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
   if (show_return)
dump_type_suffix (pp, TREE_TYPE (fntype), flags);
 
-  /* If T is a template instantiation, dump the parameter binding.  */
-  if (template_parms != NULL_TREE && template_args != NULL_TREE
- && !(flags & TFF_NO_TEMPLATE_BINDINGS))
-   {
- pp_cxx_whitespace (pp);
- pp_cxx_left_bracket (pp);
- pp_cxx_ws_string (pp, M_("with"));
- pp_cxx_whitespace (pp);
- dump_template_bindings (pp, template_parms, template_args, typenames);
- pp_cxx_right_bracket (pp);
-   }
+  dump_substitution (pp, t, template_parms, template_args, flags);
 }
   else if

Re: [PATCH, committed] Support dumping type bindings and 'mutable' qualifier in lambda diagnostics.

2013-08-29 Thread Adam Butcher

On 29.08.2013 21:59, Gabriel Dos Reis wrote:
On Thu, Aug 29, 2013 at 3:57 PM, Adam Butcher  
wrote:

From: abutcher 

* error.c (dump_lambda_function): New function, dependent on 
...
(dump_substitution): ... this new function, factored out of 
...

(subst_to_string): ... here and ...
(dump_function_decl): ... here.  Updated to early-out with 
call to

dump_lambda_function after determining template bindings.


Please go ahead and commit it.  You do have SVN commit access, right?

Yes, this is the committed patch.  I was under the impression that I 
should ping the list with the commit once pushed.


Adam


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202087 
138bc75d-0d04-0410-961f-82ee72b054a4

---
 gcc/cp/ChangeLog |  8 +++
 gcc/cp/error.c   | 73 
+++-

 2 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bf49198..f848b81 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2013-08-29  Adam Butcher  
+
+   * error.c (dump_lambda_function): New function, dependent on 
...
+   (dump_substitution): ... this new function, factored out of 
...

+   (subst_to_string): ... here and ...
+   (dump_function_decl): ... here.  Updated to early-out with 
call to

+   dump_lambda_function after determining template bindings.
+
 2013-08-28  Paolo Carlini  

PR c++/58255
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c82a0ce..af71000 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1363,6 +1363,47 @@ find_typenames (tree t)
   return ft.typenames;
 }

+/* Output the "[with ...]" clause for a template instantiation T 
iff
+   TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be 
NULL if

+   formatting a deduction/substitution diagnostic rather than an
+   instantiation.  */
+
+static void
+dump_substitution (cxx_pretty_printer *pp,
+   tree t, tree template_parms, tree template_args,
+   int flags)
+{
+  if (template_parms != NULL_TREE && template_args != NULL_TREE
+  && !(flags & TFF_NO_TEMPLATE_BINDINGS))
+{
+  vec *typenames = t ? find_typenames (t) : NULL;
+  pp_cxx_whitespace (pp);
+  pp_cxx_left_bracket (pp);
+  pp->translate_string ("with");
+  pp_cxx_whitespace (pp);
+  dump_template_bindings (pp, template_parms, template_args, 
typenames);

+  pp_cxx_right_bracket (pp);
+}
+}
+
+/* Dump the lambda function FN including its 'mutable' qualifier 
and any

+   template bindings.  */
+
+static void
+dump_lambda_function (cxx_pretty_printer *pp,
+ tree fn, tree template_parms, tree 
template_args,

+ int flags)
+{
+  /* A lambda's signature is essentially its "type".  */
+  dump_type (pp, DECL_CONTEXT (fn), flags);
+  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & 
TYPE_QUAL_CONST))

+{
+  pp->padding = pp_before;
+  pp_c_ws_string (pp, "mutable");
+}
+  dump_substitution (pp, fn, template_parms, template_args, flags);
+}
+
 /* Pretty print a function decl. There are several ways we want to 
print a
function declaration. The TFF_ bits in FLAGS tells us how to 
behave.
As error can only apply the '#' flag once to give 0 and 1 for V, 
there
@@ -1379,15 +1420,6 @@ dump_function_decl (cxx_pretty_printer *pp, 
tree t, int flags)
   int show_return = flags & TFF_RETURN_TYPE || flags & 
TFF_DECL_SPECIFIERS;

   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
-  vec *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-{
-  /* A lambda's signature is essentially its "type", so defer.  
*/

-  gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-  dump_type (pp, DECL_CONTEXT (t), flags);
-  return;
-}

   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1409,10 +1441,12 @@ dump_function_decl (cxx_pretty_printer *pp, 
tree t, int flags)

{
  template_parms = DECL_TEMPLATE_PARMS (tmpl);
  t = tmpl;
- typenames = find_typenames (t);
}
 }

+  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
+return dump_lambda_function (pp, t, template_parms, 
template_args, flags);

+
   fntype = TREE_TYPE (t);
   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);

@@ -1476,17 +1510,7 @@ dump_function_decl (cxx_pretty_printer *pp, 
tree t, int flags)

   if (show_return)
dump_type_suffix (pp, TREE_TYPE (fntype), flags);

-  /* If T is a template instantiation, dump the parameter 
binding.  */

-  if (template_parms != NULL_TREE && template_args != NULL_TREE
- && !(flags & TFF_NO_TEMPLATE_BINDINGS))
-   {
- pp_cxx_whitespace (pp);
-

Re: Lambda templates and implicit function templates.

2013-09-02 Thread Adam Butcher

On 01.09.2013 21:05, Jason Merrill wrote:

On 08/27/2013 03:42 PM, Adam Butcher wrote:

I don't know if it's the correct thing to do but the implementation
currently omits the conversion to function pointer operator if the
argument list contains a parameter pack.


I would expect that to work.  Does the specification not provide for
deduction in that case?


It doesn't forbid it as far as I can see.  But it also gives no
example of a stateless lambda with a variadic parameter.  TBH I just
couldn't figure out the right implementation so thought it better
to omit the conversion operator on the assumption that it is not a
common use case rather than ICE .  I'll have a rethink based on your
follow up to 2/4 and try to get a pack expansion working there.


One other thing, assuming the 'auto...' syntax can be made to work,
bug 41933 needs to be resolved for the expansion returned by the
generic lambda in N3690 5.1.2.5 to compile.  Currently (transforming
the 'auto&&...' to an explicit ' T&&...') appears to
yield the bug.


Bug 41933 is specifically about lambda capture; I think you're
running into something else.


The problem is in expanding the 'ts' capture from the 5.1.2.5.  It
looks like this:

  1 auto vglambda = [](auto printer) {
  2   return [=](auto&& ... ts) { // OK: ts is a function parameter 
pack

  3 printer(std::forward(ts)...);
  4 return [=]() {
  5   printer(ts ...);
  6 };
  7   };
  8 };

It is the expansion of the captured 'ts' on line 5 that I think yields
the bug.  Might be slightly different to 41933 though due to not being
explicitly captured as "ts...".  Unsure.   My point was that in order 
to

conform this issue will need to be fixed as well as getting the
'auto...' syntax to work.

Cheers,
Adam



Re: [PATCH 1/4] Support lambda templates.

2013-09-02 Thread Adam Butcher

On 01.09.2013 21:22, Jason Merrill wrote:

On 08/27/2013 03:42 PM, Adam Butcher wrote:

+ vec_safe_push (argvec, arg);


I bet we want convert_from_reference in the non-generic lambda case, 
too.


OK with that change.

I think I had made that change originally to keep the two impls the 
same and I hit issues with non-generic lambdas.  But I can't remember 
the details.  I'll try again.  If it works with convert_from_reference 
in both cases should I push or should I sort out the parameter pack 
conversion op issue and roll that up into this?





Re: [PATCH 4/4] Support using 'auto' in a function parameter list to introduce an implicit template parameter.

2013-09-02 Thread Adam Butcher

On 01.09.2013 22:20, Jason Merrill wrote:

On 08/27/2013 03:42 PM, Adam Butcher wrote:

+  else // extend current template parameter list
+  // pop the innermost template parms into tparms


Most comments should start with a capital letter and end with a 
period.



Will change.

+  for (size_t n = 0, end = TREE_VEC_LENGTH (inner_vec); n < 
end; ++n)

+   tparms = chainon (tparms, TREE_VEC_ELT (inner_vec, n));


Doing chainon in a loop has bad algorithmic complexity, as it walks
through the whole tparms list each iteration.  Better to build up a
list from inner_vec and then chainon that list as a whole.


Okay.


+template 
+inline tree
+find_type_usage (tree t, TreePredicate pred)


I don't think this needs to be a template, since we know the
predicates take a single tree and return bool.


I didn't know whether to allow for someone passing in a stateful
lambda (or other functor) in future so I avoided the issue by
making the predicate a template type param.  If we're happy that
only c-style functions (or stateless lambdas) will be passed then
I'll put it back as 'bool (*) (const_tree)'.


I don't see any diagnostic for the implicit function template
extension; my earlier comment about not controlling it with 
-std=c++1y

vs gnu++1y didn't mean it should go away entirely.  :)

Maybe we should call it part of c++1z, or just control the diagnostic
with -pedantic.


I must confess I was a bit unclear about how to proceed there.  I'll
reinstate the two messages and go with a specific diagnostic if
-pedantic is set in the non-lambda case.

Cheers,
Adam



Re: [PATCH 1/4] Support lambda templates.

2013-09-02 Thread Adam Butcher

On 02.09.2013 19:34, Jason Merrill wrote:

On 09/02/2013 02:30 PM, Adam Butcher wrote:

On 01.09.2013 21:22, Jason Merrill wrote:
I bet we want convert_from_reference in the non-generic lambda 
case, too.


I think I had made that change originally to keep the two impls the 
same

and I hit issues with non-generic lambdas.  But I can't remember the
details.  I'll try again.

Okay, finally got around to trying this again.  With 
convert_from_reference in the non-generic case, the code compiles okay 
but SEGVs on the attempt to branch to '_FUN'.


  │105   auto lf0 = [] (float& a, int const& b) { return a += b; };
  │106
  │107   INVOKEi (lf, float, 7, 0);
 >│108   AS_FUNi (lf, float, 7, 0);
  │109   AS_PTRi (lf, float, int, 7, 0);

  │0x404500  mov%eax,-0x4bc(%rbp)
  │0x404506  mov0x36f0(%rip),%eax# 0x407bfc
  │0x40450c  mov%eax,-0x4c0(%rbp)
  │0x404512  movl   $0x7,-0x2a4(%rbp)
  │0x40451c  lea-0x2a4(%rbp),%rdx
  │0x404523  lea-0x4bc(%rbp),%rax
  │0x40452a  mov%rdx,%rsi
  │0x40452d  mov%rax,%rdi
 >│0x404530  callq  0x400934 <const&)>::_FUN(float &, const int &)>




If it works with convert_from_reference in
both cases should I push or should I sort out the parameter pack
conversion op issue and roll that up into this?


I think roll them together, since that patch rewrites parts of this 
one.


Will assume, for now, that the convert_from_reference call is not 
wanted in the non-generic case (maybe something to do with using 
'build_call_a' instead of 'build_nt_call_vec' or the 
convert_from_reference on the call itself?) and will focus on the 
parameter pack stuff (when I get a chance).


Cheers,
Adam



Re: [PATCH 1/4] Support lambda templates.

2013-09-03 Thread Adam Butcher

On 03.09.2013 04:50, Jason Merrill wrote:

On 09/02/2013 05:18 PM, Adam Butcher wrote:
> will focus on the parameter pack stuff (when I get a chance).
>
Sounds good.

I had a quick hack at getting pack expansion working for the conversion 
op.
The syntactic side seems to be okay.  It gets all the way to finalizing 
the tu.
It generates suitable diagnostics if I force warnings in various places 
in my

testcase.

I've done what amounts to the following (diff hand edited to removing 
noisy

debug logging and temporaries):

--
@@ -795,20 +794,39 @@ maybe_add_lambda_conv_op (tree type)

 while (src)
   {
-   if (FUNCTION_PARAMETER_PACK_P (src))
- return;
+   tree new_node = copy_node (src);

if (!fn_args)
- fn_args = tgt = copy_node (src);
+ fn_args = tgt = new_node;
else
  {
-   TREE_CHAIN (tgt) = copy_node (src);
-   tgt = TREE_CHAIN (tgt);
+   TREE_CHAIN (tgt) = new_node;
+   tgt = new_node;
  }

mark_exp_read (tgt);
+
+   if (FUNCTION_PARAMETER_PACK_P (tgt))
+   vec_safe_push (argvec, make_pack_expansion (tgt));
+   else
vec_safe_push (argvec,
   generic_lambda_p ? convert_from_reference 
(tgt) : tgt);


src = TREE_CHAIN (src);
   }
--


Problem is that no RTL is set for the incoming parms in the 
instantiation of
the expansion.  It ICEs in gimple_expand_cfg because 'DECL_RTL_IF_SET 
(var)'
returns nullptr for the incoming parms resulting in a failed assertion 
that

SA.partition_to_pseudo[i] is non-null.

What follows below is basically a dump of various info that may help 
you to
point me in the right direction or may be completely useless or 
unnecessary to

you.

Any ideas appreciated.

Cheers,
Adam


The error diagnostic is:


/home/ajb/t7-variadic-ptr.cpp: In static member function ‘static 
decltype (((main()::...)>)0u).operator()(main::__lambda1::_FUN:: ...)) 
main()_FUN(P ...) [with P = {double, double, double}; 
decltype (((main()::...)>)0u).operator()(main::__lambda1::_FUN:: ...)) = float]’:


/home/ajb/t7-variadic-ptr.cpp:13:37: internal compiler error: in 
gimple_expand_cfg, at cfgexpand.c:4649

auto g = []  (P...) { return 3.f; };
 ^

This only occurs if I instantiate the conversion op.


I added the following tracing to gimple_expand_cfg:

--
@@ -4635,9 +4635,17 @@ gimple_expand_cfg (void)
 {
   tree var = SSA_NAME_VAR (partition_to_var (SA.map, i));

+  debug_tree (var);
+
+  if (TREE_CODE (var) != VAR_DECL)
+fprintf (stderr, "SA.partition_to_pseudo[%d] == %p\n", i, 
SA.partition_to_pseudo[i]);

+
   if (TREE_CODE (var) != VAR_DECL
  && !SA.partition_to_pseudo[i])
+   {
  SA.partition_to_pseudo[i] = DECL_RTL_IF_SET (var);
+ fprintf (stderr, "SA.partition_to_pseudo[%d] => %p\n", i, 
SA.partition_to_pseudo[i]);

+   }
   gcc_assert (SA.partition_to_pseudo[i]);

   /* If this decl was marked as living in multiple places, reset
--


I expected the instantiated parm_decl for the pack expansion parms to 
look

similar to this (from a 'normal' non-pack parm) ...

 
unit size 
align 32 symtab 0 alias set -1 canonical type 0x7f3833f83f18 
precision 32

pointer_to_this >
used SF file /home/ajb/t7-variadic-ptr.cpp line 12 col 30 size 
 unit size 

align 32 context 

(mem/c:SF (plus:DI (reg/f:DI 70 virtual-stack-vars)
(const_int -20 [0xffec])) [0 D.2134+0 S4 A32]) 
arg-type 

incoming-rtl (reg:SF 21 xmm0 [ D.2134 ])>


... but instead it looks like this:


 
unit size 
align 64 symtab 0 alias set -1 canonical type 0x7f3833f8d000 
precision 64

pointer_to_this >
used VOID file /home/ajb/t7-variadic-ptr.cpp line 13 col 34
align 8
arg-type  chain 0x7f38340e4680 D.2146>>



 Everything under the tree type seems to be 'default' and I note that 
context

 has gone (it is there in the pack expansion expression prior to
 instantiation).  I'm not sure if this is relevant.

(note I was passing 3 doubles into the variadic template and a float 
into the 'plain' single arg template)



Here's some dumps of the expansion creation from 
maybe_add_lambda_conv_op:



SRC =>
  >
type_0 type_6 VOID
align 8 symtab 0 alias set -1 structural equality>
decl_1 VOID file /home/ajb/t7-variadic-ptr.cpp line 13 col 34
align 8 context 
   >
NEW_NODE =>
  >
type_0 type_6 VOID
align 8 symtab 0 alias set -1 structural equality>
decl_1 VOID file /home/ajb/t7-variadic-ptr.cpp line 13 col 34
align 8 context 
   >
MAKE_PACK_EXPANSION =>
  >
type_0 type_6 VOID
align 8 symtab 0 alias set -1

Re: [PATCH] [lambda] Extract lambda functions from semantics.c.

2013-09-04 Thread Adam Butcher

On 04.09.2013 03:41, Gabriel Dos Reis wrote:
On Tue, Sep 3, 2013 at 9:33 PM, Mike Stump  
wrote:
On Jul 12, 2013, at 11:18 PM, Adam Butcher  
wrote:

  * gcc/cp/semantics.c (build_lambda_expr),
  (build_lambda_object), (begin_lambda_type), 
(lambda_return_type),
  (lambda_function), (lambda_capture_field_type), 
(is_capture_proxy),

  (is_normal_capture_proxy), (insert_capture_proxy),
  (insert_pending_capture_proxies), (lambda_proxy_type),
  (build_capture_proxy), (vla_capture_type),
  (register_capture_members), (add_default_capture),
  (lambda_expr_this_capture), (maybe_resolve_dummy),
  (nonlambda_method_basetype), (maybe_add_lambda_conv_op) and
  (is_lambda_ignored_entity): Moved definitions into ...
  * gcc/cp/lambda.c: ... this new file.



This can cause an incremental build failure because there are no 
dependencies:


diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 2c1774f..65dfe08 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -351,6 +351,7 @@ cp/vtable-class-hierarchy.o: 
cp/vtable-class-hierarchy.c \
 cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) 
coretypes.h \
$(TM_H) $(CXX_TREE_H) $(TIMEVAR_H) gt-cp-name-lookup.h 
$(PARAMS_H) \

$(DIAGNOSTIC_CORE_H) $(FLAGS_H) debug.h pointer-set.h
+cp/lambda.o: cp/lambda.c $(CXX_TREE_H) $(CGRAPH_H) $(VEC_H) 
$(SYSTEM_H) coretypes.h


 cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) 
\
   $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) 
tree-pretty-print.h


When tree codes are added or moved, the check is then against the 
wrong number, and this will kill the build.


I'm still looking forward to the day when all the dependancies are 
unceremoniously ripped out, until then...


Ok?


OK.

Eek.  I didn't realize dependencies had to be manually specified.  
That's prompted me to update a more recent patchset I'm working on where 
I've introduced a new header.


Is anyone working on using some use, perhaps filtered, of -MD (or -MDD) 
to generate deps on the fly?  I haven't looked into the GCC makefile 
system in any detail but I assume dependency handling is more complex 
than the standard usage pattern for -MD or I guess someone would have 
done it already.  Or are maintainers worried that auto deps will slow 
the build down too much?  In our team's experience with using -MD the 
overhead is negligible; especially when weighed up against the effort 
required to manually maintain deps.  It just takes make a little longer 
to start actually building anything.




Re: [PATCH] [lambda] Extract lambda functions from semantics.c.

2013-09-04 Thread Adam Butcher

On 04.09.2013 20:39, Gabriel Dos Reis wrote:
On Wed, Sep 4, 2013 at 12:55 PM, Adam Butcher  
wrote:


Is anyone working on using some use, perhaps filtered, of -MD (or 
-MDD) to

generate deps on the fly?


See Tom's patch series.

Ah, yes.  Cool.  I guess it's just waiting on approval for each part; I 
note that a few front ends have already been OK'd.




Re: [PATCH 1/4] Support lambda templates.

2013-09-05 Thread Adam Butcher

On 03.09.2013 22:25, Jason Merrill wrote:

On 09/03/2013 03:50 PM, Adam Butcher wrote:

Problem is that no RTL is set for the incoming parms in the
instantiation of the expansion.  It ICEs in gimple_expand_cfg 
because 'DECL_RTL_IF_SET
(var)' returns nullptr for the incoming parms resulting in a failed 
assertion that

SA.partition_to_pseudo[i] is non-null.


Sounds like a problem with how _FUN's parameters are instantiated.
I'm not sure why it would be special.

Does using a function parameter pack in the lambda body work
currently?  If so, how are the expanded parameters different?

Yes it does work.  And I think (hope) I've cracked it; 
make_pack_expansion needs to be called in the body of the thunk (i.e. 
after start_preparsed_function).


If I butcher the implementation so that I rewrite any parameter packs 
with their expansion prior to building the call in return statement, it 
seems to work.


Certainly the following does what I expect it to, the trees look right 
and, more importantly, it doesn't ICE!


   auto g = []  (P...) -> float { return 3.f; };

   float (*pg3) (double, double, double) = g;

   return pg3(1,2,3);

I'll try to clean up what I've got then submit a rolled up patch.

Cheers,
Adam



Re: [PATCH 1/4] Support lambda templates.

2013-09-05 Thread Adam Butcher

On 05.09.2013 20:14, Adam Butcher wrote:

On 03.09.2013 22:25, Jason Merrill wrote:

On 09/03/2013 03:50 PM, Adam Butcher wrote:

Problem is that no RTL is set for the incoming parms in the
instantiation of the expansion.  It ICEs in gimple_expand_cfg 
because 'DECL_RTL_IF_SET
(var)' returns nullptr for the incoming parms resulting in a failed 
assertion that

SA.partition_to_pseudo[i] is non-null.


Sounds like a problem with how _FUN's parameters are instantiated.
I'm not sure why it would be special.

Does using a function parameter pack in the lambda body work
currently?  If so, how are the expanded parameters different?


Yes it does work.  And I think (hope) I've cracked it;
make_pack_expansion needs to be called in the body of the thunk (i.e.
after start_preparsed_function).

Okay, this worked because it had the side effect of setting 
PACK_EXPANSION_LOCAL_P on the expansion.


Doing that at the top, in the existing code seems to have the same 
effect.


Cheers,
Adam



Re: [PATCH 1/4] Support lambda templates.

2013-09-09 Thread Adam Butcher

Hi Jason,

I've attached a patch that handles parameter packs in the conversion 
op.  I thought it best to get this reviewed independently before rolling 
up into the 'Support lambda templates' patch.


Do you think it's the right idea?  It seems to work okay but I've 
reworked the way the template op call is built (and built a separate 
call for the decltype expression).


Cheers,
Adam
commit 29891189d498f5c6e3aabac72db14b94a200182c
Author: Adam Butcher 
Date:   Thu Aug 15 20:21:38 2013 +0100

[Intended for rollup into 1/4]: Handle parameter packs in lambda conversion 
op.

* lambda.c (maybe_add_lambda_conv_op): Move decls to point of use.
* TODO: parm pack changelog to be merged with PATCH 1/4.

diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index e9bc7c5..3d17948 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -741,6 +741,22 @@ nonlambda_method_basetype (void)
   return TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
 }
 
+/* Helper function for maybe_add_lambda_conv_op; build a CALL_EXPR with
+   indicated FN, and NARGS, but do not initialize the return type or any of the
+   argument slots.  */
+
+static tree
+prepare_op_call (tree fn, int nargs)
+{
+  tree t;
+
+  t = build_vl_exp (CALL_EXPR, nargs + 3);
+  CALL_EXPR_FN (t) = fn;
+  CALL_EXPR_STATIC_CHAIN (t) = NULL;
+
+  return t;
+}
+
 /* If the closure TYPE has a static op(), also add a conversion to function
pointer.  */
 
@@ -749,9 +765,6 @@ maybe_add_lambda_conv_op (tree type)
 {
   bool nested = (current_function_decl != NULL_TREE);
   tree callop = lambda_function (type);
-  tree rettype, name, fntype, fn, body, compound_stmt;
-  tree thistype, stattype, statfn, convfn, call, arg;
-  vec *argvec;
 
   if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
 return;
@@ -759,7 +772,7 @@ maybe_add_lambda_conv_op (tree type)
   if (processing_template_decl)
 return;
 
-  bool generic_lambda_p
+  bool const generic_lambda_p
 = (DECL_TEMPLATE_INFO (callop)
 && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop);
 
@@ -770,63 +783,127 @@ maybe_add_lambda_conv_op (tree type)
   return;
 }
 
+  /* Non-template conversion operators are defined directly with build_call_a
+ and using DIRECT_ARGVEC for arguments (including 'this').  Templates are
+ deferred and the CALL is built in-place.  In the case of a deduced return
+ call op, the decltype expression used as a substitute for the return type,
+ DECLTYPE_CALL is also built in-place.  The arguments of DECLTYPE_CALL in
+ the return expression may differ in flags from those in body CALL.  In
+ particular, parameter pack expansions are marked PACK_EXPANSION_LOCAL_P in
+ the body CALL, but not in DECLTYPE_CALL.  */
+
+  vec *direct_argvec;
+  tree decltype_call = 0, call;
   tree fn_result = TREE_TYPE (TREE_TYPE (callop));
-  tree fn_args = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
 
   if (generic_lambda_p)
 {
-  /* Construct the dependent member call for the static member function
-'_FUN' and remove 'auto' from its return type to allow for simple
+  /* Prepare the dependent member call for the static member function
+'_FUN' and, potentially, prepare another call to be used in a decltype
+return expression for a deduced return call op to allow for simple
 implementation of the conversion operator.  */
 
   tree instance = build_nop (type, null_pointer_node);
-  argvec = make_tree_vector ();
-  for (arg = fn_args; arg; arg = DECL_CHAIN (arg))
-   {
- mark_exp_read (arg);
- vec_safe_push (argvec, convert_from_reference (arg));
-   }
-
   tree objfn = build_min (COMPONENT_REF, NULL_TREE,
  instance, DECL_NAME (callop), NULL_TREE);
-  call = build_nt_call_vec (objfn, argvec);
+  int nargs = list_length (DECL_ARGUMENTS (callop)) - 1;
 
+  call = prepare_op_call (objfn, nargs);
   if (type_uses_auto (fn_result))
+   decltype_call = prepare_op_call (objfn, nargs);
+}
+  else
+{
+  direct_argvec = make_tree_vector ();
+  direct_argvec->quick_push (build1 (NOP_EXPR,
+TREE_TYPE (DECL_ARGUMENTS (callop)),
+null_pointer_node));
+}
+
+  /* Copy CALLOP's argument list (as per 'copy_list') as FN_ARGS in order to
+ declare the static member function "_FUN" below.  For each arg append to
+ DIRECT_ARGVEC (for the non-template case) or populate the pre-allocated
+ call args (for the template case).  If a parameter pack is found, expand
+ it, flagging it as PACK_EXPANSION_LOCAL_P for the body call.  */
+
+  tree fn_args = NULL_TREE;
+  {
+int ix = 0;
+tree src = DECL_CHAIN (DECL_ARGUMENTS (callop));
+tree tgt;
+
+while (src)
+  {
+   tree

[PATCH V4 2/2] Support using 'auto' in a function parameter list to introduce an implicit template parameter.

2013-09-09 Thread Adam Butcher
* cp-tree.h (type_uses_auto_or_concept): Declare.
(is_auto_or_concept): Declare.
* decl.c (grokdeclarator): Allow 'auto' parameters in lambdas with
-std=gnu++1y or -std=c++1y or, as a GNU extension, in plain functions.
* type-utils.h: New header defining ...
(find_type_usage): ... this new function based on pt.c (type_uses_auto)
for searching a type tree given a predicate.
* pt.c (type_uses_auto): Reimplement via type-utils.h (find_type_usage).
(is_auto_or_concept): New function.
(type_uses_auto_or_concept): New function.
* parser.h (struct cp_parser): Add fully_implicit_function_template_p.
* parser.c (cp_parser_new): Initialize 
fully_implicit_function_template_p.
(cp_parser_new): Initialize fully_implicit_function_template_p.
(cp_parser_lambda_expression): Copy and restore value of
fully_implicit_function_template_p as per other parser fields.
(cp_parser_parameter_declaration_list): Count generic
parameters and call ...
(add_implicit_template_parms): ... this new function to synthesize them
with help from type-utils.h (find_type_usage), ...
(tree_type_is_auto_or_concept): ... this new static function and ...
(make_generic_type_name): ... this new static function.
(cp_parser_direct_declarator): Account for implicit template parameters.
(cp_parser_lambda_declarator_opt): Finish fully implicit template if
necessary by calling ...
(finish_fully_implicit_template): ... this new function.
(cp_parser_member_declaration): Likewise.
(cp_parser_function_definition_after_declarator): Likewise.
* Make-lang.in (cp/pt.o): Add dependency on type-utils.h.
(cp/parser.o): Likewise.
---
 gcc/cp/Make-lang.in |   5 +-
 gcc/cp/cp-tree.h|   2 +
 gcc/cp/decl.c   |  14 +++-
 gcc/cp/parser.c | 195 ++--
 gcc/cp/parser.h |   6 ++
 gcc/cp/pt.c |  35 ++
 gcc/cp/type-utils.h |  55 +++
 7 files changed, 286 insertions(+), 26 deletions(-)
 create mode 100644 gcc/cp/type-utils.h

diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 65dfe08..e8d4913 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -320,7 +320,7 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
 cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) $(TM_P_H)
 cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \
   toplev.h $(TREE_INLINE_H) pointer-set.h gt-cp-pt.h intl.h \
-  c-family/c-objc.h
+  c-family/c-objc.h cp/type-utils.h
 cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_H) \
   $(FLAGS_H) $(REAL_H) $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H) \
   tree-diagnostic.h tree-pretty-print.h pointer-set.h c-family/c-objc.h
@@ -339,7 +339,8 @@ cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) $(REAL_H) \
   gt-cp-mangle.h $(TARGET_H) $(TM_P_H) $(CGRAPH_H)
 cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_CORE_H) \
   gt-cp-parser.h $(TARGET_H) $(PLUGIN_H) intl.h cp/decl.h \
-  c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_H)
+  c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_H) \
+  cp/type-utils.h
 cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) $(C_COMMON_H) \
$(TM_H) coretypes.h pointer-set.h tree-iterator.h $(SPLAY_TREE_H)
 cp/vtable-class-hierarchy.o: cp/vtable-class-hierarchy.c \
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3e4f188..b68562d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5455,10 +5455,12 @@ extern tree make_auto   (void);
 extern tree make_decltype_auto (void);
 extern tree do_auto_deduction  (tree, tree, tree);
 extern tree type_uses_auto (tree);
+extern tree type_uses_auto_or_concept  (tree);
 extern void append_type_to_template_for_access_check (tree, tree, tree,
  location_t);
 extern tree splice_late_return_type(tree, tree);
 extern bool is_auto(const_tree);
+extern bool is_auto_or_concept (const_tree);
 extern tree process_template_parm  (tree, location_t, tree, 
 bool, bool);
 extern tree end_template_parm_list (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b4223aa..8b67ec8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10320,8 +10320,18 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (type_uses_auto (type))
{
- error ("parameter declared %");
- type = error_mark_node;
+ if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+   {
+ if (cxx_dialect < cxx1y)
+   pedwarn (location_of (type), 0,
+"use of % in lambda par

[PATCH V4 1/2] Support lambda templates.

2013-09-09 Thread Adam Butcher
* parser.c (cp_parser_lambda_declarator_opt): Accept template parameter
list with std=c++1y or std=gnu++1y.
(cp_parser_lambda_body): Don't call 'expand_or_defer_fn' for lambda call
operator template to avoid adding template result to symbol table.
* lambda.c (lambda_function): Return template result if call operator is
a template.
(maybe_add_lambda_conv_op): Move declarations to point of use.  Refactor
operator call building in order to support conversion of a non-capturing
lambda template to a function pointer with help from ...
(prepare_op_call): ... this new function.
* decl2.c (check_member_template): Don't reject lambda call operator
template in local [lambda] class.
* pt.c (instantiate_class_template_1): Don't instantiate lambda call
operator template when instantiating lambda class.
---
 gcc/cp/decl2.c  |   5 +-
 gcc/cp/lambda.c | 189 ++--
 gcc/cp/parser.c |  40 +++-
 gcc/cp/pt.c |   4 +-
 4 files changed, 200 insertions(+), 38 deletions(-)

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d5d2912..ac9dbd7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -507,8 +507,9 @@ check_member_template (tree tmpl)
   || (TREE_CODE (decl) == TYPE_DECL
  && MAYBE_CLASS_TYPE_P (TREE_TYPE (decl
 {
-  /* The parser rejects template declarations in local classes.  */
-  gcc_assert (!current_function_decl);
+  /* The parser rejects template declarations in local classes
+(with the exception of generic lambdas).  */
+  gcc_assert (!current_function_decl || LAMBDA_FUNCTION_P (decl));
   /* The parser rejects any use of virtual in a function template.  */
   gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
&& DECL_VIRTUAL_P (decl)));
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index a53e692..2d20333 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -196,7 +196,7 @@ lambda_function (tree lambda)
  /*protect=*/0, /*want_type=*/false,
  tf_warning_or_error);
   if (lambda)
-lambda = BASELINK_FUNCTIONS (lambda);
+lambda = STRIP_TEMPLATE (get_first_fn (lambda));
   return lambda;
 }
 
@@ -741,6 +741,22 @@ nonlambda_method_basetype (void)
   return TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
 }
 
+/* Helper function for maybe_add_lambda_conv_op; build a CALL_EXPR with
+   indicated FN and NARGS, but do not initialize the return type or any of the
+   argument slots.  */
+
+static tree
+prepare_op_call (tree fn, int nargs)
+{
+  tree t;
+
+  t = build_vl_exp (CALL_EXPR, nargs + 3);
+  CALL_EXPR_FN (t) = fn;
+  CALL_EXPR_STATIC_CHAIN (t) = NULL;
+
+  return t;
+}
+
 /* If the closure TYPE has a static op(), also add a conversion to function
pointer.  */
 
@@ -749,9 +765,6 @@ maybe_add_lambda_conv_op (tree type)
 {
   bool nested = (current_function_decl != NULL_TREE);
   tree callop = lambda_function (type);
-  tree rettype, name, fntype, fn, body, compound_stmt;
-  tree thistype, stattype, statfn, convfn, call, arg;
-  vec *argvec;
 
   if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
 return;
@@ -759,6 +772,10 @@ maybe_add_lambda_conv_op (tree type)
   if (processing_template_decl)
 return;
 
+  bool const generic_lambda_p
+= (DECL_TEMPLATE_INFO (callop)
+&& DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop);
+
   if (DECL_INITIAL (callop) == NULL_TREE)
 {
   /* If the op() wasn't instantiated due to errors, give up.  */
@@ -766,16 +783,127 @@ maybe_add_lambda_conv_op (tree type)
   return;
 }
 
-  stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
- FUNCTION_ARG_CHAIN (callop));
+  /* Non-template conversion operators are defined directly with build_call_a
+ and using DIRECT_ARGVEC for arguments (including 'this').  Templates are
+ deferred and the CALL is built in-place.  In the case of a deduced return
+ call op, the decltype expression, DECLTYPE_CALL, used as a substitute for
+ the return type is also built in-place.  The arguments of DECLTYPE_CALL in
+ the return expression may differ in flags from those in the body CALL.  In
+ particular, parameter pack expansions are marked PACK_EXPANSION_LOCAL_P in
+ the body CALL, but not in DECLTYPE_CALL.  */
+
+  vec *direct_argvec;
+  tree decltype_call = 0, call;
+  tree fn_result = TREE_TYPE (TREE_TYPE (callop));
+
+  if (generic_lambda_p)
+{
+  /* Prepare the dependent member call for the static member function
+'_FUN' and, potentially, prepare another call to be used in a decltype
+return expression for a deduced return call op to allow for simple
+implementation of the conversion operator.  */
+
+  tree instance = build_nop (type, null_pointer_node);
+  tree objfn = build_min (COMPONENT_REF,

V4 Lambda templates and implicit function templates.

2013-09-09 Thread Adam Butcher
Hi Jason,

Here's the latest patch set; reduced to two patches now.

Remaining issues:
 - Instantiation of generic conversion op ICEs if the call op contains
   declarations and hasn't already been instantiated.
 - Still haven't figured out a clean way to make 'auto...' work.

Cheers,
Adam

Patch summary (2):
  Support lambda templates.
  Support using 'auto' in a function parameter list to introduce an
implicit template parameter.

 gcc/cp/Make-lang.in |   5 +-
 gcc/cp/cp-tree.h|   2 +
 gcc/cp/decl.c   |  14 +++-
 gcc/cp/decl2.c  |   5 +-
 gcc/cp/lambda.c | 189 +++---
 gcc/cp/parser.c | 235 +---
 gcc/cp/parser.h |   6 ++
 gcc/cp/pt.c |  39 +
 gcc/cp/type-utils.h |  55 
 9 files changed, 486 insertions(+), 64 deletions(-)
 create mode 100644 gcc/cp/type-utils.h

-- 
1.8.4



Re: V4 Lambda templates and implicit function templates.

2013-09-11 Thread Adam Butcher

On 10.09.2013 03:19, Adam Butcher wrote:
 - Instantiation of generic conversion op ICEs if the call op 
contains

   declarations and hasn't already been instantiated.

This is not a complete enough description.  It only ICEs instantiating 
the call op through the decltype return of the conversion op if the 
return type of the call op is a deduced one (i.e. unspecified or 
specified explicitly as 'auto').  If the lambda call op is instantiated 
explicitly (i.e. the lambda is called) prior to using the conversion op 
then all is well.  It seems to only occur if there are variables 
declared within the lambda body or accessible via the lambda's 'this'.


Specifically, the ICE is in tsubst_decl (cp/pt.c:10839) asserting 
'gcc_unreachable' due to being 'cp_unevaluated_operand'.  The 
instantiation chain starts from attempting to 'mark_used' the call op in 
the decltype expression.


The same ICE can be caused in user code by attempting to take get 
decltype of a generic lambda call having a deduced return type and 
declarations:


This is fine:

   auto f = []  (T) {};
   decltype (f (4.f)) *p;

This is not; it ICEs doing 'tsubst_decl' on the declaration 'x'.

   auto f = []  (T) { int x; };
   decltype (f (4.f)) *p;

The conversion op is clearly not a factor here but can be removed from 
the equation completely by adding a capture.  The ICE still occurs.  In 
this case it occurs trying to do 'tsubst_decl' on the capture decl 'i'.


   int i = 0;
   auto f = [i]  (T) {};
   decltype (f (4.f)) *p;

ice.cpp: In instantiation of ‘main():: [with T = float]’:
ice.cpp:5:20:   required from here
ice.cpp:4:34: internal compiler error: in tsubst_decl, at cp/pt.c:10839
auto f = [i]  (T) {};
  ^
Any ideas?  Looks like it's something to do with how the call operator 
is defined.  Is there some flag I'm missing in the generic case?


Cheers,
Adam



Re: V4 Lambda templates and implicit function templates.

2013-09-11 Thread Adam Butcher

On 11.09.2013 16:25, Jason Merrill wrote:

On 09/11/2013 10:42 AM, Jason Merrill wrote:
Sounds like the problem is that the compiler is trying to 
instantiate a
function while cp_unevaluated_operand is set.  But that shouldn't be 
an
issue because push_to_top_level clears cp_unevaluated_operand.  How 
does

it come to be set when instantiating the local variable?


Ah, I see: it's because instantiate_decl doesn't push_to_top_level
for function-local templates.  We still need to save/restore
cp_unevaluated_operand in that case, and let's also do
c_inhibit_evaluation_warnings.

Great, that fixes it.  Hadn't noticed it didn't happen a namespace 
scope.


Okay for the attached to go to trunk with suitable changelog?
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 22087fb..16e57b5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18947,6 +18947,8 @@ instantiate_decl (tree d, int defer_ok,
   tree gen_tmpl;
   bool pattern_defined;
   location_t saved_loc = input_location;
+  int saved_unevaluated_operand = cp_unevaluated_operand;
+  int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
   bool external_p;
   tree fn_context;
   bool nested;
@@ -19158,8 +19160,13 @@ instantiate_decl (tree d, int defer_ok,
   nested = (current_function_decl != NULL_TREE);
   if (!fn_context)
 push_to_top_level ();
-  else if (nested)
-push_function_context ();
+  else
+{
+  if (nested)
+	push_function_context ();
+  cp_unevaluated_operand = 0;
+  c_inhibit_evaluation_warnings = 0;
+}
 
   /* Mark D as instantiated so that recursive calls to
  instantiate_decl do not try to instantiate it again.  */
@@ -19283,6 +19290,8 @@ instantiate_decl (tree d, int defer_ok,
 
 out:
   input_location = saved_loc;
+  cp_unevaluated_operand = saved_unevaluated_operand;
+  c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
   pop_deferring_access_checks ();
   pop_tinst_level ();
 


Re: [PATCH V4 2/2] Support using 'auto' in a function parameter list to introduce an implicit template parameter.

2013-09-12 Thread Adam Butcher

On 11.09.2013 17:02, Jason Merrill wrote:

On 09/09/2013 10:19 PM, Adam Butcher wrote:

+ if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+   {
+ if (cxx_dialect < cxx1y)
+   pedwarn (location_of (type), 0,
+"use of % in lambda parameter declaration "
+"only available with "
+"-std=c++1y or -std=gnu++1y");
+   }
+ else
+   pedwarn (location_of (type), OPT_Wpedantic,
+"ISO C++ forbids use of % in parameter "
+"declaration");


I think we want to limit the implicit template extension to C++1y
mode as well.

OK.  Do you think we should mark 'type' as 'error_mark_node' in the 
pre-C++1y cases to reject the user program or just stick to the pedwarn 
0?


I.e. this:

   if (current_class_type && LAMBDA_TYPE_P (current_class_type))
 {
   if (cxx_dialect < cxx1y)
 {
   pedwarn (location_of (type), 0,
"use of % in lambda parameter declaration "
"only available with "
"-std=c++1y or -std=gnu++1y");
   type = error_mark_node;
 }
 }
   else if (cxx_dialect < cxx1y)
 {
   pedwarn (location_of (type), 0,
"use of % in parameter declaration "
"only available with "
"-std=c++1y or -std=gnu++1y");
   type = error_mark_node;
 }
   else
 pedwarn (location_of (type), OPT_Wpedantic,
  "ISO C++ forbids use of % in parameter "
  "declaration");


or the same but without the  "type = error_mark_node;"  lines?



[PATCH, committed] Support decl instantiation in function-local templates.

2013-09-12 Thread Adam Butcher
From: abutcher 

* pt.c (instantiate_decl): Save/restore cp_unevaluated_operand and
c_inhibit_evaluation_warnings.  Reset if instantiating within a
function-local template.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202538 
138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog |  6 ++
 gcc/cp/pt.c  | 13 +++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9c99970..cbad022 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-12  Adam Butcher  
+
+   * pt.c (instantiate_decl): Save/restore cp_unevaluated_operand and
+   c_inhibit_evaluation_warnings.  Reset if instantiating within a
+   function-local template.
+
 2013-09-12  Paolo Carlini  
 
* semantics.c (finish_pseudo_destructor_expr): Add location_t
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e4ae4b7..3ae679a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18947,6 +18947,8 @@ instantiate_decl (tree d, int defer_ok,
   tree gen_tmpl;
   bool pattern_defined;
   location_t saved_loc = input_location;
+  int saved_unevaluated_operand = cp_unevaluated_operand;
+  int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
   bool external_p;
   tree fn_context;
   bool nested;
@@ -19158,8 +19160,13 @@ instantiate_decl (tree d, int defer_ok,
   nested = (current_function_decl != NULL_TREE);
   if (!fn_context)
 push_to_top_level ();
-  else if (nested)
-push_function_context ();
+  else
+{
+  if (nested)
+   push_function_context ();
+  cp_unevaluated_operand = 0;
+  c_inhibit_evaluation_warnings = 0;
+}
 
   /* Mark D as instantiated so that recursive calls to
  instantiate_decl do not try to instantiate it again.  */
@@ -19283,6 +19290,8 @@ instantiate_decl (tree d, int defer_ok,
 
 out:
   input_location = saved_loc;
+  cp_unevaluated_operand = saved_unevaluated_operand;
+  c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
   pop_deferring_access_checks ();
   pop_tinst_level ();
 
-- 
1.8.4



[PATCH, committed] Support using 'auto' in a function parameter list to introduce an implicit template parameter.

2013-09-12 Thread Adam Butcher
From: abutcher 

* cp-tree.h (type_uses_auto_or_concept): Declare.
(is_auto_or_concept): Declare.
* decl.c (grokdeclarator): Allow 'auto' parameters in lambdas with
-std=gnu++1y or -std=c++1y or, as a GNU extension, in plain functions.
* type-utils.h: New header defining ...
(find_type_usage): ... this new function based on pt.c (type_uses_auto)
for searching a type tree given a predicate.
* pt.c (type_uses_auto): Reimplement via type-utils.h (find_type_usage).
(is_auto_or_concept): New function.
(type_uses_auto_or_concept): New function.
* parser.h (struct cp_parser): Add fully_implicit_function_template_p.
* parser.c (cp_parser_new): Initialize 
fully_implicit_function_template_p.
(cp_parser_new): Initialize fully_implicit_function_template_p.
(cp_parser_lambda_expression): Copy and restore value of
fully_implicit_function_template_p as per other parser fields.
(cp_parser_parameter_declaration_list): Count generic
parameters and call ...
(add_implicit_template_parms): ... this new function to synthesize them
with help from type-utils.h (find_type_usage), ...
(tree_type_is_auto_or_concept): ... this new static function and ...
(make_generic_type_name): ... this new static function.
(cp_parser_direct_declarator): Account for implicit template parameters.
(cp_parser_lambda_declarator_opt): Finish fully implicit template if
necessary by calling ...
(finish_fully_implicit_template): ... this new function.
(cp_parser_member_declaration): Likewise.
(cp_parser_function_definition_after_declarator): Likewise.
* Make-lang.in (cp/pt.o): Add dependency on type-utils.h.
(cp/parser.o): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202540 
138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog|  32 +
 gcc/cp/Make-lang.in |   5 +-
 gcc/cp/cp-tree.h|   2 +
 gcc/cp/decl.c   |  19 -
 gcc/cp/parser.c | 195 ++--
 gcc/cp/parser.h |   6 ++
 gcc/cp/pt.c |  35 ++
 gcc/cp/type-utils.h |  55 +++
 8 files changed, 323 insertions(+), 26 deletions(-)
 create mode 100644 gcc/cp/type-utils.h

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 66869d2..470fa1f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,37 @@
 2013-09-12  Adam Butcher  
 
+   * cp-tree.h (type_uses_auto_or_concept): Declare.
+   (is_auto_or_concept): Declare.
+   * decl.c (grokdeclarator): Allow 'auto' parameters in lambdas with
+   -std=gnu++1y or -std=c++1y or, as a GNU extension, in plain functions.
+   * type-utils.h: New header defining ...
+   (find_type_usage): ... this new function based on pt.c (type_uses_auto)
+   for searching a type tree given a predicate.
+   * pt.c (type_uses_auto): Reimplement via type-utils.h (find_type_usage).
+   (is_auto_or_concept): New function.
+   (type_uses_auto_or_concept): New function.
+   * parser.h (struct cp_parser): Add fully_implicit_function_template_p.
+   * parser.c (cp_parser_new): Initialize 
fully_implicit_function_template_p.
+   (cp_parser_new): Initialize fully_implicit_function_template_p.
+   (cp_parser_lambda_expression): Copy and restore value of
+   fully_implicit_function_template_p as per other parser fields.
+   (cp_parser_parameter_declaration_list): Count generic
+   parameters and call ...
+   (add_implicit_template_parms): ... this new function to synthesize them
+   with help from type-utils.h (find_type_usage), ...
+   (tree_type_is_auto_or_concept): ... this new static function and ...
+   (make_generic_type_name): ... this new static function.
+   (cp_parser_direct_declarator): Account for implicit template parameters.
+   (cp_parser_lambda_declarator_opt): Finish fully implicit template if
+   necessary by calling ...
+   (finish_fully_implicit_template): ... this new function.
+   (cp_parser_member_declaration): Likewise.
+   (cp_parser_function_definition_after_declarator): Likewise.
+   * Make-lang.in (cp/pt.o): Add dependency on type-utils.h.
+   (cp/parser.o): Likewise.
+
+2013-09-12  Adam Butcher  
+
* parser.c (cp_parser_lambda_declarator_opt): Accept template parameter
list with std=c++1y or std=gnu++1y.
(cp_parser_lambda_body): Don't call 'expand_or_defer_fn' for lambda call
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 65dfe08..e8d4913 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -320,7 +320,7 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
 cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) $(TM_P_H)
 cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \
   toplev.h $(TREE

[PATCH, committed] Support lambda templates.

2013-09-12 Thread Adam Butcher
From: abutcher 

* parser.c (cp_parser_lambda_declarator_opt): Accept template parameter
list with std=c++1y or std=gnu++1y.
(cp_parser_lambda_body): Don't call 'expand_or_defer_fn' for lambda call
operator template to avoid adding template result to symbol table.
* lambda.c (lambda_function): Return template result if call operator is
a template.
(maybe_add_lambda_conv_op): Move declarations to point of use.  Refactor
operator call building in order to support conversion of a non-capturing
lambda template to a function pointer with help from ...
(prepare_op_call): ... this new function.
* decl2.c (check_member_template): Don't reject lambda call operator
template in local [lambda] class.
* pt.c (instantiate_class_template_1): Don't instantiate lambda call
operator template when instantiating lambda class.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202539 
138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog |  17 +
 gcc/cp/decl2.c   |   5 +-
 gcc/cp/lambda.c  | 189 +--
 gcc/cp/parser.c  |  40 +++-
 gcc/cp/pt.c  |   4 +-
 5 files changed, 217 insertions(+), 38 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index cbad022..66869d2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,22 @@
 2013-09-12  Adam Butcher  
 
+   * parser.c (cp_parser_lambda_declarator_opt): Accept template parameter
+   list with std=c++1y or std=gnu++1y.
+   (cp_parser_lambda_body): Don't call 'expand_or_defer_fn' for lambda call
+   operator template to avoid adding template result to symbol table.
+   * lambda.c (lambda_function): Return template result if call operator is
+   a template.
+   (maybe_add_lambda_conv_op): Move declarations to point of use.  Refactor
+   operator call building in order to support conversion of a non-capturing
+   lambda template to a function pointer with help from ...
+   (prepare_op_call): ... this new function.
+   * decl2.c (check_member_template): Don't reject lambda call operator
+   template in local [lambda] class.
+   * pt.c (instantiate_class_template_1): Don't instantiate lambda call
+   operator template when instantiating lambda class.
+
+2013-09-12  Adam Butcher  
+
* pt.c (instantiate_decl): Save/restore cp_unevaluated_operand and
c_inhibit_evaluation_warnings.  Reset if instantiating within a
function-local template.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d5d2912..ac9dbd7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -507,8 +507,9 @@ check_member_template (tree tmpl)
   || (TREE_CODE (decl) == TYPE_DECL
  && MAYBE_CLASS_TYPE_P (TREE_TYPE (decl
 {
-  /* The parser rejects template declarations in local classes.  */
-  gcc_assert (!current_function_decl);
+  /* The parser rejects template declarations in local classes
+(with the exception of generic lambdas).  */
+  gcc_assert (!current_function_decl || LAMBDA_FUNCTION_P (decl));
   /* The parser rejects any use of virtual in a function template.  */
   gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
&& DECL_VIRTUAL_P (decl)));
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index a53e692..2d20333 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -196,7 +196,7 @@ lambda_function (tree lambda)
  /*protect=*/0, /*want_type=*/false,
  tf_warning_or_error);
   if (lambda)
-lambda = BASELINK_FUNCTIONS (lambda);
+lambda = STRIP_TEMPLATE (get_first_fn (lambda));
   return lambda;
 }
 
@@ -741,6 +741,22 @@ nonlambda_method_basetype (void)
   return TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
 }
 
+/* Helper function for maybe_add_lambda_conv_op; build a CALL_EXPR with
+   indicated FN and NARGS, but do not initialize the return type or any of the
+   argument slots.  */
+
+static tree
+prepare_op_call (tree fn, int nargs)
+{
+  tree t;
+
+  t = build_vl_exp (CALL_EXPR, nargs + 3);
+  CALL_EXPR_FN (t) = fn;
+  CALL_EXPR_STATIC_CHAIN (t) = NULL;
+
+  return t;
+}
+
 /* If the closure TYPE has a static op(), also add a conversion to function
pointer.  */
 
@@ -749,9 +765,6 @@ maybe_add_lambda_conv_op (tree type)
 {
   bool nested = (current_function_decl != NULL_TREE);
   tree callop = lambda_function (type);
-  tree rettype, name, fntype, fn, body, compound_stmt;
-  tree thistype, stattype, statfn, convfn, call, arg;
-  vec *argvec;
 
   if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
 return;
@@ -759,6 +772,10 @@ maybe_add_lambda_conv_op (tree type)
   if (processing_template_decl)
 return;
 
+  bool const generic_lambda_p
+= (DECL_TEMPLATE_INFO (callop)
+&& DECL_TEMPLATE_RESULT (DECL_TI_

Re: [PATCH, committed] Support lambda templates.

2013-09-12 Thread Adam Butcher

On 12.09.2013 23:44, Andrew MacLeod wrote:

On 09/12/2013 06:41 PM, Andrew MacLeod wrote:

On 09/12/2013 05:55 PM, Tobias Burnus wrote:

Adam Butcher wrote:

From: abutcher 
* lambda.c (lambda_function): Return template result if call 
operator is

a template.


I believe that that patch causes the following build failure of 
cp/lambda.c:


In file included from ../../gcc/tree-core.h:27:0,
 from ../../gcc/tree.h:23,
 from ../../gcc/cp/lambda.c:27:
../../gcc/vec.h: In function 'void maybe_add_lambda_conv_op(tree)':
../../gcc/vec.h:626:44: error: 'direct_argvec' may be used 
uninitialized in this function [-Werror=maybe-uninitialized]

 vec_safe_space (const vec *v, unsigned nelems)
^
../../gcc/cp/lambda.c:795:21: note: 'direct_argvec' was declared 
here

   vec *direct_argvec;


Tobias

PS: I am not positive since I use a patched tree and I haven't 
bisected.
I have verified that is the patch set causing the same issue for me. 
I backed out that revision  and everything is fine.


Andrew

Only locally of course to verify... :-P

Sorry about this.  I had built without -Werror.  I believed this 
warning to be a false-positive with the maybe-uninitialized code which I 
thought might be fixed later.  I will commit a fix to initialize these 
pointers to 0.




[PATCH, committed] Fix uninitialized variables causing breakage with -Werror.

2013-09-12 Thread Adam Butcher
From: abutcher 

* lambda.c (maybe_add_lambda_conv_op): Initialize direct_argvec and call
to nullptr to avoid breakage with -Werror.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202554 
138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog | 5 +
 gcc/cp/lambda.c  | 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 68c8ea4..80e0d96 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2013-09-13  Adam Butcher  
+
+   * lambda.c (maybe_add_lambda_conv_op): Initialize direct_argvec and call
+   to nullptr to avoid breakage with -Werror.
+
 2013-09-12  Brooks Moses  
 
PR driver/42955
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 2d20333..0da22fd 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -792,8 +792,8 @@ maybe_add_lambda_conv_op (tree type)
  particular, parameter pack expansions are marked PACK_EXPANSION_LOCAL_P in
  the body CALL, but not in DECLTYPE_CALL.  */
 
-  vec *direct_argvec;
-  tree decltype_call = 0, call;
+  vec *direct_argvec = 0;
+  tree decltype_call = 0, call = 0;
   tree fn_result = TREE_TYPE (TREE_TYPE (callop));
 
   if (generic_lambda_p)
-- 
1.8.4



Re: [PATCH, committed] Support lambda templates.

2013-09-12 Thread Adam Butcher

On 13.09.2013 07:17, Adam Butcher wrote:

On 12.09.2013 23:44, Andrew MacLeod wrote:

On 09/12/2013 06:41 PM, Andrew MacLeod wrote:

On 09/12/2013 05:55 PM, Tobias Burnus wrote:

Adam Butcher wrote:

From: abutcher 
* lambda.c (lambda_function): Return template result if call 
operator is

a template.


I believe that that patch causes the following build failure of 
cp/lambda.c:


In file included from ../../gcc/tree-core.h:27:0,
 from ../../gcc/tree.h:23,
 from ../../gcc/cp/lambda.c:27:
../../gcc/vec.h: In function 'void 
maybe_add_lambda_conv_op(tree)':
../../gcc/vec.h:626:44: error: 'direct_argvec' may be used 
uninitialized in this function [-Werror=maybe-uninitialized]

 vec_safe_space (const vec *v, unsigned nelems)
^
../../gcc/cp/lambda.c:795:21: note: 'direct_argvec' was declared 
here

   vec *direct_argvec;


Tobias

PS: I am not positive since I use a patched tree and I haven't 
bisected.
I have verified that is the patch set causing the same issue for 
me. I backed out that revision  and everything is fine.


Andrew

Only locally of course to verify... :-P


Sorry about this.  I had built without -Werror.  I believed this
warning to be a false-positive with the maybe-uninitialized code 
which

I thought might be fixed later.  I will commit a fix to initialize
these pointers to 0.


Fixed in 202554.



Re: [PATCH, committed] Support using 'auto' in a function parameter list to introduce an implicit template parameter.

2013-09-13 Thread Adam Butcher

On 13.09.2013 13:26, Andreas Schwab wrote:

FAIL: g++.dg/cpp0x/auto3.C -std=c++11  (test for errors, line 24)
FAIL: g++.dg/cpp0x/auto3.C -std=c++11 (test for excess errors)
Excess errors:
: error: use of 'auto' in parameter declaration only 
available with -std=c++1y or -std=gnu++1y


I'm on it.  Specifically, I am looking into the following on the 
assumption that it is my commits that stuffed them:


FAIL: g++.dg/cpp0x/auto3.C -std=c++11  (test for errors, line 24)
FAIL: g++.dg/cpp0x/auto3.C -std=c++11  (test for errors, line 24)
FAIL: g++.dg/cpp0x/auto3.C -std=c++11 (test for excess errors)
FAIL: g++.dg/cpp0x/auto3.C -std=c++11 (test for excess errors)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 115)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 115)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 120)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 120)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 121)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 121)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 82)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 82)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 83)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 83)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 84)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 84)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 85)
FAIL: g++.dg/cpp0x/auto9.C  (test for errors, line 85)
FAIL: g++.dg/cpp0x/auto9.C (test for excess errors)
FAIL: g++.dg/cpp0x/auto9.C (test for excess errors)
FAIL: g++.dg/cpp0x/lambda/lambda-conv4.C (internal compiler error)
FAIL: g++.dg/cpp0x/lambda/lambda-conv4.C (internal compiler error)
FAIL: g++.dg/cpp0x/lambda/lambda-conv4.C (test for excess errors)
FAIL: g++.dg/cpp0x/lambda/lambda-conv4.C (test for excess errors)
FAIL: g++.dg/cpp0x/lambda/lambda-eh2.C execution test
FAIL: g++.dg/cpp0x/lambda/lambda-eh2.C execution test
FAIL: g++.dg/cpp0x/lambda/lambda-nested4.C (internal compiler error)
FAIL: g++.dg/cpp0x/lambda/lambda-nested4.C (internal compiler error)
FAIL: g++.dg/cpp0x/lambda/lambda-nested4.C (test for excess errors)
FAIL: g++.dg/cpp0x/lambda/lambda-nested4.C (test for excess errors)
FAIL: g++.dg/cpp0x/lambda/lambda-template11.C -std=c++11 (internal 
compiler error)
FAIL: g++.dg/cpp0x/lambda/lambda-template11.C -std=c++11 (internal 
compiler error)
FAIL: g++.dg/cpp0x/lambda/lambda-template11.C -std=c++11 (test for 
excess errors)
FAIL: g++.dg/cpp0x/lambda/lambda-template11.C -std=c++11 (test for 
excess errors)


Apologies for not doing before-and-after test run prior to pushing.

Cheers,
Adam



Generic lambda and implicit function template commits reverted

2013-09-13 Thread Adam Butcher


r202570 | abutcher | 2013-09-13 17:14:15 +0100 (Fri, 13 Sep 2013) | 7 
lines


Revert r202554, r202540 and r202539.

 - r202554: Fix uninitialized variables causing breakage with -Werror.
 - r202540: Support using 'auto' in a function parameter list to 
introduce an implicit template parameter.

 - r202539: Support lambda templates.


There's some additional work needed before these are ready for trunk.  
Specifically, I need to make sure there are no test regressions.


Cheers,
Adam



Re: Generic lambda and implicit function template commits reverted

2013-09-15 Thread Adam Butcher

Hi Jason,

Could you cast your eyes over these changes please?  I intend to roll
them up into the appropriate patches.  I will make sure I bootstrap
and "before-and-after" the g++.dg testsuite before pushing next time!


[PATCH 1/5] Fix uninitialized variables causing breakage with -Werror.

  Not actually sure that this should be necessary.  Initialization of
  'direct_argvec' and 'call' and subsequent references are behind
  '!generic_lambda_p' and 'generic_lambda_p' tests respectively.
  'generic_lambda_p' is declared 'const bool'.
  To pacify -Wmaybe-uninitialized, I have initialized them to 0.


[PATCH 2/5] Don't accept 'auto' as the 'type' of a template parameter.

  The implicit function template code was incorrectly firing in a 
template

  parameter list.


[PATCH 3/5] Fix location diagnostics by returning to the deprecated
'input_location' global; must be a better fix for this.

  Don't know why 'location_of (type)' gave ":" rather than
  "file:line:col:".  My current workaround is to return to using
  'input_location'.  This gives the correct result but I doubt it is
  acceptable.


[PATCH 4/5] Lift CALL_FROM_THUNK_P setting to above the potential
'build_cplus_new' call to prevent ICE due to unexpected tree type.

  Plain old bug which I introduced when reorganizing the conversion op 
code.



[PATCH 5/5] Handle forward declaration of implicit function templates.
Previously kept template parameter types in scope.

  Another bug.  Template parameter list erroneously left in scope.


Cheers,
Adam


[PATCH 1/5] Fix uninitialized variables causing breakage with -Werror.
---
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 2d20333..0da22fd 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -792,8 +792,8 @@ maybe_add_lambda_conv_op (tree type)
  particular, parameter pack expansions are marked 
PACK_EXPANSION_LOCAL_P in

  the body CALL, but not in DECLTYPE_CALL.  */

-  vec *direct_argvec;
-  tree decltype_call = 0, call;
+  vec *direct_argvec = 0;
+  tree decltype_call = 0, call = 0;
   tree fn_result = TREE_TYPE (TREE_TYPE (callop));

   if (generic_lambda_p)
--


[PATCH 2/5] Don't accept 'auto' as the 'type' of a template parameter.
---
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e6e24f8..6a4e863 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10323,7 +10323,12 @@ grokdeclarator (const cp_declarator 
*declarator,


   if (type_uses_auto (type))
{
- if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+ if (template_parm_flag)
+   {
+ error ("template parameter declared %");
+ type = error_mark_node;
+   }
+ else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
{
  if (cxx_dialect < cxx1y)
pedwarn (location_of (type), 0,
--


[PATCH 3/5] Fix location diagnostics by returning to the deprecated 
'input_location' global; must be a better fix for this.


Using 'location_of (type)' yields ": " rather than 
"file:line:col: "

---
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6a4e863..a948580 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10331,18 +10331,18 @@ grokdeclarator (const cp_declarator 
*declarator,

  else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
{
  if (cxx_dialect < cxx1y)
-   pedwarn (location_of (type), 0,
+   pedwarn (input_location, 0,
 "use of % in lambda parameter declaration "
 "only available with "
 "-std=c++1y or -std=gnu++1y");
}
  else if (cxx_dialect < cxx1y)
-   pedwarn (location_of (type), 0,
+   pedwarn (input_location, 0,
 "use of % in parameter declaration "
 "only available with "
 "-std=c++1y or -std=gnu++1y");
  else
-   pedwarn (location_of (type), OPT_Wpedantic,
+   pedwarn (input_location, OPT_Wpedantic,
 "ISO C++ forbids use of % in parameter "
 "declaration");
}
--


[PATCH 4/5] Lift CALL_FROM_THUNK_P setting to above the potential 
'build_cplus_new' call to prevent ICE due to unexpected tree type.

---
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 0da22fd..0154840 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -883,16 +883,17 @@ maybe_add_lambda_conv_op (tree type)
 tf_warning_or_error);
  --processing_template_decl;
}
+  CALL_FROM_THUNK_P (call) = 1;
 }
   else
 {
   call = build_call_a (callop,
   direct_argvec->length (),
   direct_argvec->address ());
+  CALL_FROM_THUNK_P (call) = 1;
   if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
 }
-  CALL_FROM_THUNK_P (call

Re: Generic lambda and implicit function template commits reverted

2013-09-15 Thread Adam Butcher

On 15.09.2013 15:45, Jason Merrill wrote:

On 09/15/2013 06:22 AM, Adam Butcher wrote:
[PATCH 1/5] Fix uninitialized variables causing breakage with 
-Werror.
[PATCH 2/5] Don't accept 'auto' as the 'type' of a template 
parameter.


OK.



I've also added a case for rejecting 'auto' in a catch parameter.



[PATCH 3/5] Fix location diagnostics by returning to the deprecated
 'input_location' global; must be a better fix for this.

   Don't know why 'location_of (type)' gave ":" rather 
than

   "file:line:col:".  My current workaround is to return to using
   'input_location'.  This gives the correct result but I doubt it 
is

   acceptable.


This seems to be because make_auto_1 sets the location of the auto
type to BUILTINS_LOCATION; I don't remember why I did that.  Changing
it to use input_location seems appropriate.



Thanks.  Doing that makes this patch unnecessary.



[PATCH 4/5] Lift CALL_FROM_THUNK_P setting to above the potential
 'build_cplus_new' call to prevent ICE due to unexpected 
tree type.




Rather than this, I've moved the call to 'build_cplus_new' back down to 
after 'start_preparsed_function' as I needed to call 
'set_flags_from_callee' prior to it but within function scope to prevent 
regression of 49260 and 47263.


Deltas below.  No regressions in g++.dg with these updates.

Cheers,
Adam



Subject: [PATCH] * pt.c (make_auto_1): Use input_location rather than 
BUILTINS_LOCATION.

---
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 58f920e..70f13bb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -20925,7 +20925,7 @@ static tree
 make_auto_1 (tree name)
 {
   tree au = cxx_make_type (TEMPLATE_TYPE_PARM);
-  TYPE_NAME (au) = build_decl (BUILTINS_LOCATION,
+  TYPE_NAME (au) = build_decl (input_location,
   TYPE_DECL, name, au);
   TYPE_STUB_DECL (au) = TYPE_NAME (au);
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
--


[PATCH] Move 'build_cplus_new' call to after 'start_preparsed_function' 
and call 'set_flags_from_callee' prior to prevent ICE due to unexpected 
tree type and fix exception handling.

---
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 0da22fd..c9118d8 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -885,13 +885,10 @@ maybe_add_lambda_conv_op (tree type)
}
 }
   else
-{
 call = build_call_a (callop,
 direct_argvec->length (),
 direct_argvec->address ());
-  if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
-   call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
-}
+
   CALL_FROM_THUNK_P (call) = 1;

   tree stattype = build_function_type (fn_result, FUNCTION_ARG_CHAIN 
(callop));

@@ -987,6 +984,12 @@ maybe_add_lambda_conv_op (tree type)
 }
   tree body = begin_function_body ();
   tree compound_stmt = begin_compound_stmt (0);
+  if (!generic_lambda_p)
+{
+  set_flags_from_callee (call);
+  if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
+   call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
+}
   call = convert_from_reference (call);
   finish_return_stmt (call);

--


[PATCH] Don't allow 'auto' in type of catch parameter.
---
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6a4e863..80ceca1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10328,6 +10328,11 @@ grokdeclarator (const cp_declarator 
*declarator,

  error ("template parameter declared %");
  type = error_mark_node;
}
+ else if (decl_context == CATCHPARM)
+   {
+ error ("catch parameter declared %");
+ type = error_mark_node;
+   }
  else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
{
  if (cxx_dialect < cxx1y)
--


[PATCH] cpp0x/auto9.C: Downgrade expected error to expected pedwarn.
---
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C 
b/gcc/testsuite/g++.dg/cpp0x/auto9.C

index 190bfa6..f357f2b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C
@@ -117,8 +117,8 @@ template  struct G {};		// { dg-error 
"auto" }

 template  struct H { H (); ~H (); };
 H h;   // { dg-error "invalid" }

-void qq (auto);// { dg-error "auto" }
-void qr (auto*);   // { dg-error "auto" }
+void qq (auto);// { dg-warning "auto" }
+void qr (auto*);   // { dg-warning "auto" }

 // PR c++/46145
 typedef auto autot;// { dg-error "auto" }
--





[PATCH, committed] * pt.c (make_auto_1): Use input_location rather than BUILTINS_LOCATION.

2013-09-16 Thread Adam Butcher
---
 gcc/cp/pt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2ef160a..ed08dca 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21041,7 +21041,7 @@ static tree
 make_auto_1 (tree name)
 {
   tree au = cxx_make_type (TEMPLATE_TYPE_PARM);
-  TYPE_NAME (au) = build_decl (BUILTINS_LOCATION,
+  TYPE_NAME (au) = build_decl (input_location,
   TYPE_DECL, name, au);
   TYPE_STUB_DECL (au) = TYPE_NAME (au);
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
-- 
1.8.4



[PATCH, re-committed] Support lambda templates.

2013-09-16 Thread Adam Butcher
From: abutcher 

* parser.c (cp_parser_lambda_declarator_opt): Accept template parameter
list with std=c++1y or std=gnu++1y.
(cp_parser_lambda_body): Don't call 'expand_or_defer_fn' for lambda call
operator template to avoid adding template result to symbol table.
* lambda.c (lambda_function): Return template result if call operator is
a template.
(maybe_add_lambda_conv_op): Move declarations to point of use.  Refactor
operator call building in order to support conversion of a non-capturing
lambda template to a function pointer with help from ...
(prepare_op_call): ... this new function.
* decl2.c (check_member_template): Don't reject lambda call operator
template in local [lambda] class.
* pt.c (instantiate_class_template_1): Don't instantiate lambda call
operator template when instantiating lambda class.
---
 gcc/cp/decl2.c  |   5 +-
 gcc/cp/lambda.c | 188 +++-
 gcc/cp/parser.c |  40 +++-
 gcc/cp/pt.c |   4 +-
 4 files changed, 201 insertions(+), 36 deletions(-)

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index c518551..4ac9445 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -502,8 +502,9 @@ check_member_template (tree tmpl)
   || (TREE_CODE (decl) == TYPE_DECL
  && MAYBE_CLASS_TYPE_P (TREE_TYPE (decl
 {
-  /* The parser rejects template declarations in local classes.  */
-  gcc_assert (!current_function_decl);
+  /* The parser rejects template declarations in local classes
+(with the exception of generic lambdas).  */
+  gcc_assert (!current_function_decl || LAMBDA_FUNCTION_P (decl));
   /* The parser rejects any use of virtual in a function template.  */
   gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
&& DECL_VIRTUAL_P (decl)));
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 1af301d..b04448b 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -196,7 +196,7 @@ lambda_function (tree lambda)
  /*protect=*/0, /*want_type=*/false,
  tf_warning_or_error);
   if (lambda)
-lambda = BASELINK_FUNCTIONS (lambda);
+lambda = STRIP_TEMPLATE (get_first_fn (lambda));
   return lambda;
 }
 
@@ -775,6 +775,22 @@ nonlambda_method_basetype (void)
   return TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
 }
 
+/* Helper function for maybe_add_lambda_conv_op; build a CALL_EXPR with
+   indicated FN and NARGS, but do not initialize the return type or any of the
+   argument slots.  */
+
+static tree
+prepare_op_call (tree fn, int nargs)
+{
+  tree t;
+
+  t = build_vl_exp (CALL_EXPR, nargs + 3);
+  CALL_EXPR_FN (t) = fn;
+  CALL_EXPR_STATIC_CHAIN (t) = NULL;
+
+  return t;
+}
+
 /* If the closure TYPE has a static op(), also add a conversion to function
pointer.  */
 
@@ -783,9 +799,6 @@ maybe_add_lambda_conv_op (tree type)
 {
   bool nested = (current_function_decl != NULL_TREE);
   tree callop = lambda_function (type);
-  tree rettype, name, fntype, fn, body, compound_stmt;
-  tree thistype, stattype, statfn, convfn, call, arg;
-  vec *argvec;
 
   if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
 return;
@@ -793,6 +806,10 @@ maybe_add_lambda_conv_op (tree type)
   if (processing_template_decl)
 return;
 
+  bool const generic_lambda_p
+= (DECL_TEMPLATE_INFO (callop)
+&& DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop);
+
   if (DECL_INITIAL (callop) == NULL_TREE)
 {
   /* If the op() wasn't instantiated due to errors, give up.  */
@@ -800,16 +817,124 @@ maybe_add_lambda_conv_op (tree type)
   return;
 }
 
-  stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
- FUNCTION_ARG_CHAIN (callop));
+  /* Non-template conversion operators are defined directly with build_call_a
+ and using DIRECT_ARGVEC for arguments (including 'this').  Templates are
+ deferred and the CALL is built in-place.  In the case of a deduced return
+ call op, the decltype expression, DECLTYPE_CALL, used as a substitute for
+ the return type is also built in-place.  The arguments of DECLTYPE_CALL in
+ the return expression may differ in flags from those in the body CALL.  In
+ particular, parameter pack expansions are marked PACK_EXPANSION_LOCAL_P in
+ the body CALL, but not in DECLTYPE_CALL.  */
+
+  vec *direct_argvec = 0;
+  tree decltype_call = 0, call = 0;
+  tree fn_result = TREE_TYPE (TREE_TYPE (callop));
+
+  if (generic_lambda_p)
+{
+  /* Prepare the dependent member call for the static member function
+'_FUN' and, potentially, prepare another call to be used in a decltype
+return expression for a deduced return call op to allow for simple
+implementation of the conversion operator.  */
+
+  tree instance = build_nop (type, null_pointer_node);
+  tree objfn = 

[PATCH, re-committed] Support using 'auto' in a function parameter list to introduce an implicit template parameter.

2013-09-16 Thread Adam Butcher
From: abutcher 

gcc/cp/
* cp-tree.h (type_uses_auto_or_concept): Declare.
(is_auto_or_concept): Declare.
* decl.c (grokdeclarator): Allow 'auto' parameters in lambdas with
-std=gnu++1y or -std=c++1y or, as a GNU extension, in plain functions.
* type-utils.h: New header defining ...
(find_type_usage): ... this new function based on pt.c (type_uses_auto)
for searching a type tree given a predicate.
* pt.c (type_uses_auto): Reimplement via type-utils.h (find_type_usage).
(is_auto_or_concept): New function.
(type_uses_auto_or_concept): New function.
* parser.h (struct cp_parser): Add fully_implicit_function_template_p.
* parser.c (cp_parser_new): Initialize 
fully_implicit_function_template_p.
(cp_parser_new): Initialize fully_implicit_function_template_p.
(cp_parser_lambda_expression): Copy and restore value of
fully_implicit_function_template_p as per other parser fields.
(cp_parser_parameter_declaration_list): Count generic
parameters and call ...
(add_implicit_template_parms): ... this new function to synthesize them
with help from type-utils.h (find_type_usage), ...
(tree_type_is_auto_or_concept): ... this new static function and ...
(make_generic_type_name): ... this new static function.
(cp_parser_direct_declarator): Account for implicit template parameters.
(cp_parser_lambda_declarator_opt): Finish fully implicit template if
necessary by calling ...
(finish_fully_implicit_template): ... this new function.
(cp_parser_init_declarator): Likewise.
(cp_parser_function_definition_after_declarator): Likewise.
(cp_parser_member_declaration): Likewise.
* Make-lang.in (cp/pt.o): Add dependency on type-utils.h.
(cp/parser.o): Likewise.

gcc/testsuite/
g++.dg/cpp0x/auto9.C: Downgrade two previously expected errors (now
interpreted as implicit templates) to be expected pedwarns instead.
---
 gcc/cp/Make-lang.in|   5 +-
 gcc/cp/cp-tree.h   |   2 +
 gcc/cp/decl.c  |  29 +++-
 gcc/cp/parser.c| 289 ++---
 gcc/cp/parser.h|   6 +
 gcc/cp/pt.c|  35 +++--
 gcc/cp/type-utils.h|  55 +++
 gcc/testsuite/g++.dg/cpp0x/auto9.C |   4 +-
 8 files changed, 353 insertions(+), 72 deletions(-)
 create mode 100644 gcc/cp/type-utils.h

diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 9a80434..985f22b 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -312,7 +312,7 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
 cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) $(TM_P_H)
 cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \
   toplev.h $(TREE_INLINE_H) pointer-set.h gt-cp-pt.h intl.h \
-  c-family/c-objc.h
+  c-family/c-objc.h cp/type-utils.h
 cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_H) \
   $(FLAGS_H) $(REAL_H) $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H) \
   tree-diagnostic.h tree-pretty-print.h pointer-set.h c-family/c-objc.h
@@ -331,7 +331,8 @@ cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) $(REAL_H) \
   gt-cp-mangle.h $(TARGET_H) $(TM_P_H) $(CGRAPH_H)
 cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_CORE_H) \
   gt-cp-parser.h $(TARGET_H) $(PLUGIN_H) intl.h cp/decl.h \
-  c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_H)
+  c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_H) \
+  cp/type-utils.h
 cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) $(C_COMMON_H) \
$(TM_H) coretypes.h pointer-set.h tree-iterator.h $(SPLAY_TREE_H)
 cp/vtable-class-hierarchy.o: cp/vtable-class-hierarchy.c \
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4680053..d7840af 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5453,10 +5453,12 @@ extern tree make_auto   (void);
 extern tree make_decltype_auto (void);
 extern tree do_auto_deduction  (tree, tree, tree);
 extern tree type_uses_auto (tree);
+extern tree type_uses_auto_or_concept  (tree);
 extern void append_type_to_template_for_access_check (tree, tree, tree,
  location_t);
 extern tree splice_late_return_type(tree, tree);
 extern bool is_auto(const_tree);
+extern bool is_auto_or_concept (const_tree);
 extern tree process_template_parm  (tree, location_t, tree, 
 bool, bool);
 extern tree end_template_parm_list (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f193676..80ceca1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10323,8 +10323,33 @@ grokdeclarator (const cp_declar

Re: C++ PATCH for c++/41933 (variadic lambda capture)

2013-09-16 Thread Adam Butcher
Excellent.  This now supports the variadic generic lambda from the spec 
(albeit without the auto parameter pack)


   auto vglambda = [](auto printer)
   {
 // TODO: return [=](auto&& ... ts)   // OK: ts is a function 
parameter pack
 return [=]  (T&& ... ts)   // OK: ts is a function 
parameter pack

 {
   printer(std::forward(ts)...);
   return [=]()
   {
 printer(ts ...);
   };
 };
   };
   auto p = vglambda( [](auto v1, auto v2, auto v3)
 {
   std::cout << v1 << v2 << v3;
 } );
   auto q = p(1, 'a', 3.14); // OK: outputs 1a3.14
   q(); // OK: outputs 1a3.14


Just need to get 'auto...' working now for C++14 generic lambda 
conformance.  (I'm still trying!)


Cheers,
Adam



Re: [PATCH, committed] * pt.c (make_auto_1): Use input_location rather than BUILTINS_LOCATION.

2013-09-16 Thread Adam Butcher

On 16.09.2013 09:02, Eric Botcazou wrote:

---
 gcc/cp/pt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2ef160a..ed08dca 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21041,7 +21041,7 @@ static tree
 make_auto_1 (tree name)
 {
   tree au = cxx_make_type (TEMPLATE_TYPE_PARM);
-  TYPE_NAME (au) = build_decl (BUILTINS_LOCATION,
+  TYPE_NAME (au) = build_decl (input_location,
   TYPE_DECL, name, au);
   TYPE_STUB_DECL (au) = TYPE_NAME (au);
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index


That's not a valid post to gcc-patches though.  You need to explain 
what the
patch does in a few words, post a ChangeLog entry and say how you 
tested it.


See all the other messages on the list...

Apologies if this was out of context.  This was a change suggested and 
reviewed by Jason 
(http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01114.html).


It has been commited.  The changelog happened to be a one liner which 
folded into the subject line.




Re: [PATCH, committed] * pt.c (make_auto_1): Use input_location rather than BUILTINS_LOCATION.

2013-09-16 Thread Adam Butcher

On 16.09.2013 17:54, Eric Botcazou wrote:
Apologies if this was out of context.  This was a change suggested 
and

reviewed by Jason
(http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01114.html).


Then don't repost it on gcc-patches, it is already available on 
gcc-cvs:

  http://gcc.gnu.org/ml/gcc-cvs/2013-09/msg00473.html

For some reason I had got it into my head that I should post to 
gcc-patches after any commit.  After rereading "Write access policies" 
and "Checking in a change" I now realize I was mistaken.  Sorry for the 
noise.




[C++1y] [PATCH 2/4] Support nested generic lambdas.

2013-09-19 Thread Adam Butcher
* lambda.c (maybe_add_lambda_conv_op): Don't check for instantiated
callop in the case of generic lambdas.
---
 gcc/cp/lambda.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index b04448b..2ffa7e0 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -810,7 +810,7 @@ maybe_add_lambda_conv_op (tree type)
 = (DECL_TEMPLATE_INFO (callop)
 && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop);
 
-  if (DECL_INITIAL (callop) == NULL_TREE)
+  if (!generic_lambda_p && DECL_INITIAL (callop) == NULL_TREE)
 {
   /* If the op() wasn't instantiated due to errors, give up.  */
   gcc_assert (errorcount || sorrycount);
-- 
1.8.4



[C++1y] [PATCH 0/4] Fixes and enhancements to generic lambdas and implicit function templates.

2013-09-19 Thread Adam Butcher
Hi all,

The following series contain a few miscellaneous updates to generic lambdas and
implicit function templates.


[1/4]: Use translation-unit-global rather than parameter-list-local counter for
   generic type names to facilitate nested implicit function
   templates.

  Using function-local counter means that nested generic lambdas generate
  duplicate (conflicting) template type parameters.


[2/4]: Support nested generic lambdas.

  Bug fix; remove assertion not applicable to generic lambdas.


[3/4]: Ensure implicit template parameters have distinct canonical types.

  Unsure on my solution here.  I tinkered with externalizing
  'canonical_type_parameter' from pt.c but was not sure whether it was
  necessary.  It seemed sufficient to simply make TYPE_CANONICAL be distinct for
  each parameter so I simply made it point to the generate template parameter
  type.


[4/4]: Generate more intuitive name for 'auto' parameters.

  Potentially contentious.  This makes the names generated for implicit template
  parameter types to be of the form '' rather than '__GenN'.  The former,
  IMHO, look better in diagnostics.  A better solution might be to make the
  transformation in the diagnostic code rather than relabel the type but this
  appears to work in my simplistic test cases.


On the subject of test cases; I'm trying to put together a set to test all
features of the generic lambda and implicit function template updates.  This is
taking longer than I'd hoped as I'm only getting a few minutes here and there to
spend on this at the moment.

Cheers,
Adam


 gcc/cp/lambda.c |  2 +-
 gcc/cp/parser.c | 30 ++
 2 files changed, 19 insertions(+), 13 deletions(-)

-- 
1.8.4



[C++1y] [PATCH 3/4] Ensure implicit template parameters have distinct canonical types.

2013-09-19 Thread Adam Butcher
* parser.c (add_implicit_template_parms): Set the canonical type of a
generic parameter to be that of the newly generated type such that it is
unique.
---
 gcc/cp/parser.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7e9ade2..148e2f2 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -29005,6 +29005,9 @@ add_implicit_template_parms (cp_parser *parser, size_t 
expect_count,
cur_type = cp_build_qualified_type (new_type, TYPE_QUALS (cur_type));
   else
cur_type = new_type;
+
+  /* Make the canonical type of the parameter distinct.  */
+  TYPE_CANONICAL (TREE_TYPE (TREE_VALUE (p))) = cur_type;
 }
 
   gcc_assert (synth_count == expect_count);
-- 
1.8.4



[C++1y] [PATCH 4/4] Generate more intuitive name for 'auto' parameters.

2013-09-19 Thread Adam Butcher
* parser.c (make_generic_type_name): Spell generic type names ''
rather than '__GenN'.
---
 gcc/cp/parser.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 148e2f2..a54496a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28902,7 +28902,7 @@ make_generic_type_name ()
 {
   char buf[32];
   static int i = 0;
-  sprintf (buf, "__GenT%d", i);
+  sprintf (buf, "", ++i);
   return get_identifier (buf);
 }
 
-- 
1.8.4



[C++1y] [PATCH 1/4] Use translation-unit-global rather than parameter-list-local counter for generic type names to facilitate nested implicit function templates.

2013-09-19 Thread Adam Butcher
* parser.c (make_generic_type_name): Use static count rather than
parameter and ...
(add_implicit_template_parms): ... propagate interface change here.
---
 gcc/cp/parser.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2cd60f0..7e9ade2 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28898,9 +28898,10 @@ c_parse_file (void)
template parameter implied by `auto' or a concept identifier). */
 
 static tree
-make_generic_type_name (int i)
+make_generic_type_name ()
 {
   char buf[32];
+  static int i = 0;
   sprintf (buf, "__GenT%d", i);
   return get_identifier (buf);
 }
@@ -28915,14 +28916,14 @@ tree_type_is_auto_or_concept (const_tree t)
   return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t));
 }
 
-/* Add COUNT implicit template parameters gleaned from the generic
-   type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS
-   (creating a new template parameter list if necessary).  Returns
-   PARAMETERS suitably rewritten to reference the newly created types
-   or ERROR_MARK_NODE on failure.  */
+/* Add EXPECT_COUNT implicit template parameters gleaned from the generic
+   type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS (creating a new
+   template parameter list if necessary).  Returns PARAMETERS suitably 
rewritten
+   to reference the newly created types or ERROR_MARK_NODE on failure.  */
 
 tree
-add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters)
+add_implicit_template_parms (cp_parser *parser, size_t expect_count,
+tree parameters)
 {
   gcc_assert (current_binding_level->kind == sk_function_parms);
 
@@ -28931,7 +28932,7 @@ add_implicit_template_parms (cp_parser *parser, size_t 
count, tree parameters)
   bool become_template =
 fn_parms_scope->level_chain->kind != sk_template_parms;
 
-  size_t synth_idx = 0;
+  size_t synth_count = 0;
 
   /* Roll back a scope level and either introduce a new template parameter list
  or update an existing one.  The function scope is added back after 
template
@@ -28973,7 +28974,7 @@ add_implicit_template_parms (cp_parser *parser, size_t 
count, tree parameters)
   ++processing_template_parmlist;
 }
 
-  for (tree p = parameters; p && synth_idx < count; p = TREE_CHAIN (p))
+  for (tree p = parameters; p && synth_count < expect_count; p = TREE_CHAIN 
(p))
 {
   tree generic_type_ptr
= find_type_usage (TREE_VALUE (p), tree_type_is_auto_or_concept);
@@ -28981,7 +28982,9 @@ add_implicit_template_parms (cp_parser *parser, size_t 
count, tree parameters)
   if (!generic_type_ptr)
continue;
 
-  tree synth_id = make_generic_type_name (synth_idx++);
+  ++synth_count;
+
+  tree synth_id = make_generic_type_name ();
   tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
synth_id);
   tparms = process_template_parm (tparms, DECL_SOURCE_LOCATION (TREE_VALUE
@@ -29004,7 +29007,7 @@ add_implicit_template_parms (cp_parser *parser, size_t 
count, tree parameters)
cur_type = new_type;
 }
 
-  gcc_assert (synth_idx == count);
+  gcc_assert (synth_count == expect_count);
 
   push_binding_level (fn_parms_scope);
 
-- 
1.8.4



Re: [C++1y] [PATCH 1/4] Use translation-unit-global rather than parameter-list-local counter for generic type names to facilitate nested implicit function templates.

2013-09-22 Thread Adam Butcher

On 20.09.2013 18:46, Jason Merrill wrote:

On 09/19/2013 02:37 PM, Adam Butcher wrote:

+  static int i = 0;


I think this needs to be global and GTY so that it works properly 
with PCH.



Didn't consider PCH.  This delta OK?

--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28897,12 +28897,12 @@ c_parse_file (void)
 /* Create an identifier for a generic parameter type (a synthesized
template parameter implied by `auto' or a concept identifier). */

+static GTY(()) int generic_parm_count;
 static tree
 make_generic_type_name ()
 {
   char buf[32];
-  static int i = 0;
-  sprintf (buf, "", ++i);
+  sprintf (buf, "", ++generic_parm_count);
   return get_identifier (buf);
 }




Re: [C++1y] [PATCH 3/4] Ensure implicit template parameters have distinct canonical types.

2013-09-22 Thread Adam Butcher

On 20.09.2013 18:47, Jason Merrill wrote:

Why is canonical_type_parameter not doing the right thing here?  I
don't see a reason we should need to treat these differently from
normal template parms.

The issue only happens with indirect parms.  The type 'auto' is given a 
canonical type in make_auto_1.  When the parm type is plain unqualified 
'auto', the implicit template code replaces it with the generated type 
and all's well.  When the parm is 'auto&' the implicit template code 
only replaces the template_type_parm 'auto' with the generated type, the 
wrapping reference_type is left with the canonical type of 'auto&'.


Example of two parm types in the same list (chain field removed):

 >
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

 >
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

After replacement:

  VOID
   align 8 symtab 0 alias set -1
   canonical type 0x7f27b2ff3540
   index 1 level 1 orig_level 1>>
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

  VOID
   align 8 symtab 0 alias set -1
   canonical type 0x7f27b2ff35e8
   index 2 level 1 orig_level 1>>
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

Looks like I'll need to expose canonical_type_parameter and push it 
through from the top of the parameter rather than just replace the 
template_type_parm.   Or leave this as is and arrange for this scenario 
to never occur.


I guess this wouldn't happen if we were replacing on the fly.  Maybe 
make_auto_1 could differ in behavior when in a parameter list (would not 
setting a canonical type get us anywhere?) or just call a different 
function?


I'll have a further look when I get some more time.

Cheers,
Adam



Re: [C++1y] [PATCH 3/4] Ensure implicit template parameters have distinct canonical types.

2013-09-22 Thread Adam Butcher

On 22.09.2013 14:07, Adam Butcher wrote:

On 20.09.2013 18:47, Jason Merrill wrote:

Why is canonical_type_parameter not doing the right thing here?  I
don't see a reason we should need to treat these differently from
normal template parms.


The issue only happens with indirect parms.  The type 'auto' is given
a canonical type in make_auto_1.  When the parm type is plain
unqualified 'auto', the implicit template code replaces it with the
generated type and all's well.  When the parm is 'auto&' the implicit
template code only replaces the template_type_parm 'auto' with the
generated type, the wrapping reference_type is left with the 
canonical

type of 'auto&'.

Example of two parm types in the same list (chain field removed):

 >
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

 >
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

After replacement:

  VOID
   align 8 symtab 0 alias set -1
   canonical type 0x7f27b2ff3540
   index 1 level 1 orig_level 1>>
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

  VOID
   align 8 symtab 0 alias set -1
   canonical type 0x7f27b2ff35e8
   index 2 level 1 orig_level 1>>
unsigned DI
size <...> unit size <...>
align 64 symtab 0 alias set -1
canonical type 0x7f27b2ff3150>

Looks like I'll need to expose canonical_type_parameter and push it
through from the top of the parameter rather than just replace the
template_type_parm.   Or leave this as is and arrange for this
scenario to never occur.

I guess this wouldn't happen if we were replacing on the fly.  Maybe
make_auto_1 could differ in behavior when in a parameter list (would
not setting a canonical type get us anywhere?) or just call a
different function?

I'll have a further look when I get some more time.

The following solves the canonical type issue in the general case 
(pointers and refs) and makes it equivalent to the explicit template 
case -- in terms of canonical type at least.


  for (tree t = TREE_TYPE (TREE_VALUE (p)); t; t = TREE_CHAIN (t))
TYPE_CANONICAL (t) = t;

But I'm not necessarily proposing it as a good final solution.  It is 
yet another type chain loop, and I'm not sure about preserving other 
fields that are set in the explicit template case (e.g. 
reference_to_this).


So far test cases appear to work as expected but I'm thinking that 
getting the 'auto' replaced earlier might solve these issues more 
naturally (and others such as auto... packs)


Cheers,
Adam



[C++1y] [Implicit Fix instantiation of implicit function template forward declarations.

2013-09-22 Thread Adam Butcher

Hi Jason,

I noticed that, although implicit function template declarations were 
accepted.  They weren't setup correctly and didn't instantiate properly.


The following patch fixes this by moving finish_fully_implicit_template 
to the end of cp_parser_init_declarator.  OK to go with the others?


Cheers,
Adam


Fix instantiation of implicit function template forward 
declarations.


* parser.c (cp_parser_init_declarator): Defer calling
	finish_fully_implicit_template for forward declarations until 
after
	other decl processing is complete.  Cleanup for clarity: Extract 
'else'

case after 'if' containing unconditional return.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 82abf7c..f3133f3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16318,8 +16318,7 @@ cp_parser_init_declarator (cp_parser* parser,
   "a function-definition is not allowed here");
  return error_mark_node;
}
- else
-   {
+
  location_t func_brace_location
= cp_lexer_peek_token (parser->lexer)->location;

@@ -16357,9 +16356,6 @@ cp_parser_init_declarator (cp_parser* parser,
  return decl;
}
 }
-  else if (parser->fully_implicit_function_template_p)
-   decl = finish_fully_implicit_template (parser, decl);
-}

   /* [dcl.dcl]

@@ -16581,6 +16577,15 @@ cp_parser_init_declarator (cp_parser* parser,
   if (!friend_p && pushed_scope)
 pop_scope (pushed_scope);

+  if (function_declarator_p (declarator)
+  && parser->fully_implicit_function_template_p)
+{
+  if (member_p)
+   decl = finish_fully_implicit_template (parser, decl);
+  else
+   finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
+}
+
   return decl;
 }




[C++1y] [PATCH] Fix PR c++/58500

2013-09-23 Thread Adam Butcher

Hi,

This fixes using 'auto' in the return type of a function pointer to 
introduce an implicit function template parameter.


Note that this doesn't mean that 'auto' parameters in a function ptr 
will be treated the same; I think we need a special case for this in the 
implicit template parameter introduction code (or refactor to generate 
template parm types on the fly).


Cheers,
Adam


gcc/cp/
PR c++/58500
* type-utils.h (find_type_usage) Only traverse one type level into
member function pointers.

gcc/testsuite/
PR c++/58500
* g++.dg/cpp1y/pr58500.C: New testcase.

diff --git a/gcc/cp/type-utils.h b/gcc/cp/type-utils.h
index 3e82ca4..2febce7 100644
--- a/gcc/cp/type-utils.h
+++ b/gcc/cp/type-utils.h
@@ -47,7 +47,7 @@ find_type_usage (tree t, bool (*pred) (const_tree))

   if (TYPE_PTRMEMFUNC_P (t))
 return find_type_usage
-  (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (t))), pred);
+  (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (t)), pred);

   return NULL_TREE;
 }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58500.C 
b/gcc/testsuite/g++.dg/cpp1y/pr58500.C

new file mode 100644
index 000..b9d4a26
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58500.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/58500
+
+struct A {};
+
+void foo(auto (A::*)());



Re: [C++1y] [PATCH 3/4] Ensure implicit template parameters have distinct canonical types.

2013-09-23 Thread Adam Butcher

On 22.09.2013 18:57, Adam Butcher wrote:

The following solves the canonical type issue in the general case
(pointers and refs) and makes it equivalent to the explicit template
case -- in terms of canonical type at least.

  for (tree t = TREE_TYPE (TREE_VALUE (p)); t; t = TREE_CHAIN 
(t))

TYPE_CANONICAL (t) = t;

The above is insufficient; the traversal doesn't handle function 
pointers.  Currently, to get my local testcases passing, I have the 
following workaround that abuses find_type_usage.  I intend for this to 
be replaced with a better solution but it will at least mean that people 
can start experimenting with this feature now (as they appear to be 
doing http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58500).  This supports 
that testcase also.


Cheers,
Adam



Workaround implicit function template parameter canonical type 
issue.


* parser.c (add_implicit_template_parms): Workaround to fix up 
canonical
type references left over from before substation of 'auto'.  
Better

solution needed but this makes test cases functional.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f3133f3..4171476 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28987,6 +28987,25 @@ add_implicit_template_parms (cp_parser 
*parser, size_t expect_count,

   if (!generic_type_ptr)
continue;

+  /* Make the canonical type of each part of the parameter 
distinct.
+FIXME: A better solution is needed for this.  Not least the 
abuse of
+find_type_usage.  Need foreach_type or similar for proper 
mutable
+access.  If something like this does turn out to be necessary 
then the
+find_type_usage loop above can be replaced by a foreach_type 
that fixes

+up the canonical types on the way to finding the 'auto'.  */
+
+  struct helper { static bool fixup_canonical_types (tree t) {
+ t = TREE_TYPE (t);
+ if (!t)
+   return false;
+ if (is_auto_or_concept (t))
+   return true;
+ TYPE_CANONICAL (t) = t;
+ return false;
+  }};
+  find_type_usage (TREE_VALUE (p), (bool (*)(const_tree))
+  helper::fixup_canonical_types);
+
   ++synth_count;

   tree synth_id = make_generic_type_name ();



Re: [C++1y] [Implicit Fix instantiation of implicit function template forward declarations.

2013-09-23 Thread Adam Butcher

On 23.09.2013 19:03, Jason Merrill wrote:

On 09/23/2013 01:53 AM, Adam Butcher wrote:

+  if (member_p)
+decl = finish_fully_implicit_template (parser, decl);
+  else
+finish_fully_implicit_template (parser, /*member_decl_opt=*/0);


Why don't we want to return the template for the non-member case?

If the decl is passed to finish_fully_implicit_template it is 
considered to be a member and the finished member returned.  In the 
non-member case, nullptr is returned.




Re: [C++1y] [PATCH] Fix PR c++/58500

2013-09-23 Thread Adam Butcher

On 23.09.2013 19:02, Jason Merrill wrote:

On 09/23/2013 02:08 AM, Adam Butcher wrote:

Note that this doesn't mean that 'auto' parameters in a function ptr
will be treated the same; I think we need a special case for this in 
the
implicit template parameter introduction code (or refactor to 
generate

template parm types on the fly).


It is seeming like generating the types on the fly will make various
things simpler; otherwise we need to deal with rewriting arbitrarily
complex types later on.

Agreed.  We can arrange for the parm trees to be as if the user had 
explicitly specified the template and then subsequent logic will proceed 
'naturally'.  I'll look into it.


Re: [C++1y] [PATCH 3/4] ... canonical type workaround and refactoring

2013-09-24 Thread Adam Butcher

On 23.09.2013 08:15, Adam Butcher wrote:

On 22.09.2013 18:57, Adam Butcher wrote:

The following solves the canonical type issue in the general case
(pointers and refs) and makes it equivalent to the explicit template
case -- in terms of canonical type at least.

  for (tree t = TREE_TYPE (TREE_VALUE (p)); t; t = TREE_CHAIN 
(t))

TYPE_CANONICAL (t) = t;


The above is insufficient; the traversal doesn't handle function
pointers.  Currently, to get my local testcases passing, I have the
following workaround that abuses find_type_usage.  I intend for this
to be replaced with a better solution but it will at least mean that
people can start experimenting with this feature now (as they appear
to be doing http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58500).  This
supports that testcase also.



Shall I push the patch below to trunk as an intermediate workaround 
whilst I get to refactoring to support on-the-fly template parm 
synthesis?


On the subject of on-the-fly synthesis: I haven't started yet but I'm 
thinking to trigger in 'cp_parser_simple_type_specifier' when 
'current_binding_level->kind == sk_function_parms'.  I can foresee a 
potential issue with packs in that, upon reading the 'auto' (potentially 
nested in some other type), a plain template parm will be synthesized; 
but it may need to be a pack parm type if '...' is found later.


My initial testcase is:

  template  struct X { T m(int, float); };

  auto f(X, auto (X::*) (auto...))
  {
 char* s = "warn";
  }

  int main()
  {
 X x;
 f(x, &X::m);
  }

where f should be translated as similar to:

  template 
  auto f(X, A2 (X::*) (A4...))
  {
 char* s = "warn";
  }


In the case of something like:

  auto f(X&&...)

the translation would need to be:

  template 
  auto f(X&&...)


I'm thinking that getting that to happen correctly might be tricky (but 
haven't tried yet).  The 'auto' would trigger plain template parameter 
synthesis.  Perhaps a 'could_be_parameter_pack_p' on the 
template_type_parm?  Though I don't know how the following could be 
handled as implicit


  template 
  auto f(X&&...)

It would not be possible to infer which of the template parms to make 
the pack.


  auto f(X&&...)

Probably multiple generic-type pack expansions should be forbidden.

I'll see what happens when I get there but any guidance/thoughts you 
have on the subject will be valuable.


Cheers,
Adam



Workaround implicit function template parameter canonical type 
issue.


* parser.c (add_implicit_template_parms): Workaround to fix
up canonical
type references left over from before substation of 'auto'.  
Better

solution needed but this makes test cases functional.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f3133f3..4171476 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -28987,6 +28987,25 @@ add_implicit_template_parms (cp_parser
*parser, size_t expect_count,
   if (!generic_type_ptr)
continue;

+  /* Make the canonical type of each part of the parameter 
distinct.
+FIXME: A better solution is needed for this.  Not least the 
abuse of
+find_type_usage.  Need foreach_type or similar for proper 
mutable

+access.  If something like this does turn out to be
necessary then the
+find_type_usage loop above can be replaced by a foreach_type
that fixes
+up the canonical types on the way to finding the 'auto'.  */
+
+  struct helper { static bool fixup_canonical_types (tree t) {
+ t = TREE_TYPE (t);
+ if (!t)
+   return false;
+ if (is_auto_or_concept (t))
+   return true;
+ TYPE_CANONICAL (t) = t;
+ return false;
+  }};
+  find_type_usage (TREE_VALUE (p), (bool (*)(const_tree))
+  helper::fixup_canonical_types);
+
   ++synth_count;

   tree synth_id = make_generic_type_name ();


[SKETCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-10-07 Thread Adam Butcher

Hi Jason,

I did intend to break this up but as I've completed the first pass at 
refactoring implicit function templates and along the way fixed the 5 
bugs submitted by Volker I thought I'd post the rolled up patch for you 
to peruse.


It (should) support arbitrarily complex use of 'auto' in a parameter 
list to introduce template parameters.  Implicit pack expansion 
parameters containing a single 'auto' are handled by tentatively 
assuming a single 'auto' might be a pack then reverting the flag if 
found not to be.  This now fully supports the current C++14 generic 
lambda examples.


No new regressions on trunk as of this morning.

Any feedback appreciated.  Diff attached with -w -b.

Cheers,
Adam

  TODO: Changelog post review.
  PR c++/58534
  PR c++/58536
  PR c++/58548
  PR c++/58549
  PR c++/58637

 gcc/cp/decl.c|  30 +---
 gcc/cp/parser.c  | 312 
++-

 gcc/cp/parser.h  |  15 ++
 gcc/testsuite/g++.dg/cpp1y/pr58534.C |   9 +
 gcc/testsuite/g++.dg/cpp1y/pr58536.C |  12 ++
 gcc/testsuite/g++.dg/cpp1y/pr58548.C |  10 ++
 gcc/testsuite/g++.dg/cpp1y/pr58549.C |  10 ++
 gcc/testsuite/g++.dg/cpp1y/pr58637.C |   7 +
 8 files changed, 299 insertions(+), 106 deletions(-)

commit 90c77cdd87eb63617719a9ad129803a2048761ff
Author: Adam Butcher 
Date:   Wed Sep 18 17:39:40 2013 +0100

Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

	TODO: Changelog post review.
	PR c++/58534
	PR c++/58536
	PR c++/58548
	PR c++/58549
	PR c++/58637

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 81ed409..8095eca 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10323,34 +10323,12 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (type_uses_auto (type))
 	{
-	  if (template_parm_flag)
-	{
-	  error ("template parameter declared %");
-	  type = error_mark_node;
-	}
-	  else if (decl_context == CATCHPARM)
-	{
-	  error ("catch parameter declared %");
+	  if (cxx_dialect >= cxx1y)
+	error ("% parameter not permitted in this context");
+	  else
+	error ("parameter declared %");
 	  type = error_mark_node;
 	}
-	  else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
-	{
-	  if (cxx_dialect < cxx1y)
-		pedwarn (location_of (type), 0,
-			 "use of % in lambda parameter declaration "
-			 "only available with "
-			 "-std=c++1y or -std=gnu++1y");
-	}
-	  else if (cxx_dialect < cxx1y)
-	pedwarn (location_of (type), 0,
-		 "use of % in parameter declaration "
-		 "only available with "
-		 "-std=c++1y or -std=gnu++1y");
-	  else
-	pedwarn (location_of (type), OPT_Wpedantic,
-		 "ISO C++ forbids use of % in parameter "
-		 "declaration");
-	}
 
   /* A parameter declared as an array of T is really a pointer to T.
 	 One declared as a function is really a pointer to a function.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 90c1775..8c8be4c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -245,6 +245,19 @@ static FILE *cp_lexer_debug_stream;
sizeof, typeof, or alignof.  */
 int cp_unevaluated_operand;
 
+/* Nonzero if parsing a context where 'auto' in a parameter list should not
+   trigger an implicit template parameter.  Specifically, 'auto' should not
+   introduce a new template type parameter in explicit specializations, trailing
+   return types or exception specifiers.  */
+int cp_disable_auto_as_implicit_function_template_parm;
+
+/* Track the number of implicit template parameters introduced by the
+   current function parameter and, for handling implicit parameter packs, track
+   the most recently synthesized type.  These are reset prior to parsing in
+   cp_parameter_declarator and updated in synthesize_implicit_template_parm.  */
+int cp_num_implicit_template_type_parms;
+tree cp_last_implicit_template_type_parm;
+
 /* Dump up to NUM tokens in BUFFER to FILE starting with token
START_TOKEN.  If START_TOKEN is NULL, the dump starts with the
first token in BUFFER.  If NUM is 0, dump all the tokens.  If
@@ -2064,8 +2077,8 @@ static vec *cp_parser_initializer_list
 static bool cp_parser_ctor_initializer_opt_and_function_body
   (cp_parser *, bool);
 
-static tree add_implicit_template_parms
-  (cp_parser *, size_t, tree);
+static tree synthesize_implicit_template_parm
+  (cp_parser *parser);
 static tree finish_fully_implicit_template
   (cp_parser *, tree);
 
@@ -3393,6 +3406,8 @@ cp_parser_new (void)
 
   /* Not declaring an implicit function template.  */
   parser->fully_implicit_function_template_p = false;
+  parser->implicit_template_parms = 0;
+  parser->implicit_template_scope = 0;
 
   ret

Re: [SKETCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-10-10 Thread Adam Butcher

On 2013-10-09 4:37, Jason Merrill wrote:

On 10/07/2013 05:14 AM, Adam Butcher wrote:

+ /* Forbid ambiguous implicit pack expansions by only allowing
+a single generic type in such a parameter.

+XXX: Maybe allow if explicitly specified template
+XXX: 'typename...' account for all expansions?  Though this
+XXX: could be tricky or slow.


This seems wrong.  The standard says,

The invented type template-parameter is a parameter pack if the 
corresponding parameter-declaration de-

clares a function parameter pack (8.3.5).


So if we have a function parameter pack, any generic type parameters
in the type are packs.

Of course; makes sense.  I had confused myself.  Not that it's a 
function parameter pack, but presumably you would expect


  auto f(tuple p)

to be supported?  This doesn't work with my existing impl since I only 
generate a variadic type on the declaration of a function parameter 
pack.


I think the following cases should also work

  auto g1(std::tuple, std::tuple> p)
  auto g2(std::tuple, 
std::tuple...>> p)


In both cases, the first generic type is a plain type and the second is 
a type pack.


Making the parameter a function parameter pack should also work

  auto h1(std::tuple, std::tuple>... v)
  auto h2(std::tuple, 
std::tuple...>>... v)


The first 'auto' is a pack expanded by 'v' and the second is expanded 
within the second tuple (and required to be consistent among all 'v' 
arguments).


+	  /* If there is only one generic type in the parameter, 
tentatively
+	 assume that that it is a parameter pack.  If it turns out, 
after

+grokdeclarator, that the parameter does not contain a pack
+expansion, then reset it be a non-pack type.  */
+ if (cp_num_implicit_template_type_parms == 1)
+   TEMPLATE_PARM_PARAMETER_PACK
+ (TEMPLATE_TYPE_PARM_INDEX
+   (cp_last_implicit_template_type_parm)) = true;


This will cause problems with type comparison, since TYPE_CANONICAL
of the implicit parm doesn't have TEMPLATE_PARM_PARAMETER_PACK set.


Indeed it does.

That's why I was talking about using tsubst to replace a non-pack 
with

a pack.


Will do.


+   parser->implicit_template_scope = class_scope;
+  else
+   parser->implicit_template_scope = fn_parms_scope;
+  current_binding_level = 
parser->implicit_template_scope->level_chain;


Why not make implicit_template_scope the actual template scope,
rather than the function/class?  It looks like all the users
immediately take the level_chain.

My original intent was to store the actual template parm scope but I 
changed it to the containing scope to make the comparison in 
cp_parser_parameter_declaration_list; It determines the completion point 
of the implicit template scope.  It is terminated once 
current_binding_level returns to the initiating scope.  I'll have 
another look to reduce level_chain traversal.


+/* Nonzero if parsing a context where 'auto' in a parameter list 
should not
+   trigger an implicit template parameter.  Specifically, 'auto' 
should not
+   introduce a new template type parameter in explicit 
specializations, trailing

+   return types or exception specifiers.  */
+int cp_disable_auto_as_implicit_function_template_parm;


Can we put this in cp_parser, invert the sense of the flag, and only
set it during cp_parser_parameter_declaration_clause?

Done.  But it still needs a flag to disable in the case of explicit 
template specialization.  At the moment I've replaced the 
explicit_specialization_p parm of cp_parser_single_declaration with a 
global cp_parsing_explicit_function_specialization but not sure if 
that's the best solution.


I'll post an update once I get some time to rework the pack stuff.

Cheers,
Adam



Re: [SKETCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-10-11 Thread Adam Butcher

On 2013-10-11 3:26, Jason Merrill wrote:
Can we put this in cp_parser, invert the sense of the flag, and 
only

set it during cp_parser_parameter_declaration_clause?


Done.  But it still needs a flag to disable in the case of explicit
template specialization.


Can't you just check processing_specialization?


Yep.  That's much cleaner.

Cheers,
Adam



Re: [SKETCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-10-15 Thread Adam Butcher

On Wed, 25 Sep 2013 11:01:26 -0500, Jason Merrill wrote:

On 09/24/2013 02:05 AM, Adam Butcher wrote:
> On the subject of on-the-fly synthesis: I haven't started yet but 
I'm

> thinking to trigger in 'cp_parser_simple_type_specifier' when
> 'current_binding_level->kind == sk_function_parms'.
>
This is working out quite well.  And I've cleaned up and optimized 
synthesize_implicit_template_parm to update current_template_parms 
directly.  Implicitly packs are still a problem though.



> I can foresee a
> potential issue with packs in that, upon reading the 'auto' 
(potentially
> nested in some other type), a plain template parm will be 
synthesized;

> but it may need to be a pack parm type if '...' is found later.

Hmm, good point.

I think there are two options:

1) Build up the type as normal and use tsubst to replace the non-pack 
template parameter with a pack if needed.


The problem I've hit with this (and other hacks I've tried that involve 
finishing the type first and rewriting afterward) is that, with parm 
types such as "pair...", the specialization "pair" 
is indexed in pt.c by hash_specialization into type_specializations 
before the '...' is seen.  In an explicit template, the template type 
parms are already marked as packs so are hashed as such and are distinct 
from non-pack template type parms.


The issue occurs in cases such as:

  auto a = [] (auto, pair v) { return sizeof (v); };
  auto b = [] (auto, pair... v) { return sizeof... (v); };

  a(1, pair());
  b(2, pair(), pair());

If the declarations of a and b are reversed, it works as expected.

I cannot find a way to prevent picking up the non-pack 
"pair" type on the way through parsing "pair...".  
I've tried a few hacks to prevent hashing if an 'auto' is present in the 
current type but ended up with canonical type issues.  I also tried 
rehashing after pack replacement but still hit the same issue.  My 
conclusion is that the 'auto' needs to synthesize a pack type from the 
start for parameter packs.  Which leads to:


2) If we see 'auto', scan ahead (possibly via tentative parsing) to 
see if there's a ...


My current preferred option.  The problem with it is that, ideally, I 
only want to look ahead for '...' in the parm decl if an 'auto' is seen. 
But I'm not sure how to do this in the case where the first 'auto' is 
nested in a template parameter (or other complex type).  E.g.


   auto f(pair, auto>... v)
^
From the 'auto' I'd need to unwind to the fn parm scope and then try to 
tentatively parse the ellipsis.  To unwind and look ahead for '...' 
needs the full parser mechanics but without any side-effects.  I don't 
think I can do it with the lexer alone as I think there may be ambiguity 
with scanning <, <<, >, >> tokens.


Look-ahead seems like the right way to go (unless there's a way to 
defer type hashing) but I'm not sure how to achieve it.


Any suggestions?

Cheers,
Adam



Re: [SKETCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-10-15 Thread Adam Butcher

On 2013-10-15 22:21, Adam Butcher wrote:

On Wed, 25 Sep 2013 11:01:26 -0500, Jason Merrill wrote:
>
> 2) If we see 'auto', scan ahead (possibly via tentative parsing) to 
see if there's a ...

>
My current preferred option.  The problem with it is that, ideally, I
only want to look ahead for '...' in the parm decl if an 'auto' is
seen. But I'm not sure how to do this in the case where the first
'auto' is nested in a template parameter (or other complex type).
E.g.

   auto f(pair, auto>... v)
^
From the 'auto' I'd need to unwind to the fn parm scope and then try
to tentatively parse the ellipsis.  To unwind and look ahead for 
'...'
needs the full parser mechanics but without any side-effects.  I 
don't

think I can do it with the lexer alone as I think there may be
ambiguity with scanning <, <<, >, >> tokens.

Look-ahead seems like the right way to go (unless there's a way to
defer type hashing) but I'm not sure how to achieve it.


I've got a [potential] [partial] solution to this.  It doesn't handle
edge cases but I believe it will handle the majority of cases.

By maintaining a nesting counter of calls to
cp_parser_enclosed_template_argument_list we can determine, for a
particular parm, what level of template-id were are parsing when we see
an 'auto'.  A tentative skip parse handling < << ( [ ] ) >> > can be
done until reaching an ellipsis or, if <> nesting count drops to zero,
a closing paren or comma terminating the parm.  Mismatches would also
be considered as terminating the parm.

In the ellipsis case we assume some sort of pack.  If the <> nesting
count is zero when an ellipsis is found, we assume a function parameter
pack and flag that all 'auto's in the parm should be type packs and
don't need to do the look-ahead again for this parm.  If the <> nesting
count is non-zero when an ellipsis is found, then only the 'auto's
within that level of template argument list are considered type packs
and look-ahead will be done for 'auto' found in subsequent template
argument lists within the parm.

The latter case implements the implicit type pack extension supporting,
for example, the following:

   f(tuple,tuple> t)

This doesn't handle cases where < << >> > are used as operators within
the parm but I think that's an edge case and it would only affect
whether the 'auto' was considered an implicit type pack or not.

I haven't gone all the way with this theory yet, but it could be a
plausible solution.

Let me know what you think.

Cheers,
Adam




[C++ PATCH 2/3] Support implicit parameter packs.

2013-11-02 Thread Adam Butcher
* parser.c (convert_generic_types_to_packs): New function to transform
a range of implicitly introduced non-pack template parms to be parameter
packs.
(cp_parser_parameter_declaration_list): If a function parameter pack
contains generic types, convert them to packs prior to grokdeclarator.
---
 gcc/cp/parser.c | 81 -
 1 file changed, 74 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b699ac4..10b9f72 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2109,6 +2109,8 @@ static tree cp_parser_late_parsing_omp_declare_simd
 
 static tree synthesize_implicit_template_parm
   (cp_parser *);
+static tree convert_generic_types_to_packs
+  (tree, tree, int, int);
 static tree finish_fully_implicit_template
   (cp_parser *, tree);
 
@@ -18069,7 +18071,7 @@ static tree
 cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
   tree parameters = NULL_TREE;
-  tree *tail = ¶meters; 
+  tree *tail = ¶meters;
   bool saved_in_unbraced_linkage_specification_p;
   int index = 0;
 
@@ -18078,7 +18080,7 @@ cp_parser_parameter_declaration_list (cp_parser* 
parser, bool *is_error)
   /* The special considerations that apply to a function within an
  unbraced linkage specifications do not apply to the parameters
  to the function.  */
-  saved_in_unbraced_linkage_specification_p 
+  saved_in_unbraced_linkage_specification_p
 = parser->in_unbraced_linkage_specification_p;
   parser->in_unbraced_linkage_specification_p = false;
 
@@ -18088,6 +18090,10 @@ cp_parser_parameter_declaration_list (cp_parser* 
parser, bool *is_error)
   cp_parameter_declarator *parameter;
   tree decl = error_mark_node;
   bool parenthesized_p = false;
+  int template_parm_idx = (parser->num_template_parameter_lists?
+  TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+   (current_template_parms)) : 0);
+
   /* Parse the parameter.  */
   parameter
= cp_parser_parameter_declaration (parser,
@@ -18099,11 +18105,30 @@ cp_parser_parameter_declaration_list (cp_parser* 
parser, bool *is_error)
   deprecated_state = DEPRECATED_SUPPRESS;
 
   if (parameter)
-   decl = grokdeclarator (parameter->declarator,
-  ¶meter->decl_specifiers,
-  PARM,
-  parameter->default_argument != NULL_TREE,
-  ¶meter->decl_specifiers.attributes);
+   {
+ /* If a function parameter pack was specified and an implicit template
+parameter was introduced during cp_parser_parameter_declaration,
+change any implicit parameters introduced into packs.  */
+ if (parser->implicit_template_parms
+ && parameter->declarator
+ && parameter->declarator->parameter_pack_p)
+   {
+ int latest_template_parm_idx = TREE_VEC_LENGTH
+   (INNERMOST_TEMPLATE_PARMS (current_template_parms));
+
+ if (latest_template_parm_idx != template_parm_idx)
+   parameter->decl_specifiers.type = convert_generic_types_to_packs
+ (parameter->decl_specifiers.type,
+  current_template_parms,
+  template_parm_idx, latest_template_parm_idx);
+   }
+
+ decl = grokdeclarator (parameter->declarator,
+¶meter->decl_specifiers,
+PARM,
+parameter->default_argument != NULL_TREE,
+¶meter->decl_specifiers.attributes);
+   }
 
   deprecated_state = DEPRECATED_NORMAL;
 
@@ -31213,6 +31238,48 @@ synthesize_implicit_template_parm  (cp_parser *parser)
   return new_type;
 }
 
+/* Convert the generic type parameters in PARM that match the types given in 
the
+   range [START_IDX, END_IDX) from the template parameters CURRENT into generic
+   type packs.  */
+
+tree
+convert_generic_types_to_packs (tree parm,
+   tree current, int start_idx, int end_idx)
+{
+  int depth = TMPL_PARMS_DEPTH (current);
+  current = INNERMOST_TEMPLATE_PARMS (current);
+  tree replacement = make_tree_vec (TREE_VEC_LENGTH (current));
+
+  for (int i = start_idx; i < end_idx; ++i)
+{
+  /* Create a distinct parameter pack type from the current parm and add it
+to the replacement args to tsubst below into the generic function
+parameter.  */
+
+  tree t = copy_type (TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (current, i;
+  TYPE_STUB_DECL (t) = TYPE_NAME (t) = TEMPLATE_TYPE_DECL (t);
+  TYPE_MAIN_VARIANT (t) = t;
+  TEMPLATE_TYPE_PARAMETER_PACK (t) = true;
+  SET_TYPE_STRUCTURAL_EQUALITY (t);
+  TREE_VEC_ELT (replacement, i) = t;
+}
+
+  if (depth > 1)
+{
+  /* Build up a tree vec of

Re: [SKETCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-02 Thread Adam Butcher
Hi Jason,

I've got the tsubst solution for implicit parameter packs working now.  I've
also improved the efficiency of incremental template parameter synthesis and
added some testcases.  All C++14 generic lambda examples pass and no new
regressions.

Cheers,
Adam

Patch summary (3):

  Refactor implicit function template implementation and fix 58534,
58536, 58548, 58549 and 58637.
  Support implicit parameter packs.
  Add some generic lambda test cases.

 gcc/cp/decl.c  |  30 +-
 gcc/cp/parser.c| 331 +++--
 gcc/cp/parser.h|  19 ++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-cfun.C   |  25 ++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-dep.C|  42 +++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-mixed.C  |  10 +
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C|  51 
 .../g++.dg/cpp1y/lambda-generic-variadic.C |  15 +
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-x.C  |  25 ++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xcfun.C  |  25 ++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xudt.C   |   4 +
 gcc/testsuite/g++.dg/cpp1y/lambda-generic.C|  23 ++
 gcc/testsuite/g++.dg/cpp1y/pr58534.C   |   9 +
 gcc/testsuite/g++.dg/cpp1y/pr58536.C   |  12 +
 gcc/testsuite/g++.dg/cpp1y/pr58548.C   |  10 +
 gcc/testsuite/g++.dg/cpp1y/pr58549.C   |  10 +
 gcc/testsuite/g++.dg/cpp1y/pr58637.C   |   7 +
 gcc/tree.c |  22 ++
 gcc/tree.h |   5 +
 19 files changed, 561 insertions(+), 114 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-cfun.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-dep.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-mixed.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-x.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xcfun.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xudt.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58534.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58536.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58548.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58549.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58637.C

-- 
1.8.4



[C++ PATCH 3/3] Add some generic lambda test cases.

2013-11-02 Thread Adam Butcher
gcc/testsuite/g++.dg/cpp1y/
 * lambda-generic.C: New test case.
 * lambda-generic-cfun.C: New test case.
 * lambda-generic-dep.C: New test case.
 * lambda-generic-udt.C: New test case.
 * lambda-generic-variadic.C: New test case.
 * lambda-generic-x.C: New test case.
 * lambda-generic-xcfun.C: New test case.
 * lambda-generic-xudt.C: New test case.
 * lambda-generic-mixed.C: New test case.
---
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-cfun.C   | 25 +++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-dep.C| 42 ++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-mixed.C  | 10 +
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C| 51 ++
 .../g++.dg/cpp1y/lambda-generic-variadic.C | 15 +++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-x.C  | 25 +++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xcfun.C  | 25 +++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xudt.C   |  4 ++
 gcc/testsuite/g++.dg/cpp1y/lambda-generic.C| 23 ++
 9 files changed, 220 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-cfun.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-dep.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-mixed.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-x.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xcfun.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-xudt.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic.C

diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-cfun.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-cfun.C
new file mode 100644
index 000..5e51526
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-cfun.C
@@ -0,0 +1,25 @@
+// Generic lambda conversion to function ptr test from N3690 5.1.2.6
+// { dg-options "-std=c++1y" }
+
+void f1(int (*)(int)) { }
+void f2(char (*)(int)) { }
+void g(int (*)(int)) { } // #1
+void g(char (*)(char)) { } // #2
+void h(int (*)(int)) { } // #3
+void h(char (*)(int)) { } // #4
+
+int main()
+{
+  auto glambda = [](auto a) { return a; };
+  int (*fp)(int) = glambda;
+  f1(glambda); // OK
+  f2(glambda); // { dg-error "invalid user-defined conversion" }
+  g(glambda); // { dg-error "ambiguous" }
+  h(glambda); // OK: calls #3 since it is convertible from ID
+  int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
+
+  auto GL = [](auto a) { return a; };
+  int (*GL_int)(int) = GL; // OK: through conversion function template
+  GL_int(3);
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-dep.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-dep.C
new file mode 100644
index 000..bb68738
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-dep.C
@@ -0,0 +1,42 @@
+// Generic lambda type dependence test part from N3690 5.1.2.12
+// { dg-options "-std=c++1y" }
+
+void f(int, const int (&)[2] = {}) { } // #1
+void f(const int&, const int (&)[1]) { } // #2
+
+void test()
+{
+  const int x = 17;
+  auto g = [](auto a) {
+f(x); // OK: calls #1, does not capture x
+  };
+  auto g2 = [=](auto a) {
+int selector[sizeof(a) == 1 ? 1 : 2]{};
+f(x, selector); // OK: is a dependent expression, so captures x
+  };
+}
+
+struct S {
+  struct N {
+auto test () { return 7.f; }
+  };
+};
+
+#include 
+
+int main()
+{
+  auto f = []  (T const& s) mutable {
+typename T::N x;
+return x.test ();
+  };
+  auto g = [] (auto const& s) {
+typename std::decay::type::N x;
+return x.test ();
+  };
+
+  S i;
+  f(i);
+  g(i);
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-mixed.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-mixed.C
new file mode 100644
index 000..4e26fc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-mixed.C
@@ -0,0 +1,10 @@
+// Mixed explicit and implicit generic lambda test.
+// { dg-options "-std=c++1y" }
+
+int main()
+{
+  auto f = []  (T a, auto b) { return a + b; };
+  auto g = []  (auto a, T b) { return a + b; };
+
+  return f (1.0, 3) + g (1.0, 3);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C
new file mode 100644
index 000..9f6d45a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C
@@ -0,0 +1,51 @@
+// Ensure that generic lambdas properly construct and destroy user types.
+// { dg-options "-std=c++1y -DUSE_AUTO_SYNTAX" }
+// { dg-do run }
+
+int i = 3;
+
+struct S
+{
+  S () { ++i; }
+  S (S const&) { ++i; }
+  S (S&& old) { old.shadow = true; i += 2; }
+  ~S () { if (shadow) i -= 2; else --i; }
+
+  bool shadow = false;
+};
+
+extern "C" void printf(...);
+#define assert(e) if (e); else \
+

[C++ PATCH 1/3] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-02 Thread Adam Butcher
gcc/
* tree.c (grow_tree_vec_stat): New function ...
* tree.h (grow_tree_vec_stat) (grow_tree_vec): ... and its declaration
and macro front-end.

gcc/cp/
PR c++/58534
PR c++/58536
PR c++/58548
PR c++/58549
PR c++/58637
* parser.h (struct cp_parser): New members implicit_template_parms,
implicit_template_scope and auto_is_implicit_function_template_parm_p.
* parser.c (add_implicit_template_parms): Refactor as ...
(synthesize_implicit_template_parm): ... this to append a new template
type parm to the current template parameter list (introducing a new list
if necessary).
(cp_parser_new): Initialize new cp_parser members.
(cp_parser_parameter_declaration_clause): Consider auto as implicit
template parm when parsing a parameter declaration (unless paring an
explicit specialization).
(cp_parser_parameter_declaration_list): Remove local
implicit_template_parms counter and reset cp_parser implicit template
state when complete.
(cp_parser_lambda_expression): Reset implicit template cp_parser members
whilst generating lambda class.
(cp_parser_function_definition_after_declarator): Reset implicit
template cp_parser members whilst parsing function definition.
(make_generic_type_name): Respell '' as 'auto:N' which works
better with template diagnostics.
(cp_parser_simple_type_specifier): Synthesize implicit template parm on
parsing 'auto' if auto_is_implicit_function_template_parm_p and provide
diagnostics ...
* decl.c (grokdeclarator): ... that were previously done here.

gcc/testsuite/g++.dg/
* cpp1y/pr58534.C: New testcase.
* cpp1y/pr58536.C: New testcase.
* cpp1y/pr58548.C: New testcase.
* cpp1y/pr58549.C: New testcase.
* cpp1y/pr58637.C: New testcase.
---
 gcc/cp/decl.c|  30 +---
 gcc/cp/parser.c  | 278 +++
 gcc/cp/parser.h  |  19 +++
 gcc/testsuite/g++.dg/cpp1y/pr58534.C |   9 ++
 gcc/testsuite/g++.dg/cpp1y/pr58536.C |  12 ++
 gcc/testsuite/g++.dg/cpp1y/pr58548.C |  10 ++
 gcc/testsuite/g++.dg/cpp1y/pr58549.C |  10 ++
 gcc/testsuite/g++.dg/cpp1y/pr58637.C |   7 +
 gcc/tree.c   |  22 +++
 gcc/tree.h   |   5 +
 10 files changed, 281 insertions(+), 121 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58534.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58536.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58548.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58549.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr58637.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 09c1daa..786814c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10375,33 +10375,11 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (type_uses_auto (type))
{
- if (template_parm_flag)
-   {
- error ("template parameter declared %");
- type = error_mark_node;
-   }
- else if (decl_context == CATCHPARM)
-   {
- error ("catch parameter declared %");
- type = error_mark_node;
-   }
- else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
-   {
- if (cxx_dialect < cxx1y)
-   pedwarn (location_of (type), 0,
-"use of % in lambda parameter declaration "
-"only available with "
-"-std=c++1y or -std=gnu++1y");
-   }
- else if (cxx_dialect < cxx1y)
-   pedwarn (location_of (type), 0,
-"use of % in parameter declaration "
-"only available with "
-"-std=c++1y or -std=gnu++1y");
+ if (cxx_dialect >= cxx1y)
+   error ("% parameter not permitted in this context");
  else
-   pedwarn (location_of (type), OPT_Wpedantic,
-"ISO C++ forbids use of % in parameter "
-"declaration");
+   error ("parameter declared %");
+ type = error_mark_node;
}
 
   /* A parameter declared as an array of T is really a pointer to T.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bbc8e75..b699ac4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2107,8 +2107,8 @@ static bool 
cp_parser_ctor_initializer_opt_and_function_body
 static tree cp_parser_late_parsing_omp_declare_simd
   (cp_parser *, tree);
 
-static tree add_implicit_template_parms
-  (cp_parser *, size_t, tree);
+static tree synthesize_implicit_template_parm
+  (cp_parser *);
 static tree finish_fully_implicit_template
   (cp_parser *, tree);
 
@@ -3443,7 +3443,10 @@ cp_parser_new (void)
   parser->num_template_parameter_lists = 0;
 
   /* Not decla

[PATCH] PR c++/69139

2016-02-07 Thread Adam Butcher
PR c++/69139
* cp/parser.c (cp_parser_simple_type_specifier): Don't mistake 'auto'
in trailing return function pointer types as an implicit template
parameter.

PR c++/69139
* g++.dg/cpp0x/trailing12.C: New test.
---
 gcc/cp/parser.c | 22 ++
 gcc/testsuite/g++.dg/cpp0x/trailing12.C |  6 ++
 2 files changed, 24 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/trailing12.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d03b0c9..c1a9674 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16029,8 +16029,11 @@ cp_parser_simple_type_specifier (cp_parser* parser,
   maybe_warn_cpp0x (CPP0X_AUTO);
   if (parser->auto_is_implicit_function_template_parm_p)
{
- /* The 'auto' might be the placeholder return type for a function decl
-with trailing return type.  */
+ /* The 'auto' might be the placeholder return type for a function type
+with trailing return type.  Look for a '->' after parameter list.
+Handle pointer-to-function, function reference and
+pointer-to-member-function by tentatively consuming two pairs of
+parens before testing for '->'.  */
  bool have_trailing_return_fn_decl = false;
  if (cp_lexer_peek_nth_token (parser->lexer, 2)->type
  == CPP_OPEN_PAREN)
@@ -16042,8 +16045,19 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 /*recovering*/false,
 /*or_comma*/false,
 /*consume_paren*/true))
-   have_trailing_return_fn_decl
- = cp_lexer_next_token_is (parser->lexer, CPP_DEREF);
+   {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
+   have_trailing_return_fn_decl = true;
+ else if ((cp_lexer_consume_token (parser->lexer)->type
+   == CPP_OPEN_PAREN)
+  && (cp_parser_skip_to_closing_parenthesis
+  (parser,
+   /*recovering*/false,
+   /*or_comma*/false,
+   /*consume_paren*/true)))
+   have_trailing_return_fn_decl
+ = cp_lexer_next_token_is (parser->lexer, CPP_DEREF);
+   }
  cp_parser_abort_tentative_parse (parser);
}
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing12.C 
b/gcc/testsuite/g++.dg/cpp0x/trailing12.C
new file mode 100644
index 000..f3e02a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing12.C
@@ -0,0 +1,6 @@
+// PR c++/69139
+// { dg-do compile { target c++11 } }
+
+auto get(int) -> int { return {}; }
+template  int f(auto (*)(int) -> R) { return {}; }
+int i = f(get);
-- 
2.7.0



[PATCH] Re: PR c++/69139

2016-02-08 Thread Adam Butcher
The following fixes up the handling of trailing returns with
cv/ref specifiers mentioned by TC in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69139#c3.  I've added
handling of exception and transaction specs too.

---
 gcc/cp/parser.c | 12 ++--
 gcc/testsuite/g++.dg/cpp0x/trailing12.C | 10 ++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c1a9674..f51fac4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16055,8 +16055,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
/*recovering*/false,
/*or_comma*/false,
/*consume_paren*/true)))
-   have_trailing_return_fn_decl
- = cp_lexer_next_token_is (parser->lexer, CPP_DEREF);
+   {
+ /* Consume any cv-qualifier-seq, ref-qualifier,
+tx-qualifier and/or exception specifier.  */
+ cp_parser_cv_qualifier_seq_opt (parser);
+ cp_parser_ref_qualifier_opt (parser);
+ cp_parser_tx_qualifier_opt (parser);
+ cp_parser_exception_specification_opt (parser);
+ have_trailing_return_fn_decl
+   = cp_lexer_next_token_is (parser->lexer, CPP_DEREF);
+   }
}
  cp_parser_abort_tentative_parse (parser);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing12.C 
b/gcc/testsuite/g++.dg/cpp0x/trailing12.C
index f3e02a8..707b753 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing12.C
@@ -4,3 +4,13 @@
 auto get(int) -> int { return {}; }
 template  int f(auto (*)(int) -> R) { return {}; }
 int i = f(get);
+
+struct X {
+  auto get(int) const & throw() -> int { return {}; }
+  auto get(int) && -> long { return {}; }
+};
+
+template  auto f(auto (X::*)(int) const & -> R) -> R {}
+
+using I = decltype(f(&X::get));
+using I = int;
-- 
2.7.0



Re: [PATCH] PR c++/69139

2016-02-08 Thread Adam Butcher

On 2016-02-08 19:14, Patrick Palka wrote:

On Mon, 8 Feb 2016, Jason Merrill wrote:

On 02/08/2016 11:43 AM, Patrick Palka wrote:
BTW, last month I posted a patch for this PR that handles all kinds 
of

specifiers as well __attribute__ specifiers.
Patch is at: 
https://gcc.gnu.org/ml/gcc-patches/2016-01/msg02004.html

-- it makes the parser arbitrarily look ahead (while skipping over
pairs of parens) until it finds a DEREF, a COMMA, a CLOSE_PAREN or 
an

EQ.  If it first finds a DEREF then have_trailing_return_fn_decl is
set.  Dunno if it's better to have this kind of "dumb" lookahead, 
or

to be more explicit about one expects to consume like your followup
patch does.


Hmm, I think I prefer your approach [snip]


Me too.  I was worried that the cases handled in the explicit solution 
might get longer, more complex and repeat large amounts of other parser 
code.  Providing this approach gives us no false positives I would say 
it's superior.


[PATCH] Fix PR c++/59635

2014-01-04 Thread Adam Butcher
* cp/lambda.c (maybe_add_lambda_conv_op): Handle marking conversion
function as unimplemented for generic lambdas with varargs.

* g++.dg/opt/pr59635.C: New testcase.
---
 gcc/cp/lambda.c  | 2 +-
 gcc/testsuite/g++.dg/cpp1y/pr59635.C | 9 +
 2 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr59635.C

diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 1855716..8bb820d 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -970,7 +970,7 @@ maybe_add_lambda_conv_op (tree type)
  the conversion op is used.  */
   if (varargs_function_p (callop))
 {
-  DECL_DELETED_FN (fn) = 1;
+  DECL_DELETED_FN (STRIP_TEMPLATE (fn)) = 1;
   return;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59635.C 
b/gcc/testsuite/g++.dg/cpp1y/pr59635.C
new file mode 100644
index 000..07bd6c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59635.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// { dg-options "-std=c++1y" }
+
+// PR c++/59635
+
+auto f = [] (auto, ...) { return 0; };
+
+int (*p) (int, ...) = f;  // { dg-error "unimplemented" }
+
-- 
1.8.5.2



[PATCH] Fix PR c++/59636

2014-01-04 Thread Adam Butcher
* cp/parser.c (cp_parser_template_parameter): Early out with
error_mark_node if parameter declaration was not parsed.

* g++.dg/cpp1y/pr59636.C: New testcase.
---
 gcc/cp/parser.c  | 12 ++--
 gcc/testsuite/g++.dg/cpp1y/pr59636.C |  7 +++
 2 files changed, 13 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr59636.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 35dcefd..4f737df 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12981,20 +12981,21 @@ cp_parser_template_parameter (cp_parser* parser, bool 
*is_non_type,
  = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
/*parenthesized_p=*/NULL);
 
+  if (!parameter_declarator)
+return error_mark_node;
+
   /* If the parameter declaration is marked as a parameter pack, set
  *IS_PARAMETER_PACK to notify the caller. Also, unmark the
  declarator's PACK_EXPANSION_P, otherwise we'll get errors from
  grokdeclarator. */
-  if (parameter_declarator
-  && parameter_declarator->declarator
+  if (parameter_declarator->declarator
   && parameter_declarator->declarator->parameter_pack_p)
 {
   *is_parameter_pack = true;
   parameter_declarator->declarator->parameter_pack_p = false;
 }
 
-  if (parameter_declarator
-  && parameter_declarator->default_argument)
+  if (parameter_declarator->default_argument)
 {
   /* Can happen in some cases of erroneous input (c++/34892).  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -13018,8 +13019,7 @@ cp_parser_template_parameter (cp_parser* parser, bool 
*is_non_type,
   /* We might end up with a pack expansion as the type of the non-type
  template parameter, in which case this is a non-type template
  parameter pack.  */
-  else if (parameter_declarator
-  && parameter_declarator->decl_specifiers.type
+  else if (parameter_declarator->decl_specifiers.type
   && PACK_EXPANSION_P (parameter_declarator->decl_specifiers.type))
 {
   *is_parameter_pack = true;
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59636.C 
b/gcc/testsuite/g++.dg/cpp1y/pr59636.C
new file mode 100644
index 000..f2ca5b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59636.C
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-std=c++1y" }
+
+// PR c++/59636
+
+auto f = []() { return []<>() {}; };  // { dg-error "expected identifier" }
+
-- 
1.8.5.2



Re: [PATCH] Fix PR c++/59635

2014-01-04 Thread Adam Butcher

On 2014-01-03 21:45, Adam Butcher wrote:

* g++.dg/opt/pr59635.C: New testcase.


s/opt/cpp1y/


+int (*p) (int, ...) = f;  // { dg-error "unimplemented" }


s/dg-error/dg-message/




[PATCH] Fix PR c++/59629

2014-01-05 Thread Adam Butcher
* cp/parser.c (cp_parser_lambda_expression): Save/reset/restore
auto_is_implicit_function_template_parm_p around lambda body.

* g++.dg/cpp1y/pr59629.C: New testcase.
---
 gcc/cp/parser.c  | 5 +
 gcc/testsuite/g++.dg/cpp1y/pr59629.C | 7 +++
 2 files changed, 12 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr59629.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4f737df..0e013b9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8740,6 +8740,8 @@ cp_parser_lambda_expression (cp_parser* parser)
 = parser->fully_implicit_function_template_p;
 tree implicit_template_parms = parser->implicit_template_parms;
 cp_binding_level* implicit_template_scope = 
parser->implicit_template_scope;
+bool auto_is_implicit_function_template_parm_p
+= parser->auto_is_implicit_function_template_parm_p;
 
 parser->num_template_parameter_lists = 0;
 parser->in_statement = 0;
@@ -8747,6 +8749,7 @@ cp_parser_lambda_expression (cp_parser* parser)
 parser->fully_implicit_function_template_p = false;
 parser->implicit_template_parms = 0;
 parser->implicit_template_scope = 0;
+parser->auto_is_implicit_function_template_parm_p = false;
 
 /* By virtue of defining a local class, a lambda expression has access to
the private variables of enclosing classes.  */
@@ -8774,6 +8777,8 @@ cp_parser_lambda_expression (cp_parser* parser)
= fully_implicit_function_template_p;
 parser->implicit_template_parms = implicit_template_parms;
 parser->implicit_template_scope = implicit_template_scope;
+parser->auto_is_implicit_function_template_parm_p
+   = auto_is_implicit_function_template_parm_p;
   }
 
   pop_deferring_access_checks ();
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59629.C 
b/gcc/testsuite/g++.dg/cpp1y/pr59629.C
new file mode 100644
index 000..a0c9209
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59629.C
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-std=c++1y" }
+
+// PR c++/59629
+
+void foo(int i = []{ auto 0; }()); // { dg-error "expected|could not convert" }
+
-- 
1.8.5.2



[PATCH] Fix PR c++/59638

2014-01-05 Thread Adam Butcher
* cp/parser.c (cp_parser_init_declarator): Undo fully implicit
template parameter list when declarator is not a function.

* g++.dg/cpp1y/pr59638.C: New testcase.
---
 gcc/cp/parser.c  |  8 
 gcc/testsuite/g++.dg/cpp1y/pr59638.C | 16 
 2 files changed, 24 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr59638.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0e013b9..991588d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16784,6 +16784,14 @@ cp_parser_init_declarator (cp_parser* parser,
   warning (OPT_Wattributes,
   "attributes after parenthesized initializer ignored");
 
+  /* Declarations involving function parameter lists containing implicit
+ template parameters will have been made into implicit templates.  If they
+ do not turn out to be actual function declarations then finish the
+ template declaration here.  */
+  if (parser->fully_implicit_function_template_p)
+if (!function_declarator_p (declarator))
+  finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
+
   /* For an in-class declaration, use `grokfield' to create the
  declaration.  */
   if (member_p)
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59638.C 
b/gcc/testsuite/g++.dg/cpp1y/pr59638.C
new file mode 100644
index 000..cd9dcdf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59638.C
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/59638
+
+
+void (*a)(auto); // { dg-error "template declaration" }
+
+void (*b)(auto) = 0; // { dg-error "template declaration" }
+
+typedef void (*f)(auto); // { dg-error "template declaration" }
+
+struct A
+{
+  int i;
+};
-- 
1.8.5.2



Re: [PATCH] Fix PR c++/59638

2014-01-06 Thread Adam Butcher

On 2014-01-06 14:36, Jason Merrill wrote:

On 01/04/2014 04:54 AM, Adam Butcher wrote:
+  /* Declarations involving function parameter lists containing 
implicit
+ template parameters will have been made into implicit 
templates.  If they
+ do not turn out to be actual function declarations then finish 
the

+ template declaration here.  */


This will always be an error, right?  Please mention that in the
comment.  OK with that change.


Yes I think so.  Will commit with this mod:

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 991588d..68f81b7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16784,10 +16784,11 @@ cp_parser_init_declarator (cp_parser* parser,
   warning (OPT_Wattributes,
   "attributes after parenthesized initializer ignored");

-  /* Declarations involving function parameter lists containing 
implicit
- template parameters will have been made into implicit templates.  
If they
- do not turn out to be actual function declarations then finish 
the

- template declaration here.  */
+  /* A non-template declaration involving a function parameter list 
containing
+ an implicit template parameter will have been made into a 
template.  If it
+ turns out that the resulting declaration is not an actual 
function then
+ finish the template declaration here.  An error message will 
already have

+ been issued.  */
   if (parser->fully_implicit_function_template_p)
 if (!function_declarator_p (declarator))
   finish_fully_implicit_template (parser, /*member_decl_opt=*/0);



Re: [C++ PATCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-09 Thread Adam Butcher

On 2013-11-08 18:50, Jason Merrill wrote:

On 10/31/2013 05:47 AM, Adam Butcher wrote:

+ become_template = true;

+ push_deferring_access_checks (dk_deferred);


Why is this call here?  I don't see anything in the rest of the
function that would trigger an access check, or a matching pop.

This is only in the 'fully implicit function template' case; and the 
matching pop is in finish_fully_implicit_template.  It was in the 
original impl which was trying to do all the things that beginning and 
ending an explicit template parameter list did.  Maybe this is 
unnecessary.  I'll see if anything breaks if I remove it.


+  /* Create a distinct parameter pack type from the current 
parm and add it
+to the replacement args to tsubst below into the generic 
function

+parameter.  */
+
+  tree t = copy_type (TREE_TYPE (TREE_VALUE (TREE_VEC_ELT 
(current, i;

+  TYPE_STUB_DECL (t) = TYPE_NAME (t) = TEMPLATE_TYPE_DECL (t);


Is this changing anything?  I'm not sure if we need to copy the decl
or if we can just reuse it, but either way we need to set the type of
TEMPLATE_TYPE_DECL (t) to t.

I think it (or at least one of the assignments) is necessary.  It is 
derived from some similar code in tsubst.  I'll have another look into 
it and add TREE_TYPE (TEMPLATE_TYPE_DECL (t)) = t also.  What problem 
will be caused by not setting the latter; is it a consistency issue?  I 
have not seen any probs in testing so far.



+  SET_TYPE_STRUCTURAL_EQUALITY (t);


Why not

  TYPE_CANONICAL (t) = canonical_type_parameter (t);

?

Only for the sake of not exposing this (currently static) function from 
pt.c (or moving the pack convert function into pt.c).  My original impl 
did extern canonical_type_parameter and use that and I think it worked 
as expected.  Would that be preferred?


Cheers,
Adam



Re: [C++ PATCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-09 Thread Adam Butcher

On 2013-11-09 13:21, Adam Butcher wrote:

On 2013-11-08 18:50, Jason Merrill wrote:

On 10/31/2013 05:47 AM, Adam Butcher wrote:

+ become_template = true;

+ push_deferring_access_checks (dk_deferred);


Why is this call here?  I don't see anything in the rest of the
function that would trigger an access check, or a matching pop.


This is only in the 'fully implicit function template' case; and the
matching pop is in finish_fully_implicit_template.  It was in the
original impl which was trying to do all the things that beginning 
and

ending an explicit template parameter list did.  Maybe this is
unnecessary.  I'll see if anything breaks if I remove it.

+  /* Create a distinct parameter pack type from the current 
parm and add it
+to the replacement args to tsubst below into the generic 
function

+parameter.  */
+
+  tree t = copy_type (TREE_TYPE (TREE_VALUE (TREE_VEC_ELT 
(current, i;

+  TYPE_STUB_DECL (t) = TYPE_NAME (t) = TEMPLATE_TYPE_DECL (t);


Is this changing anything?  I'm not sure if we need to copy the decl
or if we can just reuse it, but either way we need to set the type 
of

TEMPLATE_TYPE_DECL (t) to t.


I think it (or at least one of the assignments) is necessary.  It is
derived from some similar code in tsubst.  I'll have another look 
into

it and add TREE_TYPE (TEMPLATE_TYPE_DECL (t)) = t also.  What problem
will be caused by not setting the latter; is it a consistency issue?
I have not seen any probs in testing so far.


+  SET_TYPE_STRUCTURAL_EQUALITY (t);


Why not

  TYPE_CANONICAL (t) = canonical_type_parameter (t);

?


Only for the sake of not exposing this (currently static) function
from pt.c (or moving the pack convert function into pt.c).  My
original impl did extern canonical_type_parameter and use that and I
think it worked as expected.  Would that be preferred?


The following update appears to work.

Cheers,
Adam

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index be799a0..aba4a09 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -31270,8 +31270,6 @@ synthesize_implicit_template_parm  (cp_parser *parser)
 
 	  become_template = true;
 
-	  push_deferring_access_checks (dk_deferred);
-
 	  parser->implicit_template_scope
 	  = begin_scope (sk_template_parms, NULL);
 
@@ -31362,10 +31360,12 @@ convert_generic_types_to_packs (tree parm,
 	 parameter.  */
 
   tree t = copy_type (TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (current, i;
+  TREE_TYPE (TEMPLATE_TYPE_DECL (t)) = t;
   TYPE_STUB_DECL (t) = TYPE_NAME (t) = TEMPLATE_TYPE_DECL (t);
   TYPE_MAIN_VARIANT (t) = t;
   TEMPLATE_TYPE_PARAMETER_PACK (t) = true;
-  SET_TYPE_STRUCTURAL_EQUALITY (t);
+  extern tree canonical_type_parameter (tree);
+  TYPE_CANONICAL (t) = canonical_type_parameter (t);
   TREE_VEC_ELT (replacement, i) = t;
 }
 
@@ -31406,7 +31406,6 @@ finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt)
   DECL_VIRTUAL_P (member_decl_opt) = false;
 }
 
-  pop_deferring_access_checks ();
   if (member_decl_opt)
 member_decl_opt = finish_member_template_decl (member_decl_opt);
   end_template_decl ();
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8c1553f..d3047cb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3546,7 +3546,7 @@ build_template_parm_index (int index,
parameter.  Returns the canonical type parameter, which may be TYPE
if no such parameter existed.  */
 
-static tree
+tree
 canonical_type_parameter (tree type)
 {
   tree list;


Re: [C++ PATCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-10 Thread Adam Butcher

On 2013-11-10 6:10, Jason Merrill wrote:


Hmm, actually I think messing with the non-pack's decl is dangerous,
and we should come up with a new decl for the pack instead.  I think
you can use reduce_template_parm_level with a "levels" argument of 0
to build a new decl and parm index.


I actually did this in one of my experiments and it worked fine.
Although I also had to update the template parm list with new decl:

  TREE_VALUE (TREE_VEC_ELT (current, i)) = TREE_CHAIN (t);

At that point I had the convert function in pt.c an operating directly
on current_template_parms (also having direct access to the two statics
required; reduce_template_parm_level and canonical_type_parameter).

I can't think of a case where we'd want to make this substitution in
anything but the current_template_parms so maybe moving the convert
function back into to pt.c and removing the 'current' parm from it
might be best?


And if we're doing that, setting TYPE_STUB_DECL and TYPE_NAME is
indeed necessary.

Only for the sake of not exposing this (currently static) function 
from
pt.c (or moving the pack convert function into pt.c).  My original 
impl
did extern canonical_type_parameter and use that and I think it 
worked

as expected.  Would that be preferred?


Yes.  Please declare it in cp-tree.h rather than within the function.


Will do.  Unless, as suggested above, we go for moving
convert_generic_types_to_packs into pt.c in which case exposing these
internals won't be necessary.

Cheers,
Adam



Re: [C++ PATCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-10 Thread Adam Butcher

On 2013-11-10 10:38, Adam Butcher wrote:

On 2013-11-10 6:10, Jason Merrill wrote:


Hmm, actually I think messing with the non-pack's decl is dangerous,
and we should come up with a new decl for the pack instead.  I think
you can use reduce_template_parm_level with a "levels" argument of 0
to build a new decl and parm index.


I actually did this in one of my experiments and it worked fine.
Although I also had to update the template parm list with new decl:

  TREE_VALUE (TREE_VEC_ELT (current, i)) = TREE_CHAIN (t);

At that point I had the convert function in pt.c an operating 
directly
on current_template_parms (also having direct access to the two 
statics

required; reduce_template_parm_level and canonical_type_parameter).

I can't think of a case where we'd want to make this substitution in
anything but the current_template_parms so maybe moving the convert
function back into to pt.c and removing the 'current' parm from it
might be best?


And if we're doing that, setting TYPE_STUB_DECL and TYPE_NAME is
indeed necessary.

Only for the sake of not exposing this (currently static) function 
from
pt.c (or moving the pack convert function into pt.c).  My original 
impl
did extern canonical_type_parameter and use that and I think it 
worked

as expected.  Would that be preferred?


Yes.  Please declare it in cp-tree.h rather than within the 
function.



Will do.  Unless, as suggested above, we go for moving
convert_generic_types_to_packs into pt.c in which case exposing these
internals won't be necessary.



With the convert function in pt.c, PATCH 2/3 now looks as follows:


Support implicit parameter packs.

	* pt.c (convert_generic_types_to_packs): New function to transform
	a range of implicitly introduced non-pack template parms to be parameter
	packs.
	* cp-tree.h (convert_generic_types_to_packs): Declare.
	* parser.c (cp_parser_parameter_declaration_list): If a function
	parameter pack contains generic types, convert them to packs prior to
	grokdeclarator.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fd79adb..e30922a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5469,6 +5469,7 @@ extern tree type_uses_auto			(tree);
 extern tree type_uses_auto_or_concept		(tree);
 extern void append_type_to_template_for_access_check (tree, tree, tree,
 		  location_t);
+extern tree convert_generic_types_to_packs	(tree, int, int);
 extern tree splice_late_return_type		(tree, tree);
 extern bool is_auto(const_tree);
 extern bool is_auto_or_concept			(const_tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c48952a..eaad8e4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18131,6 +18131,10 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   cp_parameter_declarator *parameter;
   tree decl = error_mark_node;
   bool parenthesized_p = false;
+  int template_parm_idx = (parser->num_template_parameter_lists?
+			   TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+		(current_template_parms)) : 0);
+
   /* Parse the parameter.  */
   parameter
 	= cp_parser_parameter_declaration (parser,
@@ -18142,11 +18146,29 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   deprecated_state = DEPRECATED_SUPPRESS;
 
   if (parameter)
+	{
+	  /* If a function parameter pack was specified and an implicit template
+	 parameter was introduced during cp_parser_parameter_declaration,
+	 change any implicit parameters introduced into packs.  */
+	  if (parser->implicit_template_parms
+	  && parameter->declarator
+	  && parameter->declarator->parameter_pack_p)
+	{
+	  int latest_template_parm_idx = TREE_VEC_LENGTH
+		(INNERMOST_TEMPLATE_PARMS (current_template_parms));
+
+	  if (latest_template_parm_idx != template_parm_idx)
+		parameter->decl_specifiers.type = convert_generic_types_to_packs
+		  (parameter->decl_specifiers.type,
+		   template_parm_idx, latest_template_parm_idx);
+	}
+
 	  decl = grokdeclarator (parameter->declarator,
  ¶meter->decl_specifiers,
  PARM,
  parameter->default_argument != NULL_TREE,
  ¶meter->decl_specifiers.attributes);
+	}
 
   deprecated_state = DEPRECATED_NORMAL;
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8c1553f..360d8a3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21629,6 +21629,56 @@ append_type_to_template_for_access_check (tree templ,
 	  scope, location);
 }
 
+/* Convert the generic type parameters in PARM that match the types given in the
+   range [START_IDX, END_IDX) from the current_template_parms into generic type
+   packs.  */
+
+tree
+convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
+{
+  tree current = current_template_parms;
+  int depth = TMPL_PARMS_DEPTH (current);
+  current = INNERMOST_TEMPLATE_PARMS (current);
+  tree replacem

Re: [C++ PATCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-10 Thread Adam Butcher

On 2013-11-10 18:49, Jason Merrill wrote:

On 11/10/2013 08:10 AM, Adam Butcher wrote:


+  /* Build up a tree vec of empty tree vecs up to the inner 
substitution

+args built above.  */


I think we want to copy the enclosing args; see existing uses of
add_outermost_template_args.

OK.  I had that originally but I was concerned that it was wasteful 
which is why I ended up using nullptrs for non-subst'd types in the 
inner level and empty tree vecs for the prior levels.  It seemed to work 
as expected; I assumed that tsubst simply doesn't do anything with a 
null tree substitution (i.e. it is an identity op).  There will be an 
additional, seemingly unnecessary, cost of copying these and the loop 
above will presumably be required to set the non-subst'd types rather 
than leave them as nullptr also.


Since we are tsubsting the declaration here and we only want to adjust 
the template parameter types themselves at their declaration is this 
really necessary?  I've no problem with implementing this if it truly is 
necessary but I don't want to add unnecessary cycles if not.


One other thing, by 'copy' I take it you mean copy the tree vecs of the 
enclosing levels only, not also the types within them.  And I also 
assume that I'll need to set the currently unset types in the inner 
level also?


Cheers
Adam



Re: [C++ PATCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.

2013-11-11 Thread Adam Butcher

On 2013-11-10 23:21, Jason Merrill wrote:

On 11/10/2013 02:39 PM, Adam Butcher wrote:

I assumed that tsubst simply doesn't do anything with a
null tree substitution (i.e. it is an identity op).


Substituting NULL_TREE for a template parameter gives a template
parameter with a reduced level; this happens during partial
instantiation.


Ah, OK.

Since we are tsubsting the declaration here and we only want to 
adjust

the template parameter types themselves at their declaration is this
really necessary?  I've no problem with implementing this if it 
truly is

necessary but I don't want to add unnecessary cycles if not.


The difference between setting copying a pointer to a vec versus
setting it to null seems completely negligible to me.

Sure.  I was more concerned with allocating vecs for each outer list 
and copying the parms over versus allocating a 'null' placeholder list 
for each level which we're not concerned about.  No worries though, I've 
proceeded with your suggestion below.



I think it is necessary in case the function parameter type involves
template parameters from the enclosing context as well as implicit
template parameters.

One other thing, by 'copy' I take it you mean copy the tree vecs of 
the

enclosing levels only, not also the types within them.


Yes, using add_outermost_template_args.

I have done this (diff -w -b follows).  The route to this seems even 
more costly though; current_template_parms needs to first be converted 
to a vec by current_template_args() then the last nesting level is 
thrown away and replaced with the one we're working on.  It's all 
working but I'm wondering whether a custom loop here would be better.


And I also assume that I'll need to set the currently unset types in 
the inner

level also?


Can you have explicit template parameters at the same level as the
implicit ones?


Yes.


If so, then their places in the vec will need to be
set appropriately in case they are used in the function parameter
type.

OK.  I had testcases that appeared to pass OK with the previous 
NULL_TREE tsubst but maybe I wasn't checking something (perhaps a 
combination of an explicit template parm type and an auto in a single 
parm).


End result is that everything looks OK though so we might be able to 
get the C++14 lambda support marked as "in 4.9" soon hopefully.


Cheers,
Adam
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 360d8a3..69c7688 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21641,6 +21641,10 @@ convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
   current = INNERMOST_TEMPLATE_PARMS (current);
   tree replacement = make_tree_vec (TREE_VEC_LENGTH (current));
 
+  for (int i = 0; i < start_idx; ++i)
+TREE_VEC_ELT (replacement, i)
+  = TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (current, i)));
+
   for (int i = start_idx; i < end_idx; ++i)
 {
   /* Create a distinct parameter pack type from the current parm and add it
@@ -21662,18 +21666,15 @@ convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
   TREE_VALUE (TREE_VEC_ELT (current, i)) = TREE_CHAIN (t);
 }
 
+  for (int i = end_idx, e = TREE_VEC_LENGTH (current); i < e; ++i)
+TREE_VEC_ELT (replacement, i)
+  = TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (current, i)));
+
   if (depth > 1)
-{
 /* Build up a tree vec of empty tree vecs up to the inner substitution
args built above.  */
-
-  tree inner = replacement;
-  replacement = make_tree_vec (depth);
-  int last = depth - 1;
-  for (int i = 0; i < last; ++i)
-	TREE_VEC_ELT (replacement, i) = make_tree_vec (0);
-  TREE_VEC_ELT (replacement, last) = inner;
-}
+replacement = add_outermost_template_args (current_template_args (),
+	   replacement);
 
   return tsubst (parm, replacement, tf_none, NULL_TREE);
 }


[PATCH] Fix c++/59112 and c++/59113: Disallow implicit function templates in local functions unless defining a lambda.

2013-11-24 Thread Adam Butcher
gcc/cp/
PR c++/59112
PR c++/59113
* parser.c (cp_parser_parameter_declaration_clause): Disallow implicit
function templates in local functions unless defining a lambda.

gcc/testsuite/
PR c++/59112
PR c++/59113
g++.dg/cpp1y/pr58533.C: Updated testcase.
g++.dg/cpp1y/pr59112.C: New testcase.
g++.dg/cpp1y/pr59113.C: New testcase.
---
 gcc/cp/parser.c  |  4 +++-
 gcc/testsuite/g++.dg/cpp1y/pr58533.C |  2 +-
 gcc/testsuite/g++.dg/cpp1y/pr59112.C | 12 
 gcc/testsuite/g++.dg/cpp1y/pr59113.C | 11 +++
 4 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr59112.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr59113.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index eaad8e4..1a26811 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18026,7 +18026,9 @@ cp_parser_parameter_declaration_clause (cp_parser* 
parser)
   (void) cleanup;
 
   if (!processing_specialization)
-parser->auto_is_implicit_function_template_parm_p = true;
+if (!current_function_decl
+   || (current_class_type && LAMBDA_TYPE_P (current_class_type)))
+  parser->auto_is_implicit_function_template_parm_p = true;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58533.C 
b/gcc/testsuite/g++.dg/cpp1y/pr58533.C
index e1855d7..9bcd771 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr58533.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58533.C
@@ -3,5 +3,5 @@
 
 void foo()
 {
-  void (*fp)(auto); // { dg-error "template" }
+  void (*fp)(auto); // { dg-error "auto|not permitted" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59112.C 
b/gcc/testsuite/g++.dg/cpp1y/pr59112.C
new file mode 100644
index 000..e7326ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59112.C
@@ -0,0 +1,12 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/59112
+
+void foo()
+{
+  struct A
+  {
+A(auto) {} // { dg-error "auto|not permitted" }
+  };
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59113.C 
b/gcc/testsuite/g++.dg/cpp1y/pr59113.C
new file mode 100644
index 000..f909a76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr59113.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/59113
+
+void foo()
+{
+  void bar(auto) {} // { dg-error "function-definition|auto|not permitted" }
+}
+
+auto i = 0;
-- 
1.8.4



[PATCH] Fix PR c++/61537

2014-06-24 Thread Adam Butcher
* parser.c (cp_parser_elaborated_type_specifier): Only consider template
parameter lists outside of function parameter scope.

* g++.dg/cpp1y/pr61537.C: New testcase.
---
 gcc/cp/parser.c  | 28 +++-
 gcc/testsuite/g++.dg/cpp1y/pr61537.C | 24 
 2 files changed, 43 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr61537.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 41200a0..736d012 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15081,6 +15081,15 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
return cp_parser_make_typename_type (parser, parser->scope,
 identifier,
 token->location);
+
+  /* Template parameter lists apply only if we are not within a
+function parameter list.  */
+  bool template_parm_lists_apply
+ = parser->num_template_parameter_lists;
+  for (cp_binding_level *s = current_binding_level; s; s = s->level_chain)
+   if (s->kind == sk_function_parms)
+ template_parm_lists_apply = false;
+
   /* Look up a qualified name in the usual way.  */
   if (parser->scope)
{
@@ -15123,7 +15132,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
  decl = (cp_parser_maybe_treat_template_as_class
  (decl, /*tag_name_p=*/is_friend
-&& parser->num_template_parameter_lists));
+&& template_parm_lists_apply));
 
  if (TREE_CODE (decl) != TYPE_DECL)
{
@@ -15136,9 +15145,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
  if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
 {
-  bool allow_template = (parser->num_template_parameter_lists
- || DECL_SELF_REFERENCE_P (decl));
-  type = check_elaborated_type_specifier (tag_type, decl, 
+  bool allow_template = (template_parm_lists_apply
+|| DECL_SELF_REFERENCE_P (decl));
+  type = check_elaborated_type_specifier (tag_type, decl,
   allow_template);
 
   if (type == error_mark_node)
@@ -15224,15 +15233,16 @@ cp_parser_elaborated_type_specifier (cp_parser* 
parser,
ts = ts_global;
 
  template_p =
-   (parser->num_template_parameter_lists
+   (template_parm_lists_apply
 && (cp_parser_next_token_starts_class_definition_p (parser)
 || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)));
  /* An unqualified name was used to reference this type, so
 there were no qualifying templates.  */
- if (!cp_parser_check_template_parameters (parser,
-   /*num_templates=*/0,
-   token->location,
-   /*declarator=*/NULL))
+ if (template_parm_lists_apply
+ && !cp_parser_check_template_parameters (parser,
+  /*num_templates=*/0,
+  token->location,
+  /*declarator=*/NULL))
return error_mark_node;
  type = xref_tag (tag_type, identifier, ts, template_p);
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr61537.C 
b/gcc/testsuite/g++.dg/cpp1y/pr61537.C
new file mode 100644
index 000..55761cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr61537.C
@@ -0,0 +1,24 @@
+// PR c++/61537
+// { dg-do compile { target c++1y } }
+// { dg-options "" }
+
+struct A {};
+
+template 
+struct B
+{
+  template 
+  void f(U, struct A);
+};
+
+template 
+template 
+void B::f(U, struct A)
+{
+}
+
+int main()
+{
+  B b;
+  b.f(42, A());
+}
-- 
2.0.0



Re: [PATCH] Fix PR c++/61537

2014-06-24 Thread Adam Butcher

On 2014-06-24 23:22, Paolo Carlini wrote:

On 06/24/2014 01:40 AM, Adam Butcher wrote:

+// { dg-do compile { target c++1y } }

I don't think this is a C++1y specific issue...


You're right.  I'm so used to creating pr testcases in that 
g++.dg/cpp1y dir, I automatically added the test there without engaging 
my brain!



+// { dg-options "" }
Also, likely minor detail, could you please explain why you need 
this?




Don't think I do; it was a copy from the most recent test in the cpp1y 
dir (another bad habit).  Same issue as before; need to engage brain. :)


I've fixed these issues up in my tree and moved the test to g++.dg.

Cheers,
Adam

diff --git a/gcc/testsuite/g++.dg/cpp1y/pr61537.C 
b/gcc/testsuite/g++.dg/pr61537.C

similarity index 79%
rename from gcc/testsuite/g++.dg/cpp1y/pr61537.C
rename to gcc/testsuite/g++.dg/pr61537.C
index 55761cd..12aaf58 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr61537.C
+++ b/gcc/testsuite/g++.dg/pr61537.C
@@ -1,6 +1,5 @@
 // PR c++/61537
-// { dg-do compile { target c++1y } }
-// { dg-options "" }
+// { dg-do compile }

 struct A {};




Re: [PATCH] Fix PR c++/61537

2014-06-25 Thread Adam Butcher
* parser.c (cp_parser_elaborated_type_specifier): Only consider template
parameter lists outside of function parameter scope.

* g++.dg/template/pr61537.C: New testcase.
---
 gcc/cp/parser.c | 31 ++-
 gcc/testsuite/g++.dg/template/pr61537.C | 23 +++
 2 files changed, 45 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/pr61537.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 41200a0..c440c99 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15081,6 +15081,18 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
return cp_parser_make_typename_type (parser, parser->scope,
 identifier,
 token->location);
+
+  /* Template parameter lists apply only if we are not within a
+function parameter list.  */
+  bool template_parm_lists_apply
+ = parser->num_template_parameter_lists;
+  if (template_parm_lists_apply)
+   for (cp_binding_level *s = current_binding_level;
+s && s->kind != sk_template_parms;
+s = s->level_chain)
+ if (s->kind == sk_function_parms)
+   template_parm_lists_apply = false;
+
   /* Look up a qualified name in the usual way.  */
   if (parser->scope)
{
@@ -15123,7 +15135,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
  decl = (cp_parser_maybe_treat_template_as_class
  (decl, /*tag_name_p=*/is_friend
-&& parser->num_template_parameter_lists));
+&& template_parm_lists_apply));
 
  if (TREE_CODE (decl) != TYPE_DECL)
{
@@ -15136,9 +15148,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
  if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
 {
-  bool allow_template = (parser->num_template_parameter_lists
- || DECL_SELF_REFERENCE_P (decl));
-  type = check_elaborated_type_specifier (tag_type, decl, 
+  bool allow_template = (template_parm_lists_apply
+|| DECL_SELF_REFERENCE_P (decl));
+  type = check_elaborated_type_specifier (tag_type, decl,
   allow_template);
 
   if (type == error_mark_node)
@@ -15224,15 +15236,16 @@ cp_parser_elaborated_type_specifier (cp_parser* 
parser,
ts = ts_global;
 
  template_p =
-   (parser->num_template_parameter_lists
+   (template_parm_lists_apply
 && (cp_parser_next_token_starts_class_definition_p (parser)
 || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)));
  /* An unqualified name was used to reference this type, so
 there were no qualifying templates.  */
- if (!cp_parser_check_template_parameters (parser,
-   /*num_templates=*/0,
-   token->location,
-   /*declarator=*/NULL))
+ if (template_parm_lists_apply
+ && !cp_parser_check_template_parameters (parser,
+  /*num_templates=*/0,
+  token->location,
+  /*declarator=*/NULL))
return error_mark_node;
  type = xref_tag (tag_type, identifier, ts, template_p);
}
diff --git a/gcc/testsuite/g++.dg/template/pr61537.C 
b/gcc/testsuite/g++.dg/template/pr61537.C
new file mode 100644
index 000..12aaf58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr61537.C
@@ -0,0 +1,23 @@
+// PR c++/61537
+// { dg-do compile }
+
+struct A {};
+
+template 
+struct B
+{
+  template 
+  void f(U, struct A);
+};
+
+template 
+template 
+void B::f(U, struct A)
+{
+}
+
+int main()
+{
+  B b;
+  b.f(42, A());
+}
-- 
2.0.0



Re: [PATCH] Fix PR c++/61537

2014-06-25 Thread Adam Butcher

On 2014-06-25 21:57, Jason Merrill wrote:

OK, thanks.



Do you want me to apply to 4.9 too?


Re: [PATCH 1/2] PR c++/61636

2015-04-17 Thread Adam Butcher

On 2015-04-17 20:58, Jason Merrill wrote:

On 04/09/2015 11:31 PM, Adam Butcher wrote:

+   /* For generic lambdas, resolve default captured 'this' now.  */


This isn't quite right.  We don't want to capture 'this' any time we
see a member function call, as overload resolution might choose a
static member function that doesn't need 'this'.  The special 
handling

we want is for the case where the call depends on a generic lambda
parameter, in which case we capture 'this' because the call "names
[this] in a potentially-evaluated expression (3.2) where the 
enclosing

full-expression depends on a generic lambda parameter declared within
the reaching scope of the lambda-expression."

Good point.  I'll look into it.  So for a nullary member call we will 
always capture 'this', but for N-ary, we only capture if we find one of 
the lambda's parameters (or a parameter from an enclosing generic 
lambda?) in the call's arguments right?


Cheers,
Adam



Re: [PATCH 1/2] PR c++/61636

2015-04-18 Thread Adam Butcher

On 2015-04-17 22:06, Adam Butcher wrote:

On 2015-04-17 20:58, Jason Merrill wrote:

On 04/09/2015 11:31 PM, Adam Butcher wrote:

+   /* For generic lambdas, resolve default captured 'this' now.  */


This isn't quite right.  We don't want to capture 'this' any time we
see a member function call, as overload resolution might choose a
static member function that doesn't need 'this'.  The special 
handling

we want is for the case where the call depends on a generic lambda
parameter, in which case we capture 'this' because the call "names
[this] in a potentially-evaluated expression (3.2) where the 
enclosing
full-expression depends on a generic lambda parameter declared 
within

the reaching scope of the lambda-expression."


Good point.  I'll look into it.  So for a nullary member call we will
always capture 'this', but for N-ary, we only capture if we find one
of the lambda's parameters (or a parameter from an enclosing generic
lambda?) in the call's arguments right?



Test like this?

/* { dg-do run { target c++14 } }  */
/* { dg-final { scan-assembler-not "..." } }  */

struct X
{
  int f (int, double) { return 255; }
  static int f (int, int) { return 65535; }

  auto m1 ()
  {
return [=] (auto a) {
  return f (7, a);
};
  }

  auto m2 ()
  {
return [=] (auto a) {
  return f (9, 10) + a;
};
  }
};

#include 

int main()
{
  X x;
  assert (x.m1 () (42.0) == 255);
  assert (x.m1 () (42) == 65535);
  assert (x.m2 () (42.0) == (65535 + 42));
  assert (x.m2 () (42) == (65535 + 42));
  assert (sizeof x.m2 () < sizeof x.m1 ());
}




Re: [PATCH 1/2] PR c++/61636

2015-04-19 Thread Adam Butcher

On 2015-04-18 18:53, Adam Butcher wrote:


Test like this?

/* { dg-do run { target c++14 } }  */
/* { dg-final { scan-assembler-not "..." } }  */

struct X
{
  int f (int, double) { return 255; }
  static int f (int, int) { return 65535; }

  auto m1 ()
  {
return [=] (auto a) {
  return f (7, a);
};
  }

  auto m2 ()
  {
return [=] (auto a) {
  return f (9, 10) + a;
};
  }


And this:

  auto m3 ()
  {
return [=] (auto a) {
  return f (11, 12.0) + a;
};
  }

Currently we don't capture 'this' here despite the call not being 
dependent on any lambda parameter and resolving to a non-static member 
function.


I think I need to resolve a member call within a generic lambda as if 
it were not in template context to determine whether it unambiguously 
resolves to a static member function.  If it does, then no capture 
required.  Otherwise, 'this' should be captured because either a) the 
call is to a non-static member function without any dependent parameters 
or b) because it may resolve to a non-static member function at callop 
instantiate time.


No sure whether I can do all this at my current patch site in 
cp_parser_postfix_expression or whether it needs to be later.


Adam


Re: [PATCH 1/2] ?PR c++/61636

2015-04-20 Thread Adam Butcher

On 2015-04-20 11:25, Marek Polacek wrote:

On Sat, Apr 18, 2015 at 06:53:28PM +0100, Adam Butcher wrote:

Test like this?

/* { dg-do run { target c++14 } }  */
/* { dg-final { scan-assembler-not "..." } }  */


What is this dg-final supposed to do here?


It was a placeholder for making sure that, once fixed, the lambda 
depending on only the static member function does not capture 'this'.  I 
didn't get around to seeing whether that was possible from the asm 
output and if it were, what symbol I should check for the absence of.  
For now I have sizeof assertions but I suppose I could use an sfinae 
test for existence (or otherwise in this case) of the placeholder 
'__this'.




[PATCH 1/2] PR c++/61636 * cp/parser.c (cp_parser_postfix_expression): Resolve default captured 'this' early for generic lambdas.

2015-04-13 Thread Adam Butcher
PR c++/61636
* g++.dg/cpp1y/pr61636.C: New test.
---
 gcc/cp/parser.c  | 16 
 gcc/testsuite/g++.dg/cpp1y/pr61636.C | 19 +++
 2 files changed, 35 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr61636.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4d6b479..ac91976 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6321,6 +6321,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
tree instance = TREE_OPERAND (postfix_expression, 0);
tree fn = TREE_OPERAND (postfix_expression, 1);
 
+   /* For generic lambdas, resolve default captured 'this' now.  */
+   if (processing_template_decl
+   && is_dummy_object (instance)
+   && current_class_type
+   && CLASSTYPE_LAMBDA_EXPR (current_class_type))
+ if (tree callop = lambda_function (current_class_type))
+   if (DECL_TEMPLATE_INFO (callop)
+   && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop))
+   == callop)
+   && TREE_TYPE (instance) != current_class_type
+   && DERIVED_FROM_P (TREE_TYPE (instance),
+  current_nonlambda_class_type ()))
+ TREE_OPERAND (postfix_expression, 0)
+   = instance
+   = maybe_resolve_dummy (instance, true);
+
if (processing_template_decl
&& (type_dependent_expression_p (instance)
|| (!BASELINK_P (fn)
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr61636.C 
b/gcc/testsuite/g++.dg/cpp1y/pr61636.C
new file mode 100644
index 000..5694675
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr61636.C
@@ -0,0 +1,19 @@
+// PR c++/61636
+// { dg-do compile { target c++1y } }
+
+struct X
+{
+   void f(int) {}
+
+   auto defer_f()
+   {
+  return [&] (auto x) {
+ return f(x);
+  };
+   }
+};
+
+int main()
+{
+   X().defer_f()(2);
+}
-- 
2.3.5



[PATCH 2/2] PR c++/64382 * cp/parser.c (parsing_default_capturing_generic_lambda_in_template): New function. * cp/cp-tree.h: Declare it. * cp/semantics.c (finish_id_expression): Resolve names wit

2015-04-13 Thread Adam Butcher
PR c++/64382
* g++.dg/cpp1y/pr64382.C: New test.
---
 gcc/cp/cp-tree.h |  1 +
 gcc/cp/parser.c  | 21 +
 gcc/cp/semantics.c   |  8 +---
 gcc/testsuite/g++.dg/cpp1y/pr64382.C | 23 +++
 4 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr64382.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2a904a5..484f352 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5645,6 +5645,7 @@ extern bool maybe_clone_body  (tree);
 /* In parser.c */
 extern tree cp_convert_range_for (tree, tree, tree, bool);
 extern bool parsing_nsdmi (void);
+extern bool parsing_default_capturing_generic_lambda_in_template (void);
 extern void inject_this_parameter (tree, cp_cv_quals);
 
 /* in pt.c */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ac91976..74b55df 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18339,6 +18339,27 @@ parsing_nsdmi (void)
   return false;
 }
 
+/* Return true iff our current scope is a default capturing generic lambda
+   defined within a template.  */
+
+bool
+parsing_default_capturing_generic_lambda_in_template (void)
+{
+  if (processing_template_decl && current_class_type)
+if (tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type))
+  if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE)
+   if (tree callop = lambda_function (lam))
+ if (DECL_TEMPLATE_INFO (callop)
+ && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop))
+ == callop)
+ && ((current_nonlambda_class_type ()
+  && CLASSTYPE_TEMPLATE_INFO (current_nonlambda_class_type ()))
+ || ((current_nonlambda_function ()
+  && DECL_TEMPLATE_INFO (current_nonlambda_function ())
+   return true;
+  return false;
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
non-terminal, but part of a function declarator, which looks like
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 74af7e8..f1ab183 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3450,9 +3450,11 @@ finish_id_expression (tree id_expression,
}
}
 
-  /* If the name was dependent on a template parameter, we will
-resolve the name at instantiation time.  */
-  if (dependent_p)
+  /* If the name was dependent on a template parameter and we're not in a
+default capturing generic lambda within a template, we will resolve the
+name at instantiation time.  */
+  if (dependent_p
+ && !parsing_default_capturing_generic_lambda_in_template ())
{
  /* Create a SCOPE_REF for qualified names, if the scope is
 dependent.  */
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr64382.C 
b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
new file mode 100644
index 000..ff552ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
@@ -0,0 +1,23 @@
+// PR c++/64382
+// { dg-do compile { target c++1y } }
+
+template
+struct my_queue
+{
+  void push(T)
+  {
+  }
+  void ice()
+  {
+auto L = [=](auto &&v) {
+  push(v);
+};
+trav(L);
+  }
+  template
+  void trav(F &&f)
+  {
+f(T());
+  }
+};
+template struct my_queue;
-- 
2.3.5



[PATCH] [PR c++/61636 and c++/64382] Fix default capture in generic lambdas

2015-04-13 Thread Adam Butcher
Hi Jason,

I finally scraped some time together to look into these two generic
lambda default capture bugs and believe I have a solution.  Still have
to run tests but I thought I'd get these out for your perusal whilst I
rebase onto origin/master and run the testsuite.

Cheers,
Adam



Re: [PATCH 2/2] PR c++/64382 * cp/parser.c (parsing_default_capturing_generic_lambda_in_template): New function. * cp/cp-tree.h: Declare it. * cp/semantics.c (finish_id_expression): Resolve names

2015-04-14 Thread Adam Butcher

On 2015-04-14 8:26, Jakub Jelinek wrote:

I'd say best would be to just use separate ifs with return false.


Done.


Re: [PATCH 2/2] PR c++/64382 * cp/parser.c (parsing_default_capturing_generic_lambda_in_template)...

2015-04-14 Thread Adam Butcher

On 2015-04-10 4:31, Adam Butcher wrote:

+parsing_default_capturing_generic_lambda_in_template (void)

I'm wondering whether we should cache this as a bool on the parser.  
Currently it is called once per id-expression and will always return the 
same result for any given lambda.




[PATCH] PR c++/65750

2015-04-14 Thread Adam Butcher
* cp/parser.c (cp_parser_simple_type_specifier): Don't synthesize
implicit template parm if 'auto' is a placeholder for trailing return
type.
---
 gcc/cp/parser.c  | 23 +++
 gcc/testsuite/g++.dg/cpp1y/pr65750.C | 12 
 2 files changed, 35 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr65750.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4611be9..511ec85 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14949,6 +14949,29 @@ cp_parser_simple_type_specifier (cp_parser* parser,
   maybe_warn_cpp0x (CPP0X_AUTO);
   if (parser->auto_is_implicit_function_template_parm_p)
{
+ /* The 'auto' might be the placeholder return type for a function decl
+with trailing return type.  */
+ bool have_trailing_return_fn_decl = false;
+ if (cp_lexer_peek_nth_token (parser->lexer, 2)->type
+ == CPP_OPEN_PAREN)
+   {
+ cp_parser_parse_tentatively (parser);
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_parser_skip_to_closing_parenthesis (parser,
+/*recovering*/false,
+/*or_comma*/false,
+/*consume_paren*/true))
+   have_trailing_return_fn_decl
+ = cp_lexer_next_token_is (parser->lexer, CPP_DEREF);
+ cp_parser_abort_tentative_parse (parser);
+   }
+
+ if (have_trailing_return_fn_decl)
+   {
+ type = make_auto ();
+ break;
+   }
+
  if (cxx_dialect >= cxx14)
type = synthesize_implicit_template_parm (parser);
  else
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr65750.C 
b/gcc/testsuite/g++.dg/cpp1y/pr65750.C
new file mode 100644
index 000..798d13b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr65750.C
@@ -0,0 +1,12 @@
+// PR c++/65750
+// { dg-do compile { target c++14 } }
+
+template  struct F { };
+
+class a
+{
+  virtual auto f( F< void () > ) -> void;
+  virtual auto g( F< auto () -> void > ) -> void;
+};
+
+auto main() -> int { }
-- 
2.3.5



Re: [PATCH] PR c++/65750

2015-04-14 Thread Adam Butcher

On 2015-04-10 15:57, Adam Butcher wrote:

+ cp_lexer_consume_token (parser->lexer);


Actually there should be two of these as the 'auto' isn't consumed yet.


Re: [C++ Patch] Remove is_auto_or_concept, etc

2017-05-16 Thread Adam Butcher
Sorry for not getting back to your original post Paolo.  I haven't been 
picking up mails for a while.


On 2017-05-01 16:56, Jason Merrill wrote:
On Thu, Apr 27, 2017 at 2:02 PM, Paolo Carlini 
 wrote:

On 26/04/2017 12:32, Paolo Carlini wrote:


in 2013 (2013-09-16) Adam added two slightly obscure functions and I 
can't

find much around in terms of rationale, etc:

is_auto_or_concept (const_tree type)

type_uses_auto_or_concept (tree type)



I don't think they were there in the original 2009 version on the old 
lambdas branch -- but it stagnated somewhat and when I remade it against 
mainline (4.something) it was around the time that concepts were showing 
similar semantics (in terms of implicit/abbrievated templates).  I made 
a cardinal sin and introduced an overly-generic function name expecting 
that a future concepts implementation would need to trigger at the same 
point of the parse too.  I.e. if a concept name or 'auto' is seen we 
inject an implicit template parameter (or make the "plain" function into 
a template at that point).


That intent was not well documented or published (other than in the API 
name) and, since -fconcepts is now working without any calls to this 
function, it's clearly not been necessary or has been more naturally 
done in a different way.



The latter seems completely unused (it's meant for debugging 
purposes?);




Quite possibly for debugging though maybe some refactoring got rid of 
the need for it and neglected to bin it.




the former evidently simply forwards to is_auto, and we end up in the
front-end with uses of both, which in fact are equivalent, which 
seems
weird: IMHO, if they are actually equivalent in our implementation we 
should

clearly explain that in the comment and have only one. Or what?



... replying to myself, in practice we could do the below, which 
certainly
passes testing, and in fact now seems to me even more obvious than I 
thought

a couple of days ago...



Definitely OK to bin.  No point in having dead or confusing code; it's 
complicated enough as it is.  :)




[PATCH] Fix PR c++/64382

2017-01-19 Thread Adam Butcher
Hi Jason,

I've reopened 64382 and unhooked it from 61636
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64382#c6).

This is a rebase of my original patch for 64382 from April 2015 against latest
master.

My query about caching parsing_default_capturing_generic_lambda_in_template()
still applies.  It is currently called once for each id-expression that is
dependent but its result will be consistent within a particular lambda body.
It feels like we should compute the state once when entering a lambda body and
refer to the cached state thereafter (resetting/restoring it on descent/return
from each lambda we come across).

Cheers,
Adam

PR c++/64382
* cp/parser.c (parsing_default_capturing_generic_lambda_in_template):
New function.
* cp/cp-tree.h: Declare it.
* cp/semantics.c (finish_id_expression): Resolve names within a default
capturing generic lambda defined within a template prior to
instantiation to allow for captures to be added to the closure type.

PR c++/64382
* g++.dg/cpp1y/pr64382.C: New test.
---
 gcc/cp/cp-tree.h |  1 +
 gcc/cp/parser.c  | 25 +
 gcc/cp/semantics.c   |  8 +---
 gcc/testsuite/g++.dg/cpp1y/pr64382.C | 23 +++
 4 files changed, 54 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr64382.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9c4436710dd..77d20d4d3dc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6110,6 +6110,7 @@ extern bool maybe_clone_body  (tree);
 /* In parser.c */
 extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool);
 extern bool parsing_nsdmi (void);
+extern bool parsing_default_capturing_generic_lambda_in_template (void);
 extern void inject_this_parameter (tree, cp_cv_quals);
 
 /* in pt.c */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 29dcfea283f..5cc0ddacc2b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -20450,6 +20450,31 @@ parsing_nsdmi (void)
   return false;
 }
 
+/* Return true iff our current scope is a default capturing generic lambda
+   defined within a template.  */
+
+bool
+parsing_default_capturing_generic_lambda_in_template (void)
+{
+  if (!processing_template_decl || !current_class_type)
+return false;
+
+  tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type);
+  if (!lam || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) == CPLD_NONE)
+return false;
+
+  tree callop = lambda_function (lam);
+  if (!callop)
+return false;
+
+  return (DECL_TEMPLATE_INFO (callop)
+ && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop)
+ && ((current_nonlambda_class_type ()
+  && CLASSTYPE_TEMPLATE_INFO (current_nonlambda_class_type ()))
+ || ((current_nonlambda_function ()
+  && DECL_TEMPLATE_INFO (current_nonlambda_function ());
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
non-terminal, but part of a function declarator, which looks like
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 42024755e4f..3c0bd7e751c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3562,9 +3562,11 @@ finish_id_expression (tree id_expression,
? CP_ID_KIND_UNQUALIFIED_DEPENDENT
: CP_ID_KIND_UNQUALIFIED)));
 
-  /* If the name was dependent on a template parameter, we will
-resolve the name at instantiation time.  */
-  if (dependent_p)
+  /* If the name was dependent on a template parameter and we're not in a
+default capturing generic lambda within a template, we will resolve the
+name at instantiation time.  */
+  if (dependent_p
+ && !parsing_default_capturing_generic_lambda_in_template ())
{
  if (DECL_P (decl)
  && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl)))
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr64382.C 
b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
new file mode 100644
index 000..8f2e931e048
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
@@ -0,0 +1,23 @@
+// PR c++/64382
+// { dg-do compile { target c++14 } }
+
+template
+struct my_queue
+{
+  void push(T)
+  {
+  }
+  void ice()
+  {
+auto L = [=](auto &&v) {
+  push(v);
+};
+trav(L);
+  }
+  template
+  void trav(F &&f)
+  {
+f(T());
+  }
+};
+template struct my_queue;
-- 
2.11.0



  1   2   >