Skip to content

Commit 09cc75e

Browse files
authored
[clang] Deduplicate the logic that only warns once when stack is almost full (#112552)
Zero diff in behavior.
1 parent 508fd96 commit 09cc75e

File tree

11 files changed

+105
-45
lines changed

11 files changed

+105
-45
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//===--- StackExhaustionHandler.h - A utility for warning once when close to out
2+
// of stack space -------*- C++ -*-===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// Defines a utilitiy for warning once when close to out of stack space.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_CLANG_BASIC_STACK_EXHAUSTION_HANDLER_H
16+
#define LLVM_CLANG_BASIC_STACK_EXHAUSTION_HANDLER_H
17+
18+
#include "clang/Basic/Diagnostic.h"
19+
20+
namespace clang {
21+
class StackExhaustionHandler {
22+
public:
23+
StackExhaustionHandler(DiagnosticsEngine &diags) : DiagsRef(diags) {}
24+
25+
/// Run some code with "sufficient" stack space. (Currently, at least 256K
26+
/// is guaranteed). Produces a warning if we're low on stack space and
27+
/// allocates more in that case. Use this in code that may recurse deeply to
28+
/// avoid stack overflow.
29+
void runWithSufficientStackSpace(SourceLocation Loc,
30+
llvm::function_ref<void()> Fn);
31+
32+
/// Check to see if we're low on stack space and produce a warning if we're
33+
/// low on stack space (Currently, at least 256Kis guaranteed).
34+
void warnOnStackNearlyExhausted(SourceLocation Loc);
35+
36+
private:
37+
/// Warn that the stack is nearly exhausted.
38+
void warnStackExhausted(SourceLocation Loc);
39+
40+
DiagnosticsEngine &DiagsRef;
41+
bool WarnedStackExhausted = false;
42+
};
43+
} // end namespace clang
44+
45+
#endif // LLVM_CLANG_BASIC_STACK_EXHAUSTION_HANDLER_H

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "clang/Basic/PragmaKinds.h"
5050
#include "clang/Basic/SourceLocation.h"
5151
#include "clang/Basic/Specifiers.h"
52+
#include "clang/Basic/StackExhaustionHandler.h"
5253
#include "clang/Basic/TemplateKinds.h"
5354
#include "clang/Basic/TokenKinds.h"
5455
#include "clang/Basic/TypeTraits.h"
@@ -546,9 +547,6 @@ class Sema final : public SemaBase {
546547
/// Print out statistics about the semantic analysis.
547548
void PrintStats() const;
548549

549-
/// Warn that the stack is nearly exhausted.
550-
void warnStackExhausted(SourceLocation Loc);
551-
552550
/// Run some code with "sufficient" stack space. (Currently, at least 256K is
553551
/// guaranteed). Produces a warning if we're low on stack space and allocates
554552
/// more in that case. Use this in code that may recurse deeply (for example,
@@ -1183,7 +1181,7 @@ class Sema final : public SemaBase {
11831181
std::optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo;
11841182
bool WarnedDarwinSDKInfoMissing = false;
11851183

1186-
bool WarnedStackExhausted = false;
1184+
StackExhaustionHandler StackHandler;
11871185

11881186
Sema(const Sema &) = delete;
11891187
void operator=(const Sema &) = delete;

clang/include/clang/Serialization/ASTReader.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/Basic/IdentifierTable.h"
2020
#include "clang/Basic/OpenCLOptions.h"
2121
#include "clang/Basic/SourceLocation.h"
22+
#include "clang/Basic/StackExhaustionHandler.h"
2223
#include "clang/Basic/Version.h"
2324
#include "clang/Lex/ExternalPreprocessorSource.h"
2425
#include "clang/Lex/HeaderSearch.h"
@@ -445,7 +446,7 @@ class ASTReader
445446
DiagnosticsEngine &Diags;
446447
// Sema has duplicate logic, but SemaObj can sometimes be null so ASTReader
447448
// has its own version.
448-
bool WarnedStackExhausted = false;
449+
StackExhaustionHandler StackHandler;
449450

450451
/// The semantic analysis object that will be processing the
451452
/// AST files and the translation unit that uses it.
@@ -2180,7 +2181,8 @@ class ASTReader
21802181
/// Report a diagnostic.
21812182
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const;
21822183

2183-
void warnStackExhausted(SourceLocation Loc);
2184+
void runWithSufficientStackSpace(SourceLocation Loc,
2185+
llvm::function_ref<void()> Fn);
21842186

21852187
IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID);
21862188

clang/lib/Basic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ add_clang_library(clangBasic
8989
SourceManager.cpp
9090
SourceMgrAdapter.cpp
9191
Stack.cpp
92+
StackExhaustionHandler.cpp
9293
TargetID.cpp
9394
TargetInfo.cpp
9495
Targets.cpp
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===--- StackExhaustionHandler.cpp - - A utility for warning once when close
2+
// to out of stack space -------*- C++ -*-===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// Defines a utilitiy for warning once when close to out of stack space.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "clang/Basic/StackExhaustionHandler.h"
16+
#include "clang/Basic/Stack.h"
17+
18+
void clang::StackExhaustionHandler::runWithSufficientStackSpace(
19+
SourceLocation Loc, llvm::function_ref<void()> Fn) {
20+
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
21+
}
22+
23+
void clang::StackExhaustionHandler::warnOnStackNearlyExhausted(
24+
SourceLocation Loc) {
25+
if (isStackNearlyExhausted())
26+
warnStackExhausted(Loc);
27+
}
28+
29+
void clang::StackExhaustionHandler::warnStackExhausted(SourceLocation Loc) {
30+
// Only warn about this once.
31+
if (!WarnedStackExhausted) {
32+
DiagsRef.Report(Loc, diag::warn_stack_exhausted);
33+
WarnedStackExhausted = true;
34+
}
35+
}

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ CodeGenModule::CodeGenModule(ASTContext &C,
342342
: Context(C), LangOpts(C.getLangOpts()), FS(FS), HeaderSearchOpts(HSO),
343343
PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
344344
Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
345-
VMContext(M.getContext()), VTables(*this),
345+
VMContext(M.getContext()), VTables(*this), StackHandler(diags),
346346
SanitizerMD(new SanitizerMetadata(*this)) {
347347

348348
// Initialize the type cache.
@@ -1595,17 +1595,9 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) {
15951595
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
15961596
}
15971597

1598-
void CodeGenModule::warnStackExhausted(SourceLocation Loc) {
1599-
// Only warn about this once.
1600-
if (!WarnedStackExhausted) {
1601-
getDiags().Report(Loc, diag::warn_stack_exhausted);
1602-
WarnedStackExhausted = true;
1603-
}
1604-
}
1605-
16061598
void CodeGenModule::runWithSufficientStackSpace(SourceLocation Loc,
16071599
llvm::function_ref<void()> Fn) {
1608-
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
1600+
StackHandler.runWithSufficientStackSpace(Loc, Fn);
16091601
}
16101602

16111603
llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "clang/Basic/LangOptions.h"
2727
#include "clang/Basic/NoSanitizeList.h"
2828
#include "clang/Basic/ProfileList.h"
29+
#include "clang/Basic/StackExhaustionHandler.h"
2930
#include "clang/Basic/TargetInfo.h"
3031
#include "clang/Basic/XRayLists.h"
3132
#include "clang/Lex/PreprocessorOptions.h"
@@ -336,7 +337,7 @@ class CodeGenModule : public CodeGenTypeCache {
336337
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
337338
InstrProfStats PGOStats;
338339
std::unique_ptr<llvm::SanitizerStatReport> SanStats;
339-
bool WarnedStackExhausted = false;
340+
StackExhaustionHandler StackHandler;
340341

341342
// A set of references that have only been seen via a weakref so far. This is
342343
// used to remove the weak of the reference if we ever see a direct reference
@@ -1298,9 +1299,6 @@ class CodeGenModule : public CodeGenTypeCache {
12981299
/// Print out an error that codegen doesn't support the specified decl yet.
12991300
void ErrorUnsupported(const Decl *D, const char *Type);
13001301

1301-
/// Warn that the stack is nearly exhausted.
1302-
void warnStackExhausted(SourceLocation Loc);
1303-
13041302
/// Run some code with "sufficient" stack space. (Currently, at least 256K is
13051303
/// guaranteed). Produces a warning if we're low on stack space and allocates
13061304
/// more in that case. Use this in code that may recurse deeply to avoid stack

clang/lib/Sema/Sema.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
220220
AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr),
221221
LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr),
222222
OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr),
223-
CurScope(nullptr), Ident_super(nullptr),
223+
StackHandler(Diags), CurScope(nullptr), Ident_super(nullptr),
224224
AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
225225
ARMPtr(std::make_unique<SemaARM>(*this)),
226226
AVRPtr(std::make_unique<SemaAVR>(*this)),
@@ -562,17 +562,9 @@ Sema::~Sema() {
562562
SemaPPCallbackHandler->reset();
563563
}
564564

565-
void Sema::warnStackExhausted(SourceLocation Loc) {
566-
// Only warn about this once.
567-
if (!WarnedStackExhausted) {
568-
Diag(Loc, diag::warn_stack_exhausted);
569-
WarnedStackExhausted = true;
570-
}
571-
}
572-
573565
void Sema::runWithSufficientStackSpace(SourceLocation Loc,
574566
llvm::function_ref<void()> Fn) {
575-
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
567+
StackHandler.runWithSufficientStackSpace(Loc, Fn);
576568
}
577569

578570
bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -806,8 +806,7 @@ void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
806806

807807
// Check to see if we're low on stack space. We can't do anything about this
808808
// from here, but we can at least warn the user.
809-
if (isStackNearlyExhausted())
810-
warnStackExhausted(Ctx.PointOfInstantiation);
809+
StackHandler.warnOnStackNearlyExhausted(Ctx.PointOfInstantiation);
811810
}
812811

813812
void Sema::popCodeSynthesisContext() {

clang/lib/Serialization/ASTReader.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "clang/Basic/SourceManager.h"
6565
#include "clang/Basic/SourceManagerInternals.h"
6666
#include "clang/Basic/Specifiers.h"
67+
#include "clang/Basic/Stack.h"
6768
#include "clang/Basic/TargetInfo.h"
6869
#include "clang/Basic/TargetOptions.h"
6970
#include "clang/Basic/TokenKinds.h"
@@ -9648,18 +9649,15 @@ DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) const {
96489649
return Diags.Report(Loc, DiagID);
96499650
}
96509651

9651-
void ASTReader::warnStackExhausted(SourceLocation Loc) {
9652+
void ASTReader::runWithSufficientStackSpace(SourceLocation Loc,
9653+
llvm::function_ref<void()> Fn) {
96529654
// When Sema is available, avoid duplicate errors.
96539655
if (SemaObj) {
9654-
SemaObj->warnStackExhausted(Loc);
9656+
SemaObj->runWithSufficientStackSpace(Loc, Fn);
96559657
return;
96569658
}
96579659

9658-
if (WarnedStackExhausted)
9659-
return;
9660-
WarnedStackExhausted = true;
9661-
9662-
Diag(Loc, diag::warn_stack_exhausted);
9660+
StackHandler.runWithSufficientStackSpace(Loc, Fn);
96639661
}
96649662

96659663
/// Retrieve the identifier table associated with the
@@ -10509,13 +10507,14 @@ ASTReader::ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
1050910507
bool AllowConfigurationMismatch, bool ValidateSystemInputs,
1051010508
bool ValidateASTInputFilesContent, bool UseGlobalIndex,
1051110509
std::unique_ptr<llvm::Timer> ReadTimer)
10512-
: Listener(bool(DisableValidationKind &DisableValidationForModuleKind::PCH)
10510+
: Listener(bool(DisableValidationKind & DisableValidationForModuleKind::PCH)
1051310511
? cast<ASTReaderListener>(new SimpleASTReaderListener(PP))
1051410512
: cast<ASTReaderListener>(new PCHValidator(PP, *this))),
1051510513
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
10516-
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP),
10517-
ContextObj(Context), ModuleMgr(PP.getFileManager(), ModuleCache,
10518-
PCHContainerRdr, PP.getHeaderSearchInfo()),
10514+
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()),
10515+
StackHandler(Diags), PP(PP), ContextObj(Context),
10516+
ModuleMgr(PP.getFileManager(), ModuleCache, PCHContainerRdr,
10517+
PP.getHeaderSearchInfo()),
1051910518
DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
1052010519
DisableValidationKind(DisableValidationKind),
1052110520
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4168,8 +4168,7 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
41684168
D->setDeclContext(Context.getTranslationUnitDecl());
41694169

41704170
// Reading some declarations can result in deep recursion.
4171-
clang::runWithSufficientStackSpace([&] { warnStackExhausted(DeclLoc); },
4172-
[&] { Reader.Visit(D); });
4171+
runWithSufficientStackSpace(DeclLoc, [&] { Reader.Visit(D); });
41734172

41744173
// If this declaration is also a declaration context, get the
41754174
// offsets for its tables of lexical and visible declarations.

0 commit comments

Comments
 (0)