Почему Eclipse CDT говорит:«синтаксическая ошибка», но компиляция не вызывает проблем
-
03-07-2019 - |
Вопрос
Я работаю над существующим кодом C, в котором есть пара строк с утверждениями, подобными этому:
struct collect_conn *tc = (struct collect_conn *)
((char *)c - offsetof(struct collect_conn, runicast_conn));
Структура Collect_conn имеет следующий вид:
struct collect_conn {
struct runicast_conn runicast_conn;
struct announcement announcement;
const struct collect_callbacks *cb;
struct ctimer t;
uint16_t rtmetric;
uint8_t forwarding;
uint8_t seqno;
};
Я использую Eclipse CDT, и он помечает строку оранжевой волнистой линией как «синтаксическую ошибку».Я думаю, что это помечено индексатором CDT как таковое.Однако компиляция (вручную в терминале) не представляет проблем.
Однако это немного неудобно, поскольку элементы в строке не индексируются (поэтому дерево иерархии вызовов не всегда корректно, выделение элементов и т. д.)
Почему Ecipse не нравится строка такая, какая она есть?
Решение
Eclipse CDT содержит собственный препроцессор/парсер для анализа вашего кода и построения индекса.Однако, когда вы вызываете сборку, CDT вызывает ваш системный компилятор, например, gcc.Между синтаксисом, принимаемым анализатором CDT, и синтаксисом, принимаемым вашим компилятором, могут быть незначительные различия.Когда это происходит, анализатор CDT может запутаться.
В моей системе offsetof
макрос разворачивается в выражение, использующее __offsetof__
ключевое слово.Это ключевое слово не распознается CDT, поэтому возникает синтаксическая ошибка.Чтобы справиться с этой проблемой, в анализатор CDT встроен макрос, позволяющий справиться с этой проблемой. __offsetof__
который выглядит следующим образом:
#define __offsetof__(x) (x)
Это кажется неправильным, по крайней мере, в моей системе результатом является удаление __offsetof__
ключевое слово из источника, что по-прежнему приводит к синтаксической ошибке.
Мне удалось избавиться от синтаксической ошибки, перейдя на страницу свойств «Пути и символы» и добавив макрос для __offsetof__
который отображается как «foo».Это заставляет синтаксический анализатор думать, что это просто вызов функции, которую он раньше не видел, а не синтаксическая ошибка.
Альтернативно вы можете отключить отчеты о синтаксических ошибках в редакторе, выбрав «Окно» > «Настройки» > «Основные» > «Редакторы» > «Текстовые редакторы» > «Аннотации» и сняв все флажки для маркеров индексатора C/C++.
Другие советы
Я исправил проблему в eclipse CDT с помощью Preferences->C/C++->Language Mappings:Добавить тип контента:Язык C-заголовок:С++
Кажется, анализатору CDT не нравится часть offsetof(struct ...).Если вы объявите Collect_conn с использованием typedef, ошибка исчезнет.По крайней мере у меня работает следующий код:
typedef struct {
struct runicast_conn runicast_conn;
struct announcement announcement;
const struct collect_callbacks *cb;
struct ctimer t;
uint16_t rtmetric;
uint8_t forwarding;
uint8_t seqno;
} collect_conn;
...
struct collect_conn *tc = (struct collect_conn *)
((char *)c - offsetof(collect_conn, runicast_conn));
Если вы не можете изменить исходное объявление, сделайте что-то вроде этого:
typedef struct collect_conn collect_conn_t;
Это может быть путано, проверьте, есть ли у вас определение смещение
например, в рамках.В противном случае вы можете попытаться упростить выражение, разбив его, например.а #define
с offset
или что-то в этом роде.
Я думаю, что компилятор может предоставить встроенную версию offsetof
, а компилятор/анализатор кода Eclipses — нет.Если да, то вам необходимо убедиться, что у вас есть определение, чтобы Eclipse мог правильно анализировать ваш код.
попробуйте переключить индексатор на «Полный индексатор c/C++ (полный анализ)» в настройках->c/C++ -> индексатор
Иногда, хотя код компилируется без ошибок, анализатор кода eclipse CDT в реальном времени показывает некоторые ошибки в файлах C/C++ (например.'Функция xxx не может быть разрешена).Это связано с тем, что eclipse CDT использует собственный препроцессор/парсер для анализа кода и построения индексов вместо препроцессора MinGW (или любого другого компилятора GNU).Чтобы исправить это глобально для всех проектов eclipse в рабочей области, выполните следующие действия:(Чтобы исправить это только для конкретного проекта, выполните шаги 1, 2 и 4 в меню 'Проект->Настройки')
1-В меню 'Окно->Настройки->C/C++->Сопоставления языков', добавьте правильные сопоставления, как показано ниже:(например.для типов контента:Исходный файл/заголовочный файл C++, используйте язык GNU C++ и т. д.)Глобальные настройки сопоставления языков
2-В меню 'Окно->Настройки->C/C++->Индексатор', установите полную индексацию, установив все флажки (кроме флажков «Пропустить»), как показано ниже:Глобальные настройки индексатора
3-В конкретных свойствах каждого проекта меню 'Проект->Свойства->Общие C/C++->Индексатор', снимите флажок «Включить настройки проекта», как показано ниже:Настройки индексатора проекта
4-Перестроить индексацию, меню 'Проект->Индекс C/C++->Перестроить'.
У меня та же проблема.Существует два определения offsetof (одно для C и одно для C++).ИМХО, проблема в этом
Например, если я наберу
#ifndef __cplusplus
#endif
Затмение сделает его серым.Это означает, что __cplusplus определен, но мой проект — C.
К сожалению, я не нашел решения.
Я исправил аналогичную проблему после проверки вкладки «Парсеры ошибок» в проекте Makefile в мастере нового проекта CDT, удалив анализатор ошибок CDT Visual C (я использую gcc)
В итоге я решил проблему следующим образом.Сначала я открыл свойства проекта, затем категорию «Общие C/C++» -> «Пути и символы».На вкладке «Символы» я добавил эту запись:
Symbol: offsetof(TYPE,MEMBER)
Value: ((ssize_t) &((TYPE *)0)->MEMBER)
Эти символы используются индексатором, но не передаются компилятору (по крайней мере, в проектах Makefile, я не пробовал это в других проектах C), поэтому они не переопределяют встроенное смещение GCC.
Я видел, как Eclipse делал это несколько раз, и использую его для Java.Обычно закрытие и повторное открытие файла меня исправляет (сбрасывает все, что не так).Обычно кажется, что это ошибка, которая БЫЛА, но была исправлена, а «кэш ошибок» не обновляется правильно.