]> granicus.if.org Git - clang/commitdiff
Simplify the ownership model for DiagnosticClients, which was really
authorDouglas Gregor <dgregor@apple.com>
Wed, 18 Aug 2010 22:29:43 +0000 (22:29 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 18 Aug 2010 22:29:43 +0000 (22:29 +0000)
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

include/clang/Basic/Diagnostic.h
include/clang/Frontend/ASTUnit.h
include/clang/Frontend/CompilerInstance.h
lib/Frontend/ASTUnit.cpp
lib/Frontend/CompilerInstance.cpp
lib/Frontend/VerifyDiagnosticsClient.cpp
lib/Rewrite/FixItRewriter.cpp
tools/driver/cc1_main.cpp
tools/driver/cc1as_main.cpp
tools/driver/driver.cpp

index 6eafa03b97a3cf92ae481d2565c88808d5c98a02..37d26947c335083c0f761b09dde3d5f50322570a 100644 (file)
@@ -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.
index de10611314d5cd9d87698bce975f847de3123cb0..c05fee1fc876b957f2c4156376cfa57e42058b55 100644 (file)
@@ -59,6 +59,7 @@ class ASTUnit {
 public:
   typedef std::map<FileID, std::vector<PreprocessedEntity *> > 
     PreprocessedEntitiesByFileMap;
+  
 private:
   llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
   llvm::OwningPtr<FileManager>      FileMgr;
index 2a0a7a7747bb97ff83e53f83ee7734f738e8d8fa..e09061dbbdcd9ec6271b8fe5f1f34cb82d32427b 100644 (file)
@@ -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
   /// {
index 019d25c131fc21c8cdbc833861a5efe9a5203186..28cdc5292241010481459c0fadf7eb90e162c05f 100644 (file)
@@ -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();
 }
index aaa67804cefd7cf15e9fd8aa8ce992ba770aa63b..5db612542f1eddd40e0ba0d8f961f8bbb1f2717b 100644 (file)
@@ -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);
 
index ae36481444da0406eaa6b718f50d34a96798233a..c7c84c1a5d05e34cc7ca63f388979f13460ba1f8 100644 (file)
@@ -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.
index 3fdec07459d6bde792c5fc181e6592e66ceade94..582096978d7bcee0a05e004218d1b9338cd8ce09 100644 (file)
@@ -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);
 }
 
index bfdcefbb24e36a7bf9f69867295e10f55144ef51..2cab8da24bede0019ae58858ee2924552bce60d8 100644 (file)
@@ -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());
index 4620b605fb052bc45513a34ca4bdd7cee5445f86..b8f2b687883dcc260af24898aeab770c1c4bd665 100644 (file)
@@ -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.
index 0e99314e24e2bc19c4035ce6cb59a31beb998941..c058ece0dc9b560c08de2983a325a31199df34bf 100644 (file)
@@ -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;