The static analyzer's HTML reports contain misnested tags whenever a
variable with a `variable_popup` is the last token on a source line.
`AddLineNumber` inserts the row-closing `</td></tr>` with `InsertTextBefore`, which
places it in front of text previously inserted at the same offset. As a result,
the popup's closing `</table></span>` tags and the arrow anchor `</span>`
tags end up outside the table row. HTML parsers (jsoup, pup) and validators
reject the file from that point on.
Before:
<span class='variable'>b</td></tr><table
class='variable_popup'>...</table></span></span></span>
<img width="786" height="414" alt="image"
src="https://github.com/user-attachments/assets/023461ad-73e4-424e-a4fb-42faf7a945f0"
/>
After:
<span class='variable'>b<table
class='variable_popup'>...</table></span></span></span></td></tr>
<img width="877" height="477" alt="image"
src="https://github.com/user-attachments/assets/cf8aada4-21c8-4af7-9e07-c2d8cc1d0724"
/>
The fix inserts `</td></tr>` with `InsertTextAfter` so tags closing at
the end-of-line offset stay inside the row. To keep the message bubbles
outside the code rows, the line number table is now added before the path pieces
are processed, and bubbles are inserted after the newline, between the
current and the next row.
The pre-existing tests only exercised popups on variables followed by
more tokens (`if (b)`), which is why this was never caught; the new test
places the variable at the end of the line. This has been broken since at least
clang 10; the earlier fix (D73993 / commit 482e236e56)
only covered the macro popup variant.
I verified this with the Analysis/html_diagnostics tests, the full
clang/test/Analysis suite, and by running generated reports through an
HTML parser that checks tag nesting: 4 errors before / 0 after on the
reproducer above, and 8 → 0 on a larger file with macro popups, multiple
events per line, and mid-line popups. The visible report content is
unchanged.
Fixes#46089