-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Deduplicate the logic that only warns once when stack is almost full #112371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-modules Author: Boaz Brickner (bricknerb) ChangesZero diff in behavior. Full diff: https://github.com/llvm/llvm-project/pull/112371.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/Stack.h b/clang/include/clang/Basic/Stack.h
index 30ebd94aedd1f7..64367d8519bf84 100644
--- a/clang/include/clang/Basic/Stack.h
+++ b/clang/include/clang/Basic/Stack.h
@@ -16,6 +16,8 @@
#include <cstddef>
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
@@ -50,6 +52,31 @@ namespace clang {
Fn();
#endif
}
+
+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_STACK_H
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0faa5aed4eec3b..9c846f2b6b12f0 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -49,6 +49,7 @@
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/Stack.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/TypeTraits.h"
@@ -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,
@@ -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;
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index ee4e897b248882..2c6251ce0190c6 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -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"
@@ -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.
@@ -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);
diff --git a/clang/lib/Basic/Stack.cpp b/clang/lib/Basic/Stack.cpp
index aa15d8e66950fa..476612e281422b 100644
--- a/clang/lib/Basic/Stack.cpp
+++ b/clang/lib/Basic/Stack.cpp
@@ -72,3 +72,23 @@ void clang::runWithSufficientStackSpaceSlow(llvm::function_ref<void()> Diag,
Fn();
}, DesiredStackSize);
}
+
+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;
+ }
+}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index b05ab3606a698b..3153ec8a2d00e3 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -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.
@@ -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) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index fa82a81b05dd53..f4de284369384e 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -26,6 +26,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/ProfileList.h"
+#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/XRayLists.h"
#include "clang/Lex/PreprocessorOptions.h"
@@ -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
@@ -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
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index f0d1634af529f0..edb13226758ad9 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -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)),
@@ -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,
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8c7f694c09042e..8fb503c6f7e639 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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() {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index ecc5d3c59a3549..70b682dcbe68c4 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -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);
+ StackAwareExecutor.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()),
+ 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),
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 1ccc810f415eb4..d4e392dcc6bcd0 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -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.
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Adding @ChuanqiXu9 to get another pair of eyes on it (for naming, code structure, etc). I believe he was involved in reviewing some changes touching Please give him a chance to review this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took a pretty quick scanning and this looks good to me.
Recreated in #112552. |
Zero diff in behavior.