Hello! I have been interested in FPC trunk as of late for a project I am doing (Version=3.3.1-18324-g831e6c6d75-dirty, Windows 11 64 bit, although I don't believe the hash is as important here). I was experimenting with custom attributes, hoping they'd be at least somewhat usable. So I made this example:
program AttributeDateDemo;
{$mode objfpc}{$H+}
{$modeswitch prefixedattributes}
uses
SysUtils, Rtti;
type
DateTimeAttribute = class(TCustomAttribute)
private
FValue: TDateTime;
public
constructor Create(const RawDate: String);
property Value: TDateTime read FValue;
end;
constructor DateTimeAttribute.Create(const RawDate: String);
var
TempDate: TDateTime;
begin
ShortDateFormat := 'yyyy/mm/dd';
DateSeparator := '/';
if not TryStrToDate(RawDate, TempDate) then
raise Exception.CreateFmt('Invalid date: "%s"', [RawDate]);
FValue := TempDate;
end;
type
[DateTimeAttribute({$I %DATE%})]
TFoo = class
private
FProp: String;
public
[DateTime({$I %DATE%})]
procedure DoSomething;
[DateTime({$I %DATE%})]
property MyProp: String read FProp write FProp;
end;
procedure TFoo.DoSomething;
begin
Writeln('Doing something...');
end;
procedure PrintAttributes(AType: TRttiType);
var
Attr: TCustomAttribute;
Meth: TRttiMethod;
Prop: TRttiProperty;
begin
Writeln('Class attributes:');
for Attr in AType.GetAttributes do
if Attr is DateTimeAttribute then
Writeln(' ', FormatDateTime('dd.mm.yyyy', DateTimeAttribute(Attr).Value));
Writeln('Method attributes:');
for Meth in AType.GetMethods do
if Meth.Name = 'DoSomething' then
for Attr in Meth.GetAttributes do
if Attr is DateTimeAttribute then
Writeln(' ', FormatDateTime('dd.mm.yyyy', DateTimeAttribute(Attr).Value));
Writeln('Property attributes:');
for Prop in AType.GetProperties do
if Prop.Name = 'MyProp' then
for Attr in Prop.GetAttributes do
if Attr is DateTimeAttribute then
Writeln(' ', FormatDateTime('dd.mm.yyyy', DateTimeAttribute(Attr).Value));
end;
var
Ctx: TRttiContext;
Typ: TRttiType;
begin
Typ := Ctx.GetType(TFoo);
PrintAttributes(Typ);
Readln;
end.
Ignoring ShortDateFormat and DateSeparator there, which aren't the main point, I was expecting to see the same date on all attributes, however I got this instead:
Class attributes:
02.08.2025
Method attributes:
Property attributes:
which caught me by surprise. Am I doing something wrong in the
PrintAttributes procedure?
P.S. Is there a way to have attributes on parameters too? An example would be:
TMyClass = class
class procedure MyMethod([NotNull] Address: Pointer); static;
end;
which is at least possible in Delphi, after someone showed me how they would access it. My use case would be to have
[NonNull] and
[NonEmpty] attributes. I don't see a mention of them on the Free Pascal wiki page on custom attributes, and I have reasons to believe that's not in testing yet. Maybe it's a missing feature currently?

If you consider this topic to not be appropriate for this board, feel free to move it. Thanks for your attention!