Поиск неинстанцированных шаблонов в коде C ++ - PullRequest
8 голосов
/ 26 апреля 2011

Каков наилучший способ найти необоснованные шаблоны в коде C ++?

У меня есть кодовая база, которая интенсивно использует шаблоны. Конечно, мы хотим убедиться, что тестовое покрытие является высоким. Для всего используемого кода это работает очень хорошо, используя gcov.

Однако неиспользуемые шаблоны сообщаются как неисполняемые gcov.

После некоторого поиска в Google, кажется, нет никакого способа заставить g++ выдавать код для этих шаблонов (что логично, как компилятор должен угадывать какие-либо типы?) Представляется также, что нет способа заставить gcov распознавать необработанный код шаблона как исполняемый код.

Есть ли что-нибудь "из коробки", что позволяет мне увеличивать файлы, сгенерированные инструментарием GCC -ftest-coverage -fprofile-arcs? Согласно документации gcov для GCC , вероятно, будет достаточно отметить все тело функции шаблона как один блок, так как выполнение никогда не закончится там.

РЕДАКТИРОВАТЬ (справочная информация): я работаю над библиотекой шаблонов только для заголовка. Моя цель здесь - найти неиспользуемые / непроверенные функции.

Я знаю, что покрытие кода имеет недостатки, но поиск неосуществленного кода является очень важным шагом на пути к лучшему тестированию кода. В настоящее время мы помещаем макросы контрольных точек в начале каждой функции. В режиме тестирования они расширяются до кода, который вставляет пару (file, line) в глобальный набор пройденных контрольных точек. После выполнения тестов мы вручную читаем все файлы и сравниваем достигнутые контрольные точки с набором всех доступных контрольных точек.

Важным является нахождение неосуществленного кода, например, из-за неинтуитивного поведения приоритета шаблона C ++, где-то может быть мертвый код, который читатель или даже автор ожидают использовать.

Ответы [ 3 ]

2 голосов
/ 26 апреля 2011

Я думаю, что наш C ++ Test Coverage инструмент (не на основе GCC) делает это правильно с вашей точки зрения.

Он обрабатывает исходный код до того, как его увидит компилятор; код внутри шаблонов получает «пробники покрытия» независимо от того, используется шаблон или нет. Часть отображения тестового покрытия инструмента знает, где находятся все зонды; если код шаблона не создан, он явно не может быть выполнен, о чем будет сообщено. Вам не нужно делать какую-либо "пользовательскую" вставку макроса или что-то еще, например, BS.

Недостатком является то, что если у вас есть шаблон, параметризованный несколькими различными типами, и методы шаблона m1 и m2 выполняются для различных экземпляров типов, ваше покрытие для m1 и m2 будет 100% (в конце концов, вы выполнили инструментальный шаблон ). Не ясно, что это плохо; только то, как это интерпретируется.

1 голос
/ 26 апреля 2011

Хорошо, поскольку я не очень разбираюсь в GCC, вот утомительное и очень трудоемкое решение, но, по крайней мере, оно работает!:)
Этот тест основан на том факте, что некоторые ошибки в коде шаблона не обнаруживаются до фактического создания экземпляра, т.е. когда в параметре шаблона фактически отсутствуют зависимые имена:

template<class T>
struct Example{
  typedef typename T::_123344_non_existent_type instantiation_test;
};

Добавитьтакой typedef для каждого вашего шаблона, затем скомпилируйте.Удалите его из каждой структуры / класса / функции, для которой отображается ошибка компилятора, и каждый шаблон, который все еще содержит такой typedef, когда код в конечном итоге компилируется, никогда не создается.Или вам не повезло, и некоторые типы определяют такой _123344_non_existent_type, хотя я бы линчевал сотрудника, который за это отвечает.;)

0 голосов
/ 17 июня 2018

У меня возникла такая же проблема, поэтому я написал программу, которая изменяет отчеты о покрытии кода, чтобы показывать необоснованные шаблоны . Это не самый элегантный, но работает.

Есть две фазы:

  • Перед компиляцией вы используете программу на C ++, написанную с помощью Libtooling Clang, чтобы найти все шаблоны в вашем коде и вставить комментарии до и после них.
  • После того, как вы сгенерировали отчет о тестовом покрытии, вы запускаете скрипт python, который просматривает отчет и модифицирует строки, заключенные в комментарии из шага 1.

Таким образом, в основном используется тот факт, что, несмотря на то, что большая часть вашего кода не включена в двоичный код, в конечном итоге все это заканчивается в окончательном отчете о покрытии. Макросы, описанные в этом вопросе, послужили источником вдохновения для этого подхода (в основном это их автоматическая версия, которая не загромождает исходный код).

Пока я использовал его только в своем собственном коде, но он должен обобщаться. Вопросы и запросы на получение приветствуются!

...