Этот код нарушает одно правило определения? - PullRequest
1 голос
/ 24 февраля 2020

Некоторый код в AOSP10, похоже, нарушает ODR:

источник 1:

struct ExtentsParam
{
  void init (const OT::cff1::accelerator_t *_cff)
  {
    path_open = false;
    cff = _cff;
    bounds.init ();
  }
  void start_path ()         { path_open = true; }
  void end_path ()           { path_open = false; }
  bool is_path_open () const { return path_open; }
  bool    path_open;
  Bounds  bounds;
  const OT::cff1::accelerator_t *cff;
};

из: https://android.googlesource.com/platform/external/harfbuzz_ng/+/refs/heads/android10-gsi/src/hb-ot-cff1-table.cc

источник 2:

struct ExtentsParam
{
  void init ()
  {
    path_open = false;
    min_x.set_int (0x7FFFFFFF);
    min_y.set_int (0x7FFFFFFF);
    max_x.set_int (-0x80000000);
    max_y.set_int (-0x80000000);
  }
  void start_path ()         { path_open = true; }
  void end_path ()           { path_open = false; }
  bool is_path_open () const { return path_open; }
  void update_bounds (const Point &pt)
  {
    if (pt.x < min_x) min_x = pt.x;
    if (pt.x > max_x) max_x = pt.x;
    if (pt.y < min_y) min_y = pt.y;
    if (pt.y > max_y) max_y = pt.y;
  }
  bool  path_open;
  Number min_x;
  Number min_y;
  Number max_x;
  Number max_y;
};

от: https://android.googlesource.com/platform/external/harfbuzz_ng/+/refs/heads/android10-gsi/src/hb-ot-cff2-table.cc

скрипт сборки:

...
srcs: [
    ...
    "src/hb-ot-cff1-table.cc",
    "src/hb-ot-cff2-table.cc",
],
...

https://android.googlesource.com/platform/external/harfbuzz_ng/+/refs/heads/android10-gsi/Android.bp

Эти источники также встроены в одну общую библиотеку. Оба источника имеют определение «struct ExtentsParam», а их содержание абсолютно различно. Обе структуры, кажется, используются только локально.

Два источника имеют одинаковые имена, поэтому вероятность непреднамеренного дублирования имен мала. И вероятность нарушения ODR в Google может быть низкой.

Так ли это?

1 Ответ

5 голосов
/ 24 февраля 2020

Да : так как они оба находятся в глобальном пространстве имен, это абсолютно нарушает ODR.

Нет исключения для типов классов, используемых только в пределах единицы перевода, в которой они определены; программа может содержать только один тип класса с любым именем.

Это самое первое требование для соответствия критериям для исключения из этого правила:

В программе может быть более одного определения [..] тип класса [..] в программе, при условии, что каждое определение появляется в другой единице перевода, и при условии, что определения удовлетворяют следующие требования. [..] При условии, что такая сущность с именем D определена в более чем одной единице перевода, должны быть выполнены все следующие требования. [..] Каждое определение D должно состоять из одинаковой последовательности токенов [..] ( ref )

Разработчики просто «повезло», что компоновщик не пытался делать какие-либо шалости, которые приводят к симптомам этого нарушения.

Для этого и нужны пространства имен. Например, если тип класса используется только внутри единицы перевода, в которой он определен, он мог быть определен в анонимном пространстве имен.

...