PR c++/79228 - extensions hide C++14 complex literal operators

libcpp/
	* expr.c (interpret_float_suffix): Ignore 'i' in C++14 and up.
	(interpret_int_suffix): Likewise.
gcc/cp/
	* parser.c (cp_parser_userdef_numeric_literal): Be helpful about
	'i' in C++14 and up.

From-SVN: r255335
This commit is contained in:
Jason Merrill 2017-12-01 15:19:07 -05:00 committed by Jason Merrill
parent 0951904f49
commit f2b8b8adba
10 changed files with 175 additions and 12 deletions

View File

@ -1,3 +1,9 @@
2017-12-01 Jason Merrill <jason@redhat.com>
PR c++/79228 - extensions hide C++14 complex literal operators
* parser.c (cp_parser_userdef_numeric_literal): Be helpful about
'i' in C++14 and up.
2017-12-01 Jakub Jelinek <jakub@redhat.com>
* parser.c (cp_parser_new): Don't clear cilk_simd_fn_info.

View File

@ -4397,11 +4397,75 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
release_tree_vector (args);
error ("unable to find numeric literal operator %qD", name);
if (!cpp_get_options (parse_in)->ext_numeric_literals)
inform (token->location, "use -std=gnu++11 or -fext-numeric-literals "
/* In C++14 the standard library defines complex number suffixes that
conflict with GNU extensions. Prefer them if <complex> is #included. */
bool ext = cpp_get_options (parse_in)->ext_numeric_literals;
bool i14 = (cxx_dialect > cxx11
&& (id_equal (suffix_id, "i")
|| id_equal (suffix_id, "if")
|| id_equal (suffix_id, "il")));
diagnostic_t kind = DK_ERROR;
int opt = 0;
if (i14 && ext)
{
tree cxlit = lookup_qualified_name (std_node,
get_identifier ("complex_literals"),
0, false, false);
if (cxlit == error_mark_node)
{
/* No <complex>, so pedwarn and use GNU semantics. */
kind = DK_PEDWARN;
opt = OPT_Wpedantic;
}
}
bool complained
= emit_diagnostic (kind, input_location, opt,
"unable to find numeric literal operator %qD", name);
if (!complained)
/* Don't inform either. */;
else if (i14)
{
inform (token->location, "add %<using namespace std::complex_literals%> "
"(from <complex>) to enable the C++14 user-defined literal "
"suffixes");
if (ext)
inform (token->location, "or use %<j%> instead of %<i%> for the "
"GNU built-in suffix");
}
else if (!ext)
inform (token->location, "use -fext-numeric-literals "
"to enable more built-in suffixes");
return error_mark_node;
if (kind == DK_ERROR)
value = error_mark_node;
else
{
/* Use the built-in semantics. */
tree type;
if (id_equal (suffix_id, "i"))
{
if (TREE_CODE (value) == INTEGER_CST)
type = integer_type_node;
else
type = double_type_node;
}
else if (id_equal (suffix_id, "if"))
type = float_type_node;
else /* if (id_equal (suffix_id, "il")) */
type = long_double_type_node;
value = build_complex (build_complex_type (type),
fold_convert (type, integer_zero_node),
fold_convert (type, value));
}
if (cp_parser_uncommitted_to_tentative_parse_p (parser))
/* Avoid repeated diagnostics. */
token->u.value = value;
return value;
}
/* Parse a user-defined string constant. Returns a call to a user-defined

View File

@ -4,7 +4,7 @@
// Integer imaginary...
constexpr unsigned long long
operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" }
operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" "" { target c++11_only } }
{ return 4 * n + 0; }
constexpr unsigned long long
@ -22,7 +22,7 @@ operator"" J(unsigned long long n) // { dg-warning "shadowed by implementation"
// Floating-point imaginary...
constexpr long double
operator"" i(long double n) // { dg-warning "shadowed by implementation" }
operator"" i(long double n) // { dg-warning "shadowed by implementation" "" { target c++11_only } }
{ return 4.0L * n + 0.0L; }
constexpr long double

View File

@ -4,7 +4,7 @@
// Integer imaginary...
constexpr unsigned long long
operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" }
operator"" i(unsigned long long n) // { dg-warning "shadowed by implementation" "" { target c++11_only } }
{ return 4 * n + 0; }
constexpr unsigned long long
@ -22,7 +22,7 @@ operator"" J(unsigned long long n) // { dg-warning "shadowed by implementation"
// Floating-point imaginary...
constexpr long double
operator"" i(long double n) // { dg-warning "shadowed by implementation" }
operator"" i(long double n) // { dg-warning "shadowed by implementation" "" { target c++11_only } }
{ return 4.0L * n + 0.0L; }
constexpr long double

View File

@ -0,0 +1,10 @@
// PR c++/79228
// { dg-do compile { target c++14 } }
#include <complex>
int main()
{
using namespace std::complex_literals;
auto a = std::abs(0.0i);
}

View File

@ -0,0 +1,11 @@
// PR c++/79228
// { dg-do compile { target c++14 } }
// { dg-options "" }
#include <complex>
int main()
{
auto a = std::abs(0.0i); // { dg-error "literal operator" }
// { dg-message "complex_literals" "" { target *-*-* } .-1 }
}

View File

@ -0,0 +1,25 @@
// PR c++/79228
// { dg-do compile { target c++14 } }
// { dg-options "-Wpedantic" }
template <class,class> struct same;
template <class T> struct same<T,T> { };
int main()
{
same<decltype(0i),__complex int>{}; // { dg-warning "literal operator" }
// { dg-message "complex_literals" "" { target *-*-* } .-1 }
// { dg-message "built-in" "" { target *-*-* } .-2 }
same<decltype(0.0i),__complex double>{}; // { dg-warning "literal operator" }
// { dg-message "complex_literals" "" { target *-*-* } .-1 }
// { dg-message "built-in" "" { target *-*-* } .-2 }
same<decltype(0.0if),__complex float>{}; // { dg-warning "literal operator" }
// { dg-message "complex_literals" "" { target *-*-* } .-1 }
// { dg-message "built-in" "" { target *-*-* } .-2 }
same<decltype(0.0il),__complex long double>{}; // { dg-warning "literal operator" }
// { dg-message "complex_literals" "" { target *-*-* } .-1 }
// { dg-message "built-in" "" { target *-*-* } .-2 }
}

View File

@ -0,0 +1,14 @@
// PR c++/79228
// { dg-do compile { target c++14 } }
// { dg-options "" }
template <class,class> struct same;
template <class T> struct same<T,T> { };
int main()
{
same<decltype(0i),__complex int>{};
same<decltype(0.0i),__complex double>{};
same<decltype(0.0if),__complex float>{};
same<decltype(0.0il),__complex long double>{};
}

View File

@ -1,3 +1,9 @@
2017-12-01 Jason Merrill <jason@redhat.com>
PR c++/79228 - extensions hide C++14 complex literal operators
* expr.c (interpret_float_suffix): Ignore 'i' in C++14 and up.
(interpret_int_suffix): Likewise.
2017-11-28 David Malcolm <dmalcolm@redhat.com>
PR c/82050

View File

@ -90,6 +90,8 @@ static cpp_num parse_has_include (cpp_reader *, enum include_type);
static unsigned int
interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
{
size_t orig_len = len;
const uchar *orig_s = s;
size_t flags;
size_t f, d, l, w, q, i, fn, fnx, fn_bits;
@ -269,8 +271,20 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
if (fn && fn_bits == 96)
return 0;
if (i && !CPP_OPTION (pfile, ext_numeric_literals))
return 0;
if (i)
{
if (!CPP_OPTION (pfile, ext_numeric_literals))
return 0;
/* In C++14 and up these suffixes are in the standard library, so treat
them as user-defined literals. */
if (CPP_OPTION (pfile, cplusplus)
&& CPP_OPTION (pfile, lang) > CLK_CXX11
&& (!memcmp (orig_s, "i", orig_len)
|| !memcmp (orig_s, "if", orig_len)
|| !memcmp (orig_s, "il", orig_len)))
return 0;
}
if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals))
return 0;
@ -299,6 +313,7 @@ cpp_interpret_float_suffix (cpp_reader *pfile, const char *s, size_t len)
static unsigned int
interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
{
size_t orig_len = len;
size_t u, l, i;
u = l = i = 0;
@ -321,8 +336,20 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
if (l > 2 || u > 1 || i > 1)
return 0;
if (i && !CPP_OPTION (pfile, ext_numeric_literals))
return 0;
if (i)
{
if (!CPP_OPTION (pfile, ext_numeric_literals))
return 0;
/* In C++14 and up these suffixes are in the standard library, so treat
them as user-defined literals. */
if (CPP_OPTION (pfile, cplusplus)
&& CPP_OPTION (pfile, lang) > CLK_CXX11
&& (!memcmp (s, "i", orig_len)
|| !memcmp (s, "if", orig_len)
|| !memcmp (s, "il", orig_len)))
return 0;
}
return ((i ? CPP_N_IMAGINARY : 0)
| (u ? CPP_N_UNSIGNED : 0)