Skip to content

Commit dcb7b55

Browse files
jansvoboda11IanWood1
authored andcommitted
[clang] Hide the TargetOptions pointer from CompilerInvocation (llvm#106271)
This PR hides the reference-counted pointer that holds `TargetOptions` from the public API of `CompilerInvocation`. This gives `CompilerInvocation` an exclusive control over the lifetime of this member, which will eventually be leveraged to implement a copy-on-write behavior. There are two clients that currently share ownership of that pointer: * `TargetInfo` - This was refactored to hold a non-owning reference to `TargetOptions`. The options object is typically owned by the `CompilerInvocation` or by the new `CompilerInstance::AuxTargetOpts` for the auxiliary target. This needed a bit of care in `ASTUnit::Parse()` to keep the `CompilerInvocation` alive. * `clangd::PreambleData` - This was refactored to exclusively own the `TargetOptions` that get moved out of the `CompilerInvocation`.
1 parent 23d96fb commit dcb7b55

30 files changed

+50
-39
lines changed

clang-tools-extra/clangd/Preamble.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,10 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
711711
Result->Marks = CapturedInfo.takeMarks();
712712
Result->StatCache = StatCache;
713713
Result->MainIsIncludeGuarded = CapturedInfo.isMainFileIncludeGuarded();
714-
Result->TargetOpts = CI.TargetOpts;
714+
// Move the options instead of copying them. The invocation doesn't need
715+
// them anymore.
716+
Result->TargetOpts =
717+
std::make_unique<TargetOptions>(std::move(CI.getTargetOpts()));
715718
if (PreambleCallback) {
716719
trace::Span Tracer("Running PreambleCallback");
717720
auto Ctx = CapturedInfo.takeLife();
@@ -932,7 +935,7 @@ void PreamblePatch::apply(CompilerInvocation &CI) const {
932935
// ParsedASTTest.PreambleWithDifferentTarget.
933936
// Make sure this is a deep copy, as the same Baseline might be used
934937
// concurrently.
935-
*CI.TargetOpts = *Baseline->TargetOpts;
938+
CI.getTargetOpts() = *Baseline->TargetOpts;
936939

937940
// No need to map an empty file.
938941
if (PatchContents.empty())

clang-tools-extra/clangd/Preamble.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ struct PreambleData {
103103
// Target options used when building the preamble. Changes in target can cause
104104
// crashes when deserializing preamble, this enables consumers to use the
105105
// same target (without reparsing CompileCommand).
106-
std::shared_ptr<TargetOptions> TargetOpts = nullptr;
106+
std::unique_ptr<TargetOptions> TargetOpts = nullptr;
107107
PrecompiledPreamble Preamble;
108108
std::vector<Diag> Diags;
109109
// Processes like code completions and go-to-definitions will need #include

clang-tools-extra/clangd/SystemIncludeExtractor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ bool isValidTarget(llvm::StringRef Triple) {
256256
DiagnosticsEngine Diags(new DiagnosticIDs, new DiagnosticOptions,
257257
new IgnoringDiagConsumer);
258258
llvm::IntrusiveRefCntPtr<TargetInfo> Target =
259-
TargetInfo::CreateTargetInfo(Diags, TargetOpts);
259+
TargetInfo::CreateTargetInfo(Diags, *TargetOpts);
260260
return bool(Target);
261261
}
262262

clang-tools-extra/modularize/ModularizeUtilities.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ ModularizeUtilities::ModularizeUtilities(std::vector<std::string> &InputPaths,
5353
Diagnostics(
5454
new DiagnosticsEngine(DiagIDs, DiagnosticOpts.get(), &DC, false)),
5555
TargetOpts(new ModuleMapTargetOptions()),
56-
Target(TargetInfo::CreateTargetInfo(*Diagnostics, TargetOpts)),
56+
Target(TargetInfo::CreateTargetInfo(*Diagnostics, *TargetOpts)),
5757
FileMgr(new FileManager(FileSystemOpts)),
5858
SourceMgr(new SourceManager(*Diagnostics, *FileMgr, false)), HSOpts(),
5959
HeaderInfo(new HeaderSearch(HSOpts, *SourceMgr, *Diagnostics, *LangOpts,

clang/include/clang/Basic/TargetInfo.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ enum OpenCLTypeKind : uint8_t {
224224
///
225225
class TargetInfo : public TransferrableTargetInfo,
226226
public RefCountedBase<TargetInfo> {
227-
std::shared_ptr<TargetOptions> TargetOpts;
227+
TargetOptions *TargetOpts;
228228
llvm::Triple Triple;
229229
protected:
230230
// Target values set by the ctor of the actual target implementation. Default
@@ -310,10 +310,9 @@ class TargetInfo : public TransferrableTargetInfo,
310310
///
311311
/// \param Opts - The options to use to initialize the target. The target may
312312
/// modify the options to canonicalize the target feature information to match
313-
/// what the backend expects.
314-
static TargetInfo *
315-
CreateTargetInfo(DiagnosticsEngine &Diags,
316-
const std::shared_ptr<TargetOptions> &Opts);
313+
/// what the backend expects. These must outlive the returned TargetInfo.
314+
static TargetInfo *CreateTargetInfo(DiagnosticsEngine &Diags,
315+
TargetOptions &Opts);
317316

318317
virtual ~TargetInfo();
319318

clang/include/clang/Frontend/ASTUnit.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ class ASTUnit {
143143
/// Parse available.
144144
std::shared_ptr<CompilerInvocation> CCInvocation;
145145

146+
/// Optional owned invocation, just used to keep the invocation alive for the
147+
/// members initialized in transferASTDataFromCompilerInstance.
148+
std::shared_ptr<CompilerInvocation> ModifiedInvocation;
149+
146150
/// Fake module loader: the AST unit doesn't need to load any modules.
147151
TrivialModuleLoader ModuleLoader;
148152

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ class CompilerInstance : public ModuleLoader {
8888
/// The target being compiled for.
8989
IntrusiveRefCntPtr<TargetInfo> Target;
9090

91+
/// Options for the auxiliary target.
92+
std::unique_ptr<TargetOptions> AuxTargetOpts;
93+
9194
/// Auxiliary Target info.
9295
IntrusiveRefCntPtr<TargetInfo> AuxTarget;
9396

clang/include/clang/Frontend/CompilerInvocation.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ class CompilerInvocation : public CompilerInvocationBase {
268268
/// Base class internals.
269269
/// @{
270270
using CompilerInvocationBase::LangOpts;
271-
using CompilerInvocationBase::TargetOpts;
272271
std::shared_ptr<LangOptions> getLangOptsPtr() { return LangOpts; }
273272
/// @}
274273

clang/lib/Basic/Targets.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -774,9 +774,10 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
774774
using namespace clang::targets;
775775
/// CreateTargetInfo - Return the target info object for the specified target
776776
/// options.
777-
TargetInfo *
778-
TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
779-
const std::shared_ptr<TargetOptions> &Opts) {
777+
TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
778+
TargetOptions &OptsRef) {
779+
TargetOptions *Opts = &OptsRef;
780+
780781
llvm::Triple Triple(llvm::Triple::normalize(Opts->Triple));
781782

782783
// Construct the target

clang/lib/Frontend/ASTUnit.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ class ASTInfoCollector : public ASTReaderListener {
615615

616616
this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts);
617617
Target =
618-
TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts);
618+
TargetInfo::CreateTargetInfo(PP.getDiagnostics(), *this->TargetOpts);
619619

620620
updated();
621621
return false;
@@ -1499,6 +1499,10 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
14991499
Target = &CI.getTarget();
15001500
Reader = CI.getASTReader();
15011501
HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
1502+
if (Invocation != CI.getInvocationPtr()) {
1503+
// This happens when Parse creates a copy of \c Invocation to modify.
1504+
ModifiedInvocation = CI.getInvocationPtr();
1505+
}
15021506
}
15031507

15041508
StringRef ASTUnit::getMainFileName() const {

0 commit comments

Comments
 (0)