diff mbox

[C++-11] User defined literals

Message ID 4EA9B1D7.3060304@verizon.net
State New
Headers show

Commit Message

Ed Smith-Rowland Oct. 27, 2011, 7:32 p.m. UTC
On 10/26/2011 03:38 PM, Jason Merrill wrote:
> On 10/26/2011 02:00 AM, Ed Smith-Rowland wrote:
>> The patch was bootstrapped and regtested on x86_64-linux-gnu.
>
> Really? I ran into a warning about the unused "suffix" parameter to 
> interpret_integer. So I've fixed that error. I also added a couple of 
> comments, and implemented the change to check_literal_operator_args 
> that I wondered about a while back. And checked it all in.
>
> But we aren't quite done, I think: I notice that the lookup of 
> operators doesn't match what's in 2.14.8. For instance, I don't think 
> this should be accepted:
>
> double operator"" _foo (long long unsigned);
> double d = 1.2_foo;
>
> The lookup described in 2.14.8 involves looking through the overload 
> set for a particular signature before doing normal overload resolution.
>
> Also, we don't need to worry about argument-dependent lookup for these 
> operators, since none of the arguments can have associated namespaces. 
> So I think we can use lookup_name rather than 
> lookup_function_nonclass, only look it up once in 
> cp_userdef_numeric_literal, and then only build one call depending on 
> the contents of the overload set.
>
> Jason
Jason,

Here is a patch that prevents the conversions outlined above and also 
for char types.
I also changed the name lookup to use the simpler and correct lookup_name().
There is a new testcase.

Now for the weirdness. When I try to make test cases with char16_t or 
char32_t it's like the u or U prefix is ignored and the character 
argument is of type char. I don't really use these character widths so 
my test cases could be wonky.

char16_t operator"" _rot(char16_t c) { return 127 - c; }

char16_t c = u'x'_rot;

$ char16.cpp:6:14: error: unable to find operator ‘operator"" _rot’ with 
‘char’ argument

Ideas? I'll try and see if there is a lexing error somewhere.

Ed

Comments

Jason Merrill Oct. 27, 2011, 7:47 p.m. UTC | #1
On 10/27/2011 03:32 PM, Ed Smith-Rowland wrote:
> +  if (TREE_CODE (TREE_TYPE (decl)) != LANG_TYPE)
> +    argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));

If you have multiple overloaded operator"" _foo, you need to iterate 
over them looking for the one (or ones, in the case of numeric literals) 
you want.

> +  if (argtypes != NULL_TREE
> +      && TREE_VALUE (argtypes) != TREE_TYPE (value))

I think you want

  if (argtypes == NULL_TREE
      || !same_type_p (TREE_VALUE (argtypes), TREE_TYPE (value)))

> +  if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE)
> +    {
> +      if (argtypes != NULL_TREE
> +	  && TREE_CODE (TREE_VALUE (argtypes)) == REAL_TYPE)
> +	{
> +	  error ("unable to find %qD with %<unsigned long long int%> argument",
> +		 name);
> +	  return error_mark_node;
> +	}
> +    }
> +  else if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE)
> +    {
> +      if (argtypes != NULL_TREE
> +	  && TREE_CODE (TREE_VALUE (argtypes)) == INTEGER_TYPE)
> +	{
> +	  error ("unable to find %qD with %<long double%> argument", name);
> +	  return error_mark_node;
> +	}
> +    }

This looks like it will break raw operators.

Jason
diff mbox

Patch

Index: gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C	(revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C	(revision 0)
@@ -0,0 +1,33 @@ 
+// { dg-options -std=c++0x }
+
+int operator"" _bar (long double);
+
+double operator"" _foo (long long unsigned);
+
+int i = 12_bar; // { dg-error "unable to find|with|argument" }
+
+double d = 1.2_foo; // { dg-error "unable to find|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 cwc = 'c'_wchar_t; // { dg-error "unable to find|with|argument" }
+int cc16 = 'c'_char16_t; // { dg-error "unable to find|with|argument" }
+int cc32 = 'c'_char32_t; // { dg-error "unable to find|with|argument" }
+
+int wcc = L'c'_char; // { dg-error "unable to find|with|argument" }
+int wcc16 = L'c'_char16_t; // { dg-error "unable to find|with|argument" }
+int wcc32 = L'c'_char32_t; // { dg-error "unable to find|with|argument" }
+
+int c16c = u'c'_char; // { dg-error "unable to find|with|argument" }
+int c16wc = u'c'_wchar_t; // { dg-error "unable to find|with|argument" }
+int c16c32 = u'c'_char32_t; // { dg-error "unable to find|with|argument" }
+
+int c32c = U'c'_char; // { dg-error "unable to find|with|argument" }
+int c32wc = U'c'_wchar_t; // { dg-error "unable to find|with|argument" }
+int c32c16 = U'c'_char16_t; // { dg-error "unable to find|with|argument" }
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 180556)
+++ gcc/cp/parser.c	(working copy)
@@ -3532,7 +3532,7 @@ 
 {
   cp_token *token = NULL;
   tree literal, suffix_id, value;
-  tree name, decl;
+  tree name, decl, argtypes = NULL_TREE;
   tree result;
   VEC(tree,gc) *vec;
 
@@ -3546,7 +3546,7 @@ 
   /* 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);
+  decl = lookup_name (name);
   if (!decl || decl == error_mark_node)
     {
       error ("unable to find user-defined character literal operator %qD",
@@ -3554,6 +3554,17 @@ 
       release_tree_vector (vec);
       return error_mark_node;
     }
+
+  if (TREE_CODE (TREE_TYPE (decl)) != LANG_TYPE)
+    argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+  if (argtypes != NULL_TREE
+      && TREE_VALUE (argtypes) != TREE_TYPE (value))
+    {
+      error ("unable to find operator %qD with %qT argument",
+	     name, TREE_TYPE (value));
+      return error_mark_node;
+    }
+
   result = finish_call_expr (decl, &vec, false, true, tf_warning_or_error);
   release_tree_vector (vec);
 
@@ -3594,7 +3605,7 @@ 
 {
   cp_token *token = NULL;
   tree literal, suffix_id, value, num_string;
-  tree name, decl;
+  tree name, decl, argtypes = NULL_TREE;
   tree result = error_mark_node;
   VEC(tree,gc) *args;
 
@@ -3605,21 +3616,47 @@ 
   num_string = USERDEF_LITERAL_NUM_STRING (literal);
   name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
 
+  decl = lookup_name (name);
+  if (!decl || decl == error_mark_node)
+    {
+      error ("unable to find user-defined numeric literal operator %qD", name);
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (TREE_TYPE (decl)) != LANG_TYPE)
+    argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+
+  if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE)
+    {
+      if (argtypes != NULL_TREE
+	  && TREE_CODE (TREE_VALUE (argtypes)) == REAL_TYPE)
+	{
+	  error ("unable to find %qD with %<unsigned long long int%> argument",
+		 name);
+	  return error_mark_node;
+	}
+    }
+  else if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE)
+    {
+      if (argtypes != NULL_TREE
+	  && TREE_CODE (TREE_VALUE (argtypes)) == INTEGER_TYPE)
+	{
+	  error ("unable to find %qD with %<long double%> argument", name);
+	  return error_mark_node;
+	}
+    }
+
   /* 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.  */
   args = make_tree_vector ();
   VEC_safe_push (tree, gc, args, value);
-  decl = lookup_function_nonclass (name, args, /*block_p=*/false);
-  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_none);
-      if (result != error_mark_node)
-	{
-	  release_tree_vector (args);
-	  return result;
-	}
+      release_tree_vector (args);
+      return result;
     }
   release_tree_vector (args);
 
@@ -3628,15 +3665,11 @@ 
      in string format.  */
   args = make_tree_vector ();
   VEC_safe_push (tree, gc, args, num_string);
-  decl = lookup_function_nonclass (name, args, /*block_p=*/false);
-  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_none);
-      if (result != error_mark_node)
-	{
-	  release_tree_vector (args);
-	  return result;
-	}
+      release_tree_vector (args);
+      return result;
     }
   release_tree_vector (args);
 
@@ -3644,17 +3677,13 @@ 
      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);
-  if (decl && decl != error_mark_node)
+  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)
     {
-      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;
-	}
+      release_tree_vector (args);
+      return result;
     }
   release_tree_vector (args);
 
@@ -3688,7 +3717,7 @@ 
   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);
+  decl = lookup_name (name);
   if (!decl || decl == error_mark_node)
     {
       error ("unable to find user-defined string literal operator %qD", name);