Odd compilation error message

216 views Asked by At

The following snippet, in XE6

procedure TForm1.Test(CDS : TClientDataSet);
var
  AGuid : TGuid;
  lResult : Longint;
begin
  lResult := SysUtils.CreateGUID(AGuid);
  CDS.InsertRecord([AGuid, '', False]);
end;

produces the error message

[dcc32 Error] Unit1.pas(73): E2150 Bad argument type in variable type array constructor

Fwiw, in discovering this, I was trying to retrace my steps to a previous version of this routine where the compiler was generating the error

E2197 Constant object cannot be passed as var parameter 

on the line

  lResult := SysUtils.CreateGUID(AGuid);

despite the fact that what was provoking it turned out to be an error in the subsequent code.

3

There are 3 answers

1
David Heffernan On BEST ANSWER

This is the declaration of the InsertRecord method:

procedure InsertRecord(const Values: array of const);

The parameter is a variant open array. Variant open array parameters are implemented internally by being passed as TVarRec instances. And TVarRec cannot contain records. Since TGUID is a record, it cannot be passed in a variant open array parameter.

1
LU RD On

An array of const cannot take a TGuid record type.

An array of const takes items of a TVarRec defined as:

TVarRec = record
  case Byte of
    vtInteger:    (VInteger: Integer; VType: Byte);
    vtBoolean:    (VBoolean: Boolean);
    vtChar:       (VChar: Char);
    vtExtended:   (VExtended: PExtended);
    vtString:     (VString: PShortString);
    vtPointer:    (VPointer: Pointer);
    vtPChar:      (VPChar: PChar);
    vtObject:     (VObject: TObject);
    vtClass:      (VClass: TClass);
    vtWideChar:   (VWideChar: WideChar);
    vtPWideChar:  (VPWideChar: PWideChar);
    vtAnsiString: (VAnsiString: Pointer);
    vtCurrency:   (VCurrency: PCurrency);
    vtVariant:    (VVariant: PVariant);
3
Jason On

A type of TGuid is not permitted in array constructors.

TGuid is declared as:

  TGUID = packed record
    D1: LongWord;
    D2: Word;
    D3: Word;
    D4: array[0..7] of Byte;
    class operator Equal(const Left, Right: TGUID): Boolean;
    class operator NotEqual(const Left, Right: TGUID): Boolean;
    class function Empty: TGUID; static;
  end;

And according to the help, enumerations and records are not supported in array constructors:

... because enumerations and records are not supported in array constructors.

Presumably if you wanted the Guid stored, you should convert it to a string using GuidToString:

CDS.InsertRecord([GUIDToString(AGuid), '', False]);