On Fri, Jul 24, 2026 at 05:36:01PM +0200, Jakub Jelinek wrote:
> Or do you mean I should always unconditionally try
> cxx_fold_indirect_ref, if that succeeds, nothing to report, we're done,
> if it fails, and tree_strip_nop_conversions (op) is an ADDR_EXPR,
> use a loop to skip over all DECL_FIELD_IS_BASE (because those shouldn't
> be then matching) and just use it to find out what the dynamic
> type is?

I've tried that, but that regresses a few tests:

--- gcc/cp/constexpr.cc.jj      2026-07-24 18:38:54.332025326 +0200
+++ gcc/cp/constexpr.cc 2026-07-24 18:46:44.785857777 +0200
@@ -10259,6 +10259,44 @@ cxx_eval_constant_expression (const cons
              }
          }
 
+       /* [expr.static.cast]/10: A prvalue of type "pointer to cv1 B", where
+          B is a class type, can be converted to a prvalue of type
+          "pointer to cv2 D", where D is a complete class derived from B, ...
+          If the prvalue of type "pointer to cv1 B" points to a B that is
+          actually a base class subobject of an object of type D, the
+          resulting pointer points to the enclosing object of type D.
+          Otherwise, the behavior is undefined.
+          Similarly [expr.static.cast]/2 for references. */
+       if (INDIRECT_TYPE_P (type)
+           && INDIRECT_TYPE_P (TREE_TYPE (op))
+           && COMPLETE_TYPE_P (TREE_TYPE (type))
+           && !integer_zerop (op)
+           && is_properly_derived_from (TREE_TYPE (type),
+                                        TREE_TYPE (TREE_TYPE (op)))
+           && cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), op,
+                                     NULL, jump_target) == NULL_TREE)
+         {
+           tree sop;
+           if (!ctx->quiet
+               && (sop = tree_strip_nop_conversions (op))
+               && TREE_CODE (sop) == ADDR_EXPR)
+             {
+               sop = TREE_OPERAND (sop, 0);
+               while (TREE_CODE (sop) == COMPONENT_REF
+                      && DECL_FIELD_IS_BASE (TREE_OPERAND (sop, 1)))
+                 sop = TREE_OPERAND (sop, 0);
+               error_at (loc, "cannot cast object of dynamic type "
+                              "%qT to type %qT",
+                         strip_array_types (TREE_TYPE (sop)),
+                         TREE_TYPE (type));
+             }
+           else if (!ctx->quiet)
+             error_at (loc, "cannot cast object to type %qT",
+                       TREE_TYPE (type));
+           *non_constant_p = true;
+           return t;
+         }
+
        if (TREE_CODE (op) == PTRMEM_CST && !TYPE_PTRMEM_P (type))
          {
            op = cplus_expand_constant (op);

Just on
GXX_TESTSUITE_STDS=14,29 make check-g++ RUNTESTFLAGS="dg.exp='constexpr-base* 
constexpr-static-cast*'"
FAIL: g++.dg/cpp0x/constexpr-static-cast2.C  -std=c++14 (test for excess errors)
FAIL: g++.dg/cpp0x/constexpr-static-cast2.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp1y/constexpr-base2a.C  -std=c++14 (test for excess errors)
FAIL: g++.dg/cpp1y/constexpr-base2a.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp1y/constexpr-static-cast2.C  -std=c++14 (test for excess errors)
FAIL: g++.dg/cpp1y/constexpr-static-cast2.C  -std=c++29 (test for excess errors)
Excess errors:
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-static-cast2.C:29:47: error: 
cannot cast object of dynamic type 'const F' to type 'const F'
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-static-cast2.C:45:49: error: 
cannot cast object of dynamic type 'const F' to type 'const F'
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-static-cast2.C:52:49: error: 
cannot cast object of dynamic type 'F' to type 'const F'
Excess errors:
/usr/src/gcc/gcc/testsuite/g++.dg/cpp1y/constexpr-base2a.C:17:19: error: 
non-constant condition for static assertion
/usr/src/gcc/gcc/testsuite/g++.dg/cpp1y/constexpr-base2a.C:13:6: error: cannot 
cast object of dynamic type 'B' to type 'B'
Excess errors:
/usr/src/gcc/gcc/testsuite/g++.dg/cpp1y/constexpr-static-cast2.C:87:23: error: 
non-constant condition for static assertion
/usr/src/gcc/gcc/testsuite/g++.dg/cpp1y/constexpr-static-cast2.C:74:9: error: 
cannot cast object of dynamic type 'G' to type 'G'
So, clearly cxx_fold_indirect_ref fails in some valid cases.

        Jakub

Reply via email to