aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-12-01 15:19:07 -0500
committerJason Merrill <jason@gcc.gnu.org>2017-12-01 15:19:07 -0500
commitf2b8b8adbae9968ac30742498a21a92ac70523ff (patch)
tree2f9f105e39188cba5d4687ec6140a48fec7e11f9 /gcc
parent0951904f491340404284480603f932bd551aec80 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/parser.c72
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/complex_literals1.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/complex_literals1a.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/complex_literals2.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/complex_literals2a.C14
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>{};
+}