This is an archive of the discontinued LLVM Phabricator instance.

[C++20] [Modules] Pop Expression Evaluation Context when we skip its body during parsing
ClosedPublic

Authored by ChuanqiXu on Feb 1 2023, 1:07 AM.

Details

Summary

Close https://github.com/llvm/llvm-project/issues/60275

The root cause of issue 60275 is the imbalance of PushExpressionEvaluationContext() and PopExpressionEvaluationContext().

See https://github.com/llvm/llvm-project/blob/f1c4f927f7c15b5efdc3589c050fd0513bf6b303/clang/lib/Parse/Parser.cpp#L1396-L1437

We will PushExpressionEvaluationContext() in ActOnStartOfFunctionDef() in line 1396 and we should pop it in ActOnFinishFunctionBody later. However if we skip the function body in line 1402, the expression evaluation context will not be popped. Then here is the issue report. I fix the issue by inserting codes to pop the expression evaluation context explicitly if the function body is skipped. Maybe this looks like an ad-hoc fix. But if we want to fix this in a pretty way, we should refactor the current framework for pushing and popping expression evaluation contexts. Currently there are 23 PushExpressionEvaluationContext() callsities and 21 PopExpressionEvaluationContext() callsites in the code. And it seems not easy to balance them well and fast. So I suggest to land this fix first. At least it can prevent the crash.

Diff Detail

Event Timeline

ChuanqiXu created this revision.Feb 1 2023, 1:07 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 1 2023, 1:07 AM
ChuanqiXu requested review of this revision.Feb 1 2023, 1:07 AM

@cor3ntin did a bunch of work here lately, so he's probably a better reviewer than I am.

shafik added inline comments.Feb 1 2023, 9:12 AM
clang/lib/Parse/Parser.cpp
1415

It does seem a bit ad-hoc

cor3ntin added inline comments.Feb 1 2023, 9:35 AM
clang/lib/Parse/Parser.cpp
1415

could we use ExitFunctionBodyRAII here, maybe ? It already deals with lambdas

ChuanqiXu added inline comments.
clang/lib/Parse/Parser.cpp
1415

It does seem a bit ad-hoc

I agree. I feel the current explicit style for pushing and popping different contexts looks not easy to maintain... I just want to prevent the crash for now and I feel the patch wouldn't be a burden when someday we want to refactor this.

could we use ExitFunctionBodyRAII here, maybe ? It already deals with lambdas

Maybe. But it wouldn't be simpler. We need to move ExitFunctionBodyRAII and we need to write:

ExitFunctionBodyRAII ExitRAII(Actions, isLambdaCallOperator(dyn_cast_if_present<FunctionDecl>(Res)));
return Res;

which looks odd and unnecessary.

And if you're saying something like:

Decl *Res = Actions.ActOnStartOfFunctionDef(getCurScope(), D,
                                              TemplateInfo.TemplateParams
                                                  ? *TemplateInfo.TemplateParams
                                                  : MultiTemplateParamsArg(),
                                              &SkipBody, BodyKind);


ExitFunctionBodyRAII ExitRAII(Actions, isLambdaCallOperator(dyn_cast_if_present<FunctionDecl>(Res)));

and remove the ExitFunctionBodyRAII in ActOnFinishFunctionBody. I guess it can't work in this way simply. Since the comment (https://github.com/llvm/llvm-project/blob/c6795b1d37cee586d9b98dade64432f8f6bd004b/clang/lib/Sema/SemaDecl.cpp#L15811-L15818) says we need to pop expression evaluation context before popping decl context (and function scope info?).

cor3ntin accepted this revision.Feb 2 2023, 6:46 AM
cor3ntin added inline comments.
clang/lib/Parse/Parser.cpp
1415

I think you are right, your change is probably as good as anything without doing a major refactor.

This revision is now accepted and ready to land.Feb 2 2023, 6:46 AM
This revision was landed with ongoing or failed builds.Feb 2 2023, 6:28 PM
This revision was automatically updated to reflect the committed changes.