[clang] Deduplicate the logic that only warns once when stack is almost full (#112552)

Zero diff in behavior.
This commit is contained in:
Boaz Brickner 2024-10-18 10:11:14 +02:00 committed by GitHub
parent 508fd966fb
commit 09cc75e2cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 105 additions and 45 deletions

View File

@ -0,0 +1,45 @@
//===--- StackExhaustionHandler.h - A utility for warning once when close to out
// of stack space -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines a utilitiy for warning once when close to out of stack space.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_STACK_EXHAUSTION_HANDLER_H
#define LLVM_CLANG_BASIC_STACK_EXHAUSTION_HANDLER_H
#include "clang/Basic/Diagnostic.h"
namespace clang {
class StackExhaustionHandler {
public:
StackExhaustionHandler(DiagnosticsEngine &diags) : DiagsRef(diags) {}
/// Run some code with "sufficient" stack space. (Currently, at least 256K
/// is guaranteed). Produces a warning if we're low on stack space and
/// allocates more in that case. Use this in code that may recurse deeply to
/// avoid stack overflow.
void runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn);
/// Check to see if we're low on stack space and produce a warning if we're
/// low on stack space (Currently, at least 256Kis guaranteed).
void warnOnStackNearlyExhausted(SourceLocation Loc);
private:
/// Warn that the stack is nearly exhausted.
void warnStackExhausted(SourceLocation Loc);
DiagnosticsEngine &DiagsRef;
bool WarnedStackExhausted = false;
};
} // end namespace clang
#endif // LLVM_CLANG_BASIC_STACK_EXHAUSTION_HANDLER_H

View File

@ -49,6 +49,7 @@
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/StackExhaustionHandler.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/TypeTraits.h"
@ -546,9 +547,6 @@ public:
/// Print out statistics about the semantic analysis.
void PrintStats() const;
/// Warn that the stack is nearly exhausted.
void warnStackExhausted(SourceLocation Loc);
/// Run some code with "sufficient" stack space. (Currently, at least 256K is
/// guaranteed). Produces a warning if we're low on stack space and allocates
/// more in that case. Use this in code that may recurse deeply (for example,
@ -1183,7 +1181,7 @@ private:
std::optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo;
bool WarnedDarwinSDKInfoMissing = false;
bool WarnedStackExhausted = false;
StackExhaustionHandler StackHandler;
Sema(const Sema &) = delete;
void operator=(const Sema &) = delete;

View File

@ -19,6 +19,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/StackExhaustionHandler.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderSearch.h"
@ -445,7 +446,7 @@ private:
DiagnosticsEngine &Diags;
// Sema has duplicate logic, but SemaObj can sometimes be null so ASTReader
// has its own version.
bool WarnedStackExhausted = false;
StackExhaustionHandler StackHandler;
/// The semantic analysis object that will be processing the
/// AST files and the translation unit that uses it.
@ -2180,7 +2181,8 @@ public:
/// Report a diagnostic.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const;
void warnStackExhausted(SourceLocation Loc);
void runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn);
IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID);

View File

