Skip to content

Commit d04018f

Browse files
ChuanqiXu9CarlosAlbertoEnciso
authored andcommitted
[C++20] [Modules] Pop Expression Evaluation Context when we skip its body during parsing
Close llvm/llvm-project#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. Reviewed By: cor3ntin Differential Revision: https://reviews.llvm.org/D143053
1 parent 6a4763b commit d04018f

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

Diff for: clang/lib/Parse/Parser.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "clang/AST/ASTConsumer.h"
1515
#include "clang/AST/ASTContext.h"
1616
#include "clang/AST/DeclTemplate.h"
17+
#include "clang/AST/ASTLambda.h"
1718
#include "clang/Basic/FileManager.h"
1819
#include "clang/Parse/ParseDiagnostic.h"
1920
#include "clang/Parse/RAIIObjectsForParser.h"
@@ -1404,6 +1405,17 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
14041405
if (BodyKind == Sema::FnBodyKind::Other)
14051406
SkipFunctionBody();
14061407

1408+
// ExpressionEvaluationContext is pushed in ActOnStartOfFunctionDef
1409+
// and it would be popped in ActOnFinishFunctionBody.
1410+
// We pop it explcitly here since ActOnFinishFunctionBody won't get called.
1411+
//
1412+
// Do not call PopExpressionEvaluationContext() if it is a lambda because
1413+
// one is already popped when finishing the lambda in BuildLambdaExpr().
1414+
//
1415+
// FIXME: It looks not easy to balance PushExpressionEvaluationContext()
1416+
// and PopExpressionEvaluationContext().
1417+
if (!isLambdaCallOperator(dyn_cast_if_present<FunctionDecl>(Res)))
1418+
Actions.PopExpressionEvaluationContext();
14071419
return Res;
14081420
}
14091421

Diff for: clang/test/Modules/pr60275.cppm

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Address: https://github.com/llvm/llvm-project/issues/60275
2+
//
3+
// RUN: rm -rf %t
4+
// RUN: mkdir -p %t
5+
// RUN: split-file %s %t
6+
//
7+
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-module-interface %t/a.cppm -o %t/a.pcm
8+
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp
9+
//--- foo.h
10+
11+
consteval void global() {}
12+
13+
//--- a.cppm
14+
module;
15+
#include "foo.h"
16+
export module a;
17+
18+
//--- b.cpp
19+
#include "foo.h"
20+
import a;
21+
22+
consteval int b() {
23+
return 0;
24+
}
25+
26+
struct bb {
27+
int m = b();
28+
};
29+
30+
void bbb() {
31+
bb x;
32+
}
33+
34+
// CHECK: define{{.*}}_ZN2bbC2Ev({{.*}}[[THIS:%.+]])
35+
// CHECK-NEXT: entry:
36+
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr
37+
// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]]
38+
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]]
39+
// CHECK-NEXT: [[M_ADDR:%.*]] = getelementptr{{.*}}%struct.bb, ptr [[THIS1]], i32 0, i32 0
40+
// CHECK-NEXT: store i32 0, ptr [[M_ADDR]]

0 commit comments

Comments
 (0)