diff options
author | Jason Merrill <jason@redhat.com> | 2017-12-01 15:19:07 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2017-12-01 15:19:07 -0500 |
commit | f2b8b8adbae9968ac30742498a21a92ac70523ff (patch) | |
tree | 2f9f105e39188cba5d4687ec6140a48fec7e11f9 | |
parent | 0951904f491340404284480603f932bd551aec80 (diff) | |
download | gcc-f2b8b8adbae9968ac30742498a21a92ac70523ff.zip gcc-f2b8b8adbae9968ac30742498a21a92ac70523ff.tar.gz gcc-f2b8b8adbae9968ac30742498a21a92ac70523ff.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/parser.c | 72 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/complex_literals1.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/complex_literals2.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C | 14 | ||||
-rw-r--r-- | libcpp/ChangeLog | 6 | ||||
-rw-r--r-- | libcpp/expr.c | 35 |
10 files changed, 175 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 71f6f3a..89680a2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b469d1c..6e4c243 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C b/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C index 6a8398b..ac2db28 100644 --- a/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C +++ b/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C b/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C index 7caaa7c..ff1e7b6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C +++ b/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals1.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals1.C new file mode 100644 index 0000000..5ae2370 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals1.C @@ -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); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C new file mode 100644 index 0000000..9b61f3a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C @@ -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 } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals2.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals2.C new file mode 100644 index 0000000..6dd9947 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals2.C @@ -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 } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C b/gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C new file mode 100644 index 0000000..9ee9f3f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C @@ -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>{}; +} diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 2250b77..ec049218 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -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 diff --git a/libcpp/expr.c b/libcpp/expr.c index 04675d8..fe9f6b0 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -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) |