diff options
author | Sam McCall <sam.mccall@gmail.com> | 2019-12-09 11:57:23 +0100 |
---|---|---|
committer | Sam McCall <sam.mccall@gmail.com> | 2019-12-09 14:34:31 +0100 |
commit | 94603ec11b55ca22b5dbebcfca5e83f313b632e3 (patch) | |
tree | b2b8cf74954574d58f258783753ff202b86ae279 | |
parent | c20930a724f9ecaa6ef4bea819f5ce5115506107 (diff) | |
download | bcm5719-llvm-94603ec11b55ca22b5dbebcfca5e83f313b632e3.tar.gz bcm5719-llvm-94603ec11b55ca22b5dbebcfca5e83f313b632e3.zip |
[Parser] Don't crash on MS assembly if target desc/asm parser isn't linked in.
Summary:
Instead, emit a diagnostic and return an empty ASM node, as we do if the target
is missing.
Filter this diagnostic out in clangd, where it's not meaningful.
Fixes https://github.com/clangd/clangd/issues/222
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71189
-rw-r--r-- | clang-tools-extra/clangd/Diagnostics.cpp | 9 | ||||
-rw-r--r-- | clang-tools-extra/clangd/unittests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmtAsm.cpp | 28 |
4 files changed, 43 insertions, 5 deletions
diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index cd95807162b..f97191196e7 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -73,6 +73,13 @@ bool mentionsMainFile(const Diag &D) { return false; } +bool isBlacklisted(const Diag &D) { + // clang will always fail to MS ASM as we don't link in desc + asm parser. + if (D.ID == clang::diag::err_msasm_unable_to_create_target) + return true; + return false; +} + // Checks whether a location is within a half-open range. // Note that clang also uses closed source ranges, which this can't handle! bool locationInRange(SourceLocation L, CharSourceRange R, @@ -642,7 +649,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, void StoreDiags::flushLastDiag() { if (!LastDiag) return; - if (mentionsMainFile(*LastDiag) && + if (!isBlacklisted(*LastDiag) && mentionsMainFile(*LastDiag) && (!LastDiagWasAdjusted || // Only report the first diagnostic coming from each particular header. IncludeLinesWithErrors.insert(LastDiag->Range.start.line).second)) { diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index d2a689056ec..f8b24c60696 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS support + AllTargetsInfos ) get_filename_component(CLANGD_SOURCE_DIR diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 3c025784902..0941af25213 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticSema.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetSelect.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include <algorithm> @@ -405,6 +406,15 @@ TEST(DiagnosticsTest, NoFixItInMacro) { Not(WithFix(_))))); } +TEST(ClangdTest, MSAsm) { + // Parsing MS assembly tries to use the target MCAsmInfo, which we don't link. + // We used to crash here. Now clang emits a diagnostic, which we filter out. + llvm::InitializeAllTargetInfos(); // As in ClangdMain + auto TU = TestTU::withCode("void fn() { __asm { cmp cl,64 } }"); + TU.ExtraArgs = {"-fms-extensions"}; + EXPECT_THAT(TU.build().getDiagnostics(), IsEmpty()); +} + TEST(DiagnosticsTest, ToLSP) { URIForFile MainFile = URIForFile::canonicalize(testPath("foo/bar/main.cpp"), ""); diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp index 6b301667d3f..98133aaf67a 100644 --- a/clang/lib/Parse/ParseStmtAsm.cpp +++ b/clang/lib/Parse/ParseStmtAsm.cpp @@ -563,16 +563,19 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { assert(!LBraceLocs.empty() && "Should have at least one location here"); + SmallString<512> AsmString; + auto EmptyStmt = [&] { + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmString, + /*NumOutputs*/ 0, /*NumInputs*/ 0, + ConstraintRefs, ClobberRefs, Exprs, EndLoc); + }; // If we don't support assembly, or the assembly is empty, we don't // need to instantiate the AsmParser, etc. if (!TheTarget || AsmToks.empty()) { - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(), - /*NumOutputs*/ 0, /*NumInputs*/ 0, - ConstraintRefs, ClobberRefs, Exprs, EndLoc); + return EmptyStmt(); } // Expand the tokens into a string buffer. - SmallString<512> AsmString; SmallVector<unsigned, 8> TokOffsets; if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString)) return StmtError(); @@ -582,6 +585,11 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { llvm::join(TO.Features.begin(), TO.Features.end(), ","); std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); + if (!MRI) { + Diag(AsmLoc, diag::err_msasm_unable_to_create_target) + << "target MC unavailable"; + return EmptyStmt(); + } // FIXME: init MCOptions from sanitizer flags here. llvm::MCTargetOptions MCOptions; std::unique_ptr<llvm::MCAsmInfo> MAI( @@ -591,6 +599,12 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); std::unique_ptr<llvm::MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TT, TO.CPU, FeaturesStr)); + // Target MCTargetDesc may not be linked in clang-based tools. + if (!MAI || !MII | !MOFI || !STI) { + Diag(AsmLoc, diag::err_msasm_unable_to_create_target) + << "target MC unavailable"; + return EmptyStmt(); + } llvm::SourceMgr TempSrcMgr; llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); @@ -607,6 +621,12 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { std::unique_ptr<llvm::MCTargetAsmParser> TargetParser( TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions)); + // Target AsmParser may not be linked in clang-based tools. + if (!TargetParser) { + Diag(AsmLoc, diag::err_msasm_unable_to_create_target) + << "target ASM parser unavailable"; + return EmptyStmt(); + } std::unique_ptr<llvm::MCInstPrinter> IP( TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI)); |