aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrea Azzarone <azzaronea@gmail.com>2015-02-12 20:21:34 +0000
committerJason Merrill <jason@gcc.gnu.org>2015-02-12 15:21:34 -0500
commitbc81eb3f77b27d46e25c218cfd9f32c89cc36b3c (patch)
tree9e8f65f24d3a49b152bf5bb8ea477528a1d4764e /gcc
parent864f0146f052c560b81794aced67f5d095d241a3 (diff)
downloadgcc-bc81eb3f77b27d46e25c218cfd9f32c89cc36b3c.zip
gcc-bc81eb3f77b27d46e25c218cfd9f32c89cc36b3c.tar.gz
gcc-bc81eb3f77b27d46e25c218cfd9f32c89cc36b3c.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/parser.c107
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-namespace-ambiguous.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-namespace-using-directive.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-sfinae-neg.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-sfinae.C38
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae-neg.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C17
10 files changed, 210 insertions, 64 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 722e926..e460c55 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 57dfbcc..e81e9d3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
+ return result;
}
/* A subroutine of cp_parser_userdef_numeric_literal to
@@ -3955,26 +3950,28 @@ 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 (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && overflow > 0)
+ if (overflow > 0)
warning_at (token->location, OPT_Woverflow,
- "integer literal exceeds range of %qT type",
- long_long_unsigned_type_node);
- else
- {
- if (overflow > 0)
- warning_at (token->location, OPT_Woverflow,
- "floating literal exceeds range of %qT type",
- long_double_type_node);
- else if (overflow < 0)
- warning_at (token->location, OPT_Woverflow,
- "floating literal truncated to zero");
- }
- release_tree_vector (args);
- return result;
+ "floating literal exceeds range of %qT type",
+ long_double_type_node);
+ else if (overflow < 0)
+ warning_at (token->location, OPT_Woverflow,
+ "floating literal truncated to zero");
}
+
+ release_tree_vector (args);
+ return result;
}
release_tree_vector (args);
@@ -3986,12 +3983,10 @@ 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)
- {
- release_tree_vector (args);
- return result;
- }
+ result = finish_call_expr (decl, &args, false, true,
+ tf_warning_or_error);
+ release_tree_vector (args);
+ return result;
}
release_tree_vector (args);
@@ -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)
- {
- release_tree_vector (args);
- return result;
- }
+ 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,40 +4029,37 @@ cp_parser_userdef_string_literal (tree literal)
tree decl, result;
vec<tree, va_gc> *args;
- /* Look for a template function with typename parameter CharT
- and parameter pack CharT... Call the function with
- template parameter characters representing the string. */
+ /* 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)
{
- 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)
- {
- release_tree_vector (args);
- return result;
- }
+ 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. */
+ /* Look for a template function with typename parameter CharT
+ and parameter pack CharT... Call the function with
+ template parameter characters representing the string. */
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)
+ decl = lookup_literal_operator (name, args);
+ if (decl && decl != error_mark_node)
{
- error ("unable to find string literal operator %qD", name);
+ tree tmpl_args = make_string_pack (value);
+ decl = lookup_template_function (decl, tmpl_args);
+ result = finish_call_expr (decl, &args, false, true,
+ tf_warning_or_error);
release_tree_vector (args);
- return error_mark_node;
+ return result;
}
- 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);
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-namespace-ambiguous.C b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace-ambiguous.C
new file mode 100644
index 0000000..c67be390
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace-ambiguous.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-namespace-using-directive.C b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace-using-directive.C
new file mode 100644
index 0000000..bd1f206
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace-using-directive.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
index 4241d0a..c1ceef7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
@@ -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);
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-sfinae-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-sfinae-neg.C
new file mode 100644
index 0000000..6b84eba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-sfinae-neg.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-sfinae.C b/gcc/testsuite/g++.dg/cpp0x/udlit-sfinae.C
new file mode 100644
index 0000000..e24b79d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-sfinae.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae-neg.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae-neg.C
new file mode 100644
index 0000000..b749001
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae-neg.C
@@ -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"}
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C
new file mode 100644
index 0000000..a9c577f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C
new file mode 100644
index 0000000..2eb6a7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C
@@ -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);
+}