From 78243658c533168d51fd076fba328437932ba6f1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 13 Sep 2011 01:26:44 +0000 Subject: [PATCH] When compiling a module on-demand, re-use the diagnostics client already provided. This required a little bit of clean-up in the way that VerifyDiagnosticsClient managed ownership of its underlying "primary" client, because now it will no longer always take ownership. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139570 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Diagnostic.h | 3 ++ include/clang/Frontend/CompilerInstance.h | 7 ++++- .../clang/Frontend/VerifyDiagnosticsClient.h | 10 +++---- lib/Frontend/CompilerInstance.cpp | 29 +++++++++++++------ lib/Frontend/VerifyDiagnosticsClient.cpp | 20 ++++++++----- tools/arcmt-test/arcmt-test.cpp | 2 +- 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index c02654b2c7..ca0197b14c 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -315,6 +315,9 @@ public: DiagnosticClient *getClient() { return Client; } const DiagnosticClient *getClient() const { return Client; } + /// \brief Determine whether this \c Diagnostic object own its client. + bool ownsClient() const { return OwnsDiagClient; } + /// \brief Return the current diagnostic client along with ownership of that /// client. DiagnosticClient *takeClient() { diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 88f8976b67..c61d6df196 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -457,8 +457,12 @@ public: /// \param Client If non-NULL, a diagnostic client that will be /// attached to (and, then, owned by) the Diagnostic inside this AST /// unit. + /// + /// \param ShouldOwnClient If Client is non-NULL, specifies whether + /// the diagnostic object should take ownership of the client. void createDiagnostics(int Argc, const char* const *Argv, - DiagnosticClient *Client = 0); + DiagnosticClient *Client = 0, + bool ShouldOwnClient = true); /// Create a Diagnostic object with a the TextDiagnosticPrinter. /// @@ -487,6 +491,7 @@ public: createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, DiagnosticClient *Client = 0, + bool ShouldOwnClient = true, const CodeGenOptions *CodeGenOpts = 0); /// Create the file manager and replace any existing one with it. diff --git a/include/clang/Frontend/VerifyDiagnosticsClient.h b/include/clang/Frontend/VerifyDiagnosticsClient.h index 988a589cfe..0c789ff86d 100644 --- a/include/clang/Frontend/VerifyDiagnosticsClient.h +++ b/include/clang/Frontend/VerifyDiagnosticsClient.h @@ -65,7 +65,8 @@ class TextDiagnosticBuffer; class VerifyDiagnosticsClient : public DiagnosticClient { public: Diagnostic &Diags; - llvm::OwningPtr PrimaryClient; + DiagnosticClient *PrimaryClient; + bool OwnsPrimaryClient; llvm::OwningPtr Buffer; Preprocessor *CurrentPreprocessor; @@ -75,10 +76,9 @@ private: public: /// Create a new verifying diagnostic client, which will issue errors to \arg - /// PrimaryClient when a diagnostic does not match what is expected (as - /// indicated in the source file). The verifying diagnostic client takes - /// ownership of \arg PrimaryClient. - VerifyDiagnosticsClient(Diagnostic &Diags, DiagnosticClient *PrimaryClient); + /// the currently-attached diagnostic client when a diagnostic does not match + /// what is expected (as indicated in the source file). + VerifyDiagnosticsClient(Diagnostic &Diags); ~VerifyDiagnosticsClient(); virtual void BeginSourceFile(const LangOptions &LangOpts, diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 1f1a2f77bb..f39b119c32 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -140,15 +140,17 @@ static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts, } void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv, - DiagnosticClient *Client) { + DiagnosticClient *Client, + bool ShouldOwnClient) { Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client, - &getCodeGenOpts()); + ShouldOwnClient, &getCodeGenOpts()); } llvm::IntrusiveRefCntPtr CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, DiagnosticClient *Client, + bool ShouldOwnClient, const CodeGenOptions *CodeGenOpts) { llvm::IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); llvm::IntrusiveRefCntPtr Diags(new Diagnostic(DiagID)); @@ -156,13 +158,13 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, // Create the diagnostic client for reporting errors or for // implementing -verify. if (Client) - Diags->setClient(Client); + Diags->setClient(Client, ShouldOwnClient); else Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts)); // Chain in -verify checker, if requested. - if (Opts.VerifyDiagnostics) - Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient())); + if (Opts.VerifyDiagnostics) + Diags->setClient(new VerifyDiagnosticsClient(*Diags)); // Chain in -diagnostic-log-file dumper, if requested. if (!Opts.DiagnosticLogFile.empty()) @@ -659,6 +661,9 @@ static void compileModule(CompilerInstance &ImportingInstance, FrontendOpts.Inputs.push_back( std::make_pair(getSourceInputKindFromOptions(Invocation->getLangOpts()), UmbrellaHeader)); + + Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; + // FIXME: Strip away all of the compilation options that won't be transferred // down to the module. This presumably includes -D flags, optimization // settings, etc. @@ -667,9 +672,9 @@ static void compileModule(CompilerInstance &ImportingInstance, // module. CompilerInstance Instance; Instance.setInvocation(&*Invocation); - // Instance.setDiagnostics(&ImportingInstance.getDiagnostics()); - // FIXME: Need to route diagnostics over to the same diagnostic client! - Instance.createDiagnostics(0, 0, 0); + Instance.createDiagnostics(/*argc=*/0, /*argv=*/0, + &ImportingInstance.getDiagnosticClient(), + /*ShouldOwnClient=*/false); // Construct a module-generating action. GeneratePCHAction CreateModuleAction(true); @@ -681,7 +686,13 @@ static void compileModule(CompilerInstance &ImportingInstance, // Tell the importing instance's file manager to forget about the module // file, since we've just created it. ImportingInstance.getFileManager().forgetFile(ModuleFile); -} + + // Tell the diagnostic client that it's (re-)starting to process a source + // file. + ImportingInstance.getDiagnosticClient() + .BeginSourceFile(ImportingInstance.getLangOpts(), + &ImportingInstance.getPreprocessor()); +} ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc, IdentifierInfo &ModuleName, diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp index 16c945b417..f53e0dac23 100644 --- a/lib/Frontend/VerifyDiagnosticsClient.cpp +++ b/lib/Frontend/VerifyDiagnosticsClient.cpp @@ -20,14 +20,19 @@ #include "llvm/Support/raw_ostream.h" using namespace clang; -VerifyDiagnosticsClient::VerifyDiagnosticsClient(Diagnostic &_Diags, - DiagnosticClient *_Primary) - : Diags(_Diags), PrimaryClient(_Primary), - Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0) { +VerifyDiagnosticsClient::VerifyDiagnosticsClient(Diagnostic &_Diags) + : Diags(_Diags), PrimaryClient(Diags.getClient()), + OwnsPrimaryClient(Diags.ownsClient()), + Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0) +{ + Diags.takeClient(); } VerifyDiagnosticsClient::~VerifyDiagnosticsClient() { - CheckDiagnostics(); + CheckDiagnostics(); + Diags.takeClient(); + if (OwnsPrimaryClient) + delete PrimaryClient; } // DiagnosticClient interface. @@ -477,8 +482,9 @@ void VerifyDiagnosticsClient::CheckDiagnostics() { ExpectedData ED; // Ensure any diagnostics go to the primary client. + bool OwnsCurClient = Diags.ownsClient(); DiagnosticClient *CurClient = Diags.takeClient(); - Diags.setClient(PrimaryClient.get()); + Diags.setClient(PrimaryClient, false); // If we have a preprocessor, scan the source for expected diagnostic // markers. If not then any diagnostics are unexpected. @@ -513,7 +519,7 @@ void VerifyDiagnosticsClient::CheckDiagnostics() { } Diags.takeClient(); - Diags.setClient(CurClient); + Diags.setClient(CurClient, OwnsCurClient); // Reset the buffer, we have processed all the diagnostics in it. Buffer.reset(new TextDiagnosticBuffer()); diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp index 7477f943ee..aa229d5516 100644 --- a/tools/arcmt-test/arcmt-test.cpp +++ b/tools/arcmt-test/arcmt-test.cpp @@ -112,7 +112,7 @@ static bool checkForMigration(StringRef resourcesPath, // Chain in -verify checker, if requested. VerifyDiagnosticsClient *verifyDiag = 0; if (VerifyDiags) { - verifyDiag = new VerifyDiagnosticsClient(*Diags, Diags->takeClient()); + verifyDiag = new VerifyDiagnosticsClient(*Diags); Diags->setClient(verifyDiag); } -- 2.40.0