Clang 5.0.0 Разница в Coliru / Godbolt с участием виртуальной функции - PullRequest
0 голосов
/ 04 октября 2018

Я действительно надеюсь, что мне чего-то не хватает, но рассмотрим следующий код:

struct Base {
    virtual void doit() = 0;
};

struct Derived : Base {
    void doit_internal(int n);

    void doit() {
        doit_internal(3);
    }
};

int main() {
    Derived derived;
}

Вкл. clang (5.0.0-3~16.04.1 (tags/RELEASE_500/final)) Я получаю ошибку компоновщика (undefined reference to Derived::doit_internal(int)').Интересно, зачем нужен doit_internal, если он вообще не вызывается.

Более того, на clang (version 5.0.0 (tags/RELEASE_500/final 334239)) он прекрасно компилируется.

Какойиз лязгов это правильно?Есть ли техническая причина / специфическая для платформы вещь / что-то в стандартном мандате doit_internal, который будет определен?

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Ваша программа некорректна, диагностика не требуется.При определении doit вы использовали odr doit_internal (вы написали выражение, которое вызывает doit_internal).Не имеет значения, что ваша программа может быть оптимизирована до return 0;

Стандарт прямо говорит:

[basic.def.odr]

4 Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе с помощью odr, вне исключенного оператора;Диагностика не требуется.Определение может явным образом появиться в программе, оно может быть найдено в стандартной или пользовательской библиотеке, или (при необходимости) оно неявно определено (см. [Class.ctor], [class.dtor] и [class.copy).]).Встроенная функция или переменная должна быть определена в каждой единице перевода, в которой она используется odr, за пределами отброшенного оператора.

У Clang есть право отклонить его или не отклонять.Это может даже изменить его поведение между выпусками, потому что ваша программа нарушает вышеуказанное требование.

0 голосов
/ 04 октября 2018

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

Если вы включите оптимизацию, то Clang пропускает реализацию doit, и ваше приложение успешно связывается: http://coliru.stacked -crooked.com / a / 8496f4e097d2f0ee

godbolt - это только компилятор, он ничего не связывает и не запускает, поэтому он не отображает ошибок ссылок.Обратите внимание, что в сборке все еще есть call Derived::doit_internal(int), поэтому, если вы возьмете эту сборку и попытаетесь связать ее, вы получите ту же ошибку компоновщика.

0 голосов
/ 04 октября 2018

В обоих случаях программа компилируется правильно.
Но на coliru происходит сбой во время процесса компоновки, так как нет определения Derived::doit_internal(int).

Compiler Explorer, не запускайте код,он просто показывает код сборки для кода C ++, определенного для текущего модуля перевода.Так что не нужно делать ссылки.Поскольку этап связывания не выполняется, проблема не обнаружена и ошибка не сообщается.

...