[clang] Deduplicate the logic that only warns once when stack is almost full (#112552)
Zero diff in behavior.
This commit is contained in:
parent
508fd966fb
commit
09cc75e2cc
45
clang/include/clang/Basic/StackExhaustionHandler.h
Normal file
45
clang/include/clang/Basic/StackExhaustionHandler.h
Normal 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
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -89,6 +89,7 @@ add_clang_library(clangBasic
|
||||
SourceManager.cpp
|
||||
SourceMgrAdapter.cpp
|
||||
Stack.cpp
|
||||
StackExhaustionHandler.cpp
|
||||
TargetID.cpp
|
||||
TargetInfo.cpp
|
||||
Targets.cpp
|
||||
|
||||
35
clang/lib/Basic/StackExhaustionHandler.cpp
Normal file
35
clang/lib/Basic/StackExhaustionHandler.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user