[gcc r15-1768] c++: Relax too strict assert in stabilize_expr [PR111160]

2024-07-02 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:49058fecbfd09a3354064e7d695b4a1056ce7547

commit r15-1768-g49058fecbfd09a3354064e7d695b4a1056ce7547
Author: Simon Martin 
Date:   Tue Jun 11 11:44:28 2024 +0200

c++: Relax too strict assert in stabilize_expr [PR60]

The case in the ticket is an ICE on invalid due to an assert in 
stabilize_expr,
but the underlying issue can actually trigger on this *valid* code:

=== cut here ===
struct TheClass {
  TheClass() {}
  TheClass(volatile TheClass& t) {}
  TheClass operator=(volatile TheClass& t) volatile { return t; }
};
void the_func() {
  volatile TheClass x, y, z;
  (false ? x : y) = z;
}
=== cut here ===

The problem is that stabilize_expr asserts that it returns an expression
without TREE_SIDE_EFFECTS, which can't be if the involved type is volatile.

This patch relaxes the assert to accept having TREE_THIS_VOLATILE on the
returned expression.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/60

gcc/cp/ChangeLog:

* tree.cc (stabilize_expr): Stabilized expressions can have
TREE_SIDE_EFFECTS if they're volatile.

gcc/testsuite/ChangeLog:

* g++.dg/overload/error8.C: New test.
* g++.dg/overload/volatile2.C: New test.

Diff:
---
 gcc/cp/tree.cc|  2 +-
 gcc/testsuite/g++.dg/overload/error8.C|  9 +
 gcc/testsuite/g++.dg/overload/volatile2.C | 12 
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 28648c14c6d..dfd4a3a948b 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5969,7 +5969,7 @@ stabilize_expr (tree exp, tree* initp)
 }
   *initp = init_expr;
 
-  gcc_assert (!TREE_SIDE_EFFECTS (exp));
+  gcc_assert (!TREE_SIDE_EFFECTS (exp) || TREE_THIS_VOLATILE (exp));
   return exp;
 }
 
diff --git a/gcc/testsuite/g++.dg/overload/error8.C 
b/gcc/testsuite/g++.dg/overload/error8.C
new file mode 100644
index 000..a7e745860e0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/error8.C
@@ -0,0 +1,9 @@
+// PR c++/60
+// { dg-do compile { target c++11 } }
+
+class TheClass {}; // { dg-error "discards|bind|discards|bind" }
+void the_func() {
+  TheClass x;
+  volatile TheClass y;
+  (false ? x : x) = y; // { dg-error "ambiguous|ambiguous" }
+}
diff --git a/gcc/testsuite/g++.dg/overload/volatile2.C 
b/gcc/testsuite/g++.dg/overload/volatile2.C
new file mode 100644
index 000..9f27357aed6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/volatile2.C
@@ -0,0 +1,12 @@
+// PR c++/60
+// { dg-do compile { target c++11 } }
+
+struct TheClass {
+  TheClass() {}
+  TheClass(volatile TheClass& t) {}
+  TheClass operator=(volatile TheClass& t) volatile { return t; }
+};
+void the_func() {
+  volatile TheClass x, y, z;
+  (false ? x : y) = z;
+}


[gcc r15-847] Add testcase for PR c++/105229: ICE in lookup_template_class_1

2024-05-27 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:88c9b96b2800ddb7a499bd10abaa9441a471d5fe

commit r15-847-g88c9b96b2800ddb7a499bd10abaa9441a471d5fe
Author: Simon Martin 
Date:   Fri May 24 10:56:36 2024 +0200

Add testcase for PR c++/105229: ICE in lookup_template_class_1

The test case in PR c++/105229 has been fixed since 11.4 (via
PR c++/106024) - the attached patch simply adds the case to
the test suite.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/105229

gcc/testsuite/ChangeLog:

* g++.dg/parse/crash72.C: New test.

Diff:
---
 gcc/testsuite/g++.dg/parse/crash72.C | 12 
 1 file changed, 12 insertions(+)

diff --git a/gcc/testsuite/g++.dg/parse/crash72.C 
b/gcc/testsuite/g++.dg/parse/crash72.C
new file mode 100644
index 000..df469e20f28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash72.C
@@ -0,0 +1,12 @@
+// PR c++/105229
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-Wno-missing-template-keyword" }
+
+template  void bar ()
+{
+  []  {}.operator () <> (); // { dg-error "expected primary-expression" }
+}
+void foo ()
+{
+  bar ();
+}


[gcc r15-972] Fix PR c++/109958: ICE taking the address of bound static member function brought into derived class

2024-06-02 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:47827293551a3ec339617678c8e938c8ca3790f1

commit r15-972-g47827293551a3ec339617678c8e938c8ca3790f1
Author: Simon Martin 
Date:   Sun Jun 2 17:45:04 2024 +0200

Fix PR c++/109958: ICE taking the address of bound static member function 
brought into derived class by using-declaration

We currently ICE upon the following because we don't properly handle the
overload created for B::f through the using statement.

=== cut here ===
struct B { static int f(); };
struct D : B { using B::f; };
void f(D d) { &d.f; }
=== cut here ===

This patch makes build_class_member_access_expr and cp_build_addr_expr_1 
handle
such overloads, and fixes the PR.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/109958

gcc/cp/ChangeLog:

* typeck.cc (build_class_member_access_expr): Handle single 
OVERLOADs.
(cp_build_addr_expr_1): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/overload/using6.C: New test.

Diff:
---
 gcc/cp/typeck.cc   | 5 +
 gcc/testsuite/g++.dg/overload/using6.C | 5 +
 2 files changed, 10 insertions(+)

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 1b7a31d32f3..5970ac3d398 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -3025,6 +3025,8 @@ build_class_member_access_expr (cp_expr object, tree 
member,
 know the type of the expression.  Otherwise, we must wait
 until overload resolution has been performed.  */
   functions = BASELINK_FUNCTIONS (member);
+  if (TREE_CODE (functions) == OVERLOAD && OVL_SINGLE_P (functions))
+   functions = OVL_FIRST (functions);
   if (TREE_CODE (functions) == FUNCTION_DECL
  && DECL_STATIC_FUNCTION_P (functions))
type = TREE_TYPE (functions);
@@ -7333,6 +7335,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, 
tsubst_flags_t complain)
 {
   tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
 
+  if (TREE_CODE (fn) == OVERLOAD && OVL_SINGLE_P (fn))
+   fn = OVL_FIRST (fn);
+
   /* We can only get here with a single static member
 function.  */
   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
diff --git a/gcc/testsuite/g++.dg/overload/using6.C 
b/gcc/testsuite/g++.dg/overload/using6.C
new file mode 100644
index 000..4f89f68a30f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/using6.C
@@ -0,0 +1,5 @@
+// PR c++/109958
+
+struct B { static int f(); };
+struct D : B { using B::f; };
+void f(D d) { &d.f; }


[gcc r15-1016] Fix PR c++/111106: missing ; causes internal compiler error

2024-06-04 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:cfbd8735359d84a2d716549415eac70e885167bf

commit r15-1016-gcfbd8735359d84a2d716549415eac70e885167bf
Author: Simon Martin 
Date:   Fri May 24 17:00:17 2024 +0200

Fix PR c++/06: missing ; causes internal compiler error

We currently fail upon the following because an assert in dependent_type_p
fails for f's parameter

=== cut here ===
consteval int id (int i) { return i; }
constexpr int
f (auto i) requires requires { id (i) } { return i; }
void g () { f (42); }
=== cut here ===

This patch fixes this by relaxing the assert to pass during error recovery.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/06

gcc/cp/ChangeLog:

* pt.cc (dependent_type_p): Don't fail assert during error recovery.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/consteval37.C: New test.

Diff:
---
 gcc/cp/pt.cc |  3 ++-
 gcc/testsuite/g++.dg/cpp2a/consteval37.C | 16 
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index dfce1b3c359..edb94a000ea 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -28019,7 +28019,8 @@ dependent_type_p (tree type)
   /* If we are not processing a template, then nobody should be
 providing us with a dependent type.  */
   gcc_assert (type);
-  gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type));
+  gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type)
+ || seen_error());
   return false;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval37.C 
b/gcc/testsuite/g++.dg/cpp2a/consteval37.C
new file mode 100644
index 000..519d83d9bf8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval37.C
@@ -0,0 +1,16 @@
+// PR c++/06
+// { dg-do compile { target c++20 } }
+
+consteval int id (int i) { return i; }
+
+constexpr int f (auto i)
+  requires requires { id (i) } // { dg-error "expected" }
+{
+  return i;
+}
+
+void g () {
+  f (42);
+}
+
+// { dg-excess-errors "" }


[gcc r15-1017] Add missing space after seen_error in gcc/cp/pt.cc

2024-06-04 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:54e5cbcd82e36f5aa8205b56880821eea25701ae

commit r15-1017-g54e5cbcd82e36f5aa8205b56880821eea25701ae
Author: Simon Martin 
Date:   Tue Jun 4 17:27:25 2024 +0200

Add missing space after seen_error in gcc/cp/pt.cc

I realized that I committed a change with a missing space after seen_error.
This fixes it, as well as another occurrence in the same file.

Apologies for the mistake - I'll commit this as obvious.

gcc/cp/ChangeLog:

* pt.cc (tsubst_expr): Add missing space after seen_error.
(dependent_type_p): Likewise.

Diff:
---
 gcc/cp/pt.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index edb94a000ea..8cbcf7cdf7a 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20918,7 +20918,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
   be using lambdas anyway, so it's ok to be
   stricter.  Be strict with C++20 template-id ADL too.
   And be strict if we're already failing anyway.  */
-   bool strict = in_lambda || template_id_p || seen_error();
+   bool strict = in_lambda || template_id_p || seen_error ();
bool diag = true;
if (strict)
  error_at (cp_expr_loc_or_input_loc (t),
@@ -28020,7 +28020,7 @@ dependent_type_p (tree type)
 providing us with a dependent type.  */
   gcc_assert (type);
   gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type)
- || seen_error());
+ || seen_error ());
   return false;
 }


[gcc r15-1019] c++: Add testcase for PR103338

2024-06-04 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:126ccf8ffc46865accec22a2789f09abd98c1d85

commit r15-1019-g126ccf8ffc46865accec22a2789f09abd98c1d85
Author: Simon Martin 
Date:   Tue Jun 4 11:59:31 2024 +0200

c++: Add testcase for PR103338

The case in that PR used to ICE until commit f04dc89. This patch simply adds
the case to the testsuite.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/103388

gcc/testsuite/ChangeLog:

* g++.dg/parse/crash73.C: New test.

Diff:
---
 gcc/testsuite/g++.dg/parse/crash73.C | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/gcc/testsuite/g++.dg/parse/crash73.C 
b/gcc/testsuite/g++.dg/parse/crash73.C
new file mode 100644
index 000..97b8b5e8325
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash73.C
@@ -0,0 +1,19 @@
+// PR c++/103338
+// { dg-do compile { target c++11 } }
+
+template
+struct zip_view {
+  struct Iterator;
+};
+
+template
+struct zip_transform_view;
+
+template
+struct zip_view::Iterator { // { dg-error "no class template" }
+  template
+  template
+  friend class zip_transform_view::Iterator;
+};
+
+zip_view<>::Iterator iter;


[gcc r15-1102] lto: Fix build on MacOS

2024-06-07 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:a3d68b5155018817dd7eef5abbaeadf3959b8e5e

commit r15-1102-ga3d68b5155018817dd7eef5abbaeadf3959b8e5e
Author: Simon Martin 
Date:   Fri Jun 7 16:14:58 2024 +0200

lto: Fix build on MacOS

The build fails on x86_64-apple-darwin19.6.0 starting with 5b6d5a886ee 
because
vector is included after system.h and runs into poisoned identifiers.

This patch fixes this by defining INCLUDE_VECTOR before including system.h.

Validated by doing a full build on x86_64-apple-darwin19.6.0.

gcc/lto/ChangeLog:

* lto-partition.cc: Define INCLUDE_VECTOR to avoid running into
poisoned identifiers.

Diff:
---
 gcc/lto/lto-partition.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/lto/lto-partition.cc b/gcc/lto/lto-partition.cc
index 44b457d0b2a..2238650fa0e 100644
--- a/gcc/lto/lto-partition.cc
+++ b/gcc/lto/lto-partition.cc
@@ -18,6 +18,7 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 #include "config.h"
+#define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
 #include "target.h"
@@ -38,7 +39,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "lto-partition.h"
 
 #include 
-#include 
 
 vec ltrans_partitions;


[gcc r15-1105] c++: Handle erroneous DECL_LOCAL_DECL_ALIAS in duplicate_decls [PR107575]

2024-06-07 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:0ce138694a6b40708a80691fa4003f6af1defa49

commit r15-1105-g0ce138694a6b40708a80691fa4003f6af1defa49
Author: Simon Martin 
Date:   Tue Jun 4 21:20:23 2024 +0200

c++: Handle erroneous DECL_LOCAL_DECL_ALIAS in duplicate_decls [PR107575]

We currently ICE upon the following because we don't properly handle local
functions with an error_mark_node as DECL_LOCAL_DECL_ALIAS in 
duplicate_decls.

=== cut here ===
void f (void) {
  virtual int f (void) const;
  virtual int f (void);
}
=== cut here ===

This patch fixes this by checking for error_mark_node.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/107575

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Check for error_mark_node
DECL_LOCAL_DECL_ALIAS.

gcc/testsuite/ChangeLog:

* g++.dg/parse/crash74.C: New test.

Diff:
---
 gcc/cp/decl.cc   | 11 +++
 gcc/testsuite/g++.dg/parse/crash74.C | 11 +++
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d481e1ec074..03deb1493a4 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2792,10 +2792,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
  retrofit_lang_decl (newdecl);
  tree alias = DECL_LOCAL_DECL_ALIAS (newdecl)
= DECL_LOCAL_DECL_ALIAS (olddecl);
- DECL_ATTRIBUTES (alias)
-   = (*targetm.merge_decl_attributes) (alias, newdecl);
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
-   merge_attribute_bits (newdecl, alias);
+ if (alias != error_mark_node)
+   {
+ DECL_ATTRIBUTES (alias)
+   = (*targetm.merge_decl_attributes) (alias, newdecl);
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+   merge_attribute_bits (newdecl, alias);
+   }
}
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/crash74.C 
b/gcc/testsuite/g++.dg/parse/crash74.C
new file mode 100644
index 000..a7ba5094be6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash74.C
@@ -0,0 +1,11 @@
+// PR c++/107575
+
+void f (void) {
+  virtual int f (void) const; // { dg-line line_4 }
+  virtual int f (void); // { dg-line line_5 }
+}
+
+// { dg-error "outside class declaration" {} { target *-*-* } line_4 }
+// { dg-error "cannot have cv-qualifier" {} { target *-*-* } line_4 }
+// { dg-error "ambiguating new declaration of" {} { target *-*-* } line_4 }
+// { dg-error "outside class declaration" {} { target *-*-* } line_5 }


[gcc r15-1114] c++: Make *_cast<*> parsing more robust to errors [PR108438]

2024-06-08 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:2c9643c27ecddb7f597d34009d89e932b4aca58e

commit r15-1114-g2c9643c27ecddb7f597d34009d89e932b4aca58e
Author: Simon Martin 
Date:   Fri Jun 7 11:21:07 2024 +0200

c++: Make *_cast<*> parsing more robust to errors [PR108438]

We ICE upon the following when trying to emit a -Wlogical-not-parentheses
warning:

=== cut here ===
template  T foo (T arg, T& ref, T* ptr) {
  int a = 1;
  return static_cast(a);
}
=== cut here ===

This patch makes *_cast<*> parsing more robust by skipping to the closing 
'>'
upon error in the target type.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/108438

gcc/cp/ChangeLog:

* parser.cc (cp_parser_postfix_expression): Use
cp_parser_require_end_of_template_parameter_list to skip to the 
closing
'>' upon error parsing the target type of *_cast<*> expressions.