@ -89,6 +89,7 @@ add_clang_library(clangBasic
SourceManager.cpp
SourceMgrAdapter.cpp
Stack.cpp
StackExhaustionHandler.cpp
TargetID.cpp
TargetInfo.cpp
Targets.cpp

View File

@ -0,0 +1,35 @@
//===--- StackExhaustionHandler.cpp - - A utility for warning once when close
// to out of stack space -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines a utilitiy for warning once when close to out of stack space.
///
//===----------------------------------------------------------------------===//
#include "clang/Basic/StackExhaustionHandler.h"
#include "clang/Basic/Stack.h"
void clang::StackExhaustionHandler::runWithSufficientStackSpace(
SourceLocation Loc, llvm::function_ref<void()> Fn) {
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
}
void clang::StackExhaustionHandler::warnOnStackNearlyExhausted(
SourceLocation Loc) {
if (isStackNearlyExhausted())
warnStackExhausted(Loc);
}
void clang::StackExhaustionHandler::warnStackExhausted(SourceLocation Loc) {
// Only warn about this once.
if (!WarnedStackExhausted) {
DiagsRef.Report(Loc, diag::warn_stack_exhausted);
WarnedStackExhausted = true;
}
}

View File

@ -342,7 +342,7 @@ CodeGenModule::CodeGenModule(ASTContext &C,
: Context(C), LangOpts(C.getLangOpts()), FS(FS), HeaderSearchOpts(HSO),
PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
VMContext(M.getContext()), VTables(*this),
VMContext(M.getContext()), VTables(*this), StackHandler(diags),
SanitizerMD(new SanitizerMetadata(*this)) {
// Initialize the type cache.
@ -1595,17 +1595,9 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) {
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
}
void CodeGenModule::warnStackExhausted(SourceLocation Loc) {
// Only warn about this once.
if (!WarnedStackExhausted) {
getDiags().Report(Loc, diag::warn_stack_exhausted);
WarnedStackExhausted = true;
}
}
void CodeGenModule::runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn) {
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
StackHandler.runWithSufficientStackSpace(Loc, Fn);
}
llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {

View File

@ -26,6 +26,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/ProfileList.h"
#include "clang/Basic/StackExhaustionHandler.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/XRayLists.h"
#include "clang/Lex/PreprocessorOptions.h"
@ -336,7 +337,7 @@ private:
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
InstrProfStats PGOStats;
std::unique_ptr<llvm::SanitizerStatReport> SanStats;
bool WarnedStackExhausted = false;
StackExhaustionHandler StackHandler;
// A set of references that have only been seen via a weakref so far. This is
// used to remove the weak of the reference if we ever see a direct reference
@ -1298,9 +1299,6 @@ public:
/// Print out an error that codegen doesn't support the specified decl yet.
void ErrorUnsupported(const Decl *D, const char *Type);
/// Warn that the stack is nearly exhausted.
void warnStackExhausted(SourceLocation Loc);
/// Run some code with "sufficient" stack space. (Currently, at least 256K is
/// guaranteed). Produces a warning if we're low on stack space and allocates
/// more in that case. Use this in code that may recurse deeply to avoid stack

View File

@ -220,7 +220,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr),
LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr),
OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr),
CurScope(nullptr), Ident_super(nullptr),
StackHandler(Diags), CurScope(nullptr), Ident_super(nullptr),
AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
ARMPtr(std::make_unique<SemaARM>(*this)),
AVRPtr(std::make_unique<SemaAVR>(*this)),
@ -562,17 +562,9 @@ Sema::~Sema() {
SemaPPCallbackHandler->reset();
}
void Sema::warnStackExhausted(SourceLocation Loc) {
// Only warn about this once.
if (!WarnedStackExhausted) {
Diag(Loc, diag::warn_stack_exhausted);
WarnedStackExhausted = true;
}
}
void Sema::runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn) {
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
StackHandler.runWithSufficientStackSpace(Loc, Fn);
}
bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,

View File

@ -806,8 +806,7 @@ void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
// Check to see if we're low on stack space. We can't do anything about this
// from here, but we can at least warn the user.
if (isStackNearlyExhausted())
warnStackExhausted(Ctx.PointOfInstantiation);
StackHandler.warnOnStackNearlyExhausted(Ctx.PointOfInstantiation);
}
void Sema::popCodeSynthesisContext() {

View File

@ -64,6 +64,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TokenKinds.h"
@ -9648,18 +9649,15 @@ DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) const {
return Diags.Report(Loc, DiagID);
}
void ASTReader::warnStackExhausted(SourceLocation Loc) {
void ASTReader::runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn) {
// When Sema is available, avoid duplicate errors.
if (SemaObj) {
SemaObj->warnStackExhausted(Loc);
SemaObj->runWithSufficientStackSpace(Loc, Fn);
return;
}
if (WarnedStackExhausted)
return;
WarnedStackExhausted = true;
Diag(Loc, diag::warn_stack_exhausted);
StackHandler.runWithSufficientStackSpace(Loc, Fn);
}
/// Retrieve the identifier table associated with the
@ -10509,13 +10507,14 @@ ASTReader::ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
bool AllowConfigurationMismatch, bool ValidateSystemInputs,
bool ValidateASTInputFilesContent, bool UseGlobalIndex,
std::unique_ptr<llvm::Timer> ReadTimer)
: Listener(bool(DisableValidationKind &DisableValidationForModuleKind::PCH)
: Listener(bool(DisableValidationKind & DisableValidationForModuleKind::PCH)
? cast<ASTReaderListener>(new SimpleASTReaderListener(PP))
: cast<ASTReaderListener>(new PCHValidator(PP, *this))),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PP(PP),
ContextObj(Context), ModuleMgr(PP.getFileManager(), ModuleCache,
PCHContainerRdr, PP.getHeaderSearchInfo()),
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()),
StackHandler(Diags), PP(PP), ContextObj(Context),
ModuleMgr(PP.getFileManager(), ModuleCache, PCHContainerRdr,
PP.getHeaderSearchInfo()),
DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
DisableValidationKind(DisableValidationKind),
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),

View File

@ -4168,8 +4168,7 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
D->setDeclContext(Context.getTranslationUnitDecl());
// Reading some declarations can result in deep recursion.
clang::runWithSufficientStackSpace([&] { warnStackExhausted(DeclLoc); },
[&] { Reader.Visit(D); });
runWithSufficientStackSpace(DeclLoc, [&] { Reader.Visit(D); });
// If this declaration is also a declaration context, get the
// offsets for its tables of lexical and visible declarations.