[C++ Patch] PR 64418
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
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
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
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
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
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
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
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
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
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
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
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, +