From 962c5679b3c61f09b96ab72e474a897b870fd2c1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 5 Jan 2017 22:12:02 +0100 Subject: [PATCH] re PR c++/78890 (ICE on invalid reference type in union) PR c++/78890 * class.c (check_field_decls): Diagnose REFERENCE_TYPE fields in unions even for C++11 and later. * g++.dg/init/ref14.C: Expect error even in C++11 and later. * g++.dg/init/union1.C: Likewise. * g++.dg/cpp0x/union6.C: Expect errors. * g++.dg/cpp0x/union8.C: New test. * g++.dg/cpp0x/pr78890-1.C: New test. * g++.dg/cpp0x/pr78890-2.C: New test. From-SVN: r244112 --- gcc/cp/ChangeLog | 6 ++++ gcc/cp/class.c | 16 ++++++---- gcc/testsuite/ChangeLog | 10 ++++++ gcc/testsuite/g++.dg/cpp0x/pr78890-1.C | 13 ++++++++ gcc/testsuite/g++.dg/cpp0x/pr78890-2.C | 44 ++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/union6.C | 4 +-- gcc/testsuite/g++.dg/cpp0x/union8.C | 26 +++++++++++++++ gcc/testsuite/g++.dg/init/ref14.C | 2 +- gcc/testsuite/g++.dg/init/union1.C | 2 +- 9 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr78890-1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr78890-2.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/union8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 35f0a2222ac..5bc7d521768 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2017-01-05 Jakub Jelinek + + PR c++/78890 + * class.c (check_field_decls): Diagnose REFERENCE_TYPE fields in + unions even for C++11 and later. + 2017-01-05 Nathan Sidwell PR c++/78765 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 1c6b401ec65..b7c26a1829f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3759,25 +3759,27 @@ check_field_decls (tree t, tree *access_decls, /* When this goes into scope, it will be a non-local reference. */ DECL_NONLOCAL (x) = 1; - if (TREE_CODE (t) == UNION_TYPE - && cxx_dialect < cxx11) + if (TREE_CODE (t) == UNION_TYPE) { /* [class.union] (C++98) If a union contains a static data member, or a member of reference type, the program is ill-formed. - In C++11 this limitation doesn't exist anymore. */ - if (VAR_P (x)) + In C++11 [class.union] says: + If a union contains a non-static data member of reference type + the program is ill-formed. */ + if (VAR_P (x) && cxx_dialect < cxx11) { error ("in C++98 %q+D may not be static because it is " "a member of a union", x); continue; } - if (TREE_CODE (type) == REFERENCE_TYPE) + if (TREE_CODE (type) == REFERENCE_TYPE + && TREE_CODE (x) == FIELD_DECL) { - error ("in C++98 %q+D may not have reference type %qT " - "because it is a member of a union", x, type); + error ("non-static data member %q+D in a union may not " + "have reference type %qT", x, type); continue; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index de407c40250..c992d713921 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2017-01-05 Jakub Jelinek + + PR c++/78890 + * g++.dg/init/ref14.C: Expect error even in C++11 and later. + * g++.dg/init/union1.C: Likewise. + * g++.dg/cpp0x/union6.C: Expect errors. + * g++.dg/cpp0x/union8.C: New test. + * g++.dg/cpp0x/pr78890-1.C: New test. + * g++.dg/cpp0x/pr78890-2.C: New test. + 2017-01-05 David Edelsohn * gcc.target/powerpc/pr71670.c: Require p9vector. diff --git a/gcc/testsuite/g++.dg/cpp0x/pr78890-1.C b/gcc/testsuite/g++.dg/cpp0x/pr78890-1.C new file mode 100644 index 00000000000..6fccc4fbe0d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr78890-1.C @@ -0,0 +1,13 @@ +// PR c++/78890 +// { dg-do compile { target c++11 } } + +int +main() +{ + union { + int a; + int &b = a; // { dg-error "may not have reference type" } + }; + a = 1; + auto c = b + 1; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/pr78890-2.C b/gcc/testsuite/g++.dg/cpp0x/pr78890-2.C new file mode 100644 index 00000000000..0a11bf4bc62 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr78890-2.C @@ -0,0 +1,44 @@ +// PR c++/78890 +// { dg-do compile { target c++11 } } + +template +int +foo () +{ + union { + int a; + int &b = a; // { dg-error "may not have reference type" } + }; + a = 1; + auto c = b + 1; + return c; +} + +template +T +bar () +{ + union { + T a; + T &b = a; // { dg-error "may not have reference type" } + }; + a = 1; + auto c = b + 1; + return c; +} + +template +T baz() +{ + union { + T a; + U b = a; // { dg-error "may not have reference type" } + }; + a = 1; + auto c = b + 1; + return c; +} + +int a = foo (); +int b = bar (); +int c = baz (); diff --git a/gcc/testsuite/g++.dg/cpp0x/union6.C b/gcc/testsuite/g++.dg/cpp0x/union6.C index 1706da9db59..408755e3195 100644 --- a/gcc/testsuite/g++.dg/cpp0x/union6.C +++ b/gcc/testsuite/g++.dg/cpp0x/union6.C @@ -12,9 +12,9 @@ union Test2 { const int Test2::kConstant = 10; union Test3 { - int& kConstant; + int& kConstant; // { dg-error "may not have reference type" } }; union Test4 { - const int& kConstant = 10; + const int& kConstant = 10; // { dg-error "may not have reference type" } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/union8.C b/gcc/testsuite/g++.dg/cpp0x/union8.C new file mode 100644 index 00000000000..11b9656f745 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/union8.C @@ -0,0 +1,26 @@ +// PR c++/78890 +// { dg-do compile { target c++11 } } + +union Test1 { + static int kConstant; +}; + +union Test2 { + static const int kConstant; +}; + +const int Test2::kConstant = 10; + +int k; + +union Test3 { + static int& kRef; +}; + +int& Test3::kRef = k; + +union Test4 { + static const int& kRef; +}; + +const int& Test4::kRef = 10; diff --git a/gcc/testsuite/g++.dg/init/ref14.C b/gcc/testsuite/g++.dg/init/ref14.C index 2e522c19566..6ac42415b43 100644 --- a/gcc/testsuite/g++.dg/init/ref14.C +++ b/gcc/testsuite/g++.dg/init/ref14.C @@ -4,7 +4,7 @@ union A { - int &i; // { dg-error "may not have reference type" "" { target { ! c++11 } } } + int &i; // { dg-error "may not have reference type" } }; void foo() diff --git a/gcc/testsuite/g++.dg/init/union1.C b/gcc/testsuite/g++.dg/init/union1.C index ea88346ebe8..ccae3786b12 100644 --- a/gcc/testsuite/g++.dg/init/union1.C +++ b/gcc/testsuite/g++.dg/init/union1.C @@ -1,5 +1,5 @@ // PR c++/14401 union U { - int& i; // { dg-error "reference type" "" { target { ! c++11 } } } + int& i; // { dg-error "reference type" } }; -- 2.30.2