Duplicate Identifier: Abhängig von Reihenfolge

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
around5
Beiträge: 18
Registriert: Fr 16. Aug 2024, 08:14

Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von around5 »

Hallo zusammen!

Gibt es eine Erklärung, warum die Reihenfolge der Deklaration (constructor vs property) bestimmt, ob FPC beim Kompilieren einen "Duplicate Identifier"-Error auswirft?

Keine Fehlermeldung:

Code: Alles auswählen

program project1;

{$mode ObjFPC}{$H+}

uses sysutils;

type
  Person = class
    _name: string;

    constructor Create(Name: string);

    property Name: string read _name write _name;
  end;

  constructor Person.Create(Name: string);
    begin
      inherited Create;
      self.Name := Name;
    end;

var
  Kunde: Person;

begin
  Kunde := Person.Create('Name');
  writeln(Kunde.Name);
  FreeAndNil(Kunde);
end.
Hier 'Error: Duplicate identifier "Name"' (beim constructor):

Code: Alles auswählen

program project1;

{$mode ObjFPC}{$H+}

uses
  SysUtils;

type
  Person = class
    _name: string;

    property Name: string read _name write _name;

    constructor Create(Name: string); // <- Hier die Fehlermeldung
  end;

  constructor Person.Create(Name: string);
    begin
      inherited Create;
      self.Name := Name;
    end;

var
  Kunde: Person;

begin
  Kunde := Person.Create('Name');
  writeln(Kunde.Name);
  FreeAndNil(Kunde);
end.
Theoretisch sollte es in beiden Fällen entweder einen Fehler geben, oder eben nicht. Die Parameter sind IMHO im Scope der procedure und sollten wie im ersten Fall (richtigerweise) vom Compiler ignoriert werden.

Anmerkung: Die "Konvention" mit "AName" ist mir bekannt.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1652
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von fliegermichl »

Properties müssen immer nach den Methoden definiert werden.

around5
Beiträge: 18
Registriert: Fr 16. Aug 2024, 08:14

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von around5 »

Warum müssen Properties immer nach Methoden definiert werden?
Funktioniert ja andersrum auch.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1652
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von fliegermichl »

Ja, sorry, hatte ich verwechselt.
Felddefinitionen müssen vor den Methoden definiert werden.

wp_xyz
Beiträge: 5192
Registriert: Fr 8. Apr 2011, 09:01

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von wp_xyz »

around5 hat geschrieben: Di 12. Nov 2024, 15:58 Gibt es eine Erklärung, warum die Reihenfolge der Deklaration (constructor vs property) bestimmt, ob FPC beim Kompilieren einen "Duplicate Identifier"-Error auswirft?

Code: Alles auswählen

type
  Person = class
    _name: string;

    constructor Create(Name: string);

    property Name: string read _name write _name;
  end;
Möglicherweise geht das im Modus Delphi. Im Default-Modus ObjFPC müssen übergebene Argumente immer anders heißen als Properties oder sonstige Felder. Nimm im Constructor die Variable "AName" ("A" für "Argument"), oder sonstwie, nur nicht "Name" und nicht "_name", dann sollte es funktionieren:

Code: Alles auswählen

type
  Person = class
    _name: string;

    constructor Create(AName: string);

    property Name: string read _name write _name;
  end;
  
  constructor Person.Create(AName: string);
    begin
      inherited Create;
      _name := AName;
    end;  

around5
Beiträge: 18
Registriert: Fr 16. Aug 2024, 08:14

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von around5 »

Mit der Compilerdirektive

Code: Alles auswählen

{$mode ObjFPC}
sollte ich doch im Modus Object-Pascal sein?

wp_xyz
Beiträge: 5192
Registriert: Fr 8. Apr 2011, 09:01

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von wp_xyz »

around5 hat geschrieben: Di 12. Nov 2024, 16:58 Mit der Compilerdirektive

Code: Alles auswählen

{$mode ObjFPC}
sollte ich doch im Modus Object-Pascal sein?
Ja, eben. Da darf der Name eines Methoden-Arguments NICHT mit einem Property-Namen übereinstimmen.

around5
Beiträge: 18
Registriert: Fr 16. Aug 2024, 08:14

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von around5 »

Wie ich aber in meinem ersten Post gezeigt habe, geht das. Es hängt anscheinend nur von der Reihenfolge ab.

Und dass das dem Compiler einfach "durchrutscht", glaube ich nicht. Eher glaube ich, dass der Compiler im anderen Fall zu "streng" ist.

wp_xyz
Beiträge: 5192
Registriert: Fr 8. Apr 2011, 09:01

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von wp_xyz »

Sorry, ich hätte genauer lesen müssen...

Warf
Beiträge: 2144
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von Warf »

Das ist schlicht und ergreifend ein Bug. Wenn der FPC einen Bezeichner parsed, schaut er in der Symboltabelle der Klasse nach ob es den Bezeichner schon gibt. Dabei wird aber nur die Symboltabelle durchsucht, Parameter werden aber nicht zur Symboltabelle der Klasse hinzugefügt sondern zur Parametertabelle der Methode, und damit werden diese nicht auf Kollisionen überprüft.

