Skip to content

Commit e0442bd

Browse files
authored
[Clang] Fix segmentation fault caused by VarBypassDetector stack overflow on deeply nested expressions (#124128)
This happens when using `-O2`. Similarly to #111701 ([test](https://github.com/bricknerb/llvm-project/blob/93e4a7386ec897e53d7330c6206d38759a858be2/clang/test/CodeGen/deeply-nested-expressions.cpp)), not adding a test that reproduces since this test is slow and likely to be hard to maintained as discussed here and in [previous discussion](https://github.com/llvm/llvm-project/pull/111701/files/1a63281b6c240352653fd2e4299755c1f32a76f4#r1795518779). Test that was reverted here: d6b5576
1 parent 35f273a commit e0442bd

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1534,7 +1534,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
15341534
// Initialize helper which will detect jumps which can cause invalid
15351535
// lifetime markers.
15361536
if (ShouldEmitLifetimeMarkers)
1537-
Bypasses.Init(Body);
1537+
Bypasses.Init(CGM, Body);
15381538
}
15391539

15401540
// Emit the standard function prologue.

clang/lib/CodeGen/VarBypassDetector.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "VarBypassDetector.h"
1010

11+
#include "CodeGenModule.h"
1112
#include "clang/AST/Decl.h"
1213
#include "clang/AST/Expr.h"
1314
#include "clang/AST/Stmt.h"
@@ -17,21 +18,21 @@ using namespace CodeGen;
1718

1819
/// Clear the object and pre-process for the given statement, usually function
1920
/// body statement.
20-
void VarBypassDetector::Init(const Stmt *Body) {
21+
void VarBypassDetector::Init(CodeGenModule &CGM, const Stmt *Body) {
2122
FromScopes.clear();
2223
ToScopes.clear();
2324
Bypasses.clear();
2425
Scopes = {{~0U, nullptr}};
2526
unsigned ParentScope = 0;
26-
AlwaysBypassed = !BuildScopeInformation(Body, ParentScope);
27+
AlwaysBypassed = !BuildScopeInformation(CGM, Body, ParentScope);
2728
if (!AlwaysBypassed)
2829
Detect();
2930
}
3031

3132
/// Build scope information for a declaration that is part of a DeclStmt.
3233
/// Returns false if we failed to build scope information and can't tell for
3334
/// which vars are being bypassed.
34-
bool VarBypassDetector::BuildScopeInformation(const Decl *D,
35+
bool VarBypassDetector::BuildScopeInformation(CodeGenModule &CGM, const Decl *D,
3536
unsigned &ParentScope) {
3637
const VarDecl *VD = dyn_cast<VarDecl>(D);
3738
if (VD && VD->hasLocalStorage()) {
@@ -41,7 +42,7 @@ bool VarBypassDetector::BuildScopeInformation(const Decl *D,
4142

4243
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
4344
if (const Expr *Init = VD->getInit())
44-
return BuildScopeInformation(Init, ParentScope);
45+
return BuildScopeInformation(CGM, Init, ParentScope);
4546

4647
return true;
4748
}
@@ -50,7 +51,7 @@ bool VarBypassDetector::BuildScopeInformation(const Decl *D,
5051
/// LabelAndGotoScopes and recursively walking the AST as needed.
5152
/// Returns false if we failed to build scope information and can't tell for
5253
/// which vars are being bypassed.
53-
bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
54+
bool VarBypassDetector::BuildScopeInformation(CodeGenModule &CGM, const Stmt *S,
5455
unsigned &origParentScope) {
5556
// If this is a statement, rather than an expression, scopes within it don't
5657
// propagate out into the enclosing scope. Otherwise we have to worry about
@@ -68,12 +69,12 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
6869

6970
case Stmt::SwitchStmtClass:
7071
if (const Stmt *Init = cast<SwitchStmt>(S)->getInit()) {
71-
if (!BuildScopeInformation(Init, ParentScope))
72+
if (!BuildScopeInformation(CGM, Init, ParentScope))
7273
return false;
7374
++StmtsToSkip;
7475
}
7576
if (const VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
76-
if (!BuildScopeInformation(Var, ParentScope))
77+
if (!BuildScopeInformation(CGM, Var, ParentScope))
7778
return false;
7879
++StmtsToSkip;
7980
}
@@ -86,7 +87,7 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
8687
case Stmt::DeclStmtClass: {
8788
const DeclStmt *DS = cast<DeclStmt>(S);
8889
for (auto *I : DS->decls())
89-
if (!BuildScopeInformation(I, origParentScope))
90+
if (!BuildScopeInformation(CGM, I, origParentScope))
9091
return false;
9192
return true;
9293
}
@@ -126,7 +127,11 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
126127
}
127128

128129
// Recursively walk the AST.
129-
if (!BuildScopeInformation(SubStmt, ParentScope))
130+
bool Result;
131+
CGM.runWithSufficientStackSpace(S->getEndLoc(), [&] {
132+
Result = BuildScopeInformation(CGM, SubStmt, ParentScope);
133+
});
134+
if (!Result)
130135
return false;
131136
}
132137
return true;

clang/lib/CodeGen/VarBypassDetector.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
1515
#define LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
1616

17+
#include "CodeGenModule.h"
1718
#include "clang/AST/Decl.h"
1819
#include "llvm/ADT/DenseMap.h"
1920
#include "llvm/ADT/DenseSet.h"
@@ -50,7 +51,7 @@ class VarBypassDetector {
5051
bool AlwaysBypassed = false;
5152

5253
public:
53-
void Init(const Stmt *Body);
54+
void Init(CodeGenModule &CGM, const Stmt *Body);
5455

5556
/// Returns true if the variable declaration was by bypassed by any goto or
5657
/// switch statement.
@@ -59,8 +60,10 @@ class VarBypassDetector {
5960
}
6061

6162
private:
62-
bool BuildScopeInformation(const Decl *D, unsigned &ParentScope);
63-
bool BuildScopeInformation(const Stmt *S, unsigned &origParentScope);
63+
bool BuildScopeInformation(CodeGenModule &CGM, const Decl *D,
64+
unsigned &ParentScope);
65+
bool BuildScopeInformation(CodeGenModule &CGM, const Stmt *S,
66+
unsigned &origParentScope);
6467
void Detect();
6568
void Detect(unsigned From, unsigned To);
6669
};

0 commit comments

Comments
 (0)