re PR c++/64959 (SFINAE in UDLs)
authorAndrea Azzarone <azzaronea@gmail.com>
Thu, 12 Feb 2015 20:21:34 +0000 (20:21 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 12 Feb 2015 20:21:34 +0000 (15:21 -0500)
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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp0x/udlit-namespace-ambiguous.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/udlit-namespace-using-directive.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
gcc/testsuite/g++.dg/cpp0x/udlit-sfinae-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/udlit-sfinae.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C [new file with mode: 0644]

index 722e92684bf92b0e8f008a6294eed078ed3ae575..e460c55619d44ef9a179cf3dc86e01a43d09ab4c 100644 (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
index 57dfbcc41171196be8c55dbd984cd92010cc8f33..e81e9d34767d57340f689eec5f43ef524600e389 100644 (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;
+  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 (file)
index 0000000..c67be39
--- /dev/null
@@ -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 (file)
index 0000000..bd1f206
--- /dev/null
@@ -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;
+}
index 4241d0a80309738d5f25fda3dd845df0620b4193..c1ceef7577fc654898279d0987584f5bae766874 100644 (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);
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 (file)
index 0000000..6b84eba
--- /dev/null
@@ -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 (file)
index 0000000..e24b79d
--- /dev/null
@@ -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 (file)
index 0000000..b749001
--- /dev/null
@@ -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 (file)
index 0000000..a9c577f
--- /dev/null
@@ -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 (file)
index 0000000..2eb6a7d
--- /dev/null
@@ -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);
+}