Подтвердить что ты не робот

Есть ли инструмент для добавления "переопределяющего" идентификатора к существующему коду С++

Задача

Я пытаюсь выяснить, как лучше всего добавить идентификатор С++ 0x override ко всем существующим методам, которые уже переопределены в большой части кода на С++, не выполняя его вручную.

(У нас много, много сотен тысяч строк кода, и сделать это вручную было бы полным без стартера.)

Текущая идея

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

Итак, если бы я был с script сам добавлением, я бы написал script, который читал все наши заголовки, нашел все функции, начинающиеся с виртуального, и вставлял override перед следующей точкой с запятой. Затем скомпилируйте его в компиляторе, поддерживающем override, и исправим все ошибки в базовых классах.

Но я бы очень не хотел использовать этот домашний стиль, как:

  • это, очевидно, будет утомительным и подверженным ошибкам.
  • не каждый запомнил, каждый раз, добавить ключевое слово virtual, поэтому этот метод пропустит некоторые существующие переопределения.

Есть ли существующий инструмент?

Итак, есть ли уже инструмент, который анализирует код на С++, обнаруживает существующие методы, которые переопределяют, и добавляет override к их объявлениям?

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

(В случае, если у кого-то возникает соблазн указать, что С++ 03 не поддерживает "переопределить"... На практике я бы добавил макрос, а не фактический "переопределяющий" идентификатор, чтобы использовать наши код на старых компиляторах, которые не поддерживают эту функцию. Поэтому после добавления идентификатора я запустил отдельный script, чтобы заменить его на любой макрос, который мы собираемся использовать...)

Спасибо заранее...

4b9b3361

Ответ 1

Существует проект, разрабатываемый проектом LLVM под названием "cpp11-migrate", который в настоящее время имеет следующие функции:

  • конвертировать циклы в диапазоны для циклов
  • конвертировать константы нулевого указателя (например, NULL или 0) в С++ 11 nullptr
  • замените спецификатор типа в объявлениях переменных с помощью спецификатора типа auto
  • добавить спецификатор override к применимым функциям-членам

Этот инструмент зарегистрирован здесь и должен быть выпущен как часть clang 3.3. Однако вы можете скачать исходный код и создать его сегодня.

Edit

Дополнительная информация:

Редактировать 2: 2013-09-07

"cpp11-migrate" был переименован в "clang-modernize". Для пользователей Windows он теперь включен в новый сборщик снимков LLVM.

Ответ 2

Наш DMS Software Reengineering Toolkit с поддержкой С++ 11 С++ Front End может сделать это.

DMS - система преобразования программ общего назначения для произвольных языков программирования; передняя часть С++ позволяет обрабатывать С++. DMS анализирует, строит таблицы AST и таблиц символов, которые являются точными (это трудно сделать для С++), обеспечивает поддержку запросов свойств узлов и деревьев AST, позволяет обрабатывать процессуальные и исходные источники на дереве. После внесения всех изменений модифицированное дерево может быть восстановлено с сохраненными комментариями.

Ваша проблема требует, чтобы вы нашли производные виртуальные методы и изменили их. Правило преобразования источника-источника DMS для этого будет выглядеть примерно так:

    source domain Cpp.  -- tells DMS the following rules are for C++

    rule insert_virtual_keyword (n:identifier, a: arguments, s: statements):
       method_declaration -> method_declaration " =
       " void \n(\a) { \s } "  ->  " virtual void \n(\a) { \s }"
       if is_implicitly_virtual(n).

Такие правила соответствуют синтаксическим деревьям, поэтому они не могут не совпадать с комментарием, строкой и т.д. Смешные цитаты не являются строковыми кавычками С++; они являются мета-кавычками, чтобы язык правил мог знать, что то, что внутри них, должно рассматриваться как синтаксис целевого языка ( "Cpp" ). Обратные косые черты - это escape-последовательности из текста целевого языка, позволяющие совпадения с произвольными структурами, например, \a указывает на необходимость "a", которая определяется как "аргументы" синтаксической категории.

Вам понадобится больше правил для обработки случаев, когда функция возвращает не-void результат и т.д., но вам не нужно много их.

Интересная часть реализует предикат (возвращающий TRUE или FALSE), управляющий приложением преобразования: is_implicitly_virtual. Этот предикат принимает (абстрактное синтаксическое дерево для) имя метода n. Этот предикат будет консультироваться с полной таблицей символов С++, чтобы определить, что на самом деле существует. Мы уже знаем, что это метод только из его синтаксических настроек, но мы хотим знать, в каком контексте класса. Таблица символов обеспечивает связь между методом и классом, а информация таблицы таблиц для класса говорит нам, что наследует класс, и для этих классов, какие методы они содержат и как они объявлены, в конечном итоге приводит к открытию (или не), что метод родительского класса является виртуальным. Код для этого должен быть реализован как процедурный код, идущий против API таблиц символов С++. Однако вся напряженная работа выполнена; таблица символов верна и содержит ссылки на все другие необходимые данные. (Если у вас нет этой информации, вы не можете решить алгоритмически, и любые изменения кода, вероятно, будут ошибочными).

В прошлом DMS использовался для выполнения масштабных изменений кода С++ с использованием программных преобразований. (Проверьте страницу Papers на веб-сайте для тем, связанных с синхронизацией С++).

(Я не эксперт на С++, просто архитектор DMS, поэтому, если у меня есть незначительные детали, прошу простить.)

Ответ 3

Я сделал что-то вроде этого несколько месяцев назад с примерно 3 МБ кода, и, пока вы говорите, что "делать это вручную было бы полным без стартера", я думаю, что это единственный способ. Причина в том, что вы должны применять ключевое слово override к прототипам предназначено, чтобы переопределить методы базового класса. Любой добавочный инструмент добавит его в прототипы, чтобы на самом деле переопределить методы базового класса. Компилятор уже знает, какие методы так добавляют ключевое слово, ничего не меняет. (Обратите внимание, что я не очень хорошо знаком с новым стандартом, и я предполагаю, что ключевое слово override является необязательным. Visual Studio поддерживает переопределение с по крайней мере VS2005.)

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

Я обнаружил две ошибки, пройдя через это.

Ответ 4

Eclipse CDT имеет рабочий синтаксический анализатор и семантические утилиты С++. В последней версии IIRC также есть маркеры для переопределения методов.

Не требуется много кода для написания подключаемого модуля, который основывался бы на этом и переписывал бы код, где бы он не содержал теги override.