Index: clang/lib/Frontend/ASTUnit.cpp =================================================================== --- clang/lib/Frontend/ASTUnit.cpp +++ clang/lib/Frontend/ASTUnit.cpp @@ -1118,6 +1118,18 @@ std::unique_ptr Clang( new CompilerInstance(std::move(PCHContainerOps))); + auto OnError = [&]() { + // Remove the overridden buffer we used for the preamble. + SavedMainFileBuffer = nullptr; + + // Keep the ownership of the data in the ASTUnit because the client may + // want to see the diagnostics. + transferASTDataFromCompilerInstance(*Clang); + FailedParseDiagnostics.swap(StoredDiagnostics); + StoredDiagnostics.clear(); + NumStoredDiagnosticsFromDriver = 0; + }; + // Ensure that Clang has a FileManager with the right VFS, which may have // changed above in AddImplicitPreamble. If VFS is nullptr, rely on // createFileManager to create one. @@ -1141,8 +1153,10 @@ // Create the target instance. Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); - if (!Clang->hasTarget()) + if (!Clang->hasTarget()) { + OnError(); return true; + } // Inform the target of the language options. // @@ -1199,8 +1213,10 @@ llvm::CrashRecoveryContextCleanupRegistrar ActCleanup(Act.get()); - if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) - goto error; + if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { + OnError(); + return true; + } if (SavedMainFileBuffer) TranslateStoredDiagnostics(getFileManager(), getSourceManager(), @@ -1210,7 +1226,8 @@ if (llvm::Error Err = Act->Execute()) { consumeError(std::move(Err)); // FIXME this drops errors on the floor. - goto error; + OnError(); + return true; } transferASTDataFromCompilerInstance(*Clang); @@ -1220,18 +1237,6 @@ FailedParseDiagnostics.clear(); return false; - -error: - // Remove the overridden buffer we used for the preamble. - SavedMainFileBuffer = nullptr; - - // Keep the ownership of the data in the ASTUnit because the client may - // want to see the diagnostics. - transferASTDataFromCompilerInstance(*Clang); - FailedParseDiagnostics.swap(StoredDiagnostics); - StoredDiagnostics.clear(); - NumStoredDiagnosticsFromDriver = 0; - return true; } static std::pair Index: clang/unittests/Frontend/ASTUnitTest.cpp =================================================================== --- clang/unittests/Frontend/ASTUnitTest.cpp +++ clang/unittests/Frontend/ASTUnitTest.cpp @@ -111,4 +111,28 @@ llvm::MemoryBuffer::MemoryBuffer_MMap); } +TEST_F(ASTUnitTest, LoadFromCommandLineEarlyError) { + EXPECT_FALSE( + llvm::sys::fs::createTemporaryFile("ast-unit", "c", FD, InputFileName)); + input_file = std::make_unique(InputFileName, FD); + input_file->os() << ""; + + const char *Args[] = {"clang", "-target", "foobar", InputFileName.c_str()}; + + auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); + auto PCHContainerOps = std::make_shared(); + std::unique_ptr ErrUnit; + + ASTUnit *AST = ASTUnit::LoadFromCommandLine( + &Args[0], &Args[4], PCHContainerOps, Diags, "", false, + CaptureDiagsKind::All, None, true, 0, TU_Complete, false, false, false, + SkipFunctionBodiesScope::None, false, true, false, false, None, &ErrUnit, + nullptr); + + ASSERT_EQ(AST, nullptr); + ASSERT_NE(ErrUnit, nullptr); + ASSERT_TRUE(Diags->hasErrorOccurred()); + ASSERT_NE(ErrUnit->stored_diag_size(), 0U); +} + } // anonymous namespace