[clang] [Draft] Summary Based Analysis Prototype (PR #144224)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 14 07:27:49 PDT 2025
https://github.com/isuckatcs updated https://github.com/llvm/llvm-project/pull/144224
>From 7fba0addb97f9195eb307882254207f9b58072f2 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 22 May 2025 22:43:35 +0200
Subject: [PATCH 01/25] [clang][Driver] Add option to emit summaries
---
clang/include/clang/Driver/Options.td | 13 ++++++++++
.../include/clang/Frontend/FrontendOptions.h | 3 +++
clang/lib/Driver/ToolChains/Clang.cpp | 24 +++++++++++++++++++
clang/lib/Frontend/FrontendAction.cpp | 6 +++++
4 files changed, 46 insertions(+)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 22261621df092..f0c7b277e68e2 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5941,6 +5941,15 @@ def save_temps : Flag<["-", "--"], "save-temps">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, FlangOption, FC1Option]>,
Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
HelpText<"Alias for --save-temps=cwd">;
+def emit_summaries_EQ : Joined<["-", "--"], "emit-summaries=">, Flags<[NoXarchOption]>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Save summaries about the different functions. <arg> can be set to 'cwd' for "
+ "current working directory, or 'obj' which will save temporary files in the "
+ "same directory as the final output file">;
+def emit_summaries : Flag<["-", "--"], "emit-summaries">, Flags<[NoXarchOption]>,
+ Visibility<[ClangOption]>,
+ Alias<emit_summaries_EQ>, AliasArgs<["cwd"]>,
+ HelpText<"Alias for --emit-summaries=cwd">;
def save_stats_EQ : Joined<["-", "--"], "save-stats=">, Flags<[NoXarchOption]>,
HelpText<"Save llvm statistics.">;
def save_stats : Flag<["-", "--"], "save-stats">, Flags<[NoXarchOption]>,
@@ -8148,6 +8157,10 @@ defm emit_llvm_uselists : BoolOption<"", "emit-llvm-uselists",
NegFlag<SetFalse, [], [ClangOption], "Don't preserve">,
BothFlags<[], [ClangOption], " order of LLVM use-lists when serializing">>;
+def summary_file : Joined<["-"], "summary-file=">,
+ HelpText<"Filename to write summaries about function definitions to">,
+ MarshallingInfoString<FrontendOpts<"SummaryFile">>;
+
def print_stats : Flag<["-"], "print-stats">,
HelpText<"Print performance metrics and statistics">,
MarshallingInfoFlag<FrontendOpts<"ShowStats">>;
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index c919a53ae089e..af2451c1bde8e 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -534,6 +534,9 @@ class FrontendOptions {
/// minimization hints.
std::string DumpMinimizationHintsPath;
+ /// Filename to write summaries about function definitions to.
+ std::string SummaryFile;
+
public:
FrontendOptions()
: DisableFree(false), RelocatablePCH(false), ShowHelp(false),
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 2fb6cf8ea2bdc..676a4e34ddb27 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5470,6 +5470,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.getLastArg(options::OPT_save_temps_EQ))
Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
+ // FIXME: This needs to be cleaned up and needs proper error handling as well.
+ if (const Arg *A = Args.getLastArg(options::OPT_emit_summaries_EQ)) {
+ llvm::SmallString<10> input;
+ for (const auto &II : Inputs) {
+ if (!II.isFilename())
+ continue;
+
+ input = II.getFilename();
+ break;
+ }
+
+ if (!input.empty()) {
+ if (A->containsValue("cwd")) {
+ llvm::SmallString<10> filename = llvm::sys::path::filename(input);
+ llvm::sys::path::replace_extension(filename, "json");
+
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-summary-file=") + filename));
+ } else if (A->containsValue("obj")) {
+ // FIXME: implement
+ }
+ }
+ }
+
auto *MemProfArg = Args.getLastArg(options::OPT_fmemory_profile,
options::OPT_fmemory_profile_EQ,
options::OPT_fno_memory_profile);
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 54a2e3eb297f5..868a1f70abd43 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -1253,6 +1253,12 @@ void FrontendAction::EndSourceFile() {
// Finalize the action.
EndSourceFileAction();
+ if (CI.hasSema() && !CI.getFrontendOpts().SummaryFile.empty()) {
+ std::error_code EC;
+ llvm::raw_fd_ostream(CI.getFrontendOpts().SummaryFile, EC,
+ llvm::sys::fs::CD_CreateAlways);
+ }
+
// Sema references the ast consumer, so reset sema first.
//
// FIXME: There is more per-file stuff we could just drop here?
>From 3d7d23ad7815ef4527f000651f4321348b200873 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 7 Jun 2025 21:38:36 +0200
Subject: [PATCH 02/25] [clang][Summary] add the summarizer skeleton
---
.../include/clang/Frontend/CompilerInstance.h | 21 ++++++++++++++++++-
clang/include/clang/Sema/Sema.h | 6 +++++-
clang/include/clang/Sema/SemaSummarizer.h | 19 +++++++++++++++++
clang/include/clang/Sema/SummaryConsumer.h | 8 +++++++
clang/lib/Frontend/ChainedIncludesSource.cpp | 2 +-
clang/lib/Frontend/CompilerInstance.cpp | 11 ++++++++--
clang/lib/Frontend/FrontendAction.cpp | 10 ++++++++-
clang/lib/Frontend/FrontendActions.cpp | 2 +-
clang/lib/Sema/CMakeLists.txt | 1 +
clang/lib/Sema/Sema.cpp | 7 ++++++-
clang/lib/Sema/SemaDecl.cpp | 4 ++++
clang/lib/Sema/SemaSummarizer.cpp | 8 +++++++
clang/lib/Testing/TestAST.cpp | 2 +-
clang/unittests/CodeGen/TestCompiler.h | 2 +-
.../unittests/Frontend/CodeGenActionTest.cpp | 2 +-
.../unittests/Sema/ExternalSemaSourceTest.cpp | 2 +-
clang/unittests/Sema/SemaLookupTest.cpp | 2 +-
17 files changed, 96 insertions(+), 13 deletions(-)
create mode 100644 clang/include/clang/Sema/SemaSummarizer.h
create mode 100644 clang/include/clang/Sema/SummaryConsumer.h
create mode 100644 clang/lib/Sema/SemaSummarizer.cpp
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 5f25a932c5052..f296e6d042a54 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -48,6 +48,7 @@ class ModuleFile;
}
class CodeCompleteConsumer;
+class SummaryConsumer;
class DiagnosticsEngine;
class DiagnosticConsumer;
class FileManager;
@@ -121,6 +122,9 @@ class CompilerInstance : public ModuleLoader {
/// The code completion consumer.
std::unique_ptr<CodeCompleteConsumer> CompletionConsumer;
+ /// The summary consumer.
+ std::unique_ptr<SummaryConsumer> TheSummaryConsumer;
+
/// The semantic analysis object.
std::unique_ptr<Sema> TheSema;
@@ -607,6 +611,18 @@ class CompilerInstance : public ModuleLoader {
return *CompletionConsumer;
}
+ /// @}
+ /// @name Summary
+ /// @{
+
+ bool hasSummaryConsumer() const { return (bool)TheSummaryConsumer; }
+
+ SummaryConsumer &getSummaryConsumer() const {
+ assert(TheSummaryConsumer &&
+ "Compiler instance has no code summary consumer!");
+ return *TheSummaryConsumer;
+ }
+
/// setCodeCompletionConsumer - Replace the current code completion consumer;
/// the compiler instance takes ownership of \p Value.
void setCodeCompletionConsumer(CodeCompleteConsumer *Value);
@@ -736,9 +752,12 @@ class CompilerInstance : public ModuleLoader {
Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column,
const CodeCompleteOptions &Opts, raw_ostream &OS);
+ void createSummaryConsumer();
+
/// Create the Sema object to be used for parsing.
void createSema(TranslationUnitKind TUKind,
- CodeCompleteConsumer *CompletionConsumer);
+ CodeCompleteConsumer *CompletionConsumer,
+ SummaryConsumer *SummaryConsumer);
/// Create the frontend timer and replace any existing one with it.
void createFrontendTimer();
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index fe93df94438cb..9cb2158ab4ff1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -125,6 +125,7 @@ class CXXBasePath;
class CXXBasePaths;
class CXXFieldCollector;
class CodeCompleteConsumer;
+class SummaryConsumer;
enum class ComparisonCategoryType : unsigned char;
class ConstraintSatisfaction;
class DarwinSDKInfo;
@@ -159,6 +160,7 @@ class SemaARM;
class SemaAVR;
class SemaBPF;
class SemaCodeCompletion;
+class SemaSummarizer;
class SemaCUDA;
class SemaDirectX;
class SemaHLSL;
@@ -883,7 +885,8 @@ class Sema final : public SemaBase {
public:
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind = TU_Complete,
- CodeCompleteConsumer *CompletionConsumer = nullptr);
+ CodeCompleteConsumer *CompletionConsumer = nullptr,
+ SummaryConsumer *SummaryConsumer = nullptr);
~Sema();
/// Perform initialization that occurs after the parser has been
@@ -1564,6 +1567,7 @@ class Sema final : public SemaBase {
std::unique_ptr<SemaAVR> AVRPtr;
std::unique_ptr<SemaBPF> BPFPtr;
std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
+ std::unique_ptr<SemaSummarizer> SummarizerPtr;
std::unique_ptr<SemaCUDA> CUDAPtr;
std::unique_ptr<SemaDirectX> DirectXPtr;
std::unique_ptr<SemaHLSL> HLSLPtr;
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
new file mode 100644
index 0000000000000..3661e443bb2de
--- /dev/null
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -0,0 +1,19 @@
+#ifndef LLVM_CLANG_SEMA_SEMASUMMARIZER_H
+#define LLVM_CLANG_SEMA_SEMASUMMARIZER_H
+
+#include "clang/Sema/SemaBase.h"
+#include "clang/Sema/SummaryConsumer.h"
+
+namespace clang {
+class SemaSummarizer : public SemaBase {
+public:
+ SemaSummarizer(Sema &S, SummaryConsumer *SummaryConsumer)
+ : SemaBase(S), SummaryConsumer(SummaryConsumer) {}
+
+ SummaryConsumer *SummaryConsumer;
+
+ void SummarizeFunctionBody(FunctionDecl *FD) const;
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMASUMMARIZE_H
diff --git a/clang/include/clang/Sema/SummaryConsumer.h b/clang/include/clang/Sema/SummaryConsumer.h
new file mode 100644
index 0000000000000..8aa2713b46c65
--- /dev/null
+++ b/clang/include/clang/Sema/SummaryConsumer.h
@@ -0,0 +1,8 @@
+#ifndef LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
+#define LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
+
+namespace clang {
+class SummaryConsumer {};
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index 95b0ed248d545..437f5387375f7 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -142,7 +142,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(std::move(consumer));
- Clang->createSema(TU_Prefix, nullptr);
+ Clang->createSema(TU_Prefix, nullptr, nullptr);
if (firstInclude) {
Preprocessor &PP = Clang->getPreprocessor();
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 503d36467653e..917a187f49fb5 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -37,6 +37,7 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
+#include "clang/Sema/SummaryConsumer.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/InMemoryModuleCache.h"
@@ -741,10 +742,16 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
return new PrintingCodeCompleteConsumer(Opts, OS);
}
+void CompilerInstance::createSummaryConsumer() {
+ TheSummaryConsumer.reset(
+ getFrontendOpts().SummaryFile.empty() ? nullptr : new SummaryConsumer());
+}
+
void CompilerInstance::createSema(TranslationUnitKind TUKind,
- CodeCompleteConsumer *CompletionConsumer) {
+ CodeCompleteConsumer *CompletionConsumer,
+ SummaryConsumer *SummaryConsumer) {
TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
- TUKind, CompletionConsumer));
+ TUKind, CompletionConsumer, SummaryConsumer));
// Set up API notes.
TheSema->APINotes.setSwiftVersion(getAPINotesOpts().SwiftVersion);
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 868a1f70abd43..aeeab901b9ed7 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -1339,8 +1339,16 @@ void ASTFrontendAction::ExecuteAction() {
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();
+ CI.createSummaryConsumer();
+
+ // Use a code completion consumer?
+ SummaryConsumer *SummaryConsumer = nullptr;
+ if (CI.hasSummaryConsumer())
+ SummaryConsumer = &CI.getSummaryConsumer();
+
if (!CI.hasSema())
- CI.createSema(getTranslationUnitKind(), CompletionConsumer);
+ CI.createSema(getTranslationUnitKind(), CompletionConsumer,
+ SummaryConsumer);
ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
CI.getFrontendOpts().SkipFunctionBodies);
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 8c75e1a46da54..49f1420c75047 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -52,7 +52,7 @@ void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {
if (!CI.hasSema())
CI.createSema(Action.getTranslationUnitKind(),
- GetCodeCompletionConsumer(CI));
+ GetCodeCompletionConsumer(CI), nullptr);
}
} // namespace
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 4b87004e4b8ea..5237f20201fde 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -85,6 +85,7 @@ add_clang_library(clangSema
SemaStmt.cpp
SemaStmtAsm.cpp
SemaStmtAttr.cpp
+ SemaSummarizer.cpp
SemaSPIRV.cpp
SemaSYCL.cpp
SemaSwift.cpp
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 1901d19b14dfc..2410d513c299e 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -64,6 +64,7 @@
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
#include "clang/Sema/SemaSYCL.h"
+#include "clang/Sema/SemaSummarizer.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
@@ -248,7 +249,8 @@ const unsigned Sema::MaxAlignmentExponent;
const uint64_t Sema::MaximumAlignment;
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
- TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
+ TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter,
+ SummaryConsumer *SummaryConsumer)
: SemaBase(*this), CollectStats(false), TUKind(TUKind),
CurFPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp),
Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()),
@@ -263,6 +265,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
BPFPtr(std::make_unique<SemaBPF>(*this)),
CodeCompletionPtr(
std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
+ SummarizerPtr(SummaryConsumer ? std::make_unique<SemaSummarizer>(
+ *this, SummaryConsumer)
+ : nullptr),
CUDAPtr(std::make_unique<SemaCUDA>(*this)),
DirectXPtr(std::make_unique<SemaDirectX>(*this)),
HLSLPtr(std::make_unique<SemaHLSL>(*this)),
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 814f81cb64cae..bb80fd2a46f58 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -55,6 +55,7 @@
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSYCL.h"
+#include "clang/Sema/SemaSummarizer.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/Template.h"
@@ -16694,6 +16695,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD && !FD->isDeleted())
checkTypeSupport(FD->getType(), FD->getLocation(), FD);
+ if (FD && SummarizerPtr)
+ SummarizerPtr->SummarizeFunctionBody(FD);
+
return dcl;
}
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
new file mode 100644
index 0000000000000..ce1d514d3df9c
--- /dev/null
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -0,0 +1,8 @@
+#include "clang/Sema/SemaSummarizer.h"
+
+namespace clang {
+void SemaSummarizer::SummarizeFunctionBody(FunctionDecl *FD) const {
+ FD->dump();
+}
+
+} // namespace clang
\ No newline at end of file
diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp
index 748f59b856e83..db0490689da53 100644
--- a/clang/lib/Testing/TestAST.cpp
+++ b/clang/lib/Testing/TestAST.cpp
@@ -69,7 +69,7 @@ void createMissingComponents(CompilerInstance &Clang) {
if (!Clang.hasASTContext())
Clang.createASTContext();
if (!Clang.hasSema())
- Clang.createSema(TU_Complete, /*CodeCompleteConsumer=*/nullptr);
+ Clang.createSema(TU_Complete, /*CodeCompleteConsumer=*/nullptr, nullptr);
}
} // namespace
diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h
index a6fec7fb0945d..760fa340c3d74 100644
--- a/clang/unittests/CodeGen/TestCompiler.h
+++ b/clang/unittests/CodeGen/TestCompiler.h
@@ -69,7 +69,7 @@ struct TestCompiler {
compiler.setASTConsumer(std::move(Consumer));
- compiler.createSema(clang::TU_Prefix, nullptr);
+ compiler.createSema(clang::TU_Prefix, nullptr, nullptr);
clang::SourceManager &sm = compiler.getSourceManager();
sm.setMainFileID(sm.createFileID(
diff --git a/clang/unittests/Frontend/CodeGenActionTest.cpp b/clang/unittests/Frontend/CodeGenActionTest.cpp
index 90818b72cd6e6..e958ea1993a4a 100644
--- a/clang/unittests/Frontend/CodeGenActionTest.cpp
+++ b/clang/unittests/Frontend/CodeGenActionTest.cpp
@@ -37,7 +37,7 @@ class NullCodeGenAction : public CodeGenAction {
if (!CI.hasPreprocessor())
return;
if (!CI.hasSema())
- CI.createSema(getTranslationUnitKind(), nullptr);
+ CI.createSema(getTranslationUnitKind(), nullptr, nullptr);
}
};
diff --git a/clang/unittests/Sema/ExternalSemaSourceTest.cpp b/clang/unittests/Sema/ExternalSemaSourceTest.cpp
index 2b271d4bf7825..d223a7135ee84 100644
--- a/clang/unittests/Sema/ExternalSemaSourceTest.cpp
+++ b/clang/unittests/Sema/ExternalSemaSourceTest.cpp
@@ -194,7 +194,7 @@ class ExternalSemaSourceInstaller : public clang::ASTFrontendAction {
void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
ASSERT_FALSE(CI.hasSema());
- CI.createSema(getTranslationUnitKind(), nullptr);
+ CI.createSema(getTranslationUnitKind(), nullptr, nullptr);
ASSERT_TRUE(CI.hasDiagnostics());
DiagnosticsEngine &Diagnostics = CI.getDiagnostics();
DiagnosticConsumer *Client = Diagnostics.getClient();
diff --git a/clang/unittests/Sema/SemaLookupTest.cpp b/clang/unittests/Sema/SemaLookupTest.cpp
index d97b571f6a37c..96c27945421f9 100644
--- a/clang/unittests/Sema/SemaLookupTest.cpp
+++ b/clang/unittests/Sema/SemaLookupTest.cpp
@@ -22,7 +22,7 @@ class LookupAction : public ASTFrontendAction {
void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
ASSERT_FALSE(CI.hasSema());
- CI.createSema(getTranslationUnitKind(), nullptr);
+ CI.createSema(getTranslationUnitKind(), nullptr, nullptr);
ASSERT_TRUE(CI.hasSema());
Sema &S = CI.getSema();
ParseAST(S);
>From 2592f08b25c7394f7a765a4ca1ecb9ce69657560 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sun, 8 Jun 2025 00:21:20 +0200
Subject: [PATCH 03/25] [clang][Summary] implement summary base prototype
---
clang/include/clang/Sema/SemaSummarizer.h | 2 +-
clang/lib/Sema/SemaSummarizer.cpp | 57 +++++++++++++++++++++--
2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 3661e443bb2de..45e97529a2f1f 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -12,7 +12,7 @@ class SemaSummarizer : public SemaBase {
SummaryConsumer *SummaryConsumer;
- void SummarizeFunctionBody(FunctionDecl *FD) const;
+ void SummarizeFunctionBody(const FunctionDecl *FD);
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index ce1d514d3df9c..65ac0a7e4ec36 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -1,8 +1,59 @@
#include "clang/Sema/SemaSummarizer.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Index/USRGeneration.h"
+#include <set>
namespace clang {
-void SemaSummarizer::SummarizeFunctionBody(FunctionDecl *FD) const {
- FD->dump();
+namespace {
+class FunctionSummary {
+ SmallVector<char> ID;
+ std::vector<std::string> FunctionAttrs;
+ std::set<SmallVector<char>> Calls;
+
+public:
+ void addCall(const clang::FunctionDecl *FD) {
+ SmallVector<char> Call;
+ index::generateUSRForDecl(FD, Call);
+ Calls.emplace(Call);
+ }
+
+ FunctionSummary(const clang::FunctionDecl *FD) {
+ index::generateUSRForDecl(FD, ID);
+ }
+};
+
+class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
+ FunctionSummary *Summary;
+
+public:
+ CallCollector(FunctionSummary &Summary) : Summary(&Summary) {}
+
+ virtual void
+ run(const ast_matchers::MatchFinder::MatchResult &Result) override {
+ const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
+ if (!Call)
+ return;
+
+ const auto *Callee = llvm::dyn_cast<FunctionDecl>(Call->getCalleeDecl());
+ Summary->addCall(Callee);
+ }
+};
+
+void CollectCalledFunctions(const FunctionDecl *FD, FunctionSummary &Summary) {
+ using namespace ast_matchers;
+ MatchFinder Finder;
+ CallCollector CC(Summary);
+
+ Finder.addMatcher(functionDecl(forEachDescendant(callExpr().bind("call"))),
+ &CC);
+ Finder.match(*FD, FD->getASTContext());
+}
+
+} // namespace
+
+void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
+ FunctionSummary Summary(FD);
+ CollectCalledFunctions(FD, Summary);
}
-} // namespace clang
\ No newline at end of file
+} // namespace clang
>From 43c1b90334a7abc7caf636f6bc15ff4a3194be13 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sun, 8 Jun 2025 14:53:27 +0200
Subject: [PATCH 04/25] [clang][Summary] implement summary inference prototype
---
clang/include/clang/Sema/SemaSummarizer.h | 22 ++++-
clang/include/clang/Sema/SummaryAttribute.h | 54 ++++++++++++
clang/lib/Sema/SemaSummarizer.cpp | 95 +++++++++++++++------
3 files changed, 141 insertions(+), 30 deletions(-)
create mode 100644 clang/include/clang/Sema/SummaryAttribute.h
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 45e97529a2f1f..71ec68cf947ba 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -2,15 +2,31 @@
#define LLVM_CLANG_SEMA_SEMASUMMARIZER_H
#include "clang/Sema/SemaBase.h"
+#include "clang/Sema/SummaryAttribute.h"
#include "clang/Sema/SummaryConsumer.h"
+#include <set>
namespace clang {
+class FunctionSummary {
+ SmallVector<char> ID;
+ std::set<SummaryAttribute> FunctionAttrs;
+ std::set<SmallVector<char>> Calls;
+
+public:
+ FunctionSummary(const clang::FunctionDecl *FD);
+
+ void addAttribute(SummaryAttribute Attr) { FunctionAttrs.emplace(Attr); }
+ bool hasAttribute(SummaryAttribute Attr) { return FunctionAttrs.count(Attr); }
+
+ void addCall(const clang::FunctionDecl *FD);
+};
+
class SemaSummarizer : public SemaBase {
public:
- SemaSummarizer(Sema &S, SummaryConsumer *SummaryConsumer)
- : SemaBase(S), SummaryConsumer(SummaryConsumer) {}
+ SemaSummarizer(Sema &S, SummaryConsumer *SummaryConsumer);
- SummaryConsumer *SummaryConsumer;
+ std::vector<std::unique_ptr<SummaryAttributeManager>> Attributes;
+ SummaryConsumer *TheSummaryConsumer;
void SummarizeFunctionBody(const FunctionDecl *FD);
};
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
new file mode 100644
index 0000000000000..ed8a8125d22f1
--- /dev/null
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -0,0 +1,54 @@
+#ifndef LLVM_CLANG_SEMA_SEMASUMMARYATTRIBUTE_H
+#define LLVM_CLANG_SEMA_SEMASUMMARYATTRIBUTE_H
+
+#include "clang/AST/Decl.h"
+#include <string>
+
+namespace clang {
+enum SummaryAttribute {
+ NO_WRITE_GLOBAL,
+};
+
+class FunctionSummary;
+
+class SummaryAttributeManager {
+ inline static std::unordered_map<SummaryAttribute, std::string> AttrToStr;
+
+protected:
+ const SummaryAttribute Attr;
+ const char *Str;
+
+public:
+ SummaryAttributeManager(SummaryAttribute Attr, const char *Str)
+ : Attr(Attr), Str(Str) {
+ assert(AttrToStr.count(Attr) == 0 && "attribute already registered");
+ for (auto &&[attr, str] : AttrToStr)
+ assert(str != Str && "attribute representation is already used");
+
+ AttrToStr[Attr] = Str;
+ }
+ virtual ~SummaryAttributeManager() = default;
+
+ virtual bool predicate(const FunctionDecl *FD) = 0;
+
+ // FIXME: This should receive all the parsed summaries as well.
+ virtual bool merge(FunctionSummary &Summary) = 0;
+
+ virtual std::string serialize() const { return Str; };
+ virtual std::optional<SummaryAttribute> parse(std::string_view Input) const {
+ if (Str == Input)
+ return Attr;
+
+ return std::nullopt;
+ };
+
+ std::optional<SummaryAttribute> infer(const FunctionDecl *FD) {
+ if (predicate(FD))
+ return Attr;
+
+ return std::nullopt;
+ };
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMASUMMARYATTRIBUTEH
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 65ac0a7e4ec36..1a7dd7ba26f99 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -1,31 +1,14 @@
#include "clang/Sema/SemaSummarizer.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Index/USRGeneration.h"
+#include "clang/Sema/SummaryConsumer.h"
#include <set>
namespace clang {
namespace {
-class FunctionSummary {
- SmallVector<char> ID;
- std::vector<std::string> FunctionAttrs;
- std::set<SmallVector<char>> Calls;
-
-public:
- void addCall(const clang::FunctionDecl *FD) {
- SmallVector<char> Call;
- index::generateUSRForDecl(FD, Call);
- Calls.emplace(Call);
- }
-
- FunctionSummary(const clang::FunctionDecl *FD) {
- index::generateUSRForDecl(FD, ID);
- }
-};
-
class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
FunctionSummary *Summary;
-public:
CallCollector(FunctionSummary &Summary) : Summary(&Summary) {}
virtual void
@@ -37,23 +20,81 @@ class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
const auto *Callee = llvm::dyn_cast<FunctionDecl>(Call->getCalleeDecl());
Summary->addCall(Callee);
}
+
+public:
+ static void CollectCalledFunctions(const FunctionDecl *FD,
+ FunctionSummary &Summary) {
+ using namespace ast_matchers;
+ MatchFinder Finder;
+ CallCollector CC(Summary);
+
+ Finder.addMatcher(functionDecl(forEachDescendant(callExpr().bind("call"))),
+ &CC);
+ Finder.match(*FD, FD->getASTContext());
+ }
};
-void CollectCalledFunctions(const FunctionDecl *FD, FunctionSummary &Summary) {
- using namespace ast_matchers;
- MatchFinder Finder;
- CallCollector CC(Summary);
+class NoWriteGlobalAttrManager : public SummaryAttributeManager {
+ class Callback : public ast_matchers::MatchFinder::MatchCallback {
+ public:
+ bool WriteGlobal = false;
- Finder.addMatcher(functionDecl(forEachDescendant(callExpr().bind("call"))),
- &CC);
- Finder.match(*FD, FD->getASTContext());
-}
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override {
+ const auto *Assignment =
+ Result.Nodes.getNodeAs<BinaryOperator>("assignment");
+ if (!Assignment)
+ return;
+
+ WriteGlobal = true;
+ };
+ };
+public:
+ NoWriteGlobalAttrManager()
+ : SummaryAttributeManager(NO_WRITE_GLOBAL, "no_write_global") {}
+
+ bool predicate(const FunctionDecl *FD) override {
+ using namespace ast_matchers;
+ MatchFinder Finder;
+ Callback CB;
+
+ Finder.addMatcher(
+ functionDecl(forEachDescendant(
+ binaryOperator(isAssignmentOperator(),
+ hasLHS(declRefExpr(to(varDecl(hasGlobalStorage())))))
+ .bind("assignment"))),
+ &CB);
+ Finder.match(*FD, FD->getASTContext());
+ return !CB.WriteGlobal;
+ };
+
+ bool merge(FunctionSummary &Summary) override { return true; };
+};
} // namespace
+void FunctionSummary::addCall(const clang::FunctionDecl *FD) {
+ SmallVector<char> Call;
+ index::generateUSRForDecl(FD, Call);
+ Calls.emplace(Call);
+}
+
+FunctionSummary::FunctionSummary(const clang::FunctionDecl *FD) {
+ index::generateUSRForDecl(FD, ID);
+}
+
+SemaSummarizer::SemaSummarizer(Sema &S, SummaryConsumer *SummaryConsumer)
+ : SemaBase(S), TheSummaryConsumer(SummaryConsumer) {
+ Attributes.emplace_back(std::make_unique<NoWriteGlobalAttrManager>());
+}
+
void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
FunctionSummary Summary(FD);
- CollectCalledFunctions(FD, Summary);
+ CallCollector::CollectCalledFunctions(FD, Summary);
+
+ for (auto &&Attr : Attributes) {
+ if (const auto &InferredAttr = Attr->infer(FD))
+ Summary.addAttribute(*InferredAttr);
+ }
}
} // namespace clang
>From f1ea491e6f2cf7c6d21f25b611cd33cd6607567b Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sun, 8 Jun 2025 17:08:55 +0200
Subject: [PATCH 05/25] [clang][Summary] summary printing prototype
---
clang/include/clang/Sema/SemaSummarizer.h | 10 ++++++-
clang/include/clang/Sema/SummaryAttribute.h | 3 ++-
clang/include/clang/Sema/SummaryConsumer.h | 30 ++++++++++++++++++++-
clang/lib/Frontend/CompilerInstance.cpp | 12 +++++++--
clang/lib/Frontend/FrontendAction.cpp | 6 -----
clang/lib/Sema/CMakeLists.txt | 1 +
clang/lib/Sema/Sema.cpp | 5 ++++
clang/lib/Sema/SemaSummarizer.cpp | 13 +++++++++
clang/lib/Sema/SummaryConsumer.cpp | 24 +++++++++++++++++
9 files changed, 93 insertions(+), 11 deletions(-)
create mode 100644 clang/lib/Sema/SummaryConsumer.cpp
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 71ec68cf947ba..ef40599d982a1 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -15,8 +15,12 @@ class FunctionSummary {
public:
FunctionSummary(const clang::FunctionDecl *FD);
+ SmallVector<char> getID() const { return ID; }
+ const std::set<SummaryAttribute> &getFunctionAttrs() const { return FunctionAttrs; }
+ const std::set<SmallVector<char>> &getCalls() const { return Calls; }
+
void addAttribute(SummaryAttribute Attr) { FunctionAttrs.emplace(Attr); }
- bool hasAttribute(SummaryAttribute Attr) { return FunctionAttrs.count(Attr); }
+ bool hasAttribute(SummaryAttribute Attr) const { return FunctionAttrs.count(Attr); }
void addCall(const clang::FunctionDecl *FD);
};
@@ -28,7 +32,11 @@ class SemaSummarizer : public SemaBase {
std::vector<std::unique_ptr<SummaryAttributeManager>> Attributes;
SummaryConsumer *TheSummaryConsumer;
+ void ActOnStartOfSourceFile();
+ void ActOnEndOfSourceFile();
+
void SummarizeFunctionBody(const FunctionDecl *FD);
+
};
} // namespace clang
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index ed8a8125d22f1..2d2fd1e4ff623 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -34,7 +34,8 @@ class SummaryAttributeManager {
// FIXME: This should receive all the parsed summaries as well.
virtual bool merge(FunctionSummary &Summary) = 0;
- virtual std::string serialize() const { return Str; };
+ // FIXME: bad design
+ static std::string serialize(SummaryAttribute Attr) { return AttrToStr[Attr]; };
virtual std::optional<SummaryAttribute> parse(std::string_view Input) const {
if (Str == Input)
return Attr;
diff --git a/clang/include/clang/Sema/SummaryConsumer.h b/clang/include/clang/Sema/SummaryConsumer.h
index 8aa2713b46c65..c2698288ce721 100644
--- a/clang/include/clang/Sema/SummaryConsumer.h
+++ b/clang/include/clang/Sema/SummaryConsumer.h
@@ -1,8 +1,36 @@
#ifndef LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
#define LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/JSON.h"
namespace clang {
-class SummaryConsumer {};
+class FunctionSummary;
+
+class SummaryConsumer {
+public:
+ virtual ~SummaryConsumer() = default;
+
+ virtual void ProcessStartOfSourceFile() {};
+ virtual void ProcessFunctionSummary(const FunctionSummary&) {};
+ virtual void ProcessEndOfSourceFile() {};
+};
+
+class PrintingSummaryConsumer : public SummaryConsumer {
+public:
+ PrintingSummaryConsumer(raw_ostream &OS)
+ : SummaryConsumer() {}
+};
+
+class JSONPrintingSummaryConsumer : public PrintingSummaryConsumer {
+ llvm::json::OStream JOS;
+
+public:
+ JSONPrintingSummaryConsumer(raw_ostream &OS) : PrintingSummaryConsumer(OS), JOS(OS, 2) {}
+
+ void ProcessStartOfSourceFile() override { JOS.arrayBegin(); };
+ void ProcessFunctionSummary(const FunctionSummary&) override;
+ void ProcessEndOfSourceFile() override { JOS.arrayEnd(); };
+};
} // namespace clang
#endif // LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 917a187f49fb5..c90b8884f5731 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -743,8 +743,16 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
}
void CompilerInstance::createSummaryConsumer() {
- TheSummaryConsumer.reset(
- getFrontendOpts().SummaryFile.empty() ? nullptr : new SummaryConsumer());
+ const std::string& SummaryFile = getFrontendOpts().SummaryFile;
+ if(SummaryFile.empty())
+ return;
+
+ std::error_code EC;
+ // FIXME: this being static is a design error
+ static llvm::raw_fd_ostream SummaryOS(SummaryFile, EC, llvm::sys::fs::CD_CreateAlways);
+
+ if(!EC)
+ TheSummaryConsumer.reset(new JSONPrintingSummaryConsumer(SummaryOS));
}
void CompilerInstance::createSema(TranslationUnitKind TUKind,
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index aeeab901b9ed7..35b0c0373533a 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -1253,12 +1253,6 @@ void FrontendAction::EndSourceFile() {
// Finalize the action.
EndSourceFileAction();
- if (CI.hasSema() && !CI.getFrontendOpts().SummaryFile.empty()) {
- std::error_code EC;
- llvm::raw_fd_ostream(CI.getFrontendOpts().SummaryFile, EC,
- llvm::sys::fs::CD_CreateAlways);
- }
-
// Sema references the ast consumer, so reset sema first.
//
// FIXME: There is more per-file stuff we could just drop here?
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 5237f20201fde..d6297016c015f 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -99,6 +99,7 @@ add_clang_library(clangSema
SemaType.cpp
SemaWasm.cpp
SemaX86.cpp
+ SummaryConsumer.cpp
TypeLocBuilder.cpp
DEPENDS
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 2410d513c299e..ae9f8c00081b3 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1147,6 +1147,9 @@ void Sema::ActOnStartOfTranslationUnit() {
if (getLangOpts().CPlusPlusModules &&
getLangOpts().getCompilingModule() == LangOptions::CMK_HeaderUnit)
HandleStartOfHeaderUnit();
+
+ if(SummarizerPtr)
+ SummarizerPtr->ActOnStartOfSourceFile();
}
void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
@@ -1222,6 +1225,8 @@ void Sema::ActOnEndOfTranslationUnit() {
assert(DelayedDiagnostics.getCurrentPool() == nullptr
&& "reached end of translation unit with a pool attached?");
+ if(SummarizerPtr)
+ SummarizerPtr->ActOnEndOfSourceFile();
// If code completion is enabled, don't perform any end-of-translation-unit
// work.
if (PP.isCodeCompletionEnabled())
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 1a7dd7ba26f99..9fbb940ec3fbb 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -87,6 +87,16 @@ SemaSummarizer::SemaSummarizer(Sema &S, SummaryConsumer *SummaryConsumer)
Attributes.emplace_back(std::make_unique<NoWriteGlobalAttrManager>());
}
+void SemaSummarizer::ActOnStartOfSourceFile() {
+ if(TheSummaryConsumer)
+ TheSummaryConsumer->ProcessStartOfSourceFile();
+}
+
+void SemaSummarizer::ActOnEndOfSourceFile() {
+ if(TheSummaryConsumer)
+ TheSummaryConsumer->ProcessEndOfSourceFile();
+}
+
void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
FunctionSummary Summary(FD);
CallCollector::CollectCalledFunctions(FD, Summary);
@@ -95,6 +105,9 @@ void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
if (const auto &InferredAttr = Attr->infer(FD))
Summary.addAttribute(*InferredAttr);
}
+
+ if(TheSummaryConsumer)
+ TheSummaryConsumer->ProcessFunctionSummary(Summary);
}
} // namespace clang
diff --git a/clang/lib/Sema/SummaryConsumer.cpp b/clang/lib/Sema/SummaryConsumer.cpp
new file mode 100644
index 0000000000000..45aeaee502ed9
--- /dev/null
+++ b/clang/lib/Sema/SummaryConsumer.cpp
@@ -0,0 +1,24 @@
+#include "clang/Sema/SummaryConsumer.h"
+#include "clang/Sema/SemaSummarizer.h"
+
+namespace clang {
+void JSONPrintingSummaryConsumer::ProcessFunctionSummary(const FunctionSummary &Summary) {
+ JOS.object([&]{
+ JOS.attribute("id", llvm::json::Value(Summary.getID()));
+ JOS.attributeObject("attrs", [&]{
+ JOS.attributeArray("function", [&]{
+ for(auto &&Attr : Summary.getFunctionAttrs()) {
+ JOS.value(llvm::json::Value(SummaryAttributeManager::serialize(Attr)));
+ }
+ });
+ });
+ JOS.attributeArray("calls", [&]{
+ for(auto &&Call : Summary.getCalls()) {
+ JOS.object([&]{
+ JOS.attribute("id", llvm::json::Value(Call));
+ });
+ }
+ });
+ });
+}
+} // namespace clang
\ No newline at end of file
>From 6fb640433209596d293316ed07dab58e014acf2a Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sun, 8 Jun 2025 22:26:29 +0200
Subject: [PATCH 06/25] [clang][Driver][Summary] add a flag to specify the
directory to parse the summaries from
---
clang/include/clang/Driver/Options.td | 4 +++
.../include/clang/Frontend/FrontendOptions.h | 3 ++
clang/lib/Driver/ToolChains/Clang.cpp | 3 ++
clang/lib/Frontend/FrontendAction.cpp | 29 +++++++++++++++++++
4 files changed, 39 insertions(+)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index f0c7b277e68e2..c66f098c459c2 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5941,6 +5941,10 @@ def save_temps : Flag<["-", "--"], "save-temps">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, FlangOption, FC1Option]>,
Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
HelpText<"Alias for --save-temps=cwd">;
+def summaries_dir_EQ : Joined<["-", "--"], "summaries-dir=">, Flags<[NoXarchOption]>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Read summaries about different functions from this directory">,
+ MarshallingInfoString<FrontendOpts<"SummaryDirPath">>;
def emit_summaries_EQ : Joined<["-", "--"], "emit-summaries=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Save summaries about the different functions. <arg> can be set to 'cwd' for "
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index af2451c1bde8e..20c60f823d5f3 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -537,6 +537,9 @@ class FrontendOptions {
/// Filename to write summaries about function definitions to.
std::string SummaryFile;
+ /// The directory used to load summary files.
+ std::string SummaryDirPath;
+
public:
FrontendOptions()
: DisableFree(false), RelocatablePCH(false), ShowHelp(false),
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 676a4e34ddb27..48b19615ab08f 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5470,6 +5470,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.getLastArg(options::OPT_save_temps_EQ))
Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
+ if (Args.getLastArg(options::OPT_summaries_dir_EQ))
+ Args.AddLastArg(CmdArgs, options::OPT_summaries_dir_EQ);
+
// FIXME: This needs to be cleaned up and needs proper error handling as well.
if (const Arg *A = Args.getLastArg(options::OPT_emit_summaries_EQ)) {
llvm::SmallString<10> input;
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 35b0c0373533a..9cbebbabd8529 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -46,7 +46,9 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include <fstream>
#include <memory>
+#include <sstream>
#include <system_error>
using namespace clang;
@@ -962,6 +964,33 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
}
}
+ // FIXME: lookup dirs recursively
+ if (!CI.getFrontendOpts().SummaryDirPath.empty()) {
+ FileManager &FileMgr = CI.getFileManager();
+
+ StringRef SummaryDirPath = CI.getFrontendOpts().SummaryDirPath;
+ if (auto SummaryDir = FileMgr.getOptionalDirectoryRef(SummaryDirPath)) {
+ std::error_code EC;
+ SmallString<128> DirNative;
+ llvm::sys::path::native(SummaryDir->getName(), DirNative);
+
+ llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
+ for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
+ DirEnd;
+ Dir != DirEnd && !EC; Dir.increment(EC)) {
+ if (llvm::sys::path::extension(Dir->path()) == ".json") {
+ std::ifstream t(Dir->path().str());
+ std::stringstream buffer;
+ buffer << t.rdbuf();
+
+ auto JSON = llvm::json::parse(buffer.str());
+ if (JSON)
+ JSON->dump();
+ }
+ }
+ }
+ }
+
// Set up the preprocessor if needed. When parsing model files the
// preprocessor of the original source is reused.
if (!isModelParsingAction())
>From a45d2c0cedab95d5b0db1dba11218f97e86f64b9 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Mon, 9 Jun 2025 23:45:47 +0200
Subject: [PATCH 07/25] [clang][Summary] implement parsing the summaries
---
.../include/clang/Frontend/CompilerInstance.h | 14 +++
clang/include/clang/Sema/Sema.h | 2 +
clang/include/clang/Sema/SemaSummarizer.h | 29 ++++-
clang/include/clang/Sema/SummaryAttribute.h | 35 ++----
clang/include/clang/Sema/SummaryConsumer.h | 11 +-
clang/lib/Frontend/CompilerInstance.cpp | 9 +-
clang/lib/Frontend/FrontendAction.cpp | 23 ++--
clang/lib/Sema/CMakeLists.txt | 1 +
clang/lib/Sema/Sema.cpp | 4 +-
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaSummarizer.cpp | 105 +++++++++++++++---
clang/lib/Sema/SummaryAttribute.cpp | 19 ++++
clang/lib/Sema/SummaryConsumer.cpp | 18 +--
13 files changed, 191 insertions(+), 81 deletions(-)
create mode 100644 clang/lib/Sema/SummaryAttribute.cpp
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index f296e6d042a54..f8f13bbc998d9 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -57,6 +57,7 @@ class Module;
class ModuleCache;
class Preprocessor;
class Sema;
+class SummaryManager;
class SourceManager;
class TargetInfo;
enum class DisableValidationForModuleKind;
@@ -124,6 +125,9 @@ class CompilerInstance : public ModuleLoader {
/// The summary consumer.
std::unique_ptr<SummaryConsumer> TheSummaryConsumer;
+
+ /// The summary manager object.
+ std::unique_ptr<SummaryManager> TheSummaryManager;
/// The semantic analysis object.
std::unique_ptr<Sema> TheSema;
@@ -520,6 +524,15 @@ class CompilerInstance : public ModuleLoader {
/// setASTContext - Replace the current AST context.
void setASTContext(ASTContext *Value);
+ bool hasSummaryManager() {
+ return TheSummaryManager != nullptr;
+ }
+
+ SummaryManager &getSummaryManager() {
+ assert(TheSummaryManager && "Compiler instance has no summary manager!");
+ return *TheSummaryManager;
+ }
+
/// Replace the current Sema; the compiler instance takes ownership
/// of S.
void setSema(Sema *S);
@@ -753,6 +766,7 @@ class CompilerInstance : public ModuleLoader {
const CodeCompleteOptions &Opts, raw_ostream &OS);
void createSummaryConsumer();
+ void createSummaryManager();
/// Create the Sema object to be used for parsing.
void createSema(TranslationUnitKind TUKind,
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9cb2158ab4ff1..b36fce47fb792 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -125,6 +125,7 @@ class CXXBasePath;
class CXXBasePaths;
class CXXFieldCollector;
class CodeCompleteConsumer;
+class SummaryManager;
class SummaryConsumer;
enum class ComparisonCategoryType : unsigned char;
class ConstraintSatisfaction;
@@ -886,6 +887,7 @@ class Sema final : public SemaBase {
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind = TU_Complete,
CodeCompleteConsumer *CompletionConsumer = nullptr,
+ SummaryManager *SummaryManager = nullptr,
SummaryConsumer *SummaryConsumer = nullptr);
~Sema();
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index ef40599d982a1..38e3565af0a95 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -13,6 +13,7 @@ class FunctionSummary {
std::set<SmallVector<char>> Calls;
public:
+ FunctionSummary(SmallVector<char> ID, std::set<SummaryAttribute> FunctionAttrs, std::set<SmallVector<char>> Calls);
FunctionSummary(const clang::FunctionDecl *FD);
SmallVector<char> getID() const { return ID; }
@@ -25,18 +26,36 @@ class FunctionSummary {
void addCall(const clang::FunctionDecl *FD);
};
-class SemaSummarizer : public SemaBase {
+class SummaryManager {
+ std::map<std::string, const FunctionSummary *> IDToSummary;
+ std::vector<std::unique_ptr<FunctionSummary>> FunctionSummaries;
+
+ std::map<SummaryAttribute, const SummaryAttributeDescription *> AttrToDescription;
+ std::vector<std::unique_ptr<SummaryAttributeDescription>> AttributeDescriptions;
+
public:
- SemaSummarizer(Sema &S, SummaryConsumer *SummaryConsumer);
+ SummaryManager();
+
+ FunctionSummary SummarizeFunctionBody(const FunctionDecl *FD);
+
+ void SerializeSummary(llvm::json::OStream &, const FunctionSummary &) const;
+ void ParseSummaryFromJSON(StringRef path);
+
+ void ReduceSummaries();
+};
- std::vector<std::unique_ptr<SummaryAttributeManager>> Attributes;
+// FIXME: Is this class needed?
+class SemaSummarizer : public SemaBase {
+public:
+ SummaryManager *TheSummaryManager;
SummaryConsumer *TheSummaryConsumer;
+ SemaSummarizer(Sema &S, SummaryManager &SummaryManager, SummaryConsumer *SummaryConsumer)
+ : SemaBase(S), TheSummaryManager(&SummaryManager), TheSummaryConsumer(SummaryConsumer) {};
+
void ActOnStartOfSourceFile();
void ActOnEndOfSourceFile();
-
void SummarizeFunctionBody(const FunctionDecl *FD);
-
};
} // namespace clang
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index 2d2fd1e4ff623..66d1d11334ac5 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -11,44 +11,25 @@ enum SummaryAttribute {
class FunctionSummary;
-class SummaryAttributeManager {
- inline static std::unordered_map<SummaryAttribute, std::string> AttrToStr;
-
+class SummaryAttributeDescription {
protected:
const SummaryAttribute Attr;
- const char *Str;
+ std::string_view Serialzed;
public:
- SummaryAttributeManager(SummaryAttribute Attr, const char *Str)
- : Attr(Attr), Str(Str) {
- assert(AttrToStr.count(Attr) == 0 && "attribute already registered");
- for (auto &&[attr, str] : AttrToStr)
- assert(str != Str && "attribute representation is already used");
+ SummaryAttributeDescription(SummaryAttribute Attr, const char *Str) : Attr(Attr), Serialzed(Str) {}
+ virtual ~SummaryAttributeDescription() = default;
- AttrToStr[Attr] = Str;
- }
- virtual ~SummaryAttributeManager() = default;
+ SummaryAttribute getAttribute() { return Attr; };
virtual bool predicate(const FunctionDecl *FD) = 0;
+ std::optional<SummaryAttribute> infer(const FunctionDecl *FD);
// FIXME: This should receive all the parsed summaries as well.
virtual bool merge(FunctionSummary &Summary) = 0;
- // FIXME: bad design
- static std::string serialize(SummaryAttribute Attr) { return AttrToStr[Attr]; };
- virtual std::optional<SummaryAttribute> parse(std::string_view Input) const {
- if (Str == Input)
- return Attr;
-
- return std::nullopt;
- };
-
- std::optional<SummaryAttribute> infer(const FunctionDecl *FD) {
- if (predicate(FD))
- return Attr;
-
- return std::nullopt;
- };
+ virtual std::string serialize();
+ virtual std::optional<SummaryAttribute> parse(std::string_view input);
};
} // namespace clang
diff --git a/clang/include/clang/Sema/SummaryConsumer.h b/clang/include/clang/Sema/SummaryConsumer.h
index c2698288ce721..85c48b3c1b939 100644
--- a/clang/include/clang/Sema/SummaryConsumer.h
+++ b/clang/include/clang/Sema/SummaryConsumer.h
@@ -5,9 +5,14 @@
#include "llvm/Support/JSON.h"
namespace clang {
class FunctionSummary;
+class SummaryManager;
class SummaryConsumer {
+protected:
+ const SummaryManager *TheSummaryManager;
+
public:
+ SummaryConsumer(const SummaryManager &SummaryManager) : TheSummaryManager(&SummaryManager) {}
virtual ~SummaryConsumer() = default;
virtual void ProcessStartOfSourceFile() {};
@@ -17,15 +22,15 @@ class SummaryConsumer {
class PrintingSummaryConsumer : public SummaryConsumer {
public:
- PrintingSummaryConsumer(raw_ostream &OS)
- : SummaryConsumer() {}
+ PrintingSummaryConsumer(const SummaryManager &SummaryManager, raw_ostream &OS)
+ : SummaryConsumer(SummaryManager) {}
};
class JSONPrintingSummaryConsumer : public PrintingSummaryConsumer {
llvm::json::OStream JOS;
public:
- JSONPrintingSummaryConsumer(raw_ostream &OS) : PrintingSummaryConsumer(OS), JOS(OS, 2) {}
+ JSONPrintingSummaryConsumer(const SummaryManager &SummaryManager, raw_ostream &OS) : PrintingSummaryConsumer(SummaryManager, OS), JOS(OS, 2) {}
void ProcessStartOfSourceFile() override { JOS.arrayBegin(); };
void ProcessFunctionSummary(const FunctionSummary&) override;
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index c90b8884f5731..deed94e1f0b42 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -37,6 +37,7 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaSummarizer.h"
#include "clang/Sema/SummaryConsumer.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
@@ -752,14 +753,18 @@ void CompilerInstance::createSummaryConsumer() {
static llvm::raw_fd_ostream SummaryOS(SummaryFile, EC, llvm::sys::fs::CD_CreateAlways);
if(!EC)
- TheSummaryConsumer.reset(new JSONPrintingSummaryConsumer(SummaryOS));
+ TheSummaryConsumer.reset(new JSONPrintingSummaryConsumer(getSummaryManager(), SummaryOS));
+}
+
+void CompilerInstance::createSummaryManager() {
+ TheSummaryManager.reset(new SummaryManager());
}
void CompilerInstance::createSema(TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer,
SummaryConsumer *SummaryConsumer) {
TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
- TUKind, CompletionConsumer, SummaryConsumer));
+ TUKind, CompletionConsumer, hasSummaryManager() ? &getSummaryManager() : nullptr, SummaryConsumer));
// Set up API notes.
TheSema->APINotes.setSwiftVersion(getAPINotesOpts().SwiftVersion);
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 9cbebbabd8529..58aac1b8cd1b1 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -35,6 +35,7 @@
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/HLSLExternalSemaSource.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
+#include "clang/Sema/SemaSummarizer.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
@@ -46,9 +47,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
-#include <fstream>
#include <memory>
-#include <sstream>
#include <system_error>
using namespace clang;
@@ -894,6 +893,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
}
}
+ if(!CI.hasSummaryManager()) {
+ CI.createSummaryManager();
+ }
+
// Set up embedding for any specified files. Do this before we load any
// source files, including the primary module map for the compilation.
for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
@@ -978,16 +981,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
- if (llvm::sys::path::extension(Dir->path()) == ".json") {
- std::ifstream t(Dir->path().str());
- std::stringstream buffer;
- buffer << t.rdbuf();
-
- auto JSON = llvm::json::parse(buffer.str());
- if (JSON)
- JSON->dump();
- }
+ if (llvm::sys::path::extension(Dir->path()) == ".json")
+ CI.getSummaryManager().ParseSummaryFromJSON(Dir->path());
}
+
+ CI.getSummaryManager().ReduceSummaries();
}
}
@@ -1362,6 +1360,9 @@ void ASTFrontendAction::ExecuteAction() {
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();
+ if(!CI.hasSummaryManager()) {
+ CI.createSummaryManager();
+ }
CI.createSummaryConsumer();
// Use a code completion consumer?
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index d6297016c015f..bf8f73dc985db 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -99,6 +99,7 @@ add_clang_library(clangSema
SemaType.cpp
SemaWasm.cpp
SemaX86.cpp
+ SummaryAttribute.cpp
SummaryConsumer.cpp
TypeLocBuilder.cpp
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index ae9f8c00081b3..5b3f1a4dca36e 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -250,6 +250,7 @@ const uint64_t Sema::MaximumAlignment;
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter,
+ SummaryManager *SummaryManager,
SummaryConsumer *SummaryConsumer)
: SemaBase(*this), CollectStats(false), TUKind(TUKind),
CurFPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp),
@@ -265,8 +266,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
BPFPtr(std::make_unique<SemaBPF>(*this)),
CodeCompletionPtr(
std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
- SummarizerPtr(SummaryConsumer ? std::make_unique<SemaSummarizer>(
- *this, SummaryConsumer)
+ SummarizerPtr(SummaryManager ? std::make_unique<SemaSummarizer>(*this, *SummaryManager, SummaryConsumer)
: nullptr),
CUDAPtr(std::make_unique<SemaCUDA>(*this)),
DirectXPtr(std::make_unique<SemaDirectX>(*this)),
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index bb80fd2a46f58..45f1523868f75 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16695,7 +16695,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD && !FD->isDeleted())
checkTypeSupport(FD->getType(), FD->getLocation(), FD);
- if (FD && SummarizerPtr)
+ if (FD && SummarizerPtr && SummarizerPtr->TheSummaryConsumer)
SummarizerPtr->SummarizeFunctionBody(FD);
return dcl;
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 9fbb940ec3fbb..b4ad0d4a6db2f 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -2,7 +2,10 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Sema/SummaryConsumer.h"
+#include "clang/Sema/SummaryAttribute.h"
#include <set>
+#include <fstream>
+#include <sstream>
namespace clang {
namespace {
@@ -34,7 +37,7 @@ class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
}
};
-class NoWriteGlobalAttrManager : public SummaryAttributeManager {
+class NoWriteGlobalDescription : public SummaryAttributeDescription {
class Callback : public ast_matchers::MatchFinder::MatchCallback {
public:
bool WriteGlobal = false;
@@ -50,8 +53,8 @@ class NoWriteGlobalAttrManager : public SummaryAttributeManager {
};
public:
- NoWriteGlobalAttrManager()
- : SummaryAttributeManager(NO_WRITE_GLOBAL, "no_write_global") {}
+ NoWriteGlobalDescription()
+ : SummaryAttributeDescription(NO_WRITE_GLOBAL, "no_write_global") {}
bool predicate(const FunctionDecl *FD) override {
using namespace ast_matchers;
@@ -78,13 +81,95 @@ void FunctionSummary::addCall(const clang::FunctionDecl *FD) {
Calls.emplace(Call);
}
+FunctionSummary::FunctionSummary(SmallVector<char> ID, std::set<SummaryAttribute> FunctionAttrs, std::set<SmallVector<char>> Calls) :
+ ID(std::move(ID)), FunctionAttrs(std::move(FunctionAttrs)), Calls(std::move(Calls)) {}
+
FunctionSummary::FunctionSummary(const clang::FunctionDecl *FD) {
index::generateUSRForDecl(FD, ID);
}
-SemaSummarizer::SemaSummarizer(Sema &S, SummaryConsumer *SummaryConsumer)
- : SemaBase(S), TheSummaryConsumer(SummaryConsumer) {
- Attributes.emplace_back(std::make_unique<NoWriteGlobalAttrManager>());
+SummaryManager::SummaryManager() {
+ AttributeDescriptions.emplace_back(std::make_unique<NoWriteGlobalDescription>());
+
+ for(auto &&AttrDescr : AttributeDescriptions)
+ AttrToDescription[AttrDescr->getAttribute()] = AttrDescr.get();
+}
+
+FunctionSummary SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
+ auto Summary = std::make_unique<FunctionSummary>(FD);
+ CallCollector::CollectCalledFunctions(FD, *Summary);
+
+ for (auto &&AttrDesc : AttributeDescriptions) {
+ if (const auto &Attr = AttrDesc->infer(FD))
+ Summary->addAttribute(*Attr);
+ }
+
+ // FIXME: This is duplicated and hurts my eyes regardless
+ std::string key(Summary->getID().begin(), Summary->getID().size());
+ auto *SummaryPtr = FunctionSummaries.emplace_back(std::move(Summary)).get();
+ IDToSummary[key] = SummaryPtr;
+ return *SummaryPtr;
+}
+
+void SummaryManager::SerializeSummary(llvm::json::OStream &JOS, const FunctionSummary &Summary) const {
+ JOS.object([&]{
+ JOS.attribute("id", llvm::json::Value(Summary.getID()));
+ JOS.attributeObject("attrs", [&]{
+ JOS.attributeArray("function", [&]{
+ for(auto &&Attr : Summary.getFunctionAttrs()) {
+ JOS.value(llvm::json::Value(AttributeDescriptions[Attr]->serialize()));
+ }
+ });
+ });
+ JOS.attributeArray("calls", [&]{
+ for(auto &&Call : Summary.getCalls()) {
+ JOS.object([&]{
+ JOS.attribute("id", llvm::json::Value(Call));
+ });
+ }
+ });
+ });
+}
+
+void SummaryManager::ParseSummaryFromJSON(StringRef path) {
+ std::ifstream t(path.str());
+ std::stringstream buffer;
+ buffer << t.rdbuf();
+
+ auto JSON = llvm::json::parse(buffer.str());
+ if (!JSON)
+ return;
+
+ llvm::json::Array *Summaries = JSON->getAsArray();
+ for(auto it = Summaries->begin(); it != Summaries->end(); ++it) {
+ llvm::json::Object *Summary = it->getAsObject();
+
+ SmallString<128> ID(*Summary->getString("id"));
+ std::set<SummaryAttribute> FunctionAttrs;
+ llvm::json::Array *FunctionAttributes = Summary->getObject("attrs")->getArray("function");
+ for(auto attrIt = FunctionAttributes->begin(); attrIt != FunctionAttributes->end(); ++attrIt) {
+ for(auto &&AttrDesc : AttributeDescriptions) {
+ if(auto Attr = AttrDesc->parse(*attrIt->getAsString()))
+ FunctionAttrs.emplace(*Attr);
+ }
+ }
+
+ std::set<SmallVector<char>> Calls;
+ llvm::json::Array *CallEntries = Summary->getArray("calls");
+ for(auto callIt = CallEntries->begin(); callIt != CallEntries->end(); ++callIt) {
+ auto *Obj = callIt->getAsObject();
+ Calls.emplace(SmallString<128>(*Obj->getString("id")));
+ }
+
+ std::string key = ID.str().str();
+ auto ParsedSummary = std::make_unique<FunctionSummary>(std::move(ID), std::move(FunctionAttrs), std::move(Calls));
+ auto *ParsedSummaryPtr = FunctionSummaries.emplace_back(std::move(ParsedSummary)).get();
+ IDToSummary[key] = ParsedSummaryPtr;
+ }
+}
+
+void SummaryManager::ReduceSummaries() {
+ // FIXME: implement
}
void SemaSummarizer::ActOnStartOfSourceFile() {
@@ -98,13 +183,7 @@ void SemaSummarizer::ActOnEndOfSourceFile() {
}
void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
- FunctionSummary Summary(FD);
- CallCollector::CollectCalledFunctions(FD, Summary);
-
- for (auto &&Attr : Attributes) {
- if (const auto &InferredAttr = Attr->infer(FD))
- Summary.addAttribute(*InferredAttr);
- }
+ FunctionSummary Summary = TheSummaryManager->SummarizeFunctionBody(FD);
if(TheSummaryConsumer)
TheSummaryConsumer->ProcessFunctionSummary(Summary);
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Sema/SummaryAttribute.cpp
new file mode 100644
index 0000000000000..4affec7b4ffb7
--- /dev/null
+++ b/clang/lib/Sema/SummaryAttribute.cpp
@@ -0,0 +1,19 @@
+#include "clang/Sema/SummaryAttribute.h"
+
+namespace clang {
+std::string SummaryAttributeDescription::serialize() { return std::string(Serialzed); }
+
+std::optional<SummaryAttribute> SummaryAttributeDescription::parse(std::string_view input) {
+ if(input == Serialzed)
+ return Attr;
+
+ return std::nullopt;
+}
+
+std::optional<SummaryAttribute> SummaryAttributeDescription::infer(const FunctionDecl *FD) {
+ if (predicate(FD))
+ return Attr;
+
+ return std::nullopt;
+}
+} // namespace clang
\ No newline at end of file
diff --git a/clang/lib/Sema/SummaryConsumer.cpp b/clang/lib/Sema/SummaryConsumer.cpp
index 45aeaee502ed9..37646c1e07a7f 100644
--- a/clang/lib/Sema/SummaryConsumer.cpp
+++ b/clang/lib/Sema/SummaryConsumer.cpp
@@ -3,22 +3,6 @@
namespace clang {
void JSONPrintingSummaryConsumer::ProcessFunctionSummary(const FunctionSummary &Summary) {
- JOS.object([&]{
- JOS.attribute("id", llvm::json::Value(Summary.getID()));
- JOS.attributeObject("attrs", [&]{
- JOS.attributeArray("function", [&]{
- for(auto &&Attr : Summary.getFunctionAttrs()) {
- JOS.value(llvm::json::Value(SummaryAttributeManager::serialize(Attr)));
- }
- });
- });
- JOS.attributeArray("calls", [&]{
- for(auto &&Call : Summary.getCalls()) {
- JOS.object([&]{
- JOS.attribute("id", llvm::json::Value(Call));
- });
- }
- });
- });
+ TheSummaryManager->SerializeSummary(JOS, Summary);
}
} // namespace clang
\ No newline at end of file
>From e6b21071a455f1aeae544dec93cba08ccf985008 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Tue, 10 Jun 2025 23:30:34 +0200
Subject: [PATCH 08/25] [clang][Summary] implement reduction prototype
---
clang/include/clang/Sema/SemaSummarizer.h | 6 +++
clang/include/clang/Sema/SummaryAttribute.h | 3 +-
clang/lib/Frontend/FrontendAction.cpp | 14 +++++++
clang/lib/Sema/SemaSummarizer.cpp | 42 ++++++++++++++++++++-
4 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 38e3565af0a95..7d2f8252dc957 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -20,6 +20,7 @@ class FunctionSummary {
const std::set<SummaryAttribute> &getFunctionAttrs() const { return FunctionAttrs; }
const std::set<SmallVector<char>> &getCalls() const { return Calls; }
+ void clearAttributes() { FunctionAttrs.clear(); }
void addAttribute(SummaryAttribute Attr) { FunctionAttrs.emplace(Attr); }
bool hasAttribute(SummaryAttribute Attr) const { return FunctionAttrs.count(Attr); }
@@ -42,6 +43,11 @@ class SummaryManager {
void ParseSummaryFromJSON(StringRef path);
void ReduceSummaries();
+
+ // FIXME: debug only, remove later
+ const std::vector<std::unique_ptr<FunctionSummary>> &getSummaries() {
+ return FunctionSummaries;
+ }
};
// FIXME: Is this class needed?
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index 66d1d11334ac5..beb735c00933c 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -25,8 +25,7 @@ class SummaryAttributeDescription {
virtual bool predicate(const FunctionDecl *FD) = 0;
std::optional<SummaryAttribute> infer(const FunctionDecl *FD);
- // FIXME: This should receive all the parsed summaries as well.
- virtual bool merge(FunctionSummary &Summary) = 0;
+ virtual bool merge(const FunctionSummary &Summary) const = 0;
virtual std::string serialize();
virtual std::optional<SummaryAttribute> parse(std::string_view input);
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 58aac1b8cd1b1..7af4a79f83eec 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -985,7 +985,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.getSummaryManager().ParseSummaryFromJSON(Dir->path());
}
+ // FIXME: debug only, remove later
+ for (auto &&S : CI.getSummaryManager().getSummaries()) {
+ llvm::json::OStream Out(llvm::errs());
+ CI.getSummaryManager().SerializeSummary(Out, *S);
+ }
+ llvm::errs() << '\n';
+
CI.getSummaryManager().ReduceSummaries();
+
+ // FIXME: debug only, remove later
+ for (auto &&S : CI.getSummaryManager().getSummaries()) {
+ llvm::json::OStream Out(llvm::errs());
+ CI.getSummaryManager().SerializeSummary(Out, *S);
+ }
+ llvm::errs() << '\n';
}
}
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index b4ad0d4a6db2f..569d272b36bb3 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -71,7 +71,9 @@ class NoWriteGlobalDescription : public SummaryAttributeDescription {
return !CB.WriteGlobal;
};
- bool merge(FunctionSummary &Summary) override { return true; };
+ bool merge(const FunctionSummary &Summary) const override {
+ return Summary.getFunctionAttrs().count(Attr);
+ };
};
} // namespace
@@ -169,7 +171,43 @@ void SummaryManager::ParseSummaryFromJSON(StringRef path) {
}
void SummaryManager::ReduceSummaries() {
- // FIXME: implement
+ bool changed = true;
+ while (changed) {
+ changed = false;
+
+ for (auto &&Function : FunctionSummaries) {
+ for (auto &&call : Function->getCalls()) {
+ // FIXME: This is duplicated and hurts my eyes regardless
+ std::string key(call.begin(), call.size());
+
+ // If we don't have a summary about a called function, we forget
+ // everything about the current one as well.
+ if (!IDToSummary.count(key)) {
+ changed = true;
+ Function->clearAttributes();
+ break;
+ }
+
+ const FunctionSummary *callSummary = IDToSummary.at(key);
+
+ std::set<SummaryAttribute> reducedAttrs;
+ for (auto &&attr : Function->getFunctionAttrs()) {
+ // FIXME: handle union style attributes...
+ if (AttrToDescription[attr]->merge(*callSummary))
+ reducedAttrs.emplace(attr);
+ }
+
+ if (reducedAttrs != Function->getFunctionAttrs()) {
+ Function->clearAttributes();
+
+ for (auto &&attr : reducedAttrs)
+ Function->addAttribute(attr);
+
+ changed = true;
+ }
+ }
+ }
+ }
}
void SemaSummarizer::ActOnStartOfSourceFile() {
>From da80bdbf6e7749fc9e81ec6bfdeb211b999d637d Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 12 Jun 2025 00:31:33 +0200
Subject: [PATCH 09/25] [clang][Summary] make `SummaryManager` own the
attributes
---
clang/include/clang/Sema/SemaSummarizer.h | 22 +--
clang/include/clang/Sema/SummaryAttribute.h | 38 +++--
clang/lib/Sema/SemaSummarizer.cpp | 168 ++++++++------------
clang/lib/Sema/SummaryAttribute.cpp | 33 ++--
4 files changed, 130 insertions(+), 131 deletions(-)
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 7d2f8252dc957..42f668009d2f2 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -9,35 +9,37 @@
namespace clang {
class FunctionSummary {
SmallVector<char> ID;
- std::set<SummaryAttribute> FunctionAttrs;
+ std::set<const SummaryAttribute *> FunctionAttrs;
std::set<SmallVector<char>> Calls;
public:
- FunctionSummary(SmallVector<char> ID, std::set<SummaryAttribute> FunctionAttrs, std::set<SmallVector<char>> Calls);
+ FunctionSummary(SmallVector<char> ID, std::set<const SummaryAttribute *> FunctionAttrs, std::set<SmallVector<char>> Calls);
FunctionSummary(const clang::FunctionDecl *FD);
SmallVector<char> getID() const { return ID; }
- const std::set<SummaryAttribute> &getFunctionAttrs() const { return FunctionAttrs; }
+ const std::set<const SummaryAttribute *> &getFunctionAttrs() const { return FunctionAttrs; }
const std::set<SmallVector<char>> &getCalls() const { return Calls; }
- void clearAttributes() { FunctionAttrs.clear(); }
- void addAttribute(SummaryAttribute Attr) { FunctionAttrs.emplace(Attr); }
- bool hasAttribute(SummaryAttribute Attr) const { return FunctionAttrs.count(Attr); }
+ void replaceAttributes(std::set<const SummaryAttribute *> Attrs) { FunctionAttrs = std::move(Attrs); }
+ void addAttribute(const SummaryAttribute * Attr) { FunctionAttrs.emplace(Attr); }
void addCall(const clang::FunctionDecl *FD);
};
class SummaryManager {
- std::map<std::string, const FunctionSummary *> IDToSummary;
+ std::map<SmallVector<char>, const FunctionSummary *> IDToSummary;
std::vector<std::unique_ptr<FunctionSummary>> FunctionSummaries;
- std::map<SummaryAttribute, const SummaryAttributeDescription *> AttrToDescription;
- std::vector<std::unique_ptr<SummaryAttributeDescription>> AttributeDescriptions;
+ std::map<SummaryAttributeKind, const SummaryAttribute *> KindToAttribute;
+ std::vector<std::unique_ptr<SummaryAttribute>> Attributes;
+ void SaveSummary(std::unique_ptr<FunctionSummary> Summary);
+ bool ReduceFunctionSummary(FunctionSummary &FunctionSummary);
public:
SummaryManager();
- FunctionSummary SummarizeFunctionBody(const FunctionDecl *FD);
+ const FunctionSummary *GetSummary(const FunctionDecl *FD) const;
+ void SummarizeFunctionBody(const FunctionDecl *FD);
void SerializeSummary(llvm::json::OStream &, const FunctionSummary &) const;
void ParseSummaryFromJSON(StringRef path);
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index beb735c00933c..bfe7ecf84e795 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -2,33 +2,47 @@
#define LLVM_CLANG_SEMA_SEMASUMMARYATTRIBUTE_H
#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <string>
namespace clang {
-enum SummaryAttribute {
+enum SummaryAttributeKind {
NO_WRITE_GLOBAL,
};
class FunctionSummary;
-class SummaryAttributeDescription {
-protected:
- const SummaryAttribute Attr;
+class SummaryAttribute {
+ const SummaryAttributeKind Kind;
std::string_view Serialzed;
public:
- SummaryAttributeDescription(SummaryAttribute Attr, const char *Str) : Attr(Attr), Serialzed(Str) {}
- virtual ~SummaryAttributeDescription() = default;
+ SummaryAttribute(SummaryAttributeKind Attr, const char *Str) : Kind(Attr), Serialzed(Str) {}
+ virtual ~SummaryAttribute() = default;
+
+ SummaryAttributeKind getKind() { return Kind; }
- SummaryAttribute getAttribute() { return Attr; };
+ virtual bool infer(const FunctionDecl *FD) const = 0;
+ virtual bool merge(const FunctionSummary &Summary) const = 0;
- virtual bool predicate(const FunctionDecl *FD) = 0;
- std::optional<SummaryAttribute> infer(const FunctionDecl *FD);
+ virtual std::string serialize() const { return std::string(Serialzed); };
+ virtual bool parse(std::string_view input) const { return input == Serialzed; };
+};
- virtual bool merge(const FunctionSummary &Summary) const = 0;
+class NoWriteGlobalDescription : public SummaryAttribute {
+ class Callback : public ast_matchers::MatchFinder::MatchCallback {
+ public:
+ bool WriteGlobal = false;
- virtual std::string serialize();
- virtual std::optional<SummaryAttribute> parse(std::string_view input);
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override final;
+ };
+
+public:
+ NoWriteGlobalDescription()
+ : SummaryAttribute(NO_WRITE_GLOBAL, "no_write_global") {}
+
+ bool infer(const FunctionDecl *FD) const override final;
+ bool merge(const FunctionSummary &Summary) const override final;
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 569d272b36bb3..97b2d50bd7602 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -37,80 +37,54 @@ class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
}
};
-class NoWriteGlobalDescription : public SummaryAttributeDescription {
- class Callback : public ast_matchers::MatchFinder::MatchCallback {
- public:
- bool WriteGlobal = false;
-
- void run(const ast_matchers::MatchFinder::MatchResult &Result) override {
- const auto *Assignment =
- Result.Nodes.getNodeAs<BinaryOperator>("assignment");
- if (!Assignment)
- return;
-
- WriteGlobal = true;
- };
- };
-
-public:
- NoWriteGlobalDescription()
- : SummaryAttributeDescription(NO_WRITE_GLOBAL, "no_write_global") {}
-
- bool predicate(const FunctionDecl *FD) override {
- using namespace ast_matchers;
- MatchFinder Finder;
- Callback CB;
-
- Finder.addMatcher(
- functionDecl(forEachDescendant(
- binaryOperator(isAssignmentOperator(),
- hasLHS(declRefExpr(to(varDecl(hasGlobalStorage())))))
- .bind("assignment"))),
- &CB);
- Finder.match(*FD, FD->getASTContext());
- return !CB.WriteGlobal;
- };
-
- bool merge(const FunctionSummary &Summary) const override {
- return Summary.getFunctionAttrs().count(Attr);
- };
-};
+SmallVector<char> GetUSR(const FunctionDecl *FD) {
+ SmallVector<char> USR;
+ index::generateUSRForDecl(FD, USR);
+ return USR;
+}
} // namespace
void FunctionSummary::addCall(const clang::FunctionDecl *FD) {
- SmallVector<char> Call;
- index::generateUSRForDecl(FD, Call);
- Calls.emplace(Call);
+ Calls.emplace(GetUSR(FD));
}
-FunctionSummary::FunctionSummary(SmallVector<char> ID, std::set<SummaryAttribute> FunctionAttrs, std::set<SmallVector<char>> Calls) :
+FunctionSummary::FunctionSummary(SmallVector<char> ID, std::set<const SummaryAttribute *> FunctionAttrs, std::set<SmallVector<char>> Calls) :
ID(std::move(ID)), FunctionAttrs(std::move(FunctionAttrs)), Calls(std::move(Calls)) {}
-FunctionSummary::FunctionSummary(const clang::FunctionDecl *FD) {
- index::generateUSRForDecl(FD, ID);
-}
+FunctionSummary::FunctionSummary(const clang::FunctionDecl *FD) : ID(GetUSR(FD)) {}
SummaryManager::SummaryManager() {
- AttributeDescriptions.emplace_back(std::make_unique<NoWriteGlobalDescription>());
+ Attributes.emplace_back(std::make_unique<NoWriteGlobalDescription>());
+
+ for(auto &&Attr : Attributes) {
+ assert(KindToAttribute.count(Attr->getKind()) == 0 && "Attr already registered");
+ KindToAttribute[Attr->getKind()] = Attr.get();
+ }
+}
- for(auto &&AttrDescr : AttributeDescriptions)
- AttrToDescription[AttrDescr->getAttribute()] = AttrDescr.get();
+void SummaryManager::SaveSummary(std::unique_ptr<FunctionSummary> Summary) {
+ auto *SummaryPtr = FunctionSummaries.emplace_back(std::move(Summary)).get();
+ IDToSummary[SummaryPtr->getID()] = SummaryPtr;
}
-FunctionSummary SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
+const FunctionSummary *SummaryManager::GetSummary(const FunctionDecl *FD) const {
+ auto USR = GetUSR(FD);
+ if(!IDToSummary.count(USR))
+ return nullptr;
+
+ return IDToSummary.at(USR);
+}
+
+void SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
auto Summary = std::make_unique<FunctionSummary>(FD);
CallCollector::CollectCalledFunctions(FD, *Summary);
- for (auto &&AttrDesc : AttributeDescriptions) {
- if (const auto &Attr = AttrDesc->infer(FD))
- Summary->addAttribute(*Attr);
+ for (auto &&Attr : Attributes) {
+ if (Attr->infer(FD))
+ Summary->addAttribute(Attr.get());
}
- // FIXME: This is duplicated and hurts my eyes regardless
- std::string key(Summary->getID().begin(), Summary->getID().size());
- auto *SummaryPtr = FunctionSummaries.emplace_back(std::move(Summary)).get();
- IDToSummary[key] = SummaryPtr;
- return *SummaryPtr;
+ SaveSummary(std::move(Summary));
}
void SummaryManager::SerializeSummary(llvm::json::OStream &JOS, const FunctionSummary &Summary) const {
@@ -119,7 +93,7 @@ void SummaryManager::SerializeSummary(llvm::json::OStream &JOS, const FunctionSu
JOS.attributeObject("attrs", [&]{
JOS.attributeArray("function", [&]{
for(auto &&Attr : Summary.getFunctionAttrs()) {
- JOS.value(llvm::json::Value(AttributeDescriptions[Attr]->serialize()));
+ JOS.value(llvm::json::Value(Attr->serialize()));
}
});
});
@@ -147,12 +121,12 @@ void SummaryManager::ParseSummaryFromJSON(StringRef path) {
llvm::json::Object *Summary = it->getAsObject();
SmallString<128> ID(*Summary->getString("id"));
- std::set<SummaryAttribute> FunctionAttrs;
+ std::set<const SummaryAttribute *> FunctionAttrs;
llvm::json::Array *FunctionAttributes = Summary->getObject("attrs")->getArray("function");
for(auto attrIt = FunctionAttributes->begin(); attrIt != FunctionAttributes->end(); ++attrIt) {
- for(auto &&AttrDesc : AttributeDescriptions) {
- if(auto Attr = AttrDesc->parse(*attrIt->getAsString()))
- FunctionAttrs.emplace(*Attr);
+ for(auto &&Attr : Attributes) {
+ if(Attr->parse(*attrIt->getAsString()))
+ FunctionAttrs.emplace(Attr.get());
}
}
@@ -163,51 +137,47 @@ void SummaryManager::ParseSummaryFromJSON(StringRef path) {
Calls.emplace(SmallString<128>(*Obj->getString("id")));
}
- std::string key = ID.str().str();
- auto ParsedSummary = std::make_unique<FunctionSummary>(std::move(ID), std::move(FunctionAttrs), std::move(Calls));
- auto *ParsedSummaryPtr = FunctionSummaries.emplace_back(std::move(ParsedSummary)).get();
- IDToSummary[key] = ParsedSummaryPtr;
+ SaveSummary(std::make_unique<FunctionSummary>(std::move(ID), std::move(FunctionAttrs), std::move(Calls)));
}
}
-void SummaryManager::ReduceSummaries() {
- bool changed = true;
- while (changed) {
- changed = false;
-
- for (auto &&Function : FunctionSummaries) {
- for (auto &&call : Function->getCalls()) {
- // FIXME: This is duplicated and hurts my eyes regardless
- std::string key(call.begin(), call.size());
-
- // If we don't have a summary about a called function, we forget
- // everything about the current one as well.
- if (!IDToSummary.count(key)) {
- changed = true;
- Function->clearAttributes();
- break;
- }
+bool SummaryManager::ReduceFunctionSummary(FunctionSummary &Function) {
+ bool changed = false;
- const FunctionSummary *callSummary = IDToSummary.at(key);
+ for (auto &&call : Function.getCalls()) {
+ std::set<const SummaryAttribute *> reducedAttrs;
- std::set<SummaryAttribute> reducedAttrs;
- for (auto &&attr : Function->getFunctionAttrs()) {
- // FIXME: handle union style attributes...
- if (AttrToDescription[attr]->merge(*callSummary))
- reducedAttrs.emplace(attr);
- }
+ // If we don't have a summary about a called function, we forget
+ // everything about the current one as well.
+ if (!IDToSummary.count(call)) {
+ Function.replaceAttributes(std::move(reducedAttrs));
+ return true;
+ }
- if (reducedAttrs != Function->getFunctionAttrs()) {
- Function->clearAttributes();
+ const FunctionSummary *callSummary = IDToSummary[call];
- for (auto &&attr : reducedAttrs)
- Function->addAttribute(attr);
+ for (auto &&Attr : Function.getFunctionAttrs()) {
+ if (Attr->merge(*callSummary))
+ reducedAttrs.emplace(Attr);
+ }
- changed = true;
- }
- }
+ if (reducedAttrs != Function.getFunctionAttrs()) {
+ Function.replaceAttributes(std::move(reducedAttrs));
+ changed = true;
}
}
+
+ return changed;
+}
+
+void SummaryManager::ReduceSummaries() {
+ bool changed = true;
+ while (changed) {
+ changed = false;
+
+ for (auto &&Function : FunctionSummaries)
+ changed |= ReduceFunctionSummary(*Function);
+ }
}
void SemaSummarizer::ActOnStartOfSourceFile() {
@@ -221,10 +191,10 @@ void SemaSummarizer::ActOnEndOfSourceFile() {
}
void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
- FunctionSummary Summary = TheSummaryManager->SummarizeFunctionBody(FD);
+ TheSummaryManager->SummarizeFunctionBody(FD);
if(TheSummaryConsumer)
- TheSummaryConsumer->ProcessFunctionSummary(Summary);
+ TheSummaryConsumer->ProcessFunctionSummary(*TheSummaryManager->GetSummary(FD));
}
} // namespace clang
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Sema/SummaryAttribute.cpp
index 4affec7b4ffb7..953cc38b2e7a1 100644
--- a/clang/lib/Sema/SummaryAttribute.cpp
+++ b/clang/lib/Sema/SummaryAttribute.cpp
@@ -1,19 +1,32 @@
#include "clang/Sema/SummaryAttribute.h"
+#include "clang/Sema/SemaSummarizer.h"
namespace clang {
-std::string SummaryAttributeDescription::serialize() { return std::string(Serialzed); }
+void NoWriteGlobalDescription::Callback::run(const ast_matchers::MatchFinder::MatchResult &Result) {
+ const auto *Assignment =
+ Result.Nodes.getNodeAs<BinaryOperator>("assignment");
+ if (!Assignment)
+ return;
-std::optional<SummaryAttribute> SummaryAttributeDescription::parse(std::string_view input) {
- if(input == Serialzed)
- return Attr;
-
- return std::nullopt;
+ WriteGlobal = true;
}
-std::optional<SummaryAttribute> SummaryAttributeDescription::infer(const FunctionDecl *FD) {
- if (predicate(FD))
- return Attr;
+bool NoWriteGlobalDescription::infer(const FunctionDecl *FD) const {
+ using namespace ast_matchers;
+ MatchFinder Finder;
+ Callback CB;
+
+ Finder.addMatcher(
+ functionDecl(forEachDescendant(
+ binaryOperator(isAssignmentOperator(),
+ hasLHS(declRefExpr(to(varDecl(hasGlobalStorage())))))
+ .bind("assignment"))),
+ &CB);
+ Finder.match(*FD, FD->getASTContext());
+ return !CB.WriteGlobal;
+}
- return std::nullopt;
+bool NoWriteGlobalDescription::merge(const FunctionSummary &Summary) const {
+ return Summary.getFunctionAttrs().count(this);
}
} // namespace clang
\ No newline at end of file
>From 4964c96b88d0a1a1b6b251a0489b2e82ceb60ebe Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 12 Jun 2025 01:04:13 +0200
Subject: [PATCH 10/25] [clang][Summary] only keep one constructor for
`FunctionSummary`
---
clang/include/clang/Sema/SemaSummarizer.h | 27 ++++---
clang/include/clang/Sema/SummaryAttribute.h | 16 ++--
clang/lib/Sema/SemaSummarizer.cpp | 87 ++++++++++-----------
clang/lib/Sema/SummaryAttribute.cpp | 8 +-
4 files changed, 73 insertions(+), 65 deletions(-)
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 42f668009d2f2..7fea668bae694 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -9,38 +9,45 @@
namespace clang {
class FunctionSummary {
SmallVector<char> ID;
- std::set<const SummaryAttribute *> FunctionAttrs;
+ std::set<const SummaryAttribute *> Attrs;
std::set<SmallVector<char>> Calls;
public:
- FunctionSummary(SmallVector<char> ID, std::set<const SummaryAttribute *> FunctionAttrs, std::set<SmallVector<char>> Calls);
- FunctionSummary(const clang::FunctionDecl *FD);
+ FunctionSummary(SmallVector<char> ID,
+ std::set<const SummaryAttribute *> Attrs,
+ std::set<SmallVector<char>> Calls);
SmallVector<char> getID() const { return ID; }
- const std::set<const SummaryAttribute *> &getFunctionAttrs() const { return FunctionAttrs; }
+ const std::set<const SummaryAttribute *> &getAttributes() const {
+ return Attrs;
+ }
const std::set<SmallVector<char>> &getCalls() const { return Calls; }
- void replaceAttributes(std::set<const SummaryAttribute *> Attrs) { FunctionAttrs = std::move(Attrs); }
- void addAttribute(const SummaryAttribute * Attr) { FunctionAttrs.emplace(Attr); }
+ void replaceAttributes(std::set<const SummaryAttribute *> Attrs) {
+ this->Attrs = std::move(Attrs);
+ }
- void addCall(const clang::FunctionDecl *FD);
+ friend class SummaryManager;
};
class SummaryManager {
std::map<SmallVector<char>, const FunctionSummary *> IDToSummary;
std::vector<std::unique_ptr<FunctionSummary>> FunctionSummaries;
-
+
std::map<SummaryAttributeKind, const SummaryAttribute *> KindToAttribute;
std::vector<std::unique_ptr<SummaryAttribute>> Attributes;
- void SaveSummary(std::unique_ptr<FunctionSummary> Summary);
+ void CreateSummary(SmallVector<char> ID,
+ std::set<const SummaryAttribute *> Attrs,
+ std::set<SmallVector<char>> Calls);
bool ReduceFunctionSummary(FunctionSummary &FunctionSummary);
+
public:
SummaryManager();
const FunctionSummary *GetSummary(const FunctionDecl *FD) const;
void SummarizeFunctionBody(const FunctionDecl *FD);
-
+
void SerializeSummary(llvm::json::OStream &, const FunctionSummary &) const;
void ParseSummaryFromJSON(StringRef path);
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index bfe7ecf84e795..22067da3a4b81 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -17,16 +17,19 @@ class SummaryAttribute {
std::string_view Serialzed;
public:
- SummaryAttribute(SummaryAttributeKind Attr, const char *Str) : Kind(Attr), Serialzed(Str) {}
+ SummaryAttribute(SummaryAttributeKind Attr, const char *Str)
+ : Kind(Attr), Serialzed(Str) {}
virtual ~SummaryAttribute() = default;
-
+
SummaryAttributeKind getKind() { return Kind; }
virtual bool infer(const FunctionDecl *FD) const = 0;
virtual bool merge(const FunctionSummary &Summary) const = 0;
virtual std::string serialize() const { return std::string(Serialzed); };
- virtual bool parse(std::string_view input) const { return input == Serialzed; };
+ virtual bool parse(std::string_view input) const {
+ return input == Serialzed;
+ };
};
class NoWriteGlobalDescription : public SummaryAttribute {
@@ -34,13 +37,14 @@ class NoWriteGlobalDescription : public SummaryAttribute {
public:
bool WriteGlobal = false;
- void run(const ast_matchers::MatchFinder::MatchResult &Result) override final;
+ void
+ run(const ast_matchers::MatchFinder::MatchResult &Result) override final;
};
public:
NoWriteGlobalDescription()
- : SummaryAttribute(NO_WRITE_GLOBAL, "no_write_global") {}
-
+ : SummaryAttribute(NO_WRITE_GLOBAL, "no_write_global") {}
+
bool infer(const FunctionDecl *FD) const override final;
bool merge(const FunctionSummary &Summary) const override final;
};
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 97b2d50bd7602..811c95028abb0 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -9,10 +9,14 @@
namespace clang {
namespace {
-class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
- FunctionSummary *Summary;
+SmallVector<char> GetUSR(const FunctionDecl *FD) {
+ SmallVector<char> USR;
+ index::generateUSRForDecl(FD, USR);
+ return USR;
+}
- CallCollector(FunctionSummary &Summary) : Summary(&Summary) {}
+class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
+ std::set<SmallVector<char>> Calls;
virtual void
run(const ast_matchers::MatchFinder::MatchResult &Result) override {
@@ -21,78 +25,70 @@ class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
return;
const auto *Callee = llvm::dyn_cast<FunctionDecl>(Call->getCalleeDecl());
- Summary->addCall(Callee);
+ Calls.emplace(GetUSR(Callee));
}
public:
- static void CollectCalledFunctions(const FunctionDecl *FD,
- FunctionSummary &Summary) {
+ std::set<SmallVector<char>> collect(const FunctionDecl *FD) {
using namespace ast_matchers;
MatchFinder Finder;
- CallCollector CC(Summary);
Finder.addMatcher(functionDecl(forEachDescendant(callExpr().bind("call"))),
- &CC);
+ this);
Finder.match(*FD, FD->getASTContext());
+
+ return Calls;
}
};
-
-SmallVector<char> GetUSR(const FunctionDecl *FD) {
- SmallVector<char> USR;
- index::generateUSRForDecl(FD, USR);
- return USR;
-}
} // namespace
-void FunctionSummary::addCall(const clang::FunctionDecl *FD) {
- Calls.emplace(GetUSR(FD));
-}
-
-FunctionSummary::FunctionSummary(SmallVector<char> ID, std::set<const SummaryAttribute *> FunctionAttrs, std::set<SmallVector<char>> Calls) :
- ID(std::move(ID)), FunctionAttrs(std::move(FunctionAttrs)), Calls(std::move(Calls)) {}
-
-FunctionSummary::FunctionSummary(const clang::FunctionDecl *FD) : ID(GetUSR(FD)) {}
+FunctionSummary::FunctionSummary(
+ SmallVector<char> ID, std::set<const SummaryAttribute *> FunctionAttrs,
+ std::set<SmallVector<char>> Calls)
+ : ID(std::move(ID)), Attrs(std::move(FunctionAttrs)),
+ Calls(std::move(Calls)) {}
SummaryManager::SummaryManager() {
Attributes.emplace_back(std::make_unique<NoWriteGlobalDescription>());
- for(auto &&Attr : Attributes) {
- assert(KindToAttribute.count(Attr->getKind()) == 0 && "Attr already registered");
+ for (auto &&Attr : Attributes) {
+ assert(KindToAttribute.count(Attr->getKind()) == 0 &&
+ "Attr already registered");
KindToAttribute[Attr->getKind()] = Attr.get();
}
}
-void SummaryManager::SaveSummary(std::unique_ptr<FunctionSummary> Summary) {
+void SummaryManager::CreateSummary(SmallVector<char> ID,
+ std::set<const SummaryAttribute *> Attrs,
+ std::set<SmallVector<char>> Calls) {
+ auto Summary = std::make_unique<FunctionSummary>(
+ std::move(ID), std::move(Attrs), std::move(Calls));
auto *SummaryPtr = FunctionSummaries.emplace_back(std::move(Summary)).get();
IDToSummary[SummaryPtr->getID()] = SummaryPtr;
}
-const FunctionSummary *SummaryManager::GetSummary(const FunctionDecl *FD) const {
+const FunctionSummary *
+SummaryManager::GetSummary(const FunctionDecl *FD) const {
auto USR = GetUSR(FD);
- if(!IDToSummary.count(USR))
- return nullptr;
-
- return IDToSummary.at(USR);
+ return IDToSummary.count(USR) ? IDToSummary.at(USR) : nullptr;
}
void SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
- auto Summary = std::make_unique<FunctionSummary>(FD);
- CallCollector::CollectCalledFunctions(FD, *Summary);
-
+ std::set<const SummaryAttribute *> Attrs;
for (auto &&Attr : Attributes) {
if (Attr->infer(FD))
- Summary->addAttribute(Attr.get());
+ Attrs.emplace(Attr.get());
}
- SaveSummary(std::move(Summary));
+ CreateSummary(GetUSR(FD), std::move(Attrs), CallCollector().collect(FD));
}
void SummaryManager::SerializeSummary(llvm::json::OStream &JOS, const FunctionSummary &Summary) const {
JOS.object([&]{
JOS.attribute("id", llvm::json::Value(Summary.getID()));
- JOS.attributeObject("attrs", [&]{
- JOS.attributeArray("function", [&]{
- for(auto &&Attr : Summary.getFunctionAttrs()) {
+ JOS.attributeObject("attrs", [&] {
+ JOS.attributeArray("function", [&] {
+ for (auto &&Attr : Summary.getAttributes()) {
JOS.value(llvm::json::Value(Attr->serialize()));
}
});
@@ -124,8 +120,8 @@ void SummaryManager::ParseSummaryFromJSON(StringRef path) {
std::set<const SummaryAttribute *> FunctionAttrs;
llvm::json::Array *FunctionAttributes = Summary->getObject("attrs")->getArray("function");
for(auto attrIt = FunctionAttributes->begin(); attrIt != FunctionAttributes->end(); ++attrIt) {
- for(auto &&Attr : Attributes) {
- if(Attr->parse(*attrIt->getAsString()))
+ for (auto &&Attr : Attributes) {
+ if (Attr->parse(*attrIt->getAsString()))
FunctionAttrs.emplace(Attr.get());
}
}
@@ -136,8 +132,8 @@ void SummaryManager::ParseSummaryFromJSON(StringRef path) {
auto *Obj = callIt->getAsObject();
Calls.emplace(SmallString<128>(*Obj->getString("id")));
}
-
- SaveSummary(std::make_unique<FunctionSummary>(std::move(ID), std::move(FunctionAttrs), std::move(Calls)));
+
+ CreateSummary(std::move(ID), std::move(FunctionAttrs), std::move(Calls));
}
}
@@ -156,12 +152,12 @@ bool SummaryManager::ReduceFunctionSummary(FunctionSummary &Function) {
const FunctionSummary *callSummary = IDToSummary[call];
- for (auto &&Attr : Function.getFunctionAttrs()) {
+ for (auto &&Attr : Function.getAttributes()) {
if (Attr->merge(*callSummary))
reducedAttrs.emplace(Attr);
}
- if (reducedAttrs != Function.getFunctionAttrs()) {
+ if (reducedAttrs != Function.getAttributes()) {
Function.replaceAttributes(std::move(reducedAttrs));
changed = true;
}
@@ -194,7 +190,8 @@ void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
TheSummaryManager->SummarizeFunctionBody(FD);
if(TheSummaryConsumer)
- TheSummaryConsumer->ProcessFunctionSummary(*TheSummaryManager->GetSummary(FD));
+ TheSummaryConsumer->ProcessFunctionSummary(
+ *TheSummaryManager->GetSummary(FD));
}
} // namespace clang
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Sema/SummaryAttribute.cpp
index 953cc38b2e7a1..c1611ef90fae5 100644
--- a/clang/lib/Sema/SummaryAttribute.cpp
+++ b/clang/lib/Sema/SummaryAttribute.cpp
@@ -2,9 +2,9 @@
#include "clang/Sema/SemaSummarizer.h"
namespace clang {
-void NoWriteGlobalDescription::Callback::run(const ast_matchers::MatchFinder::MatchResult &Result) {
- const auto *Assignment =
- Result.Nodes.getNodeAs<BinaryOperator>("assignment");
+void NoWriteGlobalDescription::Callback::run(
+ const ast_matchers::MatchFinder::MatchResult &Result) {
+ const auto *Assignment = Result.Nodes.getNodeAs<BinaryOperator>("assignment");
if (!Assignment)
return;
@@ -27,6 +27,6 @@ bool NoWriteGlobalDescription::infer(const FunctionDecl *FD) const {
}
bool NoWriteGlobalDescription::merge(const FunctionSummary &Summary) const {
- return Summary.getFunctionAttrs().count(this);
+ return Summary.getAttributes().count(this);
}
} // namespace clang
\ No newline at end of file
>From d8c26d3d7a6bcf989748bcde25f6ef46c93f43eb Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 12 Jun 2025 01:13:23 +0200
Subject: [PATCH 11/25] [clang][Summary] the summary manager shouldn't be
reading the JSON file
---
clang/include/clang/Sema/SemaSummarizer.h | 2 +-
clang/lib/Frontend/FrontendAction.cpp | 15 +++++++++++--
clang/lib/Sema/SemaSummarizer.cpp | 26 +++++++----------------
3 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 7fea668bae694..2c58591350b8e 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -49,7 +49,7 @@ class SummaryManager {
void SummarizeFunctionBody(const FunctionDecl *FD);
void SerializeSummary(llvm::json::OStream &, const FunctionSummary &) const;
- void ParseSummaryFromJSON(StringRef path);
+ void ParseSummaryFromJSON(const llvm::json::Array &Summary);
void ReduceSummaries();
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 7af4a79f83eec..b8732e58e7ffd 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -47,7 +47,9 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include <fstream>
#include <memory>
+#include <sstream>
#include <system_error>
using namespace clang;
@@ -981,8 +983,17 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
- if (llvm::sys::path::extension(Dir->path()) == ".json")
- CI.getSummaryManager().ParseSummaryFromJSON(Dir->path());
+ if (llvm::sys::path::extension(Dir->path()) == ".json") {
+ std::ifstream t(Dir->path().str());
+ std::stringstream buffer;
+ buffer << t.rdbuf();
+
+ auto JSON = llvm::json::parse(buffer.str());
+ if (!JSON)
+ continue;
+
+ CI.getSummaryManager().ParseSummaryFromJSON(*JSON->getAsArray());
+ }
}
// FIXME: debug only, remove later
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 811c95028abb0..5cd25fd563b90 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -1,11 +1,9 @@
#include "clang/Sema/SemaSummarizer.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Index/USRGeneration.h"
-#include "clang/Sema/SummaryConsumer.h"
#include "clang/Sema/SummaryAttribute.h"
+#include "clang/Sema/SummaryConsumer.h"
#include <set>
-#include <fstream>
-#include <sstream>
namespace clang {
namespace {
@@ -103,22 +101,14 @@ void SummaryManager::SerializeSummary(llvm::json::OStream &JOS, const FunctionSu
});
}
-void SummaryManager::ParseSummaryFromJSON(StringRef path) {
- std::ifstream t(path.str());
- std::stringstream buffer;
- buffer << t.rdbuf();
-
- auto JSON = llvm::json::parse(buffer.str());
- if (!JSON)
- return;
-
- llvm::json::Array *Summaries = JSON->getAsArray();
- for(auto it = Summaries->begin(); it != Summaries->end(); ++it) {
- llvm::json::Object *Summary = it->getAsObject();
+void SummaryManager::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
+ for (auto it = Summary.begin(); it != Summary.end(); ++it) {
+ const llvm::json::Object *FunctionSummary = it->getAsObject();
- SmallString<128> ID(*Summary->getString("id"));
+ SmallString<128> ID(*FunctionSummary->getString("id"));
std::set<const SummaryAttribute *> FunctionAttrs;
- llvm::json::Array *FunctionAttributes = Summary->getObject("attrs")->getArray("function");
+ const llvm::json::Array *FunctionAttributes =
+ FunctionSummary->getObject("attrs")->getArray("function");
for(auto attrIt = FunctionAttributes->begin(); attrIt != FunctionAttributes->end(); ++attrIt) {
for (auto &&Attr : Attributes) {
if (Attr->parse(*attrIt->getAsString()))
@@ -127,7 +117,7 @@ void SummaryManager::ParseSummaryFromJSON(StringRef path) {
}
std::set<SmallVector<char>> Calls;
- llvm::json::Array *CallEntries = Summary->getArray("calls");
+ const llvm::json::Array *CallEntries = FunctionSummary->getArray("calls");
for(auto callIt = CallEntries->begin(); callIt != CallEntries->end(); ++callIt) {
auto *Obj = callIt->getAsObject();
Calls.emplace(SmallString<128>(*Obj->getString("id")));
>From b5465c15d2e8bf8d9667894a775b96cdaa99c768 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 12 Jun 2025 01:17:07 +0200
Subject: [PATCH 12/25] [clang][Summary] the summary manager shouldn't contain
the JSON summary consumer logic
---
clang/include/clang/Sema/SemaSummarizer.h | 7 -------
clang/lib/Frontend/FrontendAction.cpp | 14 --------------
clang/lib/Sema/SemaSummarizer.cpp | 20 --------------------
clang/lib/Sema/SummaryConsumer.cpp | 16 +++++++++++++++-
4 files changed, 15 insertions(+), 42 deletions(-)
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SemaSummarizer.h
index 2c58591350b8e..7e0c5990e5de1 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SemaSummarizer.h
@@ -48,15 +48,8 @@ class SummaryManager {
const FunctionSummary *GetSummary(const FunctionDecl *FD) const;
void SummarizeFunctionBody(const FunctionDecl *FD);
- void SerializeSummary(llvm::json::OStream &, const FunctionSummary &) const;
void ParseSummaryFromJSON(const llvm::json::Array &Summary);
-
void ReduceSummaries();
-
- // FIXME: debug only, remove later
- const std::vector<std::unique_ptr<FunctionSummary>> &getSummaries() {
- return FunctionSummaries;
- }
};
// FIXME: Is this class needed?
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index b8732e58e7ffd..dfbc3e0d14e91 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -996,21 +996,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
}
}
- // FIXME: debug only, remove later
- for (auto &&S : CI.getSummaryManager().getSummaries()) {
- llvm::json::OStream Out(llvm::errs());
- CI.getSummaryManager().SerializeSummary(Out, *S);
- }
- llvm::errs() << '\n';
-
CI.getSummaryManager().ReduceSummaries();
-
- // FIXME: debug only, remove later
- for (auto &&S : CI.getSummaryManager().getSummaries()) {
- llvm::json::OStream Out(llvm::errs());
- CI.getSummaryManager().SerializeSummary(Out, *S);
- }
- llvm::errs() << '\n';
}
}
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 5cd25fd563b90..615df8e78a90b 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -81,26 +81,6 @@ void SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
CreateSummary(GetUSR(FD), std::move(Attrs), CallCollector().collect(FD));
}
-void SummaryManager::SerializeSummary(llvm::json::OStream &JOS, const FunctionSummary &Summary) const {
- JOS.object([&]{
- JOS.attribute("id", llvm::json::Value(Summary.getID()));
- JOS.attributeObject("attrs", [&] {
- JOS.attributeArray("function", [&] {
- for (auto &&Attr : Summary.getAttributes()) {
- JOS.value(llvm::json::Value(Attr->serialize()));
- }
- });
- });
- JOS.attributeArray("calls", [&]{
- for(auto &&Call : Summary.getCalls()) {
- JOS.object([&]{
- JOS.attribute("id", llvm::json::Value(Call));
- });
- }
- });
- });
-}
-
void SummaryManager::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
for (auto it = Summary.begin(); it != Summary.end(); ++it) {
const llvm::json::Object *FunctionSummary = it->getAsObject();
diff --git a/clang/lib/Sema/SummaryConsumer.cpp b/clang/lib/Sema/SummaryConsumer.cpp
index 37646c1e07a7f..b10bc827f94ab 100644
--- a/clang/lib/Sema/SummaryConsumer.cpp
+++ b/clang/lib/Sema/SummaryConsumer.cpp
@@ -3,6 +3,20 @@
namespace clang {
void JSONPrintingSummaryConsumer::ProcessFunctionSummary(const FunctionSummary &Summary) {
- TheSummaryManager->SerializeSummary(JOS, Summary);
+ JOS.object([&] {
+ JOS.attribute("id", llvm::json::Value(Summary.getID()));
+ JOS.attributeObject("attrs", [&] {
+ JOS.attributeArray("function", [&] {
+ for (auto &&Attr : Summary.getAttributes()) {
+ JOS.value(llvm::json::Value(Attr->serialize()));
+ }
+ });
+ });
+ JOS.attributeArray("calls", [&] {
+ for (auto &&Call : Summary.getCalls()) {
+ JOS.object([&] { JOS.attribute("id", llvm::json::Value(Call)); });
+ }
+ });
+ });
}
} // namespace clang
\ No newline at end of file
>From 1754b30c1a54261223b827da001ba078815b79ea Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 12 Jun 2025 01:25:59 +0200
Subject: [PATCH 13/25] [clang][Summary] rename description to attr
---
clang/include/clang/Sema/SummaryAttribute.h | 5 ++---
clang/lib/Sema/SemaSummarizer.cpp | 2 +-
clang/lib/Sema/SummaryAttribute.cpp | 6 +++---
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index 22067da3a4b81..759710fb052e6 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -32,7 +32,7 @@ class SummaryAttribute {
};
};
-class NoWriteGlobalDescription : public SummaryAttribute {
+class NoWriteGlobalAttr : public SummaryAttribute {
class Callback : public ast_matchers::MatchFinder::MatchCallback {
public:
bool WriteGlobal = false;
@@ -42,8 +42,7 @@ class NoWriteGlobalDescription : public SummaryAttribute {
};
public:
- NoWriteGlobalDescription()
- : SummaryAttribute(NO_WRITE_GLOBAL, "no_write_global") {}
+ NoWriteGlobalAttr() : SummaryAttribute(NO_WRITE_GLOBAL, "no_write_global") {}
bool infer(const FunctionDecl *FD) const override final;
bool merge(const FunctionSummary &Summary) const override final;
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 615df8e78a90b..63091b6f7fefc 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -47,7 +47,7 @@ FunctionSummary::FunctionSummary(
Calls(std::move(Calls)) {}
SummaryManager::SummaryManager() {
- Attributes.emplace_back(std::make_unique<NoWriteGlobalDescription>());
+ Attributes.emplace_back(std::make_unique<NoWriteGlobalAttr>());
for (auto &&Attr : Attributes) {
assert(KindToAttribute.count(Attr->getKind()) == 0 &&
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Sema/SummaryAttribute.cpp
index c1611ef90fae5..48fda7077f4a3 100644
--- a/clang/lib/Sema/SummaryAttribute.cpp
+++ b/clang/lib/Sema/SummaryAttribute.cpp
@@ -2,7 +2,7 @@
#include "clang/Sema/SemaSummarizer.h"
namespace clang {
-void NoWriteGlobalDescription::Callback::run(
+void NoWriteGlobalAttr::Callback::run(
const ast_matchers::MatchFinder::MatchResult &Result) {
const auto *Assignment = Result.Nodes.getNodeAs<BinaryOperator>("assignment");
if (!Assignment)
@@ -11,7 +11,7 @@ void NoWriteGlobalDescription::Callback::run(
WriteGlobal = true;
}
-bool NoWriteGlobalDescription::infer(const FunctionDecl *FD) const {
+bool NoWriteGlobalAttr::infer(const FunctionDecl *FD) const {
using namespace ast_matchers;
MatchFinder Finder;
Callback CB;
@@ -26,7 +26,7 @@ bool NoWriteGlobalDescription::infer(const FunctionDecl *FD) const {
return !CB.WriteGlobal;
}
-bool NoWriteGlobalDescription::merge(const FunctionSummary &Summary) const {
+bool NoWriteGlobalAttr::merge(const FunctionSummary &Summary) const {
return Summary.getAttributes().count(this);
}
} // namespace clang
\ No newline at end of file
>From 7e27c32c9a0c03a0fc995bb3710aac61494219ad Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Fri, 13 Jun 2025 00:21:50 +0200
Subject: [PATCH 14/25] [clang][Summary] more flexible merge logic
---
clang/include/clang/Sema/SummaryAttribute.h | 6 ++++--
clang/lib/Sema/SemaSummarizer.cpp | 7 ++++---
clang/lib/Sema/SummaryAttribute.cpp | 6 ++++--
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index 759710fb052e6..0014a9878bacd 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -24,7 +24,8 @@ class SummaryAttribute {
SummaryAttributeKind getKind() { return Kind; }
virtual bool infer(const FunctionDecl *FD) const = 0;
- virtual bool merge(const FunctionSummary &Summary) const = 0;
+ virtual bool merge(const FunctionSummary &Caller,
+ const FunctionSummary &Callee) const = 0;
virtual std::string serialize() const { return std::string(Serialzed); };
virtual bool parse(std::string_view input) const {
@@ -45,7 +46,8 @@ class NoWriteGlobalAttr : public SummaryAttribute {
NoWriteGlobalAttr() : SummaryAttribute(NO_WRITE_GLOBAL, "no_write_global") {}
bool infer(const FunctionDecl *FD) const override final;
- bool merge(const FunctionSummary &Summary) const override final;
+ bool merge(const FunctionSummary &Caller,
+ const FunctionSummary &Callee) const override final;
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SemaSummarizer.cpp
index 63091b6f7fefc..3b056fc53f8c9 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SemaSummarizer.cpp
@@ -73,6 +73,7 @@ SummaryManager::GetSummary(const FunctionDecl *FD) const {
void SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
std::set<const SummaryAttribute *> Attrs;
+
for (auto &&Attr : Attributes) {
if (Attr->infer(FD))
Attrs.emplace(Attr.get());
@@ -122,9 +123,9 @@ bool SummaryManager::ReduceFunctionSummary(FunctionSummary &Function) {
const FunctionSummary *callSummary = IDToSummary[call];
- for (auto &&Attr : Function.getAttributes()) {
- if (Attr->merge(*callSummary))
- reducedAttrs.emplace(Attr);
+ for (auto &&Attr : Attributes) {
+ if (Attr->merge(Function, *callSummary))
+ reducedAttrs.emplace(Attr.get());
}
if (reducedAttrs != Function.getAttributes()) {
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Sema/SummaryAttribute.cpp
index 48fda7077f4a3..6f141dde68e52 100644
--- a/clang/lib/Sema/SummaryAttribute.cpp
+++ b/clang/lib/Sema/SummaryAttribute.cpp
@@ -26,7 +26,9 @@ bool NoWriteGlobalAttr::infer(const FunctionDecl *FD) const {
return !CB.WriteGlobal;
}
-bool NoWriteGlobalAttr::merge(const FunctionSummary &Summary) const {
- return Summary.getAttributes().count(this);
+bool NoWriteGlobalAttr::merge(const FunctionSummary &Caller,
+ const FunctionSummary &Callee) const {
+ return Caller.getAttributes().count(this) &&
+ Callee.getAttributes().count(this);
}
} // namespace clang
\ No newline at end of file
>From 4f8acb909effe739523a7342e5bf6dbb0ac75353 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 00:02:10 +0200
Subject: [PATCH 15/25] [clang][Summary] refactor summaries in the compiler
instance and sema
---
.../include/clang/Frontend/CompilerInstance.h | 41 ++++++++++---------
clang/include/clang/Sema/Sema.h | 8 ++--
clang/include/clang/Sema/SummaryConsumer.h | 27 ++++++------
.../{SemaSummarizer.h => SummaryContext.h} | 27 +++---------
clang/lib/Frontend/CompilerInstance.cpp | 19 +++++----
clang/lib/Frontend/FrontendAction.cpp | 14 +++----
clang/lib/Sema/CMakeLists.txt | 2 +-
clang/lib/Sema/Sema.cpp | 21 +++++-----
clang/lib/Sema/SemaDecl.cpp | 8 ++--
clang/lib/Sema/SummaryAttribute.cpp | 2 +-
clang/lib/Sema/SummaryConsumer.cpp | 2 +-
...{SemaSummarizer.cpp => SummaryContext.cpp} | 35 ++++------------
12 files changed, 89 insertions(+), 117 deletions(-)
rename clang/include/clang/Sema/{SemaSummarizer.h => SummaryContext.h} (67%)
rename clang/lib/Sema/{SemaSummarizer.cpp => SummaryContext.cpp} (82%)
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index f8f13bbc998d9..b107f15af9563 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -19,6 +19,7 @@
#include "clang/Lex/DependencyDirectivesScanner.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleLoader.h"
+#include "clang/Sema/SummaryContext.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -48,6 +49,7 @@ class ModuleFile;
}
class CodeCompleteConsumer;
+class SummaryContext;
class SummaryConsumer;
class DiagnosticsEngine;
class DiagnosticConsumer;
@@ -57,7 +59,6 @@ class Module;
class ModuleCache;
class Preprocessor;
class Sema;
-class SummaryManager;
class SourceManager;
class TargetInfo;
enum class DisableValidationForModuleKind;
@@ -125,9 +126,12 @@ class CompilerInstance : public ModuleLoader {
/// The summary consumer.
std::unique_ptr<SummaryConsumer> TheSummaryConsumer;
-
- /// The summary manager object.
- std::unique_ptr<SummaryManager> TheSummaryManager;
+
+ /// The summary context.
+ std::unique_ptr<SummaryContext> SummaryCtx;
+
+ /// The summary output file.
+ std::unique_ptr<llvm::raw_fd_ostream> SummaryOS;
/// The semantic analysis object.
std::unique_ptr<Sema> TheSema;
@@ -524,15 +528,6 @@ class CompilerInstance : public ModuleLoader {
/// setASTContext - Replace the current AST context.
void setASTContext(ASTContext *Value);
- bool hasSummaryManager() {
- return TheSummaryManager != nullptr;
- }
-
- SummaryManager &getSummaryManager() {
- assert(TheSummaryManager && "Compiler instance has no summary manager!");
- return *TheSummaryManager;
- }
-
/// Replace the current Sema; the compiler instance takes ownership
/// of S.
void setSema(Sema *S);
@@ -624,10 +619,23 @@ class CompilerInstance : public ModuleLoader {
return *CompletionConsumer;
}
+ /// setCodeCompletionConsumer - Replace the current code completion consumer;
+ /// the compiler instance takes ownership of \p Value.
+ void setCodeCompletionConsumer(CodeCompleteConsumer *Value);
+
/// @}
/// @name Summary
/// @{
+ bool hasSummaryContext() { return (bool)SummaryCtx; }
+
+ SummaryContext &getSummaryContext() {
+ assert(SummaryCtx && "Compiler instance has no summary context!");
+ return *SummaryCtx;
+ }
+
+ void createSummaryContext() { SummaryCtx.reset(new SummaryContext()); }
+
bool hasSummaryConsumer() const { return (bool)TheSummaryConsumer; }
SummaryConsumer &getSummaryConsumer() const {
@@ -636,9 +644,7 @@ class CompilerInstance : public ModuleLoader {
return *TheSummaryConsumer;
}
- /// setCodeCompletionConsumer - Replace the current code completion consumer;
- /// the compiler instance takes ownership of \p Value.
- void setCodeCompletionConsumer(CodeCompleteConsumer *Value);
+ void createSummaryConsumer();
/// @}
/// @name Frontend timer
@@ -765,9 +771,6 @@ class CompilerInstance : public ModuleLoader {
Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column,
const CodeCompleteOptions &Opts, raw_ostream &OS);
- void createSummaryConsumer();
- void createSummaryManager();
-
/// Create the Sema object to be used for parsing.
void createSema(TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer,
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b36fce47fb792..1a4d2e99685e0 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -125,7 +125,7 @@ class CXXBasePath;
class CXXBasePaths;
class CXXFieldCollector;
class CodeCompleteConsumer;
-class SummaryManager;
+class SummaryContext;
class SummaryConsumer;
enum class ComparisonCategoryType : unsigned char;
class ConstraintSatisfaction;
@@ -161,7 +161,6 @@ class SemaARM;
class SemaAVR;
class SemaBPF;
class SemaCodeCompletion;
-class SemaSummarizer;
class SemaCUDA;
class SemaDirectX;
class SemaHLSL;
@@ -887,7 +886,7 @@ class Sema final : public SemaBase {
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind = TU_Complete,
CodeCompleteConsumer *CompletionConsumer = nullptr,
- SummaryManager *SummaryManager = nullptr,
+ SummaryContext *SummaryCtx = nullptr,
SummaryConsumer *SummaryConsumer = nullptr);
~Sema();
@@ -1265,6 +1264,8 @@ class Sema final : public SemaBase {
DiagnosticsEngine &Diags;
SourceManager &SourceMgr;
api_notes::APINotesManager APINotes;
+ SummaryContext *SummaryCtx;
+ SummaryConsumer *SummaryCnsmr;
/// A RAII object to enter scope of a compound statement.
class CompoundScopeRAII {
@@ -1569,7 +1570,6 @@ class Sema final : public SemaBase {
std::unique_ptr<SemaAVR> AVRPtr;
std::unique_ptr<SemaBPF> BPFPtr;
std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
- std::unique_ptr<SemaSummarizer> SummarizerPtr;
std::unique_ptr<SemaCUDA> CUDAPtr;
std::unique_ptr<SemaDirectX> DirectXPtr;
std::unique_ptr<SemaHLSL> HLSLPtr;
diff --git a/clang/include/clang/Sema/SummaryConsumer.h b/clang/include/clang/Sema/SummaryConsumer.h
index 85c48b3c1b939..f8844ffb64e21 100644
--- a/clang/include/clang/Sema/SummaryConsumer.h
+++ b/clang/include/clang/Sema/SummaryConsumer.h
@@ -5,36 +5,37 @@
#include "llvm/Support/JSON.h"
namespace clang {
class FunctionSummary;
-class SummaryManager;
+class SummaryContext;
class SummaryConsumer {
protected:
- const SummaryManager *TheSummaryManager;
+ const SummaryContext *SummaryCtx;
public:
- SummaryConsumer(const SummaryManager &SummaryManager) : TheSummaryManager(&SummaryManager) {}
- virtual ~SummaryConsumer() = default;
+ SummaryConsumer(const SummaryContext &SummaryCtx) : SummaryCtx(&SummaryCtx) {}
+ virtual ~SummaryConsumer() = default;
- virtual void ProcessStartOfSourceFile() {};
- virtual void ProcessFunctionSummary(const FunctionSummary&) {};
- virtual void ProcessEndOfSourceFile() {};
+ virtual void ProcessStartOfSourceFile(){};
+ virtual void ProcessFunctionSummary(const FunctionSummary &){};
+ virtual void ProcessEndOfSourceFile(){};
};
class PrintingSummaryConsumer : public SummaryConsumer {
public:
- PrintingSummaryConsumer(const SummaryManager &SummaryManager, raw_ostream &OS)
- : SummaryConsumer(SummaryManager) {}
+ PrintingSummaryConsumer(const SummaryContext &SummaryCtx, raw_ostream &OS)
+ : SummaryConsumer(SummaryCtx) {}
};
class JSONPrintingSummaryConsumer : public PrintingSummaryConsumer {
llvm::json::OStream JOS;
public:
- JSONPrintingSummaryConsumer(const SummaryManager &SummaryManager, raw_ostream &OS) : PrintingSummaryConsumer(SummaryManager, OS), JOS(OS, 2) {}
+ JSONPrintingSummaryConsumer(const SummaryContext &SummaryCtx, raw_ostream &OS)
+ : PrintingSummaryConsumer(SummaryCtx, OS), JOS(OS, 2) {}
- void ProcessStartOfSourceFile() override { JOS.arrayBegin(); };
- void ProcessFunctionSummary(const FunctionSummary&) override;
- void ProcessEndOfSourceFile() override { JOS.arrayEnd(); };
+ void ProcessStartOfSourceFile() override { JOS.arrayBegin(); };
+ void ProcessFunctionSummary(const FunctionSummary &) override;
+ void ProcessEndOfSourceFile() override { JOS.arrayEnd(); };
};
} // namespace clang
diff --git a/clang/include/clang/Sema/SemaSummarizer.h b/clang/include/clang/Sema/SummaryContext.h
similarity index 67%
rename from clang/include/clang/Sema/SemaSummarizer.h
rename to clang/include/clang/Sema/SummaryContext.h
index 7e0c5990e5de1..67b1162d61763 100644
--- a/clang/include/clang/Sema/SemaSummarizer.h
+++ b/clang/include/clang/Sema/SummaryContext.h
@@ -1,7 +1,6 @@
-#ifndef LLVM_CLANG_SEMA_SEMASUMMARIZER_H
-#define LLVM_CLANG_SEMA_SEMASUMMARIZER_H
+#ifndef LLVM_CLANG_SEMA_SEMASUMMARYCONTEXT_H
+#define LLVM_CLANG_SEMA_SEMASUMMARYCONTEXT_H
-#include "clang/Sema/SemaBase.h"
#include "clang/Sema/SummaryAttribute.h"
#include "clang/Sema/SummaryConsumer.h"
#include <set>
@@ -26,11 +25,9 @@ class FunctionSummary {
void replaceAttributes(std::set<const SummaryAttribute *> Attrs) {
this->Attrs = std::move(Attrs);
}
-
- friend class SummaryManager;
};
-class SummaryManager {
+class SummaryContext {
std::map<SmallVector<char>, const FunctionSummary *> IDToSummary;
std::vector<std::unique_ptr<FunctionSummary>> FunctionSummaries;
@@ -43,7 +40,7 @@ class SummaryManager {
bool ReduceFunctionSummary(FunctionSummary &FunctionSummary);
public:
- SummaryManager();
+ SummaryContext();
const FunctionSummary *GetSummary(const FunctionDecl *FD) const;
void SummarizeFunctionBody(const FunctionDecl *FD);
@@ -51,20 +48,6 @@ class SummaryManager {
void ParseSummaryFromJSON(const llvm::json::Array &Summary);
void ReduceSummaries();
};
-
-// FIXME: Is this class needed?
-class SemaSummarizer : public SemaBase {
-public:
- SummaryManager *TheSummaryManager;
- SummaryConsumer *TheSummaryConsumer;
-
- SemaSummarizer(Sema &S, SummaryManager &SummaryManager, SummaryConsumer *SummaryConsumer)
- : SemaBase(S), TheSummaryManager(&SummaryManager), TheSummaryConsumer(SummaryConsumer) {};
-
- void ActOnStartOfSourceFile();
- void ActOnEndOfSourceFile();
- void SummarizeFunctionBody(const FunctionDecl *FD);
-};
} // namespace clang
-#endif // LLVM_CLANG_SEMA_SEMASUMMARIZE_H
+#endif // LLVM_CLANG_SEMA_SEMASUMMARYCONTEXTH
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index deed94e1f0b42..448d45b0f49db 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -37,7 +37,6 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaSummarizer.h"
#include "clang/Sema/SummaryConsumer.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
@@ -749,22 +748,24 @@ void CompilerInstance::createSummaryConsumer() {
return;
std::error_code EC;
- // FIXME: this being static is a design error
- static llvm::raw_fd_ostream SummaryOS(SummaryFile, EC, llvm::sys::fs::CD_CreateAlways);
+ SummaryOS.reset(new llvm::raw_fd_ostream(SummaryFile, EC,
+ llvm::sys::fs::CD_CreateAlways));
- if(!EC)
- TheSummaryConsumer.reset(new JSONPrintingSummaryConsumer(getSummaryManager(), SummaryOS));
-}
+ if (EC) {
+ SummaryOS = nullptr;
+ return;
+ }
-void CompilerInstance::createSummaryManager() {
- TheSummaryManager.reset(new SummaryManager());
+ TheSummaryConsumer.reset(
+ new JSONPrintingSummaryConsumer(getSummaryContext(), *SummaryOS));
}
void CompilerInstance::createSema(TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer,
SummaryConsumer *SummaryConsumer) {
TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
- TUKind, CompletionConsumer, hasSummaryManager() ? &getSummaryManager() : nullptr, SummaryConsumer));
+ TUKind, CompletionConsumer, &getSummaryContext(),
+ SummaryConsumer));
// Set up API notes.
TheSema->APINotes.setSwiftVersion(getAPINotesOpts().SwiftVersion);
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index dfbc3e0d14e91..2821327c6a824 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -35,7 +35,7 @@
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/HLSLExternalSemaSource.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
-#include "clang/Sema/SemaSummarizer.h"
+#include "clang/Sema/SummaryContext.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
@@ -895,8 +895,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
}
}
- if(!CI.hasSummaryManager()) {
- CI.createSummaryManager();
+ if (!CI.hasSummaryContext()) {
+ CI.createSummaryContext();
}
// Set up embedding for any specified files. Do this before we load any
@@ -992,11 +992,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (!JSON)
continue;
- CI.getSummaryManager().ParseSummaryFromJSON(*JSON->getAsArray());
+ CI.getSummaryContext().ParseSummaryFromJSON(*JSON->getAsArray());
}
}
- CI.getSummaryManager().ReduceSummaries();
+ CI.getSummaryContext().ReduceSummaries();
}
}
@@ -1371,8 +1371,8 @@ void ASTFrontendAction::ExecuteAction() {
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();
- if(!CI.hasSummaryManager()) {
- CI.createSummaryManager();
+ if (!CI.hasSummaryContext()) {
+ CI.createSummaryContext();
}
CI.createSummaryConsumer();
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index bf8f73dc985db..9d5a593813bd3 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -85,7 +85,6 @@ add_clang_library(clangSema
SemaStmt.cpp
SemaStmtAsm.cpp
SemaStmtAttr.cpp
- SemaSummarizer.cpp
SemaSPIRV.cpp
SemaSYCL.cpp
SemaSwift.cpp
@@ -101,6 +100,7 @@ add_clang_library(clangSema
SemaX86.cpp
SummaryAttribute.cpp
SummaryConsumer.cpp
+ SummaryContext.cpp
TypeLocBuilder.cpp
DEPENDS
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 5b3f1a4dca36e..2870871876701 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -64,11 +64,11 @@
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
#include "clang/Sema/SemaSYCL.h"
-#include "clang/Sema/SemaSummarizer.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
+#include "clang/Sema/SummaryContext.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Sema/TypoCorrection.h"
@@ -250,12 +250,12 @@ const uint64_t Sema::MaximumAlignment;
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter,
- SummaryManager *SummaryManager,
- SummaryConsumer *SummaryConsumer)
+ SummaryContext *SummaryCtx, SummaryConsumer *SummaryConsumer)
: SemaBase(*this), CollectStats(false), TUKind(TUKind),
CurFPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp),
Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()),
SourceMgr(PP.getSourceManager()), APINotes(SourceMgr, LangOpts),
+ SummaryCtx(SummaryCtx), SummaryCnsmr(SummaryConsumer),
AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr),
LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr),
OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr),
@@ -266,8 +266,6 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
BPFPtr(std::make_unique<SemaBPF>(*this)),
CodeCompletionPtr(
std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
- SummarizerPtr(SummaryManager ? std::make_unique<SemaSummarizer>(*this, *SummaryManager, SummaryConsumer)
- : nullptr),
CUDAPtr(std::make_unique<SemaCUDA>(*this)),
DirectXPtr(std::make_unique<SemaDirectX>(*this)),
HLSLPtr(std::make_unique<SemaHLSL>(*this)),
@@ -309,6 +307,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr),
InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
ArgPackSubstIndex(std::nullopt), SatisfactionCache(Context) {
+ assert((!SummaryConsumer || SummaryCtx) &&
+ "summary consumer without a summary context");
assert(pp.TUKind == TUKind);
TUScope = nullptr;
@@ -1147,9 +1147,9 @@ void Sema::ActOnStartOfTranslationUnit() {
if (getLangOpts().CPlusPlusModules &&
getLangOpts().getCompilingModule() == LangOptions::CMK_HeaderUnit)
HandleStartOfHeaderUnit();
-
- if(SummarizerPtr)
- SummarizerPtr->ActOnStartOfSourceFile();
+
+ if (SummaryCnsmr)
+ SummaryCnsmr->ProcessStartOfSourceFile();
}
void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
@@ -1225,8 +1225,9 @@ void Sema::ActOnEndOfTranslationUnit() {
assert(DelayedDiagnostics.getCurrentPool() == nullptr
&& "reached end of translation unit with a pool attached?");
- if(SummarizerPtr)
- SummarizerPtr->ActOnEndOfSourceFile();
+ if (SummaryCnsmr)
+ SummaryCnsmr->ProcessEndOfSourceFile();
+
// If code completion is enabled, don't perform any end-of-translation-unit
// work.
if (PP.isCodeCompletionEnabled())
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 45f1523868f75..1aa7a1cf178bd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -55,9 +55,9 @@
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSYCL.h"
-#include "clang/Sema/SemaSummarizer.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaWasm.h"
+#include "clang/Sema/SummaryContext.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -16695,8 +16695,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD && !FD->isDeleted())
checkTypeSupport(FD->getType(), FD->getLocation(), FD);
- if (FD && SummarizerPtr && SummarizerPtr->TheSummaryConsumer)
- SummarizerPtr->SummarizeFunctionBody(FD);
+ if (SummaryCnsmr) {
+ SummaryCtx->SummarizeFunctionBody(FD);
+ SummaryCnsmr->ProcessFunctionSummary(*SummaryCtx->GetSummary(FD));
+ }
return dcl;
}
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Sema/SummaryAttribute.cpp
index 6f141dde68e52..86d422c16fa30 100644
--- a/clang/lib/Sema/SummaryAttribute.cpp
+++ b/clang/lib/Sema/SummaryAttribute.cpp
@@ -1,5 +1,5 @@
#include "clang/Sema/SummaryAttribute.h"
-#include "clang/Sema/SemaSummarizer.h"
+#include "clang/Sema/SummaryContext.h"
namespace clang {
void NoWriteGlobalAttr::Callback::run(
diff --git a/clang/lib/Sema/SummaryConsumer.cpp b/clang/lib/Sema/SummaryConsumer.cpp
index b10bc827f94ab..043873f236b93 100644
--- a/clang/lib/Sema/SummaryConsumer.cpp
+++ b/clang/lib/Sema/SummaryConsumer.cpp
@@ -1,5 +1,5 @@
#include "clang/Sema/SummaryConsumer.h"
-#include "clang/Sema/SemaSummarizer.h"
+#include "clang/Sema/SummaryContext.h"
namespace clang {
void JSONPrintingSummaryConsumer::ProcessFunctionSummary(const FunctionSummary &Summary) {
diff --git a/clang/lib/Sema/SemaSummarizer.cpp b/clang/lib/Sema/SummaryContext.cpp
similarity index 82%
rename from clang/lib/Sema/SemaSummarizer.cpp
rename to clang/lib/Sema/SummaryContext.cpp
index 3b056fc53f8c9..6b7207eedb5e5 100644
--- a/clang/lib/Sema/SemaSummarizer.cpp
+++ b/clang/lib/Sema/SummaryContext.cpp
@@ -1,4 +1,4 @@
-#include "clang/Sema/SemaSummarizer.h"
+#include "clang/Sema/SummaryContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Sema/SummaryAttribute.h"
@@ -46,7 +46,7 @@ FunctionSummary::FunctionSummary(
: ID(std::move(ID)), Attrs(std::move(FunctionAttrs)),
Calls(std::move(Calls)) {}
-SummaryManager::SummaryManager() {
+SummaryContext::SummaryContext() {
Attributes.emplace_back(std::make_unique<NoWriteGlobalAttr>());
for (auto &&Attr : Attributes) {
@@ -56,7 +56,7 @@ SummaryManager::SummaryManager() {
}
}
-void SummaryManager::CreateSummary(SmallVector<char> ID,
+void SummaryContext::CreateSummary(SmallVector<char> ID,
std::set<const SummaryAttribute *> Attrs,
std::set<SmallVector<char>> Calls) {
auto Summary = std::make_unique<FunctionSummary>(
@@ -66,12 +66,12 @@ void SummaryManager::CreateSummary(SmallVector<char> ID,
}
const FunctionSummary *
-SummaryManager::GetSummary(const FunctionDecl *FD) const {
+SummaryContext::GetSummary(const FunctionDecl *FD) const {
auto USR = GetUSR(FD);
return IDToSummary.count(USR) ? IDToSummary.at(USR) : nullptr;
}
-void SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
+void SummaryContext::SummarizeFunctionBody(const FunctionDecl *FD) {
std::set<const SummaryAttribute *> Attrs;
for (auto &&Attr : Attributes) {
@@ -82,7 +82,7 @@ void SummaryManager::SummarizeFunctionBody(const FunctionDecl *FD) {
CreateSummary(GetUSR(FD), std::move(Attrs), CallCollector().collect(FD));
}
-void SummaryManager::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
+void SummaryContext::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
for (auto it = Summary.begin(); it != Summary.end(); ++it) {
const llvm::json::Object *FunctionSummary = it->getAsObject();
@@ -108,7 +108,7 @@ void SummaryManager::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
}
}
-bool SummaryManager::ReduceFunctionSummary(FunctionSummary &Function) {
+bool SummaryContext::ReduceFunctionSummary(FunctionSummary &Function) {
bool changed = false;
for (auto &&call : Function.getCalls()) {
@@ -137,7 +137,7 @@ bool SummaryManager::ReduceFunctionSummary(FunctionSummary &Function) {
return changed;
}
-void SummaryManager::ReduceSummaries() {
+void SummaryContext::ReduceSummaries() {
bool changed = true;
while (changed) {
changed = false;
@@ -146,23 +146,4 @@ void SummaryManager::ReduceSummaries() {
changed |= ReduceFunctionSummary(*Function);
}
}
-
-void SemaSummarizer::ActOnStartOfSourceFile() {
- if(TheSummaryConsumer)
- TheSummaryConsumer->ProcessStartOfSourceFile();
-}
-
-void SemaSummarizer::ActOnEndOfSourceFile() {
- if(TheSummaryConsumer)
- TheSummaryConsumer->ProcessEndOfSourceFile();
-}
-
-void SemaSummarizer::SummarizeFunctionBody(const FunctionDecl *FD) {
- TheSummaryManager->SummarizeFunctionBody(FD);
-
- if(TheSummaryConsumer)
- TheSummaryConsumer->ProcessFunctionSummary(
- *TheSummaryManager->GetSummary(FD));
-}
-
} // namespace clang
>From d635e3221b8218337b0f80d54eae390d417bba5d Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 00:17:47 +0200
Subject: [PATCH 16/25] [clang][Summary] give the summary consumer a default
value to keep the diff smaller
---
clang/include/clang/Frontend/CompilerInstance.h | 2 +-
clang/lib/Frontend/ChainedIncludesSource.cpp | 2 +-
clang/lib/Frontend/FrontendActions.cpp | 2 +-
clang/lib/Testing/TestAST.cpp | 2 +-
clang/unittests/CodeGen/TestCompiler.h | 2 +-
clang/unittests/Frontend/CodeGenActionTest.cpp | 2 +-
clang/unittests/Sema/ExternalSemaSourceTest.cpp | 2 +-
clang/unittests/Sema/SemaLookupTest.cpp | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index b107f15af9563..7cb82e587cdfe 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -774,7 +774,7 @@ class CompilerInstance : public ModuleLoader {
/// Create the Sema object to be used for parsing.
void createSema(TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer,
- SummaryConsumer *SummaryConsumer);
+ SummaryConsumer *SummaryConsumer = nullptr);
/// Create the frontend timer and replace any existing one with it.
void createFrontendTimer();
diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp
index 437f5387375f7..95b0ed248d545 100644
--- a/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -142,7 +142,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(std::move(consumer));
- Clang->createSema(TU_Prefix, nullptr, nullptr);
+ Clang->createSema(TU_Prefix, nullptr);
if (firstInclude) {
Preprocessor &PP = Clang->getPreprocessor();
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 49f1420c75047..8c75e1a46da54 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -52,7 +52,7 @@ void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {
if (!CI.hasSema())
CI.createSema(Action.getTranslationUnitKind(),
- GetCodeCompletionConsumer(CI), nullptr);
+ GetCodeCompletionConsumer(CI));
}
} // namespace
diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp
index db0490689da53..748f59b856e83 100644
--- a/clang/lib/Testing/TestAST.cpp
+++ b/clang/lib/Testing/TestAST.cpp
@@ -69,7 +69,7 @@ void createMissingComponents(CompilerInstance &Clang) {
if (!Clang.hasASTContext())
Clang.createASTContext();
if (!Clang.hasSema())
- Clang.createSema(TU_Complete, /*CodeCompleteConsumer=*/nullptr, nullptr);
+ Clang.createSema(TU_Complete, /*CodeCompleteConsumer=*/nullptr);
}
} // namespace
diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h
index 760fa340c3d74..a6fec7fb0945d 100644
--- a/clang/unittests/CodeGen/TestCompiler.h
+++ b/clang/unittests/CodeGen/TestCompiler.h
@@ -69,7 +69,7 @@ struct TestCompiler {
compiler.setASTConsumer(std::move(Consumer));
- compiler.createSema(clang::TU_Prefix, nullptr, nullptr);
+ compiler.createSema(clang::TU_Prefix, nullptr);
clang::SourceManager &sm = compiler.getSourceManager();
sm.setMainFileID(sm.createFileID(
diff --git a/clang/unittests/Frontend/CodeGenActionTest.cpp b/clang/unittests/Frontend/CodeGenActionTest.cpp
index e958ea1993a4a..90818b72cd6e6 100644
--- a/clang/unittests/Frontend/CodeGenActionTest.cpp
+++ b/clang/unittests/Frontend/CodeGenActionTest.cpp
@@ -37,7 +37,7 @@ class NullCodeGenAction : public CodeGenAction {
if (!CI.hasPreprocessor())
return;
if (!CI.hasSema())
- CI.createSema(getTranslationUnitKind(), nullptr, nullptr);
+ CI.createSema(getTranslationUnitKind(), nullptr);
}
};
diff --git a/clang/unittests/Sema/ExternalSemaSourceTest.cpp b/clang/unittests/Sema/ExternalSemaSourceTest.cpp
index d223a7135ee84..2b271d4bf7825 100644
--- a/clang/unittests/Sema/ExternalSemaSourceTest.cpp
+++ b/clang/unittests/Sema/ExternalSemaSourceTest.cpp
@@ -194,7 +194,7 @@ class ExternalSemaSourceInstaller : public clang::ASTFrontendAction {
void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
ASSERT_FALSE(CI.hasSema());
- CI.createSema(getTranslationUnitKind(), nullptr, nullptr);
+ CI.createSema(getTranslationUnitKind(), nullptr);
ASSERT_TRUE(CI.hasDiagnostics());
DiagnosticsEngine &Diagnostics = CI.getDiagnostics();
DiagnosticConsumer *Client = Diagnostics.getClient();
diff --git a/clang/unittests/Sema/SemaLookupTest.cpp b/clang/unittests/Sema/SemaLookupTest.cpp
index 96c27945421f9..d97b571f6a37c 100644
--- a/clang/unittests/Sema/SemaLookupTest.cpp
+++ b/clang/unittests/Sema/SemaLookupTest.cpp
@@ -22,7 +22,7 @@ class LookupAction : public ASTFrontendAction {
void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
ASSERT_FALSE(CI.hasSema());
- CI.createSema(getTranslationUnitKind(), nullptr, nullptr);
+ CI.createSema(getTranslationUnitKind(), nullptr);
ASSERT_TRUE(CI.hasSema());
Sema &S = CI.getSema();
ParseAST(S);
>From 757c0d6d3250203cdb70dc559303f4d8007c4ed5 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 02:01:47 +0200
Subject: [PATCH 17/25] [clang][Summary] change frontend action and summary
interaction
---
clang/lib/Frontend/FrontendAction.cpp | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 2821327c6a824..8e66d6b8a6c27 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -895,10 +895,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
}
}
- if (!CI.hasSummaryContext()) {
- CI.createSummaryContext();
- }
-
// Set up embedding for any specified files. Do this before we load any
// source files, including the primary module map for the compilation.
for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
@@ -969,7 +965,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
}
}
- // FIXME: lookup dirs recursively
+ bool ProcessesSummaries = !CI.getFrontendOpts().SummaryDirPath.empty() ||
+ !CI.getFrontendOpts().SummaryFile.empty();
+ if (ProcessesSummaries && !CI.hasSummaryContext())
+ CI.createSummaryContext();
+
+ // FIXME: cleanup and lookup dirs recursively
if (!CI.getFrontendOpts().SummaryDirPath.empty()) {
FileManager &FileMgr = CI.getFileManager();
@@ -1371,12 +1372,10 @@ void ASTFrontendAction::ExecuteAction() {
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();
- if (!CI.hasSummaryContext()) {
- CI.createSummaryContext();
- }
- CI.createSummaryConsumer();
+ if (!CI.getFrontendOpts().SummaryFile.empty())
+ CI.createSummaryConsumer();
- // Use a code completion consumer?
+ // Use a code summary consumer?
SummaryConsumer *SummaryConsumer = nullptr;
if (CI.hasSummaryConsumer())
SummaryConsumer = &CI.getSummaryConsumer();
>From f511c22187178d637b184d15fb2effaf1c08dd19 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 02:21:29 +0200
Subject: [PATCH 18/25] [clang][Summary] explicitly flush summary
---
clang/include/clang/Sema/SummaryConsumer.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Sema/SummaryConsumer.h b/clang/include/clang/Sema/SummaryConsumer.h
index f8844ffb64e21..3d308b8464ef8 100644
--- a/clang/include/clang/Sema/SummaryConsumer.h
+++ b/clang/include/clang/Sema/SummaryConsumer.h
@@ -35,7 +35,10 @@ class JSONPrintingSummaryConsumer : public PrintingSummaryConsumer {
void ProcessStartOfSourceFile() override { JOS.arrayBegin(); };
void ProcessFunctionSummary(const FunctionSummary &) override;
- void ProcessEndOfSourceFile() override { JOS.arrayEnd(); };
+ void ProcessEndOfSourceFile() override {
+ JOS.arrayEnd();
+ JOS.flush();
+ };
};
} // namespace clang
>From 6964f2c54db47c9ab748af19a55f4af761ed786b Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 03:00:33 +0200
Subject: [PATCH 19/25] [clang][analyzer][Summary] pass summaries to the
analyzer
---
.../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 11 +++++++----
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 5 +++--
.../lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 7 ++++++-
3 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index b8a4dcbc727a6..5e3b338be6e68 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -21,18 +21,19 @@
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/Sema/SummaryContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
#include "llvm/ADT/ArrayRef.h"
#include <cassert>
@@ -178,10 +179,12 @@ class ExprEngine {
/// The flag, which specifies the mode of inlining for the engine.
InliningModes HowToInline;
+ const SummaryContext *SummaryCtx;
+
public:
ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr,
- SetOfConstDecls *VisitedCalleesIn,
- FunctionSummariesTy *FS, InliningModes HowToInlineIn);
+ SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS,
+ InliningModes HowToInlineIn, const SummaryContext *SummaryCtx);
virtual ~ExprEngine() = default;
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 1afd4b52eb354..c4836fb9d0aac 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -223,7 +223,8 @@ static const char* TagProviderName = "ExprEngine";
ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn,
- FunctionSummariesTy *FS, InliningModes HowToInlineIn)
+ FunctionSummariesTy *FS, InliningModes HowToInlineIn,
+ const SummaryContext *SummaryCtx)
: CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),
AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),
@@ -232,7 +233,7 @@ ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
SymMgr(StateMgr.getSymbolManager()), MRMgr(StateMgr.getRegionManager()),
svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
BR(mgr, *this), VisitedCallees(VisitedCalleesIn),
- HowToInline(HowToInlineIn) {
+ HowToInline(HowToInlineIn), SummaryCtx(SummaryCtx) {
unsigned TrimInterval = mgr.options.GraphTrimInterval;
if (TrimInterval != 0) {
// Enable eager node reclamation when constructing the ExplodedGraph.
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 491aa93c96e49..b87014e4dcd00 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -93,6 +93,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,
ArrayRef<std::string> Plugins;
std::unique_ptr<CodeInjector> Injector;
cross_tu::CrossTranslationUnitContext CTU;
+ const SummaryContext *SummaryCtx;
/// Stores the declarations from the local translation unit.
/// Note, we pre-compute the local declarations at parse time as an
@@ -152,6 +153,9 @@ class AnalysisConsumer : public AnalysisASTConsumer,
if (Opts.ShouldDisplayMacroExpansions)
MacroExpansions.registerForPreprocessor(PP);
+ if (CI.hasSummaryContext())
+ SummaryCtx = &CI.getSummaryContext();
+
// Visitor options.
ShouldWalkTypesOfTypeLocs = false;
}
@@ -761,7 +765,8 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
return;
- ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
+ ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode,
+ SummaryCtx);
// Execute the worklist algorithm.
llvm::TimeRecord ExprEngineStartTime;
>From 81b039f8abc76f83583a809bc9e363122062305f Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 03:47:15 +0200
Subject: [PATCH 20/25] [analyzer] don't invalidate global regions if a
function doesn't write them
---
clang/include/clang/Sema/SummaryContext.h | 1 +
.../Core/PathSensitive/ExprEngine.h | 2 ++
clang/lib/Sema/SummaryContext.cpp | 5 +++++
clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 19 +++++++++++++++----
4 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Sema/SummaryContext.h b/clang/include/clang/Sema/SummaryContext.h
index 67b1162d61763..2675a85583d69 100644
--- a/clang/include/clang/Sema/SummaryContext.h
+++ b/clang/include/clang/Sema/SummaryContext.h
@@ -42,6 +42,7 @@ class SummaryContext {
public:
SummaryContext();
+ const SummaryAttribute *GetAttribute(SummaryAttributeKind kind) const;
const FunctionSummary *GetSummary(const FunctionDecl *FD) const;
void SummarizeFunctionBody(const FunctionDecl *FD);
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 5e3b338be6e68..68a8004a8ae26 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -217,6 +217,8 @@ class ExprEngine {
return &CTU;
}
+ const SummaryContext *getSummaryCtx() { return SummaryCtx; }
+
const NodeBuilderContext &getBuilderContext() {
assert(currBldrCtx);
return *currBldrCtx;
diff --git a/clang/lib/Sema/SummaryContext.cpp b/clang/lib/Sema/SummaryContext.cpp
index 6b7207eedb5e5..50771d2da0963 100644
--- a/clang/lib/Sema/SummaryContext.cpp
+++ b/clang/lib/Sema/SummaryContext.cpp
@@ -65,6 +65,11 @@ void SummaryContext::CreateSummary(SmallVector<char> ID,
IDToSummary[SummaryPtr->getID()] = SummaryPtr;
}
+const SummaryAttribute *
+SummaryContext::GetAttribute(SummaryAttributeKind kind) const {
+ return KindToAttribute.at(kind);
+}
+
const FunctionSummary *
SummaryContext::GetSummary(const FunctionDecl *FD) const {
auto USR = GetUSR(FD);
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 583315f4f3a90..aa9a236ead9a3 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -277,13 +277,24 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
ValuesToInvalidate.push_back(loc::MemRegionVal(TVR));
}
+ bool ShouldPreserveGlobals = false;
+ const SummaryContext *SummaryCtx =
+ State->getStateManager().getOwningEngine().getSummaryCtx();
+ if (SummaryCtx) {
+ const auto *Summary =
+ SummaryCtx->GetSummary(llvm::dyn_cast<FunctionDecl>(getDecl()));
+ ShouldPreserveGlobals =
+ Summary && Summary->getAttributes().count(
+ SummaryCtx->GetAttribute(NO_WRITE_GLOBAL));
+ }
+
// Invalidate designated regions using the batch invalidation API.
// NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
// global variables.
- return Result->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
- BlockCount, getLocationContext(),
- /*CausedByPointerEscape*/ true,
- /*Symbols=*/nullptr, this, &ETraits);
+ return Result->invalidateRegions(
+ ValuesToInvalidate, getCFGElementRef(), BlockCount, getLocationContext(),
+ /*CausedByPointerEscape*/ true,
+ /*Symbols=*/nullptr, ShouldPreserveGlobals ? nullptr : this, &ETraits);
}
ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
>From 016dcdb4707a0b8369ca0ef6a0fe788d1fb2f78f Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 14:50:08 +0200
Subject: [PATCH 21/25] [clang][Summary] refactor summary attributes
---
clang/include/clang/Sema/SummaryAttribute.h | 36 +++++++++++++--------
clang/include/clang/Sema/SummaryContext.h | 30 ++++++++++-------
clang/lib/Sema/SummaryContext.cpp | 35 +++++++++-----------
clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 9 +++---
4 files changed, 60 insertions(+), 50 deletions(-)
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index 0014a9878bacd..b3b8d452dfd18 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -3,37 +3,40 @@
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include <string>
namespace clang {
-enum SummaryAttributeKind {
+enum SummaryAttrKind {
NO_WRITE_GLOBAL,
};
class FunctionSummary;
+class SummaryContext;
-class SummaryAttribute {
- const SummaryAttributeKind Kind;
- std::string_view Serialzed;
+class SummaryAttr {
+ const SummaryAttrKind Kind;
+ const char *Spelling;
+
+protected:
+ SummaryAttr(SummaryAttrKind Kind, const char *Spelling)
+ : Kind(Kind), Spelling(Spelling){};
public:
- SummaryAttribute(SummaryAttributeKind Attr, const char *Str)
- : Kind(Attr), Serialzed(Str) {}
- virtual ~SummaryAttribute() = default;
+ virtual ~SummaryAttr() = default;
- SummaryAttributeKind getKind() { return Kind; }
+ SummaryAttrKind getKind() const { return Kind; }
+ const char *getSpelling() const { return Spelling; }
virtual bool infer(const FunctionDecl *FD) const = 0;
virtual bool merge(const FunctionSummary &Caller,
const FunctionSummary &Callee) const = 0;
- virtual std::string serialize() const { return std::string(Serialzed); };
+ virtual std::string serialize() const { return std::string(Spelling); };
virtual bool parse(std::string_view input) const {
- return input == Serialzed;
+ return input == Spelling;
};
};
-class NoWriteGlobalAttr : public SummaryAttribute {
+class NoWriteGlobalAttr : public SummaryAttr {
class Callback : public ast_matchers::MatchFinder::MatchCallback {
public:
bool WriteGlobal = false;
@@ -42,12 +45,17 @@ class NoWriteGlobalAttr : public SummaryAttribute {
run(const ast_matchers::MatchFinder::MatchResult &Result) override final;
};
-public:
- NoWriteGlobalAttr() : SummaryAttribute(NO_WRITE_GLOBAL, "no_write_global") {}
+ NoWriteGlobalAttr() : SummaryAttr(NO_WRITE_GLOBAL, "no_write_global") {}
+public:
bool infer(const FunctionDecl *FD) const override final;
bool merge(const FunctionSummary &Caller,
const FunctionSummary &Callee) const override final;
+
+ static bool classof(const SummaryAttr *A) {
+ return A->getKind() == NO_WRITE_GLOBAL;
+ }
+ friend class SummaryContext;
};
} // namespace clang
diff --git a/clang/include/clang/Sema/SummaryContext.h b/clang/include/clang/Sema/SummaryContext.h
index 2675a85583d69..c142484b131dc 100644
--- a/clang/include/clang/Sema/SummaryContext.h
+++ b/clang/include/clang/Sema/SummaryContext.h
@@ -8,21 +8,27 @@
namespace clang {
class FunctionSummary {
SmallVector<char> ID;
- std::set<const SummaryAttribute *> Attrs;
+ std::set<const SummaryAttr *> Attrs;
std::set<SmallVector<char>> Calls;
public:
- FunctionSummary(SmallVector<char> ID,
- std::set<const SummaryAttribute *> Attrs,
+ FunctionSummary(SmallVector<char> ID, std::set<const SummaryAttr *> Attrs,
std::set<SmallVector<char>> Calls);
SmallVector<char> getID() const { return ID; }
- const std::set<const SummaryAttribute *> &getAttributes() const {
- return Attrs;
- }
+ const std::set<const SummaryAttr *> &getAttributes() const { return Attrs; }
const std::set<SmallVector<char>> &getCalls() const { return Calls; }
- void replaceAttributes(std::set<const SummaryAttribute *> Attrs) {
+ template <typename T> bool hasAttribute() const {
+ for (auto &&attr : Attrs) {
+ if (llvm::isa<T>(attr))
+ return true;
+ }
+
+ return false;
+ }
+
+ void replaceAttributes(std::set<const SummaryAttr *> Attrs) {
this->Attrs = std::move(Attrs);
}
};
@@ -31,18 +37,18 @@ class SummaryContext {
std::map<SmallVector<char>, const FunctionSummary *> IDToSummary;
std::vector<std::unique_ptr<FunctionSummary>> FunctionSummaries;
- std::map<SummaryAttributeKind, const SummaryAttribute *> KindToAttribute;
- std::vector<std::unique_ptr<SummaryAttribute>> Attributes;
+ std::map<SummaryAttrKind, const SummaryAttr *> KindToAttribute;
+ std::vector<std::unique_ptr<SummaryAttr>> Attributes;
- void CreateSummary(SmallVector<char> ID,
- std::set<const SummaryAttribute *> Attrs,
+ void CreateSummary(SmallVector<char> ID, std::set<const SummaryAttr *> Attrs,
std::set<SmallVector<char>> Calls);
bool ReduceFunctionSummary(FunctionSummary &FunctionSummary);
+ template <typename T> void registerAttr();
+
public:
SummaryContext();
- const SummaryAttribute *GetAttribute(SummaryAttributeKind kind) const;
const FunctionSummary *GetSummary(const FunctionDecl *FD) const;
void SummarizeFunctionBody(const FunctionDecl *FD);
diff --git a/clang/lib/Sema/SummaryContext.cpp b/clang/lib/Sema/SummaryContext.cpp
index 50771d2da0963..b4e49451030c0 100644
--- a/clang/lib/Sema/SummaryContext.cpp
+++ b/clang/lib/Sema/SummaryContext.cpp
@@ -40,24 +40,26 @@ class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
};
} // namespace
-FunctionSummary::FunctionSummary(
- SmallVector<char> ID, std::set<const SummaryAttribute *> FunctionAttrs,
- std::set<SmallVector<char>> Calls)
+FunctionSummary::FunctionSummary(SmallVector<char> ID,
+ std::set<const SummaryAttr *> FunctionAttrs,
+ std::set<SmallVector<char>> Calls)
: ID(std::move(ID)), Attrs(std::move(FunctionAttrs)),
Calls(std::move(Calls)) {}
-SummaryContext::SummaryContext() {
- Attributes.emplace_back(std::make_unique<NoWriteGlobalAttr>());
+template <typename T> void SummaryContext::registerAttr() {
+ std::unique_ptr<T> attr(new T());
+ SummaryAttrKind Kind = attr->getKind();
- for (auto &&Attr : Attributes) {
- assert(KindToAttribute.count(Attr->getKind()) == 0 &&
- "Attr already registered");
- KindToAttribute[Attr->getKind()] = Attr.get();
- }
+ if (KindToAttribute.count(Kind))
+ return;
+
+ KindToAttribute[Kind] = Attributes.emplace_back(std::move(attr)).get();
}
+SummaryContext::SummaryContext() { registerAttr<NoWriteGlobalAttr>(); }
+
void SummaryContext::CreateSummary(SmallVector<char> ID,
- std::set<const SummaryAttribute *> Attrs,
+ std::set<const SummaryAttr *> Attrs,
std::set<SmallVector<char>> Calls) {
auto Summary = std::make_unique<FunctionSummary>(
std::move(ID), std::move(Attrs), std::move(Calls));
@@ -65,11 +67,6 @@ void SummaryContext::CreateSummary(SmallVector<char> ID,
IDToSummary[SummaryPtr->getID()] = SummaryPtr;
}
-const SummaryAttribute *
-SummaryContext::GetAttribute(SummaryAttributeKind kind) const {
- return KindToAttribute.at(kind);
-}
-
const FunctionSummary *
SummaryContext::GetSummary(const FunctionDecl *FD) const {
auto USR = GetUSR(FD);
@@ -77,7 +74,7 @@ SummaryContext::GetSummary(const FunctionDecl *FD) const {
}
void SummaryContext::SummarizeFunctionBody(const FunctionDecl *FD) {
- std::set<const SummaryAttribute *> Attrs;
+ std::set<const SummaryAttr *> Attrs;
for (auto &&Attr : Attributes) {
if (Attr->infer(FD))
@@ -92,7 +89,7 @@ void SummaryContext::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
const llvm::json::Object *FunctionSummary = it->getAsObject();
SmallString<128> ID(*FunctionSummary->getString("id"));
- std::set<const SummaryAttribute *> FunctionAttrs;
+ std::set<const SummaryAttr *> FunctionAttrs;
const llvm::json::Array *FunctionAttributes =
FunctionSummary->getObject("attrs")->getArray("function");
for(auto attrIt = FunctionAttributes->begin(); attrIt != FunctionAttributes->end(); ++attrIt) {
@@ -117,7 +114,7 @@ bool SummaryContext::ReduceFunctionSummary(FunctionSummary &Function) {
bool changed = false;
for (auto &&call : Function.getCalls()) {
- std::set<const SummaryAttribute *> reducedAttrs;
+ std::set<const SummaryAttr *> reducedAttrs;
// If we don't have a summary about a called function, we forget
// everything about the current one as well.
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index aa9a236ead9a3..a4885f62be627 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -280,12 +280,11 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
bool ShouldPreserveGlobals = false;
const SummaryContext *SummaryCtx =
State->getStateManager().getOwningEngine().getSummaryCtx();
- if (SummaryCtx) {
- const auto *Summary =
- SummaryCtx->GetSummary(llvm::dyn_cast<FunctionDecl>(getDecl()));
+ const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(getDecl());
+ if (SummaryCtx && FD) {
+ const auto *Summary = SummaryCtx->GetSummary(FD);
ShouldPreserveGlobals =
- Summary && Summary->getAttributes().count(
- SummaryCtx->GetAttribute(NO_WRITE_GLOBAL));
+ Summary && Summary->hasAttribute<NoWriteGlobalAttr>();
}
// Invalidate designated regions using the batch invalidation API.
>From 115584471eb25cd5211d8bda0854c17b2bf3eee4 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 14:57:16 +0200
Subject: [PATCH 22/25] [Summary] move the ast matcher callback out of the
attribute declaration
---
clang/include/clang/Sema/SummaryAttribute.h | 8 -------
clang/lib/Sema/SummaryAttribute.cpp | 25 ++++++++++++---------
2 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Sema/SummaryAttribute.h
index b3b8d452dfd18..27ceede1e4486 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Sema/SummaryAttribute.h
@@ -37,14 +37,6 @@ class SummaryAttr {
};
class NoWriteGlobalAttr : public SummaryAttr {
- class Callback : public ast_matchers::MatchFinder::MatchCallback {
- public:
- bool WriteGlobal = false;
-
- void
- run(const ast_matchers::MatchFinder::MatchResult &Result) override final;
- };
-
NoWriteGlobalAttr() : SummaryAttr(NO_WRITE_GLOBAL, "no_write_global") {}
public:
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Sema/SummaryAttribute.cpp
index 86d422c16fa30..6bb6b938184de 100644
--- a/clang/lib/Sema/SummaryAttribute.cpp
+++ b/clang/lib/Sema/SummaryAttribute.cpp
@@ -2,19 +2,24 @@
#include "clang/Sema/SummaryContext.h"
namespace clang {
-void NoWriteGlobalAttr::Callback::run(
- const ast_matchers::MatchFinder::MatchResult &Result) {
- const auto *Assignment = Result.Nodes.getNodeAs<BinaryOperator>("assignment");
- if (!Assignment)
- return;
-
- WriteGlobal = true;
-}
-
bool NoWriteGlobalAttr::infer(const FunctionDecl *FD) const {
using namespace ast_matchers;
MatchFinder Finder;
- Callback CB;
+
+ class Callback : public ast_matchers::MatchFinder::MatchCallback {
+ public:
+ bool WriteGlobal = false;
+
+ void
+ run(const ast_matchers::MatchFinder::MatchResult &Result) override final {
+ const auto *Assignment =
+ Result.Nodes.getNodeAs<BinaryOperator>("assignment");
+ if (!Assignment)
+ return;
+
+ WriteGlobal = true;
+ }
+ } CB;
Finder.addMatcher(
functionDecl(forEachDescendant(
>From 49937a6570ff49042b72a286896647dcdd926cb9 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 15:07:56 +0200
Subject: [PATCH 23/25] [clang] don't crash if there is no summary consumer
---
clang/lib/Frontend/CompilerInstance.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 448d45b0f49db..9682a01fab226 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -764,7 +764,8 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer,
SummaryConsumer *SummaryConsumer) {
TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
- TUKind, CompletionConsumer, &getSummaryContext(),
+ TUKind, CompletionConsumer,
+ hasSummaryContext() ? &getSummaryContext() : nullptr,
SummaryConsumer));
// Set up API notes.
>From 2499ff2e7f92537a5617f7c91a6dfb14e0c2e179 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 15:50:54 +0200
Subject: [PATCH 24/25] [Driver][Summary] implement emitting summary next to
the object file
---
clang/lib/Driver/ToolChains/Clang.cpp | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 48b19615ab08f..f61bb983900f4 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5473,7 +5473,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.getLastArg(options::OPT_summaries_dir_EQ))
Args.AddLastArg(CmdArgs, options::OPT_summaries_dir_EQ);
- // FIXME: This needs to be cleaned up and needs proper error handling as well.
if (const Arg *A = Args.getLastArg(options::OPT_emit_summaries_EQ)) {
llvm::SmallString<10> input;
for (const auto &II : Inputs) {
@@ -5485,14 +5484,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
if (!input.empty()) {
- if (A->containsValue("cwd")) {
- llvm::SmallString<10> filename = llvm::sys::path::filename(input);
- llvm::sys::path::replace_extension(filename, "json");
+ Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
+ StringRef filename = llvm::sys::path::filename(input);
+ llvm::SmallString<10> summaryFile;
+
+ if (A->containsValue("cwd") || !FinalOutput) {
+ summaryFile = filename;
+ } else if (A->containsValue("obj") && FinalOutput) {
+ summaryFile = llvm::sys::path::parent_path(FinalOutput->getValue());
+ llvm::sys::path::append(summaryFile, filename);
+ }
+ if (!summaryFile.empty()) {
+ llvm::sys::path::replace_extension(summaryFile, "json");
CmdArgs.push_back(
- Args.MakeArgString(Twine("-summary-file=") + filename));
- } else if (A->containsValue("obj")) {
- // FIXME: implement
+ Args.MakeArgString(Twine("-summary-file=") + summaryFile));
}
}
}
>From d44d9d051426b72ebf9f2b0de1e7b11ef2ae5635 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Sat, 14 Jun 2025 16:23:29 +0200
Subject: [PATCH 25/25] [Summary] move summary related logic into a separate
library
---
clang/include/clang/Frontend/CompilerInstance.h | 2 +-
.../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 2 +-
.../clang/{Sema => Summary}/SummaryAttribute.h | 6 +++---
.../clang/{Sema => Summary}/SummaryConsumer.h | 8 ++++----
.../clang/{Sema => Summary}/SummaryContext.h | 10 +++++-----
clang/lib/CMakeLists.txt | 1 +
clang/lib/Frontend/CompilerInstance.cpp | 2 +-
clang/lib/Frontend/FrontendAction.cpp | 2 +-
clang/lib/Sema/CMakeLists.txt | 4 +---
clang/lib/Sema/Sema.cpp | 2 +-
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Summary/CMakeLists.txt | 14 ++++++++++++++
clang/lib/{Sema => Summary}/SummaryAttribute.cpp | 4 ++--
clang/lib/{Sema => Summary}/SummaryConsumer.cpp | 7 ++++---
clang/lib/{Sema => Summary}/SummaryContext.cpp | 12 +++++++-----
15 files changed, 47 insertions(+), 31 deletions(-)
rename clang/include/clang/{Sema => Summary}/SummaryAttribute.h (90%)
rename clang/include/clang/{Sema => Summary}/SummaryConsumer.h (87%)
rename clang/include/clang/{Sema => Summary}/SummaryContext.h (87%)
create mode 100644 clang/lib/Summary/CMakeLists.txt
rename clang/lib/{Sema => Summary}/SummaryAttribute.cpp (92%)
rename clang/lib/{Sema => Summary}/SummaryConsumer.cpp (74%)
rename clang/lib/{Sema => Summary}/SummaryContext.cpp (92%)
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 7cb82e587cdfe..4a15fbf042cce 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -19,7 +19,7 @@
#include "clang/Lex/DependencyDirectivesScanner.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleLoader.h"
-#include "clang/Sema/SummaryContext.h"
+#include "clang/Summary/SummaryContext.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 68a8004a8ae26..e349dcbbfb9c4 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -21,7 +21,6 @@
#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Sema/SummaryContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -35,6 +34,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include "clang/Summary/SummaryContext.h"
#include "llvm/ADT/ArrayRef.h"
#include <cassert>
#include <optional>
diff --git a/clang/include/clang/Sema/SummaryAttribute.h b/clang/include/clang/Summary/SummaryAttribute.h
similarity index 90%
rename from clang/include/clang/Sema/SummaryAttribute.h
rename to clang/include/clang/Summary/SummaryAttribute.h
index 27ceede1e4486..46de04a8169eb 100644
--- a/clang/include/clang/Sema/SummaryAttribute.h
+++ b/clang/include/clang/Summary/SummaryAttribute.h
@@ -1,5 +1,5 @@
-#ifndef LLVM_CLANG_SEMA_SEMASUMMARYATTRIBUTE_H
-#define LLVM_CLANG_SEMA_SEMASUMMARYATTRIBUTE_H
+#ifndef LLVM_CLANG_SUMMARY_SUMMARYATTRIBUTE_H
+#define LLVM_CLANG_SUMMARY_SUMMARYATTRIBUTE_H
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -51,4 +51,4 @@ class NoWriteGlobalAttr : public SummaryAttr {
};
} // namespace clang
-#endif // LLVM_CLANG_SEMA_SEMASUMMARYATTRIBUTEH
+#endif // LLVM_CLANG_SUMMARY_SUMMARYATTRIBUTEH
diff --git a/clang/include/clang/Sema/SummaryConsumer.h b/clang/include/clang/Summary/SummaryConsumer.h
similarity index 87%
rename from clang/include/clang/Sema/SummaryConsumer.h
rename to clang/include/clang/Summary/SummaryConsumer.h
index 3d308b8464ef8..f0b14b3db7c79 100644
--- a/clang/include/clang/Sema/SummaryConsumer.h
+++ b/clang/include/clang/Summary/SummaryConsumer.h
@@ -1,5 +1,5 @@
-#ifndef LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
-#define LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
+#ifndef LLVM_CLANG_SUMMARY_SUMMARYCONSUMER_H
+#define LLVM_CLANG_SUMMARY_SUMMARYCONSUMER_H
#include "clang/Basic/LLVM.h"
#include "llvm/Support/JSON.h"
@@ -27,7 +27,7 @@ class PrintingSummaryConsumer : public SummaryConsumer {
};
class JSONPrintingSummaryConsumer : public PrintingSummaryConsumer {
- llvm::json::OStream JOS;
+ llvm::json::OStream JOS;
public:
JSONPrintingSummaryConsumer(const SummaryContext &SummaryCtx, raw_ostream &OS)
@@ -42,4 +42,4 @@ class JSONPrintingSummaryConsumer : public PrintingSummaryConsumer {
};
} // namespace clang
-#endif // LLVM_CLANG_SEMA_SUMMARYCONSUMER_H
+#endif // LLVM_CLANG_SUMMARY_SUMMARYCONSUMER_H
diff --git a/clang/include/clang/Sema/SummaryContext.h b/clang/include/clang/Summary/SummaryContext.h
similarity index 87%
rename from clang/include/clang/Sema/SummaryContext.h
rename to clang/include/clang/Summary/SummaryContext.h
index c142484b131dc..194f89a4b4007 100644
--- a/clang/include/clang/Sema/SummaryContext.h
+++ b/clang/include/clang/Summary/SummaryContext.h
@@ -1,8 +1,8 @@
-#ifndef LLVM_CLANG_SEMA_SEMASUMMARYCONTEXT_H
-#define LLVM_CLANG_SEMA_SEMASUMMARYCONTEXT_H
+#ifndef LLVM_CLANG_SUMMARY_SUMMARYCONTEXT_H
+#define LLVM_CLANG_SUMMARY_SUMMARYCONTEXT_H
-#include "clang/Sema/SummaryAttribute.h"
-#include "clang/Sema/SummaryConsumer.h"
+#include "clang/Summary/SummaryAttribute.h"
+#include "clang/Summary/SummaryConsumer.h"
#include <set>
namespace clang {
@@ -57,4 +57,4 @@ class SummaryContext {
};
} // namespace clang
-#endif // LLVM_CLANG_SEMA_SEMASUMMARYCONTEXTH
+#endif // LLVM_CLANG_SUMMARY_SUMMARYCONTEXTH
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index 4f2218b583e41..96f0ccd7d1c88 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -9,6 +9,7 @@ add_subdirectory(CrossTU)
add_subdirectory(Sema)
add_subdirectory(CodeGen)
add_subdirectory(Analysis)
+add_subdirectory(Summary)
add_subdirectory(Edit)
add_subdirectory(ExtractAPI)
add_subdirectory(Rewrite)
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 9682a01fab226..c75a4056e2847 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -37,11 +37,11 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
-#include "clang/Sema/SummaryConsumer.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
+#include "clang/Summary/SummaryConsumer.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 8e66d6b8a6c27..966c514e04a96 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -35,10 +35,10 @@
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/HLSLExternalSemaSource.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
-#include "clang/Sema/SummaryContext.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
+#include "clang/Summary/SummaryContext.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/BuryPointer.h"
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 9d5a593813bd3..940456e15f9f8 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -98,9 +98,6 @@ add_clang_library(clangSema
SemaType.cpp
SemaWasm.cpp
SemaX86.cpp
- SummaryAttribute.cpp
- SummaryConsumer.cpp
- SummaryContext.cpp
TypeLocBuilder.cpp
DEPENDS
@@ -117,4 +114,5 @@ add_clang_library(clangSema
clangEdit
clangLex
clangSupport
+ clangSummary
)
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 2870871876701..5c5fb005a3172 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -68,10 +68,10 @@
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
-#include "clang/Sema/SummaryContext.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Sema/TypoCorrection.h"
+#include "clang/Summary/SummaryContext.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1aa7a1cf178bd..740fccc3aad33 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -57,8 +57,8 @@
#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaWasm.h"
-#include "clang/Sema/SummaryContext.h"
#include "clang/Sema/Template.h"
+#include "clang/Summary/SummaryContext.h"
#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
diff --git a/clang/lib/Summary/CMakeLists.txt b/clang/lib/Summary/CMakeLists.txt
new file mode 100644
index 0000000000000..269d09cb10d16
--- /dev/null
+++ b/clang/lib/Summary/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ Support
+ )
+
+add_clang_library(clangSummary
+ SummaryAttribute.cpp
+ SummaryConsumer.cpp
+ SummaryContext.cpp
+
+ LINK_LIBS
+ clangAST
+ clangSupport
+ )
diff --git a/clang/lib/Sema/SummaryAttribute.cpp b/clang/lib/Summary/SummaryAttribute.cpp
similarity index 92%
rename from clang/lib/Sema/SummaryAttribute.cpp
rename to clang/lib/Summary/SummaryAttribute.cpp
index 6bb6b938184de..c9a69140c5494 100644
--- a/clang/lib/Sema/SummaryAttribute.cpp
+++ b/clang/lib/Summary/SummaryAttribute.cpp
@@ -1,5 +1,5 @@
-#include "clang/Sema/SummaryAttribute.h"
-#include "clang/Sema/SummaryContext.h"
+#include "clang/Summary/SummaryAttribute.h"
+#include "clang/Summary/SummaryContext.h"
namespace clang {
bool NoWriteGlobalAttr::infer(const FunctionDecl *FD) const {
diff --git a/clang/lib/Sema/SummaryConsumer.cpp b/clang/lib/Summary/SummaryConsumer.cpp
similarity index 74%
rename from clang/lib/Sema/SummaryConsumer.cpp
rename to clang/lib/Summary/SummaryConsumer.cpp
index 043873f236b93..716248ffc9e24 100644
--- a/clang/lib/Sema/SummaryConsumer.cpp
+++ b/clang/lib/Summary/SummaryConsumer.cpp
@@ -1,8 +1,9 @@
-#include "clang/Sema/SummaryConsumer.h"
-#include "clang/Sema/SummaryContext.h"
+#include "clang/Summary/SummaryConsumer.h"
+#include "clang/Summary/SummaryContext.h"
namespace clang {
-void JSONPrintingSummaryConsumer::ProcessFunctionSummary(const FunctionSummary &Summary) {
+void JSONPrintingSummaryConsumer::ProcessFunctionSummary(
+ const FunctionSummary &Summary) {
JOS.object([&] {
JOS.attribute("id", llvm::json::Value(Summary.getID()));
JOS.attributeObject("attrs", [&] {
diff --git a/clang/lib/Sema/SummaryContext.cpp b/clang/lib/Summary/SummaryContext.cpp
similarity index 92%
rename from clang/lib/Sema/SummaryContext.cpp
rename to clang/lib/Summary/SummaryContext.cpp
index b4e49451030c0..6cb4b7a716200 100644
--- a/clang/lib/Sema/SummaryContext.cpp
+++ b/clang/lib/Summary/SummaryContext.cpp
@@ -1,8 +1,8 @@
-#include "clang/Sema/SummaryContext.h"
+#include "clang/Summary/SummaryContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Index/USRGeneration.h"
-#include "clang/Sema/SummaryAttribute.h"
-#include "clang/Sema/SummaryConsumer.h"
+#include "clang/Summary/SummaryAttribute.h"
+#include "clang/Summary/SummaryConsumer.h"
#include <set>
namespace clang {
@@ -92,7 +92,8 @@ void SummaryContext::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
std::set<const SummaryAttr *> FunctionAttrs;
const llvm::json::Array *FunctionAttributes =
FunctionSummary->getObject("attrs")->getArray("function");
- for(auto attrIt = FunctionAttributes->begin(); attrIt != FunctionAttributes->end(); ++attrIt) {
+ for (auto attrIt = FunctionAttributes->begin();
+ attrIt != FunctionAttributes->end(); ++attrIt) {
for (auto &&Attr : Attributes) {
if (Attr->parse(*attrIt->getAsString()))
FunctionAttrs.emplace(Attr.get());
@@ -101,7 +102,8 @@ void SummaryContext::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
std::set<SmallVector<char>> Calls;
const llvm::json::Array *CallEntries = FunctionSummary->getArray("calls");
- for(auto callIt = CallEntries->begin(); callIt != CallEntries->end(); ++callIt) {
+ for (auto callIt = CallEntries->begin(); callIt != CallEntries->end();
+ ++callIt) {
auto *Obj = callIt->getAsObject();
Calls.emplace(SmallString<128>(*Obj->getString("id")));
}
More information about the cfe-commits
mailing list