Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Delphi XE4, лёгкий баг в аттрибутах  [new]
Dimonka
Member

Откуда:
Сообщений: 958
Сразу зафигачу безразмерный листинг для тех кто такого не страшится.
+
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  rtti;

type
  // TSomeType = (stA, stB, stC);
  TSomeType = (stA, stB, stC, stD, stE, stF, stG, stH, stI, stJ, stK, stL, stM,
    stN, stO, stP, stQ, stR, stT, stU, stV, stW, stX, stY, stZ, st0, st1, st2,
    st3, st4, st5, st6, st7, st8, st9);
  TSomeTypeSet = set of TSomeType;
type
  SomeAttribute = class(TCustomAttribute)
  private
    FElements: TSomeTypeSet;
  public
    constructor Create({const }AttrElements: TSomeTypeSet);
    property Elements: TSomeTypeSet read FElements;
  end;

  [SomeAttribute([stA, stC])]
  TClassWithAttribute = class
  end;

function GetChildrenFor(aClass: TClass): TSomeTypeSet;
var
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  attribute: TCustomAttribute;
begin
  rttiContext := TRttiContext.Create;
  try
    rttiType := rttiContext.GetType(aClass);
    for attribute in rttiType.GetAttributes do  // <- падает здесь
      if attribute is SomeAttribute then
        Exit(SomeAttribute(attribute).Elements);
    Result := [];
  finally
    rttiContext.Free;
  end; // try to recover and return the DisplayLabel
end;

{ SomeAttribute }

constructor SomeAttribute.Create({const }AttrElements: TSomeTypeSet);
begin
  FElements := AttrElements;
end;

var
  Elements: TSomeTypeSet;
  El: TSomeType;
begin
  try
    Elements := GetChildrenFor(TClassWithAttribute);
    for El in Elements do
      Writeln(format('Element: %d', [integer(El)]));
    readln;
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      readln;
    end;
  end;
end.

Смысл бага в том, что в атрибут компилируется разный тип данных в зависимости от количества елементов в перечисляемом типе.
Если в типе TSomeType оставить несколько элементов - приведённая программа работает, иначе падает, потому что вместо сета в аттрибут передаётся массив из 2-х элементов и при создании атрибута инвокер конструктора падает с ошибкой Invalid class typecast.

Не знаю, есть ли здесь что обсуждать и решён ли баг в более новых версиях, но оставлю это здесь для информации.
3 янв 18, 19:33    [21080528]     Ответить | Цитировать Сообщить модератору
 Re: Delphi XE4, лёгкий баг в аттрибутах  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2754
Dimonka,

Если я не ошибаюсь, баг связан с некорректным определением размера множества. Пофикшен, вроде, в берлине только.
3 янв 18, 20:02    [21080580]     Ответить | Цитировать Сообщить модератору
 Re: Delphi XE4, лёгкий баг в аттрибутах  [new]
Dimonka
Member

Откуда:
Сообщений: 958
Попробовал передать список элементов как array of const, ошибка:
E2150 Bad argument type in variable type array constructor

Похоже Дельфи не очень любит сеты с количеством элементов > 32
3 янв 18, 20:09    [21080587]     Ответить | Цитировать Сообщить модератору
 Re: Delphi XE4, лёгкий баг в аттрибутах  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2754
Dimonka
Похоже Дельфи не очень любит сеты с количеством элементов > 32

Да, именно для таких сетов в RTTI размер хранится с минусом.
3 янв 18, 20:26    [21080612]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить