Webinar: Parsing C++ - 10.10
The #line directive is added by the preprocessor and can then be used to help the developer understand which file and line a particular code fragment in the preprocessed file refers to. The #line directive tells code-processing tools to change the compiler's internally stored line number and filename to a given line number and filename. Subsequent lines will be numbered relative to that position. Explicit preprocessing is mostly used for debugging or by various generators. In any case, a bug breaking this functionality may have a variety of negative effects. One of our users was faced with such a problem in Visual Studio 2019.
The #line directive is an important part of preprocessed files used by PVS-Studio to issue warnings on problem code lines in users' programs. This is where the story of hunting down the bug begins.
One of our users, who had a large code base, started moving his project from Platform Toolset v141 to v142 in Visual Studio 2019. After that, he got a pile of V002 warnings and several dozens of other warnings pointing at wrong code lines (1 line ahead of the actual one).
Incorrect line numbering is exactly the type of issues that diagnostic V002 detects. Such bugs typically have to do with multiline macros or other preprocessor directives (such as #pragma). It's not a common problem, but it's mostly seen with Microsoft's compiler. We were surprised to see so many warnings issued on one project as our testing system had never revealed any serious problems like that. So we started debugging the analyzer based on the user's preprocessed file.
A few hours later, we finally found that PVS-Studio was already working with incorrect line information, and were able to write a test case:
#define MACRO(a, b) // line1
// line2
int main(int argc, char* argv[]) // line3
{ // line4
MACRO("Some string", // line5
42); // line6
return 0; // line7 <=
}
This is what we get as a preprocessed file:
#line 1 "D:\\_Tests\\TestApp\\Project2\\rnd_bs.cpp"
int main(int argc, char* argv[])
{
;
#line 8 "D:\\_Tests\\TestApp\\Project2\\rnd_bs.cpp"
return 0;
}
The return statement is at line 7 in the source file, while the preprocessor points at line 8 instead. This bug in the preprocessor was presumably caused by a multiline macro.
As of this writing, the problem exists in the recent Visual Studio versions up to 16.4.3 (released on January 14, 2020). We submitted a bug report "Invalid #line directive after preprocessing (VS2019, v142)" and got a curious reply four days later:
This issue has been identified as a duplicate of an earlier reported feedback linked here: https://developercommunity.visualstudio.com/content/problem/738407/preprocessor-generates-incorrect-line-information.html. If you reported or voted here, your vote has been applied to the original issue. Everyone else can add their vote directly at the above linked feedback. Voting helps increase the priority of the issue by consolidating customer impact under one feedback. Thank you!
It turns out this problem was already reported on September 18, 2019 – almost half a year ago: "Preprocessor generates incorrect line information". The user included similar test cases to reproduce the bug. According to him, it goes back to at least Visual Studio 2019 16.2.
I'm not sure if this is a coincidence or not, but a few days after our activity, the bug was assigned the status Fixed - Pending Release.
On May 19, 2020, a fixed Visual Studio 2019 16.6.0 was released. It is recommended that all PVS-Studio users update to that version.
0