Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GCC linker errors not showing up in Problems View #3950

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Bug Fixes:
- Fix our keybindings for debug and run without debugging to better match VS Code. [#3507](https://github.com/microsoft/vscode-cmake-tools/issues/3507)
- Allow success recovery in the configure precondition handler. [#3554](https://github.com/microsoft/vscode-cmake-tools/issues/3554)
- Prevent second configure after `QuickStart` if the `automaticReconfigure` setting is enabled. [#3910](https://github.com/microsoft/vscode-cmake-tools/issues/3910)
- Fix various GCC compiler errors and GCC linker errors not showing up in Problems View [#2864](https://github.com/microsoft/vscode-cmake-tools/issues/2864)
- Set usepresets context after manually creating a CMakePresets.json/CMakeUserPresets.json or using QuickStart to create it. [#3854](https://github.com/microsoft/vscode-cmake-tools/issues/3854)
- Only do special handling of `~` for code model reply path on linux. [#3957](https://github.com/microsoft/vscode-cmake-tools/issues/3957)
- Fix issues with expanding unnecessary environment variables and incorrectly saving preset environments to cache. Also fixes expansion error reporting issue with not checking for an invalid Configure preset in other types of presets. [#3961](https://github.com/microsoft/vscode-cmake-tools/issues/3961) & [#1841](https://github.com/microsoft/vscode-cmake-tools/issues/1841)
Expand Down
4 changes: 2 additions & 2 deletions src/diagnostics/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ export class Compilers {
[compiler: string]: RawDiagnosticParser;

gcc = new gcc.Parser();
gnuld = new gnu_ld.Parser();
ghs = new ghs.Parser();
diab = new diab.Parser();
gnuLD = new gnu_ld.Parser();
msvc = new mvsc.Parser();
iar = new iar.Parser();
}
Expand Down Expand Up @@ -82,7 +82,7 @@ export class CompileOutputConsumer implements OutputConsumer {
MSVC: this.compilers.msvc.diagnostics,
GHS: this.compilers.ghs.diagnostics,
DIAB: this.compilers.diab.diagnostics,
link: this.compilers.gnuLD.diagnostics,
GNULD: this.compilers.gnuld.diagnostics,
IAR: this.compilers.iar.diagnostics
};
const parsers = util.objectPairs(by_source)
Expand Down
129 changes: 95 additions & 34 deletions src/diagnostics/gcc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,34 @@ import * as vscode from 'vscode';

import { oneLess, RawDiagnostic, RawDiagnosticParser, RawRelated, FeedLineResult } from './util';

export const REGEX = /^(.*):(\d+):(\d+):\s+(?:fatal )?(\w*)(?:\sfatale)?\s?:\s+(.*)/;
enum MatchType {
Full,
File,
Line,
Column,
Severity,
Message
}

const regexPatterns: RegexPattern[] = [
{ // path/to/file:line:column: severity: message
regexPattern: /^(.+):(\d+):(\d+):\s+(?:fatal\s+)?(\w+):\s+(.+)/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Column, MatchType.Severity, MatchType.Message]
},
{ // path/to/file:line: severity: message (but not starting with "path/to/ld[.exe]:")
regexPattern: /^(?!.*?ld(?:\.exe)?:)(.+):(\d+):\s+(?:fatal\s+)?(\w+):\s+(.+)/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Severity, MatchType.Message]
},
{ // path/to/cc1[.exe]|arm-none-eabi-gcc[.exe]: severity: message
regexPattern: /^(.*(?:cc1|arm-none-eabi-gcc)(?:\.exe)?):\s+(?:fatal\s+)?(\w+):\s+(.+)/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Severity, MatchType.Message]
}
];

interface RegexPattern {
regexPattern: RegExp;
matchTypes: MatchType[];
}

interface PendingTemplateBacktrace {
rootInstantiation: string;
Expand All @@ -28,7 +55,6 @@ export class Parser extends RawDiagnosticParser {
};
return FeedLineResult.Ok;
}

if (this._pendingTemplateError) {
mat = /(.*):(\d+):(\d+):( +required from.+)/.exec(line);
if (mat) {
Expand Down Expand Up @@ -56,44 +82,79 @@ export class Parser extends RawDiagnosticParser {
}

// Test if this is a diagnostic
mat = REGEX.exec(line);
if (!mat) {
let mat2 = null;

let full = "";
let file = "";
let lineno = oneLess("1");
let columnno = oneLess("1");
let severity = 'error';
let message = "";

for (const [, regexPattern] of regexPatterns.entries()) {
mat2 = line.match(regexPattern.regexPattern);

if (mat2 !== null) {
for (let i = 0; i < mat2.length; i++) {
switch (regexPattern.matchTypes[i]) {
case MatchType.Full:
full = mat2[i];
break;
case MatchType.File:
file = mat2[i];
break;
case MatchType.Line:
lineno = oneLess(mat2[i]);
break;
case MatchType.Column:
columnno = oneLess(mat2[i]);
break;
case MatchType.Severity:
severity = mat2[i];
break;
case MatchType.Message:
message = mat2[i];
break;
default:
break;
}
}
break;
}
}

if (!mat2) {
// Nothing to see on this line of output...
return FeedLineResult.NotMine;
} else {
const [full, file, lineno_, column_, severity, message] = mat;
if (file && lineno_ && column_ && severity && message) {
const lineno = oneLess(lineno_);
const column = oneLess(column_);
if (severity === 'note' && this._prevDiag) {
this._prevDiag.related.push({
if (severity === 'note' && this._prevDiag) {
this._prevDiag.related.push({
file,
location: new vscode.Range(lineno, columnno, lineno, 999),
message
});
return FeedLineResult.Ok;
} else {
const related: RawRelated[] = [];
const location = new vscode.Range(lineno, columnno, lineno, 999);
if (this._pendingTemplateError) {
related.push({
location,
file,
location: new vscode.Range(lineno, column, lineno, 999),
message
message: this._pendingTemplateError.rootInstantiation
});
return FeedLineResult.Ok;
} else {
const related: RawRelated[] = [];
const location = new vscode.Range(lineno, column, lineno, 999);
if (this._pendingTemplateError) {
related.push({
location,
file,
message: this._pendingTemplateError.rootInstantiation
});
related.push(...this._pendingTemplateError.requiredFrom);
this._pendingTemplateError = undefined;
}

return this._prevDiag = {
full,
file,
location,
severity,
message,
related
};
related.push(...this._pendingTemplateError.requiredFrom);
this._pendingTemplateError = undefined;
}

return this._prevDiag = {
full,
file,
location,
severity,
message,
related
};
}
return FeedLineResult.NotMine;
}
Expand Down
176 changes: 155 additions & 21 deletions src/diagnostics/gnu-ld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,167 @@

import * as vscode from 'vscode';

import { FeedLineResult, oneLess, RawDiagnosticParser } from './util';
import { oneLess, RawDiagnostic, RawDiagnosticParser, RawRelated, FeedLineResult } from './util';

export const REGEX = /^(.*):(\d+)\s?:\s+(.*[^\]])$/;
enum MatchType {
Full,
File,
Line,
Column,
Severity,
Message
}

const regexPatterns: RegexPattern[] = [
{ // path/to/ld[.exe]:[ ]path/to/file:line: severity: message
regexPattern: /^(?:.*ld(?:\.exe)?:)(?:\s*)?(.+):(\d+):\s+(?:fatal )?(\w+):\s+(.+)/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Severity, MatchType.Message]
},
{ // path/to/ld[.exe]:[ ]path/to/file:line: message
regexPattern: /^(?:.*ld(?:\.exe)?\:)(?:\s*)?(.+):(\d+):\s+(.+)/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Message]
},
{ // path/to/ld[.exe]: severity: message
regexPattern: /^(.*ld(?:\.exe)?):\s+(?:fatal )?(\w+):\s+(.+)/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Severity, MatchType.Message]
},
{ // path/to/ld[.exe]: message (without trailing colon)
regexPattern: /^(.*ld(?:\.exe)?):\s+(.+)(?<!:)$/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Message]
},
{ // /path/to/file:line: message (without "[fatal] severity:" or trailing colon)
regexPattern: /^(.+?):(\d+):\s+(?!fatal\s+\w+:)(?!\w+:)(.+)(?<!:)$/,
matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Message]
}
];

interface RegexPattern {
regexPattern: RegExp;
matchTypes: MatchType[];
}

interface PendingTemplateBacktrace {
rootInstantiation: string;
requiredFrom: RawRelated[];
}

export class Parser extends RawDiagnosticParser {
private _prevDiag?: RawDiagnostic;

private _pendingTemplateError?: PendingTemplateBacktrace;

doHandleLine(line: string) {
// Try to parse for GNU ld
if (line.startsWith('make')) {
// This is a Make error. It may *look* like an LD error, so we abort early
return FeedLineResult.NotMine;
let mat = /(.*): (In instantiation of.+)/.exec(line);
if (mat) {
const [, , message] = mat;
this._pendingTemplateError = {
rootInstantiation: message,
requiredFrom: []
};
return FeedLineResult.Ok;
}
const res = REGEX.exec(line);
if (!res) {
return FeedLineResult.NotMine;
if (this._pendingTemplateError) {
mat = /(.*):(\d+):(\d+):( +required from.+)/.exec(line);
if (mat) {
const [, file, linestr, column, message] = mat;
const lineNo = oneLess(linestr);
this._pendingTemplateError.requiredFrom.push({
file,
location: new vscode.Range(lineNo, parseInt(column), lineNo, 999),
message
});
return FeedLineResult.Ok;
}
}
const [full, file, lineno_, message] = res;
const lineno = oneLess(lineno_);
if (file && lineno && message) {
return {
full,
file,
location: new vscode.Range(lineno, 0, lineno, 999),
severity: 'error',
message,
related: []
};

// Early-catch backtrace limit notes
mat = /note: \((.*backtrace-limit.*)\)/.exec(line);
if (mat && this._prevDiag && this._prevDiag.related.length !== 0) {
const prevRelated = this._prevDiag.related[0];
this._prevDiag.related.push({
file: prevRelated.file,
location: prevRelated.location,
message: mat[1]
});
return FeedLineResult.Ok;
}

// Test if this is a diagnostic
let mat2 = null;

let full = "";
let file = "";
let lineno = oneLess("1");
let columnno = oneLess("1");
let severity = 'error';
let message = "foobar";

for (const [, regexPattern] of regexPatterns.entries()) {
mat2 = line.match(regexPattern.regexPattern);

if (mat2 !== null) {
for (let i = 0; i < mat2.length; i++) {
switch (regexPattern.matchTypes[i]) {
case MatchType.Full:
full = mat2[i];
break;
case MatchType.File:
file = mat2[i];
break;
case MatchType.Line:
lineno = oneLess(mat2[i]);
break;
case MatchType.Column:
columnno = oneLess(mat2[i]);
break;
case MatchType.Severity:
severity = mat2[i];
break;
case MatchType.Message:
message = mat2[i];
break;
default:
break;
}
}
break;
}
}

if (!mat2) {
// Nothing to see on this line of output...
return FeedLineResult.NotMine;
} else {
if (severity === 'note' && this._prevDiag) {
this._prevDiag.related.push({
file,
location: new vscode.Range(lineno, columnno, lineno, 999),
message
});
return FeedLineResult.Ok;
} else {
const related: RawRelated[] = [];
const location = new vscode.Range(lineno, columnno, lineno, 999);
if (this._pendingTemplateError) {
related.push({
location,
file,
message: this._pendingTemplateError.rootInstantiation
});
related.push(...this._pendingTemplateError.requiredFrom);
this._pendingTemplateError = undefined;
}

return this._prevDiag = {
full,
file,
location,
severity,
message,
related
};
}
return FeedLineResult.NotMine;
}
return FeedLineResult.NotMine;
}
}
Loading