gcc/testsuite/ChangeLog:

* g++.dg/parse/crash75.C: New test.

Diff:
---
 gcc/cp/parser.cc | 2 +-
 gcc/testsuite/g++.dg/parse/crash75.C | 9 +
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index bc4a2359153..9f43a776889 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -7569,7 +7569,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
  NULL);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
/* Look for the closing `>'.  */
-   cp_parser_require (parser, CPP_GREATER, RT_GREATER);
+   cp_parser_require_end_of_template_parameter_list (parser);
/* Restore the old message.  */
parser->type_definition_forbidden_message = saved_message;
 
diff --git a/gcc/testsuite/g++.dg/parse/crash75.C 
b/gcc/testsuite/g++.dg/parse/crash75.C
new file mode 100644
index 000..81a16e35b14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash75.C
@@ -0,0 +1,9 @@
+// PR c++/108438
+// { dg-options "-Wlogical-not-parentheses" }
+
+template 
+T foo (T arg, T& ref, T* ptr)
+{
+  int a = 1;
+  return static_cast(a); // { dg-error "expected" }
+}


[gcc r15-2792] c++: Fix ICE on valid involving variadic constructor [PR111592]

2024-08-07 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:a1999cbc816ecd382c7af4ca44153379de49dcaf

commit r15-2792-ga1999cbc816ecd382c7af4ca44153379de49dcaf
Author: Simon Martin 
Date:   Wed Aug 7 12:45:12 2024 +0200

c++: Fix ICE on valid involving variadic constructor [PR111592]

We currently ICE upon the following valid code, due to the fix made through
commit 9efe5fbde1e8

=== cut here ===
struct ignore { ignore(...) {} };
template
void InternalCompilerError(Args... args)
{ ignore{ ignore(args) ... }; }
int main() { InternalCompilerError(0, 0); }
=== cut here ===

Change 9efe5fbde1e8 avoids infinite recursion in build_over_call by 
returning
error_mark_node if one invokes ignore::ignore(...) with an argument of type
ignore, because otherwise we end up calling convert_arg_to_ellipsis for that
argument, and recurse into build_over_call with the exact same parameters.

This patch tightens the condition to only return error_mark_node if there's 
one
and only one parameter to the call being processed - otherwise we won't
infinitely recurse.

Successfully tested on x86_64-pc-linux-gnu.

PR c++/111592

gcc/cp/ChangeLog:

* call.cc (build_over_call): Only error out if there's a single
parameter of type A in a call to A::A(...).

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/variadic186.C: New test.

Diff:
---
 gcc/cp/call.cc   |  1 +
 gcc/testsuite/g++.dg/cpp0x/variadic186.C | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index a75e2e5e3afd..67d38e2a78a7 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10365,6 +10365,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
  a = decay_conversion (a, complain);
}
   else if (DECL_CONSTRUCTOR_P (fn)
+  && vec_safe_length (args) == 1
   && same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (fn),
 TREE_TYPE (a)))
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic186.C 
b/gcc/testsuite/g++.dg/cpp0x/variadic186.C
new file mode 100644
index ..4a25a1a96bf8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic186.C
@@ -0,0 +1,11 @@
+// PR c++/111592
+// { dg-do compile { target c++11 } }
+
+struct ignore { ignore(...) {} };
+
+template
+void InternalCompilerError(Args... args)
+{ ignore{ ignore(args) ... }; }
+
+int main()
+{ InternalCompilerError(0, 0); }


[gcc r15-2855] c++: Don't accept multiple enum definitions within template class [PR115806]

2024-08-09 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:786ebbd6058540b2110da16a693f0c582c11413c

commit r15-2855-g786ebbd6058540b2110da16a693f0c582c11413c
Author: Simon Martin 
Date:   Thu Aug 8 14:59:49 2024 +0200

c++: Don't accept multiple enum definitions within template class [PR115806]

We have been accepting the following invalid code since revision 557831a91df

=== cut here ===
template  struct S {
  enum E { a };
  enum E { b };
};
S s;
=== cut here ===

The problem is that start_enum will set OPAQUE_ENUM_P to true even if it
retrieves an existing definition for the enum, which causes the redefinition
check in cp_parser_enum_specifier to be bypassed.

This patch only sets OPAQUE_ENUM_P and ENUM_FIXED_UNDERLYING_TYPE_P when
actually pushing a new tag for the enum.

PR c++/115806

gcc/cp/ChangeLog:

* decl.cc (start_enum): Only set OPAQUE_ENUM_P and
ENUM_FIXED_UNDERLYING_TYPE_P when pushing a new tag.

gcc/testsuite/ChangeLog:

* g++.dg/parse/enum15.C: New test.

Diff:
---
 gcc/cp/decl.cc  | 22 --
 gcc/testsuite/g++.dg/parse/enum15.C |  9 +
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index a468bfdb7b67..f23b635aec9f 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -17059,22 +17059,24 @@ start_enum (tree name, tree enumtype, tree 
underlying_type,
  enumtype = cxx_make_type (ENUMERAL_TYPE);
  enumtype = pushtag (name, enumtype);
 
- /* std::byte aliases anything.  */
- if (enumtype != error_mark_node
- && TYPE_CONTEXT (enumtype) == std_node
- && !strcmp ("byte", TYPE_NAME_STRING (enumtype)))
-   TYPE_ALIAS_SET (enumtype) = 0;
+ if (enumtype != error_mark_node)
+   {
+ /* The enum is considered opaque until the opening '{' of the
+enumerator list.  */
+ SET_OPAQUE_ENUM_P (enumtype, true);
+ ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) = !! underlying_type;
+
+ /* std::byte aliases anything.  */
+ if (TYPE_CONTEXT (enumtype) == std_node
+ && !strcmp ("byte", TYPE_NAME_STRING (enumtype)))
+   TYPE_ALIAS_SET (enumtype) = 0;
+   }
}
   else
  enumtype = xref_tag (enum_type, name);
 
   if (enumtype == error_mark_node)
return error_mark_node;
-
-  /* The enum is considered opaque until the opening '{' of the
-enumerator list.  */
-  SET_OPAQUE_ENUM_P (enumtype, true);
-  ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) = !! underlying_type;
 }
 
   SET_SCOPED_ENUM_P (enumtype, scoped_enum_p);
diff --git a/gcc/testsuite/g++.dg/parse/enum15.C 
b/gcc/testsuite/g++.dg/parse/enum15.C
new file mode 100644
index ..d19262156b91
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/enum15.C
@@ -0,0 +1,9 @@
+// PR c++/115806
+// { dg-do compile }
+
+template 
+struct S {
+  enum E { a }; // { dg-note "previous definition" }
+  enum E { b }; // { dg-error "multiple definition" }
+};
+S s;


[gcc r15-3145] c++: Add testcase for (now fixed) regression [PR113746]

2024-08-24 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:1d09ccc4a5fe7c9a3dd37fcef34c1523a5c95819

commit r15-3145-g1d09ccc4a5fe7c9a3dd37fcef34c1523a5c95819
Author: Simon Martin 
Date:   Fri Aug 23 10:49:31 2024 +0200

c++: Add testcase for (now fixed) regression [PR113746]

The case in PR113746 used to ICE until commit r15-123-gf04dc89a991ddc.
This patch simply adds the case to the testsuite.

PR c++/113746

gcc/testsuite/ChangeLog:

* g++.dg/parse/crash76.C: New test.

Diff:
---
 gcc/testsuite/g++.dg/parse/crash76.C | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/gcc/testsuite/g++.dg/parse/crash76.C 
b/gcc/testsuite/g++.dg/parse/crash76.C
new file mode 100644
index ..6fbd1fa9f7eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash76.C
@@ -0,0 +1,6 @@
+// PR c++/113746
+// { dg-do compile }
+
+template struct S { // { dg-error "not been declared" }
+  enum { e0 = 0, e00 = e0 };
+};


[gcc r15-3195] c++: Check template parameters in member class template specialization [PR115716]

2024-08-26 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:26ee954476bef7328d2cf45928c3c9b84df77178

