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 /gcc | |
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
Diffstat (limited to 'gcc')
-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 |
8 files changed, 138 insertions, 8 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>{}; +} |