1515using namespace Utils ;
1616
1717namespace ProjectExplorer {
18+ namespace {
1819
19- // As of MSVC 2015: "foo.cpp(42) :" -> "foo.cpp(42):"
20- static const char FILE_POS_PATTERN[] = " ^(?:\\ d+>)?(cl|LINK|.+?[^ ]) ?: " ;
20+ auto constexpr filePosRegexString () -> std::string_view {
21+ // As of MSVC 2015: "foo.cpp(42) :" -> "foo.cpp(42):"
22+ return R"( ^(?:\d+>)?(cl|LINK|.+?[^ ]) ?: )" ;
23+ }
24+
25+ struct FileData {
26+ FilePath fileName{};
27+ int lineNo{-1 };
28+ int columnNo{-1 };
29+ };
2130
22- static QPair<FilePath, int > parseFileName (const QString & input)
31+ auto parseFileName (QStringView input) -> FileData
2332{
24- QString fileName = input;
25- if (fileName.startsWith (" LINK" ) || fileName.startsWith (" cl" ))
26- return {{}, -1 };
33+ auto result = FileData{};
34+
35+ if (input.startsWith (QStringView{u" LINK " }) || input.startsWith (QStringView{u" cl " })){
36+ return result;
37+ }
38+ auto & [fileName, lineNo, columnNo] = result;
2739
2840 // Extract linenumber (if it is there):
29- int linenumber = -1 ;
30- if (fileName.endsWith (' )' )) {
31- int pos = fileName.lastIndexOf (' (' );
32- if (pos >= 0 ) {
33- // clang-cl gives column, too: "foo.cpp(34,1)" as opposed to MSVC "foo.cpp(34)".
34- int endPos = fileName.indexOf (' ,' , pos + 1 );
35- if (endPos < 0 )
36- endPos = fileName.size () - 1 ;
37- bool ok = false ;
38- const int n = fileName.mid (pos + 1 , endPos - pos - 1 ).toInt (&ok);
39- if (ok) {
40- fileName = fileName.left (pos);
41- linenumber = n;
41+ if (input.size () > 2 && input.endsWith (' )' )) {
42+ auto rit = input.rbegin () + 1 ;
43+ auto rend = input.rend ();
44+ auto f = 0 ;
45+ auto n = -1 ;
46+ while (rit != rend) {
47+ auto ch = *rit++;
48+ if (ch.isDigit ()) {
49+ if (n < 0 ) {
50+ n = ch.digitValue ();
51+ f = 10 ;
52+ }
53+ else {
54+ n += ch.digitValue () * f;
55+ f *= 10 ;
56+ }
57+ continue ;
4258 }
59+ if (ch == u' ,' ) {
60+ if (n >= 0 ) columnNo = n;
61+ n = -1 ;
62+ continue ;
63+ }
64+ if (ch == u' (' ) {
65+ if (n >= 0 ) lineNo = n;
66+ input = input.sliced (0 , rend - rit);
67+ break ;
68+ }
69+ break ;
4370 }
4471 }
45- return {FilePath::fromUserInput (fileName), linenumber};
72+ fileName = FilePath::fromUserInput (input.toString ());
73+ return result;
4674}
4775
4876// nmake/jom messages.
@@ -79,15 +107,17 @@ static Task::TaskType taskType(const QString &category)
79107 return type;
80108}
81109
110+ } // namespace
111+
82112MsvcParser::MsvcParser ()
83113{
84114 setObjectName (" MsvcParser" );
85115 setOrigin (" MSVC compiler" );
86116
87- m_compileRegExp.setPattern (QString (FILE_POS_PATTERN )
88- + " .*(?:(warning|error) ([A-Z]+\\ d{4} ?: )|note: )(.*)$" );
117+ m_compileRegExp.setPattern (QLatin1String ( filePosRegexString () )
118+ + R"( .*(?:(warning|error) ([A-Z]+\d{4} ?: )|note: )(.*)$) " );
89119 QTC_CHECK (m_compileRegExp.isValid ());
90- m_additionalInfoRegExp.setPattern (" ^ (?:(could be |or )\\ s*')?(.*)\\ ((\\ d+)\\ ) : (.*)$" );
120+ m_additionalInfoRegExp.setPattern (R"( ^ (?:(could be |or )\s*')?(.*)\((\d+)\) : (.*)$) " );
91121 QTC_CHECK (m_additionalInfoRegExp.isValid ());
92122}
93123
@@ -122,19 +152,19 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
122152 m_isCaretDiagnostics = line.contains (" /diagnostics:caret" );
123153 }
124154 if (QRegularExpressionMatch match = m_compileRegExp.match (line); match.hasMatch ()) {
125- QPair<FilePath, int > position = parseFileName (match.captured (1 ));
126- const FilePath filePath = absoluteFilePath (position. first );
155+ auto [rawFileName, lineNo, columnNo] = parseFileName (match.captured (1 ));
156+ const FilePath filePath = absoluteFilePath (rawFileName );
127157 LinkSpecs linkSpecs;
128- addLinkSpecForAbsoluteFilePath (linkSpecs, filePath, position. second , - 1 , match, 1 );
129- const QString & description = match.captured (3 ) + match.captured (4 ).trimmed ();
158+ addLinkSpecForAbsoluteFilePath (linkSpecs, filePath, lineNo, columnNo , match, 1 );
159+ const auto description = match.captured (3 ) + match.captured (4 ).trimmed ();
130160 createOrAmendTask (
131161 taskType (match.captured (2 )),
132162 description,
133163 line,
134164 false ,
135165 filePath,
136- position. second ,
137- 0 ,
166+ lineNo ,
167+ columnNo > 0 ? columnNo : 0 ,
138168 linkSpecs);
139169 m_expectCode = m_isCaretDiagnostics;
140170 return {Status::InProgress, linkSpecs};
@@ -151,7 +181,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
151181 m_expectCode = m_isCaretDiagnostics;
152182 return {Status::InProgress, linkSpecs};
153183 }
154- if (hasCurrentTask ()) {
184+ if (! currentTask (). isNull ()) {
155185 bool amend = false ;
156186 if (line.endsWith (" ^" )) {
157187 m_expectCode = false ; // code was before
@@ -165,7 +195,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
165195 amend = true ;
166196 }
167197 if (amend) {
168- amendTaskDetails ( line);
198+ createOrAmendTask (Task::Unknown, {}, line, true );
169199 return Status::InProgress;
170200 }
171201 }
@@ -183,7 +213,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
183213// ".\qwindowsgdinativeinterface.cpp(48,3) : error: unknown type name 'errr'"
184214static inline QString clangClCompilePattern ()
185215{
186- return QLatin1String (FILE_POS_PATTERN ) + " ?(warning|error): (.*)$" ;
216+ return QLatin1String (filePosRegexString () ) + " ?(warning|error): (.*)$" ;
187217}
188218
189219ClangClParser::ClangClParser ()
@@ -234,13 +264,12 @@ OutputLineParser::Result ClangClParser::handleLine(const QString &line, OutputFo
234264 QRegularExpressionMatch match = m_compileRegExp.match (lne);
235265 if (match.hasMatch ()) {
236266 flush ();
237- const QPair<FilePath, int > position = parseFileName (match.captured (1 ));
238- const FilePath file = absoluteFilePath (position.first );
239- const int lineNo = position.second ;
267+ const auto [rawFileName, lineNo, columnNo] = parseFileName (match.captured (1 ));
268+ const FilePath file = absoluteFilePath (rawFileName);
240269 LinkSpecs linkSpecs;
241- addLinkSpecForAbsoluteFilePath (linkSpecs, file, lineNo, - 1 , match, 1 );
270+ addLinkSpecForAbsoluteFilePath (linkSpecs, file, lineNo, columnNo , match, 1 );
242271 createOrAmendTask (
243- taskType (match.captured (2 )), match.captured (3 ).trimmed (), line, false , file, lineNo);
272+ taskType (match.captured (2 )), match.captured (3 ).trimmed (), line, false , file, lineNo, columnNo, linkSpecs );
244273 return {Status::InProgress, linkSpecs};
245274 }
246275
0 commit comments