From 40b6df3ed0f52082944e3760d6a12a2016dc9131 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/warnings/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/warnings/class b/t/lib/warnings/class index 4cd8de1a92c6..63ee748f7719 100644 --- a/t/lib/warnings/class +++ b/t/lib/warnings/class @@ -41,3 +41,21 @@ class C { C->new; EXPECT Odd number of elements in hash field initialization at - line 6. +######## +# 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.