re PR c++/64959 (SFINAE in UDLs)

PR c++/64959
	* parser.c (lookup_literal_operator): Return all candidates.
	(cp_parser_userdef_char_literal): Simplify error handling.
	(cp_parser_userdef_numeric_literal):  Pass tf_warning_or_error.
	(cp_parser_userdef_string_literal): Pass tf_warning_or_error.
	Also give higher priority to standard string UDL operator.

From-SVN: r220656
This commit is contained in:
Andrea Azzarone 2015-02-12 20:21:34 +00:00 committed by Jason Merrill
parent 864f0146f0
commit bc81eb3f77
10 changed files with 211 additions and 65 deletions

View File

@ -1,3 +1,12 @@
2015-02-12 Andrea Azzarone <azzaronea@gmail.com>
PR c++/64959
* parser.c (lookup_literal_operator): Return all candidates.
(cp_parser_userdef_char_literal): Simplify error handling.
(cp_parser_userdef_numeric_literal): Pass tf_warning_or_error.
(cp_parser_userdef_string_literal): Pass tf_warning_or_error.
Also give higher priority to standard string UDL operator.
2015-02-12 Jakub Jelinek <jakub@redhat.com>
PR debug/55541

View File

@ -3828,7 +3828,7 @@ lookup_literal_operator (tree name, vec<tree, va_gc> *args)
work in presence of default arguments on the literal
operator parameters. */
&& parmtypes == void_list_node)
return fn;
return decl;
}
}
@ -3862,12 +3862,7 @@ cp_parser_userdef_char_literal (cp_parser *parser)
}
result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
release_tree_vector (args);
if (result != error_mark_node)
return result;
error ("unable to find character literal operator %qD with %qT argument",
name, TREE_TYPE (value));
return error_mark_node;
}
/* A subroutine of cp_parser_userdef_numeric_literal to
@ -3955,13 +3950,15 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true, tf_none);
if (result != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true,
tf_warning_or_error);
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && overflow > 0)
{
warning_at (token->location, OPT_Woverflow,
"integer literal exceeds range of %qT type",
long_long_unsigned_type_node);
}
else
{
if (overflow > 0)
@ -3972,10 +3969,10 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
warning_at (token->location, OPT_Woverflow,
"floating literal truncated to zero");
}
release_tree_vector (args);
return result;
}
}
release_tree_vector (args);
/* If the numeric argument didn't work, look for a raw literal
@ -3986,13 +3983,11 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true, tf_none);
if (result != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true,
tf_warning_or_error);
release_tree_vector (args);
return result;
}
}
release_tree_vector (args);
/* If the raw literal didn't work, look for a non-type template
@ -4004,13 +3999,12 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
{
tree tmpl_args = make_char_string_pack (num_string);
decl = lookup_template_function (decl, tmpl_args);
result = finish_call_expr (decl, &args, false, true, tf_none);
if (result != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true,
tf_warning_or_error);
release_tree_vector (args);
return result;
}
}
release_tree_vector (args);
error ("unable to find numeric literal operator %qD", name);
@ -4035,6 +4029,22 @@ cp_parser_userdef_string_literal (tree literal)
tree decl, result;
vec<tree, va_gc> *args;
/* Build up a call to the user-defined operator. */
/* Lookup the name we got back from the id-expression. */
args = make_tree_vector ();
vec_safe_push (args, value);
vec_safe_push (args, build_int_cst (size_type_node, len));
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true,
tf_warning_or_error);
release_tree_vector (args);
return result;
}
release_tree_vector (args);
/* Look for a template function with typename parameter CharT
and parameter pack CharT... Call the function with
template parameter characters representing the string. */
@ -4044,32 +4054,13 @@ cp_parser_userdef_string_literal (tree literal)
{
tree tmpl_args = make_string_pack (value);
decl = lookup_template_function (decl, tmpl_args);
result = finish_call_expr (decl, &args, false, true, tf_none);
if (result != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true,
tf_warning_or_error);
release_tree_vector (args);
return result;
}
}
release_tree_vector (args);
/* Build up a call to the user-defined operator */
/* Lookup the name we got back from the id-expression. */
args = make_tree_vector ();
vec_safe_push (args, value);
vec_safe_push (args, build_int_cst (size_type_node, len));
decl = lookup_name (name);
if (!decl || decl == error_mark_node)
{
error ("unable to find string literal operator %qD", name);
release_tree_vector (args);
return error_mark_node;
}
result = finish_call_expr (decl, &args, false, true, tf_none);
release_tree_vector (args);
if (result != error_mark_node)
return result;
error ("unable to find string literal operator %qD with %qT, %qT arguments",
name, TREE_TYPE (value), size_type_node);
return error_mark_node;