commit r15-3195-g26ee954476bef7328d2cf45928c3c9b84df77178
Author: Simon Martin 
Date:   Sun Aug 25 21:59:31 2024 +0200

c++: Check template parameters in member class template specialization 
[PR115716]

We currently ICE upon the following invalid code, because we don't check
that the template parameters in a member class template specialization
are correct.

=== cut here ===
template  struct x {
  template  struct y {
typedef T result2;
  };
};
template<> template struct x::y {
  typedef double result2;
};
int main() {
  x::y::result2 xxx2;
}
=== cut here ===

This patch fixes the PR by calling redeclare_class_template.

PR c++/115716

gcc/cp/ChangeLog:

* pt.cc (maybe_process_partial_specialization): Call
redeclare_class_template.

gcc/testsuite/ChangeLog:

* g++.dg/template/spec42.C: New test.
* g++.dg/template/spec43.C: New test.

Diff:
---
 gcc/cp/pt.cc   |  5 +
 gcc/testsuite/g++.dg/template/spec42.C | 17 +
 gcc/testsuite/g++.dg/template/spec43.C | 18 ++
 3 files changed, 40 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index bc3ad5edcc59..24a6241d3a51 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1173,6 +1173,11 @@ maybe_process_partial_specialization (tree type)
   type, inst);
}
 
+ /* Make sure that the specialization is valid.  */
+ if (!redeclare_class_template (type, current_template_parms,
+current_template_constraints ()))
+   return error_mark_node;
+
  /* Mark TYPE as a specialization.  And as a result, we only
 have one level of template argument for the innermost
 class template.  */
diff --git a/gcc/testsuite/g++.dg/template/spec42.C 
b/gcc/testsuite/g++.dg/template/spec42.C
new file mode 100644
index ..cac1264fc9f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec42.C
@@ -0,0 +1,17 @@
+// PR c++/115716
+// { dg-do compile }
+template  struct x {
+  template  struct y { // { dg-note "used 1 template parameter" }
+typedef T result2;
+  };
+};
+
+template<>
+template
+struct x::y { // { dg-error "redeclared with 2 template parameters" }
+  typedef double result2;
+};
+
+int main() {
+  x::y::result2 xxx2;
+}
diff --git a/gcc/testsuite/g++.dg/template/spec43.C 
b/gcc/testsuite/g++.dg/template/spec43.C
new file mode 100644
index ..d33659dd5063
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec43.C
@@ -0,0 +1,18 @@
+// PR c++/115716
+// { dg-do compile { target c++20 } }
+template  struct x {
+  template  struct y { // { dg-note "original" }
+typedef T result2;
+  };
+};
+
+template<>
+template
+requires true
+struct x::y { // { dg-error "different constraints" }
+  typedef double result2;
+};
+
+int main() {
+  x::y::result2 xxx2;
+}


[gcc r15-3232] c++: Don't show constructor internal name in error message [PR105483]

2024-08-27 Thread Simon Martin via Gcc-cvs
https://gcc.gnu.org/g:02dff52c60e5b89d290147f142f655c7817154c2

commit r15-3232-g02dff52c60e5b89d290147f142f655c7817154c2
Author: Simon Martin 
Date:   Mon Aug 26 14:09:46 2024 +0200

c++: Don't show constructor internal name in error message [PR105483]

We mention 'X::__ct' instead of 'X::X' in the "names the constructor,
not the type" error for this invalid code:

=== cut here ===
struct X {};
void g () {
  X::X x;
}
=== cut here ===

The problem is that we use %<%T::%D%> to build the error message, while
%qE does exactly what we need since we have DECL_CONSTRUCTOR_P. This is
what this patch does.

It also skips until the end of the statement and returns error_mark_node
for this and the preceding if block, to avoid emitting extra (useless)
errors.

PR c++/105483

gcc/cp/ChangeLog:

* parser.cc (cp_parser_expression_statement): Use %qE instead of
incorrect %<%T::%D%>. Skip to end of statement and return
error_mark_node in case of error.

gcc/testsuite/ChangeLog:

* g++.dg/parse/error36.C: Adjust test expectation.
* g++.dg/tc1/dr147.C: Likewise.
* g++.old-deja/g++.other/typename1.C: Likewise.
* g++.dg/diagnostic/pr105483.C: New test.

Diff:
---
 gcc/cp/parser.cc | 14 +-
 gcc/testsuite/g++.dg/diagnostic/pr105483.C   |  7 +++
 gcc/testsuite/g++.dg/parse/error36.C |  4 ++--
 gcc/testsuite/g++.dg/tc1/dr147.C |  2 +-
 gcc/testsuite/g++.old-deja/g++.other/typename1.C |  2 +-
 5 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 28ebf2beb60a..a722641be347 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -13232,18 +13232,22 @@ cp_parser_expression_statement (cp_parser* parser, 
tree in_statement_expr)
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
   && !cp_parser_uncommitted_to_tentative_parse_p (parser))
 {
+  bool has_errored = true;
   if (TREE_CODE (statement) == SCOPE_REF)
error_at (token->location, "need % before %qE because "
  "%qT is a dependent scope",
  statement, TREE_OPERAND (statement, 0));
   else if (is_overloaded_fn (statement)
   && DECL_CONSTRUCTOR_P (get_first_fn (statement)))
+   /* A::A a; */
+   error_at (token->location, "%qE names the constructor, not the type",
+ get_first_fn (statement));
+  else
+   has_errored = false;
+  if (has_errored)
{
- /* A::A a; */
- tree fn = get_first_fn (statement);
- error_at (token->location,
-   "%<%T::%D%> names the constructor, not the type",
-   DECL_CONTEXT (fn), DECL_NAME (fn));
+ cp_parser_skip_to_end_of_statement (parser);
+ return error_mark_node;
}
 }
 
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr105483.C 
b/gcc/testsuite/g++.dg/diagnostic/pr105483.C
new file mode 100644
index ..b935bacea11b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr105483.C
@@ -0,0 +1,7 @@
+// PR c++/105483
+// { dg-do compile }
+
+struct X { };
+void g () {
+  X::X x; // { dg-error "'X::X' names the constructor" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error36.C 
b/gcc/testsuite/g++.dg/parse/error36.C
index bf57a6b68ce8..73b550e3f2ad 100644
--- a/gcc/testsuite/g++.dg/parse/error36.C
+++ b/gcc/testsuite/g++.dg/parse/error36.C
@@ -12,7 +12,7 @@ void f(T t)
 {
   typedef A::foo type;  // { dg-error "typename" }
   A::bar b; // { dg-error "typename" "typename" }
-} // { dg-error "expected ';'" "expected" { target *-*-* } .-1 }
+}
 
 // PR c++/36353
 template  struct B
@@ -20,7 +20,7 @@ template  struct B
   void f()
   {
 A::baz z;   // { dg-error "typename" "typename" }
-  } // { dg-error "expected ';'" "expected" { target *-*-* } .-1 }
+  }
 };
 
 // PR c++/40738
diff --git a/gcc/testsuite/g++.dg/tc1/dr147.C b/gcc/testsuite/g++.dg/tc1/dr147.C
index 6b656491e816..ced18d1879cc 100644
--- a/gcc/testsuite/g++.dg/tc1/dr147.C
+++ b/gcc/testsuite/g++.dg/tc1/dr147.C
@@ -21,7 +21,7 @@ void A::f()
 void f()
 {
   A::A a; // { dg-error "constructor" "constructor" }
-} // { dg-error "" "error cascade" { target *-*-* } .-1 } error cascade
+}
 }
 
 namespace N2 {
diff --git a/gcc/testsuite/g++.old-deja/g++.other/typename1.C 
b/gcc/testsuite/g++.old-deja/g++.other/typename1.C
index 4e1a4a834ddd..0f0f68b1cee2 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/typename1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/typename1.C
@@ -14,4 +14,4 @@ template
 void f()
 {
   Vector::iterator i = 0; // { dg-error "typename" "typename" } missing 
typename
-} // { dg-error "expected" "expected" { target *-*-* } .-1 }
+}