﻿# Как фрагмент CSS разметки сломал C\+\+ компилятор

В методологии статического анализа применяются разные технологии\. Одна из них \- препроцессирование файлов непосредственно перед их анализом\. Препроцессированные файлы создаёт компилятор, запускаемый в специальном режиме работы\. К сожалению, этот режим не очень хорошо тестируется, как показывает наш многолетний опыт разработки статического анализатора кода\. В этой заметке приведу пример свеженайденного бага в С\+\+ компиляторе от Microsoft\.

![0620_MsvcBugCSS_ru/image1.png](https://import.viva64.com/docx/blog/0620_MsvcBugCSS_ru/image1.png)

## Введение

Для демонстрации возможностей статического анализатора PVS\-Studio наша команда проверяет исходный код Open Source проектов\. Это существенный [вклад](https://pvs-studio.ru/ru/blog/inspections/) в качество открытого программного обеспечения, дополнительная реклама и тестирование анализатора\. Иногда мы выявляем очень необычные проблемы в компиляторах, с которыми сложно что\-то сделать на стороне анализатора\. Так, коллега недавно писал статью "[Перестал анализироваться файл с директивой 'import' \(compiler internal error 'msc1\.cpp'\)\. Что делать?](https://pvs-studio.ru/ru/blog/posts/0613/)", чтобы помочь нашим пользователям в решении "чужой" проблемы\.

## Причём тут CSS?

Не менее интересный баг был найден мной только что при проверке большого проекта\. Компилятор Microsoft для C/C\+\+ версии 19\.16\.27027\.1 \(Visual Studio v15\.9\.9\) выдал такую ошибку при анализе нескольких файлов:

```cpp
fatal error C1021: invalid preprocessor command 'tooltiphint'
```

Очевидно, это не директива препроцессора, но что же это? Это фрагмент CSS кода:

```cpp
#tooltiphint {
  position: fixed;
  width: 50em;
  margin-left: -25em;
  left: 50%;
  padding: 10px;
  border: 1px solid #b0b0b0;
  border-radius: 2px;
  box-shadow: 1px 1px 7px black;
  background-color: #c0c0c0;
  z-index: 2;
}
```

После просмотра фрагмента стало понятно, что компилятор ошибается во время препроцессирования файла, но при этом код компилируется успешно\. Фрагмент CSS кода является частью строкового литерала C\+\+ кода\. Вот так выглядит пример кода, достаточный для повторения ошибки:

```cpp
std::string test = R"<<<(
<style type="text/css">
body { color:#000000; background-color:#ffffff }
body { font-family:Helvetica, sans-serif; font-size:10pt }

#tooltiphint {
  position: fixed;
  width: 50em;
  margin-left: -25em;
  left: 50%;
  padding: 10px;
  border: 1px solid #b0b0b0;
  border-radius: 2px;
  box-shadow: 1px 1px 7px black;
  background-color: #c0c0c0;
  z-index: 2;
}
.macro {
  color: darkmagenta;
  background-color:LemonChiffon;
  /* Macros are position: relative to provide base for expansions. */
  position: relative;
}

</style>
</head>
<body>)<<<";
```

Приведённый фрагмент кода не мешает успешной компиляции, но, в то же время, в режиме препроцессирования \(флаг [/P](https://docs.microsoft.com/ru-ru/cpp/build/reference/p-preprocess-to-a-file?view=vs-2017)\) возникнет ошибка\.

Вот такая непростая жизнь у разработчиков статических анализаторов :\)\. Вроде виноват не PVS\-Studio, но всё равно мы должны заниматься с подобными проблемами\. Впрочем, в этом нет чего\-то нового\. С некоторыми другими подобными случаями можно познакомиться в статье "[PVS\-Studio и враждебная среда обитания](https://pvs-studio.ru/ru/blog/posts/cpp/0303/)"\.

## Заключение

Эта проблема будет отправлена в официальный баг\-трекер, но оперативное решение проблемы вряд ли возможно\. Например, проблема с директивой _\#import_, выявленная нами несколько месяцев назад, о которой я писал вначале, будет исправлена только в следующем релизе Visual Studio\. Т\.к\. релиз новой Visual Studio 2019 состоится уже через неделю, скорее всего, этот баг не успеют исправить к этой дате\. Пользователям PVS\-Studio рекомендуем также воспользоваться макросом [PVS\_STUDIO](https://pvs-studio.ru/ru/docs/manual/0020/)\.

**UPD**: _A fix for this issue has been released in VS 2019 16\.0 Preview 4 and VS 2019 16\.0 RC\._