PS: Hab mirs mal genauer angeschaut das Problem ist eigentlich diese Zeile hier: https://gitlab.com/freepascal.org/fpc/s ... .pas#L2520

Praktisch wird beim parsen der implementation die parameter liste nochmal geparsed, aber hierbei wird nicht rekursiv gegen den Owner gechecked. Wenn man die Zeile entfernt wird der Fehler wie gewohnt geworfen. Die Frage ist nur ob was anderes dann kaputt geht (die zeile ist >18 jahre alt)

Ok grad tiefer reingeschaut, was die oben benannte Zeile eigentlich ermöglichst ist das nested funktionen shadown können (ob das gewollt ist sei mal dahin gestellt, aber es ist nunmal so). Was ich aber beim weiteren fixen gemerkt hab ist das es unfassbar viel code im FPC und der RTL gibt die diesen Bug "ausnutzen" um properties (die für gewöhnlich am ende der Funktion stehen) zu shadown.
Ein fix dieses bugs würde vermutlich massiv viel produktionscode nicht mehr kompilieren lassen. Also ist das vermutlich ein Bug der hier ist um zu bleiben

around5
Beiträge: 18
Registriert: Fr 16. Aug 2024, 08:14

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von around5 »

Wenn ich das Problem richtig verstanden habe, dann ginge ja auch der Weg andersrum, also diese Prüfung in dem Fehlerfall nicht zu stark einzuschränken, sondern zu lockern - oder übersehe ich da etwas? Das stärkere Einschränken führt 100% zu unzähligen Systembrüchen bei vielen Implementierungen.

Warf
Beiträge: 2144
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von Warf »

Die strikteren shadowing regeln sind tatsächlich eine gewollte Eigenschaft des mode ObjFpc und ganz klar dokumentiert: https://www.freepascal.org/docs-html/prog/progse76.html
9. Parameters in class methods cannot have the same names as class properties.
Die Frage wie man damit Umgeht ist natürlich interessant. Zum einen stimmt es das man damit extrem viele code bases bricht, zum anderen kann man natürlich auch sagen: ätsch bätsch, wenn ihr euch nicht an die Dokumentation haltet seid ihr selbst Schuld

around5
Beiträge: 18
Registriert: Fr 16. Aug 2024, 08:14

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von around5 »

Die "Regel 9" verstehe ich so, dass damit "versehentliches Shadowing" bereits beim Kompilieren erkannt wird und somit eine weitere Fehlerklasse ausgeschlossen ist - was ja absolut sinnvoll ist.

So gesehen sollte FPC den Fehler richtig melden. Damit aber bestehender Code nicht reihenweise ungültig wird, wäre es gut einen Compiler-Schalter (analog zu "-Sh" bzw. "{$H+}", der ja auch Regel 10 anpasst) zu haben, der das Shadowing dennoch zulässt (in beiden oben genannten Fällen!). Dieser Schalter ist per Default natürlich "disabled" bei bestehenden Projekten aber "enabled" (sodass kein "Bruch" entsteht), und sollte pro Unit vice/versa en/disabled werden können. Damit wäre auch das Verhalten im Code dokumentiert, es wäre damit "gewollt", und man stolpert ggf. nicht über ein "unerklärliches" Problem, dass ja laut Spezifikation nicht existieren dürfte.

Das ist natürlich nicht ganz sauber, aber 18 Jahre das Rad zurückdrehen geht ja nicht mehr.

Warf
Beiträge: 2144
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Duplicate Identifier: Abhängig von Reihenfolge

Beitrag von Warf »

Naja es ist halt vor allem im Unterschied zu Mode Delphi gedacht:

Code: Alles auswählen

{$Mode Delphi}

type
  TMyClass = class
    A: Integer;
    procedure Foo(A: Integer); // Funktioniert
  end;
Das geht weil Delphi Shadowing explizit erlaubt, während Mode ObjFPC shadowing explizit verbietet

Code: Alles auswählen

{$Mode ObjFPC}

type
  TMyClass = class
    A: Integer;
    procedure Foo(A: Integer); // Error
  end;
Es war nie gedacht das das shadown von Properties die danach folgen funktionieren soll, es ist nur etwas was man (oftmals auch ausversehen) einfach ausgenutzt wurde.

Übrigens, beim reinschauen hab ich einen ähnlichen bug gefunden, FPC akzeptiert auch das:

Code: Alles auswählen

{$mode tp}

function Foo(Foo: Integer): Integer;
begin

end;
Und das ist komplett Kaputt denn in mode TurboPascal gibts keine Result variable, da muss man den Funktionsnamen benutzen:

Code: Alles auswählen

function Foo: Integer;
  Foo:=42; // Equivalent zur Result:=42 in Mode FPC
end;
Was natürlich nicht geht wenn der Funktionsname von einem Parameter geshadowed wird. Variablen funktionieren übrigens nicht:

Code: Alles auswählen

function Foo: Integer;
var
  Foo: Integer; // Duplicate Identifier
begin
end; 
Plus Rekursion ist nicht möglich wenn der Name geshadowed wird.

Antworten