View File

@ -0,0 +1,10 @@
// { dg-do compile { target c++11 } }
int operator""_t (long long unsigned); // { dg-message "note: candidate"}
namespace foo {
int operator""_t (long long unsigned); // { dg-message "note: candidate"}
}
using namespace foo;
int var = 10_t; // { dg-error "call of overloaded | is ambiguous" }

View File

@ -0,0 +1,16 @@
// { dg-do compile { target c++11 } }
int operator""_t(long long unsigned) {
return 0;
}
namespace foo {
int operator""_t(long long unsigned) {
return 0;
}
}
int main() {
using foo::operator""_t;
10_t;
}

View File

@ -17,15 +17,10 @@ int operator"" _foo(const char32_t*, std::size_t) { return 10; }
template<char...> int operator"" _foo2() { return 20; }
int operator"" _foo2(unsigned long long int) { return 21; }
namespace bar {
int operator"" _foo(unsigned long long int) { return 101; }
}
using namespace bar;
int
main()
{
assert(123_foo == 101);
assert(123_foo == 1);
assert(0.123_foo == 2);
assert('c'_foo == 3);
assert(L'c'_foo == 4);

View File

@ -0,0 +1,21 @@
// { dg-do compile { target c++11 } }
// { dg-prune-output "note:" }
template<bool, typename _Tp = void> struct enable_if { };
template<typename _Tp> struct enable_if<true, _Tp> { typedef _Tp type; };
template <char... c>
constexpr typename enable_if<sizeof...(c) == 2, int>::type operator""_t () // { dg-error "no type named|in" }
{
return 2;
}
template <char... c>
constexpr typename enable_if<sizeof...(c) == 1, int>::type operator""_t () // { dg-error "no type named|in" }
{
return 1;
}
int a = 45_t;
int b = 4_t;
int c = 100000_t; // { dg-error "no matching function for call to" }

View File

@ -0,0 +1,38 @@
// { dg-do run { target c++11 } }
#include <cassert>
template<bool, typename _Tp = void> struct enable_if { };
template<typename _Tp> struct enable_if<true, _Tp> { typedef _Tp type; };
template <char... c>
constexpr typename enable_if<sizeof...(c) == 2, int>::type operator""_t ()
{
return 2;
}
template <char... c>
constexpr typename enable_if<sizeof...(c) == 1, int>::type operator""_t ()
{
return 1;
}
template <char... c>
constexpr typename enable_if<sizeof...(c) >= 3, int>::type operator""_t ()
{
return 100;
}
int operator""_t (long double)
{
return 200;
}
int main ()
{
assert (45_t == 2);
assert (4_t == 1);
assert (100000_t == 100);
assert (200.0_t == 200);
}

View File

@ -0,0 +1,20 @@
// { dg-do compile { target c++14 } }
// { dg-prune-output "note:" }
template<bool, typename _Tp = void>struct enable_if {};
template<typename _Tp> struct enable_if<true, _Tp> { typedef _Tp type; };
template<typename CharT, CharT... String>
typename enable_if<sizeof...(String) == 1, int>::type operator"" _script () { // { dg-error "no type named|in" }
return 1;
}
template<typename CharT, CharT... String>
typename enable_if<sizeof...(String) == 2, int>::type operator"" _script () { // { dg-error "no type named|in" }
return 2;
}
int a = "1"_script;
int b = "22"_script;
int c = "333"_script; // { dg-error "no matching function for call to"}

View File

@ -0,0 +1,29 @@
// { dg-do run { target c++14 } }
#include <cassert>
template<bool, typename _Tp = void>struct enable_if {};
template<typename _Tp> struct enable_if<true, _Tp> { typedef _Tp type; };
template<typename CharT, CharT... String>
typename enable_if<sizeof...(String) == 6, int>::type operator"" _script () {
return 5;
}
template<typename CharT, CharT... String>
typename enable_if<sizeof...(String) == 3, int>::type operator"" _script () {
return 3;
}
template<typename CharT, CharT... String>
typename enable_if<sizeof...(String) != 3 && sizeof...(String) != 6, int>::type operator"" _script () {
return 1;
}
int main ()
{
assert ("hello!"_script == 5);
assert (u8"hi!"_script == 3);
assert ("hey!"_script == 1);
}

View File

@ -0,0 +1,17 @@
// { dg-do run { target c++14 } }
#include <cassert>
template<typename CharT, CharT... String>
int operator"" _script () {
return 1;
}
int operator"" _script (const char*, unsigned long) {
return 2;
}
int main ()
{
assert ("123"_script == 2);
}