OSDN Git Service

PR c++/50958
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 21 Nov 2011 19:27:30 +0000 (19:27 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 21 Nov 2011 19:27:30 +0000 (19:27 +0000)
gcc/cp/
* parser.c (lookup_literal_operator): New.
(cp_parser_userdef_char_literal): Use it.
(cp_parser_userdef_numeric_literal): Use it.
(cp_parser_userdef_string_literal): Use lookup_name.
libcpp/
* expr.c (cpp_userdef_char_remove_type): Fix typo.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181595 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/dfp/pr33466.c
gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C [new file with mode: 0644]
libcpp/ChangeLog
libcpp/expr.c

index c083144..7b995f1 100644 (file)
@@ -1,3 +1,11 @@
+2011-11-21  Ed Smith-Rowland  <3dw4rd@verizon.net>
+
+       PR c++/50958
+       * parser.c (lookup_literal_operator): New.
+       (cp_parser_userdef_char_literal): Use it.
+       (cp_parser_userdef_numeric_literal): Use it.
+       (cp_parser_userdef_string_literal): Use lookup_name.
+
 2011-11-20  Jason Merrill  <jason@redhat.com>
 
        * pt.c (tsubst_pack_expansion): Fix SFINAE.
index f839112..4a2b2a9 100644 (file)
@@ -3547,40 +3547,79 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
   return value;
 }
 
+/* Look up a literal operator with the name and the exact arguments.  */
+
+static tree
+lookup_literal_operator (tree name, VEC(tree,gc) *args)
+{
+  tree decl, fns;
+  decl = lookup_name (name);
+  if (!decl || decl == error_mark_node)
+    return error_mark_node;
+
+  for (fns = decl; fns; fns = OVL_NEXT (fns))
+    {
+      unsigned int ix;
+      bool found = true;
+      tree fn = OVL_CURRENT (fns);
+      tree argtypes = NULL_TREE;
+      argtypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
+      if (argtypes != NULL_TREE)
+       {
+         for (ix = 0; ix < VEC_length (tree, args) && argtypes != NULL_TREE;
+              ++ix, argtypes = TREE_CHAIN (argtypes))
+           {
+             tree targ = TREE_VALUE (argtypes);
+             tree tparm = TREE_TYPE (VEC_index (tree, args, ix));
+             bool ptr = TREE_CODE (targ) == POINTER_TYPE;
+             bool arr = TREE_CODE (tparm) == ARRAY_TYPE;
+             if ((ptr || arr || !same_type_p (targ, tparm))
+                 && (!ptr || !arr
+                     || !same_type_p (TREE_TYPE (targ),
+                                      TREE_TYPE (tparm))))
+               found = false;
+           }
+         if (found)
+           return fn;
+       }
+    }
+
+  return error_mark_node;
+}
+
 /* Parse a user-defined char constant.  Returns a call to a user-defined
    literal operator taking the character as an argument.  */
 
 static tree
 cp_parser_userdef_char_literal (cp_parser *parser)
 {
-  cp_token *token = NULL;
-  tree literal, suffix_id, value;
-  tree name, decl;
-  tree result;
-  VEC(tree,gc) *vec;
-
-  token = cp_lexer_consume_token (parser->lexer);
-  literal = token->u.value;
-  suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
-  value = USERDEF_LITERAL_VALUE (literal);
-  name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+  cp_token *token = cp_lexer_consume_token (parser->lexer);
+  tree literal = token->u.value;
+  tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+  tree value = USERDEF_LITERAL_VALUE (literal);
+  tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+  tree decl, result;
 
   /* Build up a call to the user-defined operator  */
   /* Lookup the name we got back from the id-expression.  */
-  vec = make_tree_vector ();
-  VEC_safe_push (tree, gc, vec, value);
-  decl = lookup_function_nonclass (name, vec, /*block_p=*/false);
+  VEC(tree,gc) *args = make_tree_vector ();
+  VEC_safe_push (tree, gc, args, value);
+  decl = lookup_literal_operator (name, args);
   if (!decl || decl == error_mark_node)
     {
-      error ("unable to find user-defined character literal operator %qD",
-            name);
-      release_tree_vector (vec);
+      error ("unable to find character literal operator %qD with %qT argument",
+            name, TREE_TYPE (value));
+      release_tree_vector (args);
       return error_mark_node;
     }
-  result = finish_call_expr (decl, &vec, false, true, tf_warning_or_error);
-  release_tree_vector (vec);
+  result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
+  release_tree_vector (args);
+  if (result != error_mark_node)
+    return result;
 
-  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
@@ -3615,26 +3654,20 @@ make_char_string_pack (tree value)
 static tree
 cp_parser_userdef_numeric_literal (cp_parser *parser)
 {
-  cp_token *token = NULL;
-  tree literal, suffix_id, value, num_string;
-  tree name, decl;
-  tree result = error_mark_node;
+  cp_token *token = cp_lexer_consume_token (parser->lexer);
+  tree literal = token->u.value;
+  tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+  tree value = USERDEF_LITERAL_VALUE (literal);
+  tree num_string = USERDEF_LITERAL_NUM_STRING (literal);
+  tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+  tree decl, result;
   VEC(tree,gc) *args;
 
-  token = cp_lexer_consume_token (parser->lexer);
-  literal = token->u.value;
-  suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
-  value = USERDEF_LITERAL_VALUE (literal);
-  num_string = USERDEF_LITERAL_NUM_STRING (literal);
-  name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
-
-  /* Build up a call to the user-defined operator  */
-  /* Lookup the name we got back from the id-expression.  */
-  /* Try to find the literal operator by finishing the call expression
-     with the numeric argument.  */
+  /* Look for a literal operator taking the exact type of numeric argument
+     as the literal value.  */
   args = make_tree_vector ();
   VEC_safe_push (tree, gc, args, value);
-  decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+  decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
       result = finish_call_expr (decl, &args, false, true, tf_none);
@@ -3651,7 +3684,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
      in string format.  */
   args = make_tree_vector ();
   VEC_safe_push (tree, gc, args, num_string);
-  decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+  decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
       result = finish_call_expr (decl, &args, false, true, tf_none);
@@ -3667,7 +3700,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
      function with parameter pack char....  Call the function with
      template parameter characters representing the number.  */
   args = make_tree_vector ();
-  decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+  decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
       tree tmpl_args = make_char_string_pack (num_string);
@@ -3681,10 +3714,8 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
     }
   release_tree_vector (args);
 
-  if (result == error_mark_node)
-    error ("unable to find user-defined numeric literal operator %qD", name);
-
-  return result;
+  error ("unable to find numeric literal operator %qD", name);
+  return error_mark_node;
 }
 
 /* Parse a user-defined string constant.  Returns a call to a user-defined
@@ -3694,38 +3725,34 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
 static tree
 cp_parser_userdef_string_literal (cp_token *token)
 {
-  tree literal, suffix_id, value;
-  tree name, decl;
-  tree result;
-  VEC(tree,gc) *vec;
-  int len;
-
-  literal = token->u.value;
-  suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
-  name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
-  value = USERDEF_LITERAL_VALUE (literal);
-  len = TREE_STRING_LENGTH (value)
+  tree literal = token->u.value;
+  tree suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+  tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+  tree value = USERDEF_LITERAL_VALUE (literal);
+  int len = TREE_STRING_LENGTH (value)
        / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1;
+  tree decl, result;
+
   /* Build up a call to the user-defined operator  */
   /* Lookup the name we got back from the id-expression.  */
-  vec = make_tree_vector ();
-  VEC_safe_push (tree, gc, vec, value);
-  VEC_safe_push (tree, gc, vec, build_int_cst (size_type_node, len));
-  decl = lookup_function_nonclass (name, vec, /*block_p=*/false);
+  VEC(tree,gc) *args = make_tree_vector ();
+  VEC_safe_push (tree, gc, args, value);
+  VEC_safe_push (tree, gc, args, build_int_cst (size_type_node, len));
+  decl = lookup_name (name);
   if (!decl || decl == error_mark_node)
     {
-      error ("unable to find user-defined string literal operator %qD", name);
-      release_tree_vector (vec);
+      error ("unable to find string literal operator %qD", name);
+      release_tree_vector (args);
       return error_mark_node;
     }
-  result = finish_call_expr (decl, &vec, false, true, tf_none);
-  if (result == error_mark_node)
-    error ("unable to find valid user-defined string literal operator %qD."
-          "  Possible missing length argument in string literal operator.",
-          name);
-  release_tree_vector (vec);
+  result = finish_call_expr (decl, &args, false, true, tf_none);
+  release_tree_vector (args);
+  if (result != error_mark_node)
+    return result;
 
-  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;
 }
 
 
index 6d8010d..b9ab579 100644 (file)
@@ -1,3 +1,14 @@
+2011-11-21  Ed Smith-Rowland  <3dw4rd@verizon.net>
+
+       PR c++/50958
+       * g++.dg/cpp0x/udlit-declare-neg.C: Adjust.
+       * g++.dg/cpp0x/udlit-implicit-conv-neg.C: New.
+       * g++.dg/cpp0x/udlit-member.C: Adjust.
+       * g++.dg/cpp0x/udlit-raw-length.C: New.
+       * g++.dg/cpp0x/udlit-raw-op-string-neg.C: Adjust.
+       * g++.dg/cpp0x/udlit-resolve.C: New.
+       * c-c++-common/dfp/pr33466.c: Adjust.
+
 2011-11-21  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * lib/target-supports.exp
index 8c73cef..9b10a09 100644 (file)
@@ -5,9 +5,9 @@
    These are invalid for all targets, not just those that support
     decimal float.  */
 
-long double dF = 4.5dF;           /* { dg-error "invalid suffix|user-defined" } */
-long double Df = 4.5Df;           /* { dg-error "invalid suffix|user-defined" } */
-long double dD = 4.5dD;           /* { dg-error "invalid suffix|user-defined" } */
-long double Dd = 4.5Dd;           /* { dg-error "invalid suffix|user-defined" } */
-long double dL = 4.5dL;           /* { dg-error "invalid suffix|user-defined" } */
-long double Dl = 4.5Dl;           /* { dg-error "invalid suffix|user-defined" } */
+long double dF = 4.5dF;           /* { dg-error "invalid suffix|literal operator" } */
+long double Df = 4.5Df;           /* { dg-error "invalid suffix|literal operator" } */
+long double dD = 4.5dD;           /* { dg-error "invalid suffix|literal operator" } */
+long double Dd = 4.5Dd;           /* { dg-error "invalid suffix|literal operator" } */
+long double dL = 4.5dL;           /* { dg-error "invalid suffix|literal operator" } */
+long double Dl = 4.5Dl;           /* { dg-error "invalid suffix|literal operator" } */
index 7b50c01..9060abb 100644 (file)
@@ -3,13 +3,13 @@
 //  Check that undeclared literal operator calls and literals give appropriate errors.
 
 int i = operator"" _Bar('x');  // { dg-error "was not declared in this scope" }
-int j = 'x'_Bar;  // { dg-error "unable to find user-defined character literal operator" }
+int j = 'x'_Bar;  // { dg-error "unable to find character literal operator|with|argument" }
 
 int ii = operator"" _BarCharStr("Howdy, Pardner!");  // { dg-error "was not declared in this scope" }
-int jj = "Howdy, Pardner!"_BarCharStr;  // { dg-error "unable to find user-defined string literal operator" }
+int jj = "Howdy, Pardner!"_BarCharStr;  // { dg-error "unable to find string literal operator|Possible missing length argument" }
 
 unsigned long long iULL = operator"" _BarULL(666ULL);  // { dg-error "was not declared in this scope" }
-unsigned long long jULL = 666_BarULL;  // { dg-error "unable to find user-defined numeric literal operator" }
+unsigned long long jULL = 666_BarULL;  // { dg-error "unable to find numeric literal operator" }
 
 long double iLD = operator"" _BarLD(666.0L);  // { dg-error "was not declared in this scope" }
-long double jLD = 666.0_BarLD;  // { dg-error "unable to find user-defined numeric literal operator" }
+long double jLD = 666.0_BarLD;  // { dg-error "unable to find numeric literal operator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C
new file mode 100644 (file)
index 0000000..998ad15
--- /dev/null
@@ -0,0 +1,63 @@
+// { dg-options -std=c++0x }
+
+#include <cstdint>
+
+int operator"" _bar (long double);
+
+double operator"" _foo (long long unsigned);
+
+int i = 12_bar; // { dg-error "unable to find numeric literal operator|with|argument" }
+
+double d = 1.2_foo; // { dg-error "unable to find numeric literal operator|with|argument" }
+
+int operator"" _char(char);
+
+int operator"" _wchar_t(wchar_t);
+
+int operator"" _char16_t(char16_t);
+
+int operator"" _char32_t(char32_t);
+
+int cwcx = 'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int cc16 = 'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+int cc32 = 'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int wccx = L'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int wcc16 = L'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+int wcc32 = L'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int c16c = u'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int c16wc = u'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c16c32 = u'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int c32c = U'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int c32wc = U'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c32c16 = U'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int operator"" _char_str(const char*, std::size_t);
+
+int operator"" _wchar_t_str(const wchar_t*, std::size_t);
+
+int operator"" _char16_t_str(const char16_t*, std::size_t);
+
+int operator"" _char32_t_str(const char32_t*, std::size_t);
+
+int strwstr = "str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int strstr16 = "str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int strstr32 = "str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str8wstr = u8"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str8str16 = u8"str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str8str32 = u8"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int wstrstr = L"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int wstrstr16 = L"str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int wstrstr32 = L"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str16str = u"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str16wstr = u"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str16str32 = u"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str32str = U"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str32wstr = U"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str32str16 = U"str"_char16_t_str; // { dg-error "unable to find string literal operator string operator|with|arguments" }
index 809df25..a6220c4 100644 (file)
@@ -8,7 +8,7 @@ public:
 };
 
 int i = operator"" _Bar(U'x');  // { dg-error "was not declared in this scope" }
-int j = U'x'_Bar;  // { dg-error "unable to find user-defined character literal operator" }
+int j = U'x'_Bar;  // { dg-error "unable to find character literal operator" }
 
 int
 Foo::operator"" _Bar(char32_t)  // { dg-error "must be a non-member function" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C
new file mode 100644 (file)
index 0000000..2d91062
--- /dev/null
@@ -0,0 +1,27 @@
+// { dg-options "-std=c++0x" }
+// PR c++/50958
+
+typedef decltype(sizeof(0)) size_type;
+
+constexpr size_type
+cstrlen_impl(const char* s, size_type i)
+{
+  return s[i] ? cstrlen_impl(s, i + 1) : i;
+}
+
+constexpr size_type
+cstrlen(const char* s)
+{
+  return s ? cstrlen_impl(s, 0) : throw 0;
+}
+
+constexpr size_type
+operator "" _lenraw(const char* digits)
+{
+  return cstrlen(digits);
+}
+
+static_assert(123_lenraw == 3, "Ouch");
+static_assert(1_lenraw == 1, "Ouch");
+static_assert(012_lenraw == 3, "Ouch");
+static_assert(0_lenraw == 1, "Ouch");
index 5c399af..58ad0e6 100644 (file)
@@ -5,4 +5,4 @@
 int operator"" _embedraw(const char*)
 { return 41; };
 
-int k = "Boo!"_embedraw;  //  { dg-error "unable to find valid user-defined string literal operator" }
+int k = "Boo!"_embedraw;  //  { dg-error "unable to find string literal operator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
new file mode 100644 (file)
index 0000000..a255162
--- /dev/null
@@ -0,0 +1,40 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+#include <cstdint>
+#include <cassert>
+
+int operator"" _foo(const char*)                  { return 0; }
+int operator"" _foo(unsigned long long int)       { return 1; }
+int operator"" _foo(long double)                  { return 2; }
+int operator"" _foo(char)                         { return 3; }
+int operator"" _foo(wchar_t)                      { return 4; }
+int operator"" _foo(char16_t)                     { return 5; }
+int operator"" _foo(char32_t)                     { return 6; }
+int operator"" _foo(const char*, std::size_t)     { return 7; }
+int operator"" _foo(const wchar_t*, std::size_t)  { return 8; }
+int operator"" _foo(const char16_t*, std::size_t) { return 9; }
+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(0.123_foo == 2);
+  assert('c'_foo == 3);
+  assert(L'c'_foo == 4);
+  assert(u'c'_foo == 5);
+  assert(U'c'_foo == 6);
+  assert("abc"_foo == 7);
+  assert(L"abc"_foo == 8);
+  assert(u"abc"_foo == 9);
+  assert(U"abc"_foo == 10);
+  assert(123_foo2 == 21);
+}
index 8f7d494..5929842 100644 (file)
@@ -1,3 +1,8 @@
+2011-11-21  Ed Smith-Rowland  <3dw4rd@verizon.net>
+
+       PR c++/50958
+       * expr.c (cpp_userdef_char_remove_type): Fix typo.
+
 2011-11-03  Michael Matz  <matz@suse.de>
 
        PR bootstrap/50857
index 7bbc72d..d56e56a 100644 (file)
@@ -284,9 +284,9 @@ cpp_userdef_char_remove_type (enum cpp_ttype type)
   else if (type == CPP_WCHAR_USERDEF)
     return CPP_WCHAR;
   else if (type == CPP_CHAR16_USERDEF)
-    return CPP_STRING16;
+    return CPP_CHAR16;
   else if (type == CPP_CHAR32_USERDEF)
-    return CPP_STRING32;
+    return CPP_CHAR32;
   else
     return type;
 }