[clang] [clang][deps] Optimize command line generation (PR #65412)
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 5 13:29:31 PDT 2023
https://github.com/jansvoboda11 created https://github.com/llvm/llvm-project/pull/65412:
This PR speeds up the dependency scanner by optimizing how it generates command lines for discovered modular dependencies. This now happens lazily based on copy-on-write `CompilerInvocation` objects.
>From 968fc04bc9bdcc33bb3f9401073343d2f69369f3 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Fri, 1 Sep 2023 15:07:23 -0700
Subject: [PATCH 1/5] [llvm][adt] Implement `IntrusiveRefCntPtr::unique()`
---
llvm/include/llvm/ADT/IntrusiveRefCntPtr.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h b/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
index e41eb0639ce30e..5a7f93f4a99363 100644
--- a/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
+++ b/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -93,6 +93,8 @@ template <class Derived> class RefCountedBase {
#endif
public:
+ bool Unique() const { return RefCount == 1; }
+
void Retain() const { ++RefCount; }
void Release() const {
@@ -124,6 +126,8 @@ template <class Derived> class ThreadSafeRefCountedBase {
#endif
public:
+ bool Unique() const { return RefCount.load() == 1; }
+
void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); }
void Release() const {
@@ -155,6 +159,7 @@ template <class Derived> class ThreadSafeRefCountedBase {
/// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any
/// functions on Foo itself, because Foo would be an incomplete type.
template <typename T> struct IntrusiveRefCntPtrInfo {
+ static bool unique(T *obj) { return obj->Unique(); }
static void retain(T *obj) { obj->Retain(); }
static void release(T *obj) { obj->Release(); }
};
@@ -213,6 +218,8 @@ template <typename T> class IntrusiveRefCntPtr {
void resetWithoutRelease() { Obj = nullptr; }
+ bool unique() { return Obj && IntrusiveRefCntPtrInfo<T>::unique(Obj); }
+
private:
void retain() {
if (Obj)
>From 514ae513549245eadc4046f301f7d6186a6ff81e Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 31 Aug 2023 11:39:32 -0700
Subject: [PATCH 2/5] [clang][ci] Introduce copy-on-write `CompilerInvocation`
---
clang/include/clang/Basic/CodeGenOptions.h | 1 +
clang/include/clang/Basic/DiagnosticOptions.h | 1 +
clang/include/clang/Basic/LangOptions.h | 1 +
.../clang/Frontend/CompilerInvocation.h | 326 ++++++++++++------
clang/lib/Frontend/CompilerInvocation.cpp | 208 ++++++-----
5 files changed, 355 insertions(+), 182 deletions(-)
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 14fc94fe27f995..c6d7db32f2d266 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -32,6 +32,7 @@ namespace clang {
/// that this large collection of bitfields is a trivial class type.
class CodeGenOptionsBase {
friend class CompilerInvocation;
+ friend struct CompilerInvocationBase;
public:
#define CODEGENOPT(Name, Bits, Default) unsigned Name : Bits;
diff --git a/clang/include/clang/Basic/DiagnosticOptions.h b/clang/include/clang/Basic/DiagnosticOptions.h
index 0f3120859ecef6..9fb84415e22ead 100644
--- a/clang/include/clang/Basic/DiagnosticOptions.h
+++ b/clang/include/clang/Basic/DiagnosticOptions.h
@@ -72,6 +72,7 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
clang::DiagnosticsEngine *, bool);
friend class CompilerInvocation;
+ friend struct CompilerInvocationBase;
public:
enum TextDiagnosticFormat { Clang, MSVC, Vi, SARIF };
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 2adf4751444726..aa649e675d9024 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -34,6 +34,7 @@ namespace clang {
/// this large collection of bitfields is a trivial class type.
class LangOptionsBase {
friend class CompilerInvocation;
+ friend struct CompilerInvocationBase;
public:
// Define simple language options (with no accessors).
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 5dc55bb7abdbab..a7c349cd919189 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -20,8 +20,8 @@
#include "clang/Frontend/MigratorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include <memory>
#include <string>
@@ -66,6 +66,7 @@ bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args,
DiagnosticsEngine *Diags = nullptr,
bool DefaultDiagColor = true);
+namespace CompilerInvocationDetail {
/// The base class of CompilerInvocation with reference semantics.
///
/// This class stores option objects behind reference-counted pointers. This is
@@ -74,8 +75,8 @@ bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args,
///
/// This is a separate class so that we can implement the copy constructor and
/// assignment here and leave them defaulted in the rest of CompilerInvocation.
-class CompilerInvocationRefBase {
-public:
+class RefBase {
+protected:
/// Options controlling the language variant.
std::shared_ptr<LangOptions> LangOpts;
@@ -94,47 +95,36 @@ class CompilerInvocationRefBase {
/// Options controlling the static analyzer.
AnalyzerOptionsRef AnalyzerOpts;
- CompilerInvocationRefBase();
- CompilerInvocationRefBase(const CompilerInvocationRefBase &X);
- CompilerInvocationRefBase(CompilerInvocationRefBase &&X);
- CompilerInvocationRefBase &operator=(CompilerInvocationRefBase X);
- CompilerInvocationRefBase &operator=(CompilerInvocationRefBase &&X);
- ~CompilerInvocationRefBase();
+ struct ShallowCopy {};
+ struct DeepCopy {};
- LangOptions &getLangOpts() { return *LangOpts; }
- const LangOptions &getLangOpts() const { return *LangOpts; }
+ RefBase();
- TargetOptions &getTargetOpts() { return *TargetOpts.get(); }
- const TargetOptions &getTargetOpts() const { return *TargetOpts.get(); }
+ RefBase(const RefBase &X, DeepCopy);
+ RefBase(const RefBase &X, ShallowCopy);
+ RefBase(const RefBase &) = delete;
- DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; }
+ RefBase &assign(const RefBase &X, DeepCopy);
+ RefBase &assign(const RefBase &X, ShallowCopy);
+ RefBase &operator=(const RefBase &) = delete;
- HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; }
+ RefBase(RefBase &&);
+ RefBase &operator=(RefBase &&);
- const HeaderSearchOptions &getHeaderSearchOpts() const {
- return *HeaderSearchOpts;
- }
+ ~RefBase();
- std::shared_ptr<HeaderSearchOptions> getHeaderSearchOptsPtr() const {
- return HeaderSearchOpts;
- }
-
- std::shared_ptr<PreprocessorOptions> getPreprocessorOptsPtr() {
- return PreprocessorOpts;
- }
-
- PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; }
-
- const PreprocessorOptions &getPreprocessorOpts() const {
- return *PreprocessorOpts;
- }
-
- AnalyzerOptions &getAnalyzerOpts() { return *AnalyzerOpts; }
+ // clang-format off
+ const LangOptions &getLangOpts() const { return *LangOpts; }
+ const TargetOptions &getTargetOpts() const { return *TargetOpts; }
+ const DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; }
+ const HeaderSearchOptions &getHeaderSearchOpts() const { return *HeaderSearchOpts; }
+ const PreprocessorOptions &getPreprocessorOpts() const { return *PreprocessorOpts; }
const AnalyzerOptions &getAnalyzerOpts() const { return *AnalyzerOpts; }
+ // clang-format on
};
/// The base class of CompilerInvocation with value semantics.
-class CompilerInvocationValueBase {
+class ValBase {
protected:
MigratorOptions MigratorOpts;
@@ -151,39 +141,89 @@ class CompilerInvocationValueBase {
FrontendOptions FrontendOpts;
/// Options controlling preprocessed output.
- PreprocessorOutputOptions PreprocessorOutputOpts;
+ PreprocessorOutputOptions PPOutputOpts;
-public:
- MigratorOptions &getMigratorOpts() { return MigratorOpts; }
+ // clang-format off
const MigratorOptions &getMigratorOpts() const { return MigratorOpts; }
-
- CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
+ const DependencyOutputOptions &getDependencyOutputOpts() const { return DependencyOutputOpts; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+ const FrontendOptions &getFrontendOpts() const { return FrontendOpts; }
+ const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { return PPOutputOpts; }
+ // clang-format on
+};
+} // namespace CompilerInvocationDetail
- DependencyOutputOptions &getDependencyOutputOpts() {
- return DependencyOutputOpts;
- }
+struct CompilerInvocationBase : CompilerInvocationDetail::RefBase,
+ CompilerInvocationDetail::ValBase {
+ CompilerInvocationBase() = default;
- const DependencyOutputOptions &getDependencyOutputOpts() const {
- return DependencyOutputOpts;
- }
+ CompilerInvocationBase(const CompilerInvocationBase &X, DeepCopy)
+ : RefBase(X, DeepCopy{}), ValBase(X) {}
- FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ CompilerInvocationBase(const CompilerInvocationBase &X, ShallowCopy)
+ : RefBase(X, ShallowCopy{}), ValBase(X) {}
- const FileSystemOptions &getFileSystemOpts() const {
- return FileSystemOpts;
+ CompilerInvocationBase &assign(const CompilerInvocationBase &X, DeepCopy) {
+ RefBase::assign(X, DeepCopy{});
+ ValBase::operator=(X);
+ return *this;
}
- FrontendOptions &getFrontendOpts() { return FrontendOpts; }
- const FrontendOptions &getFrontendOpts() const { return FrontendOpts; }
-
- PreprocessorOutputOptions &getPreprocessorOutputOpts() {
- return PreprocessorOutputOpts;
+ CompilerInvocationBase &assign(const CompilerInvocationBase &X, ShallowCopy) {
+ RefBase::assign(X, ShallowCopy{});
+ ValBase::operator=(X);
+ return *this;
}
- const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
- return PreprocessorOutputOpts;
+ using StringAllocator = llvm::function_ref<const char *(const Twine &)>;
+ /// Generate cc1-compatible command line arguments from this instance.
+ ///
+ /// \param [out] Args - The generated arguments. Note that the caller is
+ /// responsible for inserting the path to the clang executable and "-cc1" if
+ /// desired.
+ /// \param SA - A function that given a Twine can allocate storage for a given
+ /// command line argument and return a pointer to the newly allocated string.
+ /// The returned pointer is what gets appended to Args.
+ void generateCC1CommandLine(llvm::SmallVectorImpl<const char *> &Args,
+ StringAllocator SA) const {
+ generateCC1CommandLine([&](const Twine &Arg) {
+ // No need to allocate static string literals.
+ Args.push_back(Arg.isSingleStringLiteral()
+ ? Arg.getSingleStringRef().data()
+ : SA(Arg));
+ });
}
+
+ using ArgumentConsumer = llvm::function_ref<void(const Twine &)>;
+ /// Generate cc1-compatible command line arguments from this instance.
+ ///
+ /// \param Consumer - Callback that gets invoked for every single generated
+ /// command line argument.
+ void generateCC1CommandLine(ArgumentConsumer Consumer) const;
+
+ /// Generate cc1-compatible command line arguments from this instance,
+ /// wrapping the result as a std::vector<std::string>.
+ ///
+ /// This is a (less-efficient) wrapper over generateCC1CommandLine().
+ std::vector<std::string> getCC1CommandLine() const;
+
+ /// Generate command line options from DiagnosticOptions.
+ static void GenerateDiagnosticArgs(const DiagnosticOptions &Opts,
+ ArgumentConsumer Consumer,
+ bool DefaultDiagColor);
+
+ /// Generate command line options from LangOptions.
+ static void GenerateLangArgs(const LangOptions &Opts,
+ ArgumentConsumer Consumer, const llvm::Triple &T,
+ InputKind IK);
+
+ // Generate command line options from CodeGenOptions.
+ static void GenerateCodeGenArgs(const CodeGenOptions &Opts,
+ ArgumentConsumer Consumer,
+ const llvm::Triple &T,
+ const std::string &OutputFile,
+ const LangOptions *LangOpts);
};
/// Helper class for holding the data necessary to invoke the compiler.
@@ -191,9 +231,76 @@ class CompilerInvocationValueBase {
/// This class is designed to represent an abstract "invocation" of the
/// compiler, including data such as the include paths, the code generation
/// options, the warning flags, and so on.
-class CompilerInvocation : public CompilerInvocationRefBase,
- public CompilerInvocationValueBase {
+class CompilerInvocation : public CompilerInvocationBase {
public:
+ CompilerInvocation() = default;
+
+ CompilerInvocation(const CompilerInvocation &X)
+ : CompilerInvocationBase(X, DeepCopy{}) {}
+
+ CompilerInvocation &operator=(const CompilerInvocation &X) {
+ CompilerInvocationBase::assign(X, DeepCopy{});
+ return *this;
+ }
+
+ // Mutable RefBase accessors.
+
+ // clang-format off
+ LangOptions &getLangOpts() { return *LangOpts; }
+ TargetOptions &getTargetOpts() { return *TargetOpts; }
+ DiagnosticOptions &getDiagnosticOpts() { return *DiagnosticOpts; }
+ HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; }
+ PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; }
+ AnalyzerOptions &getAnalyzerOpts() { return *AnalyzerOpts; }
+ // clang-format on
+
+ // Const RefBase accessors.
+
+ // clang-format off
+ using RefBase::getLangOpts;
+ using RefBase::getTargetOpts;
+ using RefBase::getDiagnosticOpts;
+ using RefBase::getHeaderSearchOpts;
+ using RefBase::getPreprocessorOpts;
+ using RefBase::getAnalyzerOpts;
+ // clang-format on
+
+ // Mutable ValBase accessors.
+
+ // clang-format off
+ MigratorOptions &getMigratorOpts() { return MigratorOpts; }
+ CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
+ DependencyOutputOptions &getDependencyOutputOpts() { return DependencyOutputOpts; }
+ FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ FrontendOptions &getFrontendOpts() { return FrontendOpts; }
+ PreprocessorOutputOptions &getPreprocessorOutputOpts() { return PPOutputOpts; }
+ // clang-format on
+
+ // Const ValBase accessors.
+
+ // clang-format off
+ using ValBase::getMigratorOpts;
+ using ValBase::getCodeGenOpts;
+ using ValBase::getDependencyOutputOpts;
+ using ValBase::getFileSystemOpts;
+ using ValBase::getFrontendOpts;
+ using ValBase::getPreprocessorOutputOpts;
+ // clang-format on
+
+ /// RefBase innards
+
+ std::shared_ptr<HeaderSearchOptions> getHeaderSearchOptsPtr() const {
+ return HeaderSearchOpts;
+ }
+
+ std::shared_ptr<PreprocessorOptions> getPreprocessorOptsPtr() const {
+ return PreprocessorOpts;
+ }
+
+ using CompilerInvocationBase::DiagnosticOpts;
+ using CompilerInvocationBase::TargetOpts;
+ using CompilerInvocationBase::LangOpts;
+
/// Create a compiler invocation from a list of input options.
/// \returns true on success.
///
@@ -224,38 +331,6 @@ class CompilerInvocation : public CompilerInvocationRefBase,
/// identifying the conditions under which the module was built.
std::string getModuleHash() const;
- using StringAllocator = llvm::function_ref<const char *(const Twine &)>;
- /// Generate cc1-compatible command line arguments from this instance.
- ///
- /// \param [out] Args - The generated arguments. Note that the caller is
- /// responsible for inserting the path to the clang executable and "-cc1" if
- /// desired.
- /// \param SA - A function that given a Twine can allocate storage for a given
- /// command line argument and return a pointer to the newly allocated string.
- /// The returned pointer is what gets appended to Args.
- void generateCC1CommandLine(llvm::SmallVectorImpl<const char *> &Args,
- StringAllocator SA) const {
- generateCC1CommandLine([&](const Twine &Arg) {
- // No need to allocate static string literals.
- Args.push_back(Arg.isSingleStringLiteral()
- ? Arg.getSingleStringRef().data()
- : SA(Arg));
- });
- }
-
- using ArgumentConsumer = llvm::function_ref<void(const Twine &)>;
- /// Generate cc1-compatible command line arguments from this instance.
- ///
- /// \param Consumer - Callback that gets invoked for every single generated
- /// command line argument.
- void generateCC1CommandLine(ArgumentConsumer Consumer) const;
-
- /// Generate cc1-compatible command line arguments from this instance,
- /// wrapping the result as a std::vector<std::string>.
- ///
- /// This is a (less-efficient) wrapper over generateCC1CommandLine().
- std::vector<std::string> getCC1CommandLine() const;
-
/// Check that \p Args can be parsed and re-serialized without change,
/// emiting diagnostics for any differences.
///
@@ -280,35 +355,76 @@ class CompilerInvocation : public CompilerInvocationRefBase,
ArrayRef<const char *> CommandLineArgs,
DiagnosticsEngine &Diags, const char *Argv0);
- /// Generate command line options from DiagnosticOptions.
- static void GenerateDiagnosticArgs(const DiagnosticOptions &Opts,
- ArgumentConsumer Consumer,
- bool DefaultDiagColor);
-
/// Parse command line options that map to LangOptions.
static bool ParseLangArgs(LangOptions &Opts, llvm::opt::ArgList &Args,
InputKind IK, const llvm::Triple &T,
std::vector<std::string> &Includes,
DiagnosticsEngine &Diags);
- /// Generate command line options from LangOptions.
- static void GenerateLangArgs(const LangOptions &Opts,
- ArgumentConsumer Consumer, const llvm::Triple &T,
- InputKind IK);
-
/// Parse command line options that map to CodeGenOptions.
static bool ParseCodeGenArgs(CodeGenOptions &Opts, llvm::opt::ArgList &Args,
InputKind IK, DiagnosticsEngine &Diags,
const llvm::Triple &T,
const std::string &OutputFile,
const LangOptions &LangOptsRef);
+};
- // Generate command line options from CodeGenOptions.
- static void GenerateCodeGenArgs(const CodeGenOptions &Opts,
- ArgumentConsumer Consumer,
- const llvm::Triple &T,
- const std::string &OutputFile,
- const LangOptions *LangOpts);
+/// Same as CompilerInvocation, but copies are on-demand and per-opts-object.
+struct CowCompilerInvocation : CompilerInvocationBase {
+ CowCompilerInvocation(const CompilerInvocation &X)
+ : CompilerInvocationBase(X, DeepCopy{}) {}
+
+ CowCompilerInvocation(const CowCompilerInvocation &X)
+ : CompilerInvocationBase(X, ShallowCopy{}) {}
+
+ CowCompilerInvocation &operator=(const CowCompilerInvocation &X) {
+ CompilerInvocationBase::assign(X, ShallowCopy{});
+ return *this;
+ }
+
+ // Mutable RefBase accessors.
+
+ // clang-format off
+ LangOptions &getMutLangOpts();
+ TargetOptions &getMutTargetOpts();
+ DiagnosticOptions &getMutDiagnosticOpts();
+ HeaderSearchOptions &getMutHeaderSearchOpts();
+ PreprocessorOptions &getMutPreprocessorOpts();
+ AnalyzerOptions &getMutAnalyzerOpts();
+ // clang-format on
+
+ // Const RefBase accessors.
+
+ // clang-format off
+ const LangOptions &getConstLangOpts() const { return *LangOpts; }
+ const TargetOptions &getConstTargetOpts() const { return *TargetOpts; }
+ const DiagnosticOptions &getConstDiagnosticOpts() const { return *DiagnosticOpts; }
+ const HeaderSearchOptions &getConstHeaderSearchOpts() const { return *HeaderSearchOpts; }
+ const PreprocessorOptions &getConstPreprocessorOpts() const { return *PreprocessorOpts; }
+ const AnalyzerOptions &getConstAnalyzerOpts() const { return *AnalyzerOpts; }
+ // clang-format on
+
+ // Mutable ValBase accessors.
+
+ // clang-format off
+ MigratorOptions &getMutMigratorOpts() { return MigratorOpts; }
+ CodeGenOptions &getMutCodeGenOpts() { return CodeGenOpts; }
+ DependencyOutputOptions &getMutDependencyOutputOpts() { return DependencyOutputOpts; }
+ FileSystemOptions &getMutFileSystemOpts() { return FileSystemOpts; }
+ FrontendOptions &getMutFrontendOpts() { return FrontendOpts; }
+ PreprocessorOutputOptions &getMutPreprocessorOutputOpts() { return PPOutputOpts; }
+ // clang-format on
+
+ // Const ValBase accessors.
+
+ // clang-format off
+ const MigratorOptions &getConstMigratorOpts() const { return MigratorOpts; }
+ const CodeGenOptions &getConstCodeGenOpts() const { return CodeGenOpts; }
+ const DependencyOutputOptions &getConstDependencyOutputOpts() const { return DependencyOutputOpts; }
+ const FileSystemOptions &getConstFileSystemOpts() const { return FileSystemOpts; }
+ const FrontendOptions &getConstFrontendOpts() const { return FrontendOpts; }
+ const PreprocessorOutputOptions &getConstPreprocessorOutputOpts() const { return PPOutputOpts; }
+ // clang-format on
};
IntrusiveRefCntPtr<llvm::vfs::FileSystem>
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 11ffb3d6630d1f..41972c7b05f896 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -123,49 +123,101 @@ static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) {
}
//===----------------------------------------------------------------------===//
-// Initialization.
+// Storage details.
//===----------------------------------------------------------------------===//
-CompilerInvocationRefBase::CompilerInvocationRefBase()
- : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
- DiagnosticOpts(new DiagnosticOptions()),
- HeaderSearchOpts(new HeaderSearchOptions()),
- PreprocessorOpts(new PreprocessorOptions()),
- AnalyzerOpts(new AnalyzerOptions()) {}
-
-CompilerInvocationRefBase::CompilerInvocationRefBase(
- const CompilerInvocationRefBase &X)
- : LangOpts(new LangOptions(X.getLangOpts())),
- TargetOpts(new TargetOptions(X.getTargetOpts())),
- DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
- HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
- PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())),
- AnalyzerOpts(new AnalyzerOptions(X.getAnalyzerOpts())) {}
-
-CompilerInvocationRefBase::CompilerInvocationRefBase(
- CompilerInvocationRefBase &&X) = default;
-
-CompilerInvocationRefBase &
-CompilerInvocationRefBase::operator=(CompilerInvocationRefBase X) {
- LangOpts.swap(X.LangOpts);
- TargetOpts.swap(X.TargetOpts);
- DiagnosticOpts.swap(X.DiagnosticOpts);
- HeaderSearchOpts.swap(X.HeaderSearchOpts);
- PreprocessorOpts.swap(X.PreprocessorOpts);
- AnalyzerOpts.swap(X.AnalyzerOpts);
+namespace clang::CompilerInvocationDetail {
+namespace {
+template <class T> std::shared_ptr<T> make_shared(const T &X) {
+ return std::make_shared<T>(X);
+}
+
+template <class T> llvm::IntrusiveRefCntPtr<T> makeIntrusiveRefCnt(const T &X) {
+ return llvm::makeIntrusiveRefCnt<T>(X);
+}
+} // namespace
+
+RefBase::RefBase()
+ : LangOpts(std::make_shared<LangOptions>()),
+ TargetOpts(std::make_shared<TargetOptions>()),
+ DiagnosticOpts(llvm::makeIntrusiveRefCnt<DiagnosticOptions>()),
+ HeaderSearchOpts(std::make_shared<HeaderSearchOptions>()),
+ PreprocessorOpts(std::make_shared<PreprocessorOptions>()),
+ AnalyzerOpts(llvm::makeIntrusiveRefCnt<AnalyzerOptions>()) {}
+
+RefBase::RefBase(const RefBase &X, DeepCopy)
+ : LangOpts(make_shared(*X.LangOpts)),
+ TargetOpts(make_shared(*X.TargetOpts)),
+ DiagnosticOpts(makeIntrusiveRefCnt(*X.DiagnosticOpts)),
+ HeaderSearchOpts(make_shared(*X.HeaderSearchOpts)),
+ PreprocessorOpts(make_shared(*X.PreprocessorOpts)),
+ AnalyzerOpts(makeIntrusiveRefCnt(*X.AnalyzerOpts)) {}
+
+RefBase::RefBase(const RefBase &X, ShallowCopy)
+ : LangOpts(X.LangOpts), //
+ TargetOpts(X.TargetOpts), //
+ DiagnosticOpts(X.DiagnosticOpts), //
+ HeaderSearchOpts(X.HeaderSearchOpts), //
+ PreprocessorOpts(X.PreprocessorOpts), //
+ AnalyzerOpts(X.AnalyzerOpts) {}
+
+RefBase &RefBase::assign(const RefBase &X, DeepCopy) {
+ LangOpts = make_shared(*X.LangOpts);
+ TargetOpts = make_shared(*X.TargetOpts);
+ DiagnosticOpts = makeIntrusiveRefCnt(*X.DiagnosticOpts);
+ HeaderSearchOpts = make_shared(*X.HeaderSearchOpts);
+ PreprocessorOpts = make_shared(*X.PreprocessorOpts);
+ AnalyzerOpts = makeIntrusiveRefCnt(*X.AnalyzerOpts);
return *this;
}
-CompilerInvocationRefBase &
-CompilerInvocationRefBase::operator=(CompilerInvocationRefBase &&X) = default;
+RefBase &RefBase::assign(const RefBase &X, ShallowCopy) {
+ LangOpts = X.LangOpts;
+ TargetOpts = X.TargetOpts;
+ DiagnosticOpts = X.DiagnosticOpts;
+ HeaderSearchOpts = X.HeaderSearchOpts;
+ PreprocessorOpts = X.PreprocessorOpts;
+ AnalyzerOpts = X.AnalyzerOpts;
+ return *this;
+}
+
+RefBase::RefBase(RefBase &&) = default;
+RefBase &RefBase::operator=(RefBase &&) = default;
+
+RefBase::~RefBase() = default;
+} // namespace clang::CompilerInvocationDetail
+
+namespace {
+template <typename T>
+T &ensure_owned(std::shared_ptr<T> &Storage) {
+ if (!Storage.unique())
+ Storage = std::make_shared<T>(*Storage);
+ return *Storage;
+}
+
+template <typename T>
+T &ensure_owned(llvm::IntrusiveRefCntPtr<T> &Storage) {
+ if (!Storage.unique())
+ Storage = llvm::makeIntrusiveRefCnt<T>(*Storage);
+ return *Storage;
+}
+} // namespace
-CompilerInvocationRefBase::~CompilerInvocationRefBase() = default;
+// clang-format off
+LangOptions &CowCompilerInvocation::getMutLangOpts() { return ensure_owned(LangOpts); }
+TargetOptions &CowCompilerInvocation::getMutTargetOpts() { return ensure_owned(TargetOpts); }
+DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() { return ensure_owned(DiagnosticOpts); }
+HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() { return ensure_owned(HeaderSearchOpts); }
+PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() { return ensure_owned(PreprocessorOpts); }
+AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() { return ensure_owned(AnalyzerOpts); }
+// clang-format on
//===----------------------------------------------------------------------===//
// Normalizers
//===----------------------------------------------------------------------===//
-using ArgumentConsumer = CompilerInvocation::ArgumentConsumer;
+using ArgumentConsumer = CompilerInvocationBase::ArgumentConsumer;
+using StringAllocator = CompilerInvocationBase::StringAllocator;
#define SIMPLE_ENUM_VALUE_TABLE
#include "clang/Driver/Options.inc"
@@ -633,8 +685,7 @@ using ParseFn =
// Generate command line arguments from CompilerInvocation.
using GenerateFn = llvm::function_ref<void(
- CompilerInvocation &, SmallVectorImpl<const char *> &,
- CompilerInvocation::StringAllocator)>;
+ CompilerInvocation &, SmallVectorImpl<const char *> &, StringAllocator)>;
/// May perform round-trip of command line arguments. By default, the round-trip
/// is enabled in assert builds. This can be overwritten at run-time via the
@@ -838,7 +889,7 @@ static void getAllNoBuiltinFuncValues(ArgList &Args,
Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
}
-static void GenerateAnalyzerArgs(AnalyzerOptions &Opts,
+static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts,
ArgumentConsumer Consumer) {
const AnalyzerOptions *AnalyzerOpts = &Opts;
@@ -1346,11 +1397,11 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts,
Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
}
-void CompilerInvocation::GenerateCodeGenArgs(const CodeGenOptions &Opts,
- ArgumentConsumer Consumer,
- const llvm::Triple &T,
- const std::string &OutputFile,
- const LangOptions *LangOpts) {
+void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
+ ArgumentConsumer Consumer,
+ const llvm::Triple &T,
+ const std::string &OutputFile,
+ const LangOptions *LangOpts) {
const CodeGenOptions &CodeGenOpts = Opts;
if (Opts.OptimizationLevel == 0)
@@ -2254,9 +2305,9 @@ static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,
return Diags.getNumErrors() == NumErrorsBefore;
}
-void CompilerInvocation::GenerateDiagnosticArgs(const DiagnosticOptions &Opts,
- ArgumentConsumer Consumer,
- bool DefaultDiagColor) {
+void CompilerInvocationBase::GenerateDiagnosticArgs(
+ const DiagnosticOptions &Opts, ArgumentConsumer Consumer,
+ bool DefaultDiagColor) {
const DiagnosticOptions *DiagnosticOpts = &Opts;
#define DIAG_OPTION_WITH_MARSHALLING(...) \
GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
@@ -2917,7 +2968,7 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
}
-static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts,
+static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
ArgumentConsumer Consumer) {
const HeaderSearchOptions *HeaderSearchOpts = &Opts;
#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \
@@ -3247,9 +3298,10 @@ static StringRef GetInputKindName(InputKind IK) {
llvm_unreachable("unknown input language");
}
-void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
- ArgumentConsumer Consumer,
- const llvm::Triple &T, InputKind IK) {
+void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
+ ArgumentConsumer Consumer,
+ const llvm::Triple &T,
+ InputKind IK) {
if (IK.getFormat() == InputKind::Precompiled ||
IK.getLanguage() == Language::LLVM_IR) {
if (Opts.ObjCAutoRefCount)
@@ -4103,12 +4155,12 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
llvm_unreachable("invalid frontend action");
}
-static void GeneratePreprocessorArgs(PreprocessorOptions &Opts,
+static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts,
ArgumentConsumer Consumer,
const LangOptions &LangOpts,
const FrontendOptions &FrontendOpts,
const CodeGenOptions &CodeGenOpts) {
- PreprocessorOptions *PreprocessorOpts = &Opts;
+ const PreprocessorOptions *PreprocessorOpts = &Opts;
#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \
GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
@@ -4507,22 +4559,23 @@ std::string CompilerInvocation::getModuleHash() const {
HBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);
// Extend the signature with the language options
-#define LANGOPT(Name, Bits, Default, Description) HBuilder.add(LangOpts->Name);
+#define LANGOPT(Name, Bits, Default, Description) \
+ HBuilder.add(getLangOpts().Name);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
- HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));
+ HBuilder.add(static_cast<unsigned>(getLangOpts().get##Name()));
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
- HBuilder.addRange(LangOpts->ModuleFeatures);
+ HBuilder.addRange(getLangOpts().ModuleFeatures);
- HBuilder.add(LangOpts->ObjCRuntime);
- HBuilder.addRange(LangOpts->CommentOpts.BlockCommandNames);
+ HBuilder.add(getLangOpts().ObjCRuntime);
+ HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames);
// Extend the signature with the target options.
- HBuilder.add(TargetOpts->Triple, TargetOpts->CPU, TargetOpts->TuneCPU,
- TargetOpts->ABI);
- HBuilder.addRange(TargetOpts->FeaturesAsWritten);
+ HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU,
+ getTargetOpts().TuneCPU, getTargetOpts().ABI);
+ HBuilder.addRange(getTargetOpts().FeaturesAsWritten);
// Extend the signature with preprocessor options.
const PreprocessorOptions &ppOpts = getPreprocessorOpts();
@@ -4577,7 +4630,7 @@ std::string CompilerInvocation::getModuleHash() const {
// Extend the signature with the enabled sanitizers, if at least one is
// enabled. Sanitizers which cannot affect AST generation aren't hashed.
- SanitizerSet SanHash = LangOpts->Sanitize;
+ SanitizerSet SanHash = getLangOpts().Sanitize;
SanHash.clear(getPPTransparentSanitizers());
if (!SanHash.empty())
HBuilder.add(SanHash.Mask);
@@ -4588,28 +4641,29 @@ std::string CompilerInvocation::getModuleHash() const {
return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);
}
-void CompilerInvocation::generateCC1CommandLine(
+void CompilerInvocationBase::generateCC1CommandLine(
ArgumentConsumer Consumer) const {
- llvm::Triple T(TargetOpts->Triple);
-
- GenerateFileSystemArgs(FileSystemOpts, Consumer);
- GenerateMigratorArgs(MigratorOpts, Consumer);
- GenerateAnalyzerArgs(*AnalyzerOpts, Consumer);
- GenerateDiagnosticArgs(*DiagnosticOpts, Consumer, false);
- GenerateFrontendArgs(FrontendOpts, Consumer, LangOpts->IsHeaderFile);
- GenerateTargetArgs(*TargetOpts, Consumer);
- GenerateHeaderSearchArgs(*HeaderSearchOpts, Consumer);
- GenerateLangArgs(*LangOpts, Consumer, T, FrontendOpts.DashX);
- GenerateCodeGenArgs(CodeGenOpts, Consumer, T, FrontendOpts.OutputFile,
- &*LangOpts);
- GeneratePreprocessorArgs(*PreprocessorOpts, Consumer, *LangOpts, FrontendOpts,
- CodeGenOpts);
- GeneratePreprocessorOutputArgs(PreprocessorOutputOpts, Consumer,
- FrontendOpts.ProgramAction);
- GenerateDependencyOutputArgs(DependencyOutputOpts, Consumer);
+ llvm::Triple T(getTargetOpts().Triple);
+
+ GenerateFileSystemArgs(getFileSystemOpts(), Consumer);
+ GenerateMigratorArgs(getMigratorOpts(), Consumer);
+ GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer);
+ GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer, false);
+ GenerateFrontendArgs(getFrontendOpts(), Consumer,
+ getLangOpts().IsHeaderFile);
+ GenerateTargetArgs(getTargetOpts(), Consumer);
+ GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer);
+ GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);
+ GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,
+ getFrontendOpts().OutputFile, &getLangOpts());
+ GeneratePreprocessorArgs(getPreprocessorOpts(), Consumer, getLangOpts(),
+ getFrontendOpts(), getCodeGenOpts());
+ GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer,
+ getFrontendOpts().ProgramAction);
+ GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer);
}
-std::vector<std::string> CompilerInvocation::getCC1CommandLine() const {
+std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {
std::vector<std::string> Args{"-cc1"};
generateCC1CommandLine(
[&Args](const Twine &Arg) { Args.push_back(Arg.str()); });
>From 9ab72be5e1287465245b0d8dc656a0340065b3d3 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 24 Aug 2023 17:33:38 -0700
Subject: [PATCH 3/5] [clang][deps] Store common, partially-formed invocation
---
.../DependencyScanning/ModuleDepCollector.h | 17 ++-
.../DependencyScanning/ModuleDepCollector.cpp | 119 ++++++++++--------
2 files changed, 81 insertions(+), 55 deletions(-)
diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
index 914d55eadefe85..1f76314101c20a 100644
--- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -241,8 +241,10 @@ class ModuleDepCollector final : public DependencyCollector {
llvm::SetVector<const Module *> DirectModularDeps;
/// Options that control the dependency output generation.
std::unique_ptr<DependencyOutputOptions> Opts;
- /// The original Clang invocation passed to dependency scanner.
- CompilerInvocation OriginalInvocation;
+ /// Original Clang invocation passed to the dependency scanner that has been
+ /// partially massaged into one that can perform explicit build of a module.
+ /// This still needs to be finalized for each discovered modular dependency.
+ CowCompilerInvocation CommonInvocation;
/// Whether to optimize the modules' command-line arguments.
bool OptimizeArgs;
/// Whether to set up command-lines to load PCM files eagerly.
@@ -265,9 +267,9 @@ class ModuleDepCollector final : public DependencyCollector {
/// Constructs a CompilerInvocation that can be used to build the given
/// module, excluding paths to discovered modular dependencies that are yet to
/// be built.
- CompilerInvocation makeInvocationForModuleBuildWithoutOutputs(
+ CowCompilerInvocation makeInvocationForModuleBuildWithoutOutputs(
const ModuleDeps &Deps,
- llvm::function_ref<void(CompilerInvocation &)> Optimize) const;
+ llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const;
/// Collect module map files for given modules.
llvm::DenseSet<const FileEntry *>
@@ -279,13 +281,16 @@ class ModuleDepCollector final : public DependencyCollector {
/// Add module files (pcm) to the invocation, if needed.
void addModuleFiles(CompilerInvocation &CI,
ArrayRef<ModuleID> ClangModuleDeps) const;
+ void addModuleFiles(CowCompilerInvocation &CI,
+ ArrayRef<ModuleID> ClangModuleDeps) const;
/// Add paths that require looking up outputs to the given dependencies.
- void addOutputPaths(CompilerInvocation &CI, ModuleDeps &Deps);
+ void addOutputPaths(CowCompilerInvocation &CI, ModuleDeps &Deps);
/// Compute the context hash for \p Deps, and create the mapping
/// \c ModuleDepsByID[Deps.ID] = &Deps.
- void associateWithContextHash(const CompilerInvocation &CI, ModuleDeps &Deps);
+ void associateWithContextHash(const CompilerInvocationBase &CI,
+ ModuleDeps &Deps);
};
} // end namespace dependencies
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index e13f7c74e9b92e..09289313cb1ebe 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -54,38 +54,33 @@ static std::vector<std::string> splitString(std::string S, char Separator) {
return Result;
}
-void ModuleDepCollector::addOutputPaths(CompilerInvocation &CI,
+void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI,
ModuleDeps &Deps) {
- CI.getFrontendOpts().OutputFile =
+ CI.getMutFrontendOpts().OutputFile =
Controller.lookupModuleOutput(Deps.ID, ModuleOutputKind::ModuleFile);
- if (!CI.getDiagnosticOpts().DiagnosticSerializationFile.empty())
- CI.getDiagnosticOpts().DiagnosticSerializationFile =
+ if (!CI.getConstDiagnosticOpts().DiagnosticSerializationFile.empty())
+ CI.getMutDiagnosticOpts().DiagnosticSerializationFile =
Controller.lookupModuleOutput(
Deps.ID, ModuleOutputKind::DiagnosticSerializationFile);
- if (!CI.getDependencyOutputOpts().OutputFile.empty()) {
- CI.getDependencyOutputOpts().OutputFile = Controller.lookupModuleOutput(
+ if (!CI.getConstDependencyOutputOpts().OutputFile.empty()) {
+ CI.getMutDependencyOutputOpts().OutputFile = Controller.lookupModuleOutput(
Deps.ID, ModuleOutputKind::DependencyFile);
- CI.getDependencyOutputOpts().Targets =
+ CI.getMutDependencyOutputOpts().Targets =
splitString(Controller.lookupModuleOutput(
Deps.ID, ModuleOutputKind::DependencyTargets),
'\0');
- if (!CI.getDependencyOutputOpts().OutputFile.empty() &&
- CI.getDependencyOutputOpts().Targets.empty()) {
+ if (!CI.getMutDependencyOutputOpts().OutputFile.empty() &&
+ CI.getMutDependencyOutputOpts().Targets.empty()) {
// Fallback to -o as dependency target, as in the driver.
SmallString<128> Target;
- quoteMakeTarget(CI.getFrontendOpts().OutputFile, Target);
- CI.getDependencyOutputOpts().Targets.push_back(std::string(Target));
+ quoteMakeTarget(CI.getConstFrontendOpts().OutputFile, Target);
+ CI.getMutDependencyOutputOpts().Targets.push_back(std::string(Target));
}
}
}
-CompilerInvocation
-ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
- const ModuleDeps &Deps,
- llvm::function_ref<void(CompilerInvocation &)> Optimize) const {
- // Make a deep copy of the original Clang invocation.
- CompilerInvocation CI(OriginalInvocation);
-
+static CowCompilerInvocation
+makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
CI.resetNonModularOptions();
CI.clearImplicitModuleBuildOptions();
@@ -117,14 +112,37 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
CI.getFrontendOpts().ARCMTAction = FrontendOptions::ARCMT_None;
CI.getFrontendOpts().ObjCMTAction = FrontendOptions::ObjCMT_None;
CI.getFrontendOpts().MTMigrateDir.clear();
- CI.getLangOpts().ModuleName = Deps.ID.ModuleName;
- CI.getFrontendOpts().IsSystemModule = Deps.IsSystem;
+
+ // Remove any macro definitions that are explicitly ignored.
+ if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
+ llvm::erase_if(
+ CI.getPreprocessorOpts().Macros,
+ [&CI](const std::pair<std::string, bool> &Def) {
+ StringRef MacroDef = Def.first;
+ return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
+ llvm::CachedHashString(MacroDef.split('=').first));
+ });
+ // Remove the now unused option.
+ CI.getHeaderSearchOpts().ModulesIgnoreMacros.clear();
+ }
+
+ return CI;
+}
+
+CowCompilerInvocation
+ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
+ const ModuleDeps &Deps,
+ llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const {
+ CowCompilerInvocation CI = CommonInvocation;
+
+ CI.getMutLangOpts().ModuleName = Deps.ID.ModuleName;
+ CI.getMutFrontendOpts().IsSystemModule = Deps.IsSystem;
// Inputs
- InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(),
+ InputKind ModuleMapInputKind(CI.getConstFrontendOpts().DashX.getLanguage(),
InputKind::Format::ModuleMap);
- CI.getFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
- ModuleMapInputKind);
+ CI.getMutFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
+ ModuleMapInputKind);
auto CurrentModuleMapEntry =
ScanInstance.getFileManager().getFile(Deps.ClangModuleMapFile);
@@ -150,35 +168,23 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
!DepModuleMapFiles.contains(*ModuleMapEntry))
continue;
- CI.getFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile);
+ CI.getMutFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile);
}
// Report the prebuilt modules this module uses.
for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps)
- CI.getFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
+ CI.getMutFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
// Add module file inputs from dependencies.
addModuleFiles(CI, Deps.ClangModuleDeps);
- // Remove any macro definitions that are explicitly ignored.
- if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
- llvm::erase_if(
- CI.getPreprocessorOpts().Macros,
- [&CI](const std::pair<std::string, bool> &Def) {
- StringRef MacroDef = Def.first;
- return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
- llvm::CachedHashString(MacroDef.split('=').first));
- });
- // Remove the now unused option.
- CI.getHeaderSearchOpts().ModulesIgnoreMacros.clear();
- }
-
// Apply -Wsystem-headers-in-module for the current module.
- if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules,
- Deps.ID.ModuleName))
- CI.getDiagnosticOpts().Warnings.push_back("system-headers");
+ if (llvm::is_contained(
+ CI.getConstDiagnosticOpts().SystemHeaderWarningsModules,
+ Deps.ID.ModuleName))
+ CI.getMutDiagnosticOpts().Warnings.push_back("system-headers");
// Remove the now unused option(s).
- CI.getDiagnosticOpts().SystemHeaderWarningsModules.clear();
+ CI.getMutDiagnosticOpts().SystemHeaderWarningsModules.clear();
Optimize(CI);
@@ -224,6 +230,19 @@ void ModuleDepCollector::addModuleFiles(
}
}
+void ModuleDepCollector::addModuleFiles(
+ CowCompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
+ for (const ModuleID &MID : ClangModuleDeps) {
+ std::string PCMPath =
+ Controller.lookupModuleOutput(MID, ModuleOutputKind::ModuleFile);
+ if (EagerLoadModules)
+ CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
+ else
+ CI.getMutHeaderSearchOpts().PrebuiltModuleFiles.insert(
+ {MID.ModuleName, std::move(PCMPath)});
+ }
+}
+
static bool needsModules(FrontendInputFile FIF) {
switch (FIF.getKind().getLanguage()) {
case Language::Unknown:
@@ -264,7 +283,7 @@ void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) {
}
static std::string getModuleContextHash(const ModuleDeps &MD,
- const CompilerInvocation &CI,
+ const CompilerInvocationBase &CI,
bool EagerLoadModules) {
llvm::HashBuilder<llvm::TruncatedBLAKE3<16>,
llvm::support::endianness::native>
@@ -304,8 +323,8 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
return toString(llvm::APInt(sizeof(Words) * 8, Words), 36, /*Signed=*/false);
}
-void ModuleDepCollector::associateWithContextHash(const CompilerInvocation &CI,
- ModuleDeps &Deps) {
+void ModuleDepCollector::associateWithContextHash(
+ const CompilerInvocationBase &CI, ModuleDeps &Deps) {
Deps.ID.ContextHash = getModuleContextHash(Deps, CI, EagerLoadModules);
bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second;
(void)Inserted;
@@ -498,10 +517,10 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
MD.ModuleMapFileDeps.emplace_back(IFI.FilenameAsRequested);
});
- CompilerInvocation CI = MDC.makeInvocationForModuleBuildWithoutOutputs(
- MD, [&](CompilerInvocation &BuildInvocation) {
+ CowCompilerInvocation CI = MDC.makeInvocationForModuleBuildWithoutOutputs(
+ MD, [&](CowCompilerInvocation &BuildInvocation) {
if (MDC.OptimizeArgs)
- optimizeHeaderSearchOpts(BuildInvocation.getHeaderSearchOpts(),
+ optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(),
*MDC.ScanInstance.getASTReader(), *MF);
});
@@ -601,7 +620,9 @@ ModuleDepCollector::ModuleDepCollector(
DependencyActionController &Controller, CompilerInvocation OriginalCI,
bool OptimizeArgs, bool EagerLoadModules, bool IsStdModuleP1689Format)
: ScanInstance(ScanInstance), Consumer(C), Controller(Controller),
- Opts(std::move(Opts)), OriginalInvocation(std::move(OriginalCI)),
+ Opts(std::move(Opts)),
+ CommonInvocation(
+ makeCommonInvocationForModuleBuild(std::move(OriginalCI))),
OptimizeArgs(OptimizeArgs), EagerLoadModules(EagerLoadModules),
IsStdModuleP1689Format(IsStdModuleP1689Format) {}
>From b74f4dec1cef70a032ce5ce211addac1de5e949d Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Fri, 1 Sep 2023 13:01:24 -0700
Subject: [PATCH 4/5] [clang][deps] Generate command-lines lazily
---
.../DependencyScanningTool.h | 2 +-
.../DependencyScanning/ModuleDepCollector.h | 21 +++++++++----
.../DependencyScanning/ModuleDepCollector.cpp | 29 ++++++++---------
clang/tools/clang-scan-deps/ClangScanDeps.cpp | 31 +++++++++++++------
4 files changed, 52 insertions(+), 31 deletions(-)
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
index cb9476d1550df3..b2cfa621e183c8 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -168,7 +168,7 @@ class FullDependencyConsumer : public DependencyConsumer {
}
void handleModuleDependency(ModuleDeps MD) override {
- ClangModuleDeps[MD.ID] = std::move(MD);
+ ClangModuleDeps.insert({MD.ID, std::move(MD)});
}
void handleDirectModuleDependency(ModuleID ID) override {
diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
index 1f76314101c20a..b7189939caf714 100644
--- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -104,7 +104,16 @@ enum class ModuleOutputKind {
DiagnosticSerializationFile,
};
-struct ModuleDeps {
+class ModuleDeps {
+ std::variant<std::shared_ptr<CowCompilerInvocation>, std::vector<std::string>>
+ BuildInvocationOrArguments;
+
+ explicit ModuleDeps(std::shared_ptr<CowCompilerInvocation> CI)
+ : BuildInvocationOrArguments(std::move(CI)) {}
+
+ friend class ModuleDepCollectorPP;
+
+public:
/// The identifier of the module.
ModuleID ID;
@@ -136,9 +145,9 @@ struct ModuleDeps {
/// determined that the differences are benign for this compilation.
std::vector<ModuleID> ClangModuleDeps;
- /// Compiler invocation that can be used to build this module. Does not
- /// include argv[0].
- std::vector<std::string> BuildArguments;
+ /// Get (or compute) the compiler invocation that can be used to build this
+ /// module. Does not include argv[0].
+ const std::vector<std::string> &getBuildArguments();
};
class ModuleDepCollector;
@@ -267,8 +276,8 @@ class ModuleDepCollector final : public DependencyCollector {
/// Constructs a CompilerInvocation that can be used to build the given
/// module, excluding paths to discovered modular dependencies that are yet to
/// be built.
- CowCompilerInvocation makeInvocationForModuleBuildWithoutOutputs(
- const ModuleDeps &Deps,
+ void makeInvocationForModuleBuildWithoutOutputs(
+ CowCompilerInvocation &CI, const ModuleDeps &Deps,
llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const;
/// Collect module map files for given modules.
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index 09289313cb1ebe..ef10ad18b6314b 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -21,6 +21,13 @@ using namespace clang;
using namespace tooling;
using namespace dependencies;
+const std::vector<std::string> &ModuleDeps::getBuildArguments() {
+ if (auto *CI = std::get_if<std::shared_ptr<CowCompilerInvocation>>(
+ &BuildInvocationOrArguments))
+ BuildInvocationOrArguments = (*CI)->getCC1CommandLine();
+ return std::get<std::vector<std::string>>(BuildInvocationOrArguments);
+}
+
static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts,
ASTReader &Reader,
const serialization::ModuleFile &MF) {
@@ -129,12 +136,9 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
return CI;
}
-CowCompilerInvocation
-ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
- const ModuleDeps &Deps,
+void ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
+ CowCompilerInvocation &CI, const ModuleDeps &Deps,
llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const {
- CowCompilerInvocation CI = CommonInvocation;
-
CI.getMutLangOpts().ModuleName = Deps.ID.ModuleName;
CI.getMutFrontendOpts().IsSystemModule = Deps.IsSystem;
@@ -187,8 +191,6 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
CI.getMutDiagnosticOpts().SystemHeaderWarningsModules.clear();
Optimize(CI);
-
- return CI;
}
llvm::DenseSet<const FileEntry *> ModuleDepCollector::collectModuleMapFiles(
@@ -466,7 +468,8 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
if (!ModI.second)
return ModI.first->second->ID;
- ModI.first->second = std::make_unique<ModuleDeps>();
+ auto CI = std::make_shared<CowCompilerInvocation>(MDC.CommonInvocation);
+ ModI.first->second.reset(new ModuleDeps(CI));
ModuleDeps &MD = *ModI.first->second;
MD.ID.ModuleName = M->getFullModuleName();
@@ -517,19 +520,17 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
MD.ModuleMapFileDeps.emplace_back(IFI.FilenameAsRequested);
});
- CowCompilerInvocation CI = MDC.makeInvocationForModuleBuildWithoutOutputs(
- MD, [&](CowCompilerInvocation &BuildInvocation) {
+ MDC.makeInvocationForModuleBuildWithoutOutputs(
+ *CI, MD, [&](CowCompilerInvocation &BuildInvocation) {
if (MDC.OptimizeArgs)
optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(),
*MDC.ScanInstance.getASTReader(), *MF);
});
- MDC.associateWithContextHash(CI, MD);
+ MDC.associateWithContextHash(*CI, MD);
// Finish the compiler invocation. Requires dependencies and the context hash.
- MDC.addOutputPaths(CI, MD);
-
- MD.BuildArguments = CI.getCC1CommandLine();
+ MDC.addOutputPaths(*CI, MD);
return MD.ID;
}
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index dab3de42b7fa1a..7491d6c284fe12 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -351,14 +351,23 @@ class FullDeps {
}
void mergeDeps(ModuleDepsGraph Graph, size_t InputIndex) {
- std::unique_lock<std::mutex> ul(Lock);
- for (const ModuleDeps &MD : Graph) {
- auto I = Modules.find({MD.ID, 0});
- if (I != Modules.end()) {
- I->first.InputIndex = std::min(I->first.InputIndex, InputIndex);
- continue;
+ std::vector<ModuleDeps *> NewMDs;
+ {
+ std::unique_lock<std::mutex> ul(Lock);
+ for (const ModuleDeps &MD : Graph) {
+ auto I = Modules.find({MD.ID, 0});
+ if (I != Modules.end()) {
+ I->first.InputIndex = std::min(I->first.InputIndex, InputIndex);
+ continue;
+ }
+ auto Res = Modules.insert(I, {{MD.ID, InputIndex}, std::move(MD)});
+ NewMDs.push_back(&Res->second);
}
- Modules.insert(I, {{MD.ID, InputIndex}, std::move(MD)});
+ // First call to \c getBuildArguments is somewhat expensive. Let's call it
+ // on the current thread (instead of the main one), and outside the
+ // critical section.
+ for (ModuleDeps *MD : NewMDs)
+ MD->getBuildArguments();
}
}
@@ -382,7 +391,7 @@ class FullDeps {
/*ShouldOwnClient=*/false);
for (auto &&M : Modules)
- if (roundTripCommand(M.second.BuildArguments, *Diags))
+ if (roundTripCommand(M.second.getBuildArguments(), *Diags))
return true;
for (auto &&I : Inputs)
@@ -404,14 +413,16 @@ class FullDeps {
Array OutModules;
for (auto &&ModID : ModuleIDs) {
- auto &MD = Modules[ModID];
+ auto It = Modules.find(ModID);
+ assert(It != Modules.end());
+ auto &MD = It->second;
Object O{
{"name", MD.ID.ModuleName},
{"context-hash", MD.ID.ContextHash},
{"file-deps", toJSONSorted(MD.FileDeps)},
{"clang-module-deps", toJSONSorted(MD.ClangModuleDeps)},
{"clang-modulemap-file", MD.ClangModuleMapFile},
- {"command-line", MD.BuildArguments},
+ {"command-line", MD.getBuildArguments()},
};
OutModules.push_back(std::move(O));
}
>From b83741bd2032ab05bdf040a5c9d3ed9c1bd1c8c8 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Fri, 1 Sep 2023 14:45:48 -0700
Subject: [PATCH 5/5] [clang][cli][deps] Make CodeGenOpts copy-on-write
---
.../include/clang/Frontend/CompilerInvocation.h | 16 ++++++++--------
clang/lib/Frontend/CompilerInvocation.cpp | 6 ++++++
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index a7c349cd919189..3d5a7fdf99cb6e 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -92,6 +92,9 @@ class RefBase {
/// Options controlling the preprocessor (aside from \#include handling).
std::shared_ptr<PreprocessorOptions> PreprocessorOpts;
+ /// Options controlling IRgen and the backend.
+ std::shared_ptr<CodeGenOptions> CodeGenOpts;
+
/// Options controlling the static analyzer.
AnalyzerOptionsRef AnalyzerOpts;
@@ -119,6 +122,7 @@ class RefBase {
const DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; }
const HeaderSearchOptions &getHeaderSearchOpts() const { return *HeaderSearchOpts; }
const PreprocessorOptions &getPreprocessorOpts() const { return *PreprocessorOpts; }
+ const CodeGenOptions &getCodeGenOpts() const { return *CodeGenOpts; }
const AnalyzerOptions &getAnalyzerOpts() const { return *AnalyzerOpts; }
// clang-format on
};
@@ -128,9 +132,6 @@ class ValBase {
protected:
MigratorOptions MigratorOpts;
- /// Options controlling IRgen and the backend.
- CodeGenOptions CodeGenOpts;
-
/// Options controlling dependency output.
DependencyOutputOptions DependencyOutputOpts;
@@ -145,7 +146,6 @@ class ValBase {
// clang-format off
const MigratorOptions &getMigratorOpts() const { return MigratorOpts; }
- const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
const DependencyOutputOptions &getDependencyOutputOpts() const { return DependencyOutputOpts; }
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
const FrontendOptions &getFrontendOpts() const { return FrontendOpts; }
@@ -251,6 +251,7 @@ class CompilerInvocation : public CompilerInvocationBase {
DiagnosticOptions &getDiagnosticOpts() { return *DiagnosticOpts; }
HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; }
PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; }
+ CodeGenOptions &getCodeGenOpts() { return *CodeGenOpts; }
AnalyzerOptions &getAnalyzerOpts() { return *AnalyzerOpts; }
// clang-format on
@@ -262,6 +263,7 @@ class CompilerInvocation : public CompilerInvocationBase {
using RefBase::getDiagnosticOpts;
using RefBase::getHeaderSearchOpts;
using RefBase::getPreprocessorOpts;
+ using RefBase::getCodeGenOpts;
using RefBase::getAnalyzerOpts;
// clang-format on
@@ -269,7 +271,6 @@ class CompilerInvocation : public CompilerInvocationBase {
// clang-format off
MigratorOptions &getMigratorOpts() { return MigratorOpts; }
- CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
DependencyOutputOptions &getDependencyOutputOpts() { return DependencyOutputOpts; }
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
FrontendOptions &getFrontendOpts() { return FrontendOpts; }
@@ -280,7 +281,6 @@ class CompilerInvocation : public CompilerInvocationBase {
// clang-format off
using ValBase::getMigratorOpts;
- using ValBase::getCodeGenOpts;
using ValBase::getDependencyOutputOpts;
using ValBase::getFileSystemOpts;
using ValBase::getFrontendOpts;
@@ -390,6 +390,7 @@ struct CowCompilerInvocation : CompilerInvocationBase {
DiagnosticOptions &getMutDiagnosticOpts();
HeaderSearchOptions &getMutHeaderSearchOpts();
PreprocessorOptions &getMutPreprocessorOpts();
+ CodeGenOptions &getMutCodeGenOpts();
AnalyzerOptions &getMutAnalyzerOpts();
// clang-format on
@@ -401,6 +402,7 @@ struct CowCompilerInvocation : CompilerInvocationBase {
const DiagnosticOptions &getConstDiagnosticOpts() const { return *DiagnosticOpts; }
const HeaderSearchOptions &getConstHeaderSearchOpts() const { return *HeaderSearchOpts; }
const PreprocessorOptions &getConstPreprocessorOpts() const { return *PreprocessorOpts; }
+ const CodeGenOptions &getConstCodeGenOpts() const { return *CodeGenOpts; }
const AnalyzerOptions &getConstAnalyzerOpts() const { return *AnalyzerOpts; }
// clang-format on
@@ -408,7 +410,6 @@ struct CowCompilerInvocation : CompilerInvocationBase {
// clang-format off
MigratorOptions &getMutMigratorOpts() { return MigratorOpts; }
- CodeGenOptions &getMutCodeGenOpts() { return CodeGenOpts; }
DependencyOutputOptions &getMutDependencyOutputOpts() { return DependencyOutputOpts; }
FileSystemOptions &getMutFileSystemOpts() { return FileSystemOpts; }
FrontendOptions &getMutFrontendOpts() { return FrontendOpts; }
@@ -419,7 +420,6 @@ struct CowCompilerInvocation : CompilerInvocationBase {
// clang-format off
const MigratorOptions &getConstMigratorOpts() const { return MigratorOpts; }
- const CodeGenOptions &getConstCodeGenOpts() const { return CodeGenOpts; }
const DependencyOutputOptions &getConstDependencyOutputOpts() const { return DependencyOutputOpts; }
const FileSystemOptions &getConstFileSystemOpts() const { return FileSystemOpts; }
const FrontendOptions &getConstFrontendOpts() const { return FrontendOpts; }
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 41972c7b05f896..ba586fcac6bd29 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -143,6 +143,7 @@ RefBase::RefBase()
DiagnosticOpts(llvm::makeIntrusiveRefCnt<DiagnosticOptions>()),
HeaderSearchOpts(std::make_shared<HeaderSearchOptions>()),
PreprocessorOpts(std::make_shared<PreprocessorOptions>()),
+ CodeGenOpts(std::make_shared<CodeGenOptions>()),
AnalyzerOpts(llvm::makeIntrusiveRefCnt<AnalyzerOptions>()) {}
RefBase::RefBase(const RefBase &X, DeepCopy)
@@ -151,6 +152,7 @@ RefBase::RefBase(const RefBase &X, DeepCopy)
DiagnosticOpts(makeIntrusiveRefCnt(*X.DiagnosticOpts)),
HeaderSearchOpts(make_shared(*X.HeaderSearchOpts)),
PreprocessorOpts(make_shared(*X.PreprocessorOpts)),
+ CodeGenOpts(make_shared(*X.CodeGenOpts)),
AnalyzerOpts(makeIntrusiveRefCnt(*X.AnalyzerOpts)) {}
RefBase::RefBase(const RefBase &X, ShallowCopy)
@@ -159,6 +161,7 @@ RefBase::RefBase(const RefBase &X, ShallowCopy)
DiagnosticOpts(X.DiagnosticOpts), //
HeaderSearchOpts(X.HeaderSearchOpts), //
PreprocessorOpts(X.PreprocessorOpts), //
+ CodeGenOpts(X.CodeGenOpts), //
AnalyzerOpts(X.AnalyzerOpts) {}
RefBase &RefBase::assign(const RefBase &X, DeepCopy) {
@@ -168,6 +171,7 @@ RefBase &RefBase::assign(const RefBase &X, DeepCopy) {
HeaderSearchOpts = make_shared(*X.HeaderSearchOpts);
PreprocessorOpts = make_shared(*X.PreprocessorOpts);
AnalyzerOpts = makeIntrusiveRefCnt(*X.AnalyzerOpts);
+ CodeGenOpts = make_shared(*X.CodeGenOpts);
return *this;
}
@@ -177,6 +181,7 @@ RefBase &RefBase::assign(const RefBase &X, ShallowCopy) {
DiagnosticOpts = X.DiagnosticOpts;
HeaderSearchOpts = X.HeaderSearchOpts;
PreprocessorOpts = X.PreprocessorOpts;
+ CodeGenOpts = X.CodeGenOpts;
AnalyzerOpts = X.AnalyzerOpts;
return *this;
}
@@ -209,6 +214,7 @@ TargetOptions &CowCompilerInvocation::getMutTargetOpts() { return ensure_owned(T
DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() { return ensure_owned(DiagnosticOpts); }
HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() { return ensure_owned(HeaderSearchOpts); }
PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() { return ensure_owned(PreprocessorOpts); }
+CodeGenOptions &CowCompilerInvocation::getMutCodeGenOpts() { return ensure_owned(CodeGenOpts); }
AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() { return ensure_owned(AnalyzerOpts); }
// clang-format on
More information about the cfe-commits
mailing list