jansvoboda11 created this revision.
jansvoboda11 added reviewers: Bigcheese, dexonsmith.
jansvoboda11 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
The `CompilerInvocationBase` class factors out members of `CompilerInvocation`
that need special handling (initialization or copy constructor), so that
`CompilerInvocation` can be implemented as a simple value object.
Currently, the `AnalyzerOpts` member of `CompilerInvocation` violates that
setup. This patch extracts the member to `CompilerInvocationBase` and handles
it in the copy constructor the same way other it handles other members.
Moreover, this patch adds a copy-assignment operator to
`CompilerInvocationBase`, making the whole `CompilerInvocation`
copy-assignable. This will prove useful in a follow-up patch.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D99568
Files:
clang/include/clang/Frontend/CompilerInvocation.h
clang/lib/Frontend/CompilerInvocation.cpp
clang/unittests/Frontend/CompilerInvocationTest.cpp
Index: clang/unittests/Frontend/CompilerInvocationTest.cpp
===================================================================
--- clang/unittests/Frontend/CompilerInvocationTest.cpp
+++ clang/unittests/Frontend/CompilerInvocationTest.cpp
@@ -97,6 +97,29 @@
ASSERT_THAT(Array, ContainsN(StrEq("x"), 2));
}
+// Copy constructor/assignment do a deep copy of reference-counted pointers.
+
+TEST(CompilerInvocationTest, DeepCopyConstructor) {
+ CompilerInvocation A;
+ A.getAnalyzerOpts()->Config["Foo"] = "Original";
+
+ CompilerInvocation B(A);
+ B.getAnalyzerOpts()->Config["Foo"] = "New";
+
+ ASSERT_EQ(A.getAnalyzerOpts()->Config["Foo"], "Original");
+}
+
+TEST(CompilerInvocationTest, DeepCopyAssignment) {
+ CompilerInvocation A;
+ A.getAnalyzerOpts()->Config["Foo"] = "Original";
+
+ CompilerInvocation B;
+ B = A;
+ B.getAnalyzerOpts()->Config["Foo"] = "New";
+
+ ASSERT_EQ(A.getAnalyzerOpts()->Config["Foo"], "Original");
+}
+
// Boolean option with a keypath that defaults to true.
// The only flag with a negative spelling can set the keypath to false.
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -113,14 +113,28 @@
: LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
DiagnosticOpts(new DiagnosticOptions()),
HeaderSearchOpts(new HeaderSearchOptions()),
- PreprocessorOpts(new PreprocessorOptions()) {}
+ PreprocessorOpts(new PreprocessorOptions()),
+ AnalyzerOpts(new AnalyzerOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &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())) {}
+ PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())),
+ AnalyzerOpts(new AnalyzerOptions(*X.getAnalyzerOpts())) {}
+
+CompilerInvocationBase &
+CompilerInvocationBase::operator=(CompilerInvocationBase 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);
+
+ return *this;
+}
CompilerInvocationBase::~CompilerInvocationBase() = default;
Index: clang/include/clang/Frontend/CompilerInvocation.h
===================================================================
--- clang/include/clang/Frontend/CompilerInvocation.h
+++ clang/include/clang/Frontend/CompilerInvocation.h
@@ -78,9 +78,12 @@
/// Options controlling the preprocessor (aside from \#include handling).
std::shared_ptr<PreprocessorOptions> PreprocessorOpts;
+ /// Options controlling the static analyzer.
+ AnalyzerOptionsRef AnalyzerOpts;
+
CompilerInvocationBase();
CompilerInvocationBase(const CompilerInvocationBase &X);
- CompilerInvocationBase &operator=(const CompilerInvocationBase &) = delete;
+ CompilerInvocationBase &operator=(CompilerInvocationBase X);
~CompilerInvocationBase();
LangOptions *getLangOpts() { return LangOpts.get(); }
@@ -110,6 +113,8 @@
const PreprocessorOptions &getPreprocessorOpts() const {
return *PreprocessorOpts;
}
+
+ AnalyzerOptionsRef getAnalyzerOpts() const { return AnalyzerOpts; }
};
/// Helper class for holding the data necessary to invoke the compiler.
@@ -118,9 +123,6 @@
/// compiler, including data such as the include paths, the code generation
/// options, the warning flags, and so on.
class CompilerInvocation : public CompilerInvocationBase {
- /// Options controlling the static analyzer.
- AnalyzerOptionsRef AnalyzerOpts;
-
MigratorOptions MigratorOpts;
/// Options controlling IRgen and the backend.
@@ -139,8 +141,6 @@
PreprocessorOutputOptions PreprocessorOutputOpts;
public:
- CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {}
-
/// @name Utility Methods
/// @{
@@ -203,8 +203,6 @@
/// @name Option Subgroups
/// @{
- AnalyzerOptionsRef getAnalyzerOpts() const { return AnalyzerOpts; }
-
MigratorOptions &getMigratorOpts() { return MigratorOpts; }
const MigratorOptions &getMigratorOpts() const { return MigratorOpts; }
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits