[C++ Patch] PR 64418

2014-12-27 Thread Momchil Velikov

Hello,

This patch fixes an issue with C++11 where user-defined conversion is 
not properly suppressed in certain cases of list-initialisation.


Consider the example:
--- 8< --
struct C {
  C(const C &);
};

struct X {
  operator C() const;
};

C a{X()};

--- 8< --

This program is successfully compiled. However, I believe this is an
erroneous behaviour.

The variable "a" is initialised by direct list-initialization
according to 8.5.4. [dcl.init.list] #3 and 13.3.1.7 [over.match.list].
As the class C does not have an initializer-list ctor, all the
constructors of C are tried with the elements of the initializer list
as arguments.

GCC tries and in fact finds a user-defined conversion sequence from X
to the first parameter of the C's copy-ctor.

However, according to 13.3.3.1 [over.best.ics] #4,

"[...] when considering the argument of a constructor [...] that is a
candidate by [...] by 13.3.1.7 [...] or when the initializer list has
exactly one element and a conversion to some class X or reference to
(possibly cv-qualified) X is considered for the first parameter of a
constructor of X [...] only standard conversion sequences and ellipsis
conversion sequences are considered.

Bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51553 is related to 
this one.


Bootstrapped and regtested on:

Target: x86_64-unknown-linux-gnu
Configured with: /home/chill/src/gcc-list-conv/configure 
--prefix=/home/chill/opt/gcc-list-conv --enable-languages=c,c++ 
--disable-multilib

Thread model: posix
gcc version 5.0.0 20141225 (experimental) [chill/list-conv revision 
b97cebe:8ccc35f:77c6247fdf2b97e796de45e5a2279b3a44b2f998] (GCC)


without regressions, except the testcase initlist64.C, which, I believe 
is flawed and was fixed.





/cp
2014-12-27  Momchil Velikov  

	PR c++/64418
	* call.c (add_function_candidate): Do not allow user-defined
	conversions during list-initialisation, when the constructor is
	called with a single argument that takes a reference to the
	constructor's class.

/testsuite
2014-12-27  Momchil Velikov  

	PR c++/64418
	* g++.dg/cpp0x/initlist64.C: Fix testcase.
	* g++.dg/cpp0x/initlist91.C: New.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 86c78ab..1e36dd2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2078,11 +2078,10 @@ add_function_candidate (struct z_candidate **candidates,
 	{
 	  if (!(flags & LOOKUP_ONLYCONVERTING))
 		lflags |= LOOKUP_COPY_PARM;
-	  /* We allow user-defined conversions within init-lists, but
-		 don't list-initialize the copy parm, as that would mean
-		 using two levels of braces for the same type.  */
-	  if ((flags & LOOKUP_LIST_INIT_CTOR)
-		  && BRACE_ENCLOSED_INITIALIZER_P (arg))
+
+	  /* According to [over.best.ics] #4, suppress user-defined
+		 conversion in the context of list-initialisation.  */
+	  if ((flags & LOOKUP_LIST_INIT_CTOR))
 		lflags |= LOOKUP_NO_CONVERSION;
 	}
 	  else
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist64.C b/gcc/testsuite/g++.dg/cpp0x/initlist64.C
index 78e5308..11e6bd9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist64.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist64.C
@@ -16,14 +16,14 @@ struct Z
   explicit operator X() const;
 };
 
-X a = { Y() };
+X a = { Y() };	// { dg-error "" }
 X aa = Y();
 
-X b{ Y() };
+X b{ Y() };	// { dg-error "" }
 X bb(Y());
 
 X c = { Z() };  // { dg-error "" }
 X cc = Z();	// { dg-error "" }
 
-X d{ Z() };
+X d{ Z() };	// { dg-error "" }
 X dd( Z() );
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist91.C b/gcc/testsuite/g++.dg/cpp0x/initlist91.C
new file mode 100644
index 000..9debb79
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist91.C
@@ -0,0 +1,25 @@
+// PR c++/51553
+// { dg-do compile { target c++11 } }
+
+struct C {
+  C(const C &);
+  C(const C &, int);
+  C(int, const C &);
+};
+
+struct X {
+  operator C() const;
+};
+
+X x;
+
+C a{x};		// { dg-error "" }
+C b{x, 1};
+C c{1, x};
+C d(x);
+C e(x, 1);
+C f(1, x);
+C g = x;
+C h = {x};	// { dg-error "" }
+C i = {x, 1};
+C j = {1, x};



Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL

2014-12-27 Thread Momchil Velikov

Ping


On  5.05.2014 13:06, Momchil Velikov wrote:

Hello,

A friend function, defined in a class and not declared outside should
be hidden from ordinary name lookup and only found by argument-dependent
lookup, like:

struct S
{
friend void f() {}
friend void g(const S &) {}
};

int
main()
{
f(); // error
g(S()); // correct, found by ADL
}

GCC correctly handles this case, but fails for function templates like:

struct S
{
template friend void f(T) {}
};

int
main()
{
f(1); // should be an error, GCC succeeds
f(S()); // correct, found by ADL
}



Bootstrapped and regtested again on top of:
Target: x86_64-unknown-linux-gnu
Configured with: /home/chill/src/gcc-friend-define/configure 
--prefix=/home/chill/opt/gcc-friend-define --enable-languages=c,c++ 
--disable-multilib

Thread model: posix
gcc version 5.0.0 20141227 (experimental) (GCC)



diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b982451..5059e14 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -927,6 +927,29 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
   if (DECL_DECLARES_FUNCTION_P (t))
 	check_default_args (t);
 
+  if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
+{
+	  if (is_friend)
+	{
+	  if (t == x && !flag_friend_injection)
+		{
+		  /* This is a new friend declaration of a function or
+		 a function template, so hide it from ordinary
+		 function lookup.  */
+		  DECL_ANTICIPATED (t) = 1;
+		  DECL_HIDDEN_FRIEND_P (t) = 1;
+		}
+	}
+	  else if (t != x && t != error_mark_node)
+	{
+	  /* This is a non-friend re-declaration of a possibly
+		 hidden function or a function template, so don't hide
+		 it. */
+	  DECL_ANTICIPATED (t) = 0;
+	  DECL_HIDDEN_FRIEND_P (t) = 0;
+	}
+	}
+
   if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
 	return t;
 
@@ -987,16 +1010,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	}
 	}
 
-  if (TREE_CODE (x) == FUNCTION_DECL
-	  && is_friend
-	  && !flag_friend_injection)
-	{
-	  /* This is a new declaration of a friend function, so hide
-	 it from ordinary function lookup.  */
-	  DECL_ANTICIPATED (x) = 1;
-	  DECL_HIDDEN_FRIEND_P (x) = 1;
-	}
-
   /* This name is new in its binding level.
 	 Install the new declaration and return it.  */
   if (namespace_bindings_p ())
diff --git a/gcc/testsuite/g++.dg/template/friend57.C b/gcc/testsuite/g++.dg/template/friend57.C
new file mode 100644
index 000..7077d5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend57.C
@@ -0,0 +1,21 @@
+// PR c++/59366
+// { dg-do compile }
+template void f(T);
+
+struct S
+{
+  template friend void f(T) {}
+  template friend void g(T) {}
+  template friend void h(T) {}
+};
+
+template void h(T);
+
+int
+main ()
+{
+  f(1);
+  g(1); // { dg-error "'g' was not declared in this scope" }
+  g(S());
+  h(1);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
index 3feeb68..edb9d62 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
@@ -14,5 +14,5 @@ class C
 
 int main()
 {
-  f(7);
+  f(C());
 }

/cp
2014-12-27  Momchil Velikov  

PR c++/59366
* name-lookup.c (pushdecl_maybe_friend_1): Hide friend functions
and function templates, declared only in the class.

/testsuite
2014-12-27  Momchil Velikov  

PR c++/59366
* g++.dg/template/friend57.C: New
* g++.old-deja/g++.pt/friend5.C (main): Fix testcase. The friend
functions `f` should be found only by ADL.



Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL

2014-12-28 Thread Momchil Velikov

On 28.12.2014 01:36, Jason Merrill wrote:

On 12/27/2014 04:38 PM, Momchil Velikov wrote:

+  else if (t != x && t != error_mark_node)
+{
+  /* This is a non-friend re-declaration of a possibly
+ hidden function or a function template, so don't hide
+ it. */
+  DECL_ANTICIPATED (t) = 0;
+  DECL_HIDDEN_FRIEND_P (t) = 0;
+}


Doesn't duplicate_decls handle clearing these?


It does, but only for functions (in somewhat obscure way, by not
setting the flags in DECL_LANG_SPECIFIC(newdecl)).

It does not for function templates. Indeed, it makes sense to do this
in duplicate_decls(). How about like in the attached patch?

(bootstrap and testing in progress)


diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bbaf3d6..efd472a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1865,6 +1865,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   DECL_ATTRIBUTES (newdecl)
 = (*targetm.merge_decl_attributes) (olddecl, newdecl);
 
+  if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl))
+{
+  olddecl_friend = DECL_FRIEND_P (olddecl);
+  hidden_friend = (DECL_ANTICIPATED (olddecl)
+		   && DECL_HIDDEN_FRIEND_P (olddecl)
+		   && newdecl_is_friend);
+  if (!hidden_friend)
+	{
+	  DECL_ANTICIPATED (olddecl) = 0;
+	  DECL_HIDDEN_FRIEND_P (olddecl) = 0;
+	}
+}
+
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
 {
   tree old_result;
@@ -2147,10 +2160,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   if (DECL_DECLARES_FUNCTION_P (newdecl))
 	{
 	  DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
-	  olddecl_friend = DECL_FRIEND_P (olddecl);
-	  hidden_friend = (DECL_ANTICIPATED (olddecl)
-			   && DECL_HIDDEN_FRIEND_P (olddecl)
-			   && newdecl_is_friend);
 	  DECL_BEFRIENDING_CLASSES (newdecl)
 	= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
 		   DECL_BEFRIENDING_CLASSES (olddecl));
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b982451..69a0da6 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -925,7 +925,18 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	}
 
   if (DECL_DECLARES_FUNCTION_P (t))
-	check_default_args (t);
+	{
+	  check_default_args (t);
+
+	  if (is_friend && t == x && !flag_friend_injection)
+	{
+	  /* This is a new friend declaration of a function or a
+		 function template, so hide it from ordinary function
+		 lookup.  */
+	  DECL_ANTICIPATED (t) = 1;
+	  DECL_HIDDEN_FRIEND_P (t) = 1;
+	}
+	}
 
   if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
 	return t;
@@ -987,16 +998,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	}
 	}
 
-  if (TREE_CODE (x) == FUNCTION_DECL
-	  && is_friend
-	  && !flag_friend_injection)
-	{
-	  /* This is a new declaration of a friend function, so hide
-	 it from ordinary function lookup.  */
-	  DECL_ANTICIPATED (x) = 1;
-	  DECL_HIDDEN_FRIEND_P (x) = 1;
-	}
-
   /* This name is new in its binding level.
 	 Install the new declaration and return it.  */
   if (namespace_bindings_p ())



Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL

2014-12-30 Thread Momchil Velikov

On 30.12.2014 17:54, Jason Merrill wrote:

On 12/28/2014 01:45 PM, Momchil Velikov wrote:

+  if (!hidden_friend)
+{
+  DECL_ANTICIPATED (olddecl) = 0;
+  DECL_HIDDEN_FRIEND_P (olddecl) = 0;
+}


Why not add this...


@@ -2147,10 +2160,6 @@ duplicate_decls (tree newdecl, tree olddecl,
bool newdecl_is_friend)
if (DECL_DECLARES_FUNCTION_P (newdecl))
  {
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
-  olddecl_friend = DECL_FRIEND_P (olddecl);
-  hidden_friend = (DECL_ANTICIPATED (olddecl)
-   && DECL_HIDDEN_FRIEND_P (olddecl)
-   && newdecl_is_friend);


...here?  I don't see a reason why a function template wouldn't hit this
block.


A function template enters the body of the if statement at line 1881,

  if (TREE_CODE (newdecl) == TEMPLATE_DECL)

and exits the function at line 1951 with

  return olddecl;





Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL

2015-01-05 Thread Momchil Velikov

On  5.01.2015 15:55, Jason Merrill wrote:

On 12/30/2014 11:24 AM, Momchil Velikov wrote:

A function template enters the body of the if statement at line 1881,

   if (TREE_CODE (newdecl) == TEMPLATE_DECL)

and exits the function at line 1951 with

   return olddecl;


Ah, yes.  The patch is OK, then, but still needs ChangeLog and testcase.

Jason



Bootstrapped/tested again with:

Target: x86_64-unknown-linux-gnu
Configured with: /home/chill/src/gcc-master/configure 
--prefix=/home/chill/opt/gcc-master --enable-languages=c,c++

Thread model: posix
gcc version 5.0.0 20150105 (experimental) [master revision 
113a5d9:4b40b3c:c1fd77316d75af1122efb4b8b2988a86599558dc] (GCC)





diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2fea106..82401ab 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1865,6 +1865,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   DECL_ATTRIBUTES (newdecl)
 = (*targetm.merge_decl_attributes) (olddecl, newdecl);
 
+  if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl))
+{
+  olddecl_friend = DECL_FRIEND_P (olddecl);
+  hidden_friend = (DECL_ANTICIPATED (olddecl)
+		   && DECL_HIDDEN_FRIEND_P (olddecl)
+		   && newdecl_is_friend);
+  if (!hidden_friend)
+	{
+	  DECL_ANTICIPATED (olddecl) = 0;
+	  DECL_HIDDEN_FRIEND_P (olddecl) = 0;
+	}
+}
+
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
 {
   tree old_result;
@@ -2147,10 +2160,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   if (DECL_DECLARES_FUNCTION_P (newdecl))
 	{
 	  DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
-	  olddecl_friend = DECL_FRIEND_P (olddecl);
-	  hidden_friend = (DECL_ANTICIPATED (olddecl)
-			   && DECL_HIDDEN_FRIEND_P (olddecl)
-			   && newdecl_is_friend);
 	  DECL_BEFRIENDING_CLASSES (newdecl)
 	= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
 		   DECL_BEFRIENDING_CLASSES (olddecl));
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2dfb00d..d92a2cd 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -925,7 +925,18 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	}
 
   if (DECL_DECLARES_FUNCTION_P (t))
-	check_default_args (t);
+	{
+	  check_default_args (t);
+
+	  if (is_friend && t == x && !flag_friend_injection)
+	{
+	  /* This is a new friend declaration of a function or a
+		 function template, so hide it from ordinary function
+		 lookup.  */
+	  DECL_ANTICIPATED (t) = 1;
+	  DECL_HIDDEN_FRIEND_P (t) = 1;
+	}
+	}
 
   if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
 	return t;
@@ -987,16 +998,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	}
 	}
 
-  if (TREE_CODE (x) == FUNCTION_DECL
-	  && is_friend
-	  && !flag_friend_injection)
-	{
-	  /* This is a new declaration of a friend function, so hide
-	 it from ordinary function lookup.  */
-	  DECL_ANTICIPATED (x) = 1;
-	  DECL_HIDDEN_FRIEND_P (x) = 1;
-	}
-
   /* This name is new in its binding level.
 	 Install the new declaration and return it.  */
   if (namespace_bindings_p ())
diff --git a/gcc/testsuite/g++.dg/template/friend57.C b/gcc/testsuite/g++.dg/template/friend57.C
new file mode 100644
index 000..7077d5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend57.C
@@ -0,0 +1,21 @@
+// PR c++/59366
+// { dg-do compile }
+template void f(T);
+
+struct S
+{
+  template friend void f(T) {}
+  template friend void g(T) {}
+  template friend void h(T) {}
+};
+
+template void h(T);
+
+int
+main ()
+{
+  f(1);
+  g(1); // { dg-error "'g' was not declared in this scope" }
+  g(S());
+  h(1);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
index 3feeb68..edb9d62 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
@@ -14,5 +14,5 @@ class C
 
 int main()
 {
-  f(7);
+  f(C());
 }


/cp
2015-01-05  Momchil Velikov  

PR c++/59366
* name-lookup.c (pushdecl_maybe_friend_1): Hide friend functions
and function templates, declared only in the class.
* decl.c (duplicate_decls): Reveal hidden friend functions or
    function templates, if they are redeclared outside the class.

/testsuite
2015-01-05  Momchil Velikov  

PR c++/59366
* g++.dg/template/friend57.C: New
* g++.old-deja/g++.pt/friend5.C (main): Fix testcase. The friend
function `f` should be found only by ADL.


[PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier

2014-04-29 Thread Momchil Velikov
Hello,

gcc version 4.10.0 20140428 (experimental) (GCC)

Compiling (with c++ -c -std=c++11 b.cc) the following program

enum struct A
{
  n = 3
};

int
foo()
{
  int A;
  return A::n;
}

results in the error:

b.cc: In function 'int foo()':
b.cc:10:10: error: 'A' is not a class, namespace, or enumeration
   return A::n;
  ^
According to the C++11 Standard, [basic.lookup.qual] #1

"If a :: scope resolution operator in a nested-name-specifier is not
preceded by a decltype-specifier, lookup of the name preceding that ::
considers only namespaces, types, and templates whose specializations
are types."

GCC ought not to resolve "A" to the local variable, but to the
enumeration type. This is very similar to the example in the standard

struct A
{
  static int n;
};

int
foo()
{
  int A;
  return A::n;
}

which is compiled correctly by GCC, though.


Please, review this proposed fix. Bootstrapped/regtested for C/C++ on
x86_64-unknown-linux-gnu.

~chill
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a5f3829..36c07a6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2014-04-29  Momchil Velikov  
+
+   PR c++/60994
+   * parser.c (cp_parser_class_name): Allow enumeral type as a
+   nested-name-specifier
+
 2014-04-28  Paolo Carlini  
 
PR c++/59120
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 962cace..460535e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19218,7 +19218,8 @@ cp_parser_class_name (cp_parser *parser,
 }
   else if (TREE_CODE (decl) != TYPE_DECL
   || TREE_TYPE (decl) == error_mark_node
-  || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
+  || !(MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
+|| TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
   /* In Objective-C 2.0, a classname followed by '.' starts a
  dot-syntax expression, and it's not a type-name.  */
   || (c_dialect_objc ()
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b2f07c6..0d9468e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-04-29  Momchil Velikov  
+
+   PR c++/60994
+   * g++.dg/cpp0x/scoped_enum3.C: New testcase.
+
 2014-04-28  Martin Jambor  
 
 * gcc.dg/tree-ssa/sra-14.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C 
b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
new file mode 100644
index 000..ba527cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+enum struct A
+{
+  n = 3
+};
+
+int
+foo()
+{
+  int A;
+  return A::n; // { dg-error "cannot convert 'A' to 'int' in return" }
+}


Re: [PATCH] Fix PR c++/60463, PR c++/60755 Incorrect discard of const qualifier

2014-05-01 Thread Momchil Velikov

On 14.04.2014 23:53, Momchil Velikov wrote:

Ping


Hello,

During overload resolution of function calls in the body of a lambda it
is possible to use an implicit/dummy 'this', which differs in const-ness
from the actual 'this' that would be captured, resulting in choosing a
non-const member function even when the captured 'this' is const. This
patch makes sure that the captured 'this' is the same as the one used in
the overload resolution.


Bootstrapped and regtested again with xgcc (GCC) 4.10.0 20140430 (experimental)
[master revision b069c2a:edc7cc5:af379dd3ed2b932a506437bca77ea4f4c320dbb4]
with no regressions on x86_64-unknown-linux-gnu.

~chill

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b201825..bb89e8f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2014-04-30  Momchil Velikov  
+
+	PR c++/60463
+	PR c++/60755
+	* lambda.c (lambda_expr_this_capture): Add new parameter
+	add_capture_p controlling whether the functions will try to
+	capture 'this' via the default capture.
+	(maybe_resolve_dummy): Likewise.
+	* cp-tree.h: Adjust prototypes.
+	* call.c, semantics.c: Change callers of these functions.
+	* call.c (build_new_method_call_1): Use the actual 'this' that
+	would be potentially captured for the overload resolution, instead
+	of the dummy object.
+
 2014-04-29  Jason Merrill  
 
 	DR 1351
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8c55c32..a3aaebb 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7727,7 +7727,11 @@ build_new_method_call_1 (tree instance, tree fns, vec **args,
   if (DECL_DESTRUCTOR_P (fn))
 name = complete_dtor_identifier;
 
-  first_mem_arg = instance;
+  /* For the overload resolution we need to find the actual `this`
+ that would be captured if the call turns out to be to a
+ non-static member function.  Do not actually capture it at this
+ point.  */
+  first_mem_arg = maybe_resolve_dummy (instance, false);
 
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
@@ -7865,7 +7869,7 @@ build_new_method_call_1 (tree instance, tree fns, vec **args,
 	  && !DECL_CONSTRUCTOR_P (fn)
 	  && is_dummy_object (instance))
 	{
-	  instance = maybe_resolve_dummy (instance);
+	  instance = maybe_resolve_dummy (instance, true);
 	  if (instance == error_mark_node)
 		call = error_mark_node;
 	  else if (!is_dummy_object (instance))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 55ecc4e..4a45cc1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5889,8 +5889,8 @@ extern void insert_pending_capture_proxies	(void);
 extern bool is_capture_proxy			(tree);
 extern bool is_normal_capture_proxy (tree);
 extern void register_capture_members		(tree);
-extern tree lambda_expr_this_capture(tree);
-extern tree maybe_resolve_dummy			(tree);
+extern tree lambda_expr_this_capture(tree, bool);
+extern tree maybe_resolve_dummy			(tree, bool);
 extern tree nonlambda_method_basetype		(void);
 extern void maybe_add_lambda_conv_op(tree);
 extern bool is_lambda_ignored_entity(tree);
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 0b8b46a..3de1f15 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -620,11 +620,12 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
   return var;
 }
 
-/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an
-   INDIRECT_REF, possibly adding it through default capturing.  */
+/* Return the capture pertaining to a use of 'this' in LAMBDA, in the
+   form of an INDIRECT_REF, possibly adding it through default
+   capturing, if ADD_CAPTURE_P is false.  */
 
 tree
-lambda_expr_this_capture (tree lambda)
+lambda_expr_this_capture (tree lambda, bool add_capture_p)
 {
   tree result;
 
@@ -644,7 +645,8 @@ lambda_expr_this_capture (tree lambda)
 
   /* Try to default capture 'this' if we can.  */
   if (!this_capture
-  && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
+  && (!add_capture_p
+  || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE))
 {
   tree lambda_stack = NULL_TREE;
   tree init = NULL_TREE;
@@ -704,9 +706,14 @@ lambda_expr_this_capture (tree lambda)
 	}
 
   if (init)
-	this_capture = add_default_capture (lambda_stack,
-	/*id=*/this_identifier,
-	init);
+{
+  if (add_capture_p)
+	this_capture = add_default_capture (lambda_stack,
+	/*id=*/this_identifier,
+	init);
+  else
+	this_capture = init;
+}
 }
 
   if (!this_capture)
@@ -738,7 +745,7 @@ lambda_expr_this_capture (tree lambda)
'this' capture.  */
 
 tree
-maybe_resolve_dummy (tree object)
+maybe_resolve_dummy (tree object, bool add_capture_p)
 {
   if (!is_dummy_object (object))
 return object;
@@

[PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL

2014-05-05 Thread Momchil Velikov

Hello,

A friend function, defined in a class and not declared outside should
be hidden from ordinary name lookup and only found by argument-dependent
lookup, like:

struct S
{
   friend void f() {}
   friend void g(const S &) {}
};

int
main()
{
   f(); // error
   g(S()); // correct, found by ADL
}

GCC correctly handles this case, but fails for function templates like:

struct S
{
   template friend void f(T) {}
};

int
main()
{
   f(1); // should be an error, GCC succeeds
   f(S()); // correct, found by ADL
}

~chill

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 374cd0f..b374181 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2014-05-05  Momchil Velikov  
+
+	PR c++/59366
+	* name-lookup.c (pushdecl_maybe_friend_1): Hide friend functions
+	and function templates, declared only in the class.
+
 2014-05-03  Paolo Carlini  
 
 	PR c++/58582
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index d900560..8441047 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -924,6 +924,29 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
   if (DECL_DECLARES_FUNCTION_P (t))
 	check_default_args (t);
 
+  if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
+{
+	  if (is_friend)
+	{
+	  if (t == x && !flag_friend_injection)
+		{
+		  /* This is a new friend declaration of a function or
+		 a function template, so hide it from ordinary
+		 function lookup.  */
+		  DECL_ANTICIPATED (t) = 1;
+		  DECL_HIDDEN_FRIEND_P (t) = 1;
+		}
+	}
+	  else if (t != x && t != error_mark_node)
+	{
+	  /* This is a non-friend re-declaration of a possibly
+		 hidden function or a function template, so don't hide
+		 it. */
+	  DECL_ANTICIPATED (t) = 0;
+	  DECL_HIDDEN_FRIEND_P (t) = 0;
+	}
+	}
+
   if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
 	return t;
 
@@ -983,16 +1006,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 	}
 	}
 
-  if (TREE_CODE (x) == FUNCTION_DECL
-	  && is_friend
-	  && !flag_friend_injection)
-	{
-	  /* This is a new declaration of a friend function, so hide
-	 it from ordinary function lookup.  */
-	  DECL_ANTICIPATED (x) = 1;
-	  DECL_HIDDEN_FRIEND_P (x) = 1;
-	}
-
   /* This name is new in its binding level.
 	 Install the new declaration and return it.  */
   if (namespace_bindings_p ())
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3b613d9..dbd63bd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2014-05-05  Momchil Velikov  
+
+	PR c++/59366
+	* g++.dg/template/friend56.C: New
+	* g++.old-deja/g++.pt/friend5.C (main): Fix testcase. The friend
+	functions `f` should be found only by ADL.
+
 2014-05-03  Paolo Carlini  
 
 	PR c++/58582
diff --git a/gcc/testsuite/g++.dg/template/friend56.C b/gcc/testsuite/g++.dg/template/friend56.C
new file mode 100644
index 000..7077d5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend56.C
@@ -0,0 +1,21 @@
+// PR c++/59366
+// { dg-do compile }
+template void f(T);
+
+struct S
+{
+  template friend void f(T) {}
+  template friend void g(T) {}
+  template friend void h(T) {}
+};
+
+template void h(T);
+
+int
+main ()
+{
+  f(1);
+  g(1); // { dg-error "'g' was not declared in this scope" }
+  g(S());
+  h(1);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
index 3feeb68..edb9d62 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
@@ -14,5 +14,5 @@ class C
 
 int main()
 {
-  f(7);
+  f(C());
 }



Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL

2014-05-05 Thread Momchil Velikov

Bootstrapped/regtested on x86_64-linux-gnu.

One test, gcc/testsuite/g++.old-deja/g++.pt/friend5.C, breaks, as it should,
and was fixed.

~chill



Re: [PATCH] Fix PR c++/60994 gcc does not recognize hidden/shadowed enumeration as valid nested-name-specifier

2014-05-08 Thread Momchil Velikov
Ping.

previous post: http://gcc.gnu.org/ml/gcc-patches/2014-04/msg01938.html

Again bootstrapped/regtested/diffed against
xg++ (GCC) 4.10.0 20140508 (experimental) [master revision
ed50168:49aa3a5:e79f58c7b12f37014efb7425399c93814cddb4c4]

On 29.04.2014 12:58, Momchil Velikov wrote:
> Hello,
>
> gcc version 4.10.0 20140428 (experimental) (GCC)
>
> Compiling (with c++ -c -std=c++11 b.cc) the following program
>
> enum struct A
> {
>n = 3
> };
>
> int
> foo()
> {
>int A;
>return A::n;
> }
>
> results in the error:
>
> b.cc: In function 'int foo()':
> b.cc:10:10: error: 'A' is not a class, namespace, or enumeration
> return A::n;
>^
> According to the C++11 Standard, [basic.lookup.qual] #1
>
> "If a :: scope resolution operator in a nested-name-specifier is not
> preceded by a decltype-specifier, lookup of the name preceding that ::
> considers only namespaces, types, and templates whose specializations
> are types."
>
> GCC ought not to resolve "A" to the local variable, but to the
> enumeration type. This is very similar to the example in the standard
>
> struct A
> {
>static int n;
> };
>
> int
> foo()
> {
>int A;
>return A::n;
> }
>
> which is compiled correctly by GCC, though.
>
>
> Please, review this proposed fix. Bootstrapped/regtested for C/C++ on
> x86_64-unknown-linux-gnu.
>
> ~chill
>
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3d400bb..cd86f95 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2014-05-08  Momchil Velikov  
+
+	PR c++/60994
+	* parser.c (cp_parser_class_name): Allow enumeral type as a
+	nested-name-specifier
+
 2014-05-08  Paolo Carlini  
 
 	PR c++/13981
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5542dcd..e7ff57f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19220,7 +19220,8 @@ cp_parser_class_name (cp_parser *parser,
 }
   else if (TREE_CODE (decl) != TYPE_DECL
 	   || TREE_TYPE (decl) == error_mark_node
-	   || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
+	   || !(MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
+|| TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
 	   /* In Objective-C 2.0, a classname followed by '.' starts a
 	  dot-syntax expression, and it's not a type-name.  */
 	   || (c_dialect_objc ()
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aa92e3b..60cbe3d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-05-08  Momchil Velikov  
+
+	PR c++/60994
+	* g++.dg/cpp0x/scoped_enum3.C: New testcase.
+
 2014-05-08  Joseph Myers  
 
 	* gcc.target/i386/avx256-unaligned-load-2.c,
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
new file mode 100644
index 000..ba527cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum3.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+enum struct A
+{
+  n = 3
+};
+
+int
+foo()
+{
+  int A;
+  return A::n; // { dg-error "cannot convert 'A' to 'int' in return" }
+}


Re: [PATCH] Fix PR c++/60463, PR c++/60755 Incorrect discard of const qualifier

2014-05-09 Thread Momchil Velikov

Ping


On 14.04.2014 23:53, Momchil Velikov wrote:
Hello,

During overload resolution of function calls in the body of a lambda it
is possible to use an implicit/dummy 'this', which differs in const-ness
from the actual 'this' that would be captured, resulting in choosing a
non-const member function even when the captured 'this' is const. This
patch makes sure that the captured 'this' is the same as the one used in
the overload resolution.


Bootstrapped/regtested for C/C++ on x86_64-unknown-linux-gnu against
xg++ (GCC) 4.10.0 20140508 (experimental) [master revision 
ed50168:49aa3a5:e79f58c7b12f37014efb7425399c93814cddb4c4]


~chill

2014-05-08  Momchil Velikov  

PR c++/60463
PR c++/60755
* lambda.c (lambda_expr_this_capture): Add new parameter
add_capture_p controlling whether the functions will try to
capture 'this' via the default capture.
(maybe_resolve_dummy): Likewise.
* cp-tree.h: Adjust prototypes.
* call.c, semantics.c: Change callers of these functions.
* call.c (build_new_method_call_1): Use the actual 'this' that
would be potentially captured for the overload resolution, instead
of the dummy object.

2014-05-08  Momchil Velikov  

PR c++/60463
PR c++/60755
* g++.dg/cpp0x/lambda/lambda-const-this.C: New testcase.




diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 857df57..bfedfef 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7726,7 +7726,11 @@ build_new_method_call_1 (tree instance, tree fns, vec **args,
   if (DECL_DESTRUCTOR_P (fn))
 name = complete_dtor_identifier;
 
-  first_mem_arg = instance;
+  /* For the overload resolution we need to find the actual `this`
+ that would be captured if the call turns out to be to a
+ non-static member function.  Do not actually capture it at this
+ point.  */
+  first_mem_arg = maybe_resolve_dummy (instance, false);
 
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
@@ -7864,7 +7868,7 @@ build_new_method_call_1 (tree instance, tree fns, vec **args,
 	  && !DECL_CONSTRUCTOR_P (fn)
 	  && is_dummy_object (instance))
 	{
-	  instance = maybe_resolve_dummy (instance);
+	  instance = maybe_resolve_dummy (instance, true);
 	  if (instance == error_mark_node)
 		call = error_mark_node;
 	  else if (!is_dummy_object (instance))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 34d3d20..ed8d099 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5890,8 +5890,8 @@ extern void insert_pending_capture_proxies	(void);
 extern bool is_capture_proxy			(tree);
 extern bool is_normal_capture_proxy (tree);
 extern void register_capture_members		(tree);
-extern tree lambda_expr_this_capture(tree);
-extern tree maybe_resolve_dummy			(tree);
+extern tree lambda_expr_this_capture(tree, bool);
+extern tree maybe_resolve_dummy			(tree, bool);
 extern tree nonlambda_method_basetype		(void);
 extern void maybe_add_lambda_conv_op(tree);
 extern bool is_lambda_ignored_entity(tree);
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 5ba6f14..3ce9ebb 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -624,11 +624,12 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
   return var;
 }
 
-/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an
-   INDIRECT_REF, possibly adding it through default capturing.  */
+/* Return the capture pertaining to a use of 'this' in LAMBDA, in the
+   form of an INDIRECT_REF, possibly adding it through default
+   capturing, if ADD_CAPTURE_P is false.  */
 
 tree
-lambda_expr_this_capture (tree lambda)
+lambda_expr_this_capture (tree lambda, bool add_capture_p)
 {
   tree result;
 
@@ -648,7 +649,8 @@ lambda_expr_this_capture (tree lambda)
 
   /* Try to default capture 'this' if we can.  */
   if (!this_capture
-  && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
+  && (!add_capture_p
+  || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE))
 {
   tree lambda_stack = NULL_TREE;
   tree init = NULL_TREE;
@@ -708,9 +710,14 @@ lambda_expr_this_capture (tree lambda)
 	}
 
   if (init)
-	this_capture = add_default_capture (lambda_stack,
-	/*id=*/this_identifier,
-	init);
+{
+  if (add_capture_p)
+	this_capture = add_default_capture (lambda_stack,
+	/*id=*/this_identifier,
+	init);
+  else
+	this_capture = init;
+}
 }
 
   if (!this_capture)
@@ -742,7 +749,7 @@ lambda_expr_this_capture (tree lambda)
'this' capture.  */
 
 tree
-maybe_resolve_dummy (tree object)
+maybe_resolve_dummy (tree object, bool add_capture_p)
 {
   if (!is_dummy_object (object))
 

[PATCH] Fix PR c++/60463, PE c++/60755 Incorrect discard of const qualifier

2014-04-14 Thread Momchil Velikov

Hello,

During overload resolution of function calls in the body of a lambda it
is possible to use an implicit/dummy 'this', which differs in const-ness
from the actual 'this' that would be captured, resulting in choosing a
non-const member function even when the captured 'this' is const. This
patch makes sure that the captured 'this' is the same as the one used in
the overload resolution.

Bootstrapped and tested with no regressions relative to version
4.10.0 20140414 (experimental) [master revision
98acb41:a7ec718:cb799f0a61f3adef32474ad4e01ffb4b8b45778d] on
x86_64-unknown-linux-gnu.

~chill


diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bf61ab7..7308b57 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2014-04-14  Momchil Velikov  
+
+   PR c++/60463
+   PR c++/60755
+   * lambda.c (lambda_expr_this_capture): Add new parameter
+   add_capture_p controlling whether the functions will try to
+   capture 'this' via the default capture.
+   (maybe_resolve_dummy): Likewise.
+   * cp-tree.h: Adjust prototypes.
+   * call.c, semantics.c: Change callers of these functions.
+   * call.c (build_new_method_call_1): Use the actual 'this' that
+   would be potentially captured for the overload resolution, instead
+   of the dummy object.
+
 2014-04-11  Jason Merrill  
 
 	* parser.h (struct cp_token): Rename ambiguous_p to error_reported.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7c0dcc2..df22df4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7720,7 +7720,11 @@ build_new_method_call_1 (tree instance, tree fns, vec **args,
   if (DECL_DESTRUCTOR_P (fn))
 name = complete_dtor_identifier;
 
-  first_mem_arg = instance;

+  /* For the overload resolution we need to find the actual `this`
+ that would be captured if the call turns out to be to a
+ non-static member function.  Do not actually capture it at this
+ point.  */
+  first_mem_arg = maybe_resolve_dummy (instance, false);
 
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */

   p = conversion_obstack_alloc (0);
@@ -7858,7 +7862,7 @@ build_new_method_call_1 (tree instance, tree fns, vec **args,
  if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
  && is_dummy_object (instance))
{
- instance = maybe_resolve_dummy (instance);
+ instance = maybe_resolve_dummy (instance, true);
  if (instance == error_mark_node)
call = error_mark_node;
  else if (!is_dummy_object (instance))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bafc32d..e020251 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5881,8 +5881,8 @@ extern void insert_pending_capture_proxies(void);
 extern bool is_capture_proxy   (tree);
 extern bool is_normal_capture_proxy (tree);
 extern void register_capture_members   (tree);
-extern tree lambda_expr_this_capture(tree);
-extern tree maybe_resolve_dummy(tree);
+extern tree lambda_expr_this_capture(tree, bool);
+extern tree maybe_resolve_dummy(tree, bool);
 extern tree nonlambda_method_basetype  (void);
 extern void maybe_add_lambda_conv_op(tree);
 extern bool is_lambda_ignored_entity(tree);
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 0b8b46a..3de1f15 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -620,11 +620,12 @@ add_default_capture (tree lambda_stack, tree id, tree 
initializer)
   return var;
 }
 
-/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an

-   INDIRECT_REF, possibly adding it through default capturing.  */
+/* Return the capture pertaining to a use of 'this' in LAMBDA, in the
+   form of an INDIRECT_REF, possibly adding it through default
+   capturing, if ADD_CAPTURE_P is false.  */
 
 tree

-lambda_expr_this_capture (tree lambda)
+lambda_expr_this_capture (tree lambda, bool add_capture_p)
 {
   tree result;
 
@@ -644,7 +645,8 @@ lambda_expr_this_capture (tree lambda)
 
   /* Try to default capture 'this' if we can.  */

   if (!this_capture
-  && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
+  && (!add_capture_p
+  || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE))
 {
   tree lambda_stack = NULL_TREE;
   tree init = NULL_TREE;
@@ -704,9 +706,14 @@ lambda_expr_this_capture (tree lambda)
}
 
   if (init)

-   this_capture = add_default_capture (lambda_stack,
-   /*id=*/this_identifier,
-   init);
+{
+  if (add_capture_p)
+   this_capture = add_default_capture (lambda_stack,
+   /*id=*/this_identifier,
+