re PR c++/50958 ([C++0x] raw literal operator provides incorrect string for integer literal '0')

PR c++/50958
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.

From-SVN: r181595
This commit is contained in:
Ed Smith-Rowland 2011-11-21 19:27:30 +00:00 committed by Jason Merrill
parent f3fae478f4
commit 7e74ce3f94
12 changed files with 261 additions and 80 deletions

View 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.

View 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;
}

View 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

View 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" } */

View 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" }

View File

@ -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" }

View 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" }

View File

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

View 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" }

View File

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

View 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

View 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;
}