0
0
mirror of https://github.com/llvm/llvm-project.git synced 2025-04-21 14:06:57 +00:00

[Clang] Fix segmentation fault caused by VarBypassDetector stack overflow on deeply nested expressions ()

This happens when using `-O2`.

Similarly to 
([test](93e4a7386e/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](1a63281b6c (r1795518779)).
Test that was reverted here:
d6b5576940
This commit is contained in:
Boaz Brickner 2025-03-10 09:33:00 +01:00 committed by GitHub
parent 35f273ab07
commit e0442bdfa5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 13 deletions

@ -1534,7 +1534,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// Initialize helper which will detect jumps which can cause invalid
// lifetime markers.
if (ShouldEmitLifetimeMarkers)
Bypasses.Init(Body);
Bypasses.Init(CGM, Body);
}
// Emit the standard function prologue.

@ -8,6 +8,7 @@
#include "VarBypassDetector.h"
#include "CodeGenModule.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
@ -17,13 +18,13 @@ using namespace CodeGen;
/// Clear the object and pre-process for the given statement, usually function
/// body statement.
void VarBypassDetector::Init(const Stmt *Body) {
void VarBypassDetector::Init(CodeGenModule &CGM, const Stmt *Body) {
FromScopes.clear();
ToScopes.clear();
Bypasses.clear();
Scopes = {{~0U, nullptr}};
unsigned ParentScope = 0;
AlwaysBypassed = !BuildScopeInformation(Body, ParentScope);
AlwaysBypassed = !BuildScopeInformation(CGM, Body, ParentScope);
if (!AlwaysBypassed)
Detect();
}
@ -31,7 +32,7 @@ void VarBypassDetector::Init(const Stmt *Body) {
/// Build scope information for a declaration that is part of a DeclStmt.
/// Returns false if we failed to build scope information and can't tell for
/// which vars are being bypassed.
bool VarBypassDetector::BuildScopeInformation(const Decl *D,
bool VarBypassDetector::BuildScopeInformation(CodeGenModule &CGM, const Decl *D,
unsigned &ParentScope) {
const VarDecl *VD = dyn_cast<VarDecl>(D);
if (VD && VD->hasLocalStorage()) {
@ -41,7 +42,7 @@ bool VarBypassDetector::BuildScopeInformation(const Decl *D,
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
if (const Expr *Init = VD->getInit())
return BuildScopeInformation(Init, ParentScope);
return BuildScopeInformation(CGM, Init, ParentScope);
return true;
}
@ -50,7 +51,7 @@ bool VarBypassDetector::BuildScopeInformation(const Decl *D,
/// LabelAndGotoScopes and recursively walking the AST as needed.
/// Returns false if we failed to build scope information and can't tell for
/// which vars are being bypassed.
bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
bool VarBypassDetector::BuildScopeInformation(CodeGenModule &CGM, const Stmt *S,
unsigned &origParentScope) {
// If this is a statement, rather than an expression, scopes within it don't
// propagate out into the enclosing scope. Otherwise we have to worry about
@ -68,12 +69,12 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
case Stmt::SwitchStmtClass:
if (const Stmt *Init = cast<SwitchStmt>(S)->getInit()) {
if (!BuildScopeInformation(Init, ParentScope))
if (!BuildScopeInformation(CGM, Init, ParentScope))
return false;
++StmtsToSkip;
}
if (const VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
if (!BuildScopeInformation(Var, ParentScope))
if (!BuildScopeInformation(CGM, Var, ParentScope))
return false;
++StmtsToSkip;
}
@ -86,7 +87,7 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
case Stmt::DeclStmtClass: {
const DeclStmt *DS = cast<DeclStmt>(S);
for (auto *I : DS->decls())
if (!BuildScopeInformation(I, origParentScope))
if (!BuildScopeInformation(CGM, I, origParentScope))
return false;
return true;
}
@ -126,7 +127,11 @@ bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
}
// Recursively walk the AST.
if (!BuildScopeInformation(SubStmt, ParentScope))
bool Result;
CGM.runWithSufficientStackSpace(S->getEndLoc(), [&] {
Result = BuildScopeInformation(CGM, SubStmt, ParentScope);
});
if (!Result)
return false;
}
return true;

@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
#define LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
#include "CodeGenModule.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@ -50,7 +51,7 @@ class VarBypassDetector {
bool AlwaysBypassed = false;
public:
void Init(const Stmt *Body);
void Init(CodeGenModule &CGM, const Stmt *Body);
/// Returns true if the variable declaration was by bypassed by any goto or
/// switch statement.
@ -59,8 +60,10 @@ public:
}
private:
bool BuildScopeInformation(const Decl *D, unsigned &ParentScope);
bool BuildScopeInformation(const Stmt *S, unsigned &origParentScope);
bool BuildScopeInformation(CodeGenModule &CGM, const Decl *D,
unsigned &ParentScope);
bool BuildScopeInformation(CodeGenModule &CGM, const Stmt *S,
unsigned &origParentScope);
void Detect();
void Detect(unsigned From, unsigned To);
};