Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions clang/include/clang/Basic/SingleWarningStackAwareExecutor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//===--- SingleWarningStackAwareExecutor.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_SINGLE_WARNING_STACK_AWARE_EXECUTOR_H
#define LLVM_CLANG_BASIC_SINGLE_WARNING_STACK_AWARE_EXECUTOR_H

#include "clang/Basic/Diagnostic.h"

namespace clang {
class SingleWarningStackAwareExecutor {
public:
SingleWarningStackAwareExecutor(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_SINGLE_WARNING_STACK_AWARE_EXECUTOR_H
6 changes: 2 additions & 4 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/SingleWarningStackAwareExecutor.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
Expand Down Expand Up @@ -546,9 +547,6 @@ class Sema final : public SemaBase {
/// 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,
Expand Down Expand Up @@ -1183,7 +1181,7 @@ class Sema final : public SemaBase {
std::optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo;
bool WarnedDarwinSDKInfoMissing = false;

bool WarnedStackExhausted = false;
SingleWarningStackAwareExecutor StackAwareExecutor;

Sema(const Sema &) = delete;
void operator=(const Sema &) = delete;
Expand Down
6 changes: 4 additions & 2 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Stack.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderSearch.h"
Expand Down Expand Up @@ -445,7 +446,7 @@ class ASTReader
DiagnosticsEngine &Diags;
// Sema has duplicate logic, but SemaObj can sometimes be null so ASTReader
// has its own version.
bool WarnedStackExhausted = false;
SingleWarningStackAwareExecutor StackAwareExecutor;

/// The semantic analysis object that will be processing the
/// AST files and the translation unit that uses it.
Expand Down Expand Up @@ -2180,7 +2181,8 @@ class ASTReader
/// 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);

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ add_clang_library(clangBasic
SanitizerSpecialCaseList.cpp
Sanitizers.cpp
Sarif.cpp
SingleWarningStackAwareExecutor.cpp
SourceLocation.cpp
SourceManager.cpp
SourceMgrAdapter.cpp
Expand Down
36 changes: 36 additions & 0 deletions clang/lib/Basic/SingleWarningStackAwareExecutor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===--- SingleWarningStackAwareExecutor.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/SingleWarningStackAwareExecutor.h"
#include "clang/Basic/Stack.h"

void clang::SingleWarningStackAwareExecutor::runWithSufficientStackSpace(
SourceLocation Loc, llvm::function_ref<void()> Fn) {
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
}

void clang::SingleWarningStackAwareExecutor::warnOnStackNearlyExhausted(
SourceLocation Loc) {
if (isStackNearlyExhausted())
warnStackExhausted(Loc);
}

void clang::SingleWarningStackAwareExecutor::warnStackExhausted(
SourceLocation Loc) {
// Only warn about this once.
if (!WarnedStackExhausted) {
DiagsRef.Report(Loc, diag::warn_stack_exhausted);
WarnedStackExhausted = true;
}
}
12 changes: 2 additions & 10 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,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), StackAwareExecutor(diags),
SanitizerMD(new SanitizerMetadata(*this)) {

// Initialize the type cache.
Expand Down Expand Up @@ -1594,17 +1594,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);
StackAwareExecutor.runWithSufficientStackSpace(Loc, Fn);
}

llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/ProfileList.h"
#include "clang/Basic/SingleWarningStackAwareExecutor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/XRayLists.h"
#include "clang/Lex/PreprocessorOptions.h"
Expand Down Expand Up @@ -336,7 +337,7 @@ class CodeGenModule : public CodeGenTypeCache {
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
InstrProfStats PGOStats;
std::unique_ptr<llvm::SanitizerStatReport> SanStats;
bool WarnedStackExhausted = false;
SingleWarningStackAwareExecutor StackAwareExecutor;

// 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
Expand Down Expand Up @@ -1298,9 +1299,6 @@ class CodeGenModule : public CodeGenTypeCache {
/// 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
Expand Down
12 changes: 2 additions & 10 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
StackAwareExecutor(Diags), CurScope(nullptr), Ident_super(nullptr),
AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
ARMPtr(std::make_unique<SemaARM>(*this)),
AVRPtr(std::make_unique<SemaAVR>(*this)),
Expand Down Expand Up @@ -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);
StackAwareExecutor.runWithSufficientStackSpace(Loc, Fn);
}

bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
StackAwareExecutor.warnOnStackNearlyExhausted(Ctx.PointOfInstantiation);
}

void Sema::popCodeSynthesisContext() {
Expand Down
21 changes: 10 additions & 11 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
StackAwareExecutor.runWithSufficientStackSpace(Loc, Fn);
}

/// Retrieve the identifier table associated with the
Expand Down Expand Up @@ -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()),
StackAwareExecutor(Diags), PP(PP), ContextObj(Context),
ModuleMgr(PP.getFileManager(), ModuleCache, PCHContainerRdr,
PP.getHeaderSearchInfo()),
DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
DisableValidationKind(DisableValidationKind),
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading