Несовместимый тип указателя GCC с использованием typedef

у меня есть код, который скомпилирован отлично под GCC 4.8.4. Недавно я обновил свою систему и теперь имею GCC 5.2.1, и я получаю предупреждение о несовместимых типах указателей. Я извлек проблему на небольшой пример, который воспроизводит ошибку:

typedef const double ConstSpiceDouble;
void foo(const double (*)[3]); 

int main(int argc, char **argv) {
  double a[3][3] = {{1,2,3},{1,2,3},{1,2,3}};

  foo((ConstSpiceDouble (*)[3])a);

  return 0;
}

в реальном коде typedef, определение функции и приведение типа находятся в библиотеке вне моего контроля, иначе я бы просто исправил приведение и функцию для соответствия. Вот сообщение, которое я получаю от компилятор:

$ gcc -Werror -c test.c
test.c: In function ‘main’:
test.c:9:7: error: passing argument 1 of ‘foo’ from incompatible pointer type [-Werror=incompatible-pointer-types]
   foo((ConstSpiceDouble (*)[3])a);
       ^
test.c:4:6: note: expected ‘const double (*)[3]’ but argument is of type ‘const ConstSpiceDouble (*)[3] {aka const double (*)[3]}’
 void foo(const double (*)[3]);
      ^
cc1: all warnings being treated as errors

Примечание от gcc особенно беспокоит, поскольку, похоже, признает, что два типа идентичны, но все равно жалуется.

2 ответов


консенсус здесь и в других местах, похоже, заключается в том, что GCC делает что-то неожиданное с const и typedef. Я не знаю, что неожиданное обязательно приравнивается к ошибке,но это для разработчиков GCC.

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

Это не столько "решено", сколько" обработано", но любое дальнейшее понимание, вероятно, должно исходить от разработчиков GCC.


Если вы набираете cast 'a', чтобы быть ConstSpiceDouble, GCC делает что-то неожиданное с const и typedef, по которому в конечном итоге тип становится "const const double". Это вы можете увидеть в сообщение об ошибке "const ConstSpiceDouble", который приравнивается к "const const double", это не работает.

решение это либо сказать, что " a "является const double или сказать, что" A "является ConstSpiceDouble перед параметром "a" в foo функция

typedef const double ConstSpiceDouble;
void foo(const double (*)[3]); 

int main(int argc, char **argv) {

  const double a[3][3] = {{1,2,3},{1,2,3},{1,2,3}};
  // or ConstSpiceDouble a[3][3] = {{1,2,3},{1,2,3},{1,2,3}};

  foo(a);

  return 0;
}

"const" pre-pending кажется новой функцией в последних версиях gcc, но в этом я не уверен : (