Это ошибка в Solaris Studio?

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

Сообщение об ошибке было переформатировано с новыми строками для ясности:

"overload.cpp", line 44: Error:
runGenEntries<std::vector<int>>(const GenEntryRuleDriven<int>&, const std::vector<int>&)
and
runGenEntries<std::vector<int>>(const GenEntryRulesDriven<int>&, const std::vector<int>&)
have same extern name
"__1cNrunGenEntries4nDstdGvector4Cin0AJallocator4Ci_____6FrkTArk1_v_".
1 Error(s) detected.

Обратите внимание, что первый параметр двух функций runGenEntries отличается только одним символом ('s' в конце правила)

Это, кажется, происходит, когда первый параметр имеет тип:

const typename GenEntryRulesDrivenType<typename InputsType::value_type>::type

И не происходит, когда первый параметр вместо типа:

const typename GenEntryRulesDriven<typename InputsType::value_type>

Который решает тот же тип в конце концов!

Является ли это следствием неясного правила C++, реализованного только в Solaris? Или это ошибка Solaris Studio, которая искажает символы?

Полный источник

Следующий источник является компилируемым, как и на любом компиляторе.

Определение будет либо активировать код, который вызывает ошибку, либо активировать код, который должен был бы дать тот же результат (но на этот раз без ошибок):

#include <iostream>
#include <vector>

template<typename T>
struct GenEntryRulesDriven
{
   void foo() const
   {
   }
};

template<typename T>
struct GenEntryRuleDriven
{
   void bar() const
   {
   }
   std::string toto; // to have a different size than GenEntryRulesDriven
};


template <typename T>
struct GenEntryRulesDrivenType
{
   typedef GenEntryRulesDriven<T> type;
};

template <typename T>
struct GenEntryRuleDrivenType
{
   typedef GenEntryRuleDriven<T> type;
};

#if 1 // Gives an error

template <typename InputsType>
void runGenEntries(const typename GenEntryRulesDrivenType<
                          typename InputsType::value_type>::type &genEntry,
                          const InputsType& inputs)
{
   genEntry.foo();
}

template <typename InputsType>
void runGenEntries(const typename GenEntryRuleDrivenType<
                          typename InputsType::value_type>::type &genEntry,
                          const InputsType& inputs)
{
   genEntry.bar();
}

#else // No error but same types as above!

template <typename InputsType>
void runGenEntries(const typename GenEntryRulesDriven<
                          typename InputsType::value_type> &genEntry,
                          const InputsType& inputs)
{
   genEntry.foo();
}

template <typename InputsType>
void runGenEntries(const typename GenEntryRuleDriven<
                          typename InputsType::value_type> &genEntry,
                          const InputsType& inputs)
{
   genEntry.bar();
}

#endif

int
main()
{
   std::vector<int> v;
   GenEntryRulesDriven<int> rulesDriven;
   runGenEntries(rulesDriven, v);

   GenEntryRuleDriven<int> ruleDriven;
   runGenEntries(ruleDriven, v);

   return 0;
}

Этот код был скомпилирован на следующей платформе:

bash$ uname -a
SunOS pegasus 5.10 Generic_118855-33 i86pc i386 i86pc
bash$ CC -V
CC: Sun C++ 5.10 SunOS_i386 128229-07 2010/03/24

1 ответ

Решение

Короткий ответ

Краткий ответ: это, похоже, ошибка "unixable" 6532605 (я вижу, что на нее ссылаются многочисленные поиски в Google, но я не могу открыть саму ошибку на https://support.oracle.com/rs?type=bug&id=6532605).

Обходной путь, который делают разработчики Qt, - поместить определение метода в отдельный модуль компиляции (файл.cpp).

Фон

Если вы разобьете имя символа, на которое жалуется CC, вы увидите, что он компилирует const __type_0& аргумент в качестве первого аргумента:

$ echo __1cNrunGenEntries4nDstdGvector4Cin0AJallocator4Ci_____6FrkTArk1_v_ | c++filt
void runGenEntries<std::vector<int> >(const __type_0&,const __type_0&)
$

С g++ 3.4.6 на точно такой же коробке Solaris 10 символы из блока 1 раскладываются так:

runGenEntries<std, vector<int, std::allocator,<int>void> >(const GenEntryRuleDrivenType<int::value_type>::type(const GenEntryRuleDrivenType<int::value_type>&)&)
runGenEntries<std, vector<int, std::allocator,<int>void> >(const GenEntryRulesDrivenType<int::value_type>::type(const GenEntryRulesDrivenType<int::value_type>&)&)

Почему Oracle не может достичь того же, что мне не под силу.

Обходной путь Qt

Код Qt, на который ссылается этот баг / обходной путь, находится здесь.

Мы можем видеть, что есть две функции, объявленные с похожим именем:

Expression::Ptr DocFN::typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType);
Expression::Ptr IdFN::typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType);

И каждый компилируется в свой собственный источник ( здесь и здесь), чтобы обойти ошибку.

Неподдерживаемое решение: измените опцию искажения в ccfe

Отсюда вы также можете скомпилировать -Qoption ccfe -abiopt=mangle6, С этими флагами код успешно компилируется, и символы (размеченные):

void runGenEntries<std::vector<int> >(const GenEntryRuleDrivenType<__type_0::value_type>::type&,const __type_0&)
void runGenEntries<std::vector<int> >(const GenEntryRulesDrivenType<__type_0::value_type>::type&,const __type_0&)

Проблема в том, что эта опция компиляции не поддерживается, как написано Steve Clamage:

Наконец, у компилятора есть скрытая опция, позволяющая безоговорочно исправлять все известные ошибки. Мы не публикуем опцию, потому что

  • Это нестабильно. Будущие исправления или выпуски могут изменить искажение, если будет найдено больше ошибок.
  • Возможно, вам придется перекомпилировать весь код C++, включая сторонние библиотеки, используя эту опцию.
  • Если вы создаете библиотеку с этой опцией, это может быть несовместимо с кодом, скомпилированным без этой опции.
  • Как и все скрытые параметры, он может быть изменен или удален без уведомления.
  • Мы рассматриваем эту опцию как "использовать на свой страх и риск".

Если после всех этих предостережений вы все еще хотите попробовать вариант, вот он:

-Qoption ccfe -abiopt=mangle6

Обязательно добавьте его в каждую команду CC и перекомпилируйте все.

К счастью, ни одна из системных библиотек C++, поставляемых с Solaris или Studio, не подвержена этой ошибке или скрытому параметру, поэтому вам не нужно беспокоиться о различных версиях этих библиотек.

Другие вопросы по тегам