diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -307,8 +307,8 @@ not a type concept. - Fix crash when a doc comment contains a line splicing. (`#62054 `_) -- Work around with a clang coverage crash which happens when visiting - expressions/statements with invalid source locations in non-assert builds. +- Work around with a clang coverage crash which happens when visiting + expressions/statements with invalid source locations in non-assert builds. Assert builds may still see assertions triggered from this. - Fix a failed assertion due to an invalid source location when trying to form a coverage report for an unresolved constructor expression. @@ -321,6 +321,8 @@ (`#61885 `_) - Clang constexpr evaluator now treats comparison of [[gnu::weak]]-attributed member pointer as an invalid expression. +- Fix a stack overflow issue when evaluating ``consteval`` default arguments. + (`#60082` `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5926,7 +5926,9 @@ Param); ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = SkipImmediateInvocations; - MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables*/ true); + runWithSufficientStackSpace(CallLoc, [&] { + MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables=*/true); + }); return false; } @@ -6036,8 +6038,11 @@ ExprEvalContexts.back().DelayedDefaultInitializationContext = { CallLoc, Param, CurContext}; EnsureImmediateInvocationInDefaultArgs Immediate(*this); - ExprResult Res = Immediate.TransformInitializer(Param->getInit(), - /*NotCopy=*/false); + ExprResult Res; + runWithSufficientStackSpace(CallLoc, [&] { + Res = Immediate.TransformInitializer(Param->getInit(), + /*NotCopy=*/false); + }); if (Res.isInvalid()) return ExprError(); Res = ConvertParamDefaultArgument(Param, Res.get(), @@ -6117,10 +6122,11 @@ NestedDefaultChecking; EnsureImmediateInvocationInDefaultArgs Immediate(*this); - - ExprResult Res = - Immediate.TransformInitializer(Field->getInClassInitializer(), - /*CXXDirectInit=*/false); + ExprResult Res; + runWithSufficientStackSpace(Loc, [&] { + Res = Immediate.TransformInitializer(Field->getInClassInitializer(), + /*CXXDirectInit=*/false); + }); if (!Res.isInvalid()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { @@ -6133,7 +6139,9 @@ if (Field->getInClassInitializer()) { Expr *E = Init ? Init : Field->getInClassInitializer(); if (!NestedDefaultChecking) - MarkDeclarationsReferencedInExpr(E, /*SkipLocalVariables=*/false); + runWithSufficientStackSpace(Loc, [&] { + MarkDeclarationsReferencedInExpr(E, /*SkipLocalVariables=*/false); + }); // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. diff --git a/clang/test/SemaCXX/cxx11-default-member-initializers-recurse.cpp b/clang/test/SemaCXX/cxx11-default-member-initializers-recurse.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/cxx11-default-member-initializers-recurse.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++20 %s + +// Recursively constructing default member initializers +// should not crash clang. +namespace GH60082 { + +struct A; + +int f(const A&) { return 42; } + +struct A { + int x = f(A()); + A() { } +}; + +void foo() { A(); } + +} diff --git a/clang/test/SemaCXX/cxx11-default-member-initializers.cpp b/clang/test/SemaCXX/cxx11-default-member-initializers.cpp --- a/clang/test/SemaCXX/cxx11-default-member-initializers.cpp +++ b/clang/test/SemaCXX/cxx11-default-member-initializers.cpp @@ -106,3 +106,20 @@ } #endif + +// Recursively constructing default member initializers +// should not crash clang. +namespace GH60082 { + +struct A; + +int f(const A&) { return 42; } + +struct A { + int x = f(A()); + A() { } +}; + +void foo() { A(); } + +}