cor3ntin created this revision. Herald added a project: All. cor3ntin requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This fixes a regression introduced by ca61961380 <https://reviews.llvm.org/rGca619613801233ef2def8c3cc7d311d5ed0033cb>, that would lead to a segfault due to stack exhaustion when recursively calling a default member initializer. Fixes #60082 I'm not able to get clang to emit a stack exhaustion warning, which it seems like it should be able to. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D142401 Files: clang/lib/Sema/SemaExpr.cpp clang/test/SemaCXX/cxx11-default-member-initializers.cpp Index: clang/test/SemaCXX/cxx11-default-member-initializers.cpp =================================================================== --- clang/test/SemaCXX/cxx11-default-member-initializers.cpp +++ clang/test/SemaCXX/cxx11-default-member-initializers.cpp @@ -49,3 +49,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(); } + +} Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -5910,7 +5910,9 @@ *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = SkipImmediateInvocations; - MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables*/ true); + runWithSufficientStackSpace(CallLoc, [&] { + MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables*/ true); + }); return false; } @@ -6008,8 +6010,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(), @@ -6090,9 +6095,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()) { @@ -6105,7 +6112,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.
Index: clang/test/SemaCXX/cxx11-default-member-initializers.cpp =================================================================== --- clang/test/SemaCXX/cxx11-default-member-initializers.cpp +++ clang/test/SemaCXX/cxx11-default-member-initializers.cpp @@ -49,3 +49,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(); } + +} Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -5910,7 +5910,9 @@ *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = SkipImmediateInvocations; - MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables*/ true); + runWithSufficientStackSpace(CallLoc, [&] { + MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables*/ true); + }); return false; } @@ -6008,8 +6010,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(), @@ -6090,9 +6095,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()) { @@ -6105,7 +6112,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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits