On 9/4/26 2:37 AM, Vladislav Semykin wrote:
Looking good, just a few small issues left.
make -k check-c++-all (8313.7s) 10 to review
expected passes: 619076
unexpected failures: 9
unexpected successes: 1
expected failures: 6012
unresolved testcases: 2
unsupported tests: 23071
FAIL: c-c++-common/analyzer/flex-without-call-summaries.c -std=c++11 at
line 886 (test for warnings, line 885)
XPASS: c-c++-common/analyzer/flex-without-call-summaries.c -std=c++11 PR
analyzer/103546 (test for bogus messages, line 893)
FAIL: c-c++-common/analyzer/flex-without-call-summaries.c -std=c++11 (test
for excess errors)
FAIL: g++.dg/gomp/bad-array-section-10.C -std=c++26 (test for excess
errors)
FAIL: g++.dg/gomp/bad-array-section-10.C -std=c++26 -fimplicit-constexpr
(test for excess errors)
FAIL: g++.dg/guality/pr55665.C -O2 -flto -fno-use-linker-plugin
-flto-partition=none line 23 p == 40
FAIL: g++.dg/modules/xtreme-header-2_a.H -std=c++26 -fimplicit-constexpr
(test for excess errors)
FAIL: g++.dg/modules/xtreme-header-2_c.C -std=c++26 -fimplicit-constexpr
(test for excess errors)
FAIL: g++.dg/modules/xtreme-header-7_a.H -std=c++26 -fimplicit-constexpr
(test for excess errors)
FAIL: g++.dg/modules/xtreme-header_a.H -std=c++26 -fimplicit-constexpr
(test for excess errors)
Yes, these failures are unrelated. In general any unresolved testcases
should also be checked, but they are also unrelated (vect/pr36648.cc
doesn't like -fimplicit-constexpr, I'm adjusting the testcase now). I
generally filter these out by comparing to an earlier baseline testrun
of my own, but you can also check gcc-testresults.
* g++.dg/rtti/pr127132.C: New test.
* g++.dg/cpp0x/pr125886.C: Test capture regardless of typeid
Please name testcases by what they test, not only their PR number, to
enable testing like
cpp0x/constexpr-typeid*.C
cpp2a/constexpr-typeid*.C
template/typeid*.C
cpp0x/lambda/*.C
cpp1y/*lambda*.C
cpp2a/*lambda*.C
that you mention doing. The PR number can come at the end (our usual
convention of a sequence number often causes rebase issues).
+/* Like cp_unevaluated, but for a typeid operand's own unevaluated
+ probe: also conditionally raises cp_unevaluated_typeid_cutoff so
+ this probe does not by itself suppress lambda capture
+ ([expr.prim.lambda.capture]/7), unless something else already
+ makes the context unevaluated. */
+
+class cp_unevaluated_typeid_operand
Instead of a new class, how about making this case a defaulted parameter
to the cp_unevaluated constructor?
@@ -847,8 +847,10 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
this_capture = spec;
}
- /* In unevaluated context this isn't an odr-use, so don't capture. */
- if (cp_unevaluated_operand)
+ /* In unevaluated context this isn't an odr-use, so don't capture.
+ A typeid operand's own probe is capture-transparent
+ ([expr.prim.lambda.capture]/7). */
+ if (cp_unevaluated_operand > cp_unevaluated_typeid_cutoff)
add_capture_p = false;
This function seems to be missing the in_typeid_probe error case
handling from process_outer_var_ref.
The evaluated re-parse is still gated on
!instantiation_dependent_expression_p so mark_used runs for a
non-dependent polymorphic operand inside a generic lambda.
Are there any tests that depend on this? In general mark_used doesn't
do much in a template.
process_outer_var_ref (tree decl, tsubst_flags_t complain,
bool odr_use/*=false*/)
{
+ bool in_typeid_probe = false;
if (cp_unevaluated_operand)
{
tree type = TREE_TYPE (decl);
if (!dependent_type_p (type)
&& variably_modified_type_p (type, NULL_TREE))
/* VLAs are used even in unevaluated context. */;
- else
- /* It's not a use (3.2) if we're in an unevaluated context. */
+ else if (cp_unevaluated_operand > cp_unevaluated_typeid_cutoff
+ || !current_function_decl
+ || !LAMBDA_FUNCTION_P (current_function_decl))
These || are suprising. They seem to be needed in this patch because...
@@ -4788,6 +4799,11 @@ process_outer_var_ref (tree decl, tsubst_flags_t
complain,
return var;
else if (lambda_expr)
{
+ if (in_typeid_probe)
+ /* Don't know yet whether the operand is really evaluated. A
+ real (non-probe) pass will diagnose it if so; if it stays
+ unevaluated there is nothing to diagnose. */
+ return var;
...the in_typeid_probe check is limited to the lambda_expr case. If we
instead check it immediately after the capture case, i.e. before
else if (!odr_use && decl_constant_var_p (var))
then we don't need the || above.
+// [expr.prim.lambda.capture]/7 (P0588R1 / CWG1468): capture must ignore
+// the effect of enclosing typeid expressions. n is not a polymorphic
+// glvalue, so the operand is unevaluated ([expr.typeid]/5), but n is
+// still captured.
+void
+capture_regardless_of_evaluated (int n)
+{
+ auto lam = [=] { (void) typeid (n); };
+ static_assert (sizeof (lam) == sizeof (int), "");
+}
This test isn't reliable; the compiler is allowed to optimize away the
capture if n it isn't actually odr-used, as in
https://eel.is/c++draft/expr.prim#lambda.capture-example-4
I'd actually consider this comparison succeeding to be a (minor)
missed-optimization bug. But let's not mess with that in this patch,
since the assert passed in GCC 16 so fixing the optimization would be a
lambda ABI change that we'd need to control with -fabi-version.
So I guess let's keep this test as it is for now, but add a comment
// If this starts to fail that's OK, the compiler is allowed to optimize
// away the capture, but we need to control it with -fabi-version.
+// [expr.prim.lambda.capture]/7: capture must not depend on whether the
+// typeid operand is evaluated. F is final, so [expr.typeid]/4 would
+// leave typeid (f) unevaluated, but f is still captured. Generic-lambda
+// variant of typeid14.C's final_glvalue.
+
+struct F final { virtual ~F (); };
+
+void
+final_glvalue_generic (F &f)
+{
+ [=](auto a) { (void) typeid (f); }(1);
+}
This could also call foo(), and/or check the size?
+// D::i names no local entity, so [expr.prim.lambda.capture]/7 does not
+// apply and a DR613 non-static member id-expression stays unevaluated
+// (no capture). Generic-lambda variant of typeid14.C's nsm.
+
+struct D { int i; };
+
+void
+nsm_generic ()
+{
+ [=](auto a) { (void) typeid (D::i); }(1);
+}
This could also check the size.
It would also be good to also have tests of 'this' capture, such as if
typeid(D::i) were in a member function of D.
Also the typeid14.C references seem stale, the current patch no longer
modifies that file.
Jason