Index: test/MC/ARM/verify-diagnostics-all-matching.s =================================================================== --- test/MC/ARM/verify-diagnostics-all-matching.s +++ test/MC/ARM/verify-diagnostics-all-matching.s @@ -25,4 +25,6 @@ foo; bar // expected-error {{invalid instruction}} // expected-error@-1 {{invalid instruction}} + foo; bar // expected-error:3 {{invalid instruction}} expected-error:8 {{invalid instruction}} + // CHECK-NOT: error Index: test/MC/ARM/verify-diagnostics-column-number.s =================================================================== --- /dev/null +++ test/MC/ARM/verify-diagnostics-column-number.s @@ -0,0 +1,8 @@ +// RUN: not llvm-mc -triple armv7a--none-eabi < %s -verify-asm-diags 2>&1 | FileCheck %s + + foo // expected-error:3 {{invalid instruction}} +// CHECK-NOT: error + + foo // expected-error:4 {{invalid instruction}} +// CHECK-DAG: :[[@LINE-1]]:3: error: 'error' seen but not expected: invalid instruction +// CHECK-DAG: :[[@LINE-2]]:10: error: 'error' expected but not seen: invalid instruction Index: test/MC/ARM/verify-diagnostics-comment-parsing.s =================================================================== --- test/MC/ARM/verify-diagnostics-comment-parsing.s +++ test/MC/ARM/verify-diagnostics-comment-parsing.s @@ -14,3 +14,12 @@ // expected-error {{ // CHECK: :[[@LINE-1]]:21: error: cannot find end ('}}') of expected string + +// expected-error@a {{message}} +// CHECK: :[[@LINE-1]]:19: error: expected integer line number or offset + +// expected-error:a {{message}} +// CHECK: :[[@LINE-1]]:19: error: expected integer column number + +// expected-error@+4:a {{message}} +// CHECK: :[[@LINE-1]]:22: error: expected integer column number Index: tools/llvm-mc/llvm-mc.cpp =================================================================== --- tools/llvm-mc/llvm-mc.cpp +++ tools/llvm-mc/llvm-mc.cpp @@ -421,6 +421,9 @@ SourceMgr::DiagKind Kind; // The line number on which the diagnostic was seen or is expected. int LineNo; + // The column number at which the diagnostic was seen or is expected, or 0 + // for a diagnostic expected at any point on the line. + int ColumnNo; // The exact location at which the diagnostic was reported, or the expected // diagnostic was described. This is just used for emitting our own // diagnostics, as we wouldn't expect the expected and actual locations to @@ -433,15 +436,30 @@ // Constructor for an actually emitted diagnostic. PendingDiag(const SMDiagnostic &Diag) : DiagText(Diag.getMessage()), Kind(Diag.getKind()), - LineNo(Diag.getLineNo()), Loc(Diag.getLoc()), Matched(false) {} + LineNo(Diag.getLineNo()), ColumnNo(Diag.getColumnNo()+1), + Loc(Diag.getLoc()), Matched(false) {} // Constructor for an expected diagnostic. - PendingDiag(unsigned LineNo, StringRef ExpectedText, + PendingDiag(unsigned LineNo, unsigned ColumnNo, StringRef ExpectedText, SourceMgr::DiagKind Kind, SMLoc Loc) - : DiagText(ExpectedText), Kind(Kind), LineNo(LineNo), Loc(Loc), - Matched(false) {} + : DiagText(ExpectedText), Kind(Kind), LineNo(LineNo), + ColumnNo(ColumnNo), Loc(Loc), Matched(false) {} bool operator<(const PendingDiag &RHS) const { return LineNo < RHS.LineNo; } + + // Returns true if this expected diagnostic matches SeenDiag, and has not + // previously been matched agains a diagnostic. + bool Matches(const PendingDiag &SeenDiag) const { + if (Matched) + return false; + if (SeenDiag.DiagText.find(DiagText) == std::string::npos) + return false; + if (Kind != SeenDiag.Kind) + return false; + if (ColumnNo != 0 && ColumnNo != SeenDiag.ColumnNo) + return false; + return true; + } }; SourceMgr &SrcMgr; @@ -570,6 +588,20 @@ PH.SkipWhitespace(); + // Parse optional column number + unsigned ColumnNo = 0; + if (PH.Next(":")) { + PH.Advance(); + if (!PH.Next(ColumnNo)) { + ReportError(getCurrentLoc(Loc, PH), + "expected integer column number"); + continue; + } + PH.Advance(); + } + + PH.SkipWhitespace(); + // Parse the expected diagnostic text. if (!PH.Next("{{")) { ReportError(getCurrentLoc(Loc, PH), @@ -589,8 +621,8 @@ PH.Advance(); ExpectedDiags.push_back(PendingDiag( - LineNo, StringRef(ContentBegin, ContentEnd - ContentBegin), Kind, - DirectiveLoc)); + LineNo, ColumnNo, StringRef(ContentBegin, ContentEnd - ContentBegin), + Kind, DirectiveLoc)); } } @@ -639,10 +671,8 @@ // Iterate over seen diags, checking for a matching expected diag. for (; SeenIt != SeenNextLine; ++SeenIt) { auto ExpectedMatch = std::find_if(ExpectedIt, ExpectedNextLine, - [SeenIt](PendingDiag &Expected) { - return SeenIt->DiagText.find(Expected.DiagText) != - std::string::npos && - SeenIt->Kind == Expected.Kind && !Expected.Matched; + [SeenIt](const PendingDiag &Expected) { + return Expected.Matches(*SeenIt); }); if (ExpectedMatch != ExpectedNextLine) { ExpectedMatch->Matched = true;