Simplify the ownership model for DiagnosticClients, which was really

convoluted and a bit leaky. Now, the Diagnostic object owns its
DiagnosticClient.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111437 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2010-08-18 22:29:43 +00:00
Родитель 421649bacb
Коммит bdbb004f38
10 изменённых файлов: 57 добавлений и 64 удалений

Просмотреть файл

@ -16,6 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/type_traits.h"
#include <string>
@ -202,8 +203,8 @@ private:
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
// 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
DiagnosticClient *Client;
llvm::OwningPtr<DiagnosticClient> Client;
/// DiagMappings - Mapping information for diagnostics. Mapping info is
/// packed into four bits per diagnostic. The low three bits are the mapping
/// (an instance of diag::Mapping), or zero if unset. The high bit is set
@ -285,8 +286,12 @@ public:
// Diagnostic characterization methods, used by a client to customize how
//
DiagnosticClient *getClient() { return Client; }
const DiagnosticClient *getClient() const { return Client; }
DiagnosticClient *getClient() { return Client.get(); }
const DiagnosticClient *getClient() const { return Client.get(); }
/// \brief Return the current diagnostic client along with ownership of that
/// client.
DiagnosticClient *takeClient() { return Client.take(); }
/// pushMappings - Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack.
@ -298,7 +303,10 @@ public:
/// stack.
bool popMappings();
void setClient(DiagnosticClient* client) { Client = client; }
/// \brief Set the diagnostic client associated with this diagnostic object.
///
/// The diagnostic object takes ownership of \c client.
void setClient(DiagnosticClient* client) { Client.reset(client); }
/// setErrorLimit - Specify a limit for the number of errors we should
/// emit before giving up. Zero disables the limit.

Просмотреть файл

@ -59,6 +59,7 @@ class ASTUnit {
public:
typedef std::map<FileID, std::vector<PreprocessedEntity *> >
PreprocessedEntitiesByFileMap;
private:
llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
llvm::OwningPtr<FileManager> FileMgr;

Просмотреть файл

@ -68,9 +68,6 @@ class CompilerInstance {
/// The diagnostics engine instance.
llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
/// The diagnostics client instance.
llvm::OwningPtr<DiagnosticClient> DiagClient;
/// The target being compiled for.
llvm::OwningPtr<TargetInfo> Target;
@ -266,18 +263,11 @@ public:
void setDiagnostics(Diagnostic *Value);
DiagnosticClient &getDiagnosticClient() const {
assert(DiagClient && "Compiler instance has no diagnostic client!");
return *DiagClient;
assert(Diagnostics && Diagnostics->getClient() &&
"Compiler instance has no diagnostic client!");
return *Diagnostics->getClient();
}
/// takeDiagnosticClient - Remove the current diagnostics client and give
/// ownership to the caller.
DiagnosticClient *takeDiagnosticClient() { return DiagClient.take(); }
/// setDiagnosticClient - Replace the current diagnostics client; the compiler
/// instance takes ownership of \arg Value.
void setDiagnosticClient(DiagnosticClient *Value);
/// }
/// @name Target Info
/// {

Просмотреть файл

@ -371,14 +371,19 @@ class CaptureDroppedDiagnostics {
public:
CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
: Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient())
: Diags(Diags), Client(StoredDiags), PreviousClient(0)
{
if (RequestCapture || Diags.getClient() == 0)
if (RequestCapture || Diags.getClient() == 0) {
PreviousClient = Diags.takeClient();
Diags.setClient(&Client);
}
}
~CaptureDroppedDiagnostics() {
Diags.setClient(PreviousClient);
if (Diags.getClient() == &Client) {
Diags.takeClient();
Diags.setClient(PreviousClient);
}
}
};
@ -654,15 +659,12 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
getDiagnostics(),
StoredDiagnostics);
Clang.setDiagnosticClient(getDiagnostics().getClient());
// Create the target instance.
Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
Clang.getTargetOpts()));
if (!Clang.hasTarget()) {
Clang.takeDiagnosticClient();
if (!Clang.hasTarget())
return true;
}
// Inform the target of the language options.
//
@ -754,8 +756,6 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
}
Clang.takeDiagnosticClient();
Invocation.reset(Clang.takeInvocation());
// If we were asked to cache code-completion results and don't have any
@ -776,7 +776,6 @@ error:
Clang.takeSourceManager();
Clang.takeFileManager();
Clang.takeDiagnosticClient();
Invocation.reset(Clang.takeInvocation());
return true;
}
@ -1123,13 +1122,11 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
getDiagnostics(),
StoredDiagnostics);
Clang.setDiagnosticClient(getDiagnostics().getClient());
// Create the target instance.
Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
Clang.getTargetOpts()));
if (!Clang.hasTarget()) {
Clang.takeDiagnosticClient();
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
Preamble.clear();
if (CreatedPreambleBuffer)
@ -1168,7 +1165,6 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Act.reset(new PrecompilePreambleAction(*this));
if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
Clang.getFrontendOpts().Inputs[0].first)) {
Clang.takeDiagnosticClient();
Clang.takeInvocation();
llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
Preamble.clear();
@ -1183,7 +1179,6 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Act->Execute();
Act->EndSourceFile();
Clang.takeDiagnosticClient();
Clang.takeInvocation();
if (Diagnostics->hasErrorOccurred()) {
@ -1321,11 +1316,14 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
bool PrecompilePreamble,
bool CompleteTranslationUnit,
bool CacheCodeCompletionResults) {
bool CreatedDiagnosticsObject = false;
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
DiagnosticOptions DiagOpts;
Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
CreatedDiagnosticsObject = true;
}
llvm::SmallVector<const char *, 16> Args;
@ -1678,14 +1676,14 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
CaptureDroppedDiagnostics Capture(true,
Clang.getDiagnostics(),
StoredDiagnostics);
Clang.setDiagnosticClient(Diag.getClient());
// Create the target instance.
Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
Clang.getTargetOpts()));
if (!Clang.hasTarget()) {
Clang.takeDiagnosticClient();
Clang.takeInvocation();
CCInvocation.getLangOpts().SpellChecking = SpellChecking;
return;
}
// Inform the target of the language options.
@ -1773,7 +1771,6 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
Clang.takeFileManager();
Clang.takeSourceManager();
Clang.takeInvocation();
Clang.takeDiagnosticClient();
Clang.takeCodeCompletionConsumer();
CCInvocation.getLangOpts().SpellChecking = SpellChecking;
}
@ -1796,7 +1793,8 @@ bool ASTUnit::Save(llvm::StringRef File) {
Writer.WritePCH(getSema(), 0, 0);
// Write the generated bitstream to "Out".
Out.write((char *)&Buffer.front(), Buffer.size());
if (!Buffer.empty())
Out.write((char *)&Buffer.front(), Buffer.size());
Out.close();
return Out.has_error();
}

Просмотреть файл

@ -56,10 +56,6 @@ void CompilerInstance::setDiagnostics(Diagnostic *Value) {
Diagnostics = Value;
}
void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
DiagClient.reset(Value);
}
void CompilerInstance::setTarget(TargetInfo *Value) {
Target.reset(Value);
}
@ -131,14 +127,11 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
// Chain in a diagnostic client which will log the diagnostics.
DiagnosticClient *Logger =
new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
Diags.setClient(new ChainedDiagnosticClient(Diags.getClient(), Logger));
Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
}
void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv);
if (Diagnostics)
DiagClient.reset(Diagnostics->getClient());
}
llvm::IntrusiveRefCntPtr<Diagnostic>
@ -155,22 +148,20 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
// bit of a problem. So, just create a text diagnostic printer
// to complain about this problem, and pretend that the user
// didn't try to use binary output.
DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
Diags->setClient(DiagClient.take());
Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
Diags->Report(diag::err_fe_stderr_binary);
return Diags;
} else {
DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
Diags->setClient(new BinaryDiagnosticSerializer(llvm::errs()));
}
} else {
DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
}
// Chain in -verify checker, if requested.
if (Opts.VerifyDiagnostics)
DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient()));
Diags->setClient(DiagClient.take());
if (!Opts.DumpBuildInformation.empty())
SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);

Просмотреть файл

@ -484,7 +484,7 @@ void VerifyDiagnosticsClient::CheckDiagnostics() {
ExpectedData ED;
// Ensure any diagnostics go to the primary client.
DiagnosticClient *CurClient = Diags.getClient();
DiagnosticClient *CurClient = Diags.takeClient();
Diags.setClient(PrimaryClient.get());
// If we have a preprocessor, scan the source for expected diagnostic
@ -507,6 +507,7 @@ void VerifyDiagnosticsClient::CheckDiagnostics() {
"note", false));
}
Diags.takeClient();
Diags.setClient(CurClient);
// Reset the buffer, we have processed all the diagnostics in it.

Просмотреть файл

@ -32,11 +32,12 @@ FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
Rewrite(SourceMgr, LangOpts),
FixItOpts(FixItOpts),
NumFailures(0) {
Client = Diags.getClient();
Client = Diags.takeClient();
Diags.setClient(this);
}
FixItRewriter::~FixItRewriter() {
Diags.takeClient();
Diags.setClient(Client);
}
@ -144,9 +145,11 @@ void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
// When producing this diagnostic, we temporarily bypass ourselves,
// clear out any current diagnostic, and let the downstream client
// format the diagnostic.
Diags.takeClient();
Diags.setClient(Client);
Diags.Clear();
Diags.Report(Loc, DiagID);
Diags.takeClient();
Diags.setClient(this);
}

Просмотреть файл

@ -121,8 +121,8 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
// Run clang -cc1 test.
if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
Diagnostic Diags(&DiagClient);
Diagnostic Diags(new TextDiagnosticPrinter(llvm::errs(),
DiagnosticOptions()));
return cc1_test(Diags, ArgBegin + 1, ArgEnd);
}
@ -133,8 +133,8 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
// Buffer diagnostics from argument parsing so that we can output them using a
// well formed diagnostic object.
TextDiagnosticBuffer DiagsBuffer;
Diagnostic Diags(&DiagsBuffer);
TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
Diagnostic Diags(DiagsBuffer);
CompilerInvocation::CreateFromArgs(Clang->getInvocation(), ArgBegin, ArgEnd,
Diags);
@ -154,7 +154,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
llvm::install_fatal_error_handler(LLVMErrorHandler,
static_cast<void*>(&Clang->getDiagnostics()));
DiagsBuffer.FlushDiagnostics(Clang->getDiagnostics());
DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
// Execute the frontend actions.
bool Success = ExecuteCompilerInvocation(Clang.get());

Просмотреть файл

@ -321,9 +321,10 @@ int cc1as_main(const char **ArgBegin, const char **ArgEnd,
InitializeAllAsmParsers();
// Construct our diagnostic client.
TextDiagnosticPrinter DiagClient(errs(), DiagnosticOptions());
DiagClient.setPrefix("clang -cc1as");
Diagnostic Diags(&DiagClient);
TextDiagnosticPrinter *DiagClient
= new TextDiagnosticPrinter(errs(), DiagnosticOptions());
DiagClient->setPrefix("clang -cc1as");
Diagnostic Diags(DiagClient);
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.

Просмотреть файл

@ -285,10 +285,10 @@ int main(int argc_, const char **argv_) {
llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
DiagClient.setPrefix(Path.getBasename());
Diagnostic Diags(&DiagClient);
TextDiagnosticPrinter *DiagClient
= new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
DiagClient->setPrefix(Path.getBasename());
Diagnostic Diags(DiagClient);
#ifdef CLANG_IS_PRODUCTION
const bool IsProduction = true;