mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
864f0146f0
commit
bc81eb3f77
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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"}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue