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
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);