From a564fbe32d9d143fe0109b515c626f3c3afe47d7 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Tue, 23 Apr 2024 10:11:58 +1000 Subject: [PATCH] report an error when making an object of an incomplete class instead of asserting or crashing Fixes #22159 --- class.c | 5 +++++ pod/perldiag.pod | 12 ++++++++++++ t/lib/croak/class | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/class.c b/class.c index 68189756348f..1806f5d7e51c 100644 --- a/class.c +++ b/class.c @@ -140,6 +140,11 @@ XS(injected_constructor) Perl_warn(aTHX_ "Odd number of arguments passed to %" HvNAMEf_QUOTEDPREFIX " constructor", HvNAMEfARG(stash)); + if (!aux->xhv_class_initfields_cv) { + Perl_croak(aTHX_ "Cannot create an object of incomplete class %" HvNAMEf_QUOTEDPREFIX, + HvNAMEfARG(stash)); + } + HV *params = NULL; { /* Set up params HV */ diff --git a/pod/perldiag.pod b/pod/perldiag.pod index fc8e8d1032ef..b05554939ec7 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -731,6 +731,18 @@ be directly assigned to. an C<@ISA> array, and the array is not empty. This is not permitted, as it would lead to a class with inconsistent inheritance. +=item Cannot create an object of incomplete class "%s" + +(F) An attempt was made to create an object of a class where the start +of the class definition has been seen, but the class has not been +completed. + +This can happen for a failed eval, or if you attempt to create an +object at compile time before the class is complete: + + eval "class Foo {"; Foo->new; # error + class Bar { BEGIN { Bar->new } }; # error + =item Cannot find encoding "%s" (S io) You tried to apply an encoding that did not exist to a filehandle, diff --git a/t/lib/croak/class b/t/lib/croak/class index 6b95ce11f6f9..fde3c7a181c7 100644 --- a/t/lib/croak/class +++ b/t/lib/croak/class @@ -137,3 +137,21 @@ class XXX { } EXPECT Cannot use __CLASS__ outside of a method or field initializer expression at - line 5. +######## +# NAME try to create an object of incomplete class (error) +use v5.36; +use feature 'class'; +no warnings 'experimental::class'; +eval "class C {"; +C->new; +EXPECT +Cannot create an object of incomplete class "C" at - line 5. +######## +# NAME try to create an object of incomplete class (compile-time) +use v5.36; +use feature 'class'; +no warnings 'experimental::class'; +class C { BEGIN { C->new; } }; +EXPECT +Cannot create an object of incomplete class "C" at - line 4. +BEGIN failed--compilation aborted at - line 4.