Как сделать сборку clang (например, msvc и gcc) с двойным объявлением функций extern "C" в разных пространствах имен - PullRequest
2 голосов
/ 26 апреля 2019

У меня есть этот проект, в который включены два других проекта, которые предоставляют заголовки для той же DLL.В одном заголовке объявления помещаются в пространство имен, в другом - нет.Это хорошо работает для GCC и MSVC, но я не могу убедить clang скомпилировать его. Поэтому минимальный пример будет:

xh:

#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__

namespace XX {
  struct Type {
    std::string name;
  };

  extern "C" int Func(Type);
}

incl.h:

#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__

struct Type {
  std::string name;
};

extern "C" int Func(Type);

main.cpp

#include "incl.h"
#include "x.h"

int main()
{
  return 0;
}

G ++ жалуется с предупреждением, но оно отключается с помощью # pragma GCC system_header.Итак, как мне заставить Clang создать такую ​​среду?

1 Ответ

3 голосов
/ 26 апреля 2019

[dcl.link] Не более одной функции с конкретным именем может иметь связь на языке Си. Два объявления для функции со связью языка C с тем же именем функции (игнорируя имена пространств имен, которые его определяют), что появляются в разных пространствах имен области ссылаются на одну и ту же функцию. ...

Как таковые, ::Func и XX::Func должны относиться к одной и той же функции. Но ваши два объявления имеют разные списки параметров - одно принимает параметр ::Type, а другое - XX::Type. Как таковые, они не могут быть одной и той же функцией, и, таким образом, указанное в кавычках правило нарушается, и программа плохо сформирована. Ever

Несколько способов исправить программу:

  • Переименуйте либо XX::Func, либо ::Func, чтобы они были отдельными функциями. Убедитесь, что для каждого есть определение.
  • В incl.h включить x.h и заменить определение ::Type на using XX::Type. Так что каждый Type относится к одному и тому же типу, и, следовательно, оба имени функции относятся к одной и той же функции. Убедитесь, что существует только одно определение.
  • В x.h включить incl.h и заменить определение XX::Type на using ::Type. Для достижения того же, что и выше.

Последнее, кстати, как некоторые стандартные реализации библиотеки реализуют <cstdlib> и его друзей. Они включают соответствующий заголовок стандартной библиотеки C (<stdlib.h> в случае <cstdlib>), который объявляет все в глобальном пространстве имен (единственное «пространство имен» в C), а затем они выбирают все стандартные функции и типы в std пространство имен с using ::whatever.


P.S. Не используйте #pragma GCC system_header (если вы не пишете системный заголовок). Он будет подавлять все предупреждения (кроме тех, которые выдаются директивой #warning).

...