1 {
2   Examples:
3     ./testpassrc --suite=TTestResolver.TestEmpty
4 }
5 (*
6   CheckReferenceDirectives:
7     {#a} label "a", labels all elements at the following token
8     {@a} reference "a", search at next token for an element e with
9            TResolvedReference(e.CustomData).Declaration points to an element
10            labeled "a".
11     {=a} is "a", search at next token for a TPasAliasType t with t.DestType
12            points to an element labeled "a"
13 *)
14 unit tcresolver;
15 
16 {$mode objfpc}{$H+}
17 
18 interface
19 
20 uses
21   Classes, SysUtils, contnrs, strutils, fpcunit, testregistry,
22   PasTree, PScanner, PParser, PasResolver, PasResolveEval,
23   tcbaseparser;
24 
25 type
26   TSrcMarkerKind = (
27     mkLabel,
28     mkResolverReference,
29     mkDirectReference
30     );
31   PSrcMarker = ^TSrcMarker;
32   TSrcMarker = record
33     Kind: TSrcMarkerKind;
34     Filename: string;
35     Row: cardinal;
36     StartCol, EndCol: integer; // token start, end column
37     Identifier: string;
38     Next: PSrcMarker;
39   end;
40 
41 const
42   SrcMarker: array[TSrcMarkerKind] of char = (
43     '#', // mkLabel
44     '@', // mkResolverReference
45     '='  // mkDirectReference
46     );
47 type
endernull48   TOnFindUnit = function(Sender: TPasResolver;
49     const aUnitName, InFilename: String;
50     NameExpr, InFileExpr: TPasExpr): TPasModule of object;
51   TOnContinueParsing = procedure(Sender: TPasResolver) of object;
52 
53   { TTestEnginePasResolver }
54 
55   TTestEnginePasResolver = class(TPasResolver)
56   private
57     FFilename: string;
58     FModule: TPasModule;
59     FOnFindUnit: TOnFindUnit;
60     FParser: TPasParser;
61     FStreamResolver: TStreamResolver;
62     FScanner: TPascalScanner;
63     FSource: string;
64     procedure SetModule(AValue: TPasModule);
65   public
66     constructor Create;
67     destructor Destroy; override;
68     procedure ReleaseUsedUnits;
CreateElementnull69     function CreateElement(AClass: TPTreeElement; const AName: String;
70       AParent: TPasElement; AVisibility: TPasMemberVisibility;
71       const ASrcPos: TPasSourcePos; TypeParams: TFPList = nil): TPasElement;
72       overload; override;
FindUnitnull73     function FindUnit(const AName, InFilename: String; NameExpr,
74       InFileExpr: TPasExpr): TPasModule; override;
75     procedure UsedInterfacesFinished(Section: TPasSection); override;
76     property OnFindUnit: TOnFindUnit read FOnFindUnit write FOnFindUnit;
77     property Filename: string read FFilename write FFilename;
78     property StreamResolver: TStreamResolver read FStreamResolver write FStreamResolver;
79     property Scanner: TPascalScanner read FScanner write FScanner;
80     property Parser: TPasParser read FParser write FParser;
81     property Source: string read FSource write FSource;
82     property Module: TPasModule read FModule write SetModule;
83   end;
84 
85   { TTestResolverMessage }
86 
87   TTestResolverMessage = class
88   public
89     Id: int64;
90     MsgType: TMessageType;
91     MsgNumber: integer;
92     Msg: string;
93     SourcePos: TPasSourcePos;
94   end;
95 
96   TTestResolverReferenceData = record
97     Filename: string;
98     Row: integer;
99     StartCol: integer;
100     EndCol: integer;
101     Found: TFPList; // list of TPasElement at this token
102   end;
103   PTestResolverReferenceData = ^TTestResolverReferenceData;
104 
105   TSystemUnitPart = (
106     supTObject,
107     supTVarRec,
108     supTTypeKind
109     );
110   TSystemUnitParts = set of TSystemUnitPart;
111 
112   { TCustomTestResolver }
113 
114   TCustomTestResolver = Class(TTestParser)
115   Private
116     FHub: TPasResolverHub;
117     {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
118     FStartElementRefCount: int64;
119     {$ENDIF}
120     FFirstStatement: TPasImplBlock;
121     FModules: TObjectList;// list of TTestEnginePasResolver
122     FResolverEngine: TTestEnginePasResolver;
123     FResolverMsgs: TObjectList; // list of TTestResolverMessage
124     FResolverGoodMsgs: TFPList; // list of TTestResolverMessage marked as expected
GetModuleCountnull125     function GetModuleCount: integer;
GetModulesnull126     function GetModules(Index: integer): TTestEnginePasResolver;
GetMsgCountnull127     function GetMsgCount: integer;
GetMsgsnull128     function GetMsgs(Index: integer): TTestResolverMessage;
129     procedure OnPasResolverContinueParsing(Sender: TPasResolver);
OnPasResolverFindUnitnull130     function OnPasResolverFindUnit(SrcResolver: TPasResolver;
131       const aUnitName, InFilename: String; NameExpr, InFileExpr: TPasExpr): TPasModule;
132     procedure OnFindReference(El: TPasElement; FindData: pointer);
133     procedure OnCheckElementParent(El: TPasElement; arg: pointer);
134     procedure FreeSrcMarkers;
135     procedure OnPasResolverLog(Sender: TObject; const Msg: String);
136     procedure OnScannerDirective(Sender: TObject; Directive, Param: String;
137       var Handled: boolean);
138     procedure OnScannerLog(Sender: TObject; const Msg: String);
139   Protected
140     FirstSrcMarker, LastSrcMarker: PSrcMarker;
141     Procedure SetUp; override;
142     Procedure TearDown; override;
143     procedure CreateEngine(var TheEngine: TPasTreeContainer); override;
144     procedure ParseModule; override;
145     procedure ParseProgram; virtual;
146     procedure ParseUnit; virtual;
147     procedure CheckReferenceDirectives; virtual;
148     procedure CheckResolverHint(MsgType: TMessageType; MsgNumber: integer;
149       Msg: string; Marker: PSrcMarker = nil); virtual;
150     procedure CheckResolverUnexpectedHints(WithSourcePos: boolean = false); virtual;
151     procedure CheckResolverException(Msg: string; MsgNumber: integer);
152     procedure CheckParserException(Msg: string; MsgNumber: integer);
153     procedure CheckAccessMarkers; virtual;
154     procedure CheckParamsExpr_pkSet_Markers; virtual;
155     procedure CheckAttributeMarkers; virtual;
156     procedure GetSrc(Index: integer; out SrcLines: TStringList; out aFilename: string);
FindElementsAtnull157     function FindElementsAt(aFilename: string; aLine, aStartCol, aEndCol: integer): TFPList;// list of TPasElement
FindElementsAtnull158     function FindElementsAt(aMarker: PSrcMarker; ErrorOnNoElements: boolean = true): TFPList;// list of TPasElement
FindSrcLabelnull159     function FindSrcLabel(const Identifier: string): PSrcMarker;
FindElementsAtSrcLabelnull160     function FindElementsAtSrcLabel(const Identifier: string; ErrorOnNoElements: boolean = true): TFPList;// list of TPasElement
161     procedure WriteSources(const aFilename: string; aRow, aCol: integer);
162     procedure RaiseErrorAtSrc(Msg: string; const aFilename: string; aRow, aCol: integer);
163     procedure RaiseErrorAtSrcMarker(Msg: string; aMarker: PSrcMarker);
164     procedure HandleError(CurEngine: TTestEnginePasResolver; E: Exception);
165   Public
166     constructor Create; override;
167     destructor Destroy; override;
FindModuleWithFilenamenull168     function FindModuleWithFilename(aFilename: string): TTestEnginePasResolver;
AddModulenull169     function AddModule(aFilename: string): TTestEnginePasResolver;
AddModuleWithSrcnull170     function AddModuleWithSrc(aFilename, Src: string): TTestEnginePasResolver;
AddModuleWithIntfImplSrcnull171     function AddModuleWithIntfImplSrc(aFilename, InterfaceSrc,
172       ImplementationSrc: string): TTestEnginePasResolver;
173     procedure AddSystemUnit(Parts: TSystemUnitParts = []);
174     procedure StartProgram(NeedSystemUnit: boolean; SystemUnitParts: TSystemUnitParts = []);
175     procedure StartUnit(NeedSystemUnit: boolean);
176     property Modules[Index: integer]: TTestEnginePasResolver read GetModules;
177     property ModuleCount: integer read GetModuleCount;
178     property Hub: TPasResolverHub read FHub;
179     property ResolverEngine: TTestEnginePasResolver read FResolverEngine;
180     property MsgCount: integer read GetMsgCount;
181     property Msgs[Index: integer]: TTestResolverMessage read GetMsgs;
182   end;
183 
184   { TTestResolver }
185 
186   TTestResolver = Class(TCustomTestResolver)
187   Published
188     Procedure TestEmpty;
189 
190     // alias
191     Procedure TestAliasType;
192     Procedure TestAlias2Type;
193     Procedure TestAliasTypeRefs;
194     Procedure TestAliasOfVarFail;
195     Procedure TestAliasType_UnitPrefix;
196     Procedure TestAliasType_UnitPrefix_CycleFail;
197     Procedure TestAliasTypeNotFoundPosition;
198     Procedure TestTypeAliasType;
199 
200     // vars, const
201     Procedure TestVarLongint;
202     Procedure TestVarInteger;
203     Procedure TestConstInteger;
204     Procedure TestConstInteger2;
205     Procedure TestDuplicateVar;
206     Procedure TestVarInitConst;
207     Procedure TestVarOfVarFail;
208     Procedure TestConstOfVarFail;
209     Procedure TestTypedConstWrongExprFail;
210     Procedure TestVarWrongExprFail;
211     Procedure TestArgWrongExprFail;
212     Procedure TestTypedConstInConstExprFail;
213     Procedure TestVarExternal;
214     Procedure TestVarNoSemicolonBeginFail;
215     Procedure TestConstIntOperators;
216     Procedure TestConstBitwiseOps;
217     Procedure TestConstExternal;
218     Procedure TestIntegerTypeCast;
219     Procedure TestConstFloatOperators;
220     Procedure TestFloatTypeCast;
221     Procedure TestCurrency;
222     Procedure TestWritableConst;
223     Procedure TestWritableConst_AssignFail;
224     Procedure TestWritableConst_PassVarFail;
225 
226     // boolean
227     Procedure TestBoolTypeCast;
228     Procedure TestConstBoolOperators;
229     Procedure TestBoolSet_Const;
230     Procedure TestBool_ForIn;
231     Procedure TestBool_Assert;
232     Procedure TestBool_AssertSysutils;
233 
234     // integer range
235     Procedure TestIntegerRange;
236     Procedure TestIntegerRangeHighLowerLowFail;
237     Procedure TestIntegerRangeLowHigh;
238     Procedure TestAssignIntRangeWarning;
239     Procedure TestByteRangeWarning;
240     Procedure TestByteRangeWarningOff;
241     Procedure TestCustomIntRangeWarning;
242     Procedure TestIntSet_Const;
243     Procedure TestIntSet_ConstDuplicateElement;
244     Procedure TestInt_ForIn;
245 
246     // strings
247     Procedure TestChar_BuiltInProcs;
248     Procedure TestString_BuiltInProcs;
249     Procedure TestString_Element;
250     Procedure TestStringElement_MissingArgFail;
251     Procedure TestStringElement_IndexNonIntFail;
252     Procedure TestStringElement_AsVarArgFail;
253     Procedure TestString_DoubleQuotesFail;
254     Procedure TestString_ShortstringType;
255     Procedure TestConstStringOperators;
256     Procedure TestConstUnicodeStringOperators;
257     Procedure TestCharSet_Const;
258     Procedure TestCharSet_Custom;
259     Procedure TestCharAssignStringFail;
260     Procedure TestChar_ForIn;
261 
262     // enums and sets
263     Procedure TestEnums;
264     Procedure TestEnumRangeFail;
265     Procedure TestEnumDotValueFail;
266     Procedure TestSets;
267     Procedure TestSetOperators;
268     Procedure TestEnumParams;
269     Procedure TestSetParams;
270     Procedure TestSetFunctions;
271     Procedure TestEnumHighLow;
272     Procedure TestEnumOrd;
273     Procedure TestEnumPredSucc;
274     Procedure TestEnum_EqualNilFail;
275     Procedure TestEnum_CastIntegerToEnum;
276     Procedure TestEnum_Str;
277     Procedure TestConstEnumOperators;
278     Procedure TestEnumSetConstRange;
279     Procedure TestEnumSet_AnonymousEnumtype;
280     Procedure TestEnumSet_AnonymousEnumtypeName;
281     Procedure TestEnumSet_Const;
282     Procedure TestSet_IntRange_Const;
283     Procedure TestSet_Byte_Const;
284     Procedure TestEnumRange;
285     Procedure TestEnum_ForIn;
286     Procedure TestEnum_ForInRangeFail;
287     Procedure TestEnum_ScopedEnums;
288     Procedure TestEnum_ScopedEnumsFail;
289 
290     // operators
291     Procedure TestPrgAssignment;
292     Procedure TestPrgProcVar;
293     Procedure TestUnitProcVar;
294     Procedure TestAssignIntegers;
295     Procedure TestAssignString;
296     Procedure TestAssignIntToStringFail;
297     Procedure TestAssignStringToIntFail;
298     Procedure TestIntegerOperators;
299     Procedure TestIntegerBoolFail;
300     Procedure TestBooleanOperators;
301     Procedure TestStringOperators;
302     Procedure TestWideCharOperators;
303     Procedure TestFloatOperators;
304     Procedure TestCAssignments;
305     Procedure TestTypeCastBaseTypes;
306     Procedure TestTypeCastAliasBaseTypes;
307     Procedure TestTypeCastStrToIntFail;
308     Procedure TestTypeCastStrToCharFail;
309     Procedure TestTypeCastIntToStrFail;
310     Procedure TestTypeCastDoubleToStrFail;
311     Procedure TestTypeCastDoubleToIntFail;
312     Procedure TestTypeCastDoubleToBoolFail;
313     Procedure TestTypeCastBooleanToDoubleFail;
314     Procedure TestAssign_Access;
315     Procedure TestAssignedIntFail;
316 
317     // misc built-in functions
318     Procedure TestHighLow;
319     Procedure TestStr_BaseTypes;
320     Procedure TestStr_StringFail;
321     Procedure TestStr_CharFail;
322     Procedure TestIncDec;
323     Procedure TestIncStringFail;
324     Procedure TestTypeInfo;
325     Procedure TestTypeInfo_FailRTTIDisabled;
326     Procedure TestGetTypeKind;
327 
328     // statements
329     Procedure TestForLoop;
330     Procedure TestForLoop_NestedSameVarFail;
331     Procedure TestForLoop_AssignVarFail;
332     Procedure TestForLoop_PassVarFail;
333     Procedure TestStatements;
334     Procedure TestCaseOfInt;
335     Procedure TestCaseOfIntExtConst;
336     Procedure TestCaseIntDuplicateFail;
337     Procedure TestCaseOfStringDuplicateFail;
338     Procedure TestCaseOfStringRangeDuplicateFail;
339     Procedure TestCaseOfBaseType;
340     Procedure TestCaseOfExprNonOrdFail;
341     Procedure TestCaseOfIncompatibleValueFail;
342     Procedure TestTryStatement;
343     Procedure TestTryExceptOnNonTypeFail;
344     Procedure TestTryExceptOnNonClassFail;
345     Procedure TestRaiseNonVarFail;
346     Procedure TestRaiseNonClassFail;
347     Procedure TestRaiseDescendant;
348     Procedure TestStatementsRefs;
349     Procedure TestRepeatUntilNonBoolFail;
350     Procedure TestWhileDoNonBoolFail;
351     Procedure TestIfThen;
352     Procedure TestIfThenNonBoolFail;
353     Procedure TestIfAssignMissingSemicolonFail;
354     Procedure TestForLoopVarNonVarFail;
355     Procedure TestForLoopStartIncompFail;
356     Procedure TestForLoopEndIncompFail;
357     Procedure TestSimpleStatement_VarFail;
358     Procedure TestLabelStatementFail;
359     Procedure TestLabelStatementDelphiFail;
360 
361     // units
362     Procedure TestUnitForwardOverloads;
363     Procedure TestUnitIntfInitialization;
364     Procedure TestUnitUseSystem;
365     Procedure TestUnitUseIntf;
366     Procedure TestUnitUseImplFail;
367     Procedure TestUnit_DuplicateUsesFail;
368     Procedure TestUnit_DuplicateUsesIntfImplFail;
369     Procedure TestUnit_NestedFail;
370     Procedure TestUnitUseDotted;
371     Procedure TestUnit_ProgramDefaultNamespace;
372     Procedure TestUnit_DottedIdentifier;
373     Procedure TestUnit_DottedPrg;
374     Procedure TestUnit_DottedUnit;
375     Procedure TestUnit_DottedExpr;
376     Procedure TestUnit_DuplicateDottedUsesFail;
377     Procedure TestUnit_DuplicateUsesDiffName;
378     Procedure TestUnit_Unit1DotUnit2Fail;
379     Procedure TestUnit_InFilename;
380     Procedure TestUnit_InFilenameAliasDelphiFail;
381     Procedure TestUnit_InFilenameInUnitDelphiFail;
382     Procedure TestUnit_MissingUnitErrorPos;
383     Procedure TestUnit_UnitNotFoundErrorPos;
384     Procedure TestUnit_AccessIndirectUsedUnitFail;
385     Procedure TestUnit_Intf1Impl2Intf1;
386     Procedure TestUnit_Intf1Impl2Intf1_Duplicate;
387 
388     // procs
389     Procedure TestProcParam;
390     Procedure TestProcParamAccess;
391     Procedure TestProcParamConstRef;
392     Procedure TestFunctionResult;
393     Procedure TestProcedureResultFail;
394     Procedure TestProc_ArgVarPrecisionLossFail;
395     Procedure TestProc_ArgVarTypeAliasObjFPC;
396     Procedure TestProc_ArgVarTypeAliasDelphi;
397     Procedure TestProc_ArgVarTypeAliasDelphiMismatchFail;
398     Procedure TestProc_ArgMissingSemicolonFail;
399     Procedure TestProcOverload;
400     Procedure TestProcOverloadImplDuplicateFail;
401     Procedure TestProcOverloadImplDuplicate2Fail;
402     Procedure TestProcOverloadOtherUnit;
403     Procedure TestProcOverloadWithBaseTypes;
404     Procedure TestProcOverloadWithBaseTypes2;
405     Procedure TestProcOverloadWithDefaultArgs;
406     Procedure TestProcOverloadNearestHigherPrecision;
407     Procedure TestProcOverloadForLoopIntDouble;
408     Procedure TestProcOverloadStringArgCount;
409     Procedure TestProcCallLowPrecision;
410     Procedure TestProcOverloadUntyped;
411     Procedure TestProcOverloadMultiLowPrecisionFail;
412     Procedure TestProcOverload_TypeAlias;
413     Procedure TestProcOverload_TypeAliasLiteralFail;
414     Procedure TestProcOverloadWithClassTypes;
415     Procedure TestProcOverloadWithInhClassTypes;
416     Procedure TestProcOverloadWithInhAliasClassTypes;
417     Procedure TestProcOverloadWithInterfaces;
418     Procedure TestProcOverloadBaseTypeOtherUnit;
419     Procedure TestProcOverloadBaseProcNoHint;
420     Procedure TestProcOverload_UnitOrderFail;
421     Procedure TestProcOverload_UnitSameSignature;
422     Procedure TestProcOverloadDelphiMissingNextOverload;
423     Procedure TestProcOverloadDelphiMissingPrevOverload;
424     Procedure TestProcOverloadDelphiUnit;
425     Procedure TestProcOverloadDelphiUnitNoOverloadFail;
426     Procedure TestProcOverloadObjFPCUnitWithoutOverloadMod;
427     Procedure TestProcOverloadDelphiWithObjFPC;
428     Procedure TestProcOverloadDelphiOverride;
429     Procedure TestProcDuplicate;
430     Procedure TestNestedProc;
431     Procedure TestNestedProc_ResultString;
432     Procedure TestFuncAssignFail;
433     Procedure TestForwardProc;
434     Procedure TestForwardProcUnresolved;
435     Procedure TestNestedForwardProc;
436     Procedure TestNestedForwardProcUnresolved;
437     Procedure TestForwardProcFuncMismatch;
438     Procedure TestForwardFuncResultMismatch;
439     Procedure TestForwardProcAssemblerMismatch;
440     Procedure TestUnitIntfProc;
441     Procedure TestUnitIntfProcUnresolved;
442     Procedure TestUnitIntfMismatchArgName;
443     Procedure TestProcOverloadIsNotFunc;
444     Procedure TestProcCallMissingParams;
445     Procedure TestProcArgDefaultValue;
446     Procedure TestProcArgDefaultValueTypeMismatch;
447     Procedure TestProcPassConstToVar;
448     Procedure TestBuiltInProcCallMissingParams;
449     Procedure TestAssignFunctionResult;
450     Procedure TestAssignProcResultFail;
451     Procedure TestFunctionResultInCondition;
452     Procedure TestExit;
453     Procedure TestBreak;
454     Procedure TestContinue;
455     Procedure TestProcedureExternal;
456     Procedure TestProc_UntypedParam_Forward;
457     Procedure TestProc_Varargs;
458     Procedure TestProc_VarargsOfT;
459     Procedure TestProc_VarargsOfTMismatch;
460     Procedure TestProc_ParameterExprAccess;
461     Procedure TestProc_FunctionResult_DeclProc;
462     Procedure TestProc_TypeCastFunctionResult;
463     Procedure TestProc_ImplicitCalls;
464     Procedure TestProc_Absolute;
465     Procedure TestProc_LocalInit;
466     Procedure TestProc_ExtNamePropertyFail;
467 
468     // anonymous procs
469     Procedure TestAnonymousProc_Assign;
470     Procedure TestAnonymousProc_AssignSemicolonFail;
471     Procedure TestAnonymousProc_Assign_ReferenceToMissingFail;
472     Procedure TestAnonymousProc_Assign_WrongParamListFail;
473     Procedure TestAnonymousProc_Arg;
474     Procedure TestAnonymousProc_ArgSemicolonFail;
475     Procedure TestAnonymousProc_EqualFail;
476     Procedure TestAnonymousProc_ConstFail;
477     Procedure TestAnonymousProc_Assembler;
478     Procedure TestAnonymousProc_NameFail;
479     Procedure TestAnonymousProc_StatementFail;
480     Procedure TestAnonymousProc_Typecast_ObjFPC;
481     Procedure TestAnonymousProc_Typecast_Delphi;
482     Procedure TestAnonymousProc_TypecastToResultFail;
483     Procedure TestAnonymousProc_WithDo;
484     Procedure TestAnonymousProc_ExceptOn;
485     Procedure TestAnonymousProc_Nested;
486     Procedure TestAnonymousProc_ForLoop;
487 
488     // record
489     Procedure TestRecord;
490     Procedure TestRecordVariant;
491     Procedure TestRecordVariantNested;
492     Procedure TestRecord_WriteConstParamFail;
493     Procedure TestRecord_WriteConstParam_WithDoFail;
494     Procedure TestRecord_WriteNestedConstParamFail;
495     Procedure TestRecord_WriteNestedConstParamWithDoFail;
496     Procedure TestRecord_TypeCast;
497     Procedure TestRecord_NewDispose;
498     Procedure TestRecord_Const;
499     Procedure TestRecord_Const_DuplicateFail;
500     Procedure TestRecord_Const_ExprMismatchFail;
501     Procedure TestRecord_Const_MissingHint;
502     Procedure TestRecord_Const_UntypedFail;
503     Procedure TestRecord_Const_NestedRecord;
504     Procedure TestRecord_Const_Variant;
505     Procedure TestRecord_Default;
506     Procedure TestRecord_VarExternal;
507     Procedure TestRecord_VarSelfFail;
508 
509     // advanced record
510     Procedure TestAdvRecord;
511     Procedure TestAdvRecord_Private;
512     Procedure TestAdvRecord_StrictPrivate;
513     Procedure TestAdvRecord_StrictPrivateFail;
514     Procedure TestAdvRecord_MethodImplMissingFail;
515     Procedure TestAdvRecord_VarConst;
516     Procedure TestAdvRecord_RecVal_ConstFail;
517     Procedure TestAdvRecord_RecVal_ClassVarFail;
518     Procedure TestAdvRecord_LocalForwardType;
519     Procedure TestAdvRecord_Constructor_NewInstance;
520     Procedure TestAdvRecord_ConstructorNoParamsFail;
521     Procedure TestAdvRecord_ClassConstructor;
522     Procedure TestAdvRecord_ClassConstructorParamsFail;
523     Procedure TestAdvRecord_ClassConstructor_CallFail;
524     Procedure TestAdvRecord_ClassConstructorDuplicateFail;
525     Procedure TestAdvRecord_NestedRecordType;
526     Procedure TestAdvRecord_NestedArgConstFail;
527     Procedure TestAdvRecord_Property;
528     Procedure TestAdvRecord_ClassProperty;
529     Procedure TestAdvRecord_PropertyDefault;
530     Procedure TestAdvRecord_RecordAsFuncResult;
531     Procedure TestAdvRecord_InheritedFail;
532     Procedure TestAdvRecord_ForInEnumerator;
533     Procedure TestAdvRecord_InFunctionFail;
534     Procedure TestAdvRecord_SubClass;
535 
536     // class
537     Procedure TestClass;
538     Procedure TestClassDefaultInheritance;
539     Procedure TestClassTripleInheritance;
540     Procedure TestClassInheritanceCycleFail;
541     Procedure TestClassDefaultVisibility;
542     Procedure TestClassForward;
543     Procedure TestClassForwardAsAncestorFail;
544     Procedure TestClassForwardNotResolved;
545     Procedure TestClassForwardDuplicateFail;
546     Procedure TestClassForwardDelphiFail;
547     Procedure TestClassForwardObjFPCProgram;
548     Procedure TestClassForwardObjFPCUnit;
549     Procedure TestClass_Method;
550     Procedure TestClass_ConstructorMissingDotFail;
551     Procedure TestClass_MethodImplDuplicateFail;
552     Procedure TestClass_MethodWithoutClassFail;
553     Procedure TestClass_MethodInOtherUnitFail;
554     Procedure TestClass_MethodWithParams;
555     Procedure TestClass_MethodUnresolvedPrg;
556     Procedure TestClass_MethodUnresolvedUnit;
557     Procedure TestClass_MethodAbstract;
558     Procedure TestClass_MethodAbstractWithoutVirtualFail;
559     Procedure TestClass_MethodAbstractHasBodyFail;
560     Procedure TestClass_MethodUnresolvedWithAncestor;
561     Procedure TestClass_ProcFuncMismatch;
562     Procedure TestClass_MethodOverload;
563     Procedure TestClass_MethodInvalidOverload;
564     Procedure TestClass_MethodOverride;
565     Procedure TestClass_MethodOverride2;
566     Procedure TestClass_MethodOverrideFixCase;
567     Procedure TestClass_MethodOverrideSameResultType;
568     Procedure TestClass_MethodOverrideDiffResultTypeFail;
569     Procedure TestClass_MethodOverrideDiffVarName;
570     Procedure TestClass_MethodOverloadMissingInDelphi;
571     Procedure TestClass_MethodOverloadAncestor;
572     Procedure TestClass_MethodOverloadUnit;
573     Procedure TestClass_HintMethodHidesNonVirtualMethod;
574     Procedure TestClass_HintMethodHidesNonVirtualMethodWithoutBody_NoHint;
575     Procedure TestClass_NoHintMethodHidesPrivateMethod;
576     Procedure TestClass_MethodReintroduce;
577     Procedure TestClass_MethodOverloadArrayOfTClass;
578     Procedure TestClass_ConstructorHidesAncestorWarning;
579     Procedure TestClass_ConstructorOverride;
580     Procedure TestClass_ConstructorAccessHiddenAncestorFail;
581     Procedure TestClass_ConstructorNoteAbstractMethods;
582     Procedure TestClass_ConstructorNoNoteAbstractMethods;
583     Procedure TestClass_MethodScope;
584     Procedure TestClass_IdentifierSelf;
585     Procedure TestClassCallInherited;
586     Procedure TestClassCallInheritedNoParamsAbstractFail;
587     Procedure TestClassCallInheritedWithParamsAbstractFail;
588     Procedure TestClassCallInheritedConstructor;
589     Procedure TestClassCallInheritedNested;
590     Procedure TestClassCallInheritedAs;
591     Procedure TestClassAssignNil;
592     Procedure TestClassAssign;
593     Procedure TestClassNilAsParam;
594     Procedure TestClass_Operators_Is_As;
595     Procedure TestClass_OperatorIsOnNonTypeFail;
596     Procedure TestClass_OperatorAsOnNonDescendantFail;
597     Procedure TestClass_OperatorAsOnNonTypeFail;
598     Procedure TestClassAsFuncResult;
599     Procedure TestClassTypeCast;
600     Procedure TestClassTypeCastUnrelatedWarn;
601     Procedure TestClass_TypeCastSelf;
602     Procedure TestClass_TypeCaseMultipleParamsFail;
603     Procedure TestClass_TypeCastAssign;
604     Procedure TestClass_AccessMemberViaClassFail;
605     Procedure TestClass_FuncReturningObjectMember;
606     Procedure TestClass_StaticWithoutClassFail;
607     Procedure TestClass_SelfInStaticFail;
608     Procedure TestClass_SelfDotInStaticFail;
609     Procedure TestClass_ProcStaticMismatchFail;
610     Procedure TestClass_PrivateProtectedInSameUnit;
611     Procedure TestClass_PrivateInMainBeginFail;
612     Procedure TestClass_PrivateInDescendantFail;
613     Procedure TestClass_ProtectedInDescendant;
614     Procedure TestClass_StrictPrivateInMainBeginFail;
615     Procedure TestClass_StrictProtectedInMainBeginFail;
616     Procedure TestClass_Constructor_NewInstance;
617     Procedure TestClass_Destructor_FreeInstance;
618     Procedure TestClass_ConDestructor_CallInherited;
619     Procedure TestClass_Constructor_Inherited;
620     Procedure TestClass_SubObject;
621     Procedure TestClass_WithDoClassInstance;
622     Procedure TestClass_ProcedureExternal;
623     Procedure TestClass_ReintroducePublicVarObjFPCFail;
624     Procedure TestClass_ReintroducePublicVarDelphi;
625     Procedure TestClass_ReintroducePrivateVar;
626     Procedure TestClass_ReintroduceProc;
627     Procedure TestClass_UntypedParam_TypeCast;
628     Procedure TestClass_Sealed;
629     Procedure TestClass_SealedDescendFail;
630     Procedure TestClass_Abstract;
631     Procedure TestClass_AbstractCreateFail;
632     Procedure TestClass_VarExternal;
633     Procedure TestClass_WarnOverrideLowerVisibility;
634     Procedure TestClass_Const;
635     Procedure TestClass_ClassMissingVarFail;
636     Procedure TestClass_ClassConstFail;
637     Procedure TestClass_Enumerator;
638     Procedure TestClass_EnumeratorFunc;
639     Procedure TestClass_ForInPropertyStaticArray;
640     Procedure TestClass_TypeAlias;
641     Procedure TestClass_Message;
642     Procedure TestClass_Message_MissingParamFail;
643 
644     // published
645     Procedure TestClass_PublishedClassVarFail;
646     Procedure TestClass_PublishedClassPropertyFail;
647     Procedure TestClass_PublishedClassFunctionFail;
648     Procedure TestClass_PublishedOverloadFail;
649 
650     // nested class
651     Procedure TestNestedClass;
652     Procedure TestNestedClass_Forward;
653     procedure TestNestedClass_StrictPrivateFail;
654     procedure TestNestedClass_AccessStrictPrivate;
655     procedure TestNestedClass_AccessParent;
656     procedure TestNestedClass_BodyAccessParentVarFail;
657     procedure TestNestedClass_PropertyAccessParentVarFail;
658 
659     // external class
660     Procedure TestExternalClass;
661     Procedure TestExternalClass_Descendant;
662     Procedure TestExternalClass_HintMethodHidesNonVirtualMethodExact;
663 
664     // class of
665     Procedure TestClassOf;
666     Procedure TestClassOfAlias;
667     Procedure TestClassOfNonClassFail;
668     Procedure TestClassOfAssignClassOfFail;
669     Procedure TestClassOfIsOperatorFail;
670     Procedure TestClassOfAsOperatorFail;
671     Procedure TestClassOfIsOperator;
672     Procedure TestClass_ClassVar;
673     Procedure TestClassOfDotClassVar;
674     Procedure TestClassOfDotVarFail;
675     Procedure TestClassOfDotClassProc;
676     Procedure TestClassOfDotProcFail;
677     Procedure TestClassOfDotClassProperty;
678     Procedure TestClassOfDotPropertyFail;
679     Procedure TestClass_ClassProcSelf;
680     Procedure TestClass_ClassProcSelfTypeCastFail;
681     Procedure TestClass_ClassMembers;
682     Procedure TestClassOf_AsFail;
683     Procedure TestClassOf_MemberAsFail;
684     Procedure TestClassOf_IsFail;
685     Procedure TestClass_TypeCast;
686     Procedure TestClassOf_AlwaysForward;
687     Procedure TestClassOf_ClassOfBeforeClass_FuncResult;
688     Procedure TestClassOf_Const;
689     Procedure TestClassOf_Const2;
690 
691     // property
692     Procedure TestProperty1;
693     Procedure TestPropertyAccessorNotInFront;
694     Procedure TestPropertyReadAndWriteMissingFail;
695     Procedure TestPropertyReadAccessorVarWrongType;
696     Procedure TestPropertyReadAccessorProcNotFunc;
697     Procedure TestPropertyReadAccessorFuncWrongResult;
698     Procedure TestPropertyReadAccessorFuncWrongArgCount;
699     Procedure TestPropertyReadAccessorFunc;
700     Procedure TestPropertyReadAccessorStrictPrivate;
701     Procedure TestPropertyReadAccessorNonClassFail;
702     Procedure TestPropertyWriteAccessorVarWrongType;
703     Procedure TestPropertyWriteAccessorFuncNotProc;
704     Procedure TestPropertyWriteAccessorProcWrongArgCount;
705     Procedure TestPropertyWriteAccessorProcWrongArg;
706     Procedure TestPropertyWriteAccessorProcWrongArgType;
707     Procedure TestPropertyWriteAccessorProc;
708     Procedure TestPropertyTypeless;
709     Procedure TestPropertyTypelessNoAncestorFail;
710     Procedure TestPropertyStoredAccessor;
711     Procedure TestPropertyStoredAccessorVarWrongType;
712     Procedure TestPropertyStoredAccessorProcNotFunc;
713     Procedure TestPropertyStoredAccessorFuncWrongResult;
714     Procedure TestPropertyStoredAccessorFuncWrongArgCount;
715     Procedure TestPropertyIndexSpec;
716     Procedure TestPropertyIndexSpec_ReadAccessorWrongArgCount;
717     Procedure TestPropertyIndexSpec_ReadAccessorWrongIndexArgType;
718     Procedure TestPropertyDefaultValue;
719     Procedure TestPropertyAssign;
720     Procedure TestPropertyAssignReadOnlyFail;
721     Procedure TestProperty_PassAsParam;
722     Procedure TestPropertyReadNonReadableFail;
723     Procedure TestPropertyArgs1;
724     Procedure TestPropertyArgs2;
725     Procedure TestPropertyArgsWithDefaultsFail;
726     Procedure TestPropertyArgs_StringConstDefault;
727     Procedure TestClassProperty;
728     Procedure TestClassPropertyNonStaticFail;
729     Procedure TestClassPropertyNonStaticAllow;
730     Procedure TestArrayProperty;
731     Procedure TestArrayProperty_PassImplicitCallClassFunc;
732     Procedure TestProperty_WrongTypeAsIndexFail;
733     Procedure TestProperty_Option_ClassPropertyNonStatic;
734     Procedure TestDefaultProperty;
735     Procedure TestDefaultPropertyIncVisibility;
736     Procedure TestProperty_MissingDefault;
737     Procedure TestProperty_DefaultDotFail;
738 
739     // class interfaces
740     Procedure TestClassInterface;
741     Procedure TestClassInterfaceForward;
742     Procedure TestClassInterfaceVarFail;
743     Procedure TestClassInterfaceConstFail;
744     Procedure TestClassInterfaceClassMethodFail;
745     Procedure TestClassInterfaceNestedTypeFail;
746     Procedure TestClassInterfacePropertyStoredFail;
747     Procedure TestClassInterface_ConstructorFail;
748     Procedure TestClassInterface_DelphiClassAncestorIntfFail;
749     Procedure TestClassInterface_ObjFPCClassAncestorIntf;
750     Procedure TestClassInterface_MethodVirtualFail;
751     Procedure TestClassInterface_Overloads;
752     Procedure TestClassInterface_OverloadHint;
753     Procedure TestClassInterface_OverloadNoHint;
754     Procedure TestClassInterface_IntfListClassFail;
755     Procedure TestClassInterface_IntfListDuplicateFail;
756     Procedure TestClassInterface_MissingMethodFail;
757     Procedure TestClassInterface_MissingAncestorMethodFail;
758     Procedure TestClassInterface_DefaultProperty;
759     Procedure TestClassInterface_MethodResolution;
760     Procedure TestClassInterface_MethodResolutionDuplicateFail;
761     Procedure TestClassInterface_DelegationIntf;
762     Procedure TestClassInterface_Delegation_DuplPropFail;
763     Procedure TestClassInterface_Delegation_MethodResFail;
764     Procedure TestClassInterface_DelegationClass;
765     Procedure TestClassInterface_DelegationFQN;
766     Procedure TestClassInterface_Assign;
767     Procedure TestClassInterface_AssignObjVarIntfVarFail;
768     Procedure TestClassInterface_AssignDescendentFail;
769     Procedure TestClassInterface_Args;
770     Procedure TestClassInterface_Enumerator;
771     Procedure TestClassInterface_PassTypecastClassToIntfAsVarParamFail;
772     Procedure TestClassInterface_PassTypecastIntfToClassAsVarParamFail;
773     Procedure TestClassInterface_GUID;
774 
775     // with-do
776     Procedure TestWithDo1;
777     Procedure TestWithDo2;
778     Procedure TestWithDoFuncResult;
779     Procedure TestWithDoConstructor;
780 
781     // arrays
782     Procedure TestDynArrayOfLongint;
783     Procedure TestDynArrayOfSelfFail;
784     Procedure TestStaticArray;
785     Procedure TestStaticArrayOfChar;
786     Procedure TestStaticArrayOfCharDelphi;
787     Procedure TestStaticArrayOfRangeElCheckFail;
788     Procedure TestArrayOfChar_String;
789     Procedure TestArrayOfArray;
790     Procedure TestArrayOfArray_NameAnonymous;
791     Procedure TestFunctionReturningArray;
792     Procedure TestArray_LowHigh;
793     Procedure TestArray_LowVarFail;
794     Procedure TestArray_AssignDiffElTypeFail;
795     Procedure TestArray_AssignSameSignatureDelphiFail;
796     Procedure TestArray_Assigned;
797     Procedure TestPropertyOfTypeArray;
798     Procedure TestArrayElementFromFuncResult_AsParams;
799     Procedure TestArrayEnumTypeRange;
800     Procedure TestArrayEnumTypeConstNotEnoughValuesFail1;
801     Procedure TestArrayEnumTypeConstNotEnoughValuesFail2;
802     Procedure TestArrayEnumTypeConstWrongTypeFail;
803     Procedure TestArrayEnumTypeConstNonConstFail;
804     Procedure TestArrayEnumTypeSetLengthFail;
805     Procedure TestArrayEnumCustomRange;
806     Procedure TestArray_DynArrayConstObjFPC;
807     Procedure TestArray_DynArrayConstDelphi;
808     Procedure TestArray_DynArrAssignStaticDelphiFail;
809     Procedure TestArray_Static_Const;
810     Procedure TestArray_Record_Const;
811     Procedure TestArray_MultiDim_Const;
812     Procedure TestArray_AssignNilToStaticArrayFail1;
813     Procedure TestArray_SetLengthProperty;
814     Procedure TestStaticArray_SetlengthFail;
815     Procedure TestArray_PassArrayElementToVarParam;
816     Procedure TestArray_OpenArrayOfString;
817     Procedure TestArray_OpenArrayOfString_IntFail;
818     Procedure TestArray_OpenArrayOverride;
819     Procedure TestArray_OpenArrayAsDynArraySetLengthFail;
820     Procedure TestArray_OpenArrayAsDynArray;
821     Procedure TestArray_OpenArrayDelphi;
822     Procedure TestArray_OpenArrayChar;
823     Procedure TestArray_DynArrayChar;
824     Procedure TestArray_CopyConcat;
825     Procedure TestStaticArray_CopyConcat;// ToDo
826     Procedure TestArray_CopyMismatchFail;
827     Procedure TestArray_InsertDeleteAccess;
828     Procedure TestArray_InsertArray;
829     Procedure TestStaticArray_InsertFail;
830     Procedure TestStaticArray_DeleteFail;
831     Procedure TestArray_InsertItemMismatchFail;
832     Procedure TestArray_TypeCast;
833     Procedure TestArray_TypeCastWrongElTypeFail;
834     Procedure TestArray_ConstDynArrayWrite;
835     Procedure TestArray_ConstOpenArrayWriteFail;
836     Procedure TestArray_ForIn;
837     Procedure TestArray_Arg_AnonymousStaticFail;
838     Procedure TestArray_Arg_AnonymousMultiDimFail;
839 
840     // array of const
841     Procedure TestArrayOfConst;
842     Procedure TestArrayOfConst_PassDynArrayOfIntFail;
843     Procedure TestArrayOfConst_AssignNilFail;
844     Procedure TestArrayOfConst_SetLengthFail;
845 
846     // static arrays
847     Procedure TestArrayIntRange_OutOfRange;
848     Procedure TestArrayIntRange_OutOfRangeError;
849     Procedure TestArrayCharRange_OutOfRange;
850 
851     // procedure types
852     Procedure TestProcTypesAssignObjFPC;
853     Procedure TestMethodTypesAssignObjFPC;
854     Procedure TestProcTypeCall;
855     Procedure TestProcType_FunctionFPC;
856     Procedure TestProcType_FunctionDelphi;
857     Procedure TestProcType_ProcedureDelphi;
858     Procedure TestProcType_MethodFPC;
859     Procedure TestProcType_MethodDelphi;
860     Procedure TestAssignProcToMethodFail;
861     Procedure TestAssignMethodToProcFail;
862     Procedure TestAssignProcToFunctionFail;
863     Procedure TestAssignProcWrongArgsFail;
864     Procedure TestAssignProcWrongArgAccessFail;
865     Procedure TestProcType_SameSignatureObjFPC;
866     Procedure TestProcType_AssignNestedProcFail;
867     Procedure TestArrayOfProc;
868     Procedure TestProcType_Assigned;
869     Procedure TestProcType_TNotifyEvent;
870     Procedure TestProcType_TNotifyEvent_NoAtFPC_Fail1;
871     Procedure TestProcType_TNotifyEvent_NoAtFPC_Fail2;
872     Procedure TestProcType_TNotifyEvent_NoAtFPC_Fail3;
873     Procedure TestProcType_WhileListCompare;
874     Procedure TestProcType_IsNested;
875     Procedure TestProcType_IsNested_AssignProcFail;
876     Procedure TestProcType_ReferenceTo;
877     Procedure TestProcType_AllowNested;
878     Procedure TestProcType_AllowNestedOfObject;
879     Procedure TestProcType_AsArgOtherUnit;
880     Procedure TestProcType_Property;
881     Procedure TestProcType_PropertyCallWrongArgFail;
882     Procedure TestProcType_Typecast;
883     Procedure TestProcType_InsideFunction;
884     Procedure TestProcType_PassProcToUntyped;
885 
886     // pointer
887     Procedure TestPointer;
888     Procedure TestPointer_AnonymousSetFail;
889     Procedure TestPointer_AssignPointerToClassFail;
890     Procedure TestPointer_TypecastToMethodTypeFail;
891     Procedure TestPointer_TypecastFromMethodTypeFail;
892     Procedure TestPointer_TypecastMethod_proMethodAddrAsPointer;
893     Procedure TestPointer_OverloadSignature;
894     Procedure TestPointer_Assign;
895     Procedure TestPointerTyped;
896     Procedure TestPointerTypedForwardMissingFail;
897     Procedure TestPointerTyped_CycleFail;
898     Procedure TestPointerTyped_AssignMismatchFail;
899     Procedure TestPointerTyped_AddrAddrFail;
900     Procedure TestPointerTyped_RecordObjFPC;
901     Procedure TestPointerTyped_RecordDelphi;
902     Procedure TestPointerTyped_Arithmetic;
903 
904     // resourcestrings
905     Procedure TestResourcestring;
906     Procedure TestResourcestringAssignFail;
907     Procedure TestResourcestringLocalFail;
908     Procedure TestResourcestringInConstFail;
909     Procedure TestResourcestringPassVarArgFail;
910 
911     // hints
912     Procedure TestHint_ElementHints;
913     Procedure TestHint_ElementHintsMsg;
914     Procedure TestHint_ElementHintsAlias;
915     Procedure TestHint_ElementHints_WarnOff_SymbolDeprecated;
916     Procedure TestHint_Garbage;
917 
918     // helpers
919     Procedure TestClassHelper;
920     Procedure TestClassHelper_AncestorIsNotHelperForDescendantFail;
921     Procedure TestClassHelper_HelperForParentFail;
922     Procedure TestClassHelper_ForInterfaceFail;
923     Procedure TestClassHelper_FieldFail;
924     Procedure TestClassHelper_AbstractFail;
925     Procedure TestClassHelper_VirtualObjFPCFail;
926     Procedure TestClassHelper_VirtualDelphiFail;
927     Procedure TestClassHelper_DestructorFail;
928     Procedure TestClassHelper_ClassRefersToTypeHelperOfAncestor;
929     Procedure TestClassHelper_InheritedObjFPC;
930     Procedure TestClassHelper_InheritedObjFPC2;
931     Procedure TestClassHelper_InheritedObjFPCStrictPrivateFail;
932     Procedure TestClassHelper_InheritedClassObjFPC;
933     Procedure TestClassHelper_InheritedDelphi;
934     Procedure TestClassHelper_NestedInheritedParentFail;
935     Procedure TestClassHelper_AccessFields;
936     Procedure TestClassHelper_HelperDotClassMethodFail;
937     Procedure TestClassHelper_WithDoHelperFail;
938     Procedure TestClassHelper_AsTypeFail;
939     Procedure TestClassHelper_WithDo;
940     Procedure TestClassHelper_ClassMethod;
941     Procedure TestClassHelper_Enumerator;
942     Procedure TestClassHelper_FromUnitInterface;
943     Procedure TestClassHelper_Constructor_NewInstance;
944     Procedure TestClassHelper_ReintroduceHides_CallFail;
945     Procedure TestClassHelper_DefaultProperty;
946     Procedure TestClassHelper_DefaultClassProperty;
947     Procedure TestClassHelper_MultiHelpers;
948     Procedure TestRecordHelper;
949     Procedure TestRecordHelper_ForByteFail;
950     Procedure TestRecordHelper_ClassNonStaticFail;
951     Procedure TestRecordHelper_InheritedObjFPC;
952     Procedure TestRecordHelper_Constructor_NewInstance;
953     Procedure TestTypeHelper;
954     Procedure TestTypeHelper_HelperForProcTypeFail;
955     Procedure TestTypeHelper_DefaultPropertyFail;
956     Procedure TestTypeHelper_Enum;
957     Procedure TestTypeHelper_EnumDotValueFail;
958     Procedure TestTypeHelper_EnumHelperDotProcFail;
959     Procedure TestTypeHelper_Set;
960     Procedure TestTypeHelper_Enumerator;
961     Procedure TestTypeHelper_String;
962     Procedure TestTypeHelper_StringOtherUnit;
963     Procedure TestTypeHelper_Boolean;
964     Procedure TestTypeHelper_Double;
965     Procedure TestTypeHelper_DoubleAlias;
966     Procedure TestTypeHelper_Constructor_NewInstance;
967     Procedure TestTypeHelper_Interface;
968     Procedure TestTypeHelper_Interface_ConstructorFail;
969     Procedure TestTypeHelper_TypeAliasType;
970 
971     // attributes
972     Procedure TestAttributes_Globals;
973     Procedure TestAttributes_NonConstParam_Fail;
974     Procedure TestAttributes_UnknownAttrWarning;
975     Procedure TestAttributes_Members;
976   end;
977 
LinesToStrnull978 function LinesToStr(Args: array of const): string;
979 
980 implementation
981 
LinesToStrnull982 function LinesToStr(Args: array of const): string;
983 var
984   s: String;
985   i: Integer;
986 begin
987   s:='';
988   for i:=Low(Args) to High(Args) do
989     case Args[i].VType of
990       vtChar:         s += Args[i].VChar+LineEnding;
991       vtString:       s += Args[i].VString^+LineEnding;
992       vtPChar:        s += Args[i].VPChar+LineEnding;
993       vtWideChar:     s += AnsiString(Args[i].VWideChar)+LineEnding;
994       vtPWideChar:    s += AnsiString(Args[i].VPWideChar)+LineEnding;
995       vtAnsiString:   s += AnsiString(Args[i].VAnsiString)+LineEnding;
996       vtWidestring:   s += AnsiString(WideString(Args[i].VWideString))+LineEnding;
997       vtUnicodeString:s += AnsiString(UnicodeString(Args[i].VUnicodeString))+LineEnding;
998     end;
999   Result:=s;
1000 end;
1001 
1002 { TTestEnginePasResolver }
1003 
1004 procedure TTestEnginePasResolver.SetModule(AValue: TPasModule);
1005 begin
1006   if FModule=AValue then Exit;
1007   if Module<>nil then
1008     Module.Release{$IFDEF CheckPasTreeRefCount}('TTestEnginePasResolver.Module'){$ENDIF};
1009   FModule:=AValue;
1010   {$IFDEF CheckPasTreeRefCount}
1011   if Module<>nil then
1012     Module.ChangeRefId('CreateElement','TTestEnginePasResolver.Module');
1013   {$ENDIF}
1014 end;
1015 
1016 constructor TTestEnginePasResolver.Create;
1017 begin
1018   inherited Create;
1019   StoreSrcColumns:=true;
1020 end;
1021 
1022 destructor TTestEnginePasResolver.Destroy;
1023 begin
1024   FStreamResolver:=nil;
1025   FreeAndNil(FParser);
1026   FreeAndNil(FScanner);
1027   inherited Destroy;
1028   Module:=nil;
1029 end;
1030 
1031 procedure TTestEnginePasResolver.ReleaseUsedUnits;
1032 begin
1033   if Module<>nil then
1034     Module.ReleaseUsedUnits;
1035 end;
1036 
TTestEnginePasResolver.CreateElementnull1037 function TTestEnginePasResolver.CreateElement(AClass: TPTreeElement;
1038   const AName: String; AParent: TPasElement; AVisibility: TPasMemberVisibility;
1039   const ASrcPos: TPasSourcePos; TypeParams: TFPList): TPasElement;
1040 begin
1041   Result:=inherited CreateElement(AClass, AName, AParent, AVisibility, ASrcPos, TypeParams);
1042   if (FModule=nil) and AClass.InheritsFrom(TPasModule) then
1043     Module:=TPasModule(Result);
1044 end;
1045 
TTestEnginePasResolver.FindUnitnull1046 function TTestEnginePasResolver.FindUnit(const AName, InFilename: String;
1047   NameExpr, InFileExpr: TPasExpr): TPasModule;
1048 begin
1049   Result:=OnFindUnit(Self,AName,InFilename,NameExpr,InFileExpr);
1050 end;
1051 
1052 procedure TTestEnginePasResolver.UsedInterfacesFinished(Section: TPasSection);
1053 begin
1054   if Section=nil then ;
1055   // do not parse recursively
1056   // using a queue
1057 end;
1058 
1059 { TCustomTestResolver }
1060 
1061 procedure TCustomTestResolver.SetUp;
1062 begin
1063   {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
1064   FStartElementRefCount:=TPasElement.GlobalRefCount;
1065   {$ENDIF}
1066   FModules:=TObjectList.Create(true);
1067   FHub:=TPasResolverHub.Create(Self);
1068   inherited SetUp;
1069   Parser.Options:=Parser.Options+[po_ResolveStandardTypes];
1070   Scanner.OnDirective:=@OnScannerDirective;
1071   Scanner.OnLog:=@OnScannerLog;
1072 end;
1073 
1074 procedure TCustomTestResolver.TearDown;
1075 {$IFDEF CheckPasTreeRefCount}
1076 var El: TPasElement;
1077 {$ENDIF}
1078 var i: Integer;
1079 begin
1080   FResolverMsgs.Clear;
1081   FResolverGoodMsgs.Clear;
1082   {$IFDEF VerbosePasResolverMem}
1083   writeln('TTestResolver.TearDown START FreeSrcMarkers');
1084   {$ENDIF}
1085   FreeSrcMarkers;
1086   {$IFDEF VerbosePasResolverMem}
1087   writeln('TTestResolver.TearDown ResolverEngine.Clear');
1088   {$ENDIF}
1089   if ResolverEngine.Parser=Parser then
1090     ResolverEngine.Parser:=nil;
1091   ResolverEngine.Clear;
1092   if FModules<>nil then
1093     begin
1094     {$IFDEF VerbosePasResolverMem}
1095     writeln('TTestResolver.TearDown FModules');
1096     {$ENDIF}
1097     for i:=0 to FModules.Count-1 do
1098       TTestEnginePasResolver(FModules[i]).ReleaseUsedUnits;
1099     FModules.OwnsObjects:=false;
1100     FModules.Remove(ResolverEngine); // remove reference
1101     FModules.OwnsObjects:=true;
1102     FreeAndNil(FModules);// free all other modules
1103     end;
1104   FreeAndNil(FHub);
1105   {$IFDEF VerbosePasResolverMem}
1106   writeln('TTestResolver.TearDown inherited');
1107   {$ENDIF}
1108   if Module<>nil then
1109     Module.AddRef{$IFDEF CheckPasTreeRefCount}('CreateElement'){$ENDIF}; // for the Release in ancestor TTestParser
1110   inherited TearDown;
1111   FResolverEngine:=nil;
1112   {$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
1113   if FStartElementRefCount<>TPasElement.GlobalRefCount then
1114     begin
1115     writeln('TCustomTestResolver.TearDown GlobalRefCount Was='+IntToStr(FStartElementRefCount)+' Now='+IntToStr(TPasElement.GlobalRefCount));
1116     {$IFDEF CheckPasTreeRefCount}
1117     El:=TPasElement.FirstRefEl;
1118     if El=nil then
1119       writeln('  TPasElement.FirstRefEl=nil');
1120     while El<>nil do
1121       begin
1122       writeln('  ',GetObjName(El),' RefIds.Count=',El.RefIds.Count,':');
1123       for i:=0 to El.RefIds.Count-1 do
1124         writeln('    ',El.RefIds[i]);
1125       El:=El.NextRefEl;
1126       end;
1127     {$ENDIF}
1128     //Halt;
1129     Fail('TCustomTestResolver.TearDown GlobalRefCount Was='+IntToStr(FStartElementRefCount)+' Now='+IntToStr(TPasElement.GlobalRefCount));
1130     end;
1131   {$ENDIF}
1132   {$IFDEF VerbosePasResolverMem}
1133   writeln('TTestResolver.TearDown END');
1134   {$ENDIF}
1135 end;
1136 
1137 procedure TCustomTestResolver.CreateEngine(var TheEngine: TPasTreeContainer);
1138 begin
1139   FResolverEngine:=AddModule(MainFilename);
1140   TheEngine:=ResolverEngine;
1141 end;
1142 
1143 procedure TCustomTestResolver.ParseModule;
1144 var
1145   Section: TPasSection;
1146   i: Integer;
1147   CurResolver: TTestEnginePasResolver;
1148   Found: Boolean;
1149 begin
1150   if ResolverEngine.Parser=nil then
1151     ResolverEngine.Parser:=Parser;
1152 
1153   inherited ParseModule;
1154   repeat
1155     Found:=false;
1156     for i:=0 to ModuleCount-1 do
1157       begin
1158       CurResolver:=Modules[i];
1159       if CurResolver.Parser=nil then continue;
1160       if not CurResolver.Parser.CanParseContinue(Section) then
1161         continue;
1162       {$IFDEF VerbosePasResolver}
1163       writeln('TCustomTestResolver.ParseModule continue parsing section=',GetObjName(Section),' of ',CurResolver.Filename);
1164       {$ENDIF}
1165       Found:=true;
1166       CurResolver.Parser.ParseContinue;
1167       break;
1168       end;
1169   until not Found;
1170 
1171   for i:=0 to ModuleCount-1 do
1172     begin
1173     CurResolver:=Modules[i];
1174     if CurResolver.Parser=nil then
1175       begin
1176       if CurResolver.CurrentParser<>nil then
1177         Fail(CurResolver.Filename+' Parser<>CurrentParser Parser="'+GetObjName(CurResolver.Parser)+'" CurrentParser='+GetObjName(CurResolver.CurrentParser));
1178       continue;
1179       end;
1180     if CurResolver.Parser.CurModule<>nil then
1181       begin
1182       Section:=CurResolver.Parser.GetLastSection;
1183       {$IFDEF VerbosePasResolver}
1184       writeln('TCustomTestResolver.ParseModule module not finished "',GetObjName(CurResolver.RootElement),'" LastSection=',GetObjName(Section)+' PendingUsedIntf='+GetObjName(Section.PendingUsedIntf));
1185       if (Section<>nil) and (Section.PendingUsedIntf<>nil) then
1186         writeln('TCustomTestResolver.ParseModule PendingUsedIntf=',GetObjName(Section.PendingUsedIntf.Module));
1187       {$ENDIF}
1188       Fail('module not finished "'+GetObjName(CurResolver.RootElement)+'"');
1189       end;
1190     end;
1191 end;
1192 
1193 procedure TCustomTestResolver.ParseProgram;
1194 var
1195   aFilename: String;
1196   aRow, aCol: Integer;
1197 begin
1198   FFirstStatement:=nil;
1199   try
1200     ParseModule;
1201   except
1202     on E: EParserError do
1203       begin
1204       aFilename:=E.Filename;
1205       aRow:=E.Row;
1206       aCol:=E.Column;
1207       WriteSources(aFilename,aRow,aCol);
1208       writeln('ERROR: TTestResolver.ParseProgram Parser: '+E.ClassName+':'+E.Message,
1209         ' Scanner at'
1210         +' '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+')'
1211         +' Line="'+Scanner.CurLine+'"');
1212       Fail(E.Message);
1213       end;
1214     on E: EPasResolve do
1215       begin
1216       aFilename:=Scanner.CurFilename;
1217       aRow:=Scanner.CurRow;
1218       aCol:=Scanner.CurColumn;
1219       if E.PasElement<>nil then
1220         begin
1221         aFilename:=E.PasElement.SourceFilename;
1222         ResolverEngine.UnmangleSourceLineNumber(E.PasElement.SourceLinenumber,aRow,aCol);
1223         end;
1224       WriteSources(aFilename,aRow,aCol);
1225       writeln('ERROR: TTestResolver.ParseProgram PasResolver: '+E.ClassName+':'+E.Message
1226         +' at '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+')');
1227       Fail(E.Message);
1228       end;
1229     on E: Exception do
1230       begin
1231       writeln('ERROR: TTestResolver.ParseProgram Exception: '+E.ClassName+':'+E.Message);
1232       Fail(E.Message);
1233       end;
1234   end;
1235   TAssert.AssertSame('Has resolver',ResolverEngine,Parser.Engine);
1236   AssertEquals('Has program',TPasProgram,Module.ClassType);
1237   AssertNotNull('Has program section',PasProgram.ProgramSection);
1238   AssertNotNull('Has initialization section',PasProgram.InitializationSection);
1239   if (PasProgram.InitializationSection.Elements.Count>0) then
1240     if TObject(PasProgram.InitializationSection.Elements[0]) is TPasImplBlock then
1241       FFirstStatement:=TPasImplBlock(PasProgram.InitializationSection.Elements[0]);
1242   CheckReferenceDirectives;
1243 end;
1244 
1245 procedure TCustomTestResolver.ParseUnit;
1246 begin
1247   FFirstStatement:=nil;
1248   try
1249     ParseModule;
1250   except
1251     on E: EParserError do
1252       begin
1253       writeln('ERROR: TTestResolver.ParseUnit Parser: '+E.ClassName+':'+E.Message
1254         +' File='+Scanner.CurFilename
1255         +' LineNo='+IntToStr(Scanner.CurRow)
1256         +' Col='+IntToStr(Scanner.CurColumn)
1257         +' Line="'+Scanner.CurLine+'"'
1258         );
1259       Fail(E.Message);
1260       end;
1261     on E: EPasResolve do
1262       begin
1263       writeln('ERROR: TTestResolver.ParseUnit PasResolver: '+E.ClassName+':'+E.Message
1264         +' File='+Scanner.CurFilename
1265         +' LineNo='+IntToStr(Scanner.CurRow)
1266         +' Col='+IntToStr(Scanner.CurColumn)
1267         +' Line="'+Scanner.CurLine+'"'
1268         );
1269       Fail(E.Message);
1270       end;
1271     on E: Exception do
1272       begin
1273       writeln('ERROR: TTestResolver.ParseUnit Exception: '+E.ClassName+':'+E.Message);
1274       Fail(E.Message);
1275       end;
1276   end;
1277   TAssert.AssertSame('Has resolver',ResolverEngine,Parser.Engine);
1278   AssertEquals('Has unit',TPasModule,Module.ClassType);
1279   AssertNotNull('Has interface section',Module.InterfaceSection);
1280   AssertNotNull('Has implementation section',Module.ImplementationSection);
1281   if (Module.InitializationSection<>nil)
1282   and (Module.InitializationSection.Elements.Count>0) then
1283     if TObject(Module.InitializationSection.Elements[0]) is TPasImplBlock then
1284       FFirstStatement:=TPasImplBlock(Module.InitializationSection.Elements[0]);
1285   CheckReferenceDirectives;
1286 end;
1287 
1288 procedure TCustomTestResolver.CheckReferenceDirectives;
1289 var
1290   Filename: string;
1291   LineNumber: Integer;
1292   SrcLine: String;
1293   CommentStartP, CommentEndP: PChar;
1294 
1295   procedure RaiseError(Msg: string; p: PChar);
1296   begin
1297     RaiseErrorAtSrc(Msg,Filename,LineNumber,p-PChar(SrcLine)+1);
1298   end;
1299 
1300   procedure AddMarker(Marker: PSrcMarker);
1301   begin
1302     if LastSrcMarker<>nil then
1303       LastSrcMarker^.Next:=Marker
1304     else
1305       FirstSrcMarker:=Marker;
1306     LastSrcMarker:=Marker;
1307   end;
1308 
AddMarkernull1309   function AddMarker(Kind: TSrcMarkerKind; const aFilename: string;
1310     aLine, aStartCol, aEndCol: integer; const Identifier: string): PSrcMarker;
1311   begin
1312     New(Result);
1313     Result^.Kind:=Kind;
1314     Result^.Filename:=aFilename;
1315     Result^.Row:=aLine;
1316     Result^.StartCol:=aStartCol;
1317     Result^.EndCol:=aEndCol;
1318     Result^.Identifier:=Identifier;
1319     Result^.Next:=nil;
1320     //writeln('AddMarker Line="',SrcLine,'" Identifier=',Identifier,' Col=',aStartCol,'-',aEndCol,' "',copy(SrcLine,aStartCol,aEndCol-aStartCol),'"');
1321     AddMarker(Result);
1322   end;
1323 
AddMarkerForTokenBehindCommentnull1324   function AddMarkerForTokenBehindComment(Kind: TSrcMarkerKind;
1325     const Identifier: string): PSrcMarker;
1326   var
1327     TokenStart, p: PChar;
1328   begin
1329     p:=CommentEndP;
1330     ReadNextPascalToken(p,TokenStart,false,false);
1331     Result:=AddMarker(Kind,Filename,LineNumber,
1332       CommentEndP-PChar(SrcLine)+1,p-PChar(SrcLine)+1,Identifier);
1333   end;
1334 
ReadIdentifiernull1335   function ReadIdentifier(var p: PChar): string;
1336   var
1337     StartP: PChar;
1338   begin
1339     if not (p^ in ['a'..'z','A'..'Z','_']) then
1340       RaiseError('identifier expected',p);
1341     StartP:=p;
1342     inc(p);
1343     while p^ in ['a'..'z','A'..'Z','_','0'..'9'] do inc(p);
1344     Result:='';
1345     SetLength(Result,p-StartP);
1346     Move(StartP^,Result[1],length(Result));
1347   end;
1348 
1349   procedure AddLabel;
1350   var
1351     Identifier: String;
1352     p: PChar;
1353   begin
1354     p:=CommentStartP+2;
1355     Identifier:=ReadIdentifier(p);
1356     //writeln('TTestResolver.CheckReferenceDirectives.AddLabel ',Identifier);
1357     if FindSrcLabel(Identifier)<>nil then
1358       RaiseError('duplicate label "'+Identifier+'"',p);
1359     AddMarkerForTokenBehindComment(mkLabel,Identifier);
1360   end;
1361 
1362   procedure AddResolverReference;
1363   var
1364     Identifier: String;
1365     p: PChar;
1366   begin
1367     p:=CommentStartP+2;
1368     Identifier:=ReadIdentifier(p);
1369     //writeln('TTestResolver.CheckReferenceDirectives.AddReference ',Identifier);
1370     AddMarkerForTokenBehindComment(mkResolverReference,Identifier);
1371   end;
1372 
1373   procedure AddDirectReference;
1374   var
1375     Identifier: String;
1376     p: PChar;
1377   begin
1378     p:=CommentStartP+2;
1379     Identifier:=ReadIdentifier(p);
1380     //writeln('TTestResolver.CheckReferenceDirectives.AddDirectReference ',Identifier);
1381     AddMarkerForTokenBehindComment(mkDirectReference,Identifier);
1382   end;
1383 
1384   procedure ParseCode(SrcLines: TStringList; aFilename: string);
1385   var
1386     p: PChar;
1387     IsDirective: Boolean;
1388   begin
1389     //writeln('TTestResolver.CheckReferenceDirectives.ParseCode File=',aFilename);
1390     Filename:=aFilename;
1391     // parse code, find all labels
1392     LineNumber:=0;
1393     while LineNumber<SrcLines.Count do
1394       begin
1395       inc(LineNumber);
1396       SrcLine:=SrcLines[LineNumber-1];
1397       if SrcLine='' then continue;
1398       //writeln('TTestResolver.CheckReferenceDirectives Line=',SrcLine);
1399       p:=PChar(SrcLine);
1400       repeat
1401         case p^ of
1402           #0: if (p-PChar(SrcLine)=length(SrcLine)) then break;
1403           '{':
1404             begin
1405             CommentStartP:=p;
1406             inc(p);
1407             IsDirective:=p^ in ['#','@','='];
1408 
1409             // skip to end of comment
1410             repeat
1411               case p^ of
1412               #0:
1413                 if (p-PChar(SrcLine)=length(SrcLine)) then
1414                   begin
1415                   // multi line comment
1416                   if IsDirective then
1417                     RaiseError('directive missing closing bracket',CommentStartP);
1418                   repeat
1419                     inc(LineNumber);
1420                     if LineNumber>SrcLines.Count then exit;
1421                     SrcLine:=SrcLines[LineNumber-1];
1422                     //writeln('TTestResolver.CheckReferenceDirectives Comment Line=',SrcLine);
1423                   until SrcLine<>'';
1424                   p:=PChar(SrcLine);
1425                   continue;
1426                   end;
1427               '}':
1428                 begin
1429                 inc(p);
1430                 break;
1431                 end;
1432               end;
1433               inc(p);
1434             until false;
1435 
1436             CommentEndP:=p;
1437             case CommentStartP[1] of
1438             '#': AddLabel;
1439             '@': AddResolverReference;
1440             '=': AddDirectReference;
1441             end;
1442             p:=CommentEndP;
1443             continue;
1444 
1445             end;
1446           '/':
1447             if p[1]='/' then
1448               break; // rest of line is comment -> skip
1449         end;
1450         inc(p);
1451       until false;
1452       end;
1453   end;
1454 
1455   procedure CheckResolverReference(aMarker: PSrcMarker);
1456   // check if one element at {@a} has a TResolvedReference to an element labeled {#a}
1457   var
1458     aLabel: PSrcMarker;
1459     ReferenceElements, LabelElements: TFPList;
1460     i, j, aLine, aCol: Integer;
1461     El, Ref, LabelEl: TPasElement;
1462   begin
1463     //writeln('CheckResolverReference searching reference: ',aMarker^.Filename,' Line=',aMarker^.Row,' Col=',aMarker^.StartCol,'-',aMarker^.EndCol,' Label="',aMarker^.Identifier,'"');
1464     aLabel:=FindSrcLabel(aMarker^.Identifier);
1465     if aLabel=nil then
1466       RaiseErrorAtSrc('label "'+aMarker^.Identifier+'" not found',aMarker^.Filename,aMarker^.Row,aMarker^.StartCol);
1467 
1468     LabelElements:=nil;
1469     ReferenceElements:=nil;
1470     try
1471       LabelElements:=FindElementsAt(aLabel);
1472       ReferenceElements:=FindElementsAt(aMarker);
1473 
1474       for i:=0 to ReferenceElements.Count-1 do
1475         begin
1476         El:=TPasElement(ReferenceElements[i]);
1477         Ref:=nil;
1478         if El.CustomData is TResolvedReference then
1479           Ref:=TResolvedReference(El.CustomData).Declaration
1480         else if El.CustomData is TPasPropertyScope then
1481           Ref:=TPasPropertyScope(El.CustomData).AncestorProp
1482         else if El.CustomData is TPasSpecializeTypeData then
1483           Ref:=TPasSpecializeTypeData(El.CustomData).SpecializedType;
1484         if Ref<>nil then
1485           for j:=0 to LabelElements.Count-1 do
1486             begin
1487             LabelEl:=TPasElement(LabelElements[j]);
1488             if Ref=LabelEl then
1489               exit; // success
1490             end;
1491         end;
1492 
1493       // failure write candidates
1494       for i:=0 to ReferenceElements.Count-1 do
1495         begin
1496         El:=TPasElement(ReferenceElements[i]);
1497         write('Reference candidate for "',aMarker^.Identifier,'" at reference ',aMarker^.Filename,'(',aMarker^.Row,',',aMarker^.StartCol,'-',aMarker^.EndCol,')');
1498         write(' El=',GetObjName(El));
1499         if EL is TPrimitiveExpr then
1500           begin
1501            writeln('CheckResolverReference ',TPrimitiveExpr(El).Value);
1502           end;
1503         Ref:=nil;
1504         if El.CustomData is TResolvedReference then
1505           Ref:=TResolvedReference(El.CustomData).Declaration
1506         else if El.CustomData is TPasPropertyScope then
1507           Ref:=TPasPropertyScope(El.CustomData).AncestorProp
1508         else if El.CustomData is TPasSpecializeTypeData then
1509           Ref:=TPasSpecializeTypeData(El.CustomData).SpecializedType;
1510         if Ref<>nil then
1511           begin
1512           write(' Decl=',GetObjName(Ref));
1513           ResolverEngine.UnmangleSourceLineNumber(Ref.SourceLinenumber,aLine,aCol);
1514           write(',',Ref.SourceFilename,'(',aLine,',',aCol,')');
1515           end
1516         else
1517           write(' has no TResolvedReference. El.CustomData=',GetObjName(El.CustomData));
1518         writeln;
1519         end;
1520       for i:=0 to LabelElements.Count-1 do
1521         begin
1522         El:=TPasElement(LabelElements[i]);
1523         write('Label candidate for "',aLabel^.Identifier,'" at reference ',aLabel^.Filename,'(',aLabel^.Row,',',aLabel^.StartCol,'-',aLabel^.EndCol,')');
1524         write(' El=',GetObjName(El));
1525         writeln;
1526         end;
1527 
1528       RaiseErrorAtSrcMarker('wrong resolved reference "'+aMarker^.Identifier+'"',aMarker);
1529     finally
1530       LabelElements.Free;
1531       ReferenceElements.Free;
1532     end;
1533   end;
1534 
1535   procedure CheckDirectReference(aMarker: PSrcMarker);
1536   // check if one element at {=a} is a TPasAliasType pointing to an element labeled {#a}
1537   var
1538     aLabel: PSrcMarker;
1539     ReferenceElements, LabelElements: TFPList;
1540     i, LabelLine, LabelCol, j: Integer;
1541     El, LabelEl: TPasElement;
1542     DeclEl, TypeEl: TPasType;
1543   begin
1544     //writeln('CheckDirectReference searching pointer: ',aMarker^.Filename,' Line=',aMarker^.Row,' Col=',aMarker^.StartCol,'-',aMarker^.EndCol,' Label="',aMarker^.Identifier,'"');
1545     aLabel:=FindSrcLabel(aMarker^.Identifier);
1546     if aLabel=nil then
1547       RaiseErrorAtSrcMarker('label "'+aMarker^.Identifier+'" not found',aMarker);
1548 
1549     LabelElements:=nil;
1550     ReferenceElements:=nil;
1551     try
1552       //writeln('CheckDirectReference finding elements at label ...');
1553       LabelElements:=FindElementsAt(aLabel);
1554       //writeln('CheckDirectReference finding elements at reference ...');
1555       ReferenceElements:=FindElementsAt(aMarker);
1556 
1557       for i:=0 to ReferenceElements.Count-1 do
1558         begin
1559         El:=TPasElement(ReferenceElements[i]);
1560         //writeln('CheckDirectReference ',i,'/',ReferenceElements.Count,' ',GetTreeDbg(El,2));
1561         if El.ClassType=TPasVariable then
1562           begin
1563           if TPasVariable(El).VarType=nil then
1564             begin
1565             //writeln('CheckDirectReference Var without Type: ',GetObjName(El),' El.Parent=',GetObjName(El.Parent));
1566             AssertNotNull('TPasVariable(El='+El.Name+').VarType',TPasVariable(El).VarType);
1567             end;
1568           TypeEl:=TPasVariable(El).VarType;
1569           for j:=0 to LabelElements.Count-1 do
1570             begin
1571             LabelEl:=TPasElement(LabelElements[j]);
1572             if TypeEl=LabelEl then
1573               exit; // success
1574             end;
1575           end
1576         else if El is TPasAliasType then
1577           begin
1578           DeclEl:=TPasAliasType(El).DestType;
1579           ResolverEngine.UnmangleSourceLineNumber(DeclEl.SourceLinenumber,LabelLine,LabelCol);
1580           if (aLabel^.Filename=DeclEl.SourceFilename)
1581           and (integer(aLabel^.Row)=LabelLine)
1582           and (aLabel^.StartCol<=LabelCol)
1583           and (aLabel^.EndCol>=LabelCol) then
1584             exit; // success
1585           end
1586         else if El.ClassType=TPasArgument then
1587           begin
1588           TypeEl:=TPasArgument(El).ArgType;
1589           for j:=0 to LabelElements.Count-1 do
1590             begin
1591             LabelEl:=TPasElement(LabelElements[j]);
1592             if TypeEl=LabelEl then
1593               exit; // success
1594             end;
1595           end;
1596         end;
1597       // failed -> show candidates
1598       writeln('CheckDirectReference failed: Labels:');
1599       for j:=0 to LabelElements.Count-1 do
1600         begin
1601         LabelEl:=TPasElement(LabelElements[j]);
1602         writeln('  Label ',GetObjName(LabelEl),' at ',ResolverEngine.GetElementSourcePosStr(LabelEl));
1603         end;
1604       writeln('CheckDirectReference failed: References:');
1605       for i:=0 to ReferenceElements.Count-1 do
1606         begin
1607         El:=TPasElement(ReferenceElements[i]);
1608         writeln('  Reference ',GetObjName(El),' at ',ResolverEngine.GetElementSourcePosStr(El));
1609         //if EL is TPasVariable then
1610         //  writeln('CheckDirectReference ',GetObjPath(TPasVariable(El).VarType),' ',ResolverEngine.GetElementSourcePosStr(TPasVariable(EL).VarType));
1611         end;
1612       RaiseErrorAtSrcMarker('wrong direct reference "'+aMarker^.Identifier+'"',aMarker);
1613     finally
1614       LabelElements.Free;
1615       ReferenceElements.Free;
1616     end;
1617   end;
1618 
1619 var
1620   aMarker: PSrcMarker;
1621   i: Integer;
1622   SrcLines: TStringList;
1623 begin
1624   Module.ForEachCall(@OnCheckElementParent,nil);
1625   //writeln('TTestResolver.CheckReferenceDirectives find all markers');
1626   // find all markers
1627   for i:=0 to Resolver.Streams.Count-1 do
1628     begin
1629     GetSrc(i,SrcLines,Filename);
1630     ParseCode(SrcLines,Filename);
1631     SrcLines.Free;
1632     end;
1633 
1634   //writeln('TTestResolver.CheckReferenceDirectives check references');
1635   // check references
1636   aMarker:=FirstSrcMarker;
1637   while aMarker<>nil do
1638     begin
1639     case aMarker^.Kind of
1640     mkResolverReference: CheckResolverReference(aMarker);
1641     mkDirectReference: CheckDirectReference(aMarker);
1642     end;
1643     aMarker:=aMarker^.Next;
1644     end;
1645   //writeln('TTestResolver.CheckReferenceDirectives COMPLETE');
1646 end;
1647 
1648 procedure TCustomTestResolver.CheckResolverHint(MsgType: TMessageType;
1649   MsgNumber: integer; Msg: string; Marker: PSrcMarker);
1650 var
1651   i: Integer;
1652   Item: TTestResolverMessage;
1653   Expected,Actual: string;
1654 begin
1655   //writeln('TCustomTestResolver.CheckResolverHint MsgCount=',MsgCount);
1656   for i:=0 to MsgCount-1 do
1657     begin
1658     Item:=Msgs[i];
1659     if (Item.MsgNumber<>MsgNumber) or (Item.Msg<>Msg) then continue;
1660     if (Marker<>nil) then
1661       begin
1662       if Item.SourcePos.Row<>Marker^.Row then continue;
1663       if (integer(Item.SourcePos.Column)<Marker^.StartCol)
1664           or (integer(Item.SourcePos.Column)>Marker^.EndCol) then continue;
1665       end;
1666     // found
1667     FResolverGoodMsgs.Add(Item);
1668     str(Item.MsgType,Actual);
1669     str(MsgType,Expected);
1670     AssertEquals('MsgType',Expected,Actual);
1671     exit;
1672     end;
1673 
1674   // needed message missing -> show emitted messages
1675   WriteSources('',0,0);
1676   for i:=0 to MsgCount-1 do
1677     begin
1678     Item:=Msgs[i];
1679     write('TCustomTestResolver.CheckResolverHint ',i,'/',MsgCount,' ',Item.MsgType,
1680       ' ('+IntToStr(Item.MsgNumber),')');
1681     if Marker<>nil then
1682       write(' '+ExtractFileName(Item.SourcePos.FileName),'(',Item.SourcePos.Row,',',Item.SourcePos.Column,')');
1683     writeln(' {',Item.Msg,'}');
1684     end;
1685   str(MsgType,Expected);
1686   Actual:='Missing '+Expected+' ('+IntToStr(MsgNumber)+')';
1687   if Marker<>nil then
1688     Actual:=Actual+' '+ExtractFileName(Marker^.Filename)+'('+IntToStr(Marker^.Row)+','+IntToStr(Marker^.StartCol)+'..'+IntToStr(Marker^.EndCol)+')';
1689   Actual:=Actual+' '+Msg;
1690   Fail(Actual);
1691 end;
1692 
1693 procedure TCustomTestResolver.CheckResolverUnexpectedHints(
1694   WithSourcePos: boolean);
1695 var
1696   i: Integer;
1697   s, Txt: String;
1698   Msg: TTestResolverMessage;
1699 begin
1700   for i:=0 to MsgCount-1 do
1701     begin
1702     Msg:=Msgs[i];
1703     if FResolverGoodMsgs.IndexOf(Msg)>=0 then continue;
1704     s:='';
1705     str(Msg.MsgType,s);
1706     Txt:='Unexpected resolver message found ['+IntToStr(Msg.Id)+'] '
1707       +s+': ('+IntToStr(Msg.MsgNumber)+')';
1708     if WithSourcePos then
1709       Txt:=Txt+' '+ExtractFileName(Msg.SourcePos.FileName)+'('+IntToStr(Msg.SourcePos.Row)+','+IntToStr(Msg.SourcePos.Column)+')';
1710     Txt:=Txt+' {'+Msg.Msg+'}';
1711     Fail(Txt);
1712     end;
1713 end;
1714 
1715 procedure TCustomTestResolver.CheckResolverException(Msg: string; MsgNumber: integer);
1716 var
1717   ok: Boolean;
1718   Full: String;
1719 begin
1720   ok:=false;
1721   try
1722     ParseModule;
1723   except
1724     on E: EPasResolve do
1725       begin
1726       AssertEquals('Expected {'+Msg+'}, but got msg {'+E.Message+'} number',
1727         MsgNumber,E.MsgNumber);
1728       Full:=E.Message+' at '+E.SourcePos.FileName+' ('+IntToStr(E.SourcePos.Row)+','+IntToStr(E.SourcePos.Column)+')';
1729       if (Msg<>E.Message) and (Msg<>E.MsgPattern) and (Msg<>Full) then
1730         begin
1731         {$IFDEF VerbosePasResolver}
1732         writeln('TCustomTestResolver.CheckResolverException E.MsgPattern={',E.MsgPattern,'} E.Message={',E.Message,'} Full={',Full,'}');
1733         {$ENDIF}
1734         AssertEquals('Expected message ('+IntToStr(MsgNumber)+')',
1735           '{'+Msg+'}','{'+E.Message+'} OR {'+E.MsgPattern+'} OR {'+Full+'}');
1736         end;
1737       ok:=true;
1738       end;
1739   end;
1740   AssertEquals('Missing resolver error {'+Msg+'} ('+IntToStr(MsgNumber)+')',true,ok);
1741 end;
1742 
1743 procedure TCustomTestResolver.CheckParserException(Msg: string; MsgNumber: integer);
1744 var
1745   ok: Boolean;
1746 begin
1747   ok:=false;
1748   try
1749     ParseModule;
1750   except
1751     on E: EParserError do
1752       begin
1753       if (Parser.LastMsg<>Msg) and (Parser.LastMsgPattern<>Msg) and (E.Message<>Msg) then
1754         Fail('Expected msg {'+Msg+'}, but got {'+Parser.LastMsg+'} OR pattern {'+Parser.LastMsgPattern+'} OR E.Message {'+E.Message+'}');
1755       AssertEquals('Expected {'+Msg+'}, but got msg {'+E.Message+'} number',
1756         MsgNumber,Parser.LastMsgNumber);
1757       ok:=true;
1758       end;
1759   end;
1760   AssertEquals('Missing parser error '+Msg+' ('+IntToStr(MsgNumber)+')',true,ok);
1761 end;
1762 
1763 procedure TCustomTestResolver.CheckAccessMarkers;
1764 const
1765   AccessNames: array[TResolvedRefAccess] of string = (
1766     'none',
1767     'read',
1768     'assign',
1769     'readandassign',
1770     'var',
1771     'out',
1772     'paramtest'
1773     );
1774 var
1775   aMarker: PSrcMarker;
1776   Elements: TFPList;
1777   ActualAccess, ExpectedAccess: TResolvedRefAccess;
1778   i, j: Integer;
1779   El, El2: TPasElement;
1780   Ref: TResolvedReference;
1781   p: SizeInt;
1782   AccessPostfix: String;
1783 begin
1784   aMarker:=FirstSrcMarker;
1785   while aMarker<>nil do
1786     begin
1787     //writeln('TTestResolver.CheckAccessMarkers ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
1788     p:=RPos('_',aMarker^.Identifier);
1789     if p>1 then
1790       begin
1791       AccessPostfix:=copy(aMarker^.Identifier,p+1);
1792       ExpectedAccess:=High(TResolvedRefAccess);
1793       repeat
1794         if CompareText(AccessPostfix,AccessNames[ExpectedAccess])=0 then break;
1795         if ExpectedAccess=Low(TResolvedRefAccess) then
1796           RaiseErrorAtSrcMarker('unknown access postfix of reference at "#'+aMarker^.Identifier+'"',aMarker);
1797         ExpectedAccess:=Pred(ExpectedAccess);
1798       until false;
1799 
1800       Elements:=FindElementsAt(aMarker);
1801       try
1802         ActualAccess:=rraNone;
1803         for i:=0 to Elements.Count-1 do
1804           begin
1805           El:=TPasElement(Elements[i]);
1806           //writeln('TTestResolver.CheckAccessMarkers ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
1807           if not (El.CustomData is TResolvedReference) then continue;
1808           Ref:=TResolvedReference(El.CustomData);
1809           if ActualAccess<>rraNone then
1810             begin
1811             //writeln('TTestResolver.CheckAccessMarkers multiple references at "#'+aMarker^.Identifier+'":');
1812             for j:=0 to Elements.Count-1 do
1813               begin
1814               El2:=TPasElement(Elements[i]);
1815               if not (El2.CustomData is TResolvedReference) then continue;
1816               //writeln('TTestResolver.CheckAccessMarkers ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
1817               Ref:=TResolvedReference(El.CustomData);
1818               //writeln('  ',j,'/',Elements.Count,' Element=',GetObjName(El2),' ',AccessNames[Ref.Access],' Declaration="',El2.GetDeclaration(true),'"');
1819               end;
1820             RaiseErrorAtSrcMarker('multiple references at "#'+aMarker^.Identifier+'"',aMarker);
1821             end;
1822           ActualAccess:=Ref.Access;
1823           if ActualAccess=rraNone then
1824             RaiseErrorAtSrcMarker('missing Access in reference at "#'+aMarker^.Identifier+'"',aMarker);
1825           end;
1826         if ActualAccess<>ExpectedAccess then
1827           RaiseErrorAtSrcMarker('expected "'+AccessNames[ExpectedAccess]+'" at "#'+aMarker^.Identifier+'", but got "'+AccessNames[ActualAccess]+'"',aMarker);
1828       finally
1829         Elements.Free;
1830       end;
1831       end;
1832     aMarker:=aMarker^.Next;
1833     end;
1834 end;
1835 
1836 procedure TCustomTestResolver.CheckParamsExpr_pkSet_Markers;
1837 // e.g. {#a_set}  {#b_array}
1838 var
1839   aMarker: PSrcMarker;
1840   p: SizeInt;
1841   AccessPostfix: String;
1842   Elements: TFPList;
1843   i: Integer;
1844   El: TPasElement;
1845   Ref: TResolvedReference;
1846   ParamsExpr: TParamsExpr;
1847   NeedArray: Boolean;
1848 begin
1849   aMarker:=FirstSrcMarker;
1850   while aMarker<>nil do
1851     begin
1852     //writeln('TTestResolver.CheckParamsExpr_pkSet_Markers ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
1853     p:=RPos('_',aMarker^.Identifier);
1854     if p>1 then
1855       begin
1856       AccessPostfix:=copy(aMarker^.Identifier,p+1);
1857       if SameText(AccessPostfix,'set') then
1858         NeedArray:=false
1859       else if SameText(AccessPostfix,'array') then
1860         NeedArray:=true
1861       else
1862         RaiseErrorAtSrcMarker('unknown set/array postfix of [] expression at "#'+aMarker^.Identifier+'"',aMarker);
1863 
1864       Elements:=FindElementsAt(aMarker);
1865       try
1866         ParamsExpr:=nil;
1867         for i:=0 to Elements.Count-1 do
1868           begin
1869           El:=TPasElement(Elements[i]);
1870           //writeln('TTestResolver.CheckParamsExpr_pkSet_Markers ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
1871           if El.ClassType<>TParamsExpr then continue;
1872           if ParamsExpr<>nil then
1873             RaiseErrorAtSrcMarker('multiple paramsexpr found at "#'+aMarker^.Identifier+'"',aMarker);
1874 
1875           ParamsExpr:=TParamsExpr(El);
1876 
1877           if NeedArray then
1878             begin
1879             if not (El.CustomData is TResolvedReference) then
1880               RaiseErrorAtSrcMarker('array expr has no TResolvedReference at "#'+aMarker^.Identifier+'"',aMarker);
1881             Ref:=TResolvedReference(El.CustomData);
1882             if not (Ref.Declaration is TPasArrayType) then
1883               RaiseErrorAtSrcMarker('array expr Ref.Decl is not TPasArrayType (is '+GetObjName(Ref.Declaration)+') at "#'+aMarker^.Identifier+'"',aMarker);
1884             end
1885           else
1886             begin
1887             if not (El.CustomData is TResolvedReference) then
1888               continue; // good
1889             Ref:=TResolvedReference(El.CustomData);
1890             if Ref.Declaration is TPasArrayType then
1891               RaiseErrorAtSrcMarker('set expr Ref.Decl is '+GetObjName(Ref.Declaration)+' at "#'+aMarker^.Identifier+'"',aMarker);
1892             end;
1893           end;
1894         if TParamsExpr=nil then
1895           RaiseErrorAtSrcMarker('missing paramsexpr at "#'+aMarker^.Identifier+'"',aMarker);
1896       finally
1897         Elements.Free;
1898       end;
1899       end;
1900     aMarker:=aMarker^.Next;
1901     end;
1902 end;
1903 
1904 procedure TCustomTestResolver.CheckAttributeMarkers;
1905 // check markers of the form {#Attr__ClassMarker__ConstructorMarker[__OptionalName]}
1906 var
1907   aMarker, ClassMarker, ConstructorMarker: PSrcMarker;
1908   Elements: TFPList;
1909   i: Integer;
1910   El: TPasElement;
1911   Ref: TResolvedReference;
1912   s, ClassMarkerName, ConstructorMarkerName: String;
1913   p: SizeInt;
1914   ExpectedClass: TPasClassType;
1915   ExpectedConstrucor, ActualConstructor: TPasConstructor;
1916 begin
1917   aMarker:=FirstSrcMarker;
1918   while aMarker<>nil do
1919     begin
1920     s:=aMarker^.Identifier;
1921     if SameText(LeftStr(s,6),'Attr__') then
1922       begin
1923       //writeln('TCustomTestResolver.CheckAttributeMarkers ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
1924       Delete(s,1,6);
1925       p:=Pos('__',s);
1926       if p<1 then
1927         RaiseErrorAtSrcMarker('missing second __ at "#'+aMarker^.Identifier+'"',aMarker);
1928       ClassMarkerName:=LeftStr(s,p-1);
1929       Delete(s,1,p+1);
1930       p:=Pos('__',s);
1931       if p<1 then
1932         ConstructorMarkerName:=s
1933       else
1934         ConstructorMarkerName:=copy(s,1,p-1);
1935 
1936       // find attribute class at ClassMarkerName
1937       ClassMarker:=FindSrcLabel(ClassMarkerName);
1938       if ClassMarker=nil then
1939         RaiseErrorAtSrcMarker('ClassMarker "'+ClassMarkerName+'" not found at "#'+aMarker^.Identifier+'"',aMarker);
1940       ExpectedClass:=nil;
1941       Elements:=FindElementsAt(ClassMarker);
1942       try
1943         for i:=0 to Elements.Count-1 do
1944           begin
1945           El:=TPasElement(Elements[i]);
1946           if El is TPasClassType then
1947             begin
1948             ExpectedClass:=TPasClassType(El);
1949             break;
1950             end;
1951           end;
1952         if ExpectedClass=nil then
1953           RaiseErrorAtSrcMarker('ClassMarker "'+ClassMarkerName+'" at "#'+aMarker^.Identifier+'" has no TPasClassType',aMarker);
1954       finally
1955         Elements.Free;
1956       end;
1957 
1958       // find constructor at ConstructorMarkerName
1959       ConstructorMarker:=FindSrcLabel(ConstructorMarkerName);
1960       if ConstructorMarker=nil then
1961         RaiseErrorAtSrcMarker('ConstructorMarker "'+ConstructorMarkerName+'" not found at "#'+aMarker^.Identifier+'"',aMarker);
1962       ExpectedConstrucor:=nil;
1963       Elements:=FindElementsAt(ConstructorMarker);
1964       try
1965         for i:=0 to Elements.Count-1 do
1966           begin
1967           El:=TPasElement(Elements[i]);
1968           if El is TPasConstructor then
1969             begin
1970             ExpectedConstrucor:=TPasConstructor(El);
1971             break;
1972             end;
1973           end;
1974         if ExpectedConstrucor=nil then
1975           RaiseErrorAtSrcMarker('ConstructorMarker "'+ConstructorMarkerName+'" at "#'+aMarker^.Identifier+'" has no TPasConstructor',aMarker);
1976       finally
1977         Elements.Free;
1978       end;
1979 
1980       Elements:=FindElementsAt(aMarker);
1981       try
1982         for i:=0 to Elements.Count-1 do
1983           begin
1984           El:=TPasElement(Elements[i]);
1985           //writeln('TCustomTestResolver.CheckAttributeMarkers ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
1986           if not (El.CustomData is TResolvedReference) then continue;
1987           Ref:=TResolvedReference(El.CustomData);
1988           if Ref.Declaration<>ExpectedClass then
1989             RaiseErrorAtSrcMarker('Ref.Declaration at "#'+aMarker^.Identifier+'", expected "'+ExpectedClass.FullName+'" but found "'+Ref.Declaration.FullName+'", El='+GetObjName(El),aMarker);
1990           if not (Ref.Context is TResolvedRefCtxAttrProc) then
1991             RaiseErrorAtSrcMarker('Ref.Context at "#'+aMarker^.Identifier+'", expected "TResolvedRefCtxAttrConstructor" but found "'+GetObjName(Ref.Context)+'", El='+GetObjName(El),aMarker);
1992           ActualConstructor:=TResolvedRefCtxAttrProc(Ref.Context).Proc;
1993           if ActualConstructor<>ExpectedConstrucor then
1994             RaiseErrorAtSrcMarker('Ref.Context.Proc at "#'+aMarker^.Identifier+'", expected "'+ExpectedConstrucor.FullName+'" but found "'+ActualConstructor.FullName+'", El='+GetObjName(El),aMarker);
1995           break;
1996           end;
1997       finally
1998         Elements.Free;
1999       end;
2000       end;
2001     aMarker:=aMarker^.Next;
2002     end;
2003 end;
2004 
2005 procedure TCustomTestResolver.GetSrc(Index: integer; out SrcLines: TStringList; out
2006   aFilename: string);
2007 var
2008   aStream: TStream;
2009 begin
2010   SrcLines:=TStringList.Create;
2011   aStream:=Resolver.Streams.Objects[Index] as TStream;
2012   aStream.Position:=0;
2013   SrcLines.LoadFromStream(aStream);
2014   aFilename:=Resolver.Streams[Index];
2015 end;
2016 
FindElementsAtnull2017 function TCustomTestResolver.FindElementsAt(aFilename: string; aLine, aStartCol,
2018   aEndCol: integer): TFPList;
2019 var
2020   ok: Boolean;
2021   FoundRefs: TTestResolverReferenceData;
2022   i: Integer;
2023   CurResolver: TTestEnginePasResolver;
2024 begin
2025   //writeln('TCustomTestResolver.FindElementsAt START "',aFilename,'" Line=',aLine,' Col=',aStartCol,'-',aEndCol);
2026   FoundRefs:=Default(TTestResolverReferenceData);
2027   FoundRefs.Filename:=aFilename;
2028   FoundRefs.Row:=aLine;
2029   FoundRefs.StartCol:=aStartCol;
2030   FoundRefs.EndCol:=aEndCol;
2031   FoundRefs.Found:=TFPList.Create;
2032   ok:=false;
2033   try
2034     // find all markers
2035     Module.ForEachCall(@OnFindReference,@FoundRefs);
2036     for i:=0 to ModuleCount-1 do
2037       begin
2038       CurResolver:=Modules[i];
2039       if CurResolver.Module=Module then continue;
2040       //writeln('TCustomTestResolver.FindElementsAt ',CurResolver.Filename);
2041       CurResolver.Module.ForEachCall(@OnFindReference,@FoundRefs);
2042       end;
2043     ok:=true;
2044   finally
2045     if not ok then
2046       FreeAndNil(FoundRefs.Found);
2047   end;
2048   Result:=FoundRefs.Found;
2049   FoundRefs.Found:=nil;
2050 end;
2051 
FindElementsAtnull2052 function TCustomTestResolver.FindElementsAt(aMarker: PSrcMarker;
2053   ErrorOnNoElements: boolean): TFPList;
2054 begin
2055   Result:=FindElementsAt(aMarker^.Filename,aMarker^.Row,aMarker^.StartCol,aMarker^.EndCol);
2056   if ErrorOnNoElements and ((Result=nil) or (Result.Count=0)) then
2057     RaiseErrorAtSrcMarker('marker '+SrcMarker[aMarker^.Kind]+aMarker^.Identifier+' has no elements',aMarker);
2058 end;
2059 
FindSrcLabelnull2060 function TCustomTestResolver.FindSrcLabel(const Identifier: string): PSrcMarker;
2061 begin
2062   Result:=FirstSrcMarker;
2063   while Result<>nil do
2064     begin
2065     if (Result^.Kind=mkLabel)
2066     and (CompareText(Result^.Identifier,Identifier)=0) then
2067       exit;
2068     Result:=Result^.Next;
2069     end;
2070 end;
2071 
FindElementsAtSrcLabelnull2072 function TCustomTestResolver.FindElementsAtSrcLabel(const Identifier: string;
2073   ErrorOnNoElements: boolean): TFPList;
2074 var
2075   SrcLabel: PSrcMarker;
2076 begin
2077   SrcLabel:=FindSrcLabel(Identifier);
2078   if SrcLabel=nil then
2079     Fail('missing label "'+Identifier+'"');
2080   Result:=FindElementsAt(SrcLabel,ErrorOnNoElements);
2081 end;
2082 
2083 procedure TCustomTestResolver.WriteSources(const aFilename: string; aRow,
2084   aCol: integer);
2085 var
2086   IsSrc: Boolean;
2087   i, j: Integer;
2088   SrcLines: TStringList;
2089   SrcFilename, Line: string;
2090 begin
2091   for i:=0 to Resolver.Streams.Count-1 do
2092     begin
2093     GetSrc(i,SrcLines,SrcFilename);
2094     IsSrc:=ExtractFilename(SrcFilename)=ExtractFileName(aFilename);
2095     writeln('Testcode:-File="',SrcFilename,'"----------------------------------:');
2096     for j:=1 to SrcLines.Count do
2097       begin
2098       Line:=SrcLines[j-1];
2099       if IsSrc and (j=aRow) then
2100         begin
2101         write('*');
2102         Line:=LeftStr(Line,aCol-1)+'|'+copy(Line,aCol,length(Line));
2103         end;
2104       writeln(Format('%:4d: ',[j]),Line);
2105       end;
2106     SrcLines.Free;
2107     end;
2108 end;
2109 
2110 procedure TCustomTestResolver.RaiseErrorAtSrc(Msg: string; const aFilename: string;
2111   aRow, aCol: integer);
2112 var
2113   s: String;
2114 begin
2115   WriteSources(aFilename,aRow,aCol);
2116   s:='[TTestResolver.RaiseErrorAtSrc] '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+') Error: '+Msg;
2117   writeln('ERROR: ',s);
2118   Fail(s);
2119 end;
2120 
2121 procedure TCustomTestResolver.RaiseErrorAtSrcMarker(Msg: string; aMarker: PSrcMarker);
2122 begin
2123   RaiseErrorAtSrc(Msg,aMarker^.Filename,aMarker^.Row,aMarker^.StartCol);
2124 end;
2125 
2126 procedure TCustomTestResolver.HandleError(CurEngine: TTestEnginePasResolver;
2127   E: Exception);
2128 var
2129   ErrFilename: String;
2130   ErrRow, ErrCol: Integer;
2131 begin
2132   ErrFilename:=CurEngine.Scanner.CurFilename;
2133   ErrRow:=CurEngine.Scanner.CurRow;
2134   ErrCol:=CurEngine.Scanner.CurColumn;
2135   writeln('ERROR: TCustomTestResolver.HandleError during parsing: '+E.ClassName+':'+E.Message
2136     +' File='+ErrFilename
2137     +' LineNo='+IntToStr(ErrRow)
2138     +' Col='+IntToStr(ErrCol)
2139     +' Line="'+CurEngine.Scanner.CurLine+'"'
2140     );
2141   WriteSources(ErrFilename,ErrRow,ErrCol);
2142   Fail(E.Message);
2143 end;
2144 
2145 constructor TCustomTestResolver.Create;
2146 begin
2147   inherited Create;
2148   FResolverMsgs:=TObjectList.Create(true);
2149   FResolverGoodMsgs:=TFPList.Create;
2150 end;
2151 
2152 destructor TCustomTestResolver.Destroy;
2153 begin
2154   FreeAndNil(FResolverMsgs);
2155   FreeAndNil(FResolverGoodMsgs);
2156   inherited Destroy;
2157 end;
2158 
FindModuleWithFilenamenull2159 function TCustomTestResolver.FindModuleWithFilename(aFilename: string
2160   ): TTestEnginePasResolver;
2161 var
2162   i: Integer;
2163 begin
2164   for i:=0 to ModuleCount-1 do
2165     if CompareText(Modules[i].Filename,aFilename)=0 then
2166       exit(Modules[i]);
2167   Result:=nil;
2168 end;
2169 
TCustomTestResolver.AddModulenull2170 function TCustomTestResolver.AddModule(aFilename: string): TTestEnginePasResolver;
2171 begin
2172   //writeln('TTestResolver.AddModule ',aFilename);
2173   if FindModuleWithFilename(aFilename)<>nil then
2174     Fail('TTestResolver.AddModule: file "'+aFilename+'" already exists');
2175   Result:=TTestEnginePasResolver.Create;
2176   Result.Filename:=aFilename;
2177   Result.AddObjFPCBuiltInIdentifiers;
2178   Result.OnFindUnit:=@OnPasResolverFindUnit;
2179   Result.OnLog:=@OnPasResolverLog;
2180   Result.Hub:=Hub;
2181   FModules.Add(Result);
2182 end;
2183 
TCustomTestResolver.AddModuleWithSrcnull2184 function TCustomTestResolver.AddModuleWithSrc(aFilename, Src: string
2185   ): TTestEnginePasResolver;
2186 begin
2187   Result:=AddModule(aFilename);
2188   Result.Source:=Src;
2189 end;
2190 
TCustomTestResolver.AddModuleWithIntfImplSrcnull2191 function TCustomTestResolver.AddModuleWithIntfImplSrc(aFilename, InterfaceSrc,
2192   ImplementationSrc: string): TTestEnginePasResolver;
2193 var
2194   Src: String;
2195 begin
2196   Src:='unit '+ExtractFileUnitName(aFilename)+';'+LineEnding;
2197   Src+=LineEnding;
2198   Src+='interface'+LineEnding;
2199   Src+=LineEnding;
2200   Src+=InterfaceSrc;
2201   Src+='implementation'+LineEnding;
2202   Src+=LineEnding;
2203   Src+=ImplementationSrc;
2204   Src+='end.'+LineEnding;
2205   Result:=AddModuleWithSrc(aFilename,Src);
2206 end;
2207 
2208 procedure TCustomTestResolver.AddSystemUnit(Parts: TSystemUnitParts);
2209 var
2210   Intf, Impl: TStringList;
2211 begin
2212   Intf:=TStringList.Create;
2213   // interface
2214   Intf.Add('type');
2215   if supTTypeKind in Parts then
2216     begin
2217     Intf.Add('  TTypeKind=(tkUnknown,tkInteger,tkChar,tkEnumeration,tkFloat,');
2218     Intf.Add('             tkSet,tkMethod,tkSString,tkLString,tkAString,');
2219     Intf.Add('             tkWString,tkVariant,tkArray,tkRecord,tkInterface,');
2220     Intf.Add('             tkClass,tkObject,tkWChar,tkBool,tkInt64,tkQWord,');
2221     Intf.Add('             tkDynArray,tkInterfaceRaw,tkProcVar,tkUString,tkUChar,');
2222     Intf.Add('             tkHelper,tkFile,tkClassRef,tkPointer);');
2223     end;
2224   Intf.Add('  integer=longint;');
2225   Intf.Add('  sizeint=int64;');
2226     //'const',
2227     //'  LineEnding = #10;',
2228     //'  DirectorySeparator = ''/'';',
2229     //'  DriveSeparator = '''';',
2230     //'  AllowDirectorySeparators : set of char = [''\'',''/''];',
2231     //'  AllowDriveSeparators : set of char = [];',
2232   if supTObject in Parts then
2233     begin
2234     Intf.AddStrings([
2235     'type',
2236     '  TClass = class of TObject;',
2237     '  TObject = class',
2238     '    constructor Create;',
2239     '    destructor Destroy; virtual;',
2240     '    class function ClassType: TClass; assembler;',
2241     '    class function ClassName: String; assembler;',
2242     '    class function ClassNameIs(const Name: string): boolean;',
2243     '    class function ClassParent: TClass; assembler;',
2244     '    class function InheritsFrom(aClass: TClass): boolean; assembler;',
2245     '    class function UnitName: String; assembler;',
2246     '    procedure AfterConstruction; virtual;',
2247     '    procedure BeforeDestruction;virtual;',
2248     '    function Equals(Obj: TObject): boolean; virtual;',
2249     '    function ToString: String; virtual;',
2250     '  end;']);
2251     end;
2252   if supTVarRec in Parts then
2253     begin
2254     Intf.AddStrings([
2255     'const',
2256     '  vtInteger       = 0;',
2257     '  vtBoolean       = 1;',
2258     'type',
2259     '  PVarRec = ^TVarRec;',
2260     '  TVarRec = record',
2261     '    case VType : sizeint of',
2262     '    vtInteger       : (VInteger: Longint);',
2263     '    vtBoolean       : (VBoolean: Boolean);',
2264     '  end;']);
2265     end;
2266   Intf.Add('var');
2267   Intf.Add('  ExitCode: Longint = 0;');
2268 
2269   // implementation
2270   Impl:=TStringList.Create;
2271   if supTObject in Parts then
2272     begin
2273     Impl.AddStrings([
2274       '// needed by ClassNameIs, the real SameText is in SysUtils',
2275       'function SameText(const s1, s2: String): Boolean; assembler;',
2276       'asm',
2277       'end;',
2278       'constructor TObject.Create; begin end;',
2279       'destructor TObject.Destroy; begin end;',
2280       'class function TObject.ClassType: TClass; assembler;',
2281       'asm',
2282       'end;',
2283       'class function TObject.ClassName: String; assembler;',
2284       'asm',
2285       'end;',
2286       'class function TObject.ClassNameIs(const Name: string): boolean;',
2287       'begin',
2288       '  Result:=SameText(Name,ClassName);',
2289       'end;',
2290       'class function TObject.ClassParent: TClass; assembler;',
2291       'asm',
2292       'end;',
2293       'class function TObject.InheritsFrom(aClass: TClass): boolean; assembler;',
2294       'asm',
2295       'end;',
2296       'class function TObject.UnitName: String; assembler;',
2297       'asm',
2298       'end;',
2299       'procedure TObject.AfterConstruction; begin end;',
2300       'procedure TObject.BeforeDestruction; begin end;',
2301       'function TObject.Equals(Obj: TObject): boolean;',
2302       'begin',
2303       '  Result:=Obj=Self;',
2304       'end;',
2305       'function TObject.ToString: String;',
2306       'begin',
2307       '  Result:=ClassName;',
2308       'end;'
2309       ]);
2310     end;
2311 
2312   try
2313     AddModuleWithIntfImplSrc('system.pp',Intf.Text,Impl.Text);
2314   finally
2315     Intf.Free;
2316     Impl.Free;
2317   end;
2318 end;
2319 
2320 procedure TCustomTestResolver.StartProgram(NeedSystemUnit: boolean;
2321   SystemUnitParts: TSystemUnitParts);
2322 begin
2323   if NeedSystemUnit then
2324     AddSystemUnit(SystemUnitParts)
2325   else
2326     Parser.ImplicitUses.Clear;
2327   Add('program '+ExtractFileUnitName(MainFilename)+';');
2328 end;
2329 
2330 procedure TCustomTestResolver.StartUnit(NeedSystemUnit: boolean);
2331 begin
2332   if NeedSystemUnit then
2333     AddSystemUnit
2334   else
2335     Parser.ImplicitUses.Clear;
2336   Add('unit '+ExtractFileUnitName(MainFilename)+';');
2337 end;
2338 
OnPasResolverFindUnitnull2339 function TCustomTestResolver.OnPasResolverFindUnit(SrcResolver: TPasResolver;
2340   const aUnitName, InFilename: String; NameExpr, InFileExpr: TPasExpr
2341   ): TPasModule;
2342 
InitUnitnull2343   function InitUnit(CurEngine: TTestEnginePasResolver): TPasModule;
2344   begin
2345     if CurEngine.Module<>nil then
2346       Fail('InitUnit '+GetObjName(CurEngine.Module));
2347     CurEngine.StreamResolver:=Resolver;
2348     //writeln('TTestResolver.OnPasResolverFindUnit SOURCE=',CurEngine.Source);
2349     CurEngine.StreamResolver.AddStream(CurEngine.FileName,
2350                                     TStringStream.Create(CurEngine.Source));
2351     CurEngine.Scanner:=TPascalScanner.Create(CurEngine.StreamResolver);
2352     CurEngine.Scanner.CurrentBoolSwitches:=[bsHints,bsNotes,bsWarnings];
2353     CurEngine.Parser:=TPasParser.Create(CurEngine.Scanner,
2354                                         CurEngine.StreamResolver,CurEngine);
2355     CurEngine.Parser.Options:=CurEngine.Parser.Options+[po_StopOnUnitInterface];
2356     if CompareText(ExtractFileUnitName(CurEngine.Filename),'System')=0 then
2357       CurEngine.Parser.ImplicitUses.Clear;
2358     CurEngine.Scanner.OpenFile(CurEngine.Filename);
2359     try
2360       CurEngine.Parser.NextToken;
2361       CurEngine.Parser.ParseUnit(CurEngine.FModule);
2362     except
2363       on E: Exception do
2364         HandleError(CurEngine,E);
2365     end;
2366     //writeln('TTestResolver.OnPasResolverFindUnit END ',CurUnitName);
2367     Result:=CurEngine.Module;
2368   end;
2369 
FindUnitnull2370   function FindUnit(const aUnitName: String): TPasModule;
2371   var
2372     i: Integer;
2373     CurEngine: TTestEnginePasResolver;
2374     CurUnitName: String;
2375   begin
2376     {$IFDEF VerboseUnitSearch}
2377     writeln('TTestResolver.OnPasResolverFindUnit START Unit="',aUnitName,'"');
2378     {$ENDIF}
2379     Result:=nil;
2380     for i:=0 to ModuleCount-1 do
2381       begin
2382       CurEngine:=Modules[i];
2383       CurUnitName:=ExtractFileUnitName(CurEngine.Filename);
2384       {$IFDEF VerboseUnitSearch}
2385       writeln('TTestResolver.OnPasResolverFindUnit Checking ',i,'/',ModuleCount,' ',CurEngine.Filename,' ',CurUnitName);
2386       {$ENDIF}
2387       if CompareText(aUnitName,CurUnitName)=0 then
2388         begin
2389         Result:=CurEngine.Module;
2390         {$IFDEF VerboseUnitSearch}
2391         writeln('TTestResolver.OnPasResolverFindUnit Found unit "',CurEngine.Filename,'" Module=',GetObjName(Result));
2392         {$ENDIF}
2393         if Result<>nil then exit;
2394         {$IFDEF VerboseUnitSearch}
2395         writeln('TTestResolver.OnPasResolverFindUnit PARSING unit "',CurEngine.Filename,'"');
2396         {$ENDIF}
2397         Result:=InitUnit(CurEngine);
2398         exit;
2399         end;
2400       end;
2401   end;
2402 
GetResolvernull2403   function GetResolver(aFilename: string): boolean;
2404   var
2405     CurEngine: TTestEnginePasResolver;
2406     aModule: TPasModule;
2407   begin
2408     {$IFDEF VerbosePasResolver}
2409     writeln('TCustomTestResolver.OnPasResolverFindUnit searching file "',aFilename,'"');
2410     {$ENDIF}
2411     CurEngine:=FindModuleWithFilename(aFilename);
2412     if CurEngine=nil then exit(false);
2413     if CurEngine.Module=nil then
2414       begin
2415       aModule:=InitUnit(CurEngine);
2416       if aModule=nil then exit(false);
2417       end
2418     else
2419       aModule:=CurEngine.Module;
2420     OnPasResolverFindUnit:=aModule;
2421     Result:=true;
2422   end;
2423 
2424 var
2425   aFilename: String;
2426 begin
2427   if SrcResolver=nil then ;
2428   if NameExpr=nil then ;
2429   if InFilename<>'' then
2430     begin
2431     // uses IN parameter
2432     {$IFDEF VerbosePasResolver}
2433     writeln('TCustomTestResolver.OnPasResolverFindUnit searching IN-file "',InFilename,'"');
2434     {$ENDIF}
2435     if SrcResolver<>ResolverEngine then
2436       SrcResolver.RaiseMsg(20180222004753,100000,'in-file only allowed in program',
2437          [],InFileExpr);
2438 
2439     aFilename:=InFilename;
2440     DoDirSeparators(aFilename);
2441     if FilenameIsAbsolute(aFilename) then
2442       if GetResolver(aFilename) then exit;
2443     aFilename:=ExtractFilePath(ResolverEngine.Filename)+aFilename;
2444     if GetResolver(aFilename) then exit;
2445     SrcResolver.RaiseMsg(20180222004311,100001,'in-file ''%s'' not found',
2446       [InFilename],InFileExpr);
2447     end;
2448 
2449   if (Pos('.',aUnitName)<1) and (ResolverEngine.DefaultNameSpace<>'') then
2450     begin
2451     // first search in default program namespace
2452     {$IFDEF VerbosePasResolver}
2453     writeln('TCustomTestResolver.OnPasResolverFindUnit searching "',aUnitName,'" in default program/library namespace "',ResolverEngine.DefaultNameSpace,'"');
2454     {$ENDIF}
2455     Result:=FindUnit(ResolverEngine.DefaultNameSpace+'.'+aUnitName);
2456     if Result<>nil then exit;
2457     end;
2458   Result:=FindUnit(aUnitName);
2459   if Result<>nil then exit;
2460   {$IFDEF VerbosePasResolver}
2461   writeln('TTestResolver.OnPasResolverFindUnit missing unit "',aUnitName,'"');
2462   {$ENDIF}
2463 end;
2464 
2465 procedure TCustomTestResolver.OnFindReference(El: TPasElement; FindData: pointer);
2466 var
2467   Data: PTestResolverReferenceData absolute FindData;
2468   Line, Col: integer;
2469 begin
2470   ResolverEngine.UnmangleSourceLineNumber(El.SourceLinenumber,Line,Col);
2471   //writeln('TTestResolver.OnFindReference ',El.SourceFilename,' Line=',Line,',Col=',Col,' ',GetObjName(El),' SearchFile=',Data^.Filename,',Line=',Data^.Row,',Col=',Data^.StartCol,'-',Data^.EndCol);
2472   if (Data^.Filename=El.SourceFilename)
2473   and (Data^.Row=Line)
2474   and (Data^.StartCol<=Col)
2475   and (Data^.EndCol>=Col)
2476   then
2477     Data^.Found.Add(El);
2478 end;
2479 
2480 procedure TCustomTestResolver.OnCheckElementParent(El: TPasElement; arg: pointer);
2481 var
2482   SubEl: TPasElement;
2483   i: Integer;
2484 
2485   procedure E(Msg: string);
2486   var
2487     s: String;
2488   begin
2489     s:='TTestResolver.OnCheckElementParent El='+GetTreeDbg(El)+' '+
2490       ResolverEngine.GetElementSourcePosStr(El)+' '+Msg;
2491     writeln('ERROR: ',s);
2492     Fail(s);
2493   end;
2494 
2495 begin
2496   if arg=nil then ;
2497   //writeln('TTestResolver.OnCheckElementParent ',GetObjName(El));
2498   if El=nil then exit;
2499   if El.Parent=El then
2500     E('El.Parent=El='+GetObjName(El));
2501   if El is TBinaryExpr then
2502     begin
2503     if (TBinaryExpr(El).left<>nil) and (TBinaryExpr(El).left.Parent<>El) then
2504       E('TBinaryExpr(El).left.Parent='+GetObjName(TBinaryExpr(El).left.Parent)+'<>El');
2505     if (TBinaryExpr(El).right<>nil) and (TBinaryExpr(El).right.Parent<>El) then
2506       E('TBinaryExpr(El).right.Parent='+GetObjName(TBinaryExpr(El).right.Parent)+'<>El');
2507     end
2508   else if El is TParamsExpr then
2509     begin
2510     if (TParamsExpr(El).Value<>nil) and (TParamsExpr(El).Value.Parent<>El) then
2511       E('TParamsExpr(El).Value.Parent='+GetObjName(TParamsExpr(El).Value.Parent)+'<>El');
2512     for i:=0 to length(TParamsExpr(El).Params)-1 do
2513       if TParamsExpr(El).Params[i].Parent<>El then
2514         E('TParamsExpr(El).Params[i].Parent='+GetObjName(TParamsExpr(El).Params[i].Parent)+'<>El');
2515     end
2516   else if El is TProcedureExpr then
2517     begin
2518     if (TProcedureExpr(El).Proc<>nil) and (TProcedureExpr(El).Proc.Parent<>El) then
2519       E('TProcedureExpr(El).Proc.Parent='+GetObjName(TProcedureExpr(El).Proc.Parent)+'<>El');
2520     end
2521   else if El is TPasDeclarations then
2522     begin
2523     for i:=0 to TPasDeclarations(El).Declarations.Count-1 do
2524       begin
2525       SubEl:=TPasElement(TPasDeclarations(El).Declarations[i]);
2526       if SubEl.Parent<>El then
2527         E('SubEl=TPasElement(TPasDeclarations(El).Declarations[i])='+GetObjName(SubEl)+' SubEl.Parent='+GetObjName(SubEl.Parent)+'<>El');
2528       end;
2529     end
2530   else if El is TPasImplBlock then
2531     begin
2532     for i:=0 to TPasImplBlock(El).Elements.Count-1 do
2533       begin
2534       SubEl:=TPasElement(TPasImplBlock(El).Elements[i]);
2535       if SubEl.Parent<>El then
2536         E('TPasElement(TPasImplBlock(El).Elements[i]).Parent='+GetObjName(SubEl.Parent)+'<>El');
2537       end;
2538     end
2539   else if El is TPasImplWithDo then
2540     begin
2541     for i:=0 to TPasImplWithDo(El).Expressions.Count-1 do
2542       begin
2543       SubEl:=TPasExpr(TPasImplWithDo(El).Expressions[i]);
2544       if SubEl.Parent<>El then
2545         E('TPasExpr(TPasImplWithDo(El).Expressions[i]).Parent='+GetObjName(SubEl.Parent)+'<>El');
2546       end;
2547     end
2548   else if El is TPasProcedure then
2549     begin
2550     if TPasProcedure(El).ProcType.Parent<>El then
2551       E('TPasProcedure(El).ProcType.Parent='+GetObjName(TPasProcedure(El).ProcType.Parent)+'<>El');
2552     end
2553   else if El is TPasProcedureType then
2554     begin
2555     for i:=0 to TPasProcedureType(El).Args.Count-1 do
2556       if TPasArgument(TPasProcedureType(El).Args[i]).Parent<>El then
2557         E('TPasArgument(TPasProcedureType(El).Args[i]).Parent='+GetObjName(TPasArgument(TPasProcedureType(El).Args[i]).Parent)+'<>El');
2558     end;
2559 end;
2560 
2561 procedure TCustomTestResolver.FreeSrcMarkers;
2562 var
2563   aMarker, Last: PSrcMarker;
2564 begin
2565   aMarker:=FirstSrcMarker;
2566   while aMarker<>nil do
2567     begin
2568     Last:=aMarker;
2569     aMarker:=aMarker^.Next;
2570     Dispose(Last);
2571     end;
2572   FirstSrcMarker:=nil;
2573   LastSrcMarker:=nil;
2574 end;
2575 
2576 procedure TCustomTestResolver.OnPasResolverLog(Sender: TObject;
2577   const Msg: String);
2578 var
2579   aResolver: TTestEnginePasResolver;
2580   Item: TTestResolverMessage;
2581 begin
2582   aResolver:=Sender as TTestEnginePasResolver;
2583   Item:=TTestResolverMessage.Create;
2584   Item.Id:=aResolver.LastMsgId;
2585   Item.MsgType:=aResolver.LastMsgType;
2586   Item.MsgNumber:=aResolver.LastMsgNumber;
2587   Item.Msg:=Msg;
2588   Item.SourcePos:=aResolver.LastSourcePos;
2589   {$IFDEF VerbosePasResolver}
2590   writeln('TCustomTestResolver.OnPasResolverLog ',GetObjName(Sender),' ',Item.MsgType,' (',Item.MsgNumber,') {',Msg,'}');
2591   {$ENDIF}
2592   FResolverMsgs.Add(Item);
2593 end;
2594 
2595 procedure TCustomTestResolver.OnScannerDirective(Sender: TObject; Directive,
2596   Param: String; var Handled: boolean);
2597 var
2598   aScanner: TPascalScanner;
2599 begin
2600   if Handled then exit;
2601   aScanner:=Sender as TPascalScanner;
2602   aScanner.LastMsgType:=mtError;
2603   aScanner.LastMsg:='unknown directive "'+Directive+'"';
2604   aScanner.LastMsgPattern:=aScanner.LastMsg;
2605   aScanner.LastMsgArgs:=nil;
2606   raise EScannerError.Create(aScanner.LastMsg);
2607   if Param='' then ;
2608 end;
2609 
2610 procedure TCustomTestResolver.OnScannerLog(Sender: TObject; const Msg: String);
2611 var
2612   aScanner: TPascalScanner;
2613 begin
2614   aScanner:=TPascalScanner(Sender);
2615   if aScanner=nil then exit;
2616   {$IFDEF VerbosePasResolver}
2617   writeln('TCustomTestResolver.OnScannerLog ',GetObjName(Sender),' ',aScanner.LastMsgType,' ',aScanner.LastMsgNumber,' Msg="', Msg,'"');
2618   {$ENDIF}
2619 end;
2620 
TCustomTestResolver.GetModulesnull2621 function TCustomTestResolver.GetModules(Index: integer): TTestEnginePasResolver;
2622 begin
2623   Result:=TTestEnginePasResolver(FModules[Index]);
2624 end;
2625 
TCustomTestResolver.GetMsgCountnull2626 function TCustomTestResolver.GetMsgCount: integer;
2627 begin
2628   Result:=FResolverMsgs.Count;
2629 end;
2630 
TCustomTestResolver.GetMsgsnull2631 function TCustomTestResolver.GetMsgs(Index: integer): TTestResolverMessage;
2632 begin
2633   Result:=TTestResolverMessage(FResolverMsgs[Index]);
2634 end;
2635 
2636 procedure TCustomTestResolver.OnPasResolverContinueParsing(Sender: TPasResolver
2637   );
2638 var
2639   CurEngine: TTestEnginePasResolver;
2640 begin
2641   CurEngine:=Sender as TTestEnginePasResolver;
2642   {$IFDEF VerbosePasResolver}
2643   writeln('TCustomTestResolver.OnPasResolverContinueParsing "',CurEngine.Module.Name,'"...');
2644   {$ENDIF}
2645   try
2646     CurEngine.Parser.ParseContinue;
2647   except
2648     on E: Exception do
2649       HandleError(CurEngine,E);
2650   end;
2651 end;
2652 
GetModuleCountnull2653 function TCustomTestResolver.GetModuleCount: integer;
2654 begin
2655   Result:=FModules.Count;
2656 end;
2657 
2658 { TTestResolver }
2659 
2660 procedure TTestResolver.TestEmpty;
2661 begin
2662   StartProgram(false);
2663   Add('begin');
2664   ParseProgram;
2665   AssertEquals('No statements',0,PasProgram.InitializationSection.Elements.Count);
2666 end;
2667 
2668 procedure TTestResolver.TestAliasType;
2669 var
2670   El: TPasElement;
2671   T: TPasAliasType;
2672 begin
2673   StartProgram(false);
2674   Add('type');
2675   Add('  tint=longint;');
2676   Add('begin');
2677   ParseProgram;
2678   AssertEquals('1 declaration',1,PasProgram.ProgramSection.Declarations.Count);
2679   El:=TPasElement(PasProgram.ProgramSection.Declarations[0]);
2680   AssertEquals('Type',TPasAliasType,El.ClassType);
2681   T:=TPasAliasType(El);
2682   AssertEquals('Type tint','tint',T.Name);
2683   AssertEquals('Type built-in',TPasUnresolvedSymbolRef,T.DestType.ClassType);
2684   AssertEquals('longint type','longint',lowercase(T.DestType.Name));
2685 end;
2686 
2687 procedure TTestResolver.TestAlias2Type;
2688 var
2689   El: TPasElement;
2690   T1, T2: TPasAliasType;
2691   DestT1, DestT2: TPasType;
2692 begin
2693   StartProgram(false);
2694   Add('type');
2695   Add('  tint1=longint;');
2696   Add('  tint2=tint1;');
2697   Add('begin');
2698   ParseProgram;
2699   AssertEquals('2 declaration',2,PasProgram.ProgramSection.Declarations.Count);
2700 
2701   El:=TPasElement(PasProgram.ProgramSection.Declarations[0]);
2702   AssertEquals('Type',TPasAliasType,El.ClassType);
2703   T1:=TPasAliasType(El);
2704   AssertEquals('Type tint1','tint1',T1.Name);
2705   DestT1:=T1.DestType;
2706   AssertEquals('built-in',TPasUnresolvedSymbolRef,DestT1.ClassType);
2707   AssertEquals('built-in longint','longint',lowercase(DestT1.Name));
2708 
2709   El:=TPasElement(PasProgram.ProgramSection.Declarations[1]);
2710   AssertEquals('Type',TPasAliasType,El.ClassType);
2711   T2:=TPasAliasType(El);
2712   AssertEquals('Type tint2','tint2',T2.Name);
2713   DestT2:=T2.DestType;
2714   AssertEquals('points to alias type',TPasAliasType,DestT2.ClassType);
2715   AssertEquals('points to tint1','tint1',DestT2.Name);
2716 end;
2717 
2718 procedure TTestResolver.TestAliasTypeRefs;
2719 begin
2720   StartProgram(false);
2721   Add('type');
2722   Add('  {#a}a=longint;');
2723   Add('  {#b}{=a}b=a;');
2724   Add('var');
2725   Add('  {=a}c: a;');
2726   Add('  {=b}d: b;');
2727   Add('begin');
2728   ParseProgram;
2729 end;
2730 
2731 procedure TTestResolver.TestAliasOfVarFail;
2732 begin
2733   StartProgram(false);
2734   Add('var');
2735   Add('  a: char;');
2736   Add('type');
2737   Add('  t=a;');
2738   Add('begin');
2739   CheckParserException('Expected type, but got variable',PParser.nParserExpectedTypeButGot);
2740 end;
2741 
2742 procedure TTestResolver.TestAliasType_UnitPrefix;
2743 begin
2744   StartUnit(false);
2745   Add('interface');
2746   Add('type');
2747   Add('  {#a}a=longint;');
2748   Add('  {#b}{=a}b=afile.a;');
2749   Add('var');
2750   Add('  {=a}c: a;');
2751   Add('  {=b}d: b;');
2752   Add('implementation');
2753   ParseUnit;
2754 end;
2755 
2756 procedure TTestResolver.TestAliasType_UnitPrefix_CycleFail;
2757 begin
2758   StartUnit(false);
2759   Add('interface');
2760   Add('type');
2761   Add('  {#a}a=afile.a;');
2762   Add('implementation');
2763   CheckResolverException('identifier not found "a"',nIdentifierNotFound);
2764 end;
2765 
2766 procedure TTestResolver.TestAliasTypeNotFoundPosition;
2767 begin
2768   StartProgram(false);
2769   Add('type');
2770   Add('  integer = longint;');
2771   Add('  TColor = NotThere;');
2772   CheckResolverException('identifier not found "NotThere"',nIdentifierNotFound);
2773   // TColor element was not created yet, so LastElement must be nil
2774   AssertNull('ResolverEngine.LastElement',ResolverEngine.LastElement);
2775   with ResolverEngine.LastSourcePos do
2776     begin
2777     //writeln('TTestResolver.TestAliasTypeNotFoundPosition ',FileName,' ',Row,' ',Col);
2778     //WriteSources(FileName,Row,Column);
2779     AssertEquals('ResolverEngine.LastSourcePos.Filename','afile.pp',FileName);
2780     AssertEquals('ResolverEngine.LastSourcePos.Row',4,Row);
2781     AssertEquals('ResolverEngine.LastSourcePos.Column',20,Column);
2782     end;
2783 end;
2784 
2785 procedure TTestResolver.TestTypeAliasType;
2786 begin
2787   StartProgram(false);
2788   Add([
2789   'type',
2790   '  {#integer}integer = longint;',
2791   '  {#tcolor}TColor = type integer;',
2792   'var',
2793   '  {=integer}i: integer;',
2794   '  {=tcolor}c: TColor;',
2795   'begin',
2796   '  c:=i;',
2797   '  i:=c;',
2798   '  i:=integer(c);',
2799   '  c:=TColor(i);',
2800   '']);
2801   ParseProgram;
2802 end;
2803 
2804 procedure TTestResolver.TestVarLongint;
2805 var
2806   El: TPasElement;
2807   V1: TPasVariable;
2808   DestT1: TPasType;
2809 begin
2810   StartProgram(false);
2811   Add('var');
2812   Add('  v1:longint;');
2813   Add('begin');
2814   ParseProgram;
2815   AssertEquals('1 declaration',1,PasProgram.ProgramSection.Declarations.Count);
2816 
2817   El:=TPasElement(PasProgram.ProgramSection.Declarations[0]);
2818   AssertEquals('var',TPasVariable,El.ClassType);
2819   V1:=TPasVariable(El);
2820   AssertEquals('var v1','v1',V1.Name);
2821   DestT1:=V1.VarType;
2822   AssertEquals('built-in',TPasUnresolvedSymbolRef,DestT1.ClassType);
2823   AssertEquals('built-in longint','longint',lowercase(DestT1.Name));
2824 end;
2825 
2826 procedure TTestResolver.TestVarInteger;
2827 var
2828   El: TPasElement;
2829   V1: TPasVariable;
2830   DestT1: TPasType;
2831 begin
2832   StartProgram(true);
2833   Add('var');
2834   Add('  v1:integer;'); // defined in system.pp
2835   Add('begin');
2836   ParseProgram;
2837   AssertEquals('1 declaration',1,PasProgram.ProgramSection.Declarations.Count);
2838 
2839   El:=TPasElement(PasProgram.ProgramSection.Declarations[0]);
2840   AssertEquals('var',TPasVariable,El.ClassType);
2841   V1:=TPasVariable(El);
2842   AssertEquals('var v1','v1',V1.Name);
2843   DestT1:=V1.VarType;
2844   AssertNotNull('v1 type',DestT1);
2845   AssertEquals('built-in',TPasAliasType,DestT1.ClassType);
2846   AssertEquals('built-in integer','integer',DestT1.Name);
2847   AssertNull('v1 no expr',V1.Expr);
2848 end;
2849 
2850 procedure TTestResolver.TestConstInteger;
2851 var
2852   El: TPasElement;
2853   C1: TPasConst;
2854   DestT1: TPasType;
2855   ExprC1: TPrimitiveExpr;
2856 begin
2857   StartProgram(true);
2858   Add('const');
2859   Add('  c1: integer=3;'); // defined in system.pp
2860   Add('begin');
2861   ParseProgram;
2862   AssertEquals('1 declaration',1,PasProgram.ProgramSection.Declarations.Count);
2863 
2864   El:=TPasElement(PasProgram.ProgramSection.Declarations[0]);
2865   AssertEquals('const',TPasConst,El.ClassType);
2866   C1:=TPasConst(El);
2867   AssertEquals('const c1','c1',C1.Name);
2868   DestT1:=C1.VarType;
2869   AssertNotNull('c1 type',DestT1);
2870   AssertEquals('built-in',TPasAliasType,DestT1.ClassType);
2871   AssertEquals('built-in integer','integer',DestT1.Name);
2872   ExprC1:=TPrimitiveExpr(C1.Expr);
2873   AssertNotNull('c1 expr',ExprC1);
2874   AssertEquals('c1 expr primitive',TPrimitiveExpr,ExprC1.ClassType);
2875   AssertEquals('c1 expr value','3',ExprC1.Value);
2876 end;
2877 
2878 procedure TTestResolver.TestConstInteger2;
2879 begin
2880   StartProgram(false);
2881   Add('const');
2882   Add('  c1 = 3');
2883   Add('  c2: longint=c1;');
2884   Add('begin');
2885   CheckResolverUnexpectedHints;
2886 end;
2887 
2888 procedure TTestResolver.TestDuplicateVar;
2889 begin
2890   StartProgram(false);
2891   Add('var a: longint;');
2892   Add('var a: string;');
2893   Add('begin');
2894   CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
2895 end;
2896 
2897 procedure TTestResolver.TestVarInitConst;
2898 begin
2899   StartProgram(false);
2900   Add('const {#c}c=1;');
2901   Add('var a: longint = {@c}c;');
2902   Add('begin');
2903   ParseProgram;
2904   CheckResolverUnexpectedHints;
2905 end;
2906 
2907 procedure TTestResolver.TestVarOfVarFail;
2908 begin
2909   StartProgram(false);
2910   Add('var');
2911   Add('  a: char;');
2912   Add('  b: a;');
2913   Add('begin');
2914   CheckParserException('Expected type, but got variable',PParser.nParserExpectedTypeButGot);
2915 end;
2916 
2917 procedure TTestResolver.TestConstOfVarFail;
2918 begin
2919   StartProgram(false);
2920   Add('var');
2921   Add('  a: longint;');
2922   Add('const');
2923   Add('  b: a = 1;');
2924   Add('begin');
2925   CheckParserException('Expected type, but got variable',PParser.nParserExpectedTypeButGot);
2926 end;
2927 
2928 procedure TTestResolver.TestTypedConstWrongExprFail;
2929 begin
2930   StartProgram(false);
2931   Add('const');
2932   Add('  a: string = 1;');
2933   Add('begin');
2934   CheckResolverException('Incompatible types: got "Longint" expected "String"',
2935     nIncompatibleTypesGotExpected);
2936 end;
2937 
2938 procedure TTestResolver.TestVarWrongExprFail;
2939 begin
2940   StartProgram(false);
2941   Add('var');
2942   Add('  a: string = 1;');
2943   Add('begin');
2944   CheckResolverException('Incompatible types: got "Longint" expected "String"',
2945     nIncompatibleTypesGotExpected);
2946 end;
2947 
2948 procedure TTestResolver.TestArgWrongExprFail;
2949 begin
2950   StartProgram(false);
2951   Add('procedure ProcA(a: string = 1);');
2952   Add('begin');
2953   Add('end;');
2954   Add('begin');
2955   CheckResolverException('Incompatible types: got "Longint" expected "String"',
2956     nIncompatibleTypesGotExpected);
2957 end;
2958 
2959 procedure TTestResolver.TestTypedConstInConstExprFail;
2960 begin
2961   StartProgram(false);
2962   Add('const');
2963   Add('  a: longint = 3;');
2964   Add('  b: longint = a;');
2965   Add('begin');
2966   CheckResolverException('Constant expression expected',nConstantExpressionExpected);
2967 end;
2968 
2969 procedure TTestResolver.TestVarExternal;
2970 begin
2971   StartProgram(false);
2972   Add('var');
2973   Add('  NaN: double; external name ''Global.Nan'';');
2974   Add('begin');
2975   ParseProgram;
2976 end;
2977 
2978 procedure TTestResolver.TestVarNoSemicolonBeginFail;
2979 begin
2980   StartProgram(false);
2981   Add('procedure DoIt; begin end;');
2982   Add('var');
2983   Add('  i: longint');
2984   Add('begin');
2985   Add('  doit;');
2986   CheckParserException('Expected ";"',
2987     nParserExpectTokenError);
2988 end;
2989 
2990 procedure TTestResolver.TestConstIntOperators;
2991 begin
2992   StartProgram(false);
2993   Add([
2994   'type',
2995   '  integer = longint;',
2996   'const',
2997   '  a:byte=1+2;',
2998   '  b:shortint=1-2;',
2999   '  c:word=2*3;',
3000   '  d:smallint=5 div 2;',
3001   '  e:longword=5 mod 2;',
3002   '  f:longint=5 shl 2;',
3003   '  g:qword=5 shr 2;',
3004   '  h:boolean=5=2;',
3005   '  i:boolean=5<>2;',
3006   '  j:boolean=5<2;',
3007   '  k:boolean=5>2;',
3008   '  l:boolean=5<=2;',
3009   '  m:boolean=5>=2;',
3010   '  n:longword=5 and 2;',
3011   '  o:longword=5 or 2;',
3012   '  p:longword=5 xor 2;',
3013   '  q:longword=not (5 or not 2);',
3014   '  r=low(word)+high(int64);',
3015   '  s=low(longint)+high(integer);',
3016   '  t=succ(2)+pred(2);',
3017   '  lo1:byte=lo(word($1234));',
3018   '  hi1:byte=hi(word($1234));',
3019   '  lo2:word=lo(longword($1234CDEF));',
3020   '  hi2:word=hi(longword($1234CDEF));',
3021   '  lo3:word=lo(LongInt(-$1234CDEF));',
3022   '  hi3:word=hi(LongInt(-$1234CDEF));',
3023   '  lo4:byte=lo(byte($34));',
3024   '  hi4:byte=hi(byte($34));',
3025   '  lo5:byte=lo(shortint(-$34));',
3026   '  hi5:byte=hi(shortint(-$34));',
3027   '  lo6:longword=lo($123456789ABCDEF0);',
3028   '  hi6:longword=hi($123456789ABCDEF0);',
3029   '  lo7:longword=lo(-$123456789ABCDEF0);',
3030   '  hi7:longword=hi(-$123456789ABCDEF0);',
3031   'begin']);
3032   ParseProgram;
3033   CheckResolverUnexpectedHints;
3034 end;
3035 
3036 procedure TTestResolver.TestConstBitwiseOps;
3037 begin
3038   StartProgram(false);
3039   Add([
3040   'const',
3041   '  a=3;',
3042   '  b=not a;',
3043   '  c=not word(a);',
3044   '  d=1 shl 2;',
3045   '  e=13 shr 1;',
3046   '  f=13 and 5;',
3047   '  g=10 or 5;',
3048   '  h=5 xor 7;',
3049   'begin']);
3050   ParseProgram;
3051   CheckResolverUnexpectedHints;
3052 end;
3053 
3054 procedure TTestResolver.TestConstExternal;
3055 begin
3056   Parser.Options:=Parser.Options+[po_ExtConstWithoutExpr];
3057   StartProgram(false);
3058   Add([
3059   'const',
3060   '  PI: double; external name ''Global.PI'';',
3061   '  Tau = 2*PI;',
3062   '  TauD: double = 2*PI;',
3063   'var',
3064   '  d: double = PI;',
3065   '  e: double = PI+Tau;',
3066   'begin',
3067   '  d:=pi+tau;']);
3068   ParseProgram;
3069   // ToDo: fail on const Tau = 2*Var
3070 end;
3071 
3072 procedure TTestResolver.TestIntegerTypeCast;
3073 begin
3074   StartProgram(false);
3075   Add([
3076   'const',
3077   '  a=longint(-11);',
3078   '  b=not shortint(-12);',
3079   '  c=word(-2);',
3080   '  d=word(longword(-3));',
3081   'begin']);
3082   ParseProgram;
3083   CheckResolverUnexpectedHints;
3084 end;
3085 
3086 procedure TTestResolver.TestConstFloatOperators;
3087 begin
3088   StartProgram(false);
3089   Add([
3090   'const',
3091   '  a=4/2 + 6.1/3 + 8.1/4.1 + 10/5.1;',
3092   '  b=(1.1+1) + (2.1+3.1) + (4+5.1);',
3093   '  c=(1.1-1) + (2.1-3.1) + (4-5.1);',
3094   '  d=4*2 + 6.1*3 + 8.1*4.1 + 10*5.1;',
3095   '  e=a=b;',
3096   '  f=a<>b;',
3097   '  g=a>b;',
3098   '  h=a>=b;',
3099   '  i=a<b;',
3100   '  j=a<=b;',
3101   '  k=(1.1<1) or (2.1<3.1) or (4<5.1);',
3102   '  l=(1.1=1) or (2.1=3.1) or (4=5.1);',
3103   'begin']);
3104   ParseProgram;
3105   CheckResolverUnexpectedHints;
3106 end;
3107 
3108 procedure TTestResolver.TestFloatTypeCast;
3109 begin
3110   StartProgram(false);
3111   Add([
3112   'const',
3113   '  a=-123456890123456789012345;',
3114   '  b: double=-123456890123456789012345;',
3115   '  c=single(double(-123456890123456789012345));',
3116   '  d=single(-1);',
3117   '  e=single(word(-1));',
3118   'begin']);
3119   ParseProgram;
3120   CheckResolverUnexpectedHints;
3121 end;
3122 
3123 procedure TTestResolver.TestCurrency;
3124 begin
3125   StartProgram(false);
3126   Add([
3127   'const',
3128   '  a: currency = -922337203685477.5808;',
3129   '  b: currency = 922337203685477.5807;',
3130   '  c=double(currency(-123456890123456));',
3131   '  d=currency(-1);',
3132   '  e=currency(word(-1));',
3133   'var',
3134   '  i: longint = 1;',
3135   '  i64: int64;',
3136   '  f: double;',
3137   'begin',
3138   '  a:=i;',
3139   '  a:=i+a;',
3140   '  a:=a+i;',
3141   '  a:=-a+b;',
3142   '  a:=a*b;',
3143   '  a:=a/b;',
3144   '  a:=a/1.23;',
3145   '  a:=1.2345;',
3146   '  a:=a-i;',
3147   '  a:=i-a;',
3148   '  a:=a*i;',
3149   '  a:=i*a;',
3150   '  a:=a/i;',
3151   '  a:=i/a;',
3152   '  a:=i64;',
3153   '  a:=currency(i64);',
3154   //'  i64:=a;', not allowed
3155   '  i64:=int64(a);', // truncates a
3156   '  a:=f;',
3157   '  a:=currency(f);',
3158   '  f:=a;',
3159   '  f:=double(a);',
3160   '']);
3161   ParseProgram;
3162   CheckResolverUnexpectedHints;
3163 end;
3164 
3165 procedure TTestResolver.TestWritableConst;
3166 begin
3167   StartProgram(false);
3168   Add([
3169   '{$writeableconst off}',
3170   'const i: longint = 3;',
3171   'begin',
3172   '']);
3173   ParseProgram;
3174 end;
3175 
3176 procedure TTestResolver.TestWritableConst_AssignFail;
3177 begin
3178   StartProgram(false);
3179   Add([
3180   '{$writeableconst off}',
3181   'const i: longint = 3;',
3182   'begin',
3183   '  i:=4;',
3184   '']);
3185   CheckResolverException(sCantAssignValuesToConstVariable,nCantAssignValuesToConstVariable);
3186 end;
3187 
3188 procedure TTestResolver.TestWritableConst_PassVarFail;
3189 begin
3190   StartProgram(false);
3191   Add([
3192   '{$writeableconst off}',
3193   'const i: longint = 3;',
3194   'procedure DoIt(var j: longint); external;',
3195   'begin',
3196   '  DoIt(i);',
3197   '']);
3198   CheckResolverException(sCantAssignValuesToConstVariable,nCantAssignValuesToConstVariable);
3199 end;
3200 
3201 procedure TTestResolver.TestBoolTypeCast;
3202 begin
3203   StartProgram(false);
3204   Add('var');
3205   Add('  a: boolean = boolean(0);');
3206   Add('  b: boolean = boolean(1);');
3207   Add('begin');
3208   ParseProgram;
3209   CheckResolverUnexpectedHints;
3210 end;
3211 
3212 procedure TTestResolver.TestConstBoolOperators;
3213 begin
3214   StartProgram(false);
3215   Add([
3216   'const',
3217   '  a=true and false;',
3218   '  b=true or false;',
3219   '  c=true xor false;',
3220   '  d=not b;',
3221   '  e=a=b;',
3222   '  f=a<>b;',
3223   '  g=low(boolean) or high(boolean);',
3224   '  h=succ(false) or pred(true);',
3225   '  i=ord(false)+ord(true);',
3226   'begin']);
3227   ParseProgram;
3228   CheckResolverUnexpectedHints;
3229 end;
3230 
3231 procedure TTestResolver.TestBoolSet_Const;
3232 begin
3233   StartProgram(false);
3234   Add([
3235   'const',
3236   '  s1 = [true];',
3237   '  s2 = [false,true];',
3238   '  s3 = [false..true];',
3239   '  s7 = [true]*s2;',
3240   '  s8 = s2-s1;',
3241   '  s9 = s1+s2;',
3242   '  s10 = s1><s2;',
3243   '  s11 = s2=s3;',
3244   '  s12 = s2<>s3;',
3245   '  s13 = s2<=s3;',
3246   '  s14 = s2>=s3;',
3247   '  s15 = true in s2;',
3248   'begin']);
3249   ParseProgram;
3250   CheckResolverUnexpectedHints;
3251 end;
3252 
3253 procedure TTestResolver.TestBool_ForIn;
3254 begin
3255   StartProgram(false);
3256   Add([
3257   'type',
3258   //'  TBoolRg = false..true;',
3259   '  TSetOfBool = set of boolean;',
3260   //'  TSetOfBoolRg = set of TBoolRg;',
3261   'var',
3262   '  b: boolean;',
3263   //'  br: TBoolRg;',
3264   'begin',
3265   '  for b in boolean do;',
3266   //'  for b in TBoolRg do;',
3267   '  for b in TSetOfBool do;',
3268   //'  for b in TSetOfBoolRg do;',
3269   //'  for br in TBoolRg do;',
3270   //'  for br in TSetOfBoolRg do;',
3271   '']);
3272   ParseProgram;
3273 end;
3274 
3275 procedure TTestResolver.TestBool_Assert;
3276 begin
3277   StartProgram(false);
3278   Add([
3279   'var',
3280   '  b : boolean;',
3281   '  s: string;',
3282   'begin',
3283   '  Assert(true);',
3284   '  Assert(b);',
3285   '  Assert(b,''error'');',
3286   '  Assert(false,''error''+s);',
3287   '  Assert(not b);',
3288   '']);
3289   ParseProgram;
3290 end;
3291 
3292 procedure TTestResolver.TestBool_AssertSysutils;
3293 begin
3294   AddModuleWithIntfImplSrc('SysUtils.pas',
3295     LinesToStr([
3296     'type',
3297     '  TObject = class',
3298     '    constructor Create;',
3299     '  end;',
3300     '  EAssertionFailed = class',
3301     '    constructor Create(s: string);',
3302     '  end;',
3303     '']),
3304     LinesToStr([
3305     'constructor TObject.Create;',
3306     'begin end;',
3307     'constructor EAssertionFailed.Create(s: string);',
3308     'begin end;',
3309     '']) );
3310 
3311   StartProgram(true);
3312   Add([
3313   'uses sysutils;',
3314   'procedure DoIt;',
3315   'var',
3316   '  b: boolean;',
3317   '  s: string;',
3318   'begin',
3319   '  {$Assertions on}',
3320   '  Assert(b);',
3321   '  Assert(b,s);',
3322   'end;',
3323   'begin',
3324   '  DoIt;',
3325   '']);
3326   ParseProgram;
3327 end;
3328 
3329 procedure TTestResolver.TestIntegerRange;
3330 begin
3331   StartProgram(false);
3332   Add([
3333   'const',
3334   '  MinInt = -1;',
3335   '  MaxInt = +1;',
3336   'type',
3337   '  {#TMyInt}TMyInt = MinInt..MaxInt;',
3338   '  TInt2 = 1..3;',
3339   'var',
3340   '  i: TMyInt;',
3341   '  i2: TInt2;',
3342   'begin',
3343   '  i:=i2;',
3344   '  if i=i2 then ;']);
3345   ParseProgram;
3346 end;
3347 
3348 procedure TTestResolver.TestIntegerRangeHighLowerLowFail;
3349 begin
3350   StartProgram(false);
3351   Add('const');
3352   Add('  MinInt = -1;');
3353   Add('  MaxInt = +1;');
3354   Add('type');
3355   Add('  {#TMyInt}TMyInt = MaxInt..MinInt;');
3356   Add('begin');
3357   CheckResolverException(sHighRangeLimitLTLowRangeLimit,
3358     nHighRangeLimitLTLowRangeLimit);
3359 end;
3360 
3361 procedure TTestResolver.TestIntegerRangeLowHigh;
3362 begin
3363   StartProgram(false);
3364   Add([
3365   'const',
3366   '  MinInt = -1;',
3367   '  MaxInt = +10;',
3368   'type',
3369   '  {#TMyInt}TMyInt = MinInt..MaxInt;',
3370   'const',
3371   '  a = low(TMyInt)+High(TMyInt);',
3372   'var',
3373   '  i: TMyInt;',
3374   'begin',
3375   '  i:=low(i)+high(i);']);
3376   ParseProgram;
3377   CheckResolverUnexpectedHints;
3378 end;
3379 
3380 procedure TTestResolver.TestAssignIntRangeWarning;
3381 begin
3382   StartProgram(false);
3383   Add([
3384   'type TMyInt = 1..2;',
3385   'var i: TMyInt;',
3386   'begin',
3387   '  i:=3;']);
3388   ParseProgram;
3389   CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
3390     'range check error while evaluating constants (3 is not between 1 and 2)');
3391   CheckResolverUnexpectedHints;
3392 end;
3393 
3394 procedure TTestResolver.TestByteRangeWarning;
3395 begin
3396   StartProgram(false);
3397   Add([
3398   'var b:byte=300;',
3399   'begin']);
3400   ParseProgram;
3401   CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
3402     'range check error while evaluating constants (300 is not between 0 and 255)');
3403   CheckResolverUnexpectedHints;
3404 end;
3405 
3406 procedure TTestResolver.TestByteRangeWarningOff;
3407 begin
3408   StartProgram(false);
3409   Add([
3410   '{$warnings off}',
3411   'var b:byte=300;',
3412   'begin']);
3413   ParseProgram;
3414   CheckResolverUnexpectedHints;
3415 end;
3416 
3417 procedure TTestResolver.TestCustomIntRangeWarning;
3418 begin
3419   StartProgram(false);
3420   Add([
3421   'const i:1..2 = 3;',
3422   'begin']);
3423   ParseProgram;
3424   CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
3425     'range check error while evaluating constants (3 is not between 1 and 2)');
3426   CheckResolverUnexpectedHints;
3427 end;
3428 
3429 procedure TTestResolver.TestIntSet_Const;
3430 begin
3431   StartProgram(false);
3432   Add([
3433   'const',
3434   '  s1 = [1];',
3435   '  s2 = [1,2];',
3436   '  s3 = [1..3];',
3437   '  s4 = [1..2,4..5,6];',
3438   '  s5 = [low(shortint)..high(shortint)];',
3439   '  s6 = [succ(low(shortint))..pred(high(shortint))];',
3440   '  s7 = [1..3]*[2..4];',
3441   '  s8 = [1..5]-[2,5];',
3442   '  s9 = [1,3..4]+[2,5];',
3443   '  s10 = [1..3]><[2..5];',
3444   '  s11 = s2=s3;',
3445   '  s12 = s2<>s3;',
3446   '  s13 = s2<=s3;',
3447   '  s14 = s2>=s3;',
3448   '  s15 = 1 in s2;',
3449   'var',
3450   '  w: word;',
3451   'begin',
3452   '  if w in [1..12] then ;',
3453   '']);
3454   ParseProgram;
3455   CheckResolverUnexpectedHints;
3456 end;
3457 
3458 procedure TTestResolver.TestIntSet_ConstDuplicateElement;
3459 begin
3460   StartProgram(false);
3461   Add([
3462   'const',
3463   '  s1 = [1,1..2];',
3464   'begin']);
3465   CheckResolverException(sRangeCheckInSetConstructor,nRangeCheckInSetConstructor);
3466 end;
3467 
3468 procedure TTestResolver.TestInt_ForIn;
3469 begin
3470   StartProgram(false);
3471   Add([
3472   'type',
3473   '  TIntRg = 2..4;',
3474   '  TSetOfInt = set of byte;',
3475   '  TSetOfIntRg = set of TIntRg;',
3476   'var',
3477   '  i: longint;',
3478   '  ir: TIntRg;',
3479   'begin',
3480   '  for i in longint do;',
3481   '  for i in TIntRg do;',
3482   '  for i in TSetOfInt do;',
3483   '  for i in TSetOfIntRg do;',
3484   '  for ir in TIntRg do;',
3485   '  for ir in TSetOfIntRg do;',
3486   '']);
3487   ParseProgram;
3488 end;
3489 
3490 procedure TTestResolver.TestChar_BuiltInProcs;
3491 begin
3492   StartProgram(false);
3493   Add([
3494   'var',
3495   '  c: char;',
3496   '  i: longint;',
3497   'begin',
3498   '  i:=ord(c);',
3499   '  c:=chr(i);',
3500   '  c:=pred(c);',
3501   '  c:=succ(c);',
3502   '  c:=low(c);',
3503   '  c:=high(c);',
3504   '']);
3505   ParseProgram;
3506 end;
3507 
3508 procedure TTestResolver.TestString_BuiltInProcs;
3509 begin
3510   StartProgram(false);
3511   Add([
3512   'var',
3513   '  s: string;',
3514   'begin',
3515   '  SetLength({#a_var}s,3);',
3516   '  SetLength({#b_var}s,length({#c_read}s));',
3517   '  s:=concat(''a'',s);',
3518   '']);
3519   ParseProgram;
3520   CheckAccessMarkers;
3521 end;
3522 
3523 procedure TTestResolver.TestString_Element;
3524 begin
3525   StartProgram(false);
3526   Add([
3527   'var',
3528   '  s: string;',
3529   '  c: char;',
3530   'begin',
3531   '  if s[1]=s then ;',
3532   '  if s=s[2] then ;',
3533   '  if s[3+4]=c then ;',
3534   '  if c=s[5] then ;',
3535   '  c:=s[6];',
3536   '  s[7]:=c;',
3537   '  s[8]:=''a'';',
3538   '  s[9+1]:=''b'';',
3539   '  s[10]:='''''''';',
3540   '  s[11]:=^g;',
3541   '  s[12]:=^H;']);
3542   ParseProgram;
3543 end;
3544 
3545 procedure TTestResolver.TestStringElement_MissingArgFail;
3546 begin
3547   StartProgram(false);
3548   Add('var s: string;');
3549   Add('begin');
3550   Add('  if s[]=s then ;');
3551   CheckResolverException('Missing parameter character index',nMissingParameterX);
3552 end;
3553 
3554 procedure TTestResolver.TestStringElement_IndexNonIntFail;
3555 begin
3556   StartProgram(false);
3557   Add('var s: string;');
3558   Add('begin');
3559   Add('  if s[true]=s then ;');
3560   CheckResolverException('Incompatible types: got "Boolean" expected "integer"',
3561     nIncompatibleTypesGotExpected);
3562 end;
3563 
3564 procedure TTestResolver.TestStringElement_AsVarArgFail;
3565 begin
3566   StartProgram(false);
3567   Add('procedure DoIt(var c: char);');
3568   Add('begin');
3569   Add('end;');
3570   Add('var s: string;');
3571   Add('begin');
3572   Add('  DoIt(s[1]);');
3573   CheckResolverException('Variable identifier expected',
3574     nVariableIdentifierExpected);
3575 end;
3576 
3577 procedure TTestResolver.TestString_DoubleQuotesFail;
3578 begin
3579   StartProgram(false);
3580   Add('var s: string;');
3581   Add('begin');
3582   Add('  s:="abc" + "def";');
3583   CheckParserException('Invalid character ''"''',PScanner.nErrInvalidCharacter);
3584 end;
3585 
3586 procedure TTestResolver.TestString_ShortstringType;
3587 begin
3588   StartProgram(false);
3589   Add([
3590   'type t = string[12];',
3591   'var',
3592   '  s: t;',
3593   'begin',
3594   '  s:=''abc'';',
3595   '']);
3596   ParseProgram;
3597 end;
3598 
3599 procedure TTestResolver.TestConstStringOperators;
3600 begin
3601   StartProgram(false);
3602   Add([
3603   'const',
3604   '  a=''o''+''x''+''''+''ab'';',
3605   '  b=#65#66;',
3606   '  c=a=b;',
3607   '  d=a<>b;',
3608   '  e=a<b;',
3609   '  f=a<=b;',
3610   '  g=a>b;',
3611   '  h=a>=b;',
3612   '  i=a[1];',
3613   '  j=length(a);',
3614   '  k=chr(97);',
3615   '  l=ord(a[1]);',
3616   '  m=low(char)+high(char);',
3617   '  n = string(''A'');',
3618   '  o = UnicodeString(''A'');',
3619   'begin']);
3620   ParseProgram;
3621   CheckResolverUnexpectedHints;
3622 end;
3623 
3624 procedure TTestResolver.TestConstUnicodeStringOperators;
3625 begin
3626   ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
3627   StartProgram(false);
3628   Add([
3629   'const',
3630   '  a=''大''+''学'';',
3631   '  b=#22823+#23398;',
3632   '  c=a=b;',
3633   '  d=a<>b;',
3634   '  e=a<b;',
3635   '  f=a<=b;',
3636   '  g=a>b;',
3637   '  h=a>=b;',
3638   '  i=b[1];',
3639   '  j=length(b);',
3640   '  k=chr(22823);',
3641   '  l=ord(b[1]);',
3642   '  m=low(widechar)+high(widechar);',
3643   '  n=#65#22823;',
3644   '  ascii=#65;',
3645   '  o=ascii+b;',
3646   'begin']);
3647   ParseProgram;
3648   CheckResolverUnexpectedHints;
3649 end;
3650 
3651 procedure TTestResolver.TestCharSet_Const;
3652 begin
3653   StartProgram(false);
3654   Add([
3655   'const',
3656   '  s1 = [''a''];',
3657   '  s2 = [''a'',''b''];',
3658   '  s3 = [''a''..''c''];',
3659   '  s4 = [''a''..''b'',''d''..''e'',''f''];',
3660   '  s5 = [low(Char)..high(Char)];',
3661   '  s6 = [succ(low(Char))..pred(high(Char))];',
3662   '  s7 = [''a''..''c'']*[''b''..''d''];',
3663   '  s8 = [''a''..''e'']-[''b'',''e''];',
3664   '  s9 = [''a'',''c''..''d'']+[''b'',''e''];',
3665   '  s10 = [''a''..''c'']><[''b''..''e''];',
3666   '  s11 = [''a'',''b'']=[''a''..''b''];',
3667   '  s12 = [''a'',''b'']<>[''a''..''b''];',
3668   '  s13 = [''a'',''b'']<=[''a''..''b''];',
3669   '  s14 = [''a'',''b'']>=[''a''..''b''];',
3670   '  s15 = ''a'' in [''a'',''b''];',
3671   '  s16 = [#0..#127,#22823..#23398];',
3672   '  s17 = #22823 in s16;',
3673   'var c: char;',
3674   'begin',
3675   '  if c in s3 then ;']);
3676   ParseProgram;
3677   CheckResolverUnexpectedHints;
3678 end;
3679 
3680 procedure TTestResolver.TestCharSet_Custom;
3681 begin
3682   StartProgram(false);
3683   Add([
3684   'type',
3685   '  TCharRg = ''a''..''z'';',
3686   '  TSetOfCharRg = set of TCharRg;',
3687   '  TCharRg2 = ''m''..''p'';',
3688   'const',
3689   '  crg: TCharRg = ''b'';',
3690   'var',
3691   '  c: char;',
3692   '  crg2: TCharRg2;',
3693   '  s: TSetOfCharRg;',
3694   'begin',
3695   '  c:=crg;',
3696   '  crg:=c;',
3697   '  crg2:=crg;',
3698   '  if c=crg then ;',
3699   '  if crg=c then ;',
3700   '  if crg=crg2 then ;',
3701   '  if c in s then ;',
3702   '  if crg2 in s then ;',
3703   '']);
3704   ParseProgram;
3705   CheckResolverUnexpectedHints;
3706 end;
3707 
3708 procedure TTestResolver.TestCharAssignStringFail;
3709 begin
3710   StartProgram(false);
3711   Add([
3712   'var',
3713   '  c: char;',
3714   '  s: string;',
3715   'begin',
3716   '  c:=s;']);
3717   CheckResolverException('Incompatible types: got "String" expected "Char"',
3718     nIncompatibleTypesGotExpected);
3719 end;
3720 
3721 procedure TTestResolver.TestChar_ForIn;
3722 begin
3723   StartProgram(false);
3724   Add([
3725   'type',
3726   '  TCharRg = ''a''..''z'';',
3727   '  TSetOfChar = set of char;',
3728   '  TSetOfCharRg = set of TCharRg;',
3729   'const Foo = ''foo'';',
3730   'var',
3731   '  c: char;',
3732   '  cr: TCharRg;',
3733   '  s: string;',
3734   '  a: array of char;',
3735   '  b: array[1..3] of char;',
3736   '  soc: TSetOfChar;',
3737   '  socr: TSetOfCharRg;',
3738   'begin',
3739   '  for c in foo do;',
3740   '  for c in s do;',
3741   '  for c in a do;',
3742   '  for c in b do;',
3743   '  for c in char do;',
3744   '  for c in TCharRg do;',
3745   '  for c in TSetOfChar do;',
3746   '  for c in TSetOfCharRg do;',
3747   '  for c in soc do;',
3748   '  for c in socr do;',
3749   '  for c in [''A''..''C''] do ;',
3750   '  for cr in TCharRg do;',
3751   '  for cr in TSetOfCharRg do;',
3752   '  for cr in socr do;',
3753   //'  for cr in [''b''..''d''] do ;',
3754   '']);
3755   ParseProgram;
3756 end;
3757 
3758 procedure TTestResolver.TestEnums;
3759 begin
3760   StartProgram(false);
3761   Add([
3762   'type',
3763   '  {#TFlag}TFlag = ({#Red}Red, {#Green}Green, {#Blue}Blue);',
3764   '  {#TAlias}TAlias = TFlag;',
3765   'var',
3766   '  {#f}{=TFlag}f: TFlag;',
3767   '  {#v}{=TFlag}v: TFlag = Green;',
3768   '  {#i}i: longint;',
3769   'begin',
3770   '  {@f}f:={@Red}Red;',
3771   '  {@f}f:={@v}v;',
3772   '  if {@f}f={@Red}Red then ;',
3773   '  if {@f}f={@v}v then ;',
3774   '  if {@f}f>{@v}v then ;',
3775   '  if {@f}f<{@v}v then ;',
3776   '  if {@f}f>={@v}v then ;',
3777   '  if {@f}f<={@v}v then ;',
3778   '  if {@f}f<>{@v}v then ;',
3779   '  if ord({@f}f)<>ord({@Red}Red) then ;',
3780   '  {@f}f:={@TFlag}TFlag.{@Red}Red;',
3781   '  {@f}f:={@TFlag}TFlag({@i}i);',
3782   '  {@i}i:=longint({@f}f);',
3783   '  {@f}f:={@TAlias}TAlias.{@Green}Green;',
3784   '']);
3785   ParseProgram;
3786 end;
3787 
3788 procedure TTestResolver.TestEnumRangeFail;
3789 begin
3790   StartProgram(false);
3791   Add([
3792   'type TFlag = (a,b,c);',
3793   'const all = a..c;',
3794   'begin']);
3795   CheckParserException('Const ranges are not allowed',nParserNoConstRangeAllowed);
3796 end;
3797 
3798 procedure TTestResolver.TestEnumDotValueFail;
3799 begin
3800   StartProgram(false);
3801   Add([
3802   'type TFlag = (a,b,c);',
3803   'var f: TFlag;',
3804   'begin',
3805   '  f:=f.a;']);
3806   CheckResolverException('illegal qualifier "." after "f:TFlag"',nIllegalQualifierAfter);
3807 end;
3808 
3809 procedure TTestResolver.TestSets;
3810 begin
3811   StartProgram(false);
3812   Add('type');
3813   Add('  {#TFlag}TFlag = ({#Red}Red, {#Green}Green, {#Blue}Blue, {#Gray}Gray, {#Black}Black, {#White}White);');
3814   Add('  {#TFlags}TFlags = set of TFlag;');
3815   Add('  {#TChars}TChars = set of Char;');
3816   Add('  {#TMyInt}TMyInt = 0..17;');
3817   Add('  {#TMyInts}TMyInts = set of TMyInt;');
3818   Add('  {#TMyBools}TMyBools = set of boolean;');
3819   Add('const');
3820   Add('  {#Colors}Colors = [{@Red}Red..{@Blue}Blue];');
3821   Add('  {#ExtColors}ExtColors = {@Colors}Colors+[{@White}White,{@Black}Black];');
3822   Add('var');
3823   Add('  {#f}{=TFlag}f: TFlag;');
3824   Add('  {#s}{=TFlags}s: TFlags;');
3825   Add('  {#t}{=TFlags}t: TFlags = [Green,Gray];');
3826   Add('  {#Chars}{=TChars}Chars: TChars;');
3827   Add('  {#MyInts}{=TMyInts}MyInts: TMyInts;');
3828   Add('  {#MyBools}{=TMyBools}MyBools: TMyBools;');
3829   Add('begin');
3830   Add('  {@s}s:=[];');
3831   Add('  {@s}s:={@t}t;');
3832   Add('  {@s}s:=[{@Red}Red];');
3833   Add('  {@s}s:=[{@Red}Red,{@Blue}Blue];');
3834   Add('  {@s}s:=[{@Gray}Gray..{@White}White];');
3835   Add('  {@MyInts}MyInts:=[1];');
3836   Add('  {@MyInts}MyInts:=[1,2];');
3837   Add('  {@MyInts}MyInts:=[1..2];');
3838   Add('  {@MyInts}MyInts:=[1..2,3];');
3839   Add('  {@MyInts}MyInts:=[1..2,3..4];');
3840   Add('  {@MyInts}MyInts:=[1,2..3];');
3841   Add('  {@MyBools}MyBools:=[false];');
3842   Add('  {@MyBools}MyBools:=[false,true];');
3843   Add('  {@MyBools}MyBools:=[false..true];');
3844   ParseProgram;
3845 end;
3846 
3847 procedure TTestResolver.TestSetOperators;
3848 begin
3849   StartProgram(false);
3850   Add('type');
3851   Add('  {#TFlag}TFlag = ({#Red}Red, {#Green}Green, {#Blue}Blue, {#Gray}Gray, {#Black}Black, {#White}White);');
3852   Add('  {#TFlags}TFlags = set of TFlag;');
3853   Add('  {#TChars}TChars = set of Char;');
3854   Add('  {#TMyInt}TMyInt = 0..17;');
3855   Add('  {#TMyInts}TMyInts = set of TMyInt;');
3856   Add('  {#TMyBools}TMyBools = set of boolean;');
3857   Add('const');
3858   Add('  {#Colors}Colors = [{@Red}Red..{@Blue}Blue];');
3859   Add('  {#ExtColors}ExtColors = {@Colors}Colors+[{@White}White,{@Black}Black];');
3860   Add('var');
3861   Add('  {#f}{=TFlag}f: TFlag;');
3862   Add('  {#s}{=TFlags}s: TFlags;');
3863   Add('  {#t}{=TFlags}t: TFlags = [Green,Gray];');
3864   Add('  {#Chars}{=TChars}Chars: TChars;');
3865   Add('  {#MyInts}{=TMyInts}MyInts: TMyInts;');
3866   Add('  {#MyBools}{=TMyBools}MyBools: TMyBools;');
3867   Add('begin');
3868   Add('  {@s}s:=[];');
3869   Add('  {@s}s:=[{@Red}Red]+[{@Blue}Blue,{@Gray}Gray];');
3870   Add('  {@s}s:=[{@Blue}Blue,{@Gray}Gray]-[{@Blue}Blue];');
3871   Add('  {@s}s:={@t}t+[];');
3872   Add('  {@s}s:=[{@Red}Red]+{@s}s;');
3873   Add('  {@s}s:={@s}s+[{@Red}Red];');
3874   Add('  {@s}s:=[{@Red}Red]-{@s}s;');
3875   Add('  {@s}s:={@s}s-[{@Red}Red];');
3876   Add('  Include({@s}s,{@Blue}Blue);');
3877   Add('  Include({@s}s,{@f}f);');
3878   Add('  Exclude({@s}s,{@Blue}Blue);');
3879   Add('  Exclude({@s}s,{@f}f);');
3880   Add('  {@s}s:={@s}s+[{@f}f];');
3881   Add('  if {@Green}Green in {@s}s then ;');
3882   Add('  if {@Blue}Blue in {@Colors}Colors then ;');
3883   Add('  if {@f}f in {@ExtColors}ExtColors then ;');
3884   Add('  {@s}s:={@s}s * {@Colors}Colors;');
3885   Add('  {@s}s:={@Colors}Colors * {@s}s;');
3886   Add('  {@s}s:={@ExtColors}ExtColors * {@Colors}Colors;');
3887   Add('  {@s}s:=Colors >< {@ExtColors}ExtColors;');
3888   Add('  {@s}s:={@s}s >< {@ExtColors}ExtColors;');
3889   Add('  {@s}s:={@ExtColors}ExtColors >< s;');
3890   Add('  {@s}s:={@s}s >< {@s}s;');
3891   Add('  if ''p'' in [''a''..''z''] then ; ');
3892   Add('  if ''p'' in [''a''..''z'',''A''..''Z'',''0''..''9'',''_''] then ; ');
3893   Add('  if ''p'' in {@Chars}Chars then ; ');
3894   Add('  if 7 in {@MyInts}MyInts then ; ');
3895   Add('  if 7 in [1+2,(3*4)+5,(-2+6)..(8-3)] then ; ');
3896   Add('  if [red,blue]*s=[red,blue] then ;');
3897   Add('  if {@s}s = t then;');
3898   Add('  if {@s}s = {@Colors}Colors then;');
3899   Add('  if {@Colors}Colors = s then;');
3900   Add('  if {@s}s <> t then;');
3901   Add('  if {@s}s <> {@Colors}Colors then;');
3902   Add('  if {@Colors}Colors <> s then;');
3903   Add('  if {@s}s <= t then;');
3904   Add('  if {@s}s <= {@Colors}Colors then;');
3905   Add('  if {@Colors}Colors <= s then;');
3906   Add('  if {@s}s >= t then;');
3907   Add('  if {@s}s >= {@Colors}Colors then;');
3908   Add('  if {@Colors}Colors >= {@s}s then;');
3909   ParseProgram;
3910 end;
3911 
3912 procedure TTestResolver.TestEnumParams;
3913 begin
3914   StartProgram(false);
3915   Add('type');
3916   Add('  TFlag = (red, green, blue);');
3917   Add('function {#A1}FuncA: TFlag;');
3918   Add('begin');
3919   Add('  Result:=red;');
3920   Add('end;');
3921   Add('function {#A2}FuncA(f: TFlag): TFlag;');
3922   Add('begin');
3923   Add('  Result:=f;');
3924   Add('end;');
3925   Add('var');
3926   Add('  f: TFlag;');
3927   Add('begin');
3928   Add('  f:={@A1}FuncA;');
3929   Add('  f:={@A1}FuncA();');
3930   Add('  f:={@A2}FuncA(f);');
3931   ParseProgram;
3932 end;
3933 
3934 procedure TTestResolver.TestSetParams;
3935 begin
3936   StartProgram(false);
3937   Add('type');
3938   Add('  TFlag = (red, green, blue);');
3939   Add('  TFlags = set of TFlag;');
3940   Add('function {#A1}FuncA: TFlags;');
3941   Add('begin');
3942   Add('  Result:=[red];');
3943   Add('  Include(Result,green);');
3944   Add('  Exclude(Result,blue);');
3945   Add('end;');
3946   Add('function {#A2}FuncA(f: TFlags): TFlags;');
3947   Add('begin');
3948   Add('  Include(f,green);');
3949   Add('  Result:=f;');
3950   Add('end;');
3951   Add('var');
3952   Add('  f: TFlags;');
3953   Add('begin');
3954   Add('  f:={@A1}FuncA;');
3955   Add('  f:={@A1}FuncA();');
3956   Add('  f:={@A2}FuncA(f);');
3957   Add('  f:={@A2}FuncA([green]);');
3958   ParseProgram;
3959 end;
3960 
3961 procedure TTestResolver.TestSetFunctions;
3962 begin
3963   StartProgram(false);
3964   Add('type');
3965   Add('  TFlag = (red, green, blue);');
3966   Add('  TFlags = set of TFlag;');
3967   Add('var');
3968   Add('  e: TFlag;');
3969   Add('  s: TFlags;');
3970   Add('begin');
3971   Add('  e:=Low(TFlags);');
3972   Add('  e:=Low(s);');
3973   Add('  e:=High(TFlags);');
3974   Add('  e:=High(s);');
3975   ParseProgram;
3976 end;
3977 
3978 procedure TTestResolver.TestEnumHighLow;
3979 begin
3980   StartProgram(false);
3981   Add('type');
3982   Add('  TFlag = (red, green, blue);');
3983   Add('var f: TFlag;');
3984   Add('begin');
3985   Add('  for f:=low(TFlag) to high(TFlag) do ;');
3986   ParseProgram;
3987 end;
3988 
3989 procedure TTestResolver.TestEnumOrd;
3990 begin
3991   StartProgram(false);
3992   Add('type');
3993   Add('  TFlag = (red, green, blue);');
3994   Add('var');
3995   Add('  f: TFlag;');
3996   Add('  i: longint;');
3997   Add('begin');
3998   Add('  i:=ord(f);');
3999   Add('  i:=ord(green);');
4000   Add('  if i=ord(f) then ;');
4001   Add('  if ord(f)=i then ;');
4002   ParseProgram;
4003 end;
4004 
4005 procedure TTestResolver.TestEnumPredSucc;
4006 begin
4007   StartProgram(false);
4008   Add('type');
4009   Add('  TFlag = (red, green, blue);');
4010   Add('var');
4011   Add('  f: TFlag;');
4012   Add('begin');
4013   Add('  f:=Pred(f);');
4014   Add('  if Pred(green)=Pred(TFlag.Blue) then;');
4015   Add('  f:=Succ(f);');
4016   Add('  if Succ(green)=Succ(TFlag.Blue) then;');
4017   ParseProgram;
4018 end;
4019 
4020 procedure TTestResolver.TestEnum_EqualNilFail;
4021 begin
4022   StartProgram(false);
4023   Add('type');
4024   Add('  TFlag = (red, green);');
4025   Add('var');
4026   Add('  f: TFlag;');
4027   Add('begin');
4028   Add('  if f=nil then ;');
4029   CheckResolverException('Incompatible types: got "nil" expected "TFlag"',
4030     nIncompatibleTypesGotExpected);
4031 end;
4032 
4033 procedure TTestResolver.TestEnum_CastIntegerToEnum;
4034 begin
4035   StartProgram(false);
4036   Add('type');
4037   Add('  TFlag = (red, green, blue);');
4038   Add('var');
4039   Add('  f: TFlag;');
4040   Add('  i: longint;');
4041   Add('begin');
4042   Add('  f:=TFlag(1);');
4043   Add('  f:=TFlag({#a_read}i);');
4044   Add('  if TFlag({#b_read}i)=TFlag(1) then;');
4045   ParseProgram;
4046   CheckAccessMarkers;
4047 end;
4048 
4049 procedure TTestResolver.TestEnum_Str;
4050 begin
4051   StartProgram(false);
4052   Add([
4053   'type',
4054   '  TFlag = (red, green, blue);',
4055   'var',
4056   '  f: TFlag;',
4057   '  i: longint;',
4058   '  aString: string;',
4059   'begin',
4060   '  aString:=str(f);',
4061   '  aString:=str(f:3);',
4062   '  str(f,aString);',
4063   '  writestr(astring,f,i);',
4064   '  val(aString,f,i);']);
4065   ParseProgram;
4066 end;
4067 
4068 procedure TTestResolver.TestConstEnumOperators;
4069 begin
4070   StartProgram(false);
4071   Add([
4072   'type',
4073   '  TEnum = (red,blue,green);',
4074   'const',
4075   '  a=ord(red);',
4076   '  b=succ(low(TEnum));',
4077   '  c=pred(high(TEnum));',
4078   '  d=TEnum(0);',
4079   '  e=TEnum(2);',
4080   'begin']);
4081   ParseProgram;
4082   CheckResolverUnexpectedHints;
4083 end;
4084 
4085 procedure TTestResolver.TestEnumSetConstRange;
4086 begin
4087   StartProgram(false);
4088   Add([
4089   'type',
4090   '  TEnum = (red,blue,green);',
4091   '  TEnums = set of TEnum;',
4092   'const',
4093   '  teAny = [low(TEnum)..high(TEnum)];',
4094   '  teRedBlue = [low(TEnum)..pred(high(TEnum))];',
4095   'var',
4096   '  e: TEnum;',
4097   '  s: TEnums;',
4098   'begin',
4099   '  if blue in teAny then;',
4100   '  if blue in teAny+[e] then;',
4101   '  if blue in teAny+teRedBlue then;',
4102   '  s:=teAny;',
4103   '  s:=teAny+[e];',
4104   '  s:=[e]+teAny;',
4105   '  s:=teAny+teRedBlue;',
4106   '  s:=teAny+teRedBlue+[e];',
4107   '']);
4108   ParseProgram;
4109   CheckResolverUnexpectedHints;
4110 end;
4111 
4112 procedure TTestResolver.TestEnumSet_AnonymousEnumtype;
4113 begin
4114   StartProgram(false);
4115   Add('type');
4116   Add('  TFlags = set of (red, green);');
4117   Add('const');
4118   Add('  favorite = red;');
4119   Add('var');
4120   Add('  f: TFlags;');
4121   Add('  i: longint;');
4122   Add('begin');
4123   Add('  Include(f,red);');
4124   Add('  Include(f,favorite);');
4125   Add('  i:=ord(red);');
4126   Add('  i:=ord(favorite);');
4127   Add('  i:=ord(low(TFlags));');
4128   Add('  i:=ord(low(f));');
4129   Add('  i:=ord(low(favorite));');
4130   Add('  i:=ord(high(TFlags));');
4131   Add('  i:=ord(high(f));');
4132   Add('  i:=ord(high(favorite));');
4133   Add('  f:=[green,favorite];');
4134   ParseProgram;
4135 end;
4136 
4137 procedure TTestResolver.TestEnumSet_AnonymousEnumtypeName;
4138 begin
4139   ResolverEngine.AnonymousElTypePostfix:='$enum';
4140   StartProgram(false);
4141   Add('type');
4142   Add('  TFlags = set of (red, green);');
4143   Add('const');
4144   Add('  favorite = red;');
4145   Add('var');
4146   Add('  f: TFlags;');
4147   Add('  i: longint;');
4148   Add('begin');
4149   Add('  Include(f,red);');
4150   Add('  Include(f,favorite);');
4151   Add('  i:=ord(red);');
4152   Add('  i:=ord(favorite);');
4153   Add('  i:=ord(low(TFlags));');
4154   Add('  i:=ord(low(f));');
4155   Add('  i:=ord(low(favorite));');
4156   Add('  i:=ord(high(TFlags));');
4157   Add('  i:=ord(high(f));');
4158   Add('  i:=ord(high(favorite));');
4159   Add('  f:=[green,favorite];');
4160   ParseProgram;
4161 end;
4162 
4163 procedure TTestResolver.TestEnumSet_Const;
4164 begin
4165   StartProgram(false);
4166   Add([
4167   'type',
4168   '  TFlag = (a,b,c,d,e,f);',
4169   'const',
4170   '  s1 = [a];',
4171   '  s2 = [a,b];',
4172   '  s3 = [a..c];',
4173   '  s4 = [a..b,d..e,f];',
4174   '  s5 = [low(TFlag)..high(TFlag)];',
4175   '  s6 = [succ(low(TFlag))..pred(high(TFlag))];',
4176   '  s7 = [a..c]*[b..d];',
4177   '  s8 = [a..e]-[b,e];',
4178   '  s9 = [a,c..d]+[b,e];',
4179   '  s10 = [a..c]><[b..e];',
4180   '  s11 = [a,b]=[a..b];',
4181   '  s12 = [a,b]<>[a..b];',
4182   '  s13 = [a,b]<=[a..b];',
4183   '  s14 = [a,b]>=[a..b];',
4184   '  s15 = a in [a,b];',
4185   'var',
4186   '  Flag: TFlag;',
4187   'begin',
4188   '  if Flag in [b,c] then ;']);
4189   ParseProgram;
4190   CheckResolverUnexpectedHints;
4191 end;
4192 
4193 procedure TTestResolver.TestSet_IntRange_Const;
4194 begin
4195   StartProgram(false);
4196   Add([
4197   'type',
4198   '  TIntRg = 2..6;',
4199   '  TFiveSet = set of TIntRg;',
4200   'const',
4201   '  Three = 3;',
4202   '  a: TFiveSet = [2..Three,5]+[4];',
4203   '  b = low(TIntRg)+high(TIntRg);',
4204   '  c = [low(TIntRg)..high(TIntRg)];',
4205   'var',
4206   '  s: TFiveSet;',
4207   'begin',
4208   '  s:= {#s1_set}[];',
4209   '  s:= {#s2_set}[3];',
4210   '  s:= {#s3_set}[3..4];',
4211   '  s:= {#s4_set}[Three];',
4212   '  if 3 in a then ;',
4213   '  s:=c;']);
4214   ParseProgram;
4215   CheckParamsExpr_pkSet_Markers;
4216   CheckResolverUnexpectedHints;
4217 end;
4218 
4219 procedure TTestResolver.TestSet_Byte_Const;
4220 begin
4221   StartProgram(false);
4222   Add([
4223   'type',
4224   '  TIntRg = byte;',
4225   '  TFiveSet = set of TIntRg;',
4226   'const',
4227   '  Three = 3;',
4228   '  a: TFiveSet = [2..Three,5]+[4];',
4229   '  b = low(TIntRg)+high(TIntRg);',
4230   '  c = [low(TIntRg)..high(TIntRg)];',
4231   'var',
4232   '  s: TFiveSet;',
4233   'begin',
4234   '  s:= {#s1_set}[];',
4235   '  s:= {#s2_set}[3];',
4236   '  s:= {#s3_set}[3..4];',
4237   '  s:= {#s4_set}[Three];',
4238   '  if 3 in a then ;',
4239   '  s:=c;',
4240   //'  Include(s,Three);', // ToDo
4241   '']);
4242   ParseProgram;
4243   CheckParamsExpr_pkSet_Markers;
4244   CheckResolverUnexpectedHints;
4245 end;
4246 
4247 procedure TTestResolver.TestEnumRange;
4248 begin
4249   StartProgram(false);
4250   Add([
4251   'type',
4252   '  TEnum = (a,b,c,d,e);',
4253   '  TEnumRg = b..d;',
4254   '  TEnumRg2 = c..e;',
4255   '  TSetOfEnumRg = set of TEnumRg;',
4256   'const',
4257   '  c1: TEnumRg = c;',
4258   '  c2: TEnumRg = succ(low(TEnumRg));',
4259   '  c3: TEnumRg = pred(high(TEnumRg));',
4260   '  c4: TEnumRg = TEnumRg(2);',
4261   '  c5: TEnumRg2 = e;',
4262   'var',
4263   '  er: TEnumRg;',
4264   '  er2: TEnumRg2;',
4265   '  Enum: TEnum;',
4266   '  i: longint;',
4267   '  sr: TSetOfEnumRg;',
4268   'begin',
4269   '  er:=d;',
4270   '  Enum:=er;',
4271   '  if Enum=er then ;',
4272   '  if er=Enum then ;',
4273   '  if er=c then ;',
4274   '  if c=er then ;',
4275   '  if er=er2 then ;',
4276   '  er:=er2;',
4277   '  i:=ord(er);',
4278   '  er:=TEnumRg(i);',
4279   '  i:=longint(er);',
4280   '  if b in sr then ;',
4281   '  if er in sr then ;',
4282   '']);
4283   ParseProgram;
4284   CheckResolverUnexpectedHints;
4285 end;
4286 
4287 procedure TTestResolver.TestEnum_ForIn;
4288 begin
4289   StartProgram(false);
4290   Add([
4291   'type',
4292   '  TEnum = (red,green,blue);',
4293   '  TEnumRg = green..blue;',
4294   '  TSetOfEnum = set of TEnum;',
4295   '  TSetOfEnumRg = set of TEnumRg;',
4296   '  TArrOfEnum = array[TEnum] of byte;',
4297   '  TArrOfEnumRg = array[TEnumRg] of byte;',
4298   'var',
4299   '  e: TEnum;',
4300   '  er: TEnumRg;',
4301   'begin',
4302   '  for e in TEnum do;',
4303   '  for e in TEnumRg do;',
4304   '  for e in TSetOfEnum do;',
4305   '  for e in TSetOfEnumRg do;',
4306   '  for e in [] do;',
4307   '  for e in [red..green] do;',
4308   '  for e in [green,blue] do;',
4309   '  for e in TArrOfEnum do;',
4310   '  for e in TArrOfEnumRg do;',
4311   '  for er in TEnumRg do;',
4312   '  for er in TSetOfEnumRg do;',
4313   '  for er in [green..blue] do;',
4314   '  for er in TArrOfEnumRg do;',
4315   '']);
4316   ParseProgram;
4317 end;
4318 
4319 procedure TTestResolver.TestEnum_ForInRangeFail;
4320 begin
4321   StartProgram(false);
4322   Add([
4323   'type',
4324   '  TEnum = (red,green,blue);',
4325   'var',
4326   '  e: TEnum;',
4327   'begin',
4328   '  for e in red..green do;',
4329   '']);
4330   CheckResolverException('Cannot find an enumerator for the type "range.."',nCannotFindEnumeratorForType);
4331 end;
4332 
4333 procedure TTestResolver.TestEnum_ScopedEnums;
4334 begin
4335   StartProgram(false);
4336   Add([
4337   'type',
4338   '  {$scopedenums on}',
4339   '  TEnum = (red, green);',
4340   '  TFlags = set of (red,blue);',
4341   '  ',
4342   'var e: TEnum;',
4343   '  f: TFlags;',
4344   'begin',
4345   '  e:=TEnum.red;',
4346   '  if red in f then ;',
4347   '']);
4348   ParseProgram;
4349 end;
4350 
4351 procedure TTestResolver.TestEnum_ScopedEnumsFail;
4352 begin
4353   StartProgram(false);
4354   Add([
4355   'type',
4356   '  {$ScopedEnums on}',
4357   '  TEnum = (red, green);',
4358   'var e: TEnum;',
4359   'begin',
4360   '  e:=red;'
4361   ]);
4362   CheckResolverException(sIdentifierNotFound,nIdentifierNotFound);
4363 end;
4364 
4365 procedure TTestResolver.TestPrgAssignment;
4366 var
4367   El: TPasElement;
4368   V1: TPasVariable;
4369   ImplAssign: TPasImplAssign;
4370   Ref1: TPrimitiveExpr;
4371   Resolver1: TResolvedReference;
4372 begin
4373   StartProgram(false);
4374   Add('var');
4375   Add('  v1:longint;');
4376   Add('begin');
4377   Add('  v1:=3;');
4378   ParseProgram;
4379   AssertEquals('1 declaration',1,PasProgram.ProgramSection.Declarations.Count);
4380 
4381   El:=TPasElement(PasProgram.ProgramSection.Declarations[0]);
4382   AssertEquals('var',TPasVariable,El.ClassType);
4383   V1:=TPasVariable(El);
4384   AssertEquals('var v1','v1',V1.Name);
4385 
4386   AssertEquals('1 statement',1,PasProgram.InitializationSection.Elements.Count);
4387   AssertEquals('Assignment statement',TPasImplAssign,FFirstStatement.ClassType);
4388   ImplAssign:=FFirstStatement as TPasImplAssign;
4389   AssertEquals('Normal assignment',akDefault,ImplAssign.Kind);
4390   AssertExpression('Right side is constant',ImplAssign.Right,pekNumber,'3');
4391   AssertExpression('Left side is variable',ImplAssign.Left,pekIdent,'v1');
4392   AssertEquals('Left side is variable, primitive',TPrimitiveExpr,ImplAssign.Left.ClassType);
4393   Ref1:=TPrimitiveExpr(ImplAssign.Left);
4394   AssertNotNull('variable has customdata',Ref1.CustomData);
4395   AssertEquals('variable has resolver',TResolvedReference,Ref1.CustomData.ClassType);
4396   Resolver1:=TResolvedReference(Ref1.CustomData);
4397   AssertSame('variable resolver element',Resolver1.Element,Ref1);
4398   AssertSame('variable resolver declaration v1',Resolver1.Declaration,V1);
4399 end;
4400 
4401 procedure TTestResolver.TestPrgProcVar;
4402 begin
4403   StartProgram(false);
4404   Add('procedure Proc1;');
4405   Add('type');
4406   Add('  t1=longint;');
4407   Add('var');
4408   Add('  v1:t1;');
4409   Add('begin');
4410   Add('end;');
4411   Add('begin');
4412   ParseProgram;
4413   AssertEquals('1 declaration',1,PasProgram.ProgramSection.Declarations.Count);
4414 end;
4415 
4416 procedure TTestResolver.TestUnitProcVar;
4417 var
4418   El: TPasElement;
4419   IntfProc1, ImplProc1: TPasProcedure;
4420   IntfType1, ProcSubType1: TPasAliasType;
4421   ImplVar1, ProcSubVar1: TPasVariable;
4422   ImplVar1Type, ProcSubVar1Type: TPasType;
4423 begin
4424   StartUnit(false);
4425   Add('interface');
4426   Add('');
4427   Add('type t1=string; // unit scope');
4428   Add('procedure Proc1;');
4429   Add('');
4430   Add('implementation');
4431   Add('');
4432   Add('procedure Proc1;');
4433   Add('type t1=longint; // local proc scope');
4434   Add('var  v1:t1; // using local t1');
4435   Add('begin');
4436   Add('end;');
4437   Add('var  v2:t1; // using interface t1');
4438   ParseUnit;
4439 
4440   // interface
4441   AssertEquals('2 intf declarations',2,Module.InterfaceSection.Declarations.Count);
4442   El:=TPasElement(Module.InterfaceSection.Declarations[0]);
4443   AssertEquals('intf type',TPasAliasType,El.ClassType);
4444   IntfType1:=TPasAliasType(El);
4445   AssertEquals('intf type t1','t1',IntfType1.Name);
4446 
4447   El:=TPasElement(Module.InterfaceSection.Declarations[1]);
4448   AssertEquals('intf proc',TPasProcedure,El.ClassType);
4449   IntfProc1:=TPasProcedure(El);
4450   AssertEquals('intf proc Proc1','Proc1',IntfProc1.Name);
4451 
4452   // implementation
4453   AssertEquals('2 impl declarations',2,Module.ImplementationSection.Declarations.Count);
4454   El:=TPasElement(Module.ImplementationSection.Declarations[0]);
4455   AssertEquals('impl proc',TPasProcedure,El.ClassType);
4456   ImplProc1:=TPasProcedure(El);
4457   AssertEquals('impl proc Proc1','Proc1',ImplProc1.Name);
4458 
4459   El:=TPasElement(Module.ImplementationSection.Declarations[1]);
4460   AssertEquals('impl var',TPasVariable,El.ClassType);
4461   ImplVar1:=TPasVariable(El);
4462   AssertEquals('impl var v2','v2',ImplVar1.Name);
4463   ImplVar1Type:=TPasType(ImplVar1.VarType);
4464   AssertSame('impl var type is intf t1',IntfType1,ImplVar1Type);
4465 
4466   // proc
4467   AssertEquals('2 proc sub declarations',2,ImplProc1.Body.Declarations.Count);
4468 
4469   // proc sub type t1
4470   El:=TPasElement(ImplProc1.Body.Declarations[0]);
4471   AssertEquals('proc sub type',TPasAliasType,El.ClassType);
4472   ProcSubType1:=TPasAliasType(El);
4473   AssertEquals('proc sub type t1','t1',ProcSubType1.Name);
4474 
4475   // proc sub var v1
4476   El:=TPasElement(ImplProc1.Body.Declarations[1]);
4477   AssertEquals('proc sub var',TPasVariable,El.ClassType);
4478   ProcSubVar1:=TPasVariable(El);
4479   AssertEquals('proc sub var v1','v1',ProcSubVar1.Name);
4480   ProcSubVar1Type:=TPasType(ProcSubVar1.VarType);
4481   AssertSame('proc sub var type is proc sub t1',ProcSubType1,ProcSubVar1Type);
4482 end;
4483 
4484 procedure TTestResolver.TestAssignIntegers;
4485 begin
4486   StartProgram(false);
4487   Add('var');
4488   Add('  {#vbyte}vbyte:byte;');
4489   Add('  {#vshortint}vshortint:shortint;');
4490   Add('  {#vword}vword:word;');
4491   Add('  {#vsmallint}vsmallint:smallint;');
4492   Add('  {#vlongword}vlongword:longword;');
4493   Add('  {#vlongint}vlongint:longint;');
4494   Add('  {#vqword}vqword:qword;');
4495   Add('  {#vint64}vint64:int64;');
4496   Add('  {#vcomp}vcomp:comp;');
4497   Add('begin');
4498   Add('  {@vbyte}vbyte:=0;');
4499   Add('  {@vbyte}vbyte:=255;');
4500   Add('  {@vshortint}vshortint:=0;');
4501   Add('  {@vshortint}vshortint:=-128;');
4502   Add('  {@vshortint}vshortint:= 127;');
4503   Add('  {@vword}vword:=0;');
4504   Add('  {@vword}vword:=+$ffff;');
4505   Add('  {@vsmallint}vsmallint:=0;');
4506   Add('  {@vsmallint}vsmallint:=-$8000;');
4507   Add('  {@vsmallint}vsmallint:= $7fff;');
4508   Add('  {@vlongword}vlongword:=0;');
4509   Add('  {@vlongword}vlongword:=$ffffffff;');
4510   Add('  {@vlongint}vlongint:=0;');
4511   Add('  {@vlongint}vlongint:=-$80000000;');
4512   Add('  {@vlongint}vlongint:= $7fffffff;');
4513   Add('  {@vlongint}vlongint:={@vbyte}vbyte;');
4514   Add('  {@vlongint}vlongint:={@vshortint}vshortint;');
4515   Add('  {@vlongint}vlongint:={@vword}vword;');
4516   Add('  {@vlongint}vlongint:={@vsmallint}vsmallint;');
4517   Add('  {@vlongint}vlongint:={@vlongint}vlongint;');
4518   Add('  {@vint64}vint64:=0;');
4519   Add('  {@vint64}vint64:=-$8000000000000000;');
4520   Add('  {@vint64}vint64:= $7fffffffffffffff;');
4521   Add('  {@vqword}vqword:=0;');
4522   Add('  {@vqword}vqword:=$ffffffffffffffff;');
4523   Add('  {@vcomp}vcomp:=0;');
4524   Add('  {@vcomp}vcomp:=-$8000000000000000;');
4525   Add('  {@vcomp}vcomp:= $7fffffffffffffff;');
4526   ParseProgram;
4527 end;
4528 
4529 procedure TTestResolver.TestAssignString;
4530 begin
4531   StartProgram(false);
4532   Add('var');
4533   Add('  vstring:string;');
4534   Add('  vchar:char;');
4535   Add('begin');
4536   Add('  vstring:='''';');
4537   Add('  vstring:=''abc'';');
4538   Add('  vstring:=''a'';');
4539   Add('  vchar:=''c'';');
4540   Add('  vchar:=vstring[1];');
4541   ParseProgram;
4542 end;
4543 
4544 procedure TTestResolver.TestAssignIntToStringFail;
4545 begin
4546   StartProgram(false);
4547   Add('var');
4548   Add('  vstring:string;');
4549   Add('begin');
4550   Add('  vstring:=2;');
4551   CheckResolverException('Incompatible types: got "Longint" expected "String"',
4552     nIncompatibleTypesGotExpected);
4553 end;
4554 
4555 procedure TTestResolver.TestAssignStringToIntFail;
4556 begin
4557   StartProgram(false);
4558   Add('var');
4559   Add('  v:longint;');
4560   Add('begin');
4561   Add('  v:=''A'';');
4562   CheckResolverException('Incompatible types: got "Char" expected "Longint"',
4563     nIncompatibleTypesGotExpected);
4564 end;
4565 
4566 procedure TTestResolver.TestIntegerOperators;
4567 begin
4568   StartProgram(false);
4569   Add('var');
4570   Add('  i,j,k:longint;');
4571   Add('begin');
4572   Add('  i:=1;');
4573   Add('  i:=1+2;');
4574   Add('  i:=1+2+3;');
4575   Add('  i:=1-2;');
4576   Add('  i:=j;');
4577   Add('  i:=j+1;');
4578   Add('  i:=-j+1;');
4579   Add('  i:=j+k;');
4580   Add('  i:=-j+k;');
4581   Add('  i:=j*k;');
4582   Add('  i:=j**k;');
4583   Add('  i:=10**3;');
4584   Add('  i:=j div k;');
4585   Add('  i:=10 div 3;');
4586   Add('  i:=j mod k;');
4587   Add('  i:=10 mod 3;');
4588   Add('  i:=j shl k;');
4589   Add('  i:=j shr k;');
4590   Add('  i:=j and k;');
4591   Add('  i:=j or k;');
4592   Add('  i:=j and not k;');
4593   Add('  i:=(j+k) div 3;');
4594   Add('  if i=j then;');
4595   Add('  if i<>j then;');
4596   Add('  if i>j then;');
4597   Add('  if i>=j then;');
4598   Add('  if i<j then;');
4599   Add('  if i<=j then;');
4600   Add('  i:=lo($1234);');
4601   Add('  i:=lo($1234CDEF);');
4602   Add('  i:=hi($1234);');
4603   Add('  i:=hi($1234CDEF);');
4604   ParseProgram;
4605 end;
4606 
4607 procedure TTestResolver.TestIntegerBoolFail;
4608 begin
4609   StartProgram(false);
4610   Add([
4611   'var i: longint;',
4612   'begin',
4613   '  i:=3 * false;']);
4614   CheckResolverException('Operator is not overloaded: "Longint" * "Boolean"',
4615     nOperatorIsNotOverloadedAOpB);
4616 end;
4617 
4618 procedure TTestResolver.TestBooleanOperators;
4619 begin
4620   StartProgram(false);
4621   Add('var');
4622   Add('  i,j,k:boolean;');
4623   Add('begin');
4624   Add('  i:=false;');
4625   Add('  i:=true;');
4626   Add('  i:=j and k;');
4627   Add('  i:=j or k;');
4628   Add('  i:=j or not k;');
4629   Add('  i:=(not j) or k;');
4630   Add('  i:=j or false;');
4631   Add('  i:=j and true;');
4632   Add('  i:=j xor k;');
4633   Add('  i:=j=k;');
4634   Add('  i:=j<>k;');
4635   ParseProgram;
4636 end;
4637 
4638 procedure TTestResolver.TestStringOperators;
4639 begin
4640   StartProgram(false);
4641   Add([
4642   'var',
4643   '  i,j:string;',
4644   '  k:char;',
4645   '  w:widechar;',
4646   'begin',
4647   '  i:='''';',
4648   '  i:=''''+'''';',
4649   '  i:=k+'''';',
4650   '  i:=''''+k;',
4651   '  i:=''a''+j;',
4652   '  i:=''abc''+j;',
4653   '  k:=#65;',
4654   '  k:=#$42;',
4655   '  k:=''a'';',
4656   '  k:='''''''';',
4657   '  k:=j[1];',
4658   '  k:=char(#10);',
4659   '  w:=k;',
4660   '  w:=#66;',
4661   '  w:=#6666;',
4662   '  w:=widechar(#10);',
4663   '  w:=widechar(#$E0000);',
4664   '']);
4665   ParseProgram;
4666 end;
4667 
4668 procedure TTestResolver.TestWideCharOperators;
4669 begin
4670   ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
4671   ResolverEngine.BaseTypeChar:=btWideChar;
4672   ResolverEngine.BaseTypeString:=btUnicodeString;
4673   StartProgram(false);
4674   Add('var');
4675   Add('  k:char;');
4676   Add('  w:widechar;');
4677   Add('begin');
4678   Add('  w:=k;');
4679   Add('  w:=#66;');
4680   Add('  w:=#6666;');
4681   Add('  w:=''ä'';');
4682   ParseProgram;
4683 end;
4684 
4685 procedure TTestResolver.TestFloatOperators;
4686 begin
4687   StartProgram(false);
4688   Add('var');
4689   Add('  i,j,k:double;');
4690   Add('  o,p:longint;');
4691   Add('begin');
4692   Add('  i:=1;');
4693   Add('  i:=1+2;');
4694   Add('  i:=1+2+3;');
4695   Add('  i:=1-2;');
4696   Add('  i:=j;');
4697   Add('  i:=j+1;');
4698   Add('  i:=-j+1;');
4699   Add('  i:=j+k;');
4700   Add('  i:=-j+k;');
4701   Add('  i:=j*k;');
4702   Add('  i:=10/3;');
4703   Add('  i:=10.0/3;');
4704   Add('  i:=10/3.0;');
4705   Add('  i:=10.0/3.0;');
4706   Add('  i:=j/k;');
4707   Add('  i:=o/p;');
4708   Add('  i:=10**3;');
4709   Add('  i:=10.0**3;');
4710   Add('  i:=10.0**3.0;');
4711   Add('  i:=10**3.0;');
4712   Add('  i:=j**k;');
4713   Add('  i:=o**p;');
4714   Add('  i:=(j+k)/3;');
4715   ParseProgram;
4716 end;
4717 
4718 procedure TTestResolver.TestCAssignments;
4719 begin
4720   StartProgram(false);
4721   Parser.Options:=Parser.Options+[po_cassignments];
4722   Add('Type');
4723   Add('  TFlag = (Flag1,Flag2);');
4724   Add('  TFlags = set of TFlag;');
4725   Add('var');
4726   Add('  i: longint;');
4727   Add('  c: char;');
4728   Add('  s: string;');
4729   Add('  d: double;');
4730   Add('  f: TFlag;');
4731   Add('  fs: TFlags;');
4732   Add('begin');
4733   Add('  i+=1;');
4734   Add('  i-=2;');
4735   Add('  i*=3;');
4736   Add('  s+=''A'';');
4737   Add('  s:=c;');
4738   Add('  d+=4;');
4739   Add('  d-=5;');
4740   Add('  d*=6;');
4741   Add('  d/=7;');
4742   Add('  d+=8.5;');
4743   Add('  d-=9.5;');
4744   Add('  d*=10.5;');
4745   Add('  d/=11.5;');
4746   Add('  fs+=[f];');
4747   Add('  fs-=[f];');
4748   Add('  fs*=[f];');
4749   Add('  fs+=[Flag1];');
4750   Add('  fs-=[Flag1];');
4751   Add('  fs*=[Flag1];');
4752   Add('  fs+=[Flag1,Flag2];');
4753   Add('  fs-=[Flag1,Flag2];');
4754   Add('  fs*=[Flag1,Flag2];');
4755   ParseProgram;
4756 end;
4757 
4758 procedure TTestResolver.TestTypeCastBaseTypes;
4759 begin
4760   StartProgram(false);
4761   Add([
4762   'var',
4763   '  si: smallint;',
4764   '  i: longint;',
4765   '  fs: single;',
4766   '  d: double;',
4767   '  b: boolean;',
4768   '  c: char;',
4769   '  s: string;',
4770   'begin',
4771   '  d:=double({#a_read}i);',
4772   '  i:=shortint({#b_read}i);',
4773   '  i:=longint({#c_read}si);',
4774   '  d:=double({#d_read}d);',
4775   '  fs:=single({#e_read}d);',
4776   '  d:=single({#f_read}d);',
4777   '  b:=longbool({#g_read}b);',
4778   '  b:=bytebool({#i_read}longbool({#h_read}b));',
4779   '  d:=double({#j_read}i)/2.5;',
4780   '  b:=boolean({#k_read}i);',
4781   '  i:=longint({#l_read}b);',
4782   '  d:=double({#m_read}i);',
4783   '  c:=char({#n_read}c);',
4784   '  c:=char({#o_read}i);',
4785   '  c:=char(65);',
4786   '  s:=string({#p_read}s);',
4787   '  s:=string({#q_read}c);',
4788   '']);
4789   ParseProgram;
4790   CheckAccessMarkers;
4791 end;
4792 
4793 procedure TTestResolver.TestTypeCastAliasBaseTypes;
4794 begin
4795   StartProgram(false);
4796   Add('type');
4797   Add('  integer = longint;');
4798   Add('  TCaption = string;');
4799   Add('  TYesNo = boolean;');
4800   Add('  TFloat = double;');
4801   Add('  TChar = char;');
4802   Add('var');
4803   Add('  i: longint;');
4804   Add('  s: string;');
4805   Add('  b: boolean;');
4806   Add('  d: double;');
4807   Add('  c: char;');
4808   Add('begin');
4809   Add('  i:=integer({#a_read}i);');
4810   Add('  i:=integer({#h_read}b);');
4811   Add('  s:=TCaption({#b_read}s);');
4812   Add('  s:=TCaption({#g_read}c);');
4813   Add('  b:=TYesNo({#c_read}b);');
4814   Add('  b:=TYesNo({#d_read}i);');
4815   Add('  d:=TFloat({#e_read}d);');
4816   Add('  c:=TChar({#f_read}c);');
4817   ParseProgram;
4818   CheckAccessMarkers;
4819 end;
4820 
4821 procedure TTestResolver.TestTypeCastStrToIntFail;
4822 begin
4823   StartProgram(false);
4824   Add('var');
4825   Add('  s: string;');
4826   Add('  i: longint;');
4827   Add('begin');
4828   Add('  i:=longint(s);');
4829   CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
4830 end;
4831 
4832 procedure TTestResolver.TestTypeCastStrToCharFail;
4833 begin
4834   StartProgram(false);
4835   Add('var');
4836   Add('  s: string;');
4837   Add('  c: char;');
4838   Add('begin');
4839   Add('  c:=char(s);');
4840   CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
4841 end;
4842 
4843 procedure TTestResolver.TestTypeCastIntToStrFail;
4844 begin
4845   StartProgram(false);
4846   Add('var');
4847   Add('  s: string;');
4848   Add('  i: longint;');
4849   Add('begin');
4850   Add('  s:=string(i);');
4851   CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
4852 end;
4853 
4854 procedure TTestResolver.TestTypeCastDoubleToStrFail;
4855 begin
4856   StartProgram(false);
4857   Add('var');
4858   Add('  s: string;');
4859   Add('  d: double;');
4860   Add('begin');
4861   Add('  s:=string(d);');
4862   CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
4863 end;
4864 
4865 procedure TTestResolver.TestTypeCastDoubleToIntFail;
4866 begin
4867   StartProgram(false);
4868   Add('var');
4869   Add('  i: longint;');
4870   Add('  d: double;');
4871   Add('begin');
4872   Add('  i:=longint(d);');
4873   CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
4874 end;
4875 
4876 procedure TTestResolver.TestTypeCastDoubleToBoolFail;
4877 begin
4878   StartProgram(false);
4879   Add('var');
4880   Add('  b: boolean;');
4881   Add('  d: double;');
4882   Add('begin');
4883   Add('  b:=longint(d);');
4884   CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
4885 end;
4886 
4887 procedure TTestResolver.TestTypeCastBooleanToDoubleFail;
4888 begin
4889   StartProgram(false);
4890   Add('var');
4891   Add('  b: boolean;');
4892   Add('  d: double;');
4893   Add('begin');
4894   Add('  d:=double(b);');
4895   CheckResolverException(sIllegalTypeConversionTo,nIllegalTypeConversionTo);
4896 end;
4897 
4898 procedure TTestResolver.TestAssign_Access;
4899 begin
4900   StartProgram(false);
4901   Parser.Options:=Parser.Options+[po_cassignments];
4902   Add('var i: longint;');
4903   Add('begin');
4904   Add('  {#a1_assign}i:={#a2_read}i;');
4905   Add('  {#b1_readandassign}i+={#b2_read}i;');
4906   Add('  {#c1_readandassign}i-={#c2_read}i;');
4907   Add('  {#d1_readandassign}i*={#d2_read}i;');
4908   ParseProgram;
4909   CheckAccessMarkers;
4910 end;
4911 
4912 procedure TTestResolver.TestAssignedIntFail;
4913 begin
4914   StartProgram(false);
4915   Add('var i: longint;');
4916   Add('begin');
4917   Add('  if Assigned(i) then ;');
4918   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "class or array"',
4919     nIncompatibleTypeArgNo);
4920 end;
4921 
4922 procedure TTestResolver.TestHighLow;
4923 begin
4924   StartProgram(false);
4925   Add('var');
4926   Add('  bo: boolean;');
4927   Add('  by: byte;');
4928   Add('  ch: char;');
4929   Add('begin');
4930   Add('  for bo:=low(boolean) to high(boolean) do;');
4931   Add('  for by:=low(byte) to high(byte) do;');
4932   Add('  for ch:=low(char) to high(char) do;');
4933   ParseProgram;
4934 end;
4935 
4936 procedure TTestResolver.TestStr_BaseTypes;
4937 begin
4938   StartProgram(false);
4939   Add('var');
4940   Add('  b: boolean;');
4941   Add('  i: longint;');
4942   Add('  i64: int64;');
4943   Add('  s: single;');
4944   Add('  d: double;');
4945   Add('  aString: string;');
4946   Add('  r: record end;');
4947   Add('begin');
4948   Add('  Str(b,{#a_var}aString);');
4949   Add('  Str(b:1,aString);');
4950   Add('  Str(b:i,aString);');
4951   Add('  Str(i,aString);');
4952   Add('  Str(i:2,aString);');
4953   Add('  Str(i:i64,aString);');
4954   Add('  Str(i64,aString);');
4955   Add('  Str(i64:3,aString);');
4956   Add('  Str(i64:i,aString);');
4957   Add('  Str(s,aString);');
4958   Add('  Str(d,aString);');
4959   Add('  Str(d:4,aString);');
4960   Add('  Str(d:4:5,aString);');
4961   Add('  Str(d:4:i,aString);');
4962   Add('  aString:=Str(b);');
4963   Add('  aString:=Str(i:3);');
4964   Add('  aString:=Str(d:3:4);');
4965   Add('  aString:=Str(b,i,d);');
4966   Add('  aString:=Str(s,''foo'');');
4967   Add('  aString:=Str(i,{#assign_read}aString);');
4968   Add('  while true do Str(i,{#whiledo_var}aString);');
4969   Add('  repeat Str(i,{#repeat_var}aString); until true;');
4970   Add('  if true then Str(i,{#ifthen_var}aString) else Str(i,{#ifelse_var}aString);');
4971   Add('  for i:=0 to 0 do Str(i,{#fordo_var}aString);');
4972   Add('  with r do Str(i,{#withdo_var}aString);');
4973   Add('  case Str(s,''caseexpr'') of');
4974   Add('  ''bar'': Str(i,{#casest_var}aString);');
4975   Add('  else Str(i,{#caseelse_var}aString);');
4976   Add('  end;');
4977   ParseProgram;
4978   CheckAccessMarkers;
4979 end;
4980 
4981 procedure TTestResolver.TestStr_StringFail;
4982 begin
4983   StartProgram(false);
4984   Add('var');
4985   Add('  aString: string;');
4986   Add('begin');
4987   Add('  Str(aString,aString);');
4988   CheckResolverException('Incompatible type arg no. 1: Got "String", expected "boolean, integer, enum value"',
4989     nIncompatibleTypeArgNo);
4990 end;
4991 
4992 procedure TTestResolver.TestStr_CharFail;
4993 begin
4994   StartProgram(false);
4995   Add('var');
4996   Add('  c: char;');
4997   Add('  aString: string;');
4998   Add('begin');
4999   Add('  Str(c,aString);');
5000   CheckResolverException('Incompatible type arg no. 1: Got "Char", expected "boolean, integer, enum value"',
5001     nIncompatibleTypeArgNo);
5002 end;
5003 
5004 procedure TTestResolver.TestIncDec;
5005 begin
5006   StartProgram(false);
5007   Add('var');
5008   Add('  i: longint;');
5009   Add('begin');
5010   Add('  inc({#a_var}i);');
5011   Add('  inc({#b_var}i,2);');
5012   Add('  dec({#c_var}i);');
5013   Add('  dec({#d_var}i,3);');
5014   ParseProgram;
5015   CheckAccessMarkers;
5016 end;
5017 
5018 procedure TTestResolver.TestIncStringFail;
5019 begin
5020   StartProgram(false);
5021   Add('var');
5022   Add('  i: string;');
5023   Add('begin');
5024   Add('  inc(i);');
5025   CheckResolverException('Incompatible type arg no. 1: Got "String", expected "integer"',nIncompatibleTypeArgNo);
5026 end;
5027 
5028 procedure TTestResolver.TestTypeInfo;
5029 begin
5030   StartProgram(false);
5031   Add([
5032   'type',
5033   '  integer = longint;',
5034   '  TRec = record',
5035   '    v: integer;',
5036   '  end;',
5037   '  TClass = class of TObject;',
5038   '  TObject = class',
5039   '    class function ClassType: TClass; virtual; abstract;',
5040   '  end;',
5041   'var',
5042   '  i: integer;',
5043   '  s: string;',
5044   '  p: pointer;',
5045   '  r: TRec;',
5046   '  o: TObject;',
5047   '  c: TClass;',
5048   'begin',
5049   '  p:=typeinfo(integer);',
5050   '  p:=typeinfo(longint);',
5051   '  p:=typeinfo(i);',
5052   '  p:=typeinfo(s);',
5053   '  p:=typeinfo(p);',
5054   '  p:=typeinfo(r.v);',
5055   '  p:=typeinfo(TObject.ClassType);',
5056   '  p:=typeinfo(o.ClassType);',
5057   '  p:=typeinfo(o);',
5058   '  p:=typeinfo(c);',
5059   '  p:=typeinfo(c.ClassType);',
5060   '']);
5061   ParseProgram;
5062 end;
5063 
5064 procedure TTestResolver.TestTypeInfo_FailRTTIDisabled;
5065 begin
5066   StartProgram(false);
5067   Add([
5068   '{$modeswitch OmitRTTI}',
5069   'type',
5070   '  TObject = class',
5071   '  end;',
5072   'var o: TObject;',
5073   'begin',
5074   '  if typeinfo(o)=nil then ;',
5075   '']);
5076   CheckResolverException(sSymbolCannotBePublished,nSymbolCannotBePublished);
5077 end;
5078 
5079 procedure TTestResolver.TestGetTypeKind;
5080 begin
5081   StartProgram(true,[supTTypeKind]);
5082   Add([
5083   'type',
5084   '  integer = longint;',
5085   '  TRec = record',
5086   '    v: integer;',
5087   '  end;',
5088   '  TClass = class of TObject;',
5089   '  TObject = class',
5090   '    class function ClassType: TClass; virtual; abstract;',
5091   '  end;',
5092   'var',
5093   '  i: integer;',
5094   '  s: string;',
5095   '  p: pointer;',
5096   '  r: TRec;',
5097   '  o: TObject;',
5098   '  c: TClass;',
5099   '  k: TTypeKind;',
5100   'begin',
5101   '  k:=gettypekind(integer);',
5102   '  k:=gettypekind(longint);',
5103   '  k:=gettypekind(i);',
5104   '  k:=gettypekind(s);',
5105   '  k:=gettypekind(p);',
5106   '  k:=gettypekind(r.v);',
5107   '  k:=gettypekind(TObject.ClassType);',
5108   '  k:=gettypekind(o.ClassType);',
5109   '  k:=gettypekind(o);',
5110   '  k:=gettypekind(c);',
5111   '  k:=gettypekind(c.ClassType);',
5112   '  k:=gettypekind(k);',
5113   '']);
5114   ParseProgram;
5115 end;
5116 
5117 procedure TTestResolver.TestForLoop;
5118 begin
5119   StartProgram(false);
5120   Add('var');
5121   Add('  {#v1}v1,{#v2}v2,{#v3}v3:longint;');
5122   Add('begin');
5123   Add('  for {@v1}v1:=');
5124   Add('    {@v2}v2');
5125   Add('    to {@v3}v3 do ;');
5126   ParseProgram;
5127 end;
5128 
5129 procedure TTestResolver.TestForLoop_NestedSameVarFail;
5130 begin
5131   StartProgram(false);
5132   Add([
5133   'var i: byte;',
5134   'begin',
5135   '  for i:=1 to 2 do',
5136   '    for i:=1 to 2 do ;',
5137   '']);
5138   CheckResolverException('Illegal assignment to for-loop variable "i"',nIllegalAssignmentToForLoopVar);
5139 end;
5140 
5141 procedure TTestResolver.TestForLoop_AssignVarFail;
5142 begin
5143   StartProgram(false);
5144   Add([
5145   'var i: byte;',
5146   'begin',
5147   '  for i:=1 to 2 do',
5148   '    i:=3;',
5149   '']);
5150   CheckResolverException('Illegal assignment to for-loop variable "i"',nIllegalAssignmentToForLoopVar);
5151 end;
5152 
5153 procedure TTestResolver.TestForLoop_PassVarFail;
5154 begin
5155   StartProgram(false);
5156   Add([
5157   'procedure DoIt(var i: byte); external;',
5158   'var i: byte;',
5159   'begin',
5160   '  for i:=1 to 2 do',
5161   '    DoIt(i);',
5162   '']);
5163   CheckResolverException('Illegal assignment to for-loop variable "i"',nIllegalAssignmentToForLoopVar);
5164 end;
5165 
5166 procedure TTestResolver.TestStatements;
5167 begin
5168   StartProgram(false);
5169   Add([
5170   'var',
5171   '  v1,v2,v3:longint;',
5172   'begin',
5173   '  v1:=1;',
5174   '  v2:=v1+v1*v1+v1 div v1;',
5175   '  v3:=-v1;',
5176   '  repeat',
5177   '    v1:=v1+1;',
5178   '  until v1>=5;',
5179   '  while v1>=0 do',
5180   '    v1:=v1-v2;',
5181   '  for v1:=v2 to v3 do v2:=v1;',
5182   '  if v1<v2 then v3:=v1 else v3:=v2;',
5183   '']);
5184   ParseProgram;
5185   AssertEquals('3 declarations',3,PasProgram.ProgramSection.Declarations.Count);
5186 end;
5187 
5188 procedure TTestResolver.TestCaseOfInt;
5189 begin
5190   StartProgram(false);
5191   Add('const');
5192   Add('  {#c1}c1=1;');
5193   Add('  {#c2}c2=2;');
5194   Add('  {#c3}c3=3;');
5195   Add('  {#c4}c4=4;');
5196   Add('  {#c5}c5=5;');
5197   Add('  {#c6}c6=6;');
5198   Add('var');
5199   Add('  {#v1}v1,{#v2}v2,{#v3}v3:longint;');
5200   Add('begin');
5201   Add('  Case {@v1}v1+{@v2}v2 of');
5202   Add('  {@c1}c1:');
5203   Add('    {@v2}v2:={@v3}v3;');
5204   Add('  {@c2}c2,{@c3}c3: ;');
5205   Add('  {@c4}c4..5: ;');
5206   Add('  {@c5}c5+{@c6}c6: ;');
5207   Add('  else');
5208   Add('    {@v1}v1:=3;');
5209   Add('  end;');
5210   ParseProgram;
5211 end;
5212 
5213 procedure TTestResolver.TestCaseOfIntExtConst;
5214 begin
5215   Parser.Options:=Parser.Options+[po_ExtConstWithoutExpr];
5216   StartProgram(false);
5217   Add([
5218   'const e: longint; external;',
5219   'var i: longint;',
5220   'begin',
5221   '  case i of',
5222   '  2: ;',
5223   '  e: ;',
5224   '  1: ;',
5225   '  end;',
5226   '']);
5227   ParseProgram;
5228 end;
5229 
5230 procedure TTestResolver.TestCaseIntDuplicateFail;
5231 begin
5232   StartProgram(false);
5233   Add([
5234   'var i: longint;',
5235   'begin',
5236   '  case i of',
5237   '  2: ;',
5238   '  1..3: ;',
5239   '  end;',
5240   '']);
5241   CheckResolverException('Duplicate case value "1..3", other at afile.pp(5,3)',nDuplicateCaseValueXatY);
5242 end;
5243 
5244 procedure TTestResolver.TestCaseOfStringDuplicateFail;
5245 begin
5246   StartProgram(false);
5247   Add([
5248   'var s: string;',
5249   'begin',
5250   '  case s of',
5251   '  ''a''#10''bc'': ;',
5252   '  ''A''#10''BC'': ;',
5253   '  ''a''#10''bc'': ;',
5254   '  end;',
5255   '']);
5256   CheckResolverException('Duplicate case value "string", other at afile.pp(5,3)',nDuplicateCaseValueXatY);
5257 end;
5258 
5259 procedure TTestResolver.TestCaseOfStringRangeDuplicateFail;
5260 begin
5261   StartProgram(false);
5262   Add([
5263   'var s: string;',
5264   'begin',
5265   '  case s of',
5266   '  ''c'': ;',
5267   '  ''a''..''z'': ;',
5268   '  end;',
5269   '']);
5270   CheckResolverException('Duplicate case value "string", other at afile.pp(5,3)',nDuplicateCaseValueXatY);
5271 end;
5272 
5273 procedure TTestResolver.TestCaseOfBaseType;
5274 begin
5275   StartProgram(false);
5276   Add([
5277   'type',
5278   '  TFlag = (red,green,blue);',
5279   'var',
5280   '  i: longint;',
5281   '  f: TFlag;',
5282   '  b: boolean;',
5283   '  c: char;',
5284   '  s: string;',
5285   'begin',
5286   '  case i of',
5287   '  1: ;',
5288   '  2..3: ;',
5289   '  4,5..6,7: ;',
5290   '  else',
5291   '  end;',
5292   '  case f of',
5293   '  red: ;',
5294   '  green..blue: ;',
5295   '  end;',
5296   '  case b of',
5297   '  true: ;',
5298   '  false: ;',
5299   '  end;',
5300   '  case c of',
5301   '  #0: ;',
5302   '  #10,#13: ;',
5303   '  ''0''..''9'',''a''..''z'': ;',
5304   '  end;',
5305   '  case s of',
5306   '  #10: ;',
5307   '  ''abc'': ;',
5308   '  ''a''..''z'': ;',
5309   '  end;']);
5310   ParseProgram;
5311 end;
5312 
5313 procedure TTestResolver.TestCaseOfExprNonOrdFail;
5314 begin
5315   StartProgram(false);
5316   Add('begin');
5317   Add('  case longint of');
5318   Add('  1: ;');
5319   Add('  end;');
5320   CheckResolverException('ordinal expression expected, but Longint found',
5321     nXExpectedButYFound);
5322 end;
5323 
5324 procedure TTestResolver.TestCaseOfIncompatibleValueFail;
5325 begin
5326   StartProgram(false);
5327   Add('var i: longint;');
5328   Add('begin');
5329   Add('  case i of');
5330   Add('  ''1'': ;');
5331   Add('  end;');
5332   CheckResolverException('Incompatible types: got "Char" expected "Longint"',
5333     nIncompatibleTypesGotExpected);
5334 end;
5335 
5336 procedure TTestResolver.TestTryStatement;
5337 begin
5338   StartProgram(false);
5339   Add('type');
5340   Add('  TObject = class end;');
5341   Add('  {#Exec}Exception = class end;');
5342   Add('var');
5343   Add('  {#v1}v1,{#e1}e:longint;');
5344   Add('begin');
5345   Add('  try');
5346   Add('    {@v1}v1:={@e1}e;');
5347   Add('  finally');
5348   Add('    {@v1}v1:={@e1}e;');
5349   Add('  end;');
5350   Add('  try');
5351   Add('    {@v1}v1:={@e1}e;');
5352   Add('  except');
5353   Add('    {@v1}v1:={@e1}e;');
5354   Add('    raise;');
5355   Add('  end;');
5356   Add('  try');
5357   Add('    {@v1}v1:={@e1}e;');
5358   Add('  except');
5359   Add('    on {#e2}{=Exec}E: Exception do');
5360   Add('      if {@e2}e=nil then raise;');
5361   Add('    on {#e3}{=Exec}E: Exception do');
5362   Add('      raise {@e3}e;');
5363   Add('    else');
5364   Add('      {@v1}v1:={@e1}e;');
5365   Add('  end;');
5366   ParseProgram;
5367 end;
5368 
5369 procedure TTestResolver.TestTryExceptOnNonTypeFail;
5370 begin
5371   StartProgram(false);
5372   Add('type TObject = class end;');
5373   Add('var E: TObject;');
5374   Add('begin');
5375   Add('  try');
5376   Add('  except');
5377   Add('    on E do ;');
5378   Add('  end;');
5379   CheckParserException('Expected type, but got variable',PParser.nParserExpectedTypeButGot);
5380 end;
5381 
5382 procedure TTestResolver.TestTryExceptOnNonClassFail;
5383 begin
5384   StartProgram(false);
5385   Add('begin');
5386   Add('  try');
5387   Add('  except');
5388   Add('    on longint do ;');
5389   Add('  end;');
5390   CheckResolverException('class expected, but Longint found',nXExpectedButYFound);
5391 end;
5392 
5393 procedure TTestResolver.TestRaiseNonVarFail;
5394 begin
5395   StartProgram(false);
5396   Add('type TObject = class end;');
5397   Add('begin');
5398   Add('  raise TObject;');
5399   CheckResolverException('variable expected, but class found',nXExpectedButYFound);
5400 end;
5401 
5402 procedure TTestResolver.TestRaiseNonClassFail;
5403 begin
5404   StartProgram(false);
5405   Add('var');
5406   Add('  E: longint;');
5407   Add('begin');
5408   Add('  raise E;');
5409   CheckResolverException('class expected, but Longint found',nXExpectedButYFound);
5410 end;
5411 
5412 procedure TTestResolver.TestRaiseDescendant;
5413 var
5414   aMarker: PSrcMarker;
5415   Elements: TFPList;
5416   ActualNewInstance: Boolean;
5417   i: Integer;
5418   El: TPasElement;
5419   Ref: TResolvedReference;
5420 begin
5421   StartProgram(false);
5422   Add([
5423   'type',
5424   '  TObject = class',
5425   '    constructor Create(Msg: string); external name ''ext'';',
5426   '  end;',
5427   '  Exception = class end;',
5428   '  EConvertError = class(Exception) end;',
5429   'function AssertConv(Msg: string = ''msg''): EConvertError;',
5430   'begin',
5431   '  Result:=EConvertError.{#ass}Create(Msg);',
5432   'end;',
5433   'begin',
5434   '  raise Exception.{#a}Create(''foo'');',
5435   '  raise EConvertError.{#b}Create(''bar'');',
5436   '  raise AssertConv(''c'');',
5437   '  raise AssertConv;',
5438   '']);
5439   ParseProgram;
5440   aMarker:=FirstSrcMarker;
5441   while aMarker<>nil do
5442     begin
5443     //writeln('TTestResolver.TestRaiseDescendant ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
5444     Elements:=FindElementsAt(aMarker);
5445     try
5446       ActualNewInstance:=false;
5447       for i:=0 to Elements.Count-1 do
5448         begin
5449         El:=TPasElement(Elements[i]);
5450         //writeln('TTestResolver.TestRaiseDescendant ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
5451         if not (El.CustomData is TResolvedReference) then continue;
5452         Ref:=TResolvedReference(El.CustomData);
5453         if not (Ref.Declaration is TPasProcedure) then continue;
5454         //writeln('TTestResolver.TestRaiseDescendant ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
5455         if (Ref.Declaration is TPasConstructor) then
5456           ActualNewInstance:=rrfNewInstance in Ref.Flags;
5457         break;
5458         end;
5459       if not ActualNewInstance then
5460         RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
5461     finally
5462       Elements.Free;
5463     end;
5464     aMarker:=aMarker^.Next;
5465     end;
5466 end;
5467 
5468 procedure TTestResolver.TestStatementsRefs;
5469 begin
5470   StartProgram(false);
5471   Add('var');
5472   Add('  {#v1}v1,{#v2}v2,{#v3}v3:longint;');
5473   Add('begin');
5474   Add('  {@v1}v1:=1;');
5475   Add('  {@v2}v2:=');
5476   Add('    {@v1}v1+');
5477   Add('    {@v1}v1*{@v1}v1');
5478   Add('    +{@v1}v1 div {@v1}v1;');
5479   Add('  {@v3}v3:=');
5480   Add('    -{@v1}v1;');
5481   Add('  repeat');
5482   Add('    {@v1}v1:=');
5483   Add('      {@v1}v1+1;');
5484   Add('  until {@v1}v1>=5;');
5485   Add('  while {@v1}v1>=0 do');
5486   Add('    {@v1}v1');
5487   Add('    :={@v1}v1-{@v2}v2;');
5488   Add('  if {@v1}v1<{@v2}v2 then');
5489   Add('    {@v3}v3:={@v1}v1');
5490   Add('  else {@v3}v3:=');
5491   Add('    {@v2}v2;');
5492   ParseProgram;
5493   AssertEquals('3 declarations',3,PasProgram.ProgramSection.Declarations.Count);
5494 end;
5495 
5496 procedure TTestResolver.TestRepeatUntilNonBoolFail;
5497 begin
5498   StartProgram(false);
5499   Add('begin');
5500   Add('  repeat');
5501   Add('  until 3;');
5502   CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
5503 end;
5504 
5505 procedure TTestResolver.TestWhileDoNonBoolFail;
5506 begin
5507   StartProgram(false);
5508   Add('begin');
5509   Add('  while 3 do ;');
5510   CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
5511 end;
5512 
5513 procedure TTestResolver.TestIfThen;
5514 begin
5515   StartProgram(false);
5516   Add([
5517   'var b: boolean;',
5518   'begin',
5519   '  if b then ;',
5520   '  if b then else ;']);
5521   ParseProgram;
5522 end;
5523 
5524 procedure TTestResolver.TestIfThenNonBoolFail;
5525 begin
5526   StartProgram(false);
5527   Add('begin');
5528   Add('  if 3 then ;');
5529   CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
5530 end;
5531 
5532 procedure TTestResolver.TestIfAssignMissingSemicolonFail;
5533 begin
5534   StartProgram(false);
5535   Add([
5536   'var',
5537   '  v:longint;',
5538   'begin',
5539   '  if true then v:=1',
5540   '  v:=2']);
5541   CheckParserException('Expected "Semicolon"',nParserExpectTokenError);
5542 end;
5543 
5544 procedure TTestResolver.TestForLoopVarNonVarFail;
5545 begin
5546   StartProgram(false);
5547   Add('const i = 3;');
5548   Add('begin');
5549   Add('  for i:=1 to 2 do ;');
5550   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
5551 end;
5552 
5553 procedure TTestResolver.TestForLoopStartIncompFail;
5554 begin
5555   StartProgram(false);
5556   Add('var i: char;');
5557   Add('begin');
5558   Add('  for i:=1 to 2 do ;');
5559   CheckResolverException('Incompatible types: got "Longint" expected "Char"',
5560     nIncompatibleTypesGotExpected);
5561 end;
5562 
5563 procedure TTestResolver.TestForLoopEndIncompFail;
5564 begin
5565   StartProgram(false);
5566   Add('var i: longint;');
5567   Add('begin');
5568   Add('  for i:=1 to ''2'' do ;');
5569   CheckResolverException('Incompatible types: got "Char" expected "Longint"',
5570     nIncompatibleTypesGotExpected);
5571 end;
5572 
5573 procedure TTestResolver.TestSimpleStatement_VarFail;
5574 begin
5575   StartProgram(false);
5576   Add('var i: longint;');
5577   Add('begin');
5578   Add('  i;');
5579   CheckResolverException('Illegal expression',nIllegalExpression);
5580 end;
5581 
5582 procedure TTestResolver.TestLabelStatementFail;
5583 begin
5584   StartProgram(false);
5585   Add('var i: longint;');
5586   Add('begin');
5587   Add('  i: i;');
5588   CheckParserException('Expected ";"',nParserExpectTokenError);
5589 end;
5590 
5591 procedure TTestResolver.TestLabelStatementDelphiFail;
5592 begin
5593   StartProgram(false);
5594   Add('{$mode delphi}');
5595   Add('{$goto off}');
5596   Add('var i: longint;');
5597   Add('begin');
5598   Add('  i: i;');
5599   CheckParserException('Expected ";"',nParserExpectTokenError);
5600 end;
5601 
5602 procedure TTestResolver.TestUnitForwardOverloads;
5603 begin
5604   StartUnit(false);
5605   Add([
5606   'interface',
5607   'procedure {#ADecl}DoIt(vI: longint);',
5608   'procedure {#BDecl}DoIt(vI, vJ: longint);',
5609   'implementation',
5610   'procedure {#EDecl}DoIt(vI, vJ, vK, vL, vM: longint); forward;',
5611   'procedure {#C}DoIt(vI, vJ, vK: longint); begin end;',
5612   'procedure {#AImpl}DoIt(vi: longint); begin end;',
5613   'procedure {#D}DoIt(vI, vJ, vK, vL: longint); begin end;',
5614   'procedure {#BImpl}DoIt(vi, vj: longint); begin end;',
5615   'procedure {#EImpl}DoIt(vi, vj, vk, vl, vm: longint); begin end;',
5616   'begin',
5617   '  {@ADecl}DoIt(1);',
5618   '  {@BDecl}DoIt(2,3);',
5619   '  {@C}DoIt(4,5,6);',
5620   '  {@D}DoIt(7,8,9,10);',
5621   '  {@EDecl}DoIt(11,12,13,14,15);']);
5622   ParseUnit;
5623 end;
5624 
5625 procedure TTestResolver.TestUnitIntfInitialization;
5626 var
5627   El, DeclEl, OtherUnit: TPasElement;
5628   LocalVar: TPasVariable;
5629   Assign1, Assign2, Assign3: TPasImplAssign;
5630   Prim1, Prim2: TPrimitiveExpr;
5631   BinExp: TBinaryExpr;
5632 begin
5633   StartUnit(true);
5634   Add('interface');
5635   Add('var exitCOde: string;');
5636   Add('implementation');
5637   Add('initialization');
5638   Add('  ExitcodE:=''1'';');
5639   Add('  afile.eXitCode:=''2'';');
5640   Add('  System.exiTCode:=3;');
5641   ParseUnit;
5642 
5643   // interface
5644   AssertEquals('1 intf declaration',1,Module.InterfaceSection.Declarations.Count);
5645   El:=TPasElement(Module.InterfaceSection.Declarations[0]);
5646   AssertEquals('local var',TPasVariable,El.ClassType);
5647   LocalVar:=TPasVariable(El);
5648   AssertEquals('local var exitcode','exitCOde',LocalVar.Name);
5649 
5650   // initialization
5651   AssertEquals('3 initialization statements',3,Module.InitializationSection.Elements.Count);
5652 
5653   // check direct assignment to local var
5654   El:=TPasElement(Module.InitializationSection.Elements[0]);
5655   AssertEquals('direct assign',TPasImplAssign,El.ClassType);
5656   Assign1:=TPasImplAssign(El);
5657   AssertEquals('direct assign left',TPrimitiveExpr,Assign1.left.ClassType);
5658   Prim1:=TPrimitiveExpr(Assign1.left);
5659   AssertNotNull(Prim1.CustomData);
5660   AssertEquals('direct assign left ref',TResolvedReference,Prim1.CustomData.ClassType);
5661   DeclEl:=TResolvedReference(Prim1.CustomData).Declaration;
5662   AssertSame('direct assign local var',LocalVar,DeclEl);
5663 
5664   // check indirect assignment to local var: "afile.eXitCode"
5665   El:=TPasElement(Module.InitializationSection.Elements[1]);
5666   AssertEquals('indirect assign',TPasImplAssign,El.ClassType);
5667   Assign2:=TPasImplAssign(El);
5668   AssertEquals('indirect assign left',TBinaryExpr,Assign2.left.ClassType);
5669   BinExp:=TBinaryExpr(Assign2.left);
5670   AssertEquals('indirect assign first token',TPrimitiveExpr,BinExp.left.ClassType);
5671   Prim1:=TPrimitiveExpr(BinExp.left);
5672   AssertEquals('indirect assign first token','afile',Prim1.Value);
5673   AssertNotNull(Prim1.CustomData);
5674   AssertEquals('indirect assign unit ref resolved',TResolvedReference,Prim1.CustomData.ClassType);
5675   DeclEl:=TResolvedReference(Prim1.CustomData).Declaration;
5676   AssertSame('indirect assign unit ref',Module,DeclEl);
5677 
5678   AssertEquals('indirect assign dot',eopSubIdent,BinExp.OpCode);
5679 
5680   AssertEquals('indirect assign second token',TPrimitiveExpr,BinExp.right.ClassType);
5681   Prim2:=TPrimitiveExpr(BinExp.right);
5682   AssertEquals('indirect assign second token','eXitCode',Prim2.Value);
5683   AssertNotNull(Prim2.CustomData);
5684   AssertEquals('indirect assign var ref resolved',TResolvedReference,Prim2.CustomData.ClassType);
5685   AssertEquals('indirect assign left ref',TResolvedReference,Prim2.CustomData.ClassType);
5686   DeclEl:=TResolvedReference(Prim2.CustomData).Declaration;
5687   AssertSame('indirect assign local var',LocalVar,DeclEl);
5688 
5689   // check assignment to "system.ExitCode"
5690   El:=TPasElement(Module.InitializationSection.Elements[2]);
5691   AssertEquals('other unit assign',TPasImplAssign,El.ClassType);
5692   Assign3:=TPasImplAssign(El);
5693   AssertEquals('other unit assign left',TBinaryExpr,Assign3.left.ClassType);
5694   BinExp:=TBinaryExpr(Assign3.left);
5695   AssertEquals('othe unit assign first token',TPrimitiveExpr,BinExp.left.ClassType);
5696   Prim1:=TPrimitiveExpr(BinExp.left);
5697   AssertEquals('other unit assign first token','System',Prim1.Value);
5698   AssertNotNull(Prim1.CustomData);
5699   AssertEquals('other unit assign unit ref resolved',TResolvedReference,Prim1.CustomData.ClassType);
5700   DeclEl:=TResolvedReference(Prim1.CustomData).Declaration;
5701   OtherUnit:=DeclEl;
5702   AssertEquals('other unit assign unit ref',TPasUsesUnit,DeclEl.ClassType);
5703   AssertEquals('other unit assign unit ref system','system',lowercase(DeclEl.Name));
5704 
5705   AssertEquals('other unit assign dot',eopSubIdent,BinExp.OpCode);
5706 
5707   AssertEquals('other unit assign second token',TPrimitiveExpr,BinExp.right.ClassType);
5708   Prim2:=TPrimitiveExpr(BinExp.right);
5709   AssertEquals('other unit assign second token','exiTCode',Prim2.Value);
5710   AssertNotNull(Prim2.CustomData);
5711   AssertEquals('other unit assign var ref resolved',TResolvedReference,Prim2.CustomData.ClassType);
5712   AssertEquals('other unit assign left ref',TResolvedReference,Prim2.CustomData.ClassType);
5713   DeclEl:=TResolvedReference(Prim2.CustomData).Declaration;
5714   AssertEquals('other unit assign var',TPasVariable,DeclEl.ClassType);
5715   AssertEquals('other unit assign var exitcode','exitcode',lowercase(DeclEl.Name));
5716   AssertSame('other unit assign var exitcode',(OtherUnit as TPasUsesUnit).Module,DeclEl.GetModule);
5717 end;
5718 
5719 procedure TTestResolver.TestUnitUseSystem;
5720 begin
5721   StartProgram(true);
5722   Add('type number = system.integer;');
5723   Add('begin');
5724   Add('  if ExitCode=2 then ;');
5725   ParseProgram;
5726 end;
5727 
5728 procedure TTestResolver.TestUnitUseIntf;
5729 begin
5730   AddModuleWithIntfImplSrc('unit2.pp',
5731     LinesToStr([
5732     'type TListCallBack = procedure;',
5733     'var i: longint;',
5734     'procedure DoIt;',
5735     '']),
5736     LinesToStr([
5737     'procedure DoIt; begin end;']));
5738 
5739   StartProgram(true);
5740   Add('uses unit2;');
5741   Add('type TListCB = unit2.tlistcallback;');
5742   Add('begin');
5743   Add('  if i=2 then');
5744   Add('    DoIt;');
5745   ParseProgram;
5746 end;
5747 
5748 procedure TTestResolver.TestUnitUseImplFail;
5749 begin
5750   AddModuleWithIntfImplSrc('unit2.pp',
5751     LinesToStr([
5752     '']),
5753     LinesToStr([
5754     'procedure DoIt; begin end;']));
5755 
5756   StartProgram(true);
5757   Add('uses unit2;');
5758   Add('begin');
5759   Add('  DoIt;');
5760   CheckResolverException('identifier not found "DoIt"',nIdentifierNotFound);
5761 end;
5762 
5763 procedure TTestResolver.TestUnit_DuplicateUsesFail;
5764 begin
5765   AddModuleWithIntfImplSrc('unit2.pp',
5766     LinesToStr([
5767     'var i: longint;']),
5768     LinesToStr([
5769     '']));
5770 
5771   StartProgram(true);
5772   Add('uses unit2, unit2;');
5773   Add('begin');
5774   Add('  i:=3;');
5775   CheckParserException('Duplicate identifier "unit2"',
5776     nParserDuplicateIdentifier);
5777 end;
5778 
5779 procedure TTestResolver.TestUnit_DuplicateUsesIntfImplFail;
5780 begin
5781   AddModuleWithIntfImplSrc('unit2.pp',
5782     LinesToStr([
5783     'type number = longint;']),
5784     LinesToStr([
5785     '']));
5786 
5787   StartUnit(true);
5788   Add([
5789   'interface',
5790   'uses unit2;',
5791   'var j: number;',
5792   'implementation',
5793   'uses unit2;',
5794   'initialization',
5795   '  if number(3) then ;',
5796   '']);
5797   CheckParserException('Duplicate identifier "unit2" at token ";" in file afile.pp at line 6 column 11',
5798     nParserDuplicateIdentifier);
5799 end;
5800 
5801 procedure TTestResolver.TestUnit_NestedFail;
5802 begin
5803   AddModuleWithIntfImplSrc('unit2.pp',
5804     LinesToStr([
5805     'var i2: longint;']),
5806     LinesToStr([
5807     '']));
5808 
5809   AddModuleWithIntfImplSrc('unit1.pp',
5810     LinesToStr([
5811     'uses unit2;',
5812     'var j1: longint;']),
5813     LinesToStr([
5814     '']));
5815 
5816   StartProgram(true);
5817   Add([
5818   'uses unit1;',
5819   'begin',
5820   '  if j1=0 then ;',
5821   '  if i2=0 then ;',
5822   '']);
5823   CheckResolverException('identifier not found "i2"',nIdentifierNotFound);
5824 end;
5825 
5826 procedure TTestResolver.TestUnitUseDotted;
5827 begin
5828   AddModuleWithIntfImplSrc('ns1.unit2.pp',
5829     LinesToStr([
5830     'var i2: longint;']),
5831     LinesToStr([
5832     '']));
5833 
5834   AddModuleWithIntfImplSrc('ns2.ns2A.unit1.pp',
5835     LinesToStr([
5836     'uses ns1.unit2;',
5837     'var j1: longint;']),
5838     LinesToStr([
5839     '']));
5840 
5841   StartProgram(true);
5842   Add([
5843   'uses ns2.ns2A.unit1;',
5844   'begin',
5845   '  if j1=0 then ;',
5846   '']);
5847   ParseProgram;
5848 end;
5849 
5850 procedure TTestResolver.TestUnit_ProgramDefaultNamespace;
5851 begin
5852   MainFilename:='ns1.main1.pas';
5853 
5854   AddModuleWithIntfImplSrc('ns1.unit2.pp',
5855     LinesToStr([
5856     'var i2: longint;']),
5857     LinesToStr([
5858     '']));
5859 
5860   AddModuleWithIntfImplSrc('ns1.unit1.pp',
5861     LinesToStr([
5862     'uses unit2;',
5863     'var j1: longint;']),
5864     LinesToStr([
5865     '']));
5866 
5867   StartProgram(true);
5868   Add([
5869   'uses unit1;',
5870   'begin',
5871   '  if j1=0 then ;',
5872   '']);
5873   ParseProgram;
5874 end;
5875 
5876 procedure TTestResolver.TestUnit_DottedIdentifier;
5877 begin
5878   MainFilename:='unitdots.main1.pas';
5879 
5880   AddModuleWithIntfImplSrc('unitdots.unit1.pp',
5881     LinesToStr([
5882     'type TColor = longint;',
5883     'var i1: longint;']),
5884     LinesToStr([
5885     '']));
5886 
5887   AddModuleWithIntfImplSrc('unitdots.pp',
5888     LinesToStr([
5889     'type TBright = longint;',
5890     'var j1: longint;']),
5891     LinesToStr([
5892     '']));
5893 
5894   StartProgram(true);
5895   Add([
5896   'uses unitdots.unit1, unitdots;',
5897   'type',
5898   '  TPrgBright = unitdots.tbright;',
5899   '  TPrgColor = unitdots.unit1.tcolor;',
5900   '  TStrange = unitdots.main1.tprgcolor;',
5901   'var k1: longint;',
5902   'begin',
5903   '  if unitdots.main1.k1=0 then ;',
5904   '  if unitdots.j1=0 then ;',
5905   '  if unitdots.unit1.i1=0 then ;',
5906   '']);
5907   ParseProgram;
5908 end;
5909 
5910 procedure TTestResolver.TestUnit_DottedPrg;
5911 begin
5912   MainFilename:='unitdots.main1.pas';
5913 
5914   AddModuleWithIntfImplSrc('unitdots.unit1.pp',
5915     LinesToStr([
5916     'type TColor = longint;',
5917     'var i1: longint;']),
5918     LinesToStr([
5919     '']));
5920 
5921   StartProgram(true);
5922   Add([
5923   'uses UnIt1;',
5924   'type',
5925   '  TPrgColor = UNIT1.tcolor;',
5926   '  TStrange = UnitDots.Main1.tprgcolor;',
5927   'var k1: longint;',
5928   'begin',
5929   '  if unitdots.main1.k1=0 then ;',
5930   '  if unit1.i1=0 then ;',
5931   '']);
5932   ParseProgram;
5933 end;
5934 
5935 procedure TTestResolver.TestUnit_DottedUnit;
5936 begin
5937   MainFilename:='unitdots.unit1.pas';
5938   StartUnit(false);
5939   Add([
5940   'interface',
5941   'var k1: longint;',
5942   'implementation',
5943   'initialization',
5944   '  if unitDots.Unit1.k1=0 then ;',
5945   '']);
5946   ParseUnit;
5947 end;
5948 
5949 procedure TTestResolver.TestUnit_DottedExpr;
5950 begin
5951   MainFilename:='unitdots1.sub1.main1.pas';
5952 
5953   AddModuleWithIntfImplSrc('unitdots2.sub2.unit2.pp',
5954     LinesToStr([
5955     'procedure DoIt; external name ''$DoIt'';']),
5956     LinesToStr([
5957     '']));
5958 
5959   AddModuleWithIntfImplSrc('unitdots3.sub3.unit3.pp',
5960     LinesToStr([
5961     'procedure DoSome;']),
5962     LinesToStr([
5963     'uses unitdots2.sub2.unit2;',
5964     'procedure DoSome;',
5965     'begin',
5966     '  unitdots2.sub2.unit2.doit;',
5967     'end;']));
5968 
5969   StartProgram(true);
5970   Add([
5971   'uses unitdots3.sub3.unit3;',
5972   'begin',
5973   '  unitdots3.sub3.unit3.dosome;',
5974   '']);
5975   ParseProgram;
5976 end;
5977 
5978 procedure TTestResolver.TestUnit_DuplicateDottedUsesFail;
5979 begin
5980   AddModuleWithIntfImplSrc('ns.unit2.pp',
5981     LinesToStr([
5982     'var i: longint;']),
5983     LinesToStr([
5984     '']));
5985 
5986   StartProgram(true);
5987   Add('uses ns.unit2, ns.unit2;');
5988   Add('begin');
5989   Add('  i:=3;');
5990   CheckParserException('Duplicate identifier "ns.unit2"',
5991     nParserDuplicateIdentifier);
5992 end;
5993 
5994 procedure TTestResolver.TestUnit_DuplicateUsesDiffName;
5995 begin
5996   MainFilename:='unitdots.main1.pas';
5997   AddModuleWithIntfImplSrc('unitdots.unit1.pp',
5998     LinesToStr([
5999     'var j1: longint;']),
6000     LinesToStr([
6001     '']));
6002 
6003   StartProgram(true);
6004   Add([
6005   'uses unitdots.unit1, unit1;',
6006   'var k1: longint;',
6007   'begin',
6008   '  if unitdots.main1.k1=0 then ;',
6009   '  if unit1.j1=0 then ;',
6010   '  if unitdots.unit1.j1=0 then ;',
6011   '']);
6012   ParseProgram;
6013 end;
6014 
6015 procedure TTestResolver.TestUnit_Unit1DotUnit2Fail;
6016 begin
6017   AddModuleWithIntfImplSrc('unit1.pp',
6018     LinesToStr([
6019     'var i1: longint;']),
6020     LinesToStr([
6021     '']));
6022 
6023   AddModuleWithIntfImplSrc('unit2.pp',
6024     LinesToStr([
6025     'uses unit1;',
6026     'var j1: longint;']),
6027     LinesToStr([
6028     '']));
6029 
6030   StartProgram(true);
6031   Add([
6032   'uses unit2;',
6033   'begin',
6034   '  if unit2.unit1.i1=0 then ;',
6035   '']);
6036   CheckResolverException('identifier not found "unit1"',
6037     nIdentifierNotFound);
6038 end;
6039 
6040 procedure TTestResolver.TestUnit_InFilename;
6041 begin
6042   AddModuleWithIntfImplSrc('unit2.pp',
6043     LinesToStr([
6044     'var i1: longint;']),
6045     LinesToStr([
6046     '']));
6047 
6048   StartProgram(true);
6049   Add([
6050   'uses foo in ''unit2.pp'';',
6051   'begin',
6052   '  if foo.i1=0 then ;',
6053   '']);
6054   ParseProgram;
6055 end;
6056 
6057 procedure TTestResolver.TestUnit_InFilenameAliasDelphiFail;
6058 begin
6059   AddModuleWithIntfImplSrc('unit2.pp',
6060     LinesToStr([
6061     'var i1: longint;']),
6062     LinesToStr([
6063     '']));
6064 
6065   StartProgram(true);
6066   Add([
6067   '{$mode delphi}',
6068   'uses foo in ''unit2.pp'';',
6069   'begin',
6070   '  if foo.i1=0 then ;',
6071   '']);
6072   CheckResolverException('foo expected, but unit2 found',nXExpectedButYFound);
6073 end;
6074 
6075 procedure TTestResolver.TestUnit_InFilenameInUnitDelphiFail;
6076 begin
6077   AddModuleWithIntfImplSrc('unit2.pp',
6078     LinesToStr([
6079     'var i1: longint;']),
6080     LinesToStr([
6081     '']));
6082 
6083   StartUnit(true);
6084   Add([
6085   '{$mode delphi}',
6086   'interface',
6087   'uses unit2 in ''unit2.pp'';',
6088   'implementation',
6089   '']);
6090   CheckParserException('Expected ";"',nParserExpectTokenError);
6091 end;
6092 
6093 procedure TTestResolver.TestUnit_MissingUnitErrorPos;
6094 begin
6095   AddModuleWithIntfImplSrc('unit2.pp',
6096     LinesToStr([
6097     'var j1: longint;']),
6098     LinesToStr([
6099     '']));
6100   StartProgram(true);
6101   Add([
6102   'uses unit2, ;',
6103   'begin']);
6104   CheckParserException('Expected "Identifier" at token ";" in file afile.pp at line 2 column 13',
6105     nParserExpectTokenError);
6106 end;
6107 
6108 procedure TTestResolver.TestUnit_UnitNotFoundErrorPos;
6109 begin
6110   StartProgram(true);
6111   Add([
6112   'uses foo   ;',
6113   'begin']);
6114   CheckResolverException('can''t find unit "foo" at afile.pp (2,6)',nCantFindUnitX);
6115 end;
6116 
6117 procedure TTestResolver.TestUnit_AccessIndirectUsedUnitFail;
6118 begin
6119   AddModuleWithIntfImplSrc('unit2.pp',
6120     LinesToStr([
6121     'var i2: longint;']),
6122     LinesToStr([
6123     '']));
6124 
6125   AddModuleWithIntfImplSrc('unit1.pp',
6126     LinesToStr([
6127     'uses unit2;']),
6128     LinesToStr([
6129     '']));
6130 
6131   StartProgram(true);
6132   Add([
6133   'uses unit1;',
6134   'begin',
6135   '  if unit2.i2=0 then ;',
6136   '']);
6137   CheckResolverException('identifier not found "unit2"',nIdentifierNotFound);
6138 end;
6139 
6140 procedure TTestResolver.TestUnit_Intf1Impl2Intf1;
6141 begin
6142   AddModuleWithIntfImplSrc('unit1.pp',
6143     LinesToStr([
6144     'type number = longint;']),
6145     LinesToStr([
6146     'uses afile;',
6147     'procedure DoIt;',
6148     'begin',
6149     '  i:=3;',
6150     'end;']));
6151 
6152   StartUnit(true);
6153   Add([
6154   'interface',
6155   'uses unit1;',
6156   'var i: number;',
6157   'implementation']);
6158   ParseUnit;
6159 end;
6160 
6161 procedure TTestResolver.TestUnit_Intf1Impl2Intf1_Duplicate;
6162 begin
6163   AddModuleWithIntfImplSrc('unit1.pp',
6164     LinesToStr([
6165     'type number = longint;']),
6166     LinesToStr([
6167     'uses afile;',
6168     'procedure DoIt;',
6169     'begin',
6170     '  i:=3;',
6171     'end;']));
6172 
6173   StartUnit(true);
6174   Add([
6175   'interface',
6176   'uses unit1, foo in ''unit1.pp'';',
6177   'var i: number;',
6178   'implementation']);
6179   ParseUnit;
6180 end;
6181 
6182 procedure TTestResolver.TestProcParam;
6183 begin
6184   StartProgram(false);
6185   Add('type');
6186   Add('  integer = longint;');
6187   Add('procedure Proc1(a: integer);');
6188   Add('begin');
6189   Add('  a:=3;');
6190   Add('end;');
6191   Add('begin');
6192   ParseProgram;
6193 end;
6194 
6195 procedure TTestResolver.TestProcParamAccess;
6196 begin
6197   StartProgram(false);
6198   Add('type');
6199   Add('  integer = longint;');
6200   Add('procedure DoIt(vI: integer; const vJ: integer; var vK: integer);');
6201   Add('var vL: integer;');
6202   Add('begin');
6203   Add('  vi:=vi+1;');
6204   Add('  vl:=vj+1;');
6205   Add('  vk:=vk+1;');
6206   Add('  vl:=vl+1;');
6207   Add('  DoIt(vi,vi,vi);');
6208   Add('  DoIt(vj,vj,vl);');
6209   Add('  DoIt(vk,vk,vk);');
6210   Add('  DoIt(vl,vl,vl);');
6211   Add('end;');
6212   Add('var i: integer;');
6213   Add('begin');
6214   Add('  DoIt(i,i,i);');
6215   Add('  DoIt(1,1,i);');
6216   ParseProgram;
6217 end;
6218 
6219 procedure TTestResolver.TestProcParamConstRef;
6220 begin
6221   StartProgram(false);
6222   Add([
6223   'procedure Run(constref a: word);',
6224   'begin',
6225   'end;',
6226   'begin']);
6227   ParseProgram;
6228 end;
6229 
6230 procedure TTestResolver.TestFunctionResult;
6231 begin
6232   StartProgram(false);
6233   Add('function Func1: longint;');
6234   Add('begin');
6235   Add('  Result:=3;');
6236   Add('  Func1:=4; ');
6237   Add('end;');
6238   Add('begin');
6239   ParseProgram;
6240 end;
6241 
6242 procedure TTestResolver.TestProcedureResultFail;
6243 begin
6244   StartProgram(false);
6245   Add('procedure A: longint; begin end;');
6246   Add('begin');
6247   CheckParserException('Expected ";"',
6248     nParserExpectTokenError);
6249 end;
6250 
6251 procedure TTestResolver.TestProc_ArgVarPrecisionLossFail;
6252 begin
6253   StartProgram(false);
6254   Add([
6255   'type',
6256   '  TColor = type longint;',
6257   '  TByte = byte;',
6258   'procedure DoColor(var c: TColor); external;',
6259   'var',
6260   '  b: TByte;',
6261   'begin',
6262   '  DoColor(TColor(b));',
6263   '']);
6264   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
6265 end;
6266 
6267 procedure TTestResolver.TestProc_ArgVarTypeAliasObjFPC;
6268 begin
6269   StartProgram(false);
6270   Add([
6271   'type',
6272   '  TColor = type longint;',
6273   'procedure DoColor(var c: TColor); external;',
6274   'procedure TakeColor(c: TColor); external;',
6275   'procedure DoInt(var i: longint); external;',
6276   'var',
6277   '  i: longint;',
6278   '  c: TColor;',
6279   'begin',
6280   '  DoColor(c);',
6281   '  DoColor(longint(c));',
6282   '  DoColor(i);',
6283   '  DoColor(TColor(i));',
6284   '  TakeColor(c);',
6285   '  TakeColor(longint(c));',
6286   '  TakeColor(i);',
6287   '  TakeColor(TColor(i));',
6288   '  DoInt(i);',
6289   '  DoInt(TColor(i));',
6290   '  DoInt(c);',
6291   '  DoInt(longint(c));',
6292   '']);
6293   ParseProgram;
6294 end;
6295 
6296 procedure TTestResolver.TestProc_ArgVarTypeAliasDelphi;
6297 begin
6298   StartProgram(false);
6299   Add([
6300   '{$mode delphi}',
6301   'type',
6302   '  TColor = type longint;',
6303   'procedure DoColor(var c: TColor); external;',
6304   'procedure TakeColor(c: TColor); external;',
6305   'procedure DoInt(var i: longint); external;',
6306   'var',
6307   '  i: longint;',
6308   '  c: TColor;',
6309   'begin',
6310   '  DoColor(c);',
6311   '  DoColor(TColor(i));',
6312   '  TakeColor(i);',
6313   '  TakeColor(longint(c));',
6314   '  DoInt(i);',
6315   '  DoInt(longint(c));',
6316   '']);
6317   ParseProgram;
6318 end;
6319 
6320 procedure TTestResolver.TestProc_ArgVarTypeAliasDelphiMismatchFail;
6321 begin
6322   StartProgram(false);
6323   Add([
6324   '{$mode delphi}',
6325   'type',
6326   '  TColor = type longint;',
6327   'procedure DoColor(var c: TColor); external;',
6328   'var',
6329   '  i: longint;',
6330   'begin',
6331   '  DoColor(i);',
6332   '']);
6333   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "TColor". Var param must match exactly.',
6334     nIncompatibleTypeArgNoVarParamMustMatchExactly);
6335 end;
6336 
6337 procedure TTestResolver.TestProc_ArgMissingSemicolonFail;
6338 begin
6339   StartProgram(false);
6340   Add([
6341   'type TScalar = double;',
6342   'procedure SinCos (var sinus: TScalar var cosinus: TScalar);',
6343   'begin end;',
6344   'begin']);
6345   CheckParserException('Expected ";" at token "var" in file afile.pp at line 3 column 38',nParserExpectTokenError);
6346 end;
6347 
6348 procedure TTestResolver.TestProcOverload;
6349 var
6350   El: TPasElement;
6351 begin
6352   StartProgram(false);
6353   Add('function Func1(i: longint; j: longint = 0): longint; overload;');
6354   Add('begin');
6355   Add('  Result:=1;');
6356   Add('end;');
6357   Add('function Func1(s: string): longint; overload;');
6358   Add('begin');
6359   Add('  Result:=2;');
6360   Add('end;');
6361   Add('begin');
6362   Add('  Func1(3);');
6363   ParseProgram;
6364   AssertEquals('2 declarations',2,PasProgram.ProgramSection.Declarations.Count);
6365 
6366   El:=TPasElement(PasProgram.ProgramSection.Declarations[0]);
El.ClassTypenull6367   AssertEquals('is function',TPasFunction,El.ClassType);
6368 
6369   AssertEquals('1 statement',1,PasProgram.InitializationSection.Elements.Count);
6370 end;
6371 
6372 procedure TTestResolver.TestProcOverloadImplDuplicateFail;
6373 begin
6374   StartUnit(false);
6375   Add([
6376   'interface',
6377   'procedure DoIt(d: double);',
6378   'implementation',
6379   'procedure DoIt(d: double); begin end;',
6380   'procedure DoIt(d: double); begin end;',
6381   'end.']);
6382   CheckResolverException('Duplicate identifier "DoIt" at afile.pp(5,15)',nDuplicateIdentifier);
6383 end;
6384 
6385 procedure TTestResolver.TestProcOverloadImplDuplicate2Fail;
6386 begin
6387   StartUnit(false);
6388   Add([
6389   'interface',
6390   'implementation',
6391   'procedure DoIt(d: double); begin end;',
6392   'procedure DoIt(d: double); begin end;',
6393   'end.']);
6394   CheckResolverException('Duplicate identifier "DoIt" at afile.pp(4,15)',nDuplicateIdentifier);
6395 end;
6396 
6397 procedure TTestResolver.TestProcOverloadOtherUnit;
6398 begin
6399   AddModuleWithIntfImplSrc('unit1.pp',
6400     LinesToStr([
6401     'procedure DoIt(d: double);',
6402     '']),
6403     LinesToStr([
6404     'procedure DoIt(d: double); begin end;',
6405     '']));
6406 
6407   StartUnit(true);
6408   Add([
6409   'interface',
6410   'implementation',
6411   'procedure DoIt(d: double); begin end;',
6412   'end.']);
6413   ParseUnit;
6414 end;
6415 
6416 procedure TTestResolver.TestProcOverloadWithBaseTypes;
6417 begin
6418   StartProgram(false);
6419   Add('function {#A}Func1(i: longint; j: longint = 0): longint; overload;');
6420   Add('begin');
6421   Add('  Result:=1;');
6422   Add('end;');
6423   Add('function {#B}Func1(s: string): longint; overload;');
6424   Add('begin');
6425   Add('  Result:=2;');
6426   Add('end;');
6427   Add('begin');
6428   Add('  {@A}Func1(3);');
6429   ParseProgram;
6430 end;
6431 
6432 procedure TTestResolver.TestProcOverloadWithBaseTypes2;
6433 begin
6434   StartProgram(false);
6435   Add('procedure {#byte}DoIt(p: byte); external;  var by: byte;');
6436   Add('procedure {#shortint}DoIt(p: shortint); external;  var shi: shortint;');
6437   Add('procedure {#word}DoIt(p: word); external;  var w: word;');
6438   Add('procedure {#smallint}DoIt(p: smallint); external;  var smi: smallint;');
6439   Add('procedure {#longword}DoIt(p: longword); external;  var lw: longword;');
6440   Add('procedure {#longint}DoIt(p: longint); external;  var li: longint;');
6441   Add('procedure {#qword}DoIt(p: qword); external;  var qw: qword;');
6442   Add('procedure {#int64}DoIt(p: int64); external;  var i6: int64;');
6443   Add('procedure {#comp}DoIt(p: comp); external;  var co: comp;');
6444   Add('procedure {#boolean}DoIt(p: boolean); external;  var bo: boolean;');
6445   Add('procedure {#char}DoIt(p: char); external;  var ch: char;');
6446   Add('procedure {#widechar}DoIt(p: widechar); external;  var wc: widechar;');
6447   Add('procedure {#string}DoIt(p: string); external;  var st: string;');
6448   Add('procedure {#widestring}DoIt(p: widestring); external;  var ws: widestring;');
6449   Add('procedure {#shortstring}DoIt(p: shortstring); external;  var ss: shortstring;');
6450   Add('procedure {#unicodestring}DoIt(p: unicodestring); external;  var us: unicodestring;');
6451   Add('procedure {#rawbytestring}DoIt(p: rawbytestring); external;  var rs: rawbytestring;');
6452   Add('begin');
6453   Add('  {@byte}DoIt(by);');
6454   Add('  {@shortint}DoIt(shi);');
6455   Add('  {@word}DoIt(w);');
6456   Add('  {@smallint}DoIt(smi);');
6457   Add('  {@longword}DoIt(lw);');
6458   Add('  {@longint}DoIt(li);');
6459   Add('  {@qword}DoIt(qw);');
6460   Add('  {@int64}DoIt(i6);');
6461   Add('  {@comp}DoIt(co);');
6462   Add('  {@boolean}DoIt(bo);');
6463   Add('  {@char}DoIt(ch);');
6464   Add('  {@widechar}DoIt(wc);');
6465   Add('  {@string}DoIt(st);');
6466   Add('  {@widestring}DoIt(ws);');
6467   Add('  {@shortstring}DoIt(ss);');
6468   Add('  {@unicodestring}DoIt(us);');
6469   Add('  {@rawbytestring}DoIt(rs);');
6470   ParseProgram;
6471 end;
6472 
6473 procedure TTestResolver.TestProcOverloadWithDefaultArgs;
6474 begin
6475   StartProgram(false);
6476   Add([
6477   'type float = type single;',
6478   'type integer = longint;',
6479   'procedure {#float}DoIt(s: float); external;',
6480   'procedure {#longint}DoIt(i: integer; Scale: float = 1.0); external;',
6481   'var i: integer;',
6482   'begin',
6483   '  {@float}DoIt(1.0);',
6484   '  {@longint}DoIt(2);',
6485   '  {@longint}DoIt(i);',
6486   '']);
6487   ParseProgram;
6488 end;
6489 
6490 procedure TTestResolver.TestProcOverloadNearestHigherPrecision;
6491 begin
6492   StartProgram(false);
6493   Add([
6494   'procedure {#longint}DoIt(i: longint); external;',
6495   'procedure DoIt(i: int64); external;',
6496   'var w: word;',
6497   'begin',
6498   '  {@longint}DoIt(w);',
6499   '']);
6500   ParseProgram;
6501 end;
6502 
6503 procedure TTestResolver.TestProcOverloadForLoopIntDouble;
6504 begin
6505   StartProgram(false);
6506   Add([
6507   'function {#int}Max(a,b: longint): longint; external; overload;',
6508   'function {#double}Max(a,b: double): double; external; overload;',
6509   'var',
6510   '  i: longint;',
6511   '  S: string;',
6512   'begin',
6513   '  for i:=0 to Max(length(s),1) do ;',
6514   '']);
6515   ParseProgram;
6516 end;
6517 
6518 procedure TTestResolver.TestProcOverloadStringArgCount;
6519 begin
6520   StartProgram(false);
6521   Add([
6522   'function {#a}StrToDate(const a: String): double; begin end;',
6523   'function {#b}StrToDate(const a: String; const b: string): double; begin end;',
6524   'function {#c}StrToDate(const a: String; const b: string; c: char): double; begin end;',
6525   'var d: double;',
6526   'begin',
6527   '  d:={@a}StrToDate('''');',
6528   '  d:={@b}StrToDate('''','''');',
6529   '  d:={@c}StrToDate('''','''',''x'');',
6530   '']);
6531   ParseProgram;
6532 end;
6533 
6534 procedure TTestResolver.TestProcCallLowPrecision;
6535 begin
6536   StartProgram(false);
6537   Add([
6538   'procedure {#longint}DoIt(i: longint); external;',
6539   'var i: int64;',
6540   'begin',
6541   '  {@longint}DoIt(i);',
6542   '']);
6543   ParseProgram;
6544 end;
6545 
6546 procedure TTestResolver.TestProcOverloadUntyped;
6547 begin
6548   StartProgram(false);
6549   Add([
6550   'procedure {#a}DoIt(a, b: longint); external;',
6551   'procedure {#b}DoIt(const a; b: longint); external;',
6552   'var',
6553   '  a: longint;',
6554   '  b: boolean;',
6555   'begin',
6556   '  {@a}DoIt(a,a);',
6557   '  {@b}DoIt(b,a);',
6558   '']);
6559   ParseProgram;
6560 end;
6561 
6562 procedure TTestResolver.TestProcOverloadMultiLowPrecisionFail;
6563 begin
6564   StartProgram(false);
6565   Add([
6566   'procedure DoIt(i: longint); external;',
6567   'procedure DoIt(w: longword); external;',
6568   'var i: int64;',
6569   'begin',
6570   '  DoIt(i);',
6571   '']);
6572   CheckResolverException('Can''t determine which overloaded function to call, afile.pp(3,15), afile.pp(2,15)',
6573     nCantDetermineWhichOverloadedFunctionToCall);
6574 end;
6575 
6576 procedure TTestResolver.TestProcOverload_TypeAlias;
6577 begin
6578   StartProgram(false);
6579   Add([
6580   'type',
6581   '  TValue = type longint;',
6582   '  TAliasValue = TValue;',
6583   '  TColor = type TAliasValue;',
6584   '  TAliasColor = TColor;',
6585   'procedure {#a}DoIt(i: TAliasValue); external;',
6586   'procedure {#b}DoIt(i: TAliasColor); external;',
6587   'procedure {#c}Fly(var i: TAliasValue); external;',
6588   'procedure {#d}Fly(var i: TAliasColor); external;',
6589   'var',
6590   '  v: TAliasValue;',
6591   '  c: TAliasColor;',
6592   'begin',
6593   '  {@a}DoIt(v);',
6594   '  {@a}DoIt(TAliasValue(c));',
6595   '  {@a}DoIt(TValue(c));',
6596   '  {@b}DoIt(c);',
6597   '  {@b}DoIt(TAliasColor(v));',
6598   '  {@b}DoIt(TColor(v));',
6599   '  {@c}Fly(v);',
6600   '  {@c}Fly(TAliasValue(c));',
6601   '  {@c}Fly(TValue(c));',
6602   '  {@d}Fly(c);',
6603   '  {@d}Fly(TAliasColor(v));',
6604   '  {@d}Fly(TColor(v));',
6605   '']);
6606   ParseProgram;
6607 end;
6608 
6609 procedure TTestResolver.TestProcOverload_TypeAliasLiteralFail;
6610 begin
6611   StartProgram(false);
6612   Add([
6613   'type',
6614   '  integer = word;',
6615   '  TValue = type word;',
6616   '  TAliasValue = TValue;',
6617   'procedure DoIt(i: integer); external;',
6618   'procedure DoIt(i: TAliasValue); external;',
6619   'begin',
6620   '  DoIt(1);',
6621   '']);
6622   CheckResolverException('Can''t determine which overloaded function to call, afile.pp(7,15), afile.pp(6,15)',
6623     nCantDetermineWhichOverloadedFunctionToCall);
6624 end;
6625 
6626 procedure TTestResolver.TestProcOverloadWithClassTypes;
6627 begin
6628   StartProgram(false);
6629   Add('type');
6630   Add('  {#TOBJ}TObject = class end;');
6631   Add('  {#TA}TClassA = class end;');
6632   Add('  {#TB}TClassB = class end;');
6633   Add('procedure {#DoA}DoIt({=TA}p: TClassA); overload;');
6634   Add('begin');
6635   Add('end;');
6636   Add('procedure {#DoB}DoIt({=TB}p: TClassB); overload;');
6637   Add('begin');
6638   Add('end;');
6639   Add('var');
6640   Add('  {#A}{=TA}A: TClassA;');
6641   Add('  {#B}{=TB}B: TClassB;');
6642   Add('begin');
6643   Add('  {@DoA}DoIt({@A}A);');
6644   Add('  {@DoB}DoIt({@B}B);');
6645   ParseProgram;
6646 end;
6647 
6648 procedure TTestResolver.TestProcOverloadWithInhClassTypes;
6649 begin
6650   StartProgram(false);
6651   Add('type');
6652   Add('  {#TOBJ}TObject = class end;');
6653   Add('  {#TA}TClassA = class end;');
6654   Add('  {#TB}TClassB = class(TClassA) end;');
6655   Add('  {#TC}TClassC = class(TClassB) end;');
6656   Add('procedure {#DoA}DoIt({=TA}p: TClassA); overload;');
6657   Add('begin');
6658   Add('end;');
6659   Add('procedure {#DoB}DoIt({=TB}p: TClassB); overload;');
6660   Add('begin');
6661   Add('end;');
6662   Add('var');
6663   Add('  {#A}{=TA}A: TClassA;');
6664   Add('  {#B}{=TB}B: TClassB;');
6665   Add('  {#C}{=TC}C: TClassC;');
6666   Add('begin');
6667   Add('  {@DoA}DoIt({@A}A);');
6668   Add('  {@DoB}DoIt({@B}B);');
6669   Add('  {@DoB}DoIt({@C}C);');
6670   ParseProgram;
6671 end;
6672 
6673 procedure TTestResolver.TestProcOverloadWithInhAliasClassTypes;
6674 begin
6675   StartProgram(false);
6676   Add([
6677   'type',
6678   '  {#TOBJ}TObject = class end;',
6679   '  {#TA}TClassA = class end;',
6680   '  {#TB}{=TA}TClassB = TClassA;',
6681   '  {#TC}TClassC = class(TClassB) end;',
6682   'procedure {#DoA}DoIt({=TA}p: TClassA); overload;',
6683   'begin',
6684   'end;',
6685   'procedure {#DoC}DoIt({=TC}p: TClassC); overload;',
6686   'begin',
6687   'end;',
6688   'var',
6689   '  {#A}{=TA}A: TClassA;',
6690   '  {#B}{=TB}B: TClassB;',
6691   '  {#C}{=TC}C: TClassC;',
6692   'begin',
6693   '  {@DoA}DoIt({@A}A);',
6694   '  {@DoA}DoIt({@B}B);',
6695   '  {@DoC}DoIt({@C}C);']);
6696   ParseProgram;
6697 end;
6698 
6699 procedure TTestResolver.TestProcOverloadWithInterfaces;
6700 begin
6701   StartProgram(false);
6702   Add([
6703   '{$interfaces corba}',
6704   'type',
6705   '  {#IUnk}IUnknown = interface end;',
6706   '  {#IBird}IBird = interface(IUnknown) end;',
6707   '  {#TObj}TObject = class end;',
6708   '  {#TBird}TBird = class(IBird) end;',
6709   'procedure {#DoA}DoIt(o: TObject); overload; begin end;',
6710   'procedure {#DoB}DoIt(b: IBird); overload; begin end;',
6711   'var',
6712   '  o: TObject;',
6713   '  b: TBird;',
6714   '  i: IBird;',
6715   'begin',
6716   '  {@DoA}DoIt(o);',
6717   '  {@DoA}DoIt(b);',
6718   '  {@DoB}DoIt(i);',
6719   '']);
6720   ParseProgram;
6721 end;
6722 
6723 procedure TTestResolver.TestProcOverloadBaseTypeOtherUnit;
6724 begin
6725   AddModuleWithIntfImplSrc('unit2.pp',
6726     LinesToStr([
6727     'procedure Val(var d: double);',
6728     '']),
6729     LinesToStr([
6730     'procedure Val(var d: double); begin end;',
6731     'procedure Val(var i: integer); begin end;',
6732     '']));
6733 
6734   StartProgram(true);
6735   Add('uses unit2;');
6736   Add('var');
6737   Add('  d: double;');
6738   Add('  i: integer;');
6739   Add('begin');
6740   Add('  Val(d);');
6741   ParseProgram;
6742 end;
6743 
6744 procedure TTestResolver.TestProcOverloadBaseProcNoHint;
6745 begin
6746   StartProgram(false);
6747   Add([
6748   'function Copy(s: string): string; overload;',
6749   'begin end;',
6750   'var',
6751   '  A: array of longint;',
6752   '  s: string;',
6753   'begin',
6754   '  A:=Copy(A,1);',
6755   '  s:=copy(s)']);
6756   ParseProgram;
6757   CheckResolverUnexpectedHints;
6758 end;
6759 
6760 procedure TTestResolver.TestProcOverload_UnitOrderFail;
6761 begin
6762   AddModuleWithIntfImplSrc('unit1.pp',
6763     LinesToStr([
6764     'procedure Val(d: string);',
6765     '']),
6766     LinesToStr([
6767     'procedure Val(d: string); begin end;',
6768     '']));
6769   AddModuleWithIntfImplSrc('unit2.pp',
6770     LinesToStr([
6771     'procedure Val(d: double);',
6772     '']),
6773     LinesToStr([
6774     'procedure Val(d: double); begin end;',
6775     '']));
6776 
6777   StartProgram(true);
6778   Add([
6779   'uses unit1, unit2;',
6780   'var',
6781   '  s: string;',
6782   'begin',
6783   '  Val(s);']);
6784   CheckResolverException(sIncompatibleTypeArgNo,nIncompatibleTypeArgNo);
6785 end;
6786 
6787 procedure TTestResolver.TestProcOverload_UnitSameSignature;
6788 begin
6789   AddModuleWithIntfImplSrc('unit1.pp',
6790     LinesToStr([
6791     'procedure Val(d: string);',
6792     '']),
6793     LinesToStr([
6794     'procedure Val(d: string); begin end;',
6795     '']));
6796   StartProgram(true);
6797   Add([
6798   'uses unit1;',
6799   'procedure Val(d: string);',
6800   'begin',
6801   'end;',
6802   'var',
6803   '  s: string;',
6804   'begin',
6805   '  Val(s);']);
6806   ParseProgram;
6807 end;
6808 
6809 procedure TTestResolver.TestProcOverloadDelphiMissingNextOverload;
6810 begin
6811   StartProgram(false);
6812   Add([
6813   '{$mode delphi}',
6814   'procedure DoIt(i: longint); overload;',
6815   'begin end;',
6816   'procedure DoIt(s: string);',
6817   'begin end;',
6818   'begin']);
6819   CheckResolverException(sOverloadedProcMissesOverload,nOverloadedProcMissesOverload);
6820 end;
6821 
6822 procedure TTestResolver.TestProcOverloadDelphiMissingPrevOverload;
6823 begin
6824   StartProgram(false);
6825   Add([
6826   '{$mode delphi}',
6827   'procedure DoIt(i: longint); ',
6828   'begin end;',
6829   'procedure DoIt(s: string); overload;',
6830   'begin end;',
6831   'begin']);
6832   CheckResolverException(sPreviousDeclMissesOverload,nPreviousDeclMissesOverload);
6833 end;
6834 
6835 procedure TTestResolver.TestProcOverloadDelphiUnit;
6836 begin
6837   AddModuleWithIntfImplSrc('unit2.pp',
6838     LinesToStr([
6839     '{$mode delphi}',
6840     'procedure DoIt(s: string); overload;',
6841     'procedure DoIt(b: boolean); overload;',
6842     '']),
6843     LinesToStr([
6844     'procedure DoIt(s: string); begin end;',
6845     'procedure DoIt(b: boolean); begin end;',
6846     '']));
6847 
6848   StartProgram(true);
6849   Add([
6850   '{$mode delphi}',
6851   'uses unit2;',
6852   'procedure DoIt(i: longint); overload;',
6853   'begin end;',
6854   'begin',
6855   '  DoIt(3);',
6856   '  DoIt(true);',
6857   '  DoIt(''foo'');',
6858   '']);
6859   ParseProgram;
6860 end;
6861 
6862 procedure TTestResolver.TestProcOverloadDelphiUnitNoOverloadFail;
6863 begin
6864   AddModuleWithIntfImplSrc('unit2.pp',
6865     LinesToStr([
6866     '{$mode delphi}',
6867     'procedure DoIt(b: boolean);',
6868     '']),
6869     LinesToStr([
6870     'procedure DoIt(b: boolean); begin end;',
6871     '']));
6872 
6873   StartProgram(true);
6874   Add([
6875   '{$mode delphi}',
6876   'uses unit2;',
6877   'procedure DoIt(i: longint); overload;',
6878   'begin end;',
6879   'begin',
6880   '  DoIt(true);',
6881   '']);
6882   CheckResolverException(sIncompatibleTypeArgNo,nIncompatibleTypeArgNo);
6883 end;
6884 
6885 procedure TTestResolver.TestProcOverloadObjFPCUnitWithoutOverloadMod;
6886 begin
6887   AddModuleWithIntfImplSrc('unit2.pp',
6888     LinesToStr([
6889     '{$mode objfpc}',
6890     'procedure DoIt(s: string);',
6891     'procedure DoIt(b: boolean);',
6892     '']),
6893     LinesToStr([
6894     'procedure DoIt(s: string); begin end;',
6895     'procedure DoIt(b: boolean); begin end;',
6896     '']));
6897 
6898   StartProgram(true);
6899   Add([
6900   '{$mode objfpc}',
6901   'uses unit2;',
6902   'procedure DoIt(i: longint); overload;',
6903   'begin end;',
6904   'begin',
6905   '  DoIt(3);',
6906   '  DoIt(true);',
6907   '  DoIt(''foo'');',
6908   '']);
6909   ParseProgram;
6910 end;
6911 
6912 procedure TTestResolver.TestProcOverloadDelphiWithObjFPC;
6913 begin
6914   AddModuleWithIntfImplSrc('unit2.pp',
6915     LinesToStr([
6916     '{$mode objfpc}',
6917     'procedure DoIt(s: string);',
6918     'procedure DoIt(b: boolean);',
6919     '']),
6920     LinesToStr([
6921     'procedure DoIt(s: string); begin end;',
6922     'procedure DoIt(b: boolean); begin end;',
6923     '']));
6924 
6925   StartProgram(true);
6926   Add([
6927   '{$mode delphi}',
6928   'uses unit2;',
6929   'begin',
6930   '  DoIt(true);',
6931   '  DoIt(''foo'');',
6932   '']);
6933   ParseProgram;
6934 end;
6935 
6936 procedure TTestResolver.TestProcOverloadDelphiOverride;
6937 begin
6938   StartProgram(false);
6939   Add([
6940   '{$mode delphi}',
6941   'type',
6942   '  TObject = class end;',
6943   '  TBird = class',
6944   '    function {#a}GetValue: longint; overload; virtual;',
6945   '    function {#b}GetValue(AValue: longint): longint; overload; virtual;',
6946   '  end;',
6947   '  TEagle = class(TBird)',
6948   '    function {#c}GetValue: longint; overload; override;',
6949   '    function {#d}GetValue(AValue: longint): longint; overload; override;',
6950   '  end;',
6951   '  TBear = class',
6952   '    procedure DoIt;',
6953   '  end;',
6954   'function TBird.GetValue: longint;',
6955   'begin',
6956   '  if 3={@a}GetValue then ;',
6957   '  if 4={@b}GetValue(5) then ;',
6958   'end;',
6959   'function TBird.GetValue(AValue: longint): longint;',
6960   'begin',
6961   'end;',
6962   'function TEagle.GetValue: longint;',
6963   'begin',
6964   '  if 13={@c}GetValue then ;',
6965   '  if 14={@d}GetValue(15) then ;',
6966   '  if 15=inherited {@a}GetValue then ;',
6967   '  if 16=inherited {@b}GetValue(17) then ;',
6968   'end;',
6969   'function TEagle.GetValue(AValue: longint): longint;',
6970   'begin',
6971   'end;',
6972   'procedure TBear.DoIt;',
6973   'var',
6974   '  e: TEagle;',
6975   'begin',
6976   '  if 23=e.{@c}GetValue then ;',
6977   '  if 24=e.{@d}GetValue(25) then ;',
6978   'end;',
6979   'begin']);
6980   ParseProgram;
6981 end;
6982 
6983 procedure TTestResolver.TestProcDuplicate;
6984 begin
6985   StartProgram(false);
6986   Add('type integer = longint;');
6987   Add('procedure ProcA(i: longint);');
6988   Add('begin');
6989   Add('end;');
6990   Add('procedure ProcA(i: integer);');
6991   Add('begin');
6992   Add('end;');
6993   Add('begin');
6994   CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
6995 end;
6996 
6997 procedure TTestResolver.TestNestedProc;
6998 begin
6999   StartProgram(false);
7000   Add('function DoIt({#a1}a,{#d1}d: longint): longint;');
7001   Add('var');
7002   Add('  {#b1}b: longint;');
7003   Add('  {#c1}c: longint;');
7004   Add('  function {#Nesty1}Nesty({#a2}a: longint): longint; ');
7005   Add('  var {#b2}b: longint;');
7006   Add('  begin');
7007   Add('    Result:={@a2}a');
7008   Add('      +{@b2}b');
7009   Add('      +{@c1}c');
7010   Add('      +{@d1}d;');
7011   Add('    Nesty:=3;');
7012   Add('    DoIt:=4;');
7013   Add('  end;');
7014   Add('begin');
7015   Add('  Result:={@a1}a');
7016   Add('      +{@b1}b');
7017   Add('      +{@c1}c;');
7018   Add('  DoIt:=5;');
7019   Add('end;');
7020   Add('begin');
7021   ParseProgram;
7022 end;
7023 
7024 procedure TTestResolver.TestNestedProc_ResultString;
7025 var
7026   aMarker: PSrcMarker;
7027   Elements: TFPList;
7028   i: Integer;
7029   El: TPasElement;
7030   Ref: TResolvedReference;
7031 begin
7032   StartProgram(false);
7033   Add([
7034   'function DoIt: string;',
7035   '  function Sub: char;',
7036   '  begin',
7037   '    {#a1}DoIt:=#65;',
7038   '    {#a2}DoIt[1]:=#66;',
7039   '    {#a3}DoIt;',
7040   '  end;',
7041   'begin',
7042   '  {#b1}DoIt:=#67;',
7043   '  {#b2}DoIt[2]:=#68;',
7044   '  {#b3}DoIt;',
7045   'end;',
7046   'begin']);
7047   ParseProgram;
7048   aMarker:=FirstSrcMarker;
7049   while aMarker<>nil do
7050     begin
7051     //writeln('TTestResolver.TestNestedProc_ResultString ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
7052     Elements:=FindElementsAt(aMarker);
7053     try
7054       for i:=0 to Elements.Count-1 do
7055         begin
7056         El:=TPasElement(Elements[i]);
7057         //writeln('TTestResolver.TestNestedProc_ResultString ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
7058         if not (El.CustomData is TResolvedReference) then continue;
7059         Ref:=TResolvedReference(El.CustomData);
7060         //writeln('TTestResolver.TestNestedProc_ResultString ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' Decl=',GetObjName(Ref.Declaration));
7061         case aMarker^.Identifier of
7062         'a1','a2','b1','b2':
7063           if not (Ref.Declaration is TPasResultElement) then
7064             RaiseErrorAtSrcMarker('expected FuncResult at "#'+aMarker^.Identifier+', but was "'+GetObjName(Ref.Declaration)+'"',aMarker);
7065         'a3','b3':
thennull7066           if not (Ref.Declaration is TPasFunction) then
7067             RaiseErrorAtSrcMarker('expected TPasFunction at "#'+aMarker^.Identifier+', but was "'+GetObjName(Ref.Declaration)+'"',aMarker);
7068         end;
7069         end;
7070     finally
7071       Elements.Free;
7072     end;
7073     aMarker:=aMarker^.Next;
7074     end;
7075 end;
7076 
7077 procedure TTestResolver.TestFuncAssignFail;
7078 begin
7079   StartProgram(false);
7080   Add([
7081   'function DoIt: boolean;',
7082   'begin',
7083   'end;',
7084   'begin',
7085   '  DoIt:=true;']);
7086   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
7087 end;
7088 
7089 procedure TTestResolver.TestForwardProc;
7090 begin
7091   StartProgram(false);
7092   Add('procedure {#A_forward}FuncA(i: longint); forward;');
7093   Add('procedure {#B}FuncB(i: longint);');
7094   Add('begin');
7095   Add('  {@A_forward}FuncA(i);');
7096   Add('end;');
7097   Add('procedure {#A}FuncA(i: longint);');
7098   Add('begin');
7099   Add('end;');
7100   Add('begin');
7101   Add('  {@A_forward}FuncA(3);');
7102   Add('  {@B}FuncB(3);');
7103   ParseProgram;
7104 end;
7105 
7106 procedure TTestResolver.TestForwardProcUnresolved;
7107 begin
7108   StartProgram(false);
7109   Add('procedure FuncA(i: longint); forward;');
7110   Add('begin');
7111   CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
7112 end;
7113 
7114 procedure TTestResolver.TestNestedForwardProc;
7115 begin
7116   StartProgram(false);
7117   Add('procedure {#A}FuncA;');
7118   Add('  procedure {#B_forward}ProcB(i: longint); forward;');
7119   Add('  procedure {#C}ProcC(i: longint);');
7120   Add('  begin');
7121   Add('    {@B_forward}ProcB(i);');
7122   Add('  end;');
7123   Add('  procedure {#B}ProcB(i: longint);');
7124   Add('  begin');
7125   Add('  end;');
7126   Add('begin');
7127   Add('  {@B_forward}ProcB(3);');
7128   Add('  {@C}ProcC(3);');
7129   Add('end;');
7130   Add('begin');
7131   Add('  {@A}FuncA;');
7132   ParseProgram;
7133 end;
7134 
7135 procedure TTestResolver.TestNestedForwardProcUnresolved;
7136 begin
7137   StartProgram(false);
7138   Add('procedure FuncA;');
7139   Add('  procedure ProcB(i: longint); forward;');
7140   Add('begin');
7141   Add('end;');
7142   Add('begin');
7143   CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
7144 end;
7145 
7146 procedure TTestResolver.TestForwardProcFuncMismatch;
7147 begin
7148   StartProgram(false);
7149   Add('procedure DoIt; forward;');
7150   Add('function DoIt: longint;');
7151   Add('begin');
7152   Add('end;');
7153   Add('begin');
7154   CheckResolverException('procedure expected, but function found',nXExpectedButYFound);
7155 end;
7156 
7157 procedure TTestResolver.TestForwardFuncResultMismatch;
7158 begin
7159   StartProgram(false);
7160   Add('function DoIt: longint; forward;');
7161   Add('function DoIt: string;');
7162   Add('begin');
7163   Add('end;');
7164   Add('begin');
7165   CheckResolverException('Result type mismatch, expected Longint, but found String',
7166     nResultTypeMismatchExpectedButFound);
7167 end;
7168 
7169 procedure TTestResolver.TestForwardProcAssemblerMismatch;
7170 begin
7171   StartProgram(false);
7172   Add('procedure Run; assembler; forward;');
7173   Add('procedure Run;');
7174   Add('begin');
7175   Add('end;');
7176   Add('begin');
7177   CheckParserException('Expected "asm"',nParserExpectTokenError);
7178 end;
7179 
7180 procedure TTestResolver.TestUnitIntfProc;
7181 begin
7182   StartUnit(false);
7183   Add('interface');
7184   Add('procedure {#A_forward}FuncA({#Bar}Bar: longint);');
7185   Add('implementation');
7186   Add('procedure {#A}FuncA(bar: longint);');
7187   Add('begin');
7188   Add('  if {@Bar}bar=3 then ;');
7189   Add('end;');
7190   Add('initialization');
7191   Add('  {@A_forward}FuncA(3);');
7192   ParseUnit;
7193 end;
7194 
7195 procedure TTestResolver.TestUnitIntfProcUnresolved;
7196 begin
7197   StartUnit(false);
7198   Add('interface');
7199   Add('procedure {#A_forward}FuncA(i: longint);');
7200   Add('implementation');
7201   Add('initialization');
7202   CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
7203 end;
7204 
7205 procedure TTestResolver.TestUnitIntfMismatchArgName;
7206 begin
7207   StartUnit(false);
7208   Add('interface');
7209   Add('procedure {#A_forward}ProcA(i: longint);');
7210   Add('implementation');
7211   Add('procedure {#A}ProcA(j: longint);');
7212   Add('begin');
7213   Add('end;');
7214   CheckResolverException('function header "ProcA" doesn''t match forward : var name changes i => j',
7215     nFunctionHeaderMismatchForwardVarName);
7216 end;
7217 
7218 procedure TTestResolver.TestProcOverloadIsNotFunc;
7219 begin
7220   StartUnit(false);
7221   Add('interface');
7222   Add('var ProcA: longint;');
7223   Add('procedure {#A_Decl}ProcA(i: longint);');
7224   Add('implementation');
7225   Add('procedure {#A_Impl}ProcA(i: longint);');
7226   Add('begin');
7227   Add('end;');
7228   CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
7229 end;
7230 
7231 procedure TTestResolver.TestProcCallMissingParams;
7232 begin
7233   StartProgram(false);
7234   Add('procedure Proc1(a: longint);');
7235   Add('begin');
7236   Add('end;');
7237   Add('begin');
7238   Add('  Proc1;');
7239   CheckResolverException('Wrong number of parameters specified for call to "Proc1"',
7240     nWrongNumberOfParametersForCallTo);
7241 end;
7242 
7243 procedure TTestResolver.TestProcArgDefaultValue;
7244 begin
7245   StartProgram(false);
7246   Add('const {#DefA}DefA = 3;');
7247   Add('procedure Proc1(a: longint = {@DefA}DefA);');
7248   Add('begin');
7249   Add('end;');
7250   Add('begin');
7251   ParseProgram;
7252 end;
7253 
7254 procedure TTestResolver.TestProcArgDefaultValueTypeMismatch;
7255 begin
7256   StartProgram(false);
7257   Add('procedure Proc1(a: string = 3);');
7258   Add('begin');
7259   Add('end;');
7260   Add('begin');
7261   CheckResolverException('Incompatible types: got "Longint" expected "String"',
7262     nIncompatibleTypesGotExpected);
7263 end;
7264 
7265 procedure TTestResolver.TestProcPassConstToVar;
7266 begin
7267   StartProgram(false);
7268   Add('procedure DoSome(var i: longint); begin end;');
7269   Add('procedure DoIt(const i: longint);');
7270   Add('begin');
7271   Add('  DoSome(i);');
7272   Add('end;');
7273   Add('begin');
7274   CheckResolverException('Variable identifier expected',
7275     nVariableIdentifierExpected);
7276 end;
7277 
7278 procedure TTestResolver.TestBuiltInProcCallMissingParams;
7279 begin
7280   StartProgram(false);
7281   Add('begin');
7282   Add('  length;');
7283   CheckResolverException('Wrong number of parameters specified for call to "function Length(const String or Array): sizeint"',
7284     nWrongNumberOfParametersForCallTo);
7285 end;
7286 
7287 procedure TTestResolver.TestAssignFunctionResult;
7288 begin
7289   StartProgram(false);
7290   Add('function {#F1}F1: longint;');
7291   Add('begin');
7292   Add('end;');
7293   Add('function {#F2}F2: longint;');
7294   Add('begin');
7295   Add('end;');
7296   Add('var {#i}i: longint;');
7297   Add('begin');
7298   Add('  {@i}i:={@F1}F1();');
7299   Add('  {@i}i:={@F1}F1()+{@F2}F2();');
7300   Add('  {@i}i:={@F1}F1;');
7301   Add('  {@i}i:={@F1}F1+{@F2}F2;');
7302   ParseProgram;
7303 end;
7304 
7305 procedure TTestResolver.TestAssignProcResultFail;
7306 begin
7307   StartProgram(false);
7308   Add('procedure {#P}P;');
7309   Add('begin');
7310   Add('end;');
7311   Add('var {#i}i: longint;');
7312   Add('begin');
7313   Add('  {@i}i:={@P}P();');
7314   CheckResolverException('Incompatible types: got "Procedure/Function" expected "Longint"',
7315     nIncompatibleTypesGotExpected);
7316 end;
7317 
7318 procedure TTestResolver.TestFunctionResultInCondition;
7319 begin
7320   StartProgram(false);
7321   Add('function {#F1}F1: longint;');
7322   Add('begin');
7323   Add('end;');
7324   Add('function {#F2}F2: boolean;');
7325   Add('begin');
7326   Add('end;');
7327   Add('var {#i}i: longint;');
7328   Add('begin');
7329   Add('  if {@F2}F2 then ;');
7330   Add('  if {@i}i={@F1}F1() then ;');
7331   ParseProgram;
7332 end;
7333 
7334 procedure TTestResolver.TestExit;
7335 begin
7336   StartProgram(false);
7337   Add('procedure ProcA;');
7338   Add('begin');
7339   Add('  exit;');
7340   Add('end;');
7341   Add('function FuncB: longint;');
7342   Add('begin');
7343   Add('  exit;');
7344   Add('  exit(3);');
7345   Add('end;');
7346   Add('function FuncC: string;');
7347   Add('begin');
7348   Add('  exit;');
7349   Add('  exit(''a'');');
7350   Add('  exit(''abc'');');
7351   Add('end;');
7352   Add('begin');
7353   Add('  exit;');
7354   Add('  exit(4);');
7355   ParseProgram;
7356 end;
7357 
7358 procedure TTestResolver.TestBreak;
7359 begin
7360   StartProgram(false);
7361   Add('var i: longint;');
7362   Add('begin');
7363   Add('  repeat');
7364   Add('    break;');
7365   Add('  until false;');
7366   Add('  while true do');
7367   Add('    break;');
7368   Add('  for i:=0 to 1 do');
7369   Add('    break;');
7370   ParseProgram;
7371 end;
7372 
7373 procedure TTestResolver.TestContinue;
7374 begin
7375   StartProgram(false);
7376   Add('var i: longint;');
7377   Add('begin');
7378   Add('  repeat');
7379   Add('    continue;');
7380   Add('  until false;');
7381   Add('  while true do');
7382   Add('    continue;');
7383   Add('  for i:=0 to 1 do');
7384   Add('    continue;');
7385   ParseProgram;
7386 end;
7387 
7388 procedure TTestResolver.TestProcedureExternal;
7389 begin
7390   StartProgram(false);
7391   Add('procedure {#ProcA}ProcA; external ''ExtProcA'';');
7392   Add('function {#FuncB}FuncB: longint; external ''ExtFuncB'';');
7393   Add('function {#FuncC}FuncC(d: double): string; external ''ExtFuncC'';');
7394   Add('var');
7395   Add('  i: longint;');
7396   Add('  s: string;');
7397   Add('begin');
7398   Add('  {@ProcA}ProcA;');
7399   Add('  i:={@FuncB}FuncB;');
7400   Add('  i:={@FuncB}FuncB();');
7401   Add('  s:={@FuncC}FuncC(1.2);');
7402   ParseProgram;
7403 end;
7404 
7405 procedure TTestResolver.TestProc_UntypedParam_Forward;
7406 begin
7407   StartProgram(false);
7408   Add('procedure {#ProcA}ProcA(var {#A}A); forward;');
7409   Add('procedure {#ProcB}ProcB(const {#B}B); forward;');
7410   Add('procedure {#ProcC}ProcC(out {#C}C); forward;');
7411   //Add('procedure {#ProcD}ProcD(constref {#D}D); forward;');
7412   Add('procedure ProcA(var A);');
7413   Add('begin');
7414   Add('end;');
7415   Add('procedure ProcB(const B);');
7416   Add('begin');
7417   Add('end;');
7418   Add('procedure ProcC(out C);');
7419   Add('begin');
7420   Add('end;');
7421   //Add('procedure ProcD(constref D);');
7422   //Add('begin');
7423   //Add('end;');
7424   Add('var i: longint;');
7425   Add('begin');
7426   Add('  {@ProcA}ProcA(i);');
7427   Add('  {@ProcB}ProcB(i);');
7428   Add('  {@ProcC}ProcC(i);');
7429   //Add('  {@ProcD}ProcD(i);');
7430   ParseProgram;
7431 end;
7432 
7433 procedure TTestResolver.TestProc_Varargs;
7434 begin
7435   StartProgram(false);
7436   Add('procedure ProcA(i:longint); varargs; external;');
7437   Add('procedure ProcB; varargs; external;');
7438   Add('procedure ProcC(i: longint = 17); varargs; external;');
7439   Add('begin');
7440   Add('  ProcA(1);');
7441   Add('  ProcA(1,2);');
7442   Add('  ProcA(1,2.0);');
7443   Add('  ProcA(1,2,3);');
7444   Add('  ProcA(1,''2'');');
7445   Add('  ProcA(2,'''');');
7446   Add('  ProcA(3,false);');
7447   Add('  ProcB;');
7448   Add('  ProcB();');
7449   Add('  ProcB(4);');
7450   Add('  ProcB(''foo'');');
7451   Add('  ProcC;');
7452   Add('  ProcC();');
7453   Add('  ProcC(4);');
7454   Add('  ProcC(5,''foo'');');
7455   ParseProgram;
7456 end;
7457 
7458 procedure TTestResolver.TestProc_VarargsOfT;
7459 begin
7460   StartProgram(false);
7461   Add([
7462   'procedure ProcA(i:longint); varargs of word; external;',
7463   'procedure ProcB; varargs of boolean; external;',
7464   'procedure ProcC(i: longint = 17); varargs of double; external;',
7465   'begin',
7466   '  ProcA(1);',
7467   '  ProcA(2,3);',
7468   '  ProcA(4,5,6);',
7469   '  ProcB;',
7470   '  ProcB();',
7471   '  ProcB(false);',
7472   '  ProcB(true,false);',
7473   '  ProcC;',
7474   '  ProcC();',
7475   '  ProcC(7);',
7476   '  ProcC(8,9.3);',
7477   '  ProcC(8,9.3,1.3);',
7478   '']);
7479   ParseProgram;
7480 end;
7481 
7482 procedure TTestResolver.TestProc_VarargsOfTMismatch;
7483 begin
7484   StartProgram(false);
7485   Add([
7486   'procedure ProcA(i:longint); varargs of word; external;',
7487   'begin',
7488   '  ProcA(1,false);',
7489   '']);
7490   CheckResolverException('Incompatible type arg no. 2: Got "Boolean", expected "Word"',nIncompatibleTypeArgNo);
7491 end;
7492 
7493 procedure TTestResolver.TestProc_ParameterExprAccess;
7494 begin
7495   StartProgram(false);
7496   Add('type');
7497   Add('  TRec = record');
7498   Add('    a: longint;');
7499   Add('  end;');
7500   Add('procedure DoIt(i: longint; const j: longint; var k: longint; out l: longint);');
7501   Add('begin');
7502   Add('  DoIt({#loc1_read}i,{#loc2_read}i,{#loc3_var}i,{#loc4_out}i);');
7503   Add('end;');
7504   Add('var');
7505   Add('  r: TRec;');
7506   Add('begin');
7507   Add('  DoIt({#r1_read}r.{#r_a1_read}a,');
7508   Add('    {#r2_read}r.{#r_a2_read}a,');
7509   Add('    {#r3_read}r.{#r_a3_var}a,');
7510   Add('    {#r4_read}r.{#r_a4_out}a);');
7511   Add('  with r do');
7512   Add('    DoIt({#w_a1_read}a,');
7513   Add('      {#w_a2_read}a,');
7514   Add('      {#w_a3_var}a,');
7515   Add('      {#w_a4_out}a);');
7516   ParseProgram;
7517   CheckAccessMarkers;
7518 end;
7519 
7520 procedure TTestResolver.TestProc_FunctionResult_DeclProc;
7521 var
7522   aMarker: PSrcMarker;
7523   Elements: TFPList;
7524   i: Integer;
7525   El: TPasElement;
7526   Ref: TResolvedReference;
7527   ResultEl: TPasResultElement;
7528   Proc: TPasProcedure;
7529   ProcScope: TPasProcedureScope;
7530 begin
7531   StartProgram(false);
7532   Add('type');
7533   Add('  TObject = class');
7534   Add('    function MethodA: longint;');
7535   Add('  end;');
7536   Add('function FuncA: longint; forward;');
7537   Add('function TObject.MethodA: longint;');
7538   Add('begin');
7539   Add('  {#MethodA_Result}Result:=1;');
7540   Add('end;');
7541   Add('function FuncA: longint;');
7542   Add('  function SubFuncA: longint; forward;');
7543   Add('  function SubFuncB: longint;');
7544   Add('  begin');
7545   Add('    {#SubFuncB_Result}Result:=2;');
7546   Add('  end;');
7547   Add('  function SubFuncA: longint;');
7548   Add('  begin');
7549   Add('    {#SubFuncA_Result}Result:=3;');
7550   Add('  end;');
7551   Add('begin');
7552   Add('  {#FuncA_Result}Result:=4;');
7553   Add('end;');
7554   Add('begin');
7555   ParseProgram;
7556   aMarker:=FirstSrcMarker;
7557   while aMarker<>nil do
7558     begin
7559     //writeln('TTestResolver.TestProc_FunctionResult_DeclProc ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
7560     Elements:=FindElementsAt(aMarker);
7561     try
7562       for i:=0 to Elements.Count-1 do
7563         begin
7564         El:=TPasElement(Elements[i]);
7565         //writeln('TTestResolver.TestProc_FunctionResult_DeclProc ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
7566         if not (El.CustomData is TResolvedReference) then continue;
7567         Ref:=TResolvedReference(El.CustomData);
7568         //writeln('TTestResolver.TestProc_FunctionResult_DeclProc ',GetObjName(Ref.Declaration));
7569         if not (Ref.Declaration is TPasResultElement) then continue;
7570         ResultEl:=TPasResultElement(Ref.Declaration);
7571         Proc:=ResultEl.Parent.Parent as TPasProcedure;
7572         ProcScope:=Proc.CustomData as TPasProcedureScope;
7573         if ProcScope.DeclarationProc<>nil then
7574           RaiseErrorAtSrcMarker('expected Result to resolve to declaration at "#'+aMarker^.Identifier+', but was implproc"',aMarker);
7575         break;
7576         end;
7577     finally
7578       Elements.Free;
7579     end;
7580     aMarker:=aMarker^.Next;
7581     end;
7582 end;
7583 
7584 procedure TTestResolver.TestProc_TypeCastFunctionResult;
7585 begin
7586   StartProgram(false);
7587   Add('function GetIt: longint; begin end;');
7588   Add('var s: smallint;');
7589   Add('begin');
7590   Add('  s:=smallint(GetIt);');
7591   ParseProgram;
7592 end;
7593 
7594 procedure TTestResolver.TestProc_ImplicitCalls;
7595 var
7596   aMarker: PSrcMarker;
7597   Elements: TFPList;
7598   ActualImplicitCallWithoutParams: Boolean;
7599   i: Integer;
7600   El: TPasElement;
7601   Ref: TResolvedReference;
7602 begin
7603   StartProgram(false);
7604   Add([
7605   'function b: longint;',
7606   'begin',
7607   'end;',
7608   'function GetStr: string;',
7609   'begin',
7610   'end;',
7611   'var',
7612   '  a: longint;',
7613   '  s: string;',
7614   '  arr: array of longint;',
7615   'begin',
7616   '  Inc(a,{#b1}b);',
7617   '  Dec(a,{#b2}b);',
7618   '  str({#b3}b,s);',
7619   '  SetLength(arr,{#b4}b);',
7620   '  Insert({#b5}b,arr,{#b6}b);',
7621   '  Delete(arr,{#b7}b,{#b8}b);',
7622   '  a:=length({#b9}GetStr);',
7623   '']);
7624   ParseProgram;
7625   aMarker:=FirstSrcMarker;
7626   while aMarker<>nil do
7627     begin
7628     //writeln('TTestResolver.TestProc_IncWithImplicitCall ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
7629     Elements:=FindElementsAt(aMarker);
7630     try
7631       ActualImplicitCallWithoutParams:=false;
7632       for i:=0 to Elements.Count-1 do
7633         begin
7634         El:=TPasElement(Elements[i]);
7635         //writeln('TTestResolver.TestProc_IncWithImplicitCall ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
7636         if not (El.CustomData is TResolvedReference) then continue;
7637         Ref:=TResolvedReference(El.CustomData);
7638         if not (Ref.Declaration is TPasProcedure) then continue;
7639         //writeln('TTestResolver.TestProc_IncWithImplicitCall ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
7640         ActualImplicitCallWithoutParams:=rrfImplicitCallWithoutParams in Ref.Flags;
7641         break;
7642         end;
7643       if not ActualImplicitCallWithoutParams then
7644         RaiseErrorAtSrcMarker('expected implicit call at "#'+aMarker^.Identifier+', but got function ref"',aMarker);
7645     finally
7646       Elements.Free;
7647     end;
7648     aMarker:=aMarker^.Next;
7649     end;
7650 end;
7651 
7652 procedure TTestResolver.TestProc_Absolute;
7653 begin
7654   StartProgram(false);
7655   Add([
7656   'procedure DoIt(p: Pointer);',
7657   'var',
7658   '  s: string absolute p;',
7659   '  t: array of char absolute s;',
7660   'begin',
7661   'end;',
7662   'begin']);
7663   ParseProgram;
7664 end;
7665 
7666 procedure TTestResolver.TestProc_LocalInit;
7667 begin
7668   StartProgram(false);
7669   Add([
7670   'type TBytes = array of byte;',
7671   'procedure DoIt;',
7672   'const c = 4;',
7673   'var',
7674   '  w: word = c;',
7675   '  b: byte = 1+c;',
7676   '  p: pointer = nil;',
7677   '  buf: TBytes = nil;',
7678   'begin',
7679   'end;',
7680   'begin']);
7681   ParseProgram;
7682 end;
7683 
7684 procedure TTestResolver.TestProc_ExtNamePropertyFail;
7685 begin
7686   StartProgram(false);
7687   Add([
7688   'procedure Foo; external name ''});'' property;',
7689   'begin']);
7690   CheckParserException('Expected ";" at token "property" in file afile.pp at line 2 column 36',
7691     nParserExpectTokenError);
7692 end;
7693 
7694 procedure TTestResolver.TestAnonymousProc_Assign;
7695 begin
7696   StartProgram(false);
7697   Add([
7698   'type',
7699   '  TFunc = reference to function(x: word): word;',
7700   'var Func: TFunc;',
7701   'procedure DoIt(a: word);',
7702   'begin',
7703   '  Func:=function(b:word): word',
7704   '  begin',
7705   '    Result:=a+b;',
7706   '    exit(b);',
7707   '    exit(Result);',
7708   '  end;',// test semicolon
7709   '  a:=3;',
7710   'end;',
7711   'begin',
7712   '  Func:=function(c:word):word begin',
7713   '    Result:=3+c;',
7714   '    exit(c);',
7715   '    exit(Result);',
7716   '  end;']);
7717   ParseProgram;
7718 end;
7719 
7720 procedure TTestResolver.TestAnonymousProc_AssignSemicolonFail;
7721 begin
7722   StartProgram(false);
7723   Add([
7724   'type',
7725   '  TProc = reference to procedure;',
7726   'procedure DoIt(a: word);',
7727   'var p: TProc;',
7728   'begin',
7729   '  p:=procedure; begin end;',
7730   '  a:=3;',
7731   'end;',
7732   'begin']);
7733   CheckParserException('Expected "begin" at token ";" in file afile.pp at line 7 column 15',
7734     nParserExpectTokenError);
7735 end;
7736 
7737 procedure TTestResolver.TestAnonymousProc_Assign_ReferenceToMissingFail;
7738 begin
7739   StartProgram(false);
7740   Add([
7741   'type',
7742   '  TProc = procedure;',
7743   'procedure DoIt;',
7744   'var p: TProc;',
7745   'begin',
7746   '  p:=procedure(w: word) begin end;',
7747   'end;',
7748   'begin']);
7749   CheckResolverException('procedural type modifier "reference to" mismatch',
7750     nXModifierMismatchY);
7751 end;
7752 
7753 procedure TTestResolver.TestAnonymousProc_Assign_WrongParamListFail;
7754 begin
7755   StartProgram(false);
7756   Add([
7757   'type',
7758   '  TProc = reference to procedure;',
7759   'procedure DoIt;',
7760   'var p: TProc;',
7761   'begin',
7762   '  p:=procedure(w: word) begin end;',
7763   'end;',
7764   'begin']);
7765   CheckResolverException('Incompatible types, got 0 parameters, expected 1',
7766     nIncompatibleTypesGotParametersExpected);
7767 end;
7768 
7769 procedure TTestResolver.TestAnonymousProc_Arg;
7770 begin
7771   StartProgram(false);
7772   Add([
7773   'type',
7774   '  TProc = reference to procedure;',
7775   '  TFunc = reference to function(x: word): word;',
7776   'procedure DoMore(f,g: TProc);',
7777   'begin',
7778   'end;',
7779   'procedure DoIt(f: TFunc);',
7780   'begin',
7781   '  DoIt(function(b:word): word',
7782   '    begin',
7783   '      Result:=1+b;',
7784   '    end);',
7785   '  DoMore(procedure begin end, procedure begin end);',
7786   'end;',
7787   'begin',
7788   '  DoMore(procedure begin end, procedure begin end);',
7789   '']);
7790   ParseProgram;
7791 end;
7792 
7793 procedure TTestResolver.TestAnonymousProc_ArgSemicolonFail;
7794 begin
7795   StartProgram(false);
7796   Add([
7797   'type',
7798   '  TProc = reference to procedure;',
7799   'procedure DoIt(p: TProc);',
7800   'begin',
7801   'end;',
7802   'begin',
7803   '  DoIt(procedure begin end;);']);
7804   CheckParserException('Expected "," at token ";" in file afile.pp at line 8 column 27',
7805     nParserExpectTokenError);
7806 end;
7807 
7808 procedure TTestResolver.TestAnonymousProc_EqualFail;
7809 begin
7810   StartProgram(false);
7811   Add([
7812   'type',
7813   '  TFunc = reference to function(x: word): word;',
7814   'procedure DoIt(f: TFunc);',
7815   'var w: word;',
7816   'begin',
7817   '  if w=function(b:word): word',
7818   '    begin',
7819   '      Result:=1+b;',
7820   '    end then ;',
7821   'end;',
7822   'begin']);
7823   CheckResolverException('Incompatible types: got "Procedure/Function" expected "Word"',nIncompatibleTypesGotExpected);
7824 end;
7825 
7826 procedure TTestResolver.TestAnonymousProc_ConstFail;
7827 begin
7828   StartProgram(false);
7829   Add([
7830   'type',
7831   '  TProc = reference to procedure;',
7832   'const',
7833   '  p: TProc = procedure begin end;',
7834   'begin']);
7835   CheckParserException('Identifier expected at token "procedure" in file afile.pp at line 5 column 14',nParserExpectedIdentifier);
7836 end;
7837 
7838 procedure TTestResolver.TestAnonymousProc_Assembler;
7839 begin
7840   StartProgram(false);
7841   Add([
7842   'type',
7843   '  TProc = reference to procedure;',
7844   '  TProcB = reference to procedure cdecl;',
7845   'procedure DoIt(p: TProc);',
7846   'var b: TProcB;',
7847   'begin',
7848   '  p:=procedure assembler asm end;',
7849   '  p:=procedure() assembler asm end;',
7850   '  b:=procedure() cdecl assembler asm end;',
7851   'end;',
7852   'begin']);
7853   ParseProgram;
7854 end;
7855 
7856 procedure TTestResolver.TestAnonymousProc_NameFail;
7857 begin
7858   StartProgram(false);
7859   Add([
7860   'type',
7861   '  TProc = reference to procedure;',
7862   'procedure DoIt(p: TProc);',
7863   'begin',
7864   '  p:=procedure Bla() begin end;',
7865   'end;',
7866   'begin']);
7867   CheckParserException(SParserSyntaxError,nParserSyntaxError);
7868 end;
7869 
7870 procedure TTestResolver.TestAnonymousProc_StatementFail;
7871 begin
7872   StartProgram(false);
7873   Add([
7874   'procedure DoIt;',
7875   'begin',
7876   '  procedure () begin end;',
7877   'end;',
7878   'begin']);
7879   CheckParserException(SParserSyntaxError,nParserSyntaxError);
7880 end;
7881 
7882 procedure TTestResolver.TestAnonymousProc_Typecast_ObjFPC;
7883 begin
7884   StartProgram(false);
7885   Add([
7886   '{$mode ObjFPC}',
7887   'type',
7888   '  TProc = reference to procedure(w: word);',
7889   '  TArr = array of word;',
7890   '  TFuncArr = reference to function: TArr;',
7891   'procedure DoIt(p: TProc);',
7892   'var',
7893   '  w: word;',
7894   '  a: TArr;',
7895   'begin',
7896   '  p:=TProc(procedure(b: smallint) begin end);',
7897   '  a:=TFuncArr(function: TArr begin end)();',
7898   '  w:=TFuncArr(function: TArr begin end)()[3];',
7899   'end;',
7900   'begin']);
7901   ParseProgram;
7902 end;
7903 
7904 procedure TTestResolver.TestAnonymousProc_Typecast_Delphi;
7905 begin
7906   StartProgram(false);
7907   Add([
7908   '{$mode Delphi}',
7909   'type',
7910   '  TProc = reference to procedure(w: word);',
7911   '  TArr = array of word;',
7912   '  TFuncArr = reference to function: TArr;',
7913   'procedure DoIt(p: TProc);',
7914   'var',
7915   '  w: word;',
7916   '  a: TArr;',
7917   'begin',
7918   '  p:=TProc(procedure(b: smallint) begin end);',
7919   '  a:=TFuncArr(function: TArr begin end)();',
7920   '  w:=TFuncArr(function: TArr begin end)()[3];',
7921   'end;',
7922   'begin']);
7923   ParseProgram;
7924 end;
7925 
7926 procedure TTestResolver.TestAnonymousProc_TypecastToResultFail;
7927 begin
7928   StartProgram(false);
7929   Add([
7930   'procedure DoIt;',
7931   'var i: longint;',
7932   'begin',
7933   '  i:=longint(function(b: byte): byte begin end);',
7934   'end;',
7935   'begin']);
7936   CheckResolverException('Illegal type conversion: "Procedure/Function" to "Longint"',
7937     nIllegalTypeConversionTo);
7938 end;
7939 
7940 procedure TTestResolver.TestAnonymousProc_WithDo;
7941 begin
7942   StartProgram(false);
7943   Add([
7944   'type',
7945   '  TProc = reference to procedure(w: word);',
7946   '  TObject = class end;',
7947   '  TBird = class',
7948   '    {#bool}b: boolean;',
7949   '  end;',
7950   'procedure DoIt({#i}i: longint);',
7951   'var',
7952   '  {#p}p: TProc;',
7953   '  {#bird}bird: TBird;',
7954   'begin',
7955   '  with {@bird}bird do',
7956   '    {@p}p:=procedure({#w}w: word)',
7957   '      begin',
7958   '        {@bool}b:=true;',
7959   '        {@bool}b:=({@w}w+{@i}i)>2;',
7960   '      end;',
7961   'end;',
7962   'begin']);
7963   ParseProgram;
7964 end;
7965 
7966 procedure TTestResolver.TestAnonymousProc_ExceptOn;
7967 begin
7968   StartProgram(false);
7969   Add([
7970   'type',
7971   '  TProc = reference to procedure;',
7972   '  TObject = class end;',
7973   '  Exception = class',
7974   '    {#bool}b: boolean;',
7975   '  end;',
7976   'procedure DoIt;',
7977   'var',
7978   '  {#p}p: TProc;',
7979   'begin',
7980   '  try',
7981   '  except',
7982   '    on {#E}E: Exception do',
7983   '    {@p}p:=procedure',
7984   '      begin',
7985   '        {@E}E.{@bool}b:=true;',
7986   '      end;',
7987   '  end;',
7988   'end;',
7989   'begin']);
7990   ParseProgram;
7991 end;
7992 
7993 procedure TTestResolver.TestAnonymousProc_Nested;
7994 begin
7995   StartProgram(false);
7996   Add([
7997   'type',
7998   '  TProc = reference to procedure;',
7999   '  TObject = class',
8000   '    i: byte;',
8001   '    procedure DoIt;',
8002   '  end;',
8003   'procedure TObject.DoIt;',
8004   'var',
8005   '  p: TProc;',
8006   '  procedure Sub;',
8007   '  begin',
8008   '    p:=procedure',
8009   '      begin',
8010   '        i:=3;',
8011   '        Self.i:=4;',
8012   '        p:=procedure',
8013   '            procedure SubSub;',
8014   '            begin',
8015   '              i:=13;',
8016   '              Self.i:=14;',
8017   '            end;',
8018   '          begin',
8019   '            i:=13;',
8020   '            Self.i:=14;',
8021   '          end;',
8022   '      end;',
8023   '  end;',
8024   'begin',
8025   'end;',
8026   'begin']);
8027   ParseProgram;
8028 end;
8029 
8030 procedure TTestResolver.TestAnonymousProc_ForLoop;
8031 begin
8032   StartProgram(false);
8033   Add([
8034   'type TProc = reference to procedure;',
8035   'procedure Foo(p: TProc);',
8036   'begin',
8037   'end;',
8038   'procedure DoIt;',
8039   'var i: word;',
8040   '  a: word;',
8041   'begin',
8042   '  for i:=1 to 10 do begin',
8043   '    Foo(procedure begin a:=3; end);',
8044   '  end;',
8045   'end;',
8046   'begin',
8047   '  DoIt;']);
8048   ParseProgram;
8049 end;
8050 
8051 procedure TTestResolver.TestRecord;
8052 begin
8053   StartProgram(false);
8054   Add('type');
8055   Add('  {#TRec}TRec = record');
8056   Add('    {#Size}Size: longint;');
8057   Add('  end;');
8058   Add('var');
8059   Add('  {#r}{=TRec}r: TRec;');
8060   Add('begin');
8061   Add('  {@r}r.{@Size}Size:=3;');
8062   ParseProgram;
8063 end;
8064 
8065 procedure TTestResolver.TestRecordVariant;
8066 begin
8067   StartProgram(false);
8068   Add('type');
8069   Add('  {#TRec}TRec = record');
8070   Add('    {#Size}Size: longint;');
8071   Add('    case {#vari}vari: longint of');
8072   Add('    0: ({#b}b: longint)');
8073   Add('  end;');
8074   Add('var');
8075   Add('  {#r}{=TRec}r: TRec;');
8076   Add('begin');
8077   Add('  {@r}r.{@Size}Size:=3;');
8078   Add('  {@r}r.{@vari}vari:=4;');
8079   Add('  {@r}r.{@b}b:=5;');
8080   ParseProgram;
8081 end;
8082 
8083 procedure TTestResolver.TestRecordVariantNested;
8084 begin
8085   StartProgram(false);
8086   Add([
8087   'type',
8088   '  {#TRec}TRec = record',
8089   '    {#Size}Size: longint;',
8090   '    case {#vari}vari: longint of',
8091   '    0: ({#b}b: longint)',
8092   '    1: ({#c}c:',
8093   '          record',
8094   '            {#d}d: longint;',
8095   '            case {#e}e: longint of',
8096   '            0: ({#f}f: longint)',
8097   '          end)',
8098   '  end;',
8099   'var',
8100   '  {#r}{=TRec}r: TRec;',
8101   'begin',
8102   '  {@r}r.{@Size}Size:=3;',
8103   '  {@r}r.{@vari}vari:=4;',
8104   '  {@r}r.{@b}b:=5;',
8105   '  {@r}r.{@c}c.{@d}d:=6;',
8106   '  {@r}r.{@c}c.{@e}e:=7;',
8107   '  {@r}r.{@c}c.{@f}f:=8;']);
8108   ParseProgram;
8109 end;
8110 
8111 procedure TTestResolver.TestRecord_WriteConstParamFail;
8112 begin
8113   StartProgram(false);
8114   Add('type');
8115   Add('  TSmall = record');
8116   Add('    Size: longint;');
8117   Add('  end;');
8118   Add('procedure DoIt(const S: TSmall);');
8119   Add('begin');
8120   Add('  S.Size:=3;');
8121   Add('end;');
8122   Add('begin');
8123   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
8124 end;
8125 
8126 procedure TTestResolver.TestRecord_WriteConstParam_WithDoFail;
8127 begin
8128   StartProgram(false);
8129   Add('type');
8130   Add('  TSmall = record');
8131   Add('    Size: longint;');
8132   Add('  end;');
8133   Add('procedure DoIt(const S: TSmall);');
8134   Add('begin');
8135   Add('  with S do Size:=3;');
8136   Add('end;');
8137   Add('begin');
8138   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
8139 end;
8140 
8141 procedure TTestResolver.TestRecord_WriteNestedConstParamFail;
8142 begin
8143   StartProgram(false);
8144   Add('type');
8145   Add('  TSmall = record');
8146   Add('    Size: longint;');
8147   Add('  end;');
8148   Add('  TBig = record');
8149   Add('    Small: TSmall;');
8150   Add('  end;');
8151   Add('procedure DoIt(const B: TBig);');
8152   Add('begin');
8153   Add('  B.Small.Size:=3;');
8154   Add('end;');
8155   Add('begin');
8156   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
8157 end;
8158 
8159 procedure TTestResolver.TestRecord_WriteNestedConstParamWithDoFail;
8160 begin
8161   StartProgram(false);
8162   Add('type');
8163   Add('  TSmall = record');
8164   Add('    Size: longint;');
8165   Add('  end;');
8166   Add('  TBig = record');
8167   Add('    Small: TSmall;');
8168   Add('  end;');
8169   Add('procedure DoIt(const B: TBig);');
8170   Add('begin');
8171   Add('  with B do with Small do Size:=3;');
8172   Add('end;');
8173   Add('begin');
8174   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
8175 end;
8176 
8177 procedure TTestResolver.TestRecord_TypeCast;
8178 begin
8179   StartProgram(false);
8180   Add([
8181   'type',
8182   '  TAnimal = record',
8183   '    Size: longint;',
8184   '  end;',
8185   '  TBird = record',
8186   '    Length: longint;',
8187   '  end;',
8188   'var',
8189   '  a: TAnimal;',
8190   '  b: TBird;',
8191   'begin',
8192   '  b:=TBird(a);',
8193   '  TAnimal(b).Size:=TBird(a).Length;',
8194   '  ']);
8195   ParseProgram;
8196 end;
8197 
8198 procedure TTestResolver.TestRecord_NewDispose;
8199 begin
8200   StartProgram(false);
8201   Add([
8202   'type',
8203   '  TBird = record',
8204   '    Length: longint;',
8205   '  end;',
8206   '  PBird = ^TBird;',
8207   'var',
8208   '  p: PBird;',
8209   '  q: ^TBird;',
8210   'begin',
8211   '  New(p);',
8212   '  Dispose(p);',
8213   '  New(q);',
8214   '  Dispose(q);',
8215   '  ']);
8216   ParseProgram;
8217 end;
8218 
8219 procedure TTestResolver.TestRecord_Const;
8220 begin
8221   StartProgram(false);
8222   Add([
8223   'type',
8224   '  TPoint = record x, y: longint; end;',
8225   'const r: TPoint = (x:1; y:2);',
8226   'type',
8227   '  TPasSourcePos = Record',
8228   '    FileName: String;',
8229   '    Row, Column: LongWord;',
8230   '  end;',
8231   'const',
8232   '  DefPasSourcePos: TPasSourcePos = (Filename:''''; Row:0; Column:0);',
8233   'begin',
8234   '']);
8235   ParseProgram;
8236 end;
8237 
8238 procedure TTestResolver.TestRecord_Const_DuplicateFail;
8239 begin
8240   StartProgram(false);
8241   Add([
8242   'type',
8243   '  TPoint = record x, y: longint; end;',
8244   'const r: TPoint = (x:1; x:2);',
8245   'begin',
8246   '']);
8247   CheckResolverException('Duplicate identifier "x" at afile.pp(4,20)',nDuplicateIdentifier);
8248 end;
8249 
8250 procedure TTestResolver.TestRecord_Const_ExprMismatchFail;
8251 begin
8252   StartProgram(false);
8253   Add([
8254   'type',
8255   '  TPoint = record x, y: longint; end;',
8256   'const r: TPoint = (x:1; x:2);',
8257   'begin',
8258   '']);
8259   CheckResolverException('Duplicate identifier "x" at afile.pp(4,20)',nDuplicateIdentifier);
8260 end;
8261 
8262 procedure TTestResolver.TestRecord_Const_MissingHint;
8263 begin
8264   StartProgram(false);
8265   Add([
8266   'type',
8267   '  TPoint = record x, y: longint; end;',
8268   'const r: TPoint = (x:1);',
8269   'begin',
8270   '']);
8271   ParseProgram;
8272   CheckResolverHint(mtHint,nMissingFieldsX,'Missing fields: "y"');
8273 end;
8274 
8275 procedure TTestResolver.TestRecord_Const_UntypedFail;
8276 begin
8277   StartProgram(false);
8278   Add([
8279   'const r = (x:1);',
8280   'begin',
8281   '']);
8282   CheckResolverException('Syntax error, "const" expected but "record values" found',nSyntaxErrorExpectedButFound);
8283 end;
8284 
8285 procedure TTestResolver.TestRecord_Const_NestedRecord;
8286 begin
8287   StartProgram(false);
8288   Add([
8289   'type',
8290   '  TPoint = record x, y: longint; end;',
8291   '  TSrc = record',
8292   '    Id: longint;',
8293   '    XY: TPoint',
8294   '  end;',
8295   'const r: TSrc = (Id:1; XY: (x:2; y:3));',
8296   'begin',
8297   '']);
8298   ParseProgram;
8299 end;
8300 
8301 procedure TTestResolver.TestRecord_Const_Variant;
8302 begin
8303   StartProgram(false);
8304   Add([
8305   'type',
8306   '  {#TRec}TRec = record',
8307   '    {#Size}Size: longint;',
8308   '    case {#vari}vari: longint of',
8309   '    0: ({#b}b: longint);',
8310   '    1: ({#c}c:',
8311   '          record',
8312   '            {#d}d: longint;',
8313   '            case {#e}e: longint of',
8314   '            0: ({#f}f: longint)',
8315   '          end)',
8316   '  end;',
8317   'const',
8318   '  {#r}r: TRec = (',
8319   '    {@Size}Size:2;',
8320   '    {@c}c:(',
8321   '      {@d}d:3;',
8322   '      {@f}f:4',
8323   '    )',
8324   '  );',
8325   'begin']);
8326   ParseProgram;
8327 end;
8328 
8329 procedure TTestResolver.TestRecord_Default;
8330 begin
8331   StartProgram(false);
8332   Add([
8333   'type',
8334   '  TPoint = record x, y: longint; end;',
8335   'var',
8336   '  i: longint;',
8337   '  r: TPoint;',
8338   'begin',
8339   '  i:=Default(longint);',
8340   '  r:=Default(r);',
8341   '  r:=Default(TPoint);',
8342   '']);
8343   ParseProgram;
8344 end;
8345 
8346 procedure TTestResolver.TestRecord_VarExternal;
8347 begin
8348   StartProgram(false);
8349   Add([
8350   '{$modeswitch externalclass}',
8351   'type',
8352   '  TRec = record',
8353   '    Id: longint external name ''$Id'';',
8354   '  end;',
8355   'begin']);
8356   ParseProgram;
8357 end;
8358 
8359 procedure TTestResolver.TestRecord_VarSelfFail;
8360 begin
8361   StartProgram(false);
8362   Add([
8363   'type',
8364   '  TRec = record',
8365   '    r: Trec;',
8366   '  end;',
8367   'begin']);
8368   CheckResolverException('type "TRec" is not yet completely defined',nTypeXIsNotYetCompletelyDefined);
8369 end;
8370 
8371 procedure TTestResolver.TestAdvRecord;
8372 begin
8373   StartProgram(false);
8374   Add([
8375   '{$modeswitch advancedrecords}',
8376   'type',
8377   '  TRec = record',
8378   '    procedure DoIt;',
8379   '  end;',
8380   'procedure TRec.DoIt;',
8381   'begin',
8382   'end;',
8383   'begin']);
8384   ParseProgram;
8385 end;
8386 
8387 procedure TTestResolver.TestAdvRecord_Private;
8388 begin
8389   StartProgram(false);
8390   Add([
8391   '{$modeswitch advancedrecords}',
8392   'type',
8393   '  TRec = record',
8394   '  private',
8395   '    a: byte;',
8396   '  public',
8397   '    b: byte;',
8398   '  end;',
8399   'var',
8400   '  r: TRec;',
8401   'begin',
8402   '  r.a:=r.b;']);
8403   ParseProgram;
8404 end;
8405 
8406 procedure TTestResolver.TestAdvRecord_StrictPrivate;
8407 begin
8408   StartProgram(false);
8409   Add([
8410   '{$modeswitch advancedrecords}',
8411   'type',
8412   '  TRec = record',
8413   '  strict private',
8414   '    FSize: longword;',
8415   '    function GetSize: longword;',
8416   '  public',
8417   '    property Size: longword read GetSize write FSize;',
8418   '  end;',
8419   'function TRec.GetSize: longword;',
8420   'begin',
8421   '  FSize:=GetSize;',
8422   'end;',
8423   'var',
8424   '  r: TRec;',
8425   'begin',
8426   '  r.Size:=r.Size;']);
8427   ParseProgram;
8428 end;
8429 
8430 procedure TTestResolver.TestAdvRecord_StrictPrivateFail;
8431 begin
8432   StartProgram(false);
8433   Add([
8434   '{$modeswitch advancedrecords}',
8435   'type',
8436   '  TRec = record',
8437   '  strict private',
8438   '    A: word;',
8439   '  end;',
8440   'var',
8441   '  r: TRec;',
8442   'begin',
8443   '  r.a:=r.a;']);
8444   CheckResolverException('Can''t access strict private member A',nCantAccessXMember);
8445 end;
8446 
8447 procedure TTestResolver.TestAdvRecord_MethodImplMissingFail;
8448 begin
8449   StartProgram(false);
8450   Add([
8451   '{$modeswitch advancedrecords}',
8452   'type',
8453   '  TRec = record',
8454   '    procedure SetSize(Value: word);',
8455   '  end;',
8456   'begin',
8457   '']);
8458   CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
8459 end;
8460 
8461 procedure TTestResolver.TestAdvRecord_VarConst;
8462 begin
8463   StartProgram(false);
8464   Add([
8465   '{$modeswitch advancedrecords}',
8466   'type',
8467   '  TRec = record',
8468   '  type TInt = word;',
8469   '  const',
8470   '    C1 = 3;',
8471   '    C2: TInt = 4;',
8472   '  var',
8473   '    V1: TInt;',
8474   '    V2: TInt;',
8475   '  class var',
8476   '    VC: TInt;',
8477   '    CA: array[1..C1] of TInt;',
8478   '  procedure DoIt;',
8479   '  end;',
8480   'procedure TRec.DoIt;',
8481   'begin',
8482   '  C2:=Self.C2;',
8483   '  V1:=VC;',
8484   '  Self.V1:=Self.VC;',
8485   '  VC:=V1;',
8486   '  Self.VC:=Self.V1;',
8487   'end;',
8488   'var',
8489   '  r: TRec;',
8490   'begin',
8491   '  trec.C2:=trec.C2;',
8492   '  r.V1:=r.VC;',
8493   '  r.V1:=trec.VC;',
8494   '  r.VC:=r.V1;',
8495   '  trec.VC:=trec.c1;',
8496   '  trec.ca[1]:=trec.c2;',
8497   '']);
8498   ParseProgram;
8499 end;
8500 
8501 procedure TTestResolver.TestAdvRecord_RecVal_ConstFail;
8502 begin
8503   StartProgram(false);
8504   Add([
8505   '{$modeswitch advancedrecords}',
8506   'type',
8507   '  TRec = record',
8508   '    V1: word;',
8509   '  const',
8510   '    C1 = 3;',
8511   '  end;',
8512   'var',
8513   '  r: TRec = (V1:2; C1: 4);',
8514   'begin',
8515   '']);
8516   CheckResolverException(sIdentifierXIsNotAnInstanceField,nIdentifierXIsNotAnInstanceField);
8517 end;
8518 
8519 procedure TTestResolver.TestAdvRecord_RecVal_ClassVarFail;
8520 begin
8521   StartProgram(false);
8522   Add([
8523   '{$modeswitch advancedrecords}',
8524   'type',
8525   '  TRec = record',
8526   '    V1: word;',
8527   '  class var',
8528   '    C1: word;',
8529   '  end;',
8530   'var',
8531   '  r: TRec = (V1:2; C1: 4);',
8532   'begin',
8533   '']);
8534   CheckResolverException(sIdentifierXIsNotAnInstanceField,nIdentifierXIsNotAnInstanceField);
8535 end;
8536 
8537 procedure TTestResolver.TestAdvRecord_LocalForwardType;
8538 begin
8539   StartProgram(false);
8540   Add([
8541   '{$modeswitch advancedrecords}',
8542   'type',
8543   '  TRec = record',
8544   '  type',
8545   '    PInt = ^TInt;',
8546   '    TInt = word;',
8547   '  var i: PInt;',
8548   '  end;',
8549   'var',
8550   '  r: TRec;',
8551   'begin',
8552   '']);
8553   ParseProgram;
8554 end;
8555 
8556 procedure TTestResolver.TestAdvRecord_Constructor_NewInstance;
8557 var
8558   aMarker: PSrcMarker;
8559   Elements: TFPList;
8560   ActualNewInstance: Boolean;
8561   i: Integer;
8562   El: TPasElement;
8563   Ref: TResolvedReference;
8564 begin
8565   StartProgram(false);
8566   Add([
8567   '{$modeswitch advancedrecords}',
8568   'type',
8569   '  TRec = record',
8570   '    constructor Create(w: word);',
8571   '    class function DoSome: TRec; static;',
8572   '  end;',
8573   'constructor TRec.Create(w: word);',
8574   'begin',
8575   '  {#a}Create(1); // normal call',
8576   '  TRec.{#b}Create(2); // new instance',
8577   'end;',
8578   'class function TRec.DoSome: TRec;',
8579   'begin',
8580   '  Result:={#c}Create(3); // new instance',
8581   'end;',
8582   'var',
8583   '  r: TRec;',
8584   'begin',
8585   '  TRec.{#p}Create(4); // new object',
8586   '  r:=TRec.{#q}Create(5); // new object',
8587   '  with TRec do begin',
8588   '    {#r}Create(6); // new object',
8589   '    r:={#s}Create(7); // new object',
8590   '  end;',
8591   '  r.{#t}Create(8); // normal call',
8592   '  r:=r.{#u}Create(9); // normal call',
8593   '  with r do begin',
8594   '    {#v}Create(10); // normal call',
8595   '    r:={#w}Create(11); // normal call',
8596   '  end;',
8597   '']);
8598   ParseProgram;
8599   aMarker:=FirstSrcMarker;
8600   while aMarker<>nil do
8601     begin
8602     //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
8603     Elements:=FindElementsAt(aMarker);
8604     try
8605       ActualNewInstance:=false;
8606       for i:=0 to Elements.Count-1 do
8607         begin
8608         El:=TPasElement(Elements[i]);
8609         //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
8610         if not (El.CustomData is TResolvedReference) then continue;
8611         Ref:=TResolvedReference(El.CustomData);
8612         if not (Ref.Declaration is TPasProcedure) then continue;
8613         //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
8614         if (Ref.Declaration is TPasConstructor) then
8615           ActualNewInstance:=rrfNewInstance in Ref.Flags;
8616         if rrfImplicitCallWithoutParams in Ref.Flags then
8617           RaiseErrorAtSrcMarker('unexpected implicit call at "#'+aMarker^.Identifier+' ref"',aMarker);
8618         break;
8619         end;
8620       case aMarker^.Identifier of
8621       'a','t','u','v','w':// should be normal call
8622         if ActualNewInstance then
8623           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
8624       else // should be newinstance
8625         if not ActualNewInstance then
8626           RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
8627       end;
8628     finally
8629       Elements.Free;
8630     end;
8631     aMarker:=aMarker^.Next;
8632     end;
8633 end;
8634 
8635 procedure TTestResolver.TestAdvRecord_ConstructorNoParamsFail;
8636 begin
8637   StartProgram(false);
8638   Add([
8639   '{$modeswitch advancedrecords}',
8640   'type',
8641   '  TRec = record',
8642   '    constructor Create(w: word = 3);',
8643   '  end;',
8644   'constructor TRec.Create(w: word);',
8645   'begin',
8646   'end;',
8647   'begin',
8648   '']);
8649   CheckResolverException(sParameterlessConstructorsNotAllowedInRecords,
8650     nParameterlessConstructorsNotAllowedInRecords);
8651 end;
8652 
8653 procedure TTestResolver.TestAdvRecord_ClassConstructor;
8654 begin
8655   StartProgram(false);
8656   Add([
8657   '{$modeswitch advancedrecords}',
8658   'type',
8659   '  TRec = record',
8660   '    class var w: word;',
8661   '    class procedure {#a}Create; static;',
8662   '    class constructor Create;', // name clash is allowed!
8663   '  end;',
8664   'class constructor TRec.Create;',
8665   'begin',
8666   '  w:=w+1;',
8667   'end;',
8668   'class procedure TRec.Create; static;',
8669   'begin',
8670   '  w:=w+1;',
8671   'end;',
8672   'begin',
8673   '  TRec.{@a}Create;',
8674   '']);
8675   ParseProgram;
8676 end;
8677 
8678 procedure TTestResolver.TestAdvRecord_ClassConstructorParamsFail;
8679 begin
8680   StartProgram(false);
8681   Add([
8682   '{$modeswitch advancedrecords}',
8683   'type',
8684   '  TRec = record',
8685   '    class constructor Create(w: word);',
8686   '  end;',
8687   'class constructor TRec.Create(w: word);',
8688   'begin',
8689   'end;',
8690   'begin',
8691   '']);
8692   CheckResolverException('class constructor cannot have parameters',nXCannotHaveParameters);
8693 end;
8694 
8695 procedure TTestResolver.TestAdvRecord_ClassConstructor_CallFail;
8696 begin
8697   StartProgram(false);
8698   Add([
8699   '{$modeswitch advancedrecords}',
8700   'type',
8701   '  TRec = record',
8702   '    class constructor Create;',
8703   '  end;',
8704   'class constructor TRec.Create;',
8705   'begin',
8706   'end;',
8707   'begin',
8708   '  TRec.Create;',
8709   '']);
8710   CheckResolverException('identifier not found "Create"',nIdentifierNotFound);
8711 end;
8712 
8713 procedure TTestResolver.TestAdvRecord_ClassConstructorDuplicateFail;
8714 begin
8715   StartProgram(false);
8716   Add([
8717   '{$modeswitch advancedrecords}',
8718   'type',
8719   '  TRec = record',
8720   '    class constructor Create;',
8721   '    class constructor Init;',
8722   '  end;',
8723   'class constructor TRec.Create;',
8724   'begin',
8725   'end;',
8726   'class constructor TRec.Init;',
8727   'begin',
8728   'end;',
8729   'begin',
8730   '']);
8731   CheckResolverException('Multiple class constructor in record TRec: Create and Init',
8732     nMultipleXinTypeYNameZCAandB);
8733 end;
8734 
8735 procedure TTestResolver.TestAdvRecord_NestedRecordType;
8736 begin
8737   StartProgram(false);
8738   Add([
8739   '{$modeswitch advancedrecords}',
8740   'type',
8741   '  TRec = record',
8742   '  type',
8743   '    TSub = record',
8744   '      x: word;',
8745   '      class var y: word;',
8746   '      procedure DoSub;',
8747   '    end;',
8748   '  var',
8749   '    Sub: TSub;',
8750   '    procedure DoIt(const r: TRec);',
8751   '  end;',
8752   'procedure TRec.TSub.DoSub;',
8753   'begin',
8754   '  x:=3;',
8755   'end;',
8756   'procedure TRec.DoIt(const r: TRec);',
8757   'begin',
8758   '  Sub.x:=4;',
8759   '  r.Sub.y:=Sub.x;', // class var y is writable, even though r.Sub is not
8760   'end;',
8761   'var r: TRec;',
8762   'begin',
8763   '  r.sub.x:=4;',
8764   '']);
8765   ParseProgram;
8766 end;
8767 
8768 procedure TTestResolver.TestAdvRecord_NestedArgConstFail;
8769 begin
8770   StartProgram(false);
8771   Add([
8772   '{$modeswitch advancedrecords}',
8773   'type',
8774   '  TRec = record',
8775   '  type',
8776   '    TSub = record',
8777   '      x: word;',
8778   '    end;',
8779   '  var',
8780   '    Sub: TSub;',
8781   '    procedure DoIt(const r: TRec);',
8782   '  end;',
8783   'procedure TRec.DoIt(const r: TRec);',
8784   'begin',
8785   '  r.Sub.x:=4;',
8786   'end;',
8787   'begin',
8788   '']);
8789   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
8790 end;
8791 
8792 procedure TTestResolver.TestAdvRecord_Property;
8793 begin
8794   StartProgram(false);
8795   Add([
8796   '{$modeswitch advancedrecords}',
8797   'type',
8798   '  TRec = record',
8799   '  private',
8800   '    FSize: word;',
8801   '    function SizeStored: boolean;',
8802   '    function GetWidth: word;',
8803   '    procedure SetWidth(Value: word);',
8804   '  public',
8805   '    property Size: word read FSize write FSize stored SizeStored default 3;',
8806   '    property Width: word read GetWidth write SetWidth;',
8807   '  end;',
8808   'function TRec.SizeStored: boolean;',
8809   'begin',
8810   'end;',
8811   'function TRec.GetWidth: word;',
8812   'begin',
8813   '  Result:=FSize;',
8814   'end;',
8815   'procedure TRec.SetWidth(Value: word);',
8816   'begin',
8817   '  FSize:=Value;',
8818   'end;',
8819   'var r: TRec;',
8820   'begin',
8821   '  r.Size:=r.Size;',
8822   '  r.Width:=r.Width;',
8823   '']);
8824   ParseProgram;
8825 end;
8826 
8827 procedure TTestResolver.TestAdvRecord_ClassProperty;
8828 begin
8829   StartProgram(false);
8830   Add([
8831   '{$modeswitch advancedrecords}',
8832   'type',
8833   '  TRec = record',
8834   '  private',
8835   '    class var FSize: word;',
8836   '    class function GetWidth: word; static;',
8837   '    class procedure SetWidth(Value: word); static;',
8838   '  public',
8839   '    class property Size: word read FSize write FSize;',
8840   '    class property Width: word read GetWidth write SetWidth;',
8841   '  end;',
8842   'class function TRec.GetWidth: word;',
8843   'begin',
8844   '  Result:=FSize;',
8845   'end;',
8846   'class procedure TRec.SetWidth(Value: word);',
8847   'begin',
8848   '  FSize:=Value;',
8849   'end;',
8850   'begin',
8851   '  TRec.Size:=TRec.Size;',
8852   '  TRec.Width:=TRec.Width;',
8853   '']);
8854   ParseProgram;
8855 end;
8856 
8857 procedure TTestResolver.TestAdvRecord_PropertyDefault;
8858 begin
8859   StartProgram(false);
8860   Add([
8861   '{$modeswitch advancedrecords}',
8862   'type',
8863   '  TRec = record',
8864   '  private',
8865   '    function GetItems(Index: word): word;',
8866   '    procedure SetItems(Index: word; Value: word);',
8867   '  public',
8868   '    property Items[Index: word]: word read GetItems write SetItems; default;',
8869   '  end;',
8870   '  TGlob = record',
8871   '  private',
8872   '    class function GetSizes(Index: word): word; static;',
8873   '    class procedure SetSizes(Index: word; Value: word); static;',
8874   '  public',
8875   '    class property Sizes[Index: word]: word read GetSizes write SetSizes; default;',
8876   '  end;',
8877   'function TRec.GetItems(Index: word): word;',
8878   'begin',
8879   'end;',
8880   'procedure TRec.SetItems(Index: word; Value: word);',
8881   'begin',
8882   'end;',
8883   'class function TGlob.GetSizes(Index: word): word;',
8884   'begin',
8885   'end;',
8886   'class procedure TGlob.SetSizes(Index: word; Value: word);',
8887   'begin',
8888   'end;',
8889   'var',
8890   '  r: TRec;',
8891   '  g: TGlob;',
8892   'begin',
8893   '  r[1]:=r[2];',
8894   '  TGlob[1]:=TGlob[2];',
8895   '']);
8896   ParseProgram;
8897 end;
8898 
8899 procedure TTestResolver.TestAdvRecord_RecordAsFuncResult;
8900 begin
8901   StartProgram(false);
8902   Add([
8903   '{$modeswitch advancedrecords}',
8904   'type',
8905   '  {#A}TRec = record',
8906   '     {#A_i}i: longint;',
8907   '     class function {#A_CreateA}Create: TRec; static;',
8908   '     class function {#A_CreateB}Create(i: longint): TRec; static;',
8909   '  end;',
8910   'function {#F}F: TRec;',
8911   'begin',
8912   '  Result:=default(TRec);',
8913   'end;',
8914   'class function TRec.Create: TRec;',
8915   'begin',
8916   '  Result:=default(TRec);',
8917   'end;',
8918   'class function TRec.Create(i: longint): TRec;',
8919   'begin',
8920   '  Result:=default(TRec);',
8921   '  Result.i:=i;',
8922   'end;',
8923   'var',
8924   '  {#v}{=A}v: TRec;',
8925   'begin',
8926   '  {@v}v:={@F}F;',
8927   '  {@v}v:={@F}F();',
8928   '  if {@v}v={@F}F then ;',
8929   '  if {@v}v={@F}F() then ;',
8930   '  {@v}v:={@A}TRec.{@A_CreateA}Create;',
8931   '  {@v}v:={@A}TRec.{@A_CreateA}Create();',
8932   '  {@v}v:={@A}TRec.{@A_CreateB}Create(3);',
8933   '  {@A}TRec.{@A_CreateA}Create . {@A_i}i:=4;',
8934   '  {@A}TRec.{@A_CreateA}Create().{@A_i}i:=5;',
8935   '  {@A}TRec.{@A_CreateB}Create(3).{@A_i}i:=6;']);
8936   ParseProgram;
8937 end;
8938 
8939 procedure TTestResolver.TestAdvRecord_InheritedFail;
8940 begin
8941   StartProgram(false);
8942   Add([
8943   '{$modeswitch advancedrecords}',
8944   'type',
8945   '  TRec = record',
8946   '    procedure DoIt;',
8947   '  end;',
8948   'procedure TRec.DoIt;',
8949   'begin',
8950   '  inherited;',
8951   'end;',
8952   'begin',
8953   '']);
8954   CheckResolverException('The use of "inherited" is not allowed in a record',
8955     nTheUseOfXisNotAllowedInARecord);
8956 end;
8957 
8958 procedure TTestResolver.TestAdvRecord_ForInEnumerator;
8959 begin
8960   StartProgram(false);
8961   Add([
8962   '{$modeswitch advancedrecords}',
8963   'type',
8964   '  TObject = class end;',
8965   '  TItem = TObject;',
8966   '  TEnumerator = class',
8967   '    FCurrent: TItem;',
8968   '    property Current: TItem read FCurrent;',
8969   '    function MoveNext: boolean;',
8970   '  end;',
8971   '  TBird = record',
8972   '    function GetEnumerator: TEnumerator;',
8973   '  end;',
8974   'function TEnumerator.MoveNext: boolean;',
8975   'begin',
8976   'end;',
8977   'function TBird.GetEnumerator: TEnumerator;',
8978   'begin',
8979   'end;',
8980   'var',
8981   '  b: TBird;',
8982   '  i: TItem;',
8983   '  {#i2}i2: TItem;',
8984   'begin',
8985   '  for i in b do {@i2}i2:=i;']);
8986   ParseProgram;
8987 end;
8988 
8989 procedure TTestResolver.TestAdvRecord_InFunctionFail;
8990 begin
8991   StartProgram(false);
8992   Add([
8993   '{$modeswitch advancedrecords}',
8994   'procedure DoIt;',
8995   'type',
8996   '  TBird = record',
8997   '    class var i: word;',
8998   '  end;',
8999   'var',
9000   '  b: TBird;',
9001   'begin',
9002   'end;',
9003   'begin']);
9004   CheckParserException(sErrRecordVariablesNotAllowed,nErrRecordVariablesNotAllowed);
9005 end;
9006 
9007 procedure TTestResolver.TestAdvRecord_SubClass;
9008 begin
9009   StartProgram(false);
9010   Add([
9011   '{$modeswitch AdvancedRecords}',
9012   'type',
9013   '  TObject = class end;',
9014   '  TPoint = record',
9015   '  type',
9016   '    TBird = class',
9017   '      procedure DoIt;',
9018   '      class procedure Glob;',
9019   '    end;',
9020   '    procedure DoIt(b: TBird);',
9021   '  end;',
9022   'procedure TPoint.TBird.DoIt;',
9023   'begin',
9024   'end;',
9025   'class procedure TPoint.TBird.Glob;',
9026   'begin',
9027   'end;',
9028   'procedure TPoint.DoIt(b: TBird);',
9029   'begin',
9030   'end;',
9031   'begin',
9032   '']);
9033   ParseProgram;
9034 end;
9035 
9036 procedure TTestResolver.TestClass;
9037 begin
9038   StartProgram(false);
9039   Add('type');
9040   Add('  {#TOBJ}TObject = class');
9041   Add('    {#B}b: longint;');
9042   Add('  end;');
9043   Add('var');
9044   Add('  {#C}{=TOBJ}c: TObject;');
9045   Add('begin');
9046   Add('  {@C}c.{@b}b:=3;');
9047   ParseProgram;
9048 end;
9049 
9050 procedure TTestResolver.TestClassDefaultInheritance;
9051 begin
9052   StartProgram(false);
9053   Add('type');
9054   Add('  {#TOBJ}TObject = class');
9055   Add('    {#OBJ_b}b: longint;');
9056   Add('  end;');
9057   Add('  {#A}TClassA = class');
9058   Add('    {#A_c}c: longint;');
9059   Add('  end;');
9060   Add('var');
9061   Add('  {#V}{=A}v: TClassA;');
9062   Add('begin');
9063   Add('  {@V}v.{@A_c}c:=2;');
9064   Add('  {@V}v.{@OBJ_b}b:=3;');
9065   ParseProgram;
9066 end;
9067 
9068 procedure TTestResolver.TestClassTripleInheritance;
9069 begin
9070   StartProgram(false);
9071   Add('type');
9072   Add('  {#TOBJ}TObject = class');
9073   Add('    {#OBJ_a}a: longint;');
9074   Add('    {#OBJ_b}b: longint;');
9075   Add('  end;');
9076   Add('  {#A}TClassA = class');
9077   Add('    {#A_c}c: longint;');
9078   Add('  end;');
9079   Add('  {#B}TClassB = class(TClassA)');
9080   Add('    {#B_d}d: longint;');
9081   Add('  end;');
9082   Add('var');
9083   Add('  {#V}{=B}v: TClassB;');
9084   Add('begin');
9085   Add('  {@V}v.{@B_d}d:=1;');
9086   Add('  {@V}v.{@A_c}c:=2;');
9087   Add('  {@V}v.{@OBJ_B}b:=3;');
9088   Add('  {@V}v.{@Obj_a}a:=4;');
9089   ParseProgram;
9090 end;
9091 
9092 procedure TTestResolver.TestClassInheritanceCycleFail;
9093 begin
9094   StartProgram(false);
9095   Add([
9096   'type A = class(A)',
9097   'begin']);
9098   CheckResolverException(sAncestorCycleDetected,nAncestorCycleDetected);
9099 end;
9100 
9101 procedure TTestResolver.TestClassDefaultVisibility;
9102 var
9103   Elements: TFPList;
9104   El: TPasElement;
9105   aMarker: PSrcMarker;
9106   i: Integer;
9107 begin
9108   StartProgram(false);
9109   Add([
9110   'type',
9111   '  TObject = class',
9112   '    {#B}b: longint;',
9113   '  end;',
9114   '  {$M+}',
9115   '  TPersistent = class',
9116   '    {#C}c: longint;',
9117   '  end;',
9118   '  {$M-}',
9119   '  TPic = class',
9120   '    {#D}d: longint;',
9121   '  end;',
9122   '  TComponent = class(TPersistent)',
9123   '    {#E}e: longint;',
9124   '  end;',
9125   '  TControl = class(TComponent)',
9126   '    {#F}f: longint;',
9127   '  end;',
9128   'begin']);
9129   ParseProgram;
9130   aMarker:=FirstSrcMarker;
9131   while aMarker<>nil do
9132     begin
9133     //writeln('TTestResolver.TestClassDefaultVisibility',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
9134     Elements:=FindElementsAt(aMarker);
9135     try
9136       for i:=0 to Elements.Count-1 do
9137         begin
9138         El:=TPasElement(Elements[i]);
9139         //writeln('TTestResolver.TestClassDefaultVisibility ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
9140         if not (El is TPasVariable) then continue;
9141         case aMarker^.Identifier of
9142         'B','D':
9143           if El.Visibility<>visPublic then
9144             RaiseErrorAtSrcMarker('expected visPublic at #'+aMarker^.Identifier+', but got '+VisibilityNames[El.Visibility],aMarker);
9145         else
9146           if El.Visibility<>visPublished then
9147             RaiseErrorAtSrcMarker('expected visPublished at #'+aMarker^.Identifier+', but got '+VisibilityNames[El.Visibility],aMarker);
9148         end;
9149         break;
9150         end;
9151     finally
9152       Elements.Free;
9153     end;
9154     aMarker:=aMarker^.Next;
9155     end;
9156 end;
9157 
9158 procedure TTestResolver.TestClassForward;
9159 begin
9160   StartProgram(false);
9161   Add('type');
9162   Add('  TObject = class');
9163   Add('  end;');
9164   Add('  {#B_forward}TClassB = class;');
9165   Add('  {#A}TClassA = class');
9166   Add('    {#A_b}{=B_forward}b: TClassB;');
9167   Add('  end;');
9168   Add('  {#B}TClassB = class(TClassA)');
9169   Add('    {#B_a}a: longint;');
9170   Add('    {#B_d}d: longint;');
9171   Add('  end;');
9172   Add('var');
9173   Add('  {#V}{=B}v: TClassB;');
9174   Add('begin');
9175   Add('  {@V}v.{@B_d}d:=1;');
9176   Add('  {@V}v.{@B_a}a:=2;');
9177   Add('  {@V}v.{@A_b}b:=nil;');
9178   Add('  {@V}v.{@A_b}b.{@B_a}a:=3;');
9179   ParseProgram;
9180 end;
9181 
9182 procedure TTestResolver.TestClassForwardAsAncestorFail;
9183 begin
9184   StartProgram(false);
9185   Add('type');
9186   Add('  TObject = class;');
9187   Add('  TBird = class end;');
9188   Add('  TObject = class');
9189   Add('  end;');
9190   Add('var');
9191   Add('  v: TBird;');
9192   Add('begin');
9193   CheckResolverException('Can''t use forward declaration "TObject" as ancestor',
9194     nCantUseForwardDeclarationAsAncestor);
9195 end;
9196 
9197 procedure TTestResolver.TestClassForwardNotResolved;
9198 begin
9199   StartProgram(false);
9200   Add('type');
9201   Add('  TObject = class');
9202   Add('  end;');
9203   Add('  TClassB = class;');
9204   Add('var');
9205   Add('  v: TClassB;');
9206   Add('begin');
9207   CheckResolverException(sForwardTypeNotResolved,
9208     nForwardTypeNotResolved);
9209 end;
9210 
9211 procedure TTestResolver.TestClassForwardDuplicateFail;
9212 begin
9213   StartProgram(false);
9214   Add([
9215   'type',
9216   '  TObject = class;',
9217   '  TObject = class;',
9218   '  TObject = class',
9219   '  end;',
9220   'begin']);
9221   CheckResolverException('Duplicate identifier "TObject" at afile.pp(3,10)',nDuplicateIdentifier);
9222 end;
9223 
9224 procedure TTestResolver.TestClassForwardDelphiFail;
9225 begin
9226   StartProgram(false);
9227   Add([
9228   '{$mode delphi}',
9229   'type',
9230   '  TObject = class end;',
9231   '  TBird = class;',
9232   'const k = 1;',
9233   'type',
9234   '  TBird = class',
9235   '  end;',
9236   'begin']);
9237   CheckResolverException('Forward type not resolved "TBird"',nForwardTypeNotResolved);
9238 end;
9239 
9240 procedure TTestResolver.TestClassForwardObjFPCProgram;
9241 begin
9242   StartProgram(false);
9243   Add([
9244   '{$mode objfpc}',
9245   'type',
9246   '  TObject = class end;',
9247   '  TBird = class;',
9248   'const k = 1;',
9249   'type',
9250   '  TBird = class',
9251   '  end;',
9252   'begin']);
9253   ParseProgram;
9254 end;
9255 
9256 procedure TTestResolver.TestClassForwardObjFPCUnit;
9257 begin
9258   StartUnit(false);
9259   Add([
9260   '{$mode objfpc}',
9261   'interface',
9262   'type',
9263   '  TObject = class end;',
9264   '  TBird = class;',
9265   'const k = 1;',
9266   'type',
9267   '  TBird = class',
9268   '  end;',
9269   'implementation',
9270   'type',
9271   '  TEagle = class;',
9272   'const c = 1;',
9273   'type',
9274   '  TEagle = class',
9275   '  end;',
9276   '']);
9277   ParseUnit;
9278 end;
9279 
9280 procedure TTestResolver.TestClass_Method;
9281 begin
9282   StartProgram(false);
9283   Add('type');
9284   Add('  TObject = class');
9285   Add('  end;');
9286   Add('  {#A}TClassA = class');
9287   Add('    procedure {#A_ProcA_Decl}ProcA;');
9288   Add('  end;');
9289   Add('procedure TClassA.ProcA;');
9290   Add('begin');
9291   Add('end;');
9292   Add('var');
9293   Add('  {#V}{=A}v: TClassA;');
9294   Add('begin');
9295   Add('  {@V}v.{@A_ProcA_Decl}ProcA;');
9296   ParseProgram;
9297 end;
9298 
9299 procedure TTestResolver.TestClass_ConstructorMissingDotFail;
9300 begin
9301   StartProgram(false);
9302   Add([
9303   'type',
9304   '  TObject = class',
9305   '    constructor Create;',
9306   '  end;',
9307   'constructor Create; begin end;',
9308   'begin',
9309   '']);
9310   CheckResolverException('full method name expected, but short name found',
9311     nXExpectedButYFound);
9312 end;
9313 
9314 procedure TTestResolver.TestClass_MethodImplDuplicateFail;
9315 begin
9316   StartProgram(false);
9317   Add([
9318   'type',
9319   '  TObject = class',
9320   '    procedure DoIt;',
9321   '  end;',
9322   'procedure TObject.DoIt; begin end;',
9323   'procedure TObject.DoIt; begin end;',
9324   'begin',
9325   '']);
9326   CheckResolverException('Duplicate identifier "TObject.DoIt" at afile.pp(6,23) at afile.pp (7,23)',
9327     nDuplicateIdentifier);
9328 end;
9329 
9330 procedure TTestResolver.TestClass_MethodWithoutClassFail;
9331 begin
9332   StartProgram(false);
9333   Add('type');
9334   Add('  TObject = class');
9335   Add('  end;');
9336   Add('procedure TClassA.ProcA;');
9337   Add('begin');
9338   Add('end;');
9339   Add('begin');
9340   CheckResolverException('class "TClassA" not found in this module',nClassXNotFoundInThisModule);
9341 end;
9342 
9343 procedure TTestResolver.TestClass_MethodInOtherUnitFail;
9344 begin
9345   AddModuleWithIntfImplSrc('unit1.pas',
9346     LinesToStr([
9347     'type',
9348     '  TObject = class',
9349     '  public',
9350     '  end;',
9351     '']),
9352     '');
9353 
9354   StartProgram(true);
9355   Add([
9356   'uses unit1;',
9357   'procedure TObject.DoIt;',
9358   'begin',
9359   'end;',
9360   'begin']);
9361   CheckResolverException('class "TObject" not found in this module',
9362     nClassXNotFoundInThisModule);
9363 end;
9364 
9365 procedure TTestResolver.TestClass_MethodWithParams;
9366 begin
9367   StartProgram(false);
9368   Add('type');
9369   Add('  {#A}TObject = class');
9370   Add('    procedure {#ProcA_Decl}ProcA({#Bar}Bar: longint);');
9371   Add('  end;');
9372   Add('procedure tobject.proca(bar: longint);');
9373   Add('begin');
9374   Add('  if {@Bar}bar=3 then ;');
9375   Add('end;');
9376   Add('var');
9377   Add('  {#V}{=A}Obj: TObject;');
9378   Add('begin');
9379   Add('  {@V}Obj.{@ProcA_Decl}ProcA(4);');
9380   ParseProgram;
9381 end;
9382 
9383 procedure TTestResolver.TestClass_MethodUnresolvedPrg;
9384 begin
9385   StartProgram(false);
9386   Add('type');
9387   Add('  TObject = class');
9388   Add('  end;');
9389   Add('  TClassA = class');
9390   Add('    procedure ProcA;');
9391   Add('  end;');
9392   Add('begin');
9393   CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
9394 end;
9395 
9396 procedure TTestResolver.TestClass_MethodUnresolvedUnit;
9397 begin
9398   StartUnit(false);
9399   Add('interface');
9400   Add('type');
9401   Add('  TObject = class');
9402   Add('  end;');
9403   Add('  TClassA = class');
9404   Add('    procedure ProcA;');
9405   Add('  end;');
9406   Add('implementation');
9407   CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
9408 end;
9409 
9410 procedure TTestResolver.TestClass_MethodAbstract;
9411 begin
9412   StartProgram(false);
9413   Add('type');
9414   Add('  TObject = class');
9415   Add('    procedure ProcA; virtual; abstract;');
9416   Add('  end;');
9417   Add('begin');
9418   ParseProgram;
9419 end;
9420 
9421 procedure TTestResolver.TestClass_MethodAbstractWithoutVirtualFail;
9422 begin
9423   StartProgram(false);
9424   Add('type');
9425   Add('  TObject = class');
9426   Add('    procedure ProcA; abstract;');
9427   Add('  end;');
9428   Add('begin');
9429   CheckResolverException('Invalid procedure modifier abstract without virtual',nInvalidXModifierY);
9430 end;
9431 
9432 procedure TTestResolver.TestClass_MethodAbstractHasBodyFail;
9433 begin
9434   StartProgram(false);
9435   Add('type');
9436   Add('  TObject = class');
9437   Add('    procedure ProcA; virtual; abstract;');
9438   Add('  end;');
9439   Add('procedure TObject.ProcA;');
9440   Add('begin');
9441   Add('end;');
9442   Add('begin');
9443   CheckResolverException(sAbstractMethodsMustNotHaveImplementation,
9444     nAbstractMethodsMustNotHaveImplementation);
9445 end;
9446 
9447 procedure TTestResolver.TestClass_MethodUnresolvedWithAncestor;
9448 begin
9449   StartProgram(false);
9450   Add('type');
9451   Add('  TObject = class');
9452   Add('    procedure ProcA; virtual; abstract;');
9453   Add('  end;');
9454   Add('  TClassA = class');
9455   Add('    procedure ProcA;');
9456   Add('  end;');
9457   Add('begin');
9458   CheckResolverException(sForwardProcNotResolved,nForwardProcNotResolved);
9459 end;
9460 
9461 procedure TTestResolver.TestClass_ProcFuncMismatch;
9462 begin
9463   StartProgram(false);
9464   Add('type');
9465   Add('  TObject = class');
9466   Add('    procedure DoIt;');
9467   Add('  end;');
9468   Add('function TObject.DoIt: longint;');
9469   Add('begin');
9470   Add('end;');
9471   Add('begin');
9472   CheckResolverException('procedure expected, but function found',
9473     nXExpectedButYFound);
9474 end;
9475 
9476 procedure TTestResolver.TestClass_MethodOverload;
9477 begin
9478   StartProgram(false);
9479   Add('type');
9480   Add('  TObject = class');
9481   Add('    procedure DoIt;');
9482   Add('    procedure DoIt(i: longint);');
9483   Add('    procedure DoIt(s: string);');
9484   Add('  end;');
9485   Add('procedure TObject.DoIt;');
9486   Add('begin');
9487   Add('end;');
9488   Add('procedure TObject.DoIt(i: longint);');
9489   Add('begin');
9490   Add('end;');
9491   Add('procedure TObject.DoIt(s: string);');
9492   Add('begin');
9493   Add('end;');
9494   Add('begin');
9495   ParseProgram;
9496 end;
9497 
9498 procedure TTestResolver.TestClass_MethodInvalidOverload;
9499 begin
9500   StartProgram(false);
9501   Add('type');
9502   Add('  TObject = class');
9503   Add('    procedure DoIt(i: longint);');
9504   Add('    procedure DoIt(k: longint);');
9505   Add('  end;');
9506   Add('procedure TObject.DoIt(i: longint);');
9507   Add('begin');
9508   Add('end;');
9509   Add('procedure TObject.DoIt(k: longint);');
9510   Add('begin');
9511   Add('end;');
9512   Add('begin');
9513   CheckResolverException(sDuplicateIdentifier,nDuplicateIdentifier);
9514 end;
9515 
9516 procedure TTestResolver.TestClass_MethodOverride;
9517 begin
9518   StartProgram(false);
9519   Add('type');
9520   Add('  TObject = class');
9521   Add('    procedure {#TOBJ_ProcA}ProcA; virtual; abstract;');
9522   Add('  end;');
9523   Add('  {#A}TClassA = class');
9524   Add('    procedure {#A_ProcA}ProcA; override;');
9525   Add('  end;');
9526   Add('procedure TClassA.ProcA;');
9527   Add('begin');
9528   Add('end;');
9529   Add('var');
9530   Add('  {#V}{=A}v: TClassA;');
9531   Add('begin');
9532   Add('  {@V}v.{@A_ProcA}ProcA;');
9533   ParseProgram;
9534 end;
9535 
9536 procedure TTestResolver.TestClass_MethodOverride2;
9537 begin
9538   StartProgram(false);
9539   Add('type');
9540   Add('  TObject = class');
9541   Add('    procedure {#TOBJ_ProcA}ProcA; virtual; abstract;');
9542   Add('  end;');
9543   Add('  {#A}TClassA = class');
9544   Add('    procedure {#A_ProcA}ProcA; override;');
9545   Add('  end;');
9546   Add('  {#B}TClassB = class');
9547   Add('    procedure {#B_ProcA}ProcA; override;');
9548   Add('  end;');
9549   Add('procedure TClassA.ProcA;');
9550   Add('begin');
9551   Add('end;');
9552   Add('procedure TClassB.ProcA;');
9553   Add('begin');
9554   Add('end;');
9555   Add('var');
9556   Add('  {#V}{=B}v: TClassB;');
9557   Add('begin');
9558   Add('  {@V}v.{@B_ProcA}ProcA;');
9559   ParseProgram;
9560 end;
9561 
9562 procedure TTestResolver.TestClass_MethodOverrideFixCase;
9563 
9564   procedure CheckOverrideName(aLabel: string);
9565   var
9566     Elements: TFPList;
9567     i: Integer;
9568     El: TPasElement;
9569     Scope: TPasProcedureScope;
9570   begin
9571     Elements:=FindElementsAtSrcLabel(aLabel);
9572     try
9573       for i:=0 to Elements.Count-1 do
9574         begin
9575         El:=TPasElement(Elements[i]);
9576         if not (El is TPasProcedure) then continue;
9577         Scope:=El.CustomData as TPasProcedureScope;
9578         if Scope.OverriddenProc=nil then
9579           Fail('Scope.OverriddenProc=nil');
9580         AssertEquals('Proc Name and Proc.Scope.OverriddenProc.Name',El.Name,Scope.OverriddenProc.Name);
9581         end;
9582     finally
9583       Elements.Free;
9584     end;
9585   end;
9586 
9587 begin
9588   ResolverEngine.Options:=ResolverEngine.Options+[proFixCaseOfOverrides];
9589   StartProgram(false);
9590   Add('type');
9591   Add('  TObject = class');
9592   Add('    procedure {#TOBJ_ProcA}ProcA; virtual; abstract;');
9593   Add('  end;');
9594   Add('  {#A}TClassA = class');
9595   Add('    procedure {#A_ProcA}proca; override;');
9596   Add('  end;');
9597   Add('  {#B}TClassB = class');
9598   Add('    procedure {#B_ProcA}prOca; override;');
9599   Add('  end;');
9600   Add('procedure tclassa.proca;');
9601   Add('begin');
9602   Add('end;');
9603   Add('procedure tclassb.proca;');
9604   Add('begin');
9605   Add('end;');
9606   Add('var');
9607   Add('  {#V}{=B}v: TClassB;');
9608   Add('begin');
9609   Add('  {@V}v.{@B_ProcA}ProcA;');
9610   ParseProgram;
9611   CheckOverrideName('A_ProcA');
9612   CheckOverrideName('B_ProcA');
9613 end;
9614 
9615 procedure TTestResolver.TestClass_MethodOverrideSameResultType;
9616 begin
9617   AddModuleWithIntfImplSrc('unit2.pp',
9618     LinesToStr([
9619     'type',
9620     '  TObject = class',
9621     '  public',
9622     '    function ProcA(const s: string): string; virtual; abstract;',
9623     '  end;',
9624     '']),
9625     LinesToStr([
9626     ''])
9627     );
9628 
9629   StartProgram(true);
9630   Add('uses unit2;');
9631   Add('type');
9632   Add('  TCar = class');
9633   Add('  public');
9634   Add('    function ProcA(const s: string): string; override;');
9635   Add('  end;');
9636   Add('function TCar.ProcA(const s: string): string; begin end;');
9637   Add('begin');
9638   ParseProgram;
9639 end;
9640 
9641 procedure TTestResolver.TestClass_MethodOverrideDiffResultTypeFail;
9642 begin
9643   StartProgram(false);
9644   Add('type');
9645   Add('  TObject = class');
9646   Add('  public');
9647   Add('    function ProcA(const s: string): string; virtual; abstract;');
9648   Add('  end;');
9649   Add('  TCar = class');
9650   Add('  public');
9651   Add('    function ProcA(const s: string): longint; override;');
9652   Add('  end;');
9653   Add('function TCar.ProcA(const s: string): longint; begin end;');
9654   Add('begin');
9655   CheckResolverException('Result type mismatch, expected String, but found Longint',
9656     nResultTypeMismatchExpectedButFound);
9657 end;
9658 
9659 procedure TTestResolver.TestClass_MethodOverrideDiffVarName;
9660 begin
9661   StartProgram(false);
9662   Add([
9663   'type',
9664   '  TObject = class',
9665   '    procedure DoIt(aName: string); virtual; abstract;',
9666   '  end;',
9667   '  TCar = class',
9668   '    procedure DoIt(aCaption: string); override;',
9669   '  end;',
9670   'procedure TCar.DoIt(aCaption: string); begin end;',
9671   'begin'
9672   ]);
9673   ParseProgram;
9674 end;
9675 
9676 procedure TTestResolver.TestClass_MethodOverloadMissingInDelphi;
9677 begin
9678   StartProgram(false);
9679   Add([
9680   '{$mode delphi}',
9681   'type',
9682   '  TObject = class',
9683   '    procedure DoIt(i: longint); virtual; abstract;',
9684   '    procedure DoIt(s: string); virtual; abstract;',
9685   '  end;',
9686   'begin'
9687   ]);
9688   CheckResolverException(sPreviousDeclMissesOverload,nPreviousDeclMissesOverload);
9689 end;
9690 
9691 procedure TTestResolver.TestClass_MethodOverloadAncestor;
9692 begin
9693   StartProgram(false);
9694   Add('type');
9695   Add('  TObject = class');
9696   Add('    procedure {#A1}DoIt;');
9697   Add('    procedure {#B1}DoIt(i: longint);');
9698   Add('  end;');
9699   Add('  TCar = class');
9700   Add('    procedure {#A2}DoIt;');
9701   Add('    procedure {#B2}DoIt(i: longint);');
9702   Add('  end;');
9703   Add('procedure TObject.DoIt; begin end;');
9704   Add('procedure TObject.DoIt(i: longint); begin end;');
9705   Add('procedure TCar.DoIt;');
9706   Add('begin');
9707   Add('  {@A2}DoIt;');
9708   Add('  {@B2}DoIt(1);');
9709   Add('  inherited {@A1}DoIt;');
9710   Add('  inherited {@B1}DoIt(2);');
9711   Add('end;');
9712   Add('procedure TCar.DoIt(i: longint); begin end;');
9713   Add('begin');
9714   ParseProgram;
9715 end;
9716 
9717 procedure TTestResolver.TestClass_MethodOverloadUnit;
9718 begin
9719   StartProgram(true);
9720   Add([
9721   'type',
9722   '  TObject = class',
9723   '    procedure Copy(s: string);',
9724   '  end;',
9725   'procedure TObject.Copy(s: string);',
9726   'var a: array of longint;',
9727   'begin',
9728   '  a:=system.Copy(a,1,3);',
9729   'end;',
9730   'begin']);
9731   ParseProgram;
9732   CheckResolverUnexpectedHints;
9733 end;
9734 
9735 procedure TTestResolver.TestClass_HintMethodHidesNonVirtualMethod;
9736 begin
9737   StartProgram(false);
9738   Add([
9739   'type',
9740   '  TObject = class',
9741   '    procedure DoIt(p: pointer);',
9742   '  end;',
9743   '  TBird = class',
9744   '    procedure DoIt(i: longint);',
9745   '  end;',
9746   'procedure TObject.DoIt(p: pointer);',
9747   'begin',
9748   '  if p=nil then ;',
9749   'end;',
9750   'procedure TBird.DoIt(i: longint); begin end;',
9751   'var b: TBird;',
9752   'begin',
9753   '  b.DoIt(3);']);
9754   ParseProgram;
9755   CheckResolverHint(mtHint,nFunctionHidesIdentifier_NonVirtualMethod,
9756    'function hides identifier at "afile.pp(4,19)". Use overload or reintroduce');
9757 end;
9758 
9759 procedure TTestResolver.
9760   TestClass_HintMethodHidesNonVirtualMethodWithoutBody_NoHint;
9761 begin
9762   AddModuleWithIntfImplSrc('unit2.pas',
9763     LinesToStr([
9764     'type',
9765     '  TObject = class',
9766     '  public',
9767     '    procedure DoIt(p: pointer);',
9768     '  end;',
9769     '']),
9770     LinesToStr([
9771     'procedure TObject.DoIt(p: pointer);',
9772     'begin',
9773     'end;',
9774     '']) );
9775 
9776   StartProgram(true);
9777   Add([
9778   'uses unit2;',
9779   'type',
9780   '  TBird = class',
9781   '    procedure DoIt(i: longint);',
9782   '  end;',
9783   'procedure TBird.DoIt(i: longint); begin end;',
9784   'var b: TBird;',
9785   'begin',
9786   '  b.DoIt(3);']);
9787   ParseProgram;
9788   CheckResolverUnexpectedHints(true);
9789 end;
9790 
9791 procedure TTestResolver.TestClass_NoHintMethodHidesPrivateMethod;
9792 begin
9793   AddModuleWithIntfImplSrc('unit2.pas',
9794     LinesToStr([
9795     'type',
9796     '  TObject = class',
9797     '  private',
9798     '    procedure DoIt(p: pointer);',
9799     '  end;',
9800     '']),
9801     LinesToStr([
9802     'procedure TObject.DoIt(p: pointer);',
9803     'begin',
9804     '  if p=nil then ;',
9805     'end;',
9806     '']) );
9807   StartProgram(true);
9808   Add([
9809   'uses unit2;',
9810   'type',
9811   '  TAnimal = class',
9812   '  strict private',
9813   '    procedure Fly(p: pointer);',
9814   '  end;',
9815   '  TBird = class(TAnimal)',
9816   '    procedure DoIt(i: longint);',
9817   '    procedure Fly(b: boolean);',
9818   '  end;',
9819   'procedure TAnimal.Fly(p: pointer);',
9820   'begin',
9821   '  if p=nil then ;',
9822   'end;',
9823   'procedure TBird.DoIt(i: longint); begin end;',
9824   'procedure TBird.Fly(b: boolean); begin end;',
9825   'var b: TBird;',
9826   'begin',
9827   '  b.DoIt(3);']);
9828   ParseProgram;
9829   CheckResolverUnexpectedHints;
9830 end;
9831 
9832 procedure TTestResolver.TestClass_MethodReintroduce;
9833 begin
9834   StartProgram(false);
9835   Add([
9836   'type',
9837   '  TObject = class',
9838   '    procedure DoIt(p: pointer); virtual; abstract;',
9839   '  end;',
9840   '  TBird = class',
9841   '    procedure DoIt(i: longint); virtual; abstract; reintroduce;',
9842   '    procedure DoIt(s: string); virtual; abstract;',
9843   '  end;',
9844   'begin']);
9845   ParseProgram;
9846   CheckResolverUnexpectedHints;
9847 end;
9848 
9849 procedure TTestResolver.TestClass_MethodOverloadArrayOfTClass;
9850 begin
9851   StartProgram(false);
9852   Add([
9853   'type',
9854   '  TClass = class of TObject;',
9855   '  TObject = class',
9856   '    constructor {#A}Builder(AClass: TClass; AName: string); reintroduce; overload; virtual;',
9857   '    constructor {#B}Builder(AClass: TClass); reintroduce; overload; virtual;',
9858   '    constructor {#C}Builder(AClassArray: Array of TClass); reintroduce; overload; virtual;',
9859   '    constructor {#D}Builder(AName: string); reintroduce; overload; virtual;',
9860   '    constructor {#E}Builder; reintroduce; overload; virtual;',
9861   '    class var ClassName: string;',
9862   '  end;',
9863   '  TTestCase = class end;',
9864   'constructor TObject.Builder(AClass: TClass; AName: string);',
9865   'begin',
9866   '  Builder(AClass);',
9867   'end;',
9868   'constructor TObject.Builder(AClass: TClass);',
9869   'begin',
9870   '  Builder(AClass.ClassName);',
9871   'end;',
9872   'constructor TObject.Builder(AClassArray: Array of TClass);',
9873   'var',
9874   '  i: longint;',
9875   'begin',
9876   '  Builder;',
9877   '  for i := Low(AClassArray) to High(AClassArray) do',
9878   '    if Assigned(AClassArray[i]) then ;',
9879   'end;',
9880   'constructor TObject.Builder(AName: string);',
9881   'begin',
9882   '  Builder();',
9883   'end;',
9884   'constructor TObject.Builder;',
9885   'begin',
9886   'end;',
9887   'var',
9888   '  o: TObject;',
9889   'begin',
9890   '  o.{@A}Builder(TTestCase,''first'');',
9891   '  o.{@B}Builder(TTestCase);',
9892   '  o.{@C}Builder([]);',
9893   '  o.{@C}Builder([TTestCase]);',
9894   '  o.{@C}Builder([TObject,TTestCase]);',
9895   '  o.{@D}Builder(''fourth'');',
9896   '  o.{@E}Builder();',
9897   '  o.{@E}Builder;',
9898   '']);
9899   ParseProgram;
9900 end;
9901 
9902 procedure TTestResolver.TestClass_ConstructorHidesAncestorWarning;
9903 begin
9904   StartProgram(false);
9905   Add([
9906   'type',
9907   '  TObject = class',
9908   '    constructor Create(o: tobject); virtual; abstract;',
9909   '  end;',
9910   '  TBird = class',
9911   '    constructor Create(s: string); virtual; abstract;',
9912   '  end;',
9913   'begin',
9914   '']);
9915   ParseProgram;
9916   CheckResolverHint(mtWarning,nMethodHidesMethodOfBaseType,
9917     'Method "Create" hides method of base type "TObject" at afile.pp(4,23)');
9918   CheckResolverUnexpectedHints;
9919 end;
9920 
9921 procedure TTestResolver.TestClass_ConstructorOverride;
9922 begin
9923   StartProgram(false);
9924   Add([
9925   'type',
9926   '  TObject = class',
9927   '    constructor Create(o: tobject); virtual;',
9928   '  end;',
9929   '  TBird = class',
9930   '    constructor Create(o: tobject); override;',
9931   '  end;',
9932   '  TEagle = class(TBird)',
9933   '    constructor Create(o: tobject); override;',
9934   '  end;',
9935   'constructor tobject.Create(o: tobject); begin end;',
9936   'constructor tbird.Create(o: tobject); begin end;',
9937   'constructor teagle.Create(o: tobject); begin end;',
9938   'var o: TEagle;',
9939   'begin',
9940   '  o:=TEagle.Create(nil);',
9941   '  o:=TEagle.Create(o);',
9942   '']);
9943   ParseProgram;
9944 end;
9945 
9946 procedure TTestResolver.TestClass_ConstructorAccessHiddenAncestorFail;
9947 begin
9948   StartProgram(false);
9949   Add([
9950   'type',
9951   '  TObject = class',
9952   '    constructor Create(o: tobject);',
9953   '  end;',
9954   '  TBird = class',
9955   '    constructor Create(i: longint); reintroduce;',
9956   '  end;',
9957   'constructor tobject.Create(o: tobject); begin end;',
9958   'constructor tbird.Create(i: longint); begin end;',
9959   'var o: TBird;',
9960   'begin',
9961   '  o:=TBird.Create(nil);',
9962   '']);
9963   CheckResolverException('Incompatible type arg no. 1: Got "Nil", expected "Longint"',
9964     nIncompatibleTypeArgNo);
9965 end;
9966 
9967 procedure TTestResolver.TestClass_ConstructorNoteAbstractMethods;
9968 begin
9969   StartProgram(false);
9970   Add([
9971   'type',
9972   '  TObject = class',
9973   '    procedure DoIt; virtual; abstract;',
9974   '    constructor Create; virtual;',
9975   '  end;',
9976   'constructor TObject.Create;',
9977   'begin',
9978   'end;',
9979   'begin',
9980   '  TObject.Create;']);
9981   ParseProgram;
9982   CheckResolverHint(mtWarning,nConstructingClassXWithAbstractMethodY,'Constructing a class "TObject" with abstract method "DoIt"');
9983   CheckResolverUnexpectedHints;
9984 end;
9985 
9986 procedure TTestResolver.TestClass_ConstructorNoNoteAbstractMethods;
9987 begin
9988   StartProgram(false);
9989   Add([
9990   'type',
9991   '  TObject = class',
9992   '    procedure DoIt; virtual; abstract;',
9993   '    constructor Create;',
9994   '  end;',
9995   '  TClass = class of TObject;',
9996   'constructor TObject.Create;',
9997   'begin',
9998   'end;',
9999   'var c: TClass;',
10000   'begin',
10001   '  c.Create;',
10002   '  with c do Create;',
10003   '']);
10004   ParseProgram;
10005   CheckResolverUnexpectedHints;
10006 end;
10007 
10008 procedure TTestResolver.TestClass_MethodScope;
10009 begin
10010   StartProgram(false);
10011   Add('type');
10012   Add('  TObject = class');
10013   Add('  end;');
10014   Add('  {#A}TClassA = class');
10015   Add('    {#A_A}A: longint;');
10016   Add('    procedure {#A_ProcB}ProcB;');
10017   Add('  end;');
10018   Add('procedure TClassA.ProcB;');
10019   Add('begin');
10020   Add('  {@A_A}A:=3;');
10021   Add('end;');
10022   Add('begin');
10023   ParseProgram;
10024 end;
10025 
10026 procedure TTestResolver.TestClass_IdentifierSelf;
10027 begin
10028   StartProgram(false);
10029   Add('type');
10030   Add('  TObject = class');
10031   Add('    {#C}C: longint;');
10032   Add('  end;');
10033   Add('  {#A}TClassA = class');
10034   Add('    {#B}B: longint;');
10035   Add('    procedure {#A_ProcB}ProcB;');
10036   Add('  end;');
10037   Add('procedure TClassA.ProcB;');
10038   Add('begin');
10039   Add('  {@B}B:=1;');
10040   Add('  {@C}C:=2;');
10041   Add('  Self.{@B}B:=3;');
10042   Add('end;');
10043   Add('begin');
10044   ParseProgram;
10045 end;
10046 
10047 procedure TTestResolver.TestClassCallInherited;
10048 begin
10049   StartProgram(false);
10050   Add([
10051   'type',
10052   '  TObject = class',
10053   '    procedure {#TOBJ_ProcA}ProcA(vI: longint); virtual;',
10054   '    procedure {#TOBJ_ProcB}ProcB(vJ: longint); virtual;',
10055   '  end;',
10056   '  {#A}TClassA = class',
10057   '    procedure {#A_ProcA}ProcA({#i1}vI: longint); override;',
10058   '    procedure {#A_ProcB}ProcB(vJ: longint); override;',
10059   '    procedure {#A_ProcC}ProcC; virtual;',
10060   '  end;',
10061   'procedure TObject.ProcA(vi: longint);',
10062   'begin',
10063   '  inherited; // ignore, do not raise error',
10064   'end;',
10065   'procedure TObject.ProcB(vj: longint);',
10066   'begin',
10067   'end;',
10068   'procedure TClassA.ProcA(vi: longint);',
10069   'begin',
10070   '  {@A_ProcA}ProcA({@i1}vI);',
10071   '  {@TOBJ_ProcA}inherited;',
10072   '  inherited {@TOBJ_ProcA}ProcA({@i1}vI);',
10073   '  {@A_ProcB}ProcB({@i1}vI);',
10074   '  inherited {@TOBJ_ProcB}ProcB({@i1}vI);',
10075   'end;',
10076   'procedure TClassA.ProcB(vJ: longint);',
10077   'begin',
10078   'end;',
10079   'procedure TClassA.ProcC;',
10080   'begin',
10081   '  inherited; // ignore, do not raise error',
10082   'end;',
10083   'begin']);
10084   ParseProgram;
10085   CheckResolverUnexpectedHints;
10086 end;
10087 
10088 procedure TTestResolver.TestClassCallInheritedNoParamsAbstractFail;
10089 begin
10090   StartProgram(false);
10091   Add('type');
10092   Add('  TObject = class');
10093   Add('    procedure ProcA; virtual; abstract;');
10094   Add('  end;');
10095   Add('  TClassA = class');
10096   Add('    procedure ProcA; override;');
10097   Add('  end;');
10098   Add('procedure TClassA.ProcA;');
10099   Add('begin');
10100   Add('  inherited;');
10101   Add('end;');
10102   Add('begin');
10103   CheckResolverException('Abstract methods cannot be called directly',
10104     nAbstractMethodsCannotBeCalledDirectly);
10105 end;
10106 
10107 procedure TTestResolver.TestClassCallInheritedWithParamsAbstractFail;
10108 begin
10109   StartProgram(false);
10110   Add('type');
10111   Add('  TObject = class');
10112   Add('    procedure ProcA(c: char); virtual; abstract;');
10113   Add('  end;');
10114   Add('  TClassA = class');
10115   Add('    procedure ProcA(c: char); override;');
10116   Add('  end;');
10117   Add('procedure TClassA.ProcA(c: char);');
10118   Add('begin');
10119   Add('  inherited ProcA(c);');
10120   Add('end;');
10121   Add('begin');
10122   CheckResolverException('Abstract methods cannot be called directly',
10123     nAbstractMethodsCannotBeCalledDirectly);
10124 end;
10125 
10126 procedure TTestResolver.TestClassCallInheritedConstructor;
10127 begin
10128   StartProgram(false);
10129   Add('type');
10130   Add('  TObject = class');
10131   Add('    constructor {#TOBJ_CreateA}Create(vI: longint); virtual;');
10132   Add('  end;');
10133   Add('  {#A}TClassA = class');
10134   Add('    constructor {#A_CreateA}Create({#i1}vI: longint); override;');
10135   Add('  end;');
10136   Add('constructor TObject.Create(vI: longint);');
10137   Add('begin');
10138   Add('  inherited; // ignore and do not raise error');
10139   Add('end;');
10140   Add('constructor TClassA.Create(vI: longint);');
10141   Add('begin');
10142   Add('  {@A_CreateA}Create({@i1}vI);');
10143   Add('  {@TOBJ_CreateA}inherited;');
10144   Add('  inherited {@TOBJ_CreateA}Create({@i1}vI);');
10145   Add('end;');
10146   Add('begin');
10147   ParseProgram;
10148 end;
10149 
10150 procedure TTestResolver.TestClassCallInheritedNested;
10151 begin
10152   StartProgram(false);
10153   Add([
10154   'type',
10155   '  TObject = class',
10156   '    function DoIt: longint; virtual;',
10157   '  end;',
10158   '  TBird = class',
10159   '    function DoIt: longint; override;',
10160   '  end;',
10161   'function tobject.doit: longint;',
10162   'begin',
10163   'end;',
10164   'function tbird.doit: longint;',
10165   '  procedure Sub;',
10166   '  begin',
10167   '    inherited;',
10168   '    inherited DoIt;',
10169   '    if inherited DoIt=4 then ;',
10170   '  end;',
10171   'begin',
10172   '  Sub;',
10173   '  inherited;',
10174   '  inherited DoIt;',
10175   '  if inherited DoIt=14 then ;',
10176   '  with Self do inherited;',
10177   '  with Self do inherited DoIt;',
10178   'end;',
10179   'begin',
10180    '']);
10181   ParseProgram;
10182 end;
10183 
10184 procedure TTestResolver.TestClassCallInheritedAs;
10185 begin
10186   StartProgram(false);
10187   Add([
10188   'type',
10189   '  TObject = class',
10190   '    function GetSome: TObject; virtual;',
10191   '  end;',
10192   '  TBird = class',
10193   '    function GetIt: TBird;',
10194   '  end;',
10195   'function TObject.GetSome: TObject;',
10196   'begin',
10197   'end;',
10198   'function TBird.GetIt: TBird;',
10199   'begin',
10200   '  Result:=inherited GetSome as TBird;',
10201   'end;',
10202   'begin']);
10203   ParseProgram;
10204 end;
10205 
10206 procedure TTestResolver.TestClassAssignNil;
10207 begin
10208   StartProgram(false);
10209   Add('type');
10210   Add('  {#TOBJ}TObject = class');
10211   Add('  end;');
10212   Add('  {#A}TClassA = class');
10213   Add('    {#FSub}FSub: TClassA;');
10214   Add('    property {#Sub}Sub: TClassA read {@FSub}FSub write {@FSub}FSub;');
10215   Add('  end;');
10216   Add('var');
10217   Add('  {#v}{=A}v: TClassA;');
10218   Add('begin');
10219   Add('  {@v}v:=nil;');
10220   Add('  if {@v}v=nil then ;');
10221   Add('  if nil={@v}v then ;');
10222   Add('  if {@v}v<>nil then ;');
10223   Add('  if nil<>{@v}v then ;');
10224   Add('  {@v}v.{@FSub}FSub:=nil;');
10225   Add('  if {@v}v.{@FSub}FSub=nil then ;');
10226   Add('  if {@v}v.{@FSub}FSub<>nil then ;');
10227   Add('  {@v}v.{@Sub}Sub:=nil;');
10228   Add('  if {@v}v.{@Sub}Sub=nil then ;');
10229   Add('  if {@v}v.{@Sub}Sub<>nil then ;');
10230   ParseProgram;
10231 end;
10232 
10233 procedure TTestResolver.TestClassAssign;
10234 begin
10235   StartProgram(false);
10236   Add('type');
10237   Add('  {#TOBJ}TObject = class');
10238   Add('  end;');
10239   Add('  {#A}TClassA = class');
10240   Add('    {#FSub}FSub: TClassA;');
10241   Add('    property {#Sub}Sub: TClassA read {@FSub}FSub write {@FSub}FSub;');
10242   Add('  end;');
10243   Add('var');
10244   Add('  {#o}{=TOBJ}o: TObject;');
10245   Add('  {#v}{=A}v: TClassA;');
10246   Add('  {#p}{=A}p: TClassA;');
10247   Add('begin');
10248   Add('  {@o}o:={@v}v;');
10249   Add('  {@v}v:={@p}p;');
10250   Add('  if {@v}v={@p}p then ;');
10251   Add('  if {@v}v={@o}o then ;');
10252   Add('  if {@o}o={@o}o then ;');
10253   Add('  if {@o}o={@v}v then ;');
10254   Add('  if {@v}v<>{@p}p then ;');
10255   Add('  if {@v}v<>{@o}o then ;');
10256   Add('  if {@o}o<>{@o}o then ;');
10257   Add('  if {@o}o<>{@v}v then ;');
10258   Add('  {@v}v.{@FSub}FSub:={@p}p;');
10259   Add('  {@p}p:={@v}v.{@FSub}FSub;');
10260   Add('  {@o}o:={@v}v.{@FSub}FSub;');
10261   Add('  {@v}v.{@Sub}Sub:={@p}p;');
10262   Add('  {@p}p:={@v}v.{@Sub}Sub;');
10263   Add('  {@o}o:={@v}v.{@Sub}Sub;');
10264   ParseProgram;
10265 end;
10266 
10267 procedure TTestResolver.TestClassNilAsParam;
10268 begin
10269   StartProgram(false);
10270   Add('type');
10271   Add('  {#TOBJ}TObject = class');
10272   Add('  end;');
10273   Add('procedure ProcP(o: TObject);');
10274   Add('begin end;');
10275   Add('begin');
10276   Add('  ProcP(nil);');
10277   ParseProgram;
10278 end;
10279 
10280 procedure TTestResolver.TestClass_Operators_Is_As;
10281 begin
10282   StartProgram(false);
10283   Add('type');
10284   Add('  {#TOBJ}TObject = class');
10285   Add('  end;');
10286   Add('  {#A}TClassA = class');
10287   Add('    {#Sub}Sub: TClassA;');
10288   Add('  end;');
10289   Add('var');
10290   Add('  {#o}{=TOBJ}o: TObject;');
10291   Add('  {#v}{=A}v: TClassA;');
10292   Add('begin');
10293   Add('  if {@o}o is {@A}TClassA then;');
10294   Add('  if {@v}v is {@A}TClassA then;');
10295   Add('  if {@v}v is {@TOBJ}TObject then;');
10296   Add('  if {@v}v.{@Sub}Sub is {@A}TClassA then;');
10297   Add('  {@v}v:={@o}o as {@A}TClassA;');
10298   ParseProgram;
10299 end;
10300 
10301 procedure TTestResolver.TestClass_OperatorIsOnNonTypeFail;
10302 begin
10303   StartProgram(false);
10304   Add('type');
10305   Add('  {#TOBJ}TObject = class');
10306   Add('  end;');
10307   Add('  {#A}TClassA = class');
10308   Add('  end;');
10309   Add('var');
10310   Add('  {#o}{=TOBJ}o: TObject;');
10311   Add('  {#v}{=A}v: TClassA;');
10312   Add('begin');
10313   Add('  if {@o}o is {@v}v then;');
10314   CheckResolverException('class type expected, but class found',
10315     nXExpectedButYFound);
10316 end;
10317 
10318 procedure TTestResolver.TestClass_OperatorAsOnNonDescendantFail;
10319 begin
10320   StartProgram(false);
10321   Add('type');
10322   Add('  {#TOBJ}TObject = class');
10323   Add('  end;');
10324   Add('  {#A}TClassA = class');
10325   Add('  end;');
10326   Add('var');
10327   Add('  {#o}{=TOBJ}o: TObject;');
10328   Add('  {#v}{=A}v: TClassA;');
10329   Add('begin');
10330   Add('  {@o}o:={@v}v as {@TObj}TObject;');
10331   CheckResolverException('Types are not related: "TClassA" and "class TObject" at afile.pp (11,16)',nTypesAreNotRelatedXY);
10332 end;
10333 
10334 procedure TTestResolver.TestClass_OperatorAsOnNonTypeFail;
10335 begin
10336   StartProgram(false);
10337   Add('type');
10338   Add('  {#TOBJ}TObject = class');
10339   Add('  end;');
10340   Add('  {#A}TClassA = class');
10341   Add('  end;');
10342   Add('var');
10343   Add('  {#o}{=TOBJ}o: TObject;');
10344   Add('  {#v}{=A}v: TClassA;');
10345   Add('begin');
10346   Add('  {@o}o:={@v}v as {@o}o;');
10347   CheckResolverException('class expected, but o found',
10348     nXExpectedButYFound);
10349 end;
10350 
10351 procedure TTestResolver.TestClassAsFuncResult;
10352 begin
10353   StartProgram(false);
10354   Add([
10355   'type',
10356   '  {#TOBJ}TObject = class',
10357   '  end;',
10358   '  {#A}TClassA = class',
10359   '     {#A_i}i: longint;',
10360   '     constructor {#A_CreateA}Create;',
10361   '     constructor {#A_CreateB}Create(i: longint);',
10362   '  end;',
10363   'function {#F}F: TClassA;',
10364   'begin',
10365   '  Result:=nil;',
10366   'end;',
10367   'constructor TClassA.Create;',
10368   'begin',
10369   'end;',
10370   'constructor TClassA.Create(i: longint);',
10371   'begin',
10372   'end;',
10373   'var',
10374   '  {#o}{=TOBJ}o: TObject;',
10375   '  {#v}{=A}v: TClassA;',
10376   'begin',
10377   '  {@o}o:={@F}F;',
10378   '  {@o}o:={@F}F();',
10379   '  {@v}v:={@F}F;',
10380   '  {@v}v:={@F}F();',
10381   '  if {@o}o={@F}F then ;',
10382   '  if {@o}o={@F}F() then ;',
10383   '  if {@v}v={@F}F then ;',
10384   '  if {@v}v={@F}F() then ;',
10385   '  {@v}v:={@A}TClassA.{@A_CreateA}Create;',
10386   '  {@v}v:={@A}TClassA.{@A_CreateA}Create();',
10387   '  {@v}v:={@A}TClassA.{@A_CreateB}Create(3);',
10388   '  {@A}TClassA.{@A_CreateA}Create.{@A_i}i:=3;',
10389   '  {@A}TClassA.{@A_CreateA}Create().{@A_i}i:=3;',
10390   '  {@A}TClassA.{@A_CreateB}Create(3).{@A_i}i:=3;']);
10391   ParseProgram;
10392 end;
10393 
10394 procedure TTestResolver.TestClassTypeCast;
10395 begin
10396   StartProgram(false);
10397   Add('type');
10398   Add('  {#TOBJ}TObject = class');
10399   Add('  end;');
10400   Add('  {#A}TClassA = class');
10401   Add('    id: longint;');
10402   Add('  end;');
10403   Add('procedure ProcA(var a: TClassA);');
10404   Add('begin');
10405   Add('end;');
10406   Add('var');
10407   Add('  {#o}{=TOBJ}o: TObject;');
10408   Add('  {#v}{=A}v: TClassA;');
10409   Add('begin');
10410   Add('  {@o}o:={@v}v;');
10411   Add('  {@o}o:=TObject({@o}o);');
10412   Add('  {@v}v:=TClassA({@o}o);');
10413   Add('  {@v}v:=TClassA(TObject({@o}o));');
10414   Add('  {@v}v:=TClassA({@v}v);');
10415   Add('  {@v}v:=v as TClassA;');
10416   Add('  {@v}v:=o as TClassA;');
10417   Add('  ProcA({@v}v);');
10418   Add('  ProcA(TClassA({@o}o));');
10419   Add('  if TClassA({@o}o).id=3 then ;');
10420   Add('  if (o as TClassA).id=3 then ;');
10421   Add('  o:=TObject(nil);');
10422   ParseProgram;
10423 end;
10424 
10425 procedure TTestResolver.TestClassTypeCastUnrelatedWarn;
10426 begin
10427   StartProgram(false);
10428   Add([
10429   'type',
10430   '  {#TOBJ}TObject = class',
10431   '  end;',
10432   '  {#A}TClassA = class',
10433   '    id: longint;',
10434   '  end;',
10435   '  {#B}TClassB = class',
10436   '    Name: string;',
10437   '  end;',
10438   'var',
10439   '  {#o}{=TOBJ}o: TObject;',
10440   '  {#va}{=A}va: TClassA;',
10441   '  {#vb}{=B}vb: TClassB;',
10442   'begin',
10443   '  {@vb}vb:=TClassB({@va}va);']);
10444   ParseProgram;
10445   CheckResolverHint(mtWarning,nClassTypesAreNotRelatedXY,'Class types "TClassA" and "TClassB" are not related');
10446   CheckResolverUnexpectedHints;
10447 end;
10448 
10449 procedure TTestResolver.TestClass_TypeCastSelf;
10450 begin
10451   StartProgram(false);
10452   Add('type');
10453   Add('  TObject = class');
10454   Add('    constructor Create;');
10455   Add('    procedure ProcA;');
10456   Add('  end;');
10457   Add('  TClassA = class');
10458   Add('    id: longint;');
10459   Add('  end;');
10460   Add('constructor TObject.Create;');
10461   Add('begin');
10462   Add('  TClassA(Self).id:=3;');
10463   Add('  if TClassA(Self).id=4 then;');
10464   Add('  if 5=TClassA(Self).id then;');
10465   Add('end;');
10466   Add('procedure TObject.ProcA;');
10467   Add('begin');
10468   Add('  TClassA(Self).id:=3;');
10469   Add('  if TClassA(Self).id=4 then;');
10470   Add('  if 5=TClassA(Self).id then;');
10471   Add('end;');
10472   Add('begin');
10473   ParseProgram;
10474 end;
10475 
10476 procedure TTestResolver.TestClass_TypeCaseMultipleParamsFail;
10477 begin
10478   StartProgram(false);
10479   Add('type');
10480   Add('  TObject = class');
10481   Add('    i: longint;');
10482   Add('  end;');
10483   Add('var o: TObject;');
10484   Add('begin');
10485   Add('  o.i:=TObject(o,o).i;');
10486   CheckResolverException('wrong number of parameters for type cast to TObject',
10487     nWrongNumberOfParametersForTypeCast);
10488 end;
10489 
10490 procedure TTestResolver.TestClass_TypeCastAssign;
10491 begin
10492   StartProgram(false);
10493   Add('type');
10494   Add('  TObject = class');
10495   Add('  end;');
10496   Add('  TCar = class');
10497   Add('  end;');
10498   Add('procedure DoIt(a: TCar; const b: TCar; var c: TCar; out d: TCar); begin end;');
10499   Add('var');
10500   Add('  o: TObject;');
10501   Add('  c: TCar;');
10502   Add('begin');
10503   Add('  TCar({#a_assign}o):=nil;');
10504   Add('  TCar({#b_assign}o):=c;');
10505   Add('  DoIt(TCar({#c1_read}o),TCar({#c2_read}o),TCar({#c3_var}o),TCar({#c4_out}o));');
10506   ParseProgram;
10507   CheckAccessMarkers;
10508 end;
10509 
10510 procedure TTestResolver.TestClass_AccessMemberViaClassFail;
10511 begin
10512   StartProgram(false);
10513   Add('type');
10514   Add('  TObject = class');
10515   Add('    i: longint;');
10516   Add('  end;');
10517   Add('begin');
10518   Add('  if TObject.i=7 then ;');
10519   CheckResolverException(sInstanceMemberXInaccessible,
10520     nInstanceMemberXInaccessible);
10521 end;
10522 
10523 procedure TTestResolver.TestClass_FuncReturningObjectMember;
10524 begin
10525   StartProgram(false);
10526   Add('type');
10527   Add('  TObject = class');
10528   Add('    i: longint;');
10529   Add('  end;');
10530   Add('function FuncO: TObject;');
10531   Add('begin');
10532   Add('end;');
10533   Add('begin');
10534   Add('  FuncO.i:=3;');
10535   Add('  if FuncO.i=4 then ;');
10536   Add('  if 5=FuncO.i then ;');
10537   ParseProgram;
10538 end;
10539 
10540 procedure TTestResolver.TestClass_StaticWithoutClassFail;
10541 begin
10542   StartProgram(false);
10543   Add('type');
10544   Add('  TObject = class');
10545   Add('    procedure ProcA; static;');
10546   Add('  end;');
10547   Add('procedure TObject.ProcA; begin end;');
10548   Add('begin');
10549   CheckResolverException('Invalid procedure modifier static',
10550     nInvalidXModifierY);
10551 end;
10552 
10553 procedure TTestResolver.TestClass_SelfInStaticFail;
10554 begin
10555   StartProgram(false);
10556   Add('type');
10557   Add('  TObject = class');
10558   Add('    class procedure ProcA; static;');
10559   Add('  end;');
10560   Add('class procedure TObject.ProcA;');
10561   Add('begin');
10562   Add('  if Self=nil then ;');
10563   Add('end;');
10564   Add('begin');
10565   CheckResolverException('identifier not found "Self"',nIdentifierNotFound);
10566 end;
10567 
10568 procedure TTestResolver.TestClass_SelfDotInStaticFail;
10569 begin
10570   StartProgram(false);
10571   Add('type');
10572   Add('  TObject = class');
10573   Add('    class var FLeft: word;');
10574   Add('    class function DoIt: word; static;');
10575   Add('    class property Left: word read FLeft;');
10576   Add('  end;');
10577   Add('class function TObject.DoIt: word;');
10578   Add('begin');
10579   Add('  Result:=Self.Left;');
10580   Add('end;');
10581   Add('begin');
10582   CheckResolverException('identifier not found "Self"',nIdentifierNotFound);
10583 end;
10584 
10585 procedure TTestResolver.TestClass_ProcStaticMismatchFail;
10586 begin
10587   StartProgram(false);
10588   Add([
10589   'type',
10590   '  TObject = class',
10591   '    procedure Run;',
10592   '  end;',
10593   'procedure TObject.Run; static;',
10594   'begin',
10595   'end;',
10596   'begin']);
10597   CheckResolverException('Directive "static" not allowed here',nDirectiveXNotAllowedHere);
10598 end;
10599 
10600 procedure TTestResolver.TestClass_PrivateProtectedInSameUnit;
10601 begin
10602   StartProgram(false);
10603   Add('type');
10604   Add('  TObject = class');
10605   Add('  strict private {#vstrictprivate}vstrictprivate: longint;');
10606   Add('  strict protected {#vstrictprotected}vstrictprotected: longint;');
10607   Add('  private {#vprivate}vprivate: longint;');
10608   Add('  protected {#vprotected}vprotected: longint;');
10609   Add('  public {#vpublic}vpublic: longint;');
10610   Add('    procedure ProcA;');
10611   Add('  automated {#vautomated}vautomated: longint;');
10612   Add('  published {#vpublished}vpublished: longint;');
10613   Add('  end;');
10614   Add('procedure TObject.ProcA;');
10615   Add('begin');
10616   Add('  if {@vstrictprivate}vstrictprivate=1 then ;');
10617   Add('  if {@vstrictprotected}vstrictprotected=2 then ;');
10618   Add('  if {@vprivate}vprivate=3 then ;');
10619   Add('  if {@vprotected}vprotected=4 then ;');
10620   Add('  if {@vpublic}vpublic=5 then ;');
10621   Add('  if {@vautomated}vautomated=6 then ;');
10622   Add('  if {@vpublished}vpublished=7 then ;');
10623   Add('end;');
10624   Add('var');
10625   Add('  o: TObject;');
10626   Add('begin');
10627   Add('  if o.vprivate=10 then ;');
10628   Add('  if o.vprotected=11 then ;');
10629   Add('  if o.vpublic=12 then ;');
10630   Add('  if o.vautomated=13 then ;');
10631   Add('  if o.vpublished=14 then ;');
10632   ParseProgram;
10633 end;
10634 
10635 procedure TTestResolver.TestClass_PrivateInMainBeginFail;
10636 begin
10637   AddModuleWithSrc('unit1.pas',
10638     LinesToStr([
10639       'unit unit1;',
10640       'interface',
10641       'type',
10642       '  TObject = class',
10643       '  private v: longint;',
10644       '  end;',
10645       'implementation',
10646       'end.'
10647       ]));
10648   StartProgram(true);
10649   Add('uses unit1;');
10650   Add('var');
10651   Add('  o: TObject;');
10652   Add('begin');
10653   Add('  if o.v=3 then ;');
10654   CheckResolverException('Can''t access private member v',
10655     nCantAccessXMember);
10656 end;
10657 
10658 procedure TTestResolver.TestClass_PrivateInDescendantFail;
10659 begin
10660   AddModuleWithSrc('unit1.pas',
10661     LinesToStr([
10662       'unit unit1;',
10663       'interface',
10664       'type',
10665       '  TObject = class',
10666       '  private v: longint;',
10667       '  end;',
10668       'implementation',
10669       'end.'
10670       ]));
10671   StartProgram(true);
10672   Add('uses unit1;');
10673   Add('type');
10674   Add('  TClassA = class(TObject)');
10675   Add('    procedure ProcA;');
10676   Add('  end;');
10677   Add('procedure TClassA.ProcA;');
10678   Add('begin');
10679   Add('  if v=3 then ;');
10680   Add('end;');
10681   Add('begin');
10682   CheckResolverException('Can''t access private member v',
10683     nCantAccessXMember);
10684 end;
10685 
10686 procedure TTestResolver.TestClass_ProtectedInDescendant;
10687 begin
10688   AddModuleWithSrc('unit1.pas',
10689     LinesToStr([
10690       'unit unit1;',
10691       'interface',
10692       'type',
10693       '  TObject = class',
10694       '  protected vprotected: longint;',
10695       '  strict protected vstrictprotected: longint;',
10696       '  end;',
10697       'implementation',
10698       'end.'
10699       ]));
10700   StartProgram(true);
10701   Add([
10702   'uses unit1;',
10703   'type',
10704   '  TClassA = class(TObject)',
10705   '    procedure ProcA;',
10706   '  end;',
10707   '  TClassB = class(TObject)',
10708   '    procedure ProcB;',
10709   '  end;',
10710   'procedure TClassA.ProcA;',
10711   'begin',
10712   '  if vprotected=3 then ;',
10713   '  if vstrictprotected=4 then ;',
10714   '  if self.vprotected=5 then;',
10715   '  if self.vstrictprotected=6 then;',
10716   '  with self do if vprotected=7 then;',
10717   '  with self do if vstrictprotected=8 then;',
10718   'end;',
10719   'procedure TClassB.ProcB;',
10720   'var A: TClassA;',
10721   'begin',
10722   '  if A.vprotected=9 then;',
10723   '  with A do if vprotected=10 then;',
10724   'end;',
10725   'var A: TClassA;',
10726   'begin',
10727   '  A.vprotected:=11;',
10728   '  with A do vprotected:=12;',
10729   '  // error: A.vstrictprotected:=13; ']);
10730   ParseProgram;
10731 end;
10732 
10733 procedure TTestResolver.TestClass_StrictPrivateInMainBeginFail;
10734 begin
10735   StartProgram(false);
10736   Add('type');
10737   Add('  TObject = class');
10738   Add('  strict private v: longint;');
10739   Add('  end;');
10740   Add('var');
10741   Add('  o: TObject;');
10742   Add('begin');
10743   Add('  if o.v=3 then ;');
10744   CheckResolverException('Can''t access strict private member v',
10745     nCantAccessXMember);
10746 end;
10747 
10748 procedure TTestResolver.TestClass_StrictProtectedInMainBeginFail;
10749 begin
10750   StartProgram(false);
10751   Add('type');
10752   Add('  TObject = class');
10753   Add('  strict protected v: longint;');
10754   Add('  end;');
10755   Add('var');
10756   Add('  o: TObject;');
10757   Add('begin');
10758   Add('  if o.v=3 then ;');
10759   CheckResolverException('Can''t access strict protected member v',
10760     nCantAccessXMember);
10761 end;
10762 
10763 procedure TTestResolver.TestClass_Constructor_NewInstance;
10764 var
10765   aMarker: PSrcMarker;
10766   Elements: TFPList;
10767   i: Integer;
10768   El: TPasElement;
10769   Ref: TResolvedReference;
10770   ActualNewInstance, ActualImplicitCallWithoutParams: Boolean;
10771 begin
10772   StartProgram(false);
10773   Add([
10774   'type',
10775   '  TObject = class',
10776   '    constructor Create;',
10777   '    class function DoSome: TObject;',
10778   '  end;',
10779   'constructor TObject.Create;',
10780   'begin',
10781   '  {#a}Create; // normal call',
10782   '  TObject.{#b}Create; // new instance',
10783   'end;',
10784   'class function TObject.DoSome: TObject;',
10785   'begin',
10786   '  Result:={#c}Create; // new instance',
10787   'end;',
10788   'var',
10789   '  o: TObject;',
10790   'begin',
10791   '  TObject.{#p}Create; // new object',
10792   '  o:=TObject.{#q}Create; // new object',
10793   '  o.{#r}Create; // normal call',
10794   '  o:=o.{#s}Create; // normal call',
10795   '']);
10796   ParseProgram;
10797   aMarker:=FirstSrcMarker;
10798   while aMarker<>nil do
10799     begin
10800     //writeln('TTestResolver.TestClass_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
10801     Elements:=FindElementsAt(aMarker);
10802     try
10803       ActualNewInstance:=false;
10804       ActualImplicitCallWithoutParams:=false;
10805       for i:=0 to Elements.Count-1 do
10806         begin
10807         El:=TPasElement(Elements[i]);
10808         //writeln('TTestResolver.TestClass_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
10809         if not (El.CustomData is TResolvedReference) then continue;
10810         Ref:=TResolvedReference(El.CustomData);
10811         if not (Ref.Declaration is TPasProcedure) then continue;
10812         //writeln('TTestResolver.TestClass_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
10813         if (Ref.Declaration is TPasConstructor) then
10814           ActualNewInstance:=rrfNewInstance in Ref.Flags;
10815         ActualImplicitCallWithoutParams:=rrfImplicitCallWithoutParams in Ref.Flags;
10816         break;
10817         end;
10818       if not ActualImplicitCallWithoutParams then
10819         RaiseErrorAtSrcMarker('expected implicit call at "#'+aMarker^.Identifier+', but got function ref"',aMarker);
10820       case aMarker^.Identifier of
10821       'a','r','s':// should be normal call
10822         if ActualNewInstance then
10823           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
10824       else // should be newinstance
10825         if not ActualNewInstance then
10826           RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
10827       end;
10828     finally
10829       Elements.Free;
10830     end;
10831     aMarker:=aMarker^.Next;
10832     end;
10833 end;
10834 
10835 procedure TTestResolver.TestClass_Destructor_FreeInstance;
10836 var
10837   aMarker: PSrcMarker;
10838   Elements: TFPList;
10839   i: Integer;
10840   El: TPasElement;
10841   Ref: TResolvedReference;
10842   ActualFreeInstance, ActualImplicitCallWithoutParams: Boolean;
10843 begin
10844   StartProgram(false);
10845   Add('type');
10846   Add('  TObject = class');
10847   Add('    destructor Destroy; virtual;');
10848   Add('  end;');
10849   Add('  TChild = class(TObject)');
10850   Add('    destructor DestroyOther;');
10851   Add('  end;');
10852   Add('destructor TObject.Destroy;');
10853   Add('begin');
10854   Add('end;');
10855   Add('destructor TChild.DestroyOther;');
10856   Add('begin');
10857   Add('  {#a}Destroy; // free instance');
10858   Add('  inherited {#b}Destroy; // normal call');
10859   Add('end;');
10860   Add('var');
10861   Add('  c: TChild;');
10862   Add('begin');
10863   Add('  c.{#c}Destroy; // free instance');
10864   Add('  c.{#d}DestroyOther; // free instance');
10865   ParseProgram;
10866   aMarker:=FirstSrcMarker;
10867   while aMarker<>nil do
10868     begin
10869     //writeln('TTestResolver.TestClass_Destructor_FreeInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
10870     Elements:=FindElementsAt(aMarker);
10871     try
10872       ActualFreeInstance:=false;
10873       ActualImplicitCallWithoutParams:=false;
10874       for i:=0 to Elements.Count-1 do
10875         begin
10876         El:=TPasElement(Elements[i]);
10877         //writeln('TTestResolver.TestClass_Destructor_FreeInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
10878         if not (El.CustomData is TResolvedReference) then continue;
10879         Ref:=TResolvedReference(El.CustomData);
10880         if not (Ref.Declaration is TPasProcedure) then continue;
10881         //writeln('TTestResolver.TestClass_Destructor_FreeInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
10882         if (Ref.Declaration is TPasDestructor) then
10883           ActualFreeInstance:=rrfFreeInstance in Ref.Flags;
10884         ActualImplicitCallWithoutParams:=rrfImplicitCallWithoutParams in Ref.Flags;
10885         break;
10886         end;
10887       if not ActualImplicitCallWithoutParams then
10888         RaiseErrorAtSrcMarker('expected implicit call at "#'+aMarker^.Identifier+', but got function ref"',aMarker);
10889       case aMarker^.Identifier of
10890       'b':// should be normal call
10891         if ActualFreeInstance then
10892           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got freeinstance"',aMarker);
10893       else // should be freeinstance
10894         if not ActualFreeInstance then
10895           RaiseErrorAtSrcMarker('expected freeinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
10896       end;
10897     finally
10898       Elements.Free;
10899     end;
10900     aMarker:=aMarker^.Next;
10901     end;
10902 end;
10903 
10904 procedure TTestResolver.TestClass_ConDestructor_CallInherited;
10905 var
10906   aMarker: PSrcMarker;
10907   Elements: TFPList;
10908   i: Integer;
10909   El: TPasElement;
10910   Ref: TResolvedReference;
10911 begin
10912   StartProgram(false);
10913   Add('type');
10914   Add('  TObject = class');
10915   Add('    constructor Create;');
10916   Add('    destructor Destroy; virtual;');
10917   Add('  end;');
10918   Add('  TChild = class(TObject)');
10919   Add('    constructor Create;');
10920   Add('    destructor Destroy; override;');
10921   Add('  end;');
10922   Add('constructor TObject.Create;');
10923   Add('begin');
10924   Add('end;');
10925   Add('destructor TObject.Destroy;');
10926   Add('begin');
10927   Add('end;');
10928   Add('constructor TChild.Create;');
10929   Add('begin');
10930   Add('  {#c}inherited; // normal call');
10931   Add('end;');
10932   Add('destructor TChild.Destroy;');
10933   Add('begin');
10934   Add('  {#d}inherited; // normal call');
10935   Add('end;');
10936   Add('begin');
10937   ParseProgram;
10938   aMarker:=FirstSrcMarker;
10939   while aMarker<>nil do
10940     begin
10941     //writeln('TTestResolver.TestClass_ConDestructor_Inherited ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
10942     Elements:=FindElementsAt(aMarker);
10943     try
10944       for i:=0 to Elements.Count-1 do
10945         begin
10946         El:=TPasElement(Elements[i]);
10947         //writeln('TTestResolver.TestClass_ConDestructor_Inherited ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
10948         if not (El.CustomData is TResolvedReference) then continue;
10949         Ref:=TResolvedReference(El.CustomData);
10950         if not (Ref.Declaration is TPasProcedure) then continue;
10951         //writeln('TTestResolver.TestClass_ConDestructor_Inherited ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
10952         if rrfNewInstance in Ref.Flags then
10953           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
10954         if rrfFreeInstance in Ref.Flags then
10955           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got freeinstance"',aMarker);
10956         break;
10957         end;
10958     finally
10959       Elements.Free;
10960     end;
10961     aMarker:=aMarker^.Next;
10962     end;
10963 end;
10964 
10965 procedure TTestResolver.TestClass_Constructor_Inherited;
10966 begin
10967   StartProgram(false);
10968   Add('type');
10969   Add('  {#TOBJ}TObject = class');
10970   Add('    constructor Create;');
10971   Add('    destructor Destroy;');
10972   Add('    procedure DoIt;');
10973   Add('  end;');
10974   Add('  {#TClassA}TClassA = class');
10975   Add('    Sub: TObject;');
10976   Add('  end;');
10977   Add('constructor TObject.Create; begin end;');
10978   Add('destructor TObject.Destroy; begin end;');
10979   Add('procedure TObject.DoIt; begin end;');
10980   Add('var a: TClassA;');
10981   Add('begin');
10982   Add('  a:=TClassA.Create;');
10983   Add('  a.DoIt;');
10984   Add('  a.Destroy;');
10985   Add('  if TClassA.Create.Sub=nil then ;');
10986   Add('  with TClassA.Create do Sub:=nil;');
10987   Add('  with TClassA do a:=Create;');
10988   Add('  with TClassA do Create.Sub:=nil;');
10989   ParseProgram;
10990 end;
10991 
10992 procedure TTestResolver.TestClass_SubObject;
10993 begin
10994   StartProgram(false);
10995   Add('type');
10996   Add('  {#TOBJ}TObject = class');
10997   Add('    {#Sub}Sub: TObject;');
10998   Add('    procedure DoIt(p: longint);');
10999   Add('    function GetIt(p: longint): TObject;');
11000   Add('  end;');
11001   Add('procedure TObject.DoIt(p: longint); begin end;');
11002   Add('function TObject.GetIt(p: longint): TObject; begin end;');
11003   Add('var o: TObject;');
11004   Add('begin');
11005   Add('  o.Sub:=nil;');
11006   Add('  o.Sub.Sub:=nil;');
11007   Add('  if o.Sub=nil then ;');
11008   Add('  if o.Sub=o.Sub.Sub then ;');
11009   Add('  o.Sub.DoIt(3);');
11010   Add('  o.Sub.GetIt(4);');
11011   Add('  o.Sub.GetIt(5).DoIt(6);');
11012   Add('  o.Sub.GetIt(7).Sub.DoIt(8);');
11013   ParseProgram;
11014 end;
11015 
11016 procedure TTestResolver.TestClass_WithDoClassInstance;
11017 var
11018   aMarker: PSrcMarker;
11019   Elements: TFPList;
11020   ActualRefWith: Boolean;
11021   i: Integer;
11022   El: TPasElement;
11023   Ref: TResolvedReference;
11024 begin
11025   StartProgram(false);
11026   Add('type');
11027   Add('  TObject = class');
11028   Add('    FInt: longint;');
11029   Add('    FObj: TObject;');
11030   Add('    FArr: array of longint;');
11031   Add('    constructor Create;');
11032   Add('    function GetSize: longint;');
11033   Add('    procedure SetSize(Value: longint);');
11034   Add('    function GetItems(Index: longint): longint;');
11035   Add('    procedure SetItems(Index, Value: longint);');
11036   Add('    property Size: longint read GetSize write SetSize;');
11037   Add('    property Items[Index: longint]: longint read GetItems write SetItems;');
11038   Add('  end;');
11039   Add('constructor TObject.Create; begin end;');
11040   Add('function TObject.GetSize: longint; begin end;');
11041   Add('procedure TObject.SetSize(Value: longint); begin end;');
11042   Add('function TObject.GetItems(Index: longint): longint; begin end;');
11043   Add('procedure TObject.SetItems(Index, Value: longint); begin end;');
11044   Add('var');
11045   Add('  Obj: TObject;');
11046   Add('  i: longint;');
11047   Add('begin');
11048   Add('  with TObject.Create do begin');
11049   Add('    {#A}FInt:=3;');
11050   Add('    i:={#B}FInt;');
11051   Add('    i:={#C}GetSize;');
11052   Add('    i:={#D}GetSize();');
11053   Add('    {#E}SetSize(i);');
11054   Add('    i:={#F}Size;');
11055   Add('    {#G}Size:=i;');
11056   Add('    i:={#H}Items[i];');
11057   Add('    {#I}Items[i]:=i;');
11058   Add('    i:={#J}FArr[i];');
11059   Add('    {#K}FArr[i]:=i;');
11060   Add('  end;');
11061   ParseProgram;
11062   aMarker:=FirstSrcMarker;
11063   while aMarker<>nil do
11064     begin
11065     //writeln('TTestResolver.TestClass_WithClassInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
11066     Elements:=FindElementsAt(aMarker);
11067     try
11068       ActualRefWith:=false;
11069       for i:=0 to Elements.Count-1 do
11070         begin
11071         El:=TPasElement(Elements[i]);
11072         //writeln('TTestResolver.TestClass_WithClassInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
11073         if not (El.CustomData is TResolvedReference) then continue;
11074         Ref:=TResolvedReference(El.CustomData);
11075         if Ref.WithExprScope=nil then continue;
11076         ActualRefWith:=true;
11077         break;
11078         end;
11079       if not ActualRefWith then
11080         RaiseErrorAtSrcMarker('expected Ref.WithExprScope<>nil at "#'+aMarker^.Identifier+', but got nil"',aMarker);
11081     finally
11082       Elements.Free;
11083     end;
11084     aMarker:=aMarker^.Next;
11085     end;
11086 end;
11087 
11088 procedure TTestResolver.TestClass_ProcedureExternal;
11089 begin
11090   StartProgram(false);
11091   Add('type');
11092   Add('  TObject = class');
11093   Add('    procedure DoIt; external ''somewhere'';');
11094   Add('  end;');
11095   Add('begin');
11096   ParseProgram;
11097 end;
11098 
11099 procedure TTestResolver.TestClass_ReintroducePublicVarObjFPCFail;
11100 begin
11101   StartProgram(false);
11102   Add([
11103   'type',
11104   '  TObject = class',
11105   '  public',
11106   '    Some: longint;',
11107   '  end;',
11108   '  TCar = class(tobject)',
11109   '  public',
11110   '    Some: longint;',
11111   '  end;',
11112   'begin']);
11113   CheckResolverException('Duplicate identifier "Some" at afile.pp(5,5)',nDuplicateIdentifier);
11114 end;
11115 
11116 procedure TTestResolver.TestClass_ReintroducePublicVarDelphi;
11117 begin
11118   StartProgram(false);
11119   Add([
11120   '{$mode delphi}',
11121   'type',
11122   '  TObject = class',
11123   '  public',
11124   '    {#Obj_Some}Some: longint;',
11125   '    {#Obj_Foo}Foo: word;',
11126   '    function {#Obj_Bar}Bar: string;',
11127   '  end;',
11128   '  TCar = class(tobject)',
11129   '  public',
11130   '    {#Car_Some}Some: double;',
11131   '    function {#Car_Foo}Foo: boolean;',
11132   '    {#Car_Bar}Bar: single;',
11133   '  end;',
11134   'function TObject.Bar: string;',
11135   'begin',
11136   'end;',
11137   'function TCar.Foo: boolean;',
11138   'begin',
11139   '  {@Car_Some}Some:=3.3;',
11140   '  {@Car_Bar}Bar:=4.3;',
11141   '  inherited {@Obj_Bar}Bar;',
11142   '  inherited {@Obj_Bar}Bar();',
11143   '  inherited {@Obj_Foo}Foo := 4;',
11144   '  if inherited {@Obj_Some}Some = 5 then ;',
11145   'end;',
11146   'var C: TCar;',
11147   'begin',
11148   '  C.Some:=1.3;']);
11149   ParseProgram;
11150 end;
11151 
11152 procedure TTestResolver.TestClass_ReintroducePrivateVar;
11153 begin
11154   StartProgram(false);
11155   Add('type');
11156   Add('  TObject = class');
11157   Add('  strict private');
11158   Add('    Some: longint;');
11159   Add('  end;');
11160   Add('  TCar = class(tobject)');
11161   Add('  public');
11162   Add('    Some: longint;');
11163   Add('  end;');
11164   Add('begin');
11165   ParseProgram;
11166 end;
11167 
11168 procedure TTestResolver.TestClass_ReintroduceProc;
11169 begin
11170   StartProgram(false);
11171   Add('type');
11172   Add('  TObject = class');
11173   Add('  strict private');
11174   Add('    Some: longint;');
11175   Add('  end;');
11176   Add('  TMobile = class');
11177   Add('  strict private');
11178   Add('    Some: string;');
11179   Add('  end;');
11180   Add('  TCar = class(tmobile)');
11181   Add('    procedure {#A}Some;');
11182   Add('    procedure {#B}Some(vA: longint);');
11183   Add('  end;');
11184   Add('procedure tcar.some;');
11185   Add('begin');
11186   Add('  {@A}Some;');
11187   Add('  {@B}Some(1);');
11188   Add('end;');
11189   Add('procedure tcar.some(va: longint); begin end;');
11190   Add('begin');
11191   ParseProgram;
11192 end;
11193 
11194 procedure TTestResolver.TestClass_UntypedParam_TypeCast;
11195 begin
11196   StartProgram(false);
11197   Add('type');
11198   Add('  TObject = class end;');
11199   Add('procedure {#ProcA}ProcA(var {#A}A);');
11200   Add('begin');
11201   Add('  TObject({@A}A):=TObject({@A}A);');
11202   Add('  if TObject({@A}A)=nil then ;');
11203   Add('  if nil=TObject({@A}A) then ;');
11204   Add('end;');
11205   Add('procedure {#ProcB}ProcB(const {#B}B);');
11206   Add('begin');
11207   Add('  if TObject({@B}B)=nil then ;');
11208   Add('  if nil=TObject({@B}B) then ;');
11209   Add('end;');
11210   Add('var o: TObject;');
11211   Add('begin');
11212   Add('  {@ProcA}ProcA(o);');
11213   Add('  {@ProcB}ProcB(o);');
11214   ParseProgram;
11215 end;
11216 
11217 procedure TTestResolver.TestClass_Sealed;
11218 begin
11219   StartProgram(false);
11220   Add('type');
11221   Add('  TObject = class sealed');
11222   Add('  end;');
11223   Add('begin');
11224   ParseProgram;
11225 end;
11226 
11227 procedure TTestResolver.TestClass_SealedDescendFail;
11228 begin
11229   StartProgram(false);
11230   Add('type');
11231   Add('  TObject = class sealed');
11232   Add('  end;');
11233   Add('  TNop = class(TObject)');
11234   Add('  end;');
11235   Add('begin');
11236   CheckResolverException(sCannotCreateADescendantOfTheSealedXY,
11237     nCannotCreateADescendantOfTheSealedXY);
11238 end;
11239 
11240 procedure TTestResolver.TestClass_Abstract;
11241 begin
11242   StartProgram(false);
11243   Add([
11244   'type',
11245   '  TObject = class',
11246   '    constructor Create;',
11247   '  end;',
11248   '  TNop = class abstract(TObject)',
11249   '  end;',
11250   '  TBird = class(TNop)',
11251   '    constructor Create(w: word);',
11252   '  end;',
11253   'constructor TObject.Create;',
11254   'begin',
11255   'end;',
11256   'constructor TBird.Create(w: word);',
11257   'begin',
11258   '  inherited Create;',
11259   'end;',
11260   'begin',
11261   '  TBird.Create;']);
11262   ParseProgram;
11263   CheckResolverUnexpectedHints;
11264 end;
11265 
11266 procedure TTestResolver.TestClass_AbstractCreateFail;
11267 begin
11268   StartProgram(false);
11269   Add([
11270   'type',
11271   '  TObject = class',
11272   '    constructor Create;',
11273   '  end;',
11274   '  TNop = class abstract(TObject)',
11275   '  end;',
11276   'constructor TObject.Create;',
11277   'begin',
11278   'end;',
11279   'begin',
11280   '  TNop.Create;']);
11281   ParseProgram;
11282   CheckResolverHint(mtWarning,nCreatingAnInstanceOfAbstractClassY,
11283     'Creating an instance of abstract class "TNop"');
11284 end;
11285 
11286 procedure TTestResolver.TestClass_VarExternal;
11287 begin
11288   StartProgram(false);
11289   Add('{$modeswitch externalclass}');
11290   Add('type');
11291   Add('  TExtA = class external name ''ExtA''');
11292   Add('    Id: longint external name ''$Id'';');
11293   Add('    Data: longint external name ''$Data'';');
11294   Add('  end;');
11295   Add('begin');
11296   ParseProgram;
11297 end;
11298 
11299 procedure TTestResolver.TestClass_WarnOverrideLowerVisibility;
11300 begin
11301   StartProgram(false);
11302   Add('type');
11303   Add('  TObject = class');
11304   Add('  strict protected');
11305   Add('    procedure DoStrictProtected; virtual; abstract;');
11306   Add('  protected');
11307   Add('    procedure DoProtected; virtual; abstract;');
11308   Add('  public');
11309   Add('    procedure DoPublic; virtual; abstract;');
11310   Add('  published');
11311   Add('    procedure DoPublished; virtual; abstract;');
11312   Add('  end;');
11313   Add('  TBird = class(TObject)');
11314   Add('  private');
11315   Add('    procedure DoStrictProtected; override;');
11316   Add('    procedure DoProtected; override;');
11317   Add('  protected');
11318   Add('    procedure DoPublic; override;');
11319   Add('    procedure DoPublished; override;');
11320   Add('  end;');
11321   Add('procedure TBird.DoStrictProtected; begin end;');
11322   Add('procedure TBird.DoProtected; begin end;');
11323   Add('procedure TBird.DoPublic; begin end;');
11324   Add('procedure TBird.DoPublished; begin end;');
11325   Add('begin');
11326   ParseProgram;
11327   CheckResolverHint(mtNote,nVirtualMethodXHasLowerVisibility,
11328     'Virtual method "DoStrictProtected" has a lower visibility (private) than parent class TObject (strict protected)');
11329   CheckResolverHint(mtNote,nVirtualMethodXHasLowerVisibility,
11330     'Virtual method "DoProtected" has a lower visibility (private) than parent class TObject (protected)');
11331   CheckResolverHint(mtNote,nVirtualMethodXHasLowerVisibility,
11332     'Virtual method "DoPublic" has a lower visibility (protected) than parent class TObject (public)');
11333   CheckResolverHint(mtNote,nVirtualMethodXHasLowerVisibility,
11334     'Virtual method "DoPublished" has a lower visibility (protected) than parent class TObject (published)');
11335   CheckResolverUnexpectedHints;
11336 end;
11337 
11338 procedure TTestResolver.TestClass_Const;
11339 begin
11340   StartProgram(false);
11341   Add([
11342   'type',
11343   '  integer = longint;',
11344   '  TClass = class of TObject;',
11345   '  TObject = class',
11346   '  strict private const',
11347   '    Prefix = ''binary'';',
11348   '    PrefixLength = Length(Prefix);',
11349   '  public',
11350   '    const cI: integer = 3;',
11351   '    procedure DoIt;',
11352   '    class procedure DoMore;',
11353   '  end;',
11354   'procedure tobject.doit;',
11355   'begin',
11356   '  if cI=4 then;',
11357   '  if 5=cI then;',
11358   '  if Self.cI=6 then;',
11359   '  if 7=Self.cI then;',
11360   '  with Self do begin',
11361   '    if cI=11 then;',
11362   '    if 12=cI then;',
11363   '  end;',
11364   'end;',
11365   'class procedure tobject.domore;',
11366   'begin',
11367   '  if cI=8 then;',
11368   '  if Self.cI=9 then;',
11369   '  if 10=cI then;',
11370   '  if 11=Self.cI then;',
11371   '  with Self do begin',
11372   '    if cI=13 then;',
11373   '    if 14=cI then;',
11374   '  end;',
11375   'end;',
11376   'var',
11377   '  Obj: TObject;',
11378   '  Cla: TClass;',
11379   'begin',
11380   '  if TObject.cI=21 then ;',
11381   '  if Obj.cI=22 then ;',
11382   '  if Cla.cI=23 then ;',
11383   '  with obj do if ci=24 then;',
11384   '  with TObject do if ci=25 then;',
11385   '  with Cla do if ci=26 then;']);
11386   ParseProgram;
11387   CheckResolverUnexpectedHints;
11388 end;
11389 
11390 procedure TTestResolver.TestClass_ClassMissingVarFail;
11391 begin
11392   StartProgram(false);
11393   Add([
11394   'type',
11395   '  TObject = class',
11396   '    class c: word;',
11397   '  end;',
11398   'begin']);
11399   CheckParserException('Expected "Procedure" or "Function"',nParserExpectToken2Error);
11400 end;
11401 
11402 procedure TTestResolver.TestClass_ClassConstFail;
11403 begin
11404   StartProgram(false);
11405   Add([
11406   'type',
11407   '  TObject = class',
11408   '    class const c = 1;',
11409   '  end;',
11410   'begin']);
11411   CheckParserException(sParserExpectToken2Error,nParserExpectToken2Error);
11412 end;
11413 
11414 procedure TTestResolver.TestClass_Enumerator;
11415 begin
11416   StartProgram(false);
11417   Add([
11418   'type',
11419   '  TObject = class end;',
11420   '  TItem = TObject;',
11421   '  TEnumerator = class',
11422   '    FCurrent: TItem;',
11423   '    property Current: TItem read FCurrent;',
11424   '    function MoveNext: boolean;',
11425   '  end;',
11426   '  TBird = class',
11427   '    function GetEnumerator: TEnumerator;',
11428   '  end;',
11429   'function TEnumerator.MoveNext: boolean;',
11430   'begin',
11431   'end;',
11432   'function TBird.GetEnumerator: TEnumerator;',
11433   'begin',
11434   'end;',
11435   'var',
11436   '  b: TBird;',
11437   '  i: TItem;',
11438   '  {#i2}i2: TItem;',
11439   'begin',
11440   '  for i in b do {@i2}i2:=i;']);
11441   ParseProgram;
11442 end;
11443 
11444 procedure TTestResolver.TestClass_EnumeratorFunc;
11445 begin
11446   StartProgram(false);
11447   Add([
11448   'type',
11449   '  TObject = class end;',
11450   '  TItem = longint;',
11451   '  TEnumerator = class',
11452   '    FCurrent: TItem;',
11453   '    property Current: TItem read FCurrent;',
11454   '    function MoveNext: boolean;',
11455   '    function GetEnumerator: TEnumerator;',
11456   '  end;',
11457   'function TEnumerator.MoveNext: boolean;',
11458   'begin',
11459   'end;',
11460   'function TEnumerator.GetEnumerator: TEnumerator;',
11461   'begin',
11462   'end;',
11463   'function GetIt: TEnumerator;',
11464   'begin',
11465   'end;',
11466   'var',
11467   '  i, i2: TItem;',
11468   'begin',
11469   '  for i in GetIt do i2:=i;']);
11470   ParseProgram;
11471 end;
11472 
11473 procedure TTestResolver.TestClass_ForInPropertyStaticArray;
11474 begin
11475   StartProgram(false);
11476   Add([
11477   'type',
11478   '  TMonthNameArray = array [1..12] of string;',
11479   '  TMonthNames = TMonthNameArray;',
11480   '  TObject = class',
11481   '  private',
11482   '    function GetLongMonthNames: TMonthNames; virtual; abstract;',
11483   '  public',
11484   '    Property LongMonthNames : TMonthNames Read GetLongMonthNames;',
11485   '  end;',
11486   'var f: TObject;',
11487   '  Month: string;',
11488   'begin',
11489   '  for Month in f.LongMonthNames do ;',
11490   '']);
11491   ParseProgram;
11492 end;
11493 
11494 procedure TTestResolver.TestClass_TypeAlias;
11495 begin
11496   StartProgram(false);
11497   Add([
11498   'type',
11499   '  TObject = class',
11500   '  end;',
11501   '  TBird = type TObject;',
11502   'var',
11503   '  o: TObject;',
11504   '  b: TBird;',
11505   'begin',
11506   '  o:=b;',
11507   '']);
11508   ParseProgram;
11509 end;
11510 
11511 procedure TTestResolver.TestClass_Message;
11512 begin
11513   StartProgram(false);
11514   Add([
11515   'const',
11516   '  FlyId = 2;',
11517   '  RunStr = ''Fast'';',
11518   'type',
11519   '  TObject = class',
11520   '    procedure Fly(var msg); message 3+FlyId;',
11521   '    procedure Run(var msg); virtual; abstract; message ''prefix''+RunStr;',
11522   '  end;',
11523   'procedure TObject.Fly(var msg);',
11524   'begin',
11525   'end;',
11526   'begin',
11527   '']);
11528   ParseProgram;
11529 end;
11530 
11531 procedure TTestResolver.TestClass_Message_MissingParamFail;
11532 begin
11533   StartProgram(false);
11534   Add([
11535   'type',
11536   '  TObject = class',
11537   '    procedure Fly; message 3;',
11538   '  end;',
11539   'procedure TObject.Fly;',
11540   'begin',
11541   'end;',
11542   'begin',
11543   '']);
11544   CheckResolverException(sMessageHandlersInvalidParams,nMessageHandlersInvalidParams);
11545 end;
11546 
11547 procedure TTestResolver.TestClass_PublishedClassVarFail;
11548 begin
11549   StartProgram(false);
11550   Add('type');
11551   Add('  TObject = class');
11552   Add('  published');
11553   Add('    class var Id: longint;');
11554   Add('  end;');
11555   Add('begin');
11556   CheckResolverException(sSymbolCannotBePublished,nSymbolCannotBePublished);
11557 end;
11558 
11559 procedure TTestResolver.TestClass_PublishedClassPropertyFail;
11560 begin
11561   StartProgram(false);
11562   Add('type');
11563   Add('  TObject = class');
11564   Add('    class var FA: longint;');
11565   Add('  published');
11566   Add('    class property A: longint read FA;');
11567   Add('  end;');
11568   Add('begin');
11569   CheckResolverException('Invalid published property modifier "class"',
11570     nInvalidXModifierY);
11571 end;
11572 
11573 procedure TTestResolver.TestClass_PublishedClassFunctionFail;
11574 begin
11575   StartProgram(false);
11576   Add('type');
11577   Add('  TObject = class');
11578   Add('  published');
11579   Add('    class procedure DoIt;');
11580   Add('  end;');
11581   Add('class procedure TObject.DoIt; begin end;');
11582   Add('begin');
11583   CheckResolverException(sSymbolCannotBePublished,nSymbolCannotBePublished);
11584 end;
11585 
11586 procedure TTestResolver.TestClass_PublishedOverloadFail;
11587 begin
11588   StartProgram(false);
11589   Add('type');
11590   Add('  TObject = class');
11591   Add('  published');
11592   Add('    procedure DoIt;');
11593   Add('    procedure DoIt(i: longint);');
11594   Add('  end;');
11595   Add('procedure TObject.DoIt; begin end;');
11596   Add('procedure TObject.DoIt(i: longint); begin end;');
11597   Add('begin');
11598   CheckResolverException(sDuplicatePublishedMethodXAtY,nDuplicatePublishedMethodXAtY);
11599 end;
11600 
11601 procedure TTestResolver.TestNestedClass;
11602 begin
11603   StartProgram(false);
11604   Add([
11605   'type',
11606   '  TObject = class end;',
11607   '  TBear = class',
11608   '  type',
11609   '    TNumber = byte;',
11610   '    TLeg = class',
11611   '      constructor Create(i: TNumber);',
11612   '      function {#Walk}Walk(i: TNumber): TLeg;',
11613   '    end;',
11614   '    procedure Move(i: TNumber);',
11615   '  end;',
11616   'procedure TBear.Move(i: TNumber);',
11617   'var Leg: TLeg;',
11618   'begin',
11619   '  Leg:=TLeg.Create(i);',
11620   '  Leg:=TBear.TLeg.Create(i);',
11621   'end;',
11622   'constructor tBear.tLeg.Create(i: TNumber);',
11623   'begin',
11624   '  {@Walk}Walk(i);',
11625   '  Self.{@Walk}Walk(i);',
11626   'end;',
11627   'function tBear.tLeg.walk(i: TNumber): TLeg;',
11628   'begin',
11629   '  Result:=Walk(3);',
11630   'end;',
11631   'var Leg: TBear.TLeg;',
11632   'begin',
11633   '  Leg:=TBear.TLeg.Create(2);',
11634   '  Leg:=Leg.Walk(3);',
11635   '']);
11636   ParseProgram;
11637 end;
11638 
11639 procedure TTestResolver.TestNestedClass_Forward;
11640 begin
11641   StartProgram(false);
11642   Add([
11643   'type',
11644   '  TObject = class',
11645   '  type',
11646   '    TArm = class;',
11647   '    TLeg = class',
11648   '      procedure Send(Arm: TArm);',
11649   '    end;',
11650   '    TArm = class',
11651   '      i: byte;',
11652   '    end;',
11653   '  end;',
11654   'procedure tObject.tLeg.send(Arm: TArm);',
11655   'begin',
11656   '  Arm.i:=3;',
11657   'end;',
11658   'var',
11659   '  Leg: TObject.TLeg;',
11660   '  Arm: TObject.TArm;',
11661   'begin',
11662   '  Leg.Send(Arm);',
11663   '']);
11664   ParseProgram;
11665 end;
11666 
11667 procedure TTestResolver.TestNestedClass_StrictPrivateFail;
11668 begin
11669   StartProgram(false);
11670   Add([
11671   'type',
11672   '  TObject = class',
11673   '  strict private type',
11674   '    TArm = class',
11675   '      i: byte;',
11676   '    end;',
11677   '  end;',
11678   'var',
11679   '  Arm: TObject.TArm;',
11680   'begin',
11681   '']);
11682   CheckResolverException('Can''t access strict private member TArm',nCantAccessXMember);
11683 end;
11684 
11685 procedure TTestResolver.TestNestedClass_AccessStrictPrivate;
11686 begin
11687   StartProgram(false);
11688   Add([
11689   'type',
11690   '  TObject = class',
11691   '  public type',
11692   '    TWing = class',
11693   '      procedure Fly;',
11694   '    end;',
11695   '  strict private',
11696   '    class var i: longint;',
11697   '  end;',
11698   'procedure TObject.TWing.Fly;',
11699   'begin',
11700   '  i:=3;',
11701   'end;',
11702   'begin']);
11703   ParseProgram;
11704 end;
11705 
11706 procedure TTestResolver.TestNestedClass_AccessParent;
11707 begin
11708   StartUnit(false);
11709   Add([
11710   'interface',
11711   'type',
11712   '  TObject = class',
11713   '  end;',
11714   '  TLimb = class',
11715   '    {#tlimb_d}d: longint;',
11716   '  end;',
11717   '  TAnt = boolean;',
11718   '  TBird = class',
11719   '  public type',
11720   '    TBody = class',
11721   '    public type',
11722   '      TAnt = word;',
11723   '      TWing = class(TLimb)',
11724   '        {#ant}ant: TAnt;',
11725   '        procedure Fly(i: longint);',
11726   '      end;',
11727   '    public',
11728   '      class var {#tbody_a}a, {#tbody_b}b, {#tbody_d}d, {#tbody_e}e: longint;',
11729   '    end;',
11730   '  public',
11731   '    class var {#tbird_a}a, {#tbird_b}b, {#tbird_c}c, {#tbird_d}d, {#tbird_e}e: longint;',
11732   '  end;',
11733   'var {#intf_a}a, {#intf_d}d: longint;',
11734   'implementation',
11735   'var {#impl_e}e: longint;',
11736   'procedure TBird.TBody.TWing.Fly(i: longint);',
11737   'begin',
11738   '  {@ant}ant:=2;',
11739   '  {@intf_a}a:=3;',
11740   '  {@tbody_b}b:=4;',
11741   '  {@tbird_c}c:=5;',
11742   '  {@tlimb_d}d:=6;',
11743   '  {@impl_e}e:=7;',
11744   'end;',
11745   '']);
11746   ParseUnit;
11747 end;
11748 
11749 procedure TTestResolver.TestNestedClass_BodyAccessParentVarFail;
11750 begin
11751   StartProgram(false);
11752   Add([
11753   'type',
11754   '  TObject = class end;',
11755   '  TBird = class',
11756   '  public type',
11757   '    TWing = class',
11758   '      procedure Fly;',
11759   '    end;',
11760   '  public',
11761   '    var i: longint;',
11762   '  end;',
11763   'procedure TBird.TWing.Fly;',
11764   'begin',
11765   '  i:=3;',
11766   'end;',
11767   'begin']);
11768   CheckResolverException('Instance member "i" inaccessible here',nInstanceMemberXInaccessible);
11769 end;
11770 
11771 procedure TTestResolver.TestNestedClass_PropertyAccessParentVarFail;
11772 begin
11773   StartProgram(false);
11774   Add([
11775   'type',
11776   '  TObject = class end;',
11777   '  TBird = class',
11778   '    fSize: word;',
11779   '  public type',
11780   '    TWing = class',
11781   '      property Size: word read fSize;',
11782   '    end;',
11783   '  end;',
11784   'begin']);
11785   CheckResolverException('identifier not found "fSize"',nIdentifierNotFound);
11786 end;
11787 
11788 procedure TTestResolver.TestExternalClass;
11789 begin
11790   StartProgram(false);
11791   Add('type');
11792   Add('{$modeswitch externalclass}');
11793   Add('  TExtA = class external ''namespace'' name ''symbol''');
11794   Add('    Id: longint;');
11795   Add('  end;');
11796   Add('begin');
11797   ParseProgram;
11798 end;
11799 
11800 procedure TTestResolver.TestExternalClass_Descendant;
11801 begin
11802   StartProgram(false);
11803   Add('type');
11804   Add('{$modeswitch externalclass}');
11805   Add('  TExtA = class external ''namespace'' name ''symbol''');
11806   Add('    Id: longint;');
11807   Add('  end;');
11808   Add('  TExtB = class external ''namespace'' name ''symbol''(TExtA)');
11809   Add('  end;');
11810   Add('begin');
11811   ParseProgram;
11812 end;
11813 
11814 procedure TTestResolver.TestExternalClass_HintMethodHidesNonVirtualMethodExact;
11815 begin
11816   StartProgram(false);
11817   Add([
11818   '{$modeswitch externalclass}',
11819   'type',
11820   '  TJSObject = class external name ''JSObject''',
11821   '    procedure DoIt(p: pointer);',
11822   '  end;',
11823   '  TBird = class external name ''Bird''(TJSObject)',
11824   '    procedure DoIt(p: pointer);',
11825   '  end;',
11826   'procedure TJSObject.DoIt(p: pointer);',
11827   'begin',
11828   '  if p=nil then ;',
11829   'end;',
11830   'procedure TBird.DoIt(p: pointer); begin end;',
11831   'var b: TBird;',
11832   'begin',
11833   '  b.DoIt(nil);']);
11834   ParseProgram;
11835   CheckResolverHint(mtHint,nMethodHidesNonVirtualMethodExactly,
11836    'method hides identifier at "afile.pp(5,19)". Use reintroduce');
11837 end;
11838 
11839 procedure TTestResolver.TestClassOf;
11840 begin
11841   StartProgram(false);
11842   Add([
11843   'type',
11844   '  {#TClass}{=TObj}TClass = class of TObject;',
11845   '  {#TOBJ}TObject = class',
11846   '    ClassType: TClass; ',
11847   '  end;',
11848   'type',
11849   '  {#TMobile}TMobile = class',
11850   '  end;',
11851   '  {#TMobiles}{=TMobile}TMobiles = class of TMobile;',
11852   'type',
11853   '  {#TCars}{=TCar}TCars = class of TCar;',
11854   '  {#TShips}{=TShip}TShips = class of TShip;',
11855   '  {#TCar}TCar = class(TMobile)',
11856   '  end;',
11857   '  {#TShip}TShip = class(TMobile)',
11858   '  end;',
11859   'var',
11860   '  o: TObject;',
11861   '  c: TClass;',
11862   '  mobile: TMobile;',
11863   '  mobiletype: TMobiles;',
11864   '  car: TCar;',
11865   '  cartype: TCars;',
11866   '  ship: TShip;',
11867   '  shiptype: TShips;',
11868   '  p: pointer;',
11869   'begin',
11870   '  c:=nil;',
11871   '  c:=o.ClassType;',
11872   '  if c=nil then;',
11873   '  if nil=c then;',
11874   '  if c=o.ClassType then ;',
11875   '  if c<>o.ClassType then ;',
11876   '  if Assigned(o) then ;',
11877   '  if Assigned(o.ClassType) then ;',
11878   '  if Assigned(c) then ;',
11879   '  mobiletype:=TMobile;',
11880   '  mobiletype:=TCar;',
11881   '  mobiletype:=TShip;',
11882   '  mobiletype:=cartype;',
11883   '  if mobiletype=nil then ;',
11884   '  if nil=mobiletype then ;',
11885   '  if mobiletype=TShip then ;',
11886   '  if TShip=mobiletype then ;',
11887   '  if mobiletype<>TShip then ;',
11888   '  if mobile is mobiletype then ;',
11889   '  if car is mobiletype then ;',
11890   '  if mobile is cartype then ;',
11891   '  p:=c;',
11892   '  if p=c then ;',
11893   '  if c=p then ;',
11894   '']);
11895   ParseProgram;
11896 end;
11897 
11898 procedure TTestResolver.TestClassOfAlias;
11899 begin
11900   StartProgram(false);
11901   Add([
11902   'type',
11903   '  TObject = class',
11904   '  end;',
11905   '  TBird = TObject;',
11906   '  TBirds = class of TBird;',
11907   '  TEagles = TBirds;',
11908   'var',
11909   '  o: TBird;',
11910   '  c: TEagles;',
11911   'begin',
11912   '  c:=TObject;',
11913   '  c:=TBird;',
11914   '  if c=TObject then ;',
11915   '  if c=TBird then ;',
11916   '  if o is c then ;',
11917   '']);
11918   ParseProgram;
11919 end;
11920 
11921 procedure TTestResolver.TestClassOfNonClassFail;
11922 begin
11923   StartProgram(false);
11924   Add('type');
11925   Add('  TCars = class of longint;');
11926   Add('begin');
11927   CheckResolverException('Incompatible types: got "Longint" expected "class"',
11928     nIncompatibleTypesGotExpected);
11929 end;
11930 
11931 procedure TTestResolver.TestClassOfAssignClassOfFail;
11932 begin
11933   StartProgram(false);
11934   Add([
11935   'type',
11936   '  TObject = class end;',
11937   '  TClass = class of TObject;',
11938   'var c: TClass;',
11939   'begin',
11940   '  c:=TClass;']);
11941   CheckResolverException('Incompatible types: got "type class-of" expected "class of TObject"',
11942     nIncompatibleTypesGotExpected);
11943 end;
11944 
11945 procedure TTestResolver.TestClassOfIsOperatorFail;
11946 begin
11947   StartProgram(false);
11948   Add('type');
11949   Add('  TObject = class end;');
11950   Add('  TCar = class end;');
11951   Add('  TCars = class of TCar;');
11952   Add('var cars: TCars;');
11953   Add('begin');
11954   Add('  if cars is TCars then ;');
11955   CheckResolverException('left side of is-operator expects a class, but got "class of"',
11956     nLeftSideOfIsOperatorExpectsAClassButGot);
11957 end;
11958 
11959 procedure TTestResolver.TestClassOfAsOperatorFail;
11960 begin
11961   StartProgram(false);
11962   Add('type');
11963   Add('  TObject = class end;');
11964   Add('  TCar = class end;');
11965   Add('  TCars = class of TCar;');
11966   Add('var');
11967   Add('  o: TObject;');
11968   Add('  cars: TCars;');
11969   Add('begin');
11970   Add('  cars:=cars as TCars;');
11971   CheckResolverException('Operator is not overloaded: "TCars" as "class of TCars"',
11972     nOperatorIsNotOverloadedAOpB);
11973 end;
11974 
11975 procedure TTestResolver.TestClassOfIsOperator;
11976 begin
11977   StartProgram(false);
11978   ResolverEngine.Options:=ResolverEngine.Options+[proClassOfIs];
11979   Add('type');
11980   Add('  TObject = class end;');
11981   Add('  TClass = class of TObject;');
11982   Add('  TCar = class end;');
11983   Add('  TCars = class of TCar;');
11984   Add('var C: TClass;');
11985   Add('  D: TCars;');
11986   Add('begin');
11987   Add('  if C is TCar then;');
11988   Add('  if C is TCars then;');
11989   Add('  if C is D then ;');
11990   ParseProgram;
11991 end;
11992 
11993 procedure TTestResolver.TestClass_ClassVar;
11994 begin
11995   StartProgram(false);
11996   Add('type');
11997   Add('  TObject = class');
11998   Add('    class var GlobalId: longint;');
11999   Add('  end;');
12000   Add('  TObjectClass = class of TObject;');
12001   Add('var');
12002   Add('  o: TObject;');
12003   Add('  oc: TObjectClass;');
12004   Add('begin');
12005   Add('  o.GlobalId:=3;');
12006   Add('  if o.GlobalId=4 then ;');
12007   Add('  if 5=o.GlobalId then ;');
12008   Add('  TObject.GlobalId:=6;');
12009   Add('  if TObject.GlobalId=7 then ;');
12010   Add('  if 8=TObject.GlobalId then ;');
12011   Add('  oc.GlobalId:=9;');
12012   Add('  if oc.GlobalId=10 then ;');
12013   Add('  if 11=oc.GlobalId then ;');
12014   ParseProgram;
12015 end;
12016 
12017 procedure TTestResolver.TestClassOfDotClassVar;
12018 begin
12019   StartProgram(false);
12020   Add('type');
12021   Add('  TObject = class');
12022   Add('    class var Id: longint;');
12023   Add('  end;');
12024   Add('  TObjectClass = class of TObject;');
12025   Add('var');
12026   Add('  oc: TObjectClass;');
12027   Add('begin');
12028   Add('  oc.Id:=3;');
12029   Add('  if oc.Id=4 then ;');
12030   Add('  if 5=oc.Id then ;');
12031   Add('  TObject.Id:=3;');
12032   Add('  if TObject.Id=4 then ;');
12033   Add('  if 5=TObject.Id then ;');
12034   ParseProgram;
12035 end;
12036 
12037 procedure TTestResolver.TestClassOfDotVarFail;
12038 begin
12039   StartProgram(false);
12040   Add('type');
12041   Add('  TObject = class');
12042   Add('    Id: longint;');
12043   Add('  end;');
12044   Add('  TObjectClass = class of TObject;');
12045   Add('var');
12046   Add('  oc: TObjectClass;');
12047   Add('begin');
12048   Add('  oc.Id:=3;');
12049   CheckResolverException(sInstanceMemberXInaccessible,
12050     nInstanceMemberXInaccessible);
12051 end;
12052 
12053 procedure TTestResolver.TestClassOfDotClassProc;
12054 begin
12055   StartProgram(false);
12056   Add('type');
12057   Add('  TObject = class');
12058   Add('    class procedure ProcA;');
12059   Add('    class function FuncB: longint;');
12060   Add('    class procedure ProcC(i: longint);');
12061   Add('    class function FuncD(i: longint): longint;');
12062   Add('  end;');
12063   Add('  TObjectClass = class of TObject;');
12064   Add('class procedure TObject.ProcA; begin end;');
12065   Add('class function TObject.FuncB: longint; begin end;');
12066   Add('class procedure TObject.ProcC(i: longint); begin end;');
12067   Add('class function TObject.FuncD(i: longint): longint; begin end;');
12068   Add('var');
12069   Add('  o: TObject;');
12070   Add('  oc: TObjectClass;');
12071   Add('begin');
12072   Add('  o.ProcA;');
12073   Add('  oc.ProcA;');
12074   Add('  TObject.ProcA;');
12075   Add('  o.FuncB;');
12076   Add('  o.FuncB();');
12077   Add('  oc.FuncB;');
12078   Add('  oc.FuncB();');
12079   Add('  TObject.FuncB;');
12080   Add('  TObject.FuncB();');
12081   Add('  if oc.FuncB=3 then ;');
12082   Add('  if oc.FuncB()=4 then ;');
12083   Add('  if 5=oc.FuncB then ;');
12084   Add('  if 6=oc.FuncB() then ;');
12085   Add('  oc.ProcC(7);');
12086   Add('  TObject.ProcC(8);');
12087   Add('  oc.FuncD(7);');
12088   Add('  TObject.FuncD(8);');
12089   Add('  if oc.FuncD(9)=10 then ;');
12090   Add('  if 11=oc.FuncD(12) then ;');
12091   Add('  if TObject.FuncD(13)=14 then ;');
12092   Add('  if 15=TObject.FuncD(16) then ;');
12093   ParseProgram;
12094 end;
12095 
12096 procedure TTestResolver.TestClassOfDotProcFail;
12097 begin
12098   StartProgram(false);
12099   Add('type');
12100   Add('  TObject = class');
12101   Add('    procedure ProcA;');
12102   Add('  end;');
12103   Add('  TObjectClass = class of TObject;');
12104   Add('procedure TObject.ProcA; begin end;');
12105   Add('var');
12106   Add('  oc: TObjectClass;');
12107   Add('begin');
12108   Add('  oc.ProcA;');
12109   CheckResolverException(sInstanceMemberXInaccessible,
12110     nInstanceMemberXInaccessible);
12111 end;
12112 
12113 procedure TTestResolver.TestClassOfDotClassProperty;
12114 begin
12115   StartProgram(false);
12116   Add('type');
12117   Add('  TObject = class');
12118   Add('    class var FA: longint;');
12119   Add('    class function GetA: longint; static;');
12120   Add('    class procedure SetA(Value: longint); static;');
12121   Add('    class property A1: longint read FA write SetA;');
12122   Add('    class property A2: longint read GetA write FA;');
12123   Add('  end;');
12124   Add('  TObjectClass = class of TObject;');
12125   Add('class function TObject.GetA: longint; begin end;');
12126   Add('class procedure TObject.SetA(Value: longint); begin end;');
12127   Add('var');
12128   Add('  o: TObject;');
12129   Add('  oc: TObjectClass;');
12130   Add('begin');
12131   Add('  o.A1:=3;');
12132   Add('  if o.A1=4 then ;');
12133   Add('  if 5=o.A1 then ;');
12134   Add('  oc.A1:=6;');
12135   Add('  if oc.A1=7 then ;');
12136   Add('  if 8=oc.A1 then ;');
12137   Add('  TObject.A1:=9;');
12138   Add('  if TObject.A1=10 then ;');
12139   Add('  if 11=TObject.A1 then ;');
12140   ParseProgram;
12141 end;
12142 
12143 procedure TTestResolver.TestClassOfDotPropertyFail;
12144 begin
12145   StartProgram(false);
12146   Add('type');
12147   Add('  TObject = class');
12148   Add('    FA: longint;');
12149   Add('    property A: longint read FA;');
12150   Add('  end;');
12151   Add('  TObjectClass = class of TObject;');
12152   Add('var');
12153   Add('  oc: TObjectClass;');
12154   Add('begin');
12155   Add('  if oc.A=3 then ;');
12156   CheckResolverException(sInstanceMemberXInaccessible,
12157     nInstanceMemberXInaccessible);
12158 end;
12159 
12160 procedure TTestResolver.TestClass_ClassProcSelf;
12161 begin
12162   StartProgram(false);
12163   Add('type');
12164   Add('  TObject = class');
12165   Add('    class var GlobalId: longint;');
12166   Add('    class procedure ProcA;');
12167   Add('  end;');
12168   Add('  TClass = class of TObject;');
12169   Add('class procedure TObject.ProcA;');
12170   Add('var c: TClass;');
12171   Add('begin');
12172   Add('  if Self=nil then ;');
12173   Add('  if Self.GlobalId=3 then ;');
12174   Add('  if 4=Self.GlobalId then ;');
12175   Add('  Self.GlobalId:=5;');
12176   Add('  c:=Self;');
12177   Add('  c:=TClass(Self);');
12178   Add('  if Self=c then ;');
12179   Add('end;');
12180   Add('begin');
12181   ParseProgram;
12182 end;
12183 
12184 procedure TTestResolver.TestClass_ClassProcSelfTypeCastFail;
12185 begin
12186   StartProgram(false);
12187   Add('type');
12188   Add('  TObject = class');
12189   Add('    class procedure ProcA;');
12190   Add('  end;');
12191   Add('class procedure TObject.ProcA;');
12192   Add('begin');
12193   Add('  if TObject(Self)=nil then ;');
12194   Add('end;');
12195   Add('begin');
12196   CheckResolverException('Illegal type conversion: "Self" to "class TObject"',
12197     nIllegalTypeConversionTo);
12198 end;
12199 
12200 procedure TTestResolver.TestClass_ClassMembers;
12201 begin
12202   StartProgram(false);
12203   Add('type');
12204   Add('  TObject = class');
12205   Add('  end;');
12206   Add('  TMobile = class');
12207   Add('  public');
12208   Add('    MobileId: longint;');
12209   Add('    class var LastVal: longint;');
12210   Add('    constructor Create; virtual;');
12211   Add('    class procedure ClProcA;');
12212   Add('    class function ClFuncB: longint;');
12213   Add('    class function StFuncC: longint; static;');
12214   Add('    class property ClMobileId: longint read StFuncC write LastVal;');
12215   Add('  end;');
12216   Add('  TMobiles = class of TMobile;');
12217   Add('  TCars = class of TCar;');
12218   Add('  TCar = class(TMobile)');
12219   Add('  public');
12220   Add('    CarId: longint;');
12221   Add('    class var LastCarVal: longint;');
12222   Add('    constructor Create; override;');
12223   Add('  end;');
12224   Add('constructor TMobile.Create;');
12225   Add('begin');
12226   Add('  Self.MobileId:=7;');
12227   Add('  LastVal:=LastVal+ClMobileId+1;');
12228   Add('  ClMobileId:=MobileId+3;');
12229   Add('  TCar(Self).CarId:=4;');
12230   Add('end;');
12231   Add('class procedure TMobile.ClProcA;');
12232   Add('var');
12233   Add('  m: TMobiles;');
12234   Add('begin');
12235   Add('  LastVal:=9;');
12236   Add('  Self.LastVal:=ClFuncB+ClMobileId;');
12237   Add('  m:=Self;');
12238   Add('  if m=Self then ;');
12239   Add('end;');
12240   Add('class function TMobile.ClFuncB: longint;');
12241   Add('begin');
12242   Add('  if LastVal=3 then ;');
12243   Add('  Result:=Self.LastVal-ClMobileId;');
12244   Add('end;');
12245   Add('class function TMobile.StFuncC: longint;');
12246   Add('begin');
12247   Add('  Result:=LastVal;');
12248   Add('  // Forbidden: no Self in static methods');
12249   Add('end;');
12250   Add('');
12251   Add('constructor TCar.Create;');
12252   Add('begin');
12253   Add('  inherited Create;');
12254   Add('  Self.CarId:=8;');
12255   Add('  TMobile(Self).LastVal:=5;');
12256   Add('  if TMobile(Self).LastVal=25 then ;');
12257   Add('end;');
12258   Add('');
12259   Add('var');
12260   Add('  car: TCar;');
12261   Add('  cartype: TCars;');
12262   Add('begin');
12263   Add('  car:=TCar.Create;');
12264   Add('  car.MobileId:=10;');
12265   Add('  car.ClProcA;');
12266   Add('  exit;');
12267   Add('  car.ClMobileId:=11;');
12268   Add('  if car.ClFuncB=16 then ;');
12269   Add('  if 17=car.ClFuncB then ;');
12270   Add('  cartype:=TCar;');
12271   Add('  cartype.LastVal:=18;');
12272   Add('  if cartype.LastVal=19 then ;');
12273   Add('  if 20=cartype.LastVal then ;');
12274   ParseProgram;
12275 end;
12276 
12277 procedure TTestResolver.TestClassOf_AsFail;
12278 begin
12279   StartProgram(false);
12280   Add('type');
12281   Add('  TClass = class of TObject;');
12282   Add('  TObject = class');
12283   Add('  end;');
12284   Add('var');
12285   Add('  c: tclass;');
12286   Add('begin');
12287   Add('  c:=c as TClass;');
12288   CheckResolverException('Operator is not overloaded: "TClass" as "class of TClass"',
12289     nOperatorIsNotOverloadedAOpB);
12290 end;
12291 
12292 procedure TTestResolver.TestClassOf_MemberAsFail;
12293 begin
12294   StartProgram(false);
12295   Add('type');
12296   Add('  TClass = class of TObject;');
12297   Add('  TObject = class');
12298   Add('    c: tclass;');
12299   Add('  end;');
12300   Add('var o: TObject;');
12301   Add('begin');
12302   Add('  o.c:=o.c as TClass;');
12303   CheckResolverException('Operator is not overloaded: "TClass" as "class of TClass"',nOperatorIsNotOverloadedAOpB);
12304 end;
12305 
12306 procedure TTestResolver.TestClassOf_IsFail;
12307 begin
12308   StartProgram(false);
12309   Add('type');
12310   Add('  TClass = class of TObject;');
12311   Add('  TObject = class');
12312   Add('  end;');
12313   Add('var');
12314   Add('  c: tclass;');
12315   Add('begin');
12316   Add('  if c is TObject then;');
12317   CheckResolverException('left side of is-operator expects a class, but got "class of"',
12318     nLeftSideOfIsOperatorExpectsAClassButGot);
12319 end;
12320 
12321 procedure TTestResolver.TestClass_TypeCast;
12322 begin
12323   StartProgram(false);
12324   Add('type');
12325   Add('  TObject = class');
12326   Add('    class procedure {#TObject_DoIt}DoIt;');
12327   Add('  end;');
12328   Add('  TClass = class of TObject;');
12329   Add('  TMobile = class');
12330   Add('    class procedure {#TMobile_DoIt}DoIt;');
12331   Add('  end;');
12332   Add('  TMobileClass = class of TMobile;');
12333   Add('  TCar = class(TMobile)');
12334   Add('    class procedure {#TCar_DoIt}DoIt;');
12335   Add('  end;');
12336   Add('  TCarClass = class of TCar;');
12337   Add('class procedure TObject.DoIt;');
12338   Add('begin');
12339   Add('  TClass(Self).{@TObject_DoIt}DoIt;');
12340   Add('  TMobileClass(Self).{@TMobile_DoIt}DoIt;');
12341   Add('end;');
12342   Add('class procedure TMobile.DoIt;');
12343   Add('begin');
12344   Add('  TClass(Self).{@TObject_DoIt}DoIt;');
12345   Add('  TMobileClass(Self).{@TMobile_DoIt}DoIt;');
12346   Add('  TCarClass(Self).{@TCar_DoIt}DoIt;');
12347   Add('end;');
12348   Add('class procedure TCar.DoIt; begin end;');
12349   Add('var');
12350   Add('  ObjC: TClass;');
12351   Add('  MobileC: TMobileClass;');
12352   Add('  CarC: TCarClass;');
12353   Add('begin');
12354   Add('  ObjC.{@TObject_DoIt}DoIt;');
12355   Add('  MobileC.{@TMobile_DoIt}DoIt;');
12356   Add('  CarC.{@TCar_DoIt}DoIt;');
12357   Add('  TClass(ObjC).{@TObject_DoIt}DoIt;');
12358   Add('  TMobileClass(ObjC).{@TMobile_DoIt}DoIt;');
12359   Add('  TCarClass(ObjC).{@TCar_DoIt}DoIt;');
12360   Add('  TClass(MobileC).{@TObject_DoIt}DoIt;');
12361   Add('  TMobileClass(MobileC).{@TMobile_DoIt}DoIt;');
12362   Add('  TCarClass(MobileC).{@TCar_DoIt}DoIt;');
12363   Add('  TClass(CarC).{@TObject_DoIt}DoIt;');
12364   Add('  TMobileClass(CarC).{@TMobile_DoIt}DoIt;');
12365   Add('  TCarClass(CarC).{@TCar_DoIt}DoIt;');
12366   ParseProgram;
12367 end;
12368 
12369 procedure TTestResolver.TestClassOf_AlwaysForward;
12370 begin
12371   AddModuleWithIntfImplSrc('unit2.pp',
12372     LinesToStr([
12373     'type',
12374     '  TObject = class',
12375     '  end;',
12376     '  TCar = class',
12377     '  end;',
12378     '  TCarry = TCar;']),
12379     LinesToStr([
12380     '']));
12381 
12382   StartProgram(true);
12383   Add('uses unit2;');
12384   Add('type');
12385   Add('  {#C}{=A}TCars = class of TCarry;');
12386   Add('  {#A}TCarry = class');
12387   Add('    class var {#B}B: longint;');
12388   Add('  end;');
12389   Add('begin');
12390   Add('  {@C}TCars.{@B}B:=3;');
12391   ParseProgram;
12392 end;
12393 
12394 procedure TTestResolver.TestClassOf_ClassOfBeforeClass_FuncResult;
12395 begin
12396   StartProgram(false);
12397   Add('type');
12398   Add('  TClass = class of TObject;');
12399   Add('  TObject = class');
12400   Add('  end;');
12401   Add('function GetClass: TClass;');
12402   Add('begin');
12403   Add('  Result:=TObject;');
12404   Add('end;');
12405   Add('begin');
12406   ParseProgram;
12407 end;
12408 
12409 procedure TTestResolver.TestClassOf_Const;
12410 begin
12411   StartProgram(false);
12412   Add([
12413   'type',
12414   '  TObject = class',
12415   '  end;',
12416   '  TBird = TObject;',
12417   '  TBirds = class of TBird;',
12418   '  TEagles = TBirds;',
12419   '  THawk = class(TBird);',
12420   'const',
12421   '  Hawk: TEagles = THawk;',
12422   '  DefaultBirdClasses : Array [1..2] of TEagles = (',
12423   '    TBird,',
12424   '    THawk',
12425   '  );',
12426   'begin']);
12427   ParseProgram;
12428 end;
12429 
12430 procedure TTestResolver.TestClassOf_Const2;
12431 begin
12432   StartProgram(false);
12433   Add([
12434   'type',
12435   '  TObject = class',
12436   '  end;',
12437   '  TFieldType = (fta,ftb);',
12438   '  TField = Class;',
12439   '  TFieldClass = class of TField;',
12440   '  TField = Class(TObject);',
12441   '  TFieldA = Class(TField);',
12442   '  TFieldB = Class(TField);',
12443   'Const',
12444   '  DefaultFieldClasses : Array [TFieldType] of TFieldClass = (TFieldA,TFieldB);',
12445   'begin']);
12446   ParseProgram;
12447 end;
12448 
12449 procedure TTestResolver.TestProperty1;
12450 begin
12451   StartProgram(false);
12452   Add('type');
12453   Add('  integer = longint;');
12454   Add('  {#TOBJ}TObject = class');
12455   Add('  end;');
12456   Add('  {#A}TClassA = class');
12457   Add('    {#FB}FB: integer;');
12458   Add('    property {#B}B: longint read {@FB}FB write {@FB}FB;');
12459   Add('  end;');
12460   Add('var');
12461   Add('  {#v}{=A}v: TClassA;');
12462   Add('begin');
12463   Add('  {@v}v.{@b}b:=3;');
12464   ParseProgram;
12465 end;
12466 
12467 procedure TTestResolver.TestPropertyAccessorNotInFront;
12468 begin
12469   StartProgram(false);
12470   Add('type');
12471   Add('  TObject = class');
12472   Add('    property B: longint read FB;');
12473   Add('    FB: longint;');
12474   Add('  end;');
12475   Add('begin');
12476   CheckResolverException('identifier not found "FB"',nIdentifierNotFound);
12477 end;
12478 
12479 procedure TTestResolver.TestPropertyReadAndWriteMissingFail;
12480 begin
12481   StartProgram(false);
12482   Add([
12483   'type',
12484   '  TObject = class',
12485   '    property B: longint;',
12486   '  end;',
12487   'begin']);
12488   CheckResolverException(sPropertyMustHaveReadOrWrite,nPropertyMustHaveReadOrWrite);
12489 end;
12490 
12491 procedure TTestResolver.TestPropertyReadAccessorVarWrongType;
12492 begin
12493   StartProgram(false);
12494   Add('type');
12495   Add('  TObject = class');
12496   Add('    FB: string;');
12497   Add('    property B: longint read FB;');
12498   Add('  end;');
12499   Add('begin');
12500   CheckResolverException('Incompatible types: got "Longint" expected "String"',
12501     nIncompatibleTypesGotExpected);
12502 end;
12503 
12504 procedure TTestResolver.TestPropertyReadAccessorProcNotFunc;
12505 begin
12506   StartProgram(false);
12507   Add('type');
12508   Add('  TObject = class');
12509   Add('    procedure GetB;');
12510   Add('    property B: longint read GetB;');
12511   Add('  end;');
12512   Add('begin');
12513   CheckResolverException('function expected, but procedure found',nXExpectedButYFound);
12514 end;
12515 
12516 procedure TTestResolver.TestPropertyReadAccessorFuncWrongResult;
12517 begin
12518   StartProgram(false);
12519   Add('type');
12520   Add('  TObject = class');
12521   Add('    function GetB: string;');
12522   Add('    property B: longint read GetB;');
12523   Add('  end;');
12524   Add('begin');
12525   CheckResolverException('function result Longint expected, but String found',
12526     nXExpectedButYFound);
12527 end;
12528 
12529 procedure TTestResolver.TestPropertyReadAccessorFuncWrongArgCount;
12530 begin
12531   StartProgram(false);
12532   Add('type');
12533   Add('  TObject = class');
12534   Add('    function GetB(i: longint): longint;');
12535   Add('    property B: longint read GetB;');
12536   Add('  end;');
12537   Add('begin');
12538   CheckResolverException('Wrong number of parameters specified for call to "GetB"',
12539     nWrongNumberOfParametersForCallTo);
12540 end;
12541 
12542 procedure TTestResolver.TestPropertyReadAccessorFunc;
12543 begin
12544   StartProgram(false);
12545   Add('type');
12546   Add('  {#TOBJ}TObject = class');
12547   Add('    function {#GetB}GetB: longint;');
12548   Add('    property {#B}B: longint read {@GetB}GetB;');
12549   Add('  end;');
12550   Add('function TObject.GetB: longint;');
12551   Add('begin');
12552   Add('end;');
12553   Add('var');
12554   Add('  {#o}{=TOBJ}o: TObject;');
12555   Add('begin');
12556   Add('  if {@o}o.{@B}B=3 then ;');
12557   ParseProgram;
12558 end;
12559 
12560 procedure TTestResolver.TestPropertyReadAccessorStrictPrivate;
12561 begin
12562   StartProgram(false);
12563   Add([
12564   'type',
12565   '  TObject = class',
12566   '  strict private',
12567   '    FSize: word;',
12568   '    property Size: word read FSize;',
12569   '  strict protected',
12570   '    FName: string;',
12571   '    property Name: string read FName;',
12572   '  end;',
12573   '  TBird = class',
12574   '  strict protected',
12575   '    property Caption: string read FName;',
12576   '  end;',
12577   'begin',
12578   '']);
12579   ParseProgram;
12580 end;
12581 
12582 procedure TTestResolver.TestPropertyReadAccessorNonClassFail;
12583 begin
12584   StartProgram(false);
12585   Add([
12586   'type',
12587   '  TObject = class',
12588   '    FSize: word;',
12589   '    class property Size: word read FSize;',
12590   '  end;',
12591   'begin',
12592   '']);
12593   CheckResolverException('class var expected, but var found',nXExpectedButYFound);
12594 end;
12595 
12596 procedure TTestResolver.TestPropertyWriteAccessorVarWrongType;
12597 begin
12598   StartProgram(false);
12599   Add('type');
12600   Add('  TObject = class');
12601   Add('    FB: string;');
12602   Add('    property B: longint write FB;');
12603   Add('  end;');
12604   Add('begin');
12605   CheckResolverException('Incompatible types: got "Longint" expected "String"',
12606     nIncompatibleTypesGotExpected);
12607 end;
12608 
12609 procedure TTestResolver.TestPropertyWriteAccessorFuncNotProc;
12610 begin
12611   StartProgram(false);
12612   Add('type');
12613   Add('  TObject = class');
12614   Add('    function SetB: longint;');
12615   Add('    property B: longint write SetB;');
12616   Add('  end;');
12617   Add('begin');
12618   CheckResolverException('procedure expected, but function found',nXExpectedButYFound);
12619 end;
12620 
12621 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArgCount;
12622 begin
12623   StartProgram(false);
12624   Add('type');
12625   Add('  TObject = class');
12626   Add('    procedure SetB;');
12627   Add('    property B: longint write SetB;');
12628   Add('  end;');
12629   Add('begin');
12630   CheckResolverException('Wrong number of parameters specified for call to "SetB"',
12631     nWrongNumberOfParametersForCallTo);
12632 end;
12633 
12634 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArg;
12635 begin
12636   StartProgram(false);
12637   Add('type');
12638   Add('  TObject = class');
12639   Add('    procedure SetB(var Value: longint);');
12640   Add('    property B: longint write SetB;');
12641   Add('  end;');
12642   Add('begin');
12643   CheckResolverException('Incompatible type arg no. 1: Got "var", expected "const"',
12644     nIncompatibleTypeArgNo);
12645 end;
12646 
12647 procedure TTestResolver.TestPropertyWriteAccessorProcWrongArgType;
12648 begin
12649   StartProgram(false);
12650   Add('type');
12651   Add('  TObject = class');
12652   Add('    procedure SetB(Value: string);');
12653   Add('    property B: longint write SetB;');
12654   Add('  end;');
12655   Add('begin');
12656   CheckResolverException('Incompatible type arg no. 1: Got "String", expected "Longint"',
12657     nIncompatibleTypeArgNo);
12658 end;
12659 
12660 procedure TTestResolver.TestPropertyWriteAccessorProc;
12661 begin
12662   StartProgram(false);
12663   Add('type');
12664   Add('  {#TOBJ}TObject = class');
12665   Add('    procedure {#SetB}SetB(Value: longint);');
12666   Add('    property {#B}B: longint write {@SetB}SetB;');
12667   Add('  end;');
12668   Add('procedure TObject.SetB(Value: longint);');
12669   Add('begin');
12670   Add('end;');
12671   Add('var');
12672   Add('  {#o}{=TOBJ}o: TObject;');
12673   Add('begin');
12674   Add('  {@o}o.{@B}B:=3;');
12675   ParseProgram;
12676 end;
12677 
12678 procedure TTestResolver.TestPropertyTypeless;
12679 begin
12680   StartProgram(false);
12681   Add([
12682   'type',
12683   '  {#TOBJ}TObject = class',
12684   '    {#FB}FB: longint;',
12685   '    property {#TOBJ_B}B: longint write {@FB}FB;',
12686   '    property {#TOBJ_D}D: longint write {@FB}FB;',
12687   '  end;',
12688   '  {#TA}TClassA = class',
12689   '    {#FC}FC: longint;',
12690   '    property {#TA_B}{@TOBJ_B}B write {@FC}FC;',
12691   '  end;',
12692   '  {#TB}TClassB = class(TClassA)',
12693   '  published',
12694   '    property {#TB_D}{@TOBJ_D}D;',
12695   '  end;',
12696   'var',
12697   '  {#v}{=TA}v: TClassA;',
12698   'begin',
12699   '  {@v}v.{@TA_B}B:=3;',
12700   '  {@v}v.{@TObj_D}D:=4;',
12701   '']);
12702   ParseProgram;
12703 end;
12704 
12705 procedure TTestResolver.TestPropertyTypelessNoAncestorFail;
12706 begin
12707   StartProgram(false);
12708   Add('type');
12709   Add('  TObject = class');
12710   Add('  end;');
12711   Add('  TClassA = class');
12712   Add('    property B;');
12713   Add('  end;');
12714   Add('begin');
12715   CheckResolverException(sNoPropertyFoundToOverride,
12716     nNoPropertyFoundToOverride);
12717 end;
12718 
12719 procedure TTestResolver.TestPropertyStoredAccessor;
12720 begin
12721   StartProgram(false);
12722   Add('const StoreB = true;');
12723   Add('type');
12724   Add('  TObject = class');
12725   Add('    FBird: longint;');
12726   Add('    VStored: boolean;');
12727   Add('    function IsBirdStored: boolean; virtual; abstract;');
12728   Add('    property Bird: longint read FBird stored VStored;');
12729   Add('    property B: longint read FBird stored IsBirdStored;');
12730   Add('    property Eagle: longint read FBird stored StoreB;');
12731   Add('    property Hawk: longint read FBird stored false;');
12732   Add('  end;');
12733   Add('begin');
12734   ParseProgram;
12735 end;
12736 
12737 procedure TTestResolver.TestPropertyStoredAccessorVarWrongType;
12738 begin
12739   StartProgram(false);
12740   Add('type');
12741   Add('  TObject = class');
12742   Add('    FB: longint;');
12743   Add('    BStored: longint;');
12744   Add('    property B: longint read FB stored BStored;');
12745   Add('  end;');
12746   Add('begin');
12747   CheckResolverException('Incompatible types: got "Longint" expected "Boolean"',
12748     nIncompatibleTypesGotExpected);
12749 end;
12750 
12751 procedure TTestResolver.TestPropertyStoredAccessorProcNotFunc;
12752 begin
12753   StartProgram(false);
12754   Add('type');
12755   Add('  TObject = class');
12756   Add('    FB: longint;');
12757   Add('    procedure GetB;');
12758   Add('    property B: longint read FB stored GetB;');
12759   Add('  end;');
12760   Add('begin');
12761   CheckResolverException('function expected, but procedure found',nXExpectedButYFound);
12762 end;
12763 
12764 procedure TTestResolver.TestPropertyStoredAccessorFuncWrongResult;
12765 begin
12766   StartProgram(false);
12767   Add('type');
12768   Add('  TObject = class');
12769   Add('    FB: longint;');
12770   Add('    function GetB: string;');
12771   Add('    property B: longint read FB stored GetB;');
12772   Add('  end;');
12773   Add('begin');
12774   CheckResolverException('function: boolean expected, but function:String found',
12775     nXExpectedButYFound);
12776 end;
12777 
12778 procedure TTestResolver.TestPropertyStoredAccessorFuncWrongArgCount;
12779 begin
12780   StartProgram(false);
12781   Add('type');
12782   Add('  TObject = class');
12783   Add('    FB: longint;');
12784   Add('    function GetB(i: longint): boolean;');
12785   Add('    property B: longint read FB stored GetB;');
12786   Add('  end;');
12787   Add('begin');
12788   CheckResolverException('Wrong number of parameters specified for call to "GetB"',
12789     nWrongNumberOfParametersForCallTo);
12790 end;
12791 
12792 procedure TTestResolver.TestPropertyIndexSpec;
12793 begin
12794   StartProgram(false);
12795   Add([
12796   'const',
12797   '  CB = true or false;',
12798   '  CI = 1+2;',
12799   'type',
12800   '  TEnum = (red, blue);',
12801   '  TObject = class',
12802   '    FB: boolean;',
12803   '    function GetIntBool(Index: longint): boolean; virtual; abstract;',
12804   '    procedure SetIntBool(Index: longint; b: boolean); virtual; abstract;',
12805   '    function GetBoolBool(Index: boolean): boolean; virtual; abstract;',
12806   '    procedure SetBoolBool(Index: boolean; b: boolean); virtual; abstract;',
12807   '    function GetEnumBool(Index: TEnum): boolean; virtual; abstract;',
12808   '    procedure SetEnumBool(Index: TEnum; b: boolean); virtual; abstract;',
12809   '    function GetStrIntBool(A: String; I: longint): boolean; virtual; abstract;',
12810   '    procedure SetStrIntBool(A: String; I: longint; b: boolean); virtual; abstract;',
12811   '    property B1: boolean index 1 read GetIntBool write SetIntBool stored GetIntBool;',
12812   '    property B2: boolean index CI read GetIntBool write SetIntBool stored GetIntBool;',
12813   '    property B3: boolean index false read GetBoolBool write SetBoolBool stored GetBoolBool;',
12814   '    property B4: boolean index CB read GetBoolBool write SetBoolBool stored GetBoolBool;',
12815   '    property B5: boolean index red read GetEnumBool write SetEnumBool stored GetEnumBool;',
12816   '    property B6: boolean index TEnum.blue read GetEnumBool write SetEnumBool stored GetEnumBool;',
12817   '    property B7: boolean index 1 read GetIntBool write FB stored FB;',
12818   '    property I1[A: String]: boolean index 2 read GetStrIntBool write SetStrIntBool;',
12819   '  end;',
12820   '  TBird = class',
12821   '    function GetIntBoolOvr(Index: longint): boolean; virtual; abstract;',
12822   '    property B1 index 3;',
12823   '    property B2 read GetIntBoolOvr;',
12824   '  end;',
12825   'begin']);
12826   ParseProgram;
12827 end;
12828 
12829 procedure TTestResolver.TestPropertyIndexSpec_ReadAccessorWrongArgCount;
12830 begin
12831   StartProgram(false);
12832   Add([
12833   'type',
12834   '  TObject = class',
12835   '    function GetB: boolean; virtual; abstract;',
12836   '    property B: boolean index 1 read GetB;',
12837   '  end;',
12838   'begin']);
12839   CheckResolverException('Wrong number of parameters specified for call to "GetB"',
12840     nWrongNumberOfParametersForCallTo);
12841 end;
12842 
12843 procedure TTestResolver.TestPropertyIndexSpec_ReadAccessorWrongIndexArgType;
12844 begin
12845   StartProgram(false);
12846   Add([
12847   'type',
12848   '  TObject = class',
12849   '    function GetB(S: string): boolean; virtual; abstract;',
12850   '    property B: boolean index 1 read GetB;',
12851   '  end;',
12852   'begin']);
12853   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "String"',
12854     nIncompatibleTypeArgNo);
12855 end;
12856 
12857 procedure TTestResolver.TestPropertyDefaultValue;
12858 begin
12859   StartProgram(false);
12860   Add([
12861   'type',
12862   '  TEnum = (red, blue, green, white, grey, black);',
12863   '  TEnumRg = blue..grey;',
12864   '  TSet = set of TEnum;',
12865   'const',
12866   '  CB = true or false;',
12867   '  CI = 1+2;',
12868   '  CS = [red,blue];',
12869   'type',
12870   '  TObject = class',
12871   '    FB: boolean;',
12872   '    property B1: boolean read FB default true;',
12873   '    property B2: boolean read FB default CB;',
12874   '    property B3: boolean read FB default afile.cb;',
12875   '    FI: longint;',
12876   '    property I1: longint read FI default 2;',
12877   '    property I2: longint read FI default CI;',
12878   '    FE: TEnum;',
12879   '    property E1: TEnum read FE default red;',
12880   '    property E2: TEnum read FE default TEnum.blue;',
12881   '    FEnumRg: TEnumRg;',
12882   '    property EnumRg1: TEnumRg read FEnumRg default white;',
12883   '    FSet: TSet;',
12884   '    property Set1: TSet read FSet default [];',
12885   '    property Set2: TSet read FSet default [red];',
12886   '    property Set3: TSet read FSet default [red,blue];',
12887   '    property Set4: TSet read FSet default CS;',
12888   '  end;',
12889   'begin']);
12890   ParseProgram;
12891 end;
12892 
12893 procedure TTestResolver.TestPropertyArgs1;
12894 begin
12895   StartProgram(false);
12896   Add('type');
12897   Add('  TObject = class');
12898   Add('    function GetB(Index: longint): boolean;');
12899   Add('    procedure SetB(Index: longint; Value: boolean);');
12900   Add('    property B[Index: longint]: boolean read GetB write SetB;');
12901   Add('  end;');
12902   Add('function TObject.GetB(Index: longint): boolean;');
12903   Add('begin');
12904   Add('end;');
12905   Add('procedure TObject.SetB(Index: longint; Value: boolean);');
12906   Add('begin');
12907   Add('end;');
12908   Add('var o: TObject;');
12909   Add('begin');
12910   Add('  o.B[3]:=true;');
12911   Add('  if o.B[4] then;');
12912   Add('  if o.B[5]=true then;');
12913   Add('  if false=o.B[6] then;');
12914   ParseProgram;
12915 end;
12916 
12917 procedure TTestResolver.TestPropertyArgs2;
12918 begin
12919   StartProgram(false);
12920   Add('type');
12921   Add('  TObject = class');
12922   Add('    function GetB(Index: longint; const ID: string): longint;');
12923   Add('    procedure SetB(Index: longint; const ID: string; Value: longint);');
12924   Add('    property B[Index: longint; const ID: string]: longint read GetB write SetB;');
12925   Add('  end;');
12926   Add('function TObject.GetB(Index: longint; const ID: string): longint;');
12927   Add('begin');
12928   Add('end;');
12929   Add('procedure TObject.SetB(Index: longint; const ID: string; Value: longint);');
12930   Add('begin');
12931   Add('end;');
12932   Add('var o: TObject;');
12933   Add('begin');
12934   Add('  o.B[3,''abc'']:=7;');
12935   Add('  if o.B[4,'''']=8 then;');
12936   Add('  if 9=o.B[6,''d''] then;');
12937   ParseProgram;
12938 end;
12939 
12940 procedure TTestResolver.TestPropertyArgsWithDefaultsFail;
12941 begin
12942   StartProgram(false);
12943   Add('type');
12944   Add('  TObject = class');
12945   Add('    function GetB(Index: longint): boolean;');
12946   Add('    procedure SetB(Index: longint; Value: boolean);');
12947   Add('    property B[Index: longint = 0]: boolean read GetB write SetB;');
12948   Add('  end;');
12949   Add('function TObject.GetB(Index: longint): boolean;');
12950   Add('begin');
12951   Add('end;');
12952   Add('procedure TObject.SetB(Index: longint; Value: boolean);');
12953   Add('begin');
12954   Add('end;');
12955   Add('begin');
12956   CheckParserException('Property arguments can not have default values',
12957     PParser.nParserPropertyArgumentsCanNotHaveDefaultValues);
12958 end;
12959 
12960 procedure TTestResolver.TestPropertyArgs_StringConstDefault;
12961 begin
12962   StartProgram(false);
12963   Add([
12964   'type',
12965   '  TObject = class',
12966   '    function GetItems(const s: string): byte; virtual; abstract;',
12967   '    procedure SetItems(const s: string; b: byte); virtual; abstract;',
12968   '    property Items[s: string]: byte read GetItems write SetItems;',
12969   '  end;',
12970   'begin']);
12971   ParseProgram;
12972 end;
12973 
12974 procedure TTestResolver.TestClassProperty;
12975 begin
12976   StartProgram(false);
12977   Add([
12978   'type',
12979   '  TObject = class',
12980   '    class function GetStatic: word; static;',
12981   '    class procedure SetStatic(Value: word); static;',
12982   '    class property StaticP: word read GetStatic write SetStatic;',
12983   '  end;',
12984   'class function TObject.GetStatic: word;',
12985   'begin',
12986   '  StaticP:=StaticP;',
12987   'end;',
12988   'class procedure TObject.SetStatic(Value: word);',
12989   'begin',
12990   'end;',
12991   'begin',
12992   '']);
12993   ParseProgram;
12994 end;
12995 
12996 procedure TTestResolver.TestClassPropertyNonStaticFail;
12997 begin
12998   StartProgram(false);
12999   Add([
13000   'type',
13001   '  TObject = class',
13002   '    class function GetNonStatic: word;',
13003   '    class property NonStatic: word read GetNonStatic;',
13004   '  end;',
13005   'class function TObject.GetNonStatic: word;',
13006   'begin',
13007   'end;',
13008   'begin',
13009   '']);
13010   CheckResolverException(sClassPropertyAccessorMustBeStatic,nClassPropertyAccessorMustBeStatic);
13011 end;
13012 
13013 procedure TTestResolver.TestClassPropertyNonStaticAllow;
13014 begin
13015   ResolverEngine.Options:=ResolverEngine.Options+[proClassPropertyNonStatic];
13016   StartProgram(false);
13017   Add([
13018   'type',
13019   '  TObject = class',
13020   '    class function GetStatic: word; static;',
13021   '    class procedure SetStatic(Value: word); static;',
13022   '    class property StaticP: word read GetStatic write SetStatic;',
13023   '    class function GetNonStatic: word;',
13024   '    class procedure SetNonStatic(Value: word);',
13025   '    class property NonStatic: word read GetNonStatic write SetNonStatic;',
13026   '  end;',
13027   '  TClass = class of TObject;',
13028   'class function TObject.GetStatic: word;',
13029   'begin',
13030   '  StaticP:=StaticP;',
13031   '  NonStatic:=NonStatic;',
13032   'end;',
13033   'class procedure TObject.SetStatic(Value: word);',
13034   'begin',
13035   'end;',
13036   'class function TObject.GetNonStatic: word;',
13037   'begin',
13038   '  StaticP:=StaticP;',
13039   '  NonStatic:=NonStatic;',
13040   'end;',
13041   'class procedure TObject.SetNonStatic(Value: word);',
13042   'begin',
13043   'end;',
13044   'var',
13045   '  c: TClass;',
13046   '  o: TObject;',
13047   'begin',
13048   '  c.STaticP:=c.StaticP;',
13049   '  o.STaticP:=o.StaticP;',
13050   '  c.NonStatic:=c.NonStatic;',
13051   '  o.NonStatic:=o.NonStatic;',
13052   '']);
13053   ParseProgram;
13054 end;
13055 
13056 procedure TTestResolver.TestArrayProperty;
13057 begin
13058   StartProgram(false);
13059   Add('type');
13060   Add('  TObject = class');
13061   Add('    {#FItems}FItems: array of string;');
13062   Add('    function {#GetItems}GetItems(Index: longint): string;');
13063   Add('    procedure {#SetItems}SetItems(Index: longint; Value: string);');
13064   Add('    procedure DoIt;');
13065   Add('    property {#Items}Items[Index: longint]: string read {@GetItems}getitems write {@SetItems}setitems;');
13066   Add('  end;');
13067   Add('function tobject.getitems(index: longint): string;');
13068   Add('begin');
13069   Add('  Result:={@FItems}fitems[index];');
13070   Add('end;');
13071   Add('procedure tobject.setitems(index: longint; value: string);');
13072   Add('begin');
13073   Add('  {@FItems}fitems[index]:=value;');
13074   Add('end;');
13075   Add('procedure tobject.doit;');
13076   Add('begin');
13077   Add('  {@Items}items[1]:={@Items}items[2];');
13078   Add('  self.{@Items}items[3]:=self.{@Items}items[4];');
13079   Add('end;');
13080   Add('var Obj: tobject;');
13081   Add('begin');
13082   Add('  obj.{@Items}Items[11]:=obj.{@Items}Items[12];');
13083   ParseProgram;
13084 end;
13085 
13086 procedure TTestResolver.TestArrayProperty_PassImplicitCallClassFunc;
13087 var
13088   aMarker: PSrcMarker;
13089   Elements: TFPList;
13090   ActualImplicitCallWithoutParams, ExpectedImplicitCallWithoutParams: Boolean;
13091   i: Integer;
13092   El: TPasElement;
13093   Ref: TResolvedReference;
13094 begin
13095   StartProgram(false);
13096   Add([
13097   'type',
13098   '  TObject = class',
13099   '    function GetItems(s: string): string;',
13100   '    property Items[s: string]: string read GetItems; default;',
13101   '    class function Desc: string; virtual; abstract;',
13102   '  end;',
13103   'function TObject.GetItems(s: string): string;',
13104   'begin',
13105   '  Result:=Items[{#a_implicit}Desc];',
13106   '  Result:=Items[{#b_direct}Desc()];',
13107   '  Result:=Items[Self.{#c_implicit}Desc];',
13108   '  Result:=Items[Self.{#d_direct}Desc()];',
13109   'end;',
13110   'var b: TObject;',
13111   '  s: string;',
13112   'begin',
13113   '  s:=b.Items[b.{#m_implicit}Desc];',
13114   '  s:=b.Items[b.{#n_direct}Desc()];',
13115   '  s:=b.Items[TObject.{#o_implicit}Desc];',
13116   '  s:=b.Items[TObject.{#p_direct}Desc()];',
13117   '  s:=b[b.{#q_implicit}Desc];',
13118   '  s:=b[b.{#r_direct}Desc()];',
13119   '  s:=b[TObject.{#s_implicit}Desc];',
13120   '  s:=b[TObject.{#t_direct}Desc()];',
13121   '']);
13122   ParseProgram;
13123   aMarker:=FirstSrcMarker;
13124   while aMarker<>nil do
13125     begin
13126     //writeln('TTestResolver.TestArrayProperty_PassImplicitCallClassFunc ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
13127     Elements:=FindElementsAt(aMarker);
13128     try
13129       ActualImplicitCallWithoutParams:=false;
13130       Ref:=nil;
13131       for i:=0 to Elements.Count-1 do
13132         begin
13133         El:=TPasElement(Elements[i]);
13134         //writeln('TTestResolver.TestArrayProperty_PassImplicitCallClassFunc ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
13135         if not (El.CustomData is TResolvedReference) then continue;
13136         Ref:=TResolvedReference(El.CustomData);
13137         if Ref.Declaration is TPasProcedure then
13138           break
13139         else
13140           Ref:=nil;
13141         end;
13142       if Ref=nil then
13143         RaiseErrorAtSrcMarker('missing proc ref at "#'+aMarker^.Identifier+'"',aMarker);
13144       ActualImplicitCallWithoutParams:=rrfImplicitCallWithoutParams in Ref.Flags;
13145       ExpectedImplicitCallWithoutParams:=RightStr(aMarker^.Identifier,length('_implicit'))='_implicit';
13146       if ActualImplicitCallWithoutParams<>ExpectedImplicitCallWithoutParams then
13147         RaiseErrorAtSrcMarker('wrong implicit call at "#'+aMarker^.Identifier
13148           +', ExpectedImplicitCall='+BoolToStr(ExpectedImplicitCallWithoutParams,true)+'"',aMarker);
13149     finally
13150       Elements.Free;
13151     end;
13152     aMarker:=aMarker^.Next;
13153     end;
13154 end;
13155 
13156 procedure TTestResolver.TestProperty_WrongTypeAsIndexFail;
13157 begin
13158   StartProgram(false);
13159   Add('type');
13160   Add('  TObject = class');
13161   Add('    function GetItems(Index: string): string;');
13162   Add('    property Items[Index: string]: string read getitems;');
13163   Add('  end;');
13164   Add('function tobject.getitems(index: string): string;');
13165   Add('begin');
13166   Add('end;');
13167   Add('var Obj: tobject;');
13168   Add('begin');
13169   Add('  obj.Items[3]:=''4'';');
13170   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "String"',
13171     nIncompatibleTypeArgNo);
13172 end;
13173 
13174 procedure TTestResolver.TestProperty_Option_ClassPropertyNonStatic;
13175 begin
13176   ResolverEngine.Options:=ResolverEngine.Options+[proClassPropertyNonStatic];
13177   StartProgram(false);
13178   Add('type');
13179   Add('  TObject = class');
13180   Add('    class function GetB: longint;');
13181   Add('    class procedure SetB(Value: longint);');
13182   Add('    class property B: longint read GetB write SetB;');
13183   Add('  end;');
13184   Add('class function TObject.GetB: longint;');
13185   Add('begin');
13186   Add('end;');
13187   Add('class procedure TObject.SetB(Value: longint);');
13188   Add('begin');
13189   Add('end;');
13190   Add('begin');
13191   Add('  TObject.B:=4;');
13192   Add('  if TObject.B=6 then;');
13193   Add('  if 7=TObject.B then;');
13194   ParseProgram;
13195 end;
13196 
13197 procedure TTestResolver.TestDefaultProperty;
13198 begin
13199   StartProgram(false);
13200   Add([
13201   'type',
13202   '  TObject = class',
13203   '  end;',
13204   '  TBird = class',
13205   '    function GetB(Index: longint): longint;',
13206   '    procedure SetB(Index: longint; Value: longint);',
13207   '    property B[Index: longint]: longint read GetB write SetB; default;',
13208   '  end;',
13209   'function TBird.GetB(Index: longint): longint;',
13210   'begin',
13211   'end;',
13212   'procedure TBird.SetB(Index: longint; Value: longint);',
13213   'begin',
13214   '  if Value=Self[Index] then ;',
13215   '  Self[Index]:=Value;',
13216   'end;',
13217   'var',
13218   '  b: TBird;',
13219   '  o: TObject;',
13220   'begin',
13221   '  b[3]:=4;',
13222   '  if b[5]=6 then;',
13223   '  if 7=b[8] then;',
13224   '  (o as TBird)[9]:=10;',
13225   '']);
13226   ParseProgram;
13227 end;
13228 
13229 procedure TTestResolver.TestDefaultPropertyIncVisibility;
13230 begin
13231   AddModuleWithIntfImplSrc('unit1.pp',
13232     LinesToStr([
13233     'type',
13234     '  TNumber = longint;',
13235     '  TInteger = longint;',
13236     '  TObject = class',
13237     '  private',
13238     '    function GetItems(Index: TNumber): TInteger; virtual; abstract;',
13239     '    procedure SetItems(Index: TInteger; Value: TNumber); virtual; abstract;',
13240     '  protected',
13241     '    property Items[Index: TNumber]: longint read GetItems write SetItems;',
13242     '  end;']),
13243     LinesToStr([
13244     '']));
13245 
13246   StartProgram(true);
13247   Add([
13248   'uses unit1;',
13249   'type',
13250   '  TBird = class',
13251   '  public',
13252   '    property Items;',
13253   '  end;',
13254   'procedure DoIt(i: TInteger);',
13255   'begin',
13256   'end;',
13257   'var b: TBird;',
13258   'begin',
13259   '  b.Items[1]:=2;',
13260   '  b.Items[3]:=b.Items[4];',
13261   '  DoIt(b.Items[5]);',
13262   '']);
13263   ParseProgram;
13264 end;
13265 
13266 procedure TTestResolver.TestProperty_MissingDefault;
13267 begin
13268   StartProgram(false);
13269   Add('type');
13270   Add('  TObject = class');
13271   Add('  end;');
13272   Add('var o: TObject;');
13273   Add('begin');
13274   Add('  if o[5]=6 then;');
13275   CheckResolverException('illegal qualifier "[" after "TObject"',
13276     nIllegalQualifierAfter);
13277 end;
13278 
13279 procedure TTestResolver.TestProperty_DefaultDotFail;
13280 begin
13281   StartProgram(false);
13282   Add([
13283   'type',
13284   '  TObject = class',
13285   '    function GetItems(Index: byte): byte;',
13286   '    property Items[Index: byte]: byte read GetItems; default;',
13287   '  end;',
13288   'function TObject.GetItems(Index: byte): byte; begin end;',
13289   'var o: TObject;',
13290   'begin',
13291   '  if o.Items.i=6 then;',
13292   '']);
13293   CheckResolverException('illegal qualifier "." after "Items:array property"',
13294     nIllegalQualifierAfter);
13295 end;
13296 
13297 procedure TTestResolver.TestClassInterface;
13298 begin
13299   StartProgram(false);
13300   Add([
13301   'type',
13302   '  {$interfaces corba}',
13303   '  ICorbaIntf = interface',
13304   '  end;',
13305   '  {$interfaces com}',
13306   '  IUnknown = interface',
13307   '  end;',
13308   '  IInterface = IUnknown;',
13309   '  IComIntf = interface',
13310   '  end;',
13311   'begin']);
13312   ParseProgram;
13313 end;
13314 
13315 procedure TTestResolver.TestClassInterfaceForward;
13316 begin
13317   StartProgram(false);
13318   Add([
13319   'type',
13320   '  IBird = interface;',
13321   '  TObject = class',
13322   '    Bird: IBird;',
13323   '  end;',
13324   '  IUnknown = interface',
13325   '  end;',
13326   '  IBird = interface(IUnknown)',
13327   '  end;',
13328   'begin']);
13329   ParseProgram;
13330 end;
13331 
13332 procedure TTestResolver.TestClassInterfaceVarFail;
13333 begin
13334   StartProgram(false);
13335   Add([
13336   'type',
13337   '  IUnknown = interface',
13338   '    i: longint;',
13339   '  end;',
13340   'begin']);
13341   CheckParserException('Fields are not allowed in interface',nParserNoFieldsAllowed);
13342 end;
13343 
13344 procedure TTestResolver.TestClassInterfaceConstFail;
13345 begin
13346   StartProgram(false);
13347   Add([
13348   'type',
13349   '  IUnknown = interface',
13350   '    const i = 3;',
13351   '  end;',
13352   'begin']);
13353   CheckParserException('CONST is not allowed in interface',nParserXNotAllowedInY);
13354 end;
13355 
13356 procedure TTestResolver.TestClassInterfaceClassMethodFail;
13357 begin
13358   StartProgram(false);
13359   Add([
13360   'type',
13361   '  IUnknown = interface',
13362   '    class procedure DoIt;',
13363   '  end;',
13364   'begin']);
13365   CheckParserException('CLASS is not allowed in interface',nParserXNotAllowedInY);
13366 end;
13367 
13368 procedure TTestResolver.TestClassInterfaceNestedTypeFail;
13369 begin
13370   StartProgram(false);
13371   Add([
13372   'type',
13373   '  IUnknown = interface',
13374   '    type l = longint;',
13375   '  end;',
13376   'begin']);
13377   CheckParserException('TYPE is not allowed in interface',nParserXNotAllowedInY);
13378 end;
13379 
13380 procedure TTestResolver.TestClassInterfacePropertyStoredFail;
13381 begin
13382   StartProgram(false);
13383   Add([
13384   'type',
13385   '  IUnknown = interface',
13386   '    function GetSize: longint;',
13387   '    property Size: longint read GetSize stored false;',
13388   '  end;',
13389   'begin']);
13390   CheckParserException('STORED is not allowed in interface',nParserXNotAllowedInY);
13391 end;
13392 
13393 procedure TTestResolver.TestClassInterface_ConstructorFail;
13394 begin
13395   StartProgram(false);
13396   Add([
13397   'type',
13398   '  IUnknown = interface',
13399   '    constructor Create;',
13400   '  end;',
13401   'begin']);
13402   CheckParserException('constructor is not allowed in interface',nParserXNotAllowedInY);
13403 end;
13404 
13405 procedure TTestResolver.TestClassInterface_DelphiClassAncestorIntfFail;
13406 begin
13407   StartProgram(false);
13408   Add([
13409   '{$mode delphi}',
13410   'type',
13411   '  IInterface = interface',
13412   '  end;',
13413   '  TObject = class(IInterface)',
13414   '  end;',
13415   'begin']);
13416   CheckResolverException('class type expected, but interface type found',nXExpectedButYFound);
13417 end;
13418 
13419 procedure TTestResolver.TestClassInterface_ObjFPCClassAncestorIntf;
13420 begin
13421   StartProgram(false);
13422   Add([
13423   '{$mode objfpc}',
13424   'type',
13425   '  IUnknown = interface',
13426   '  end;',
13427   '  TObject = class(IUnknown)',
13428   '  end;',
13429   'begin']);
13430   ParseProgram;
13431 end;
13432 
13433 procedure TTestResolver.TestClassInterface_MethodVirtualFail;
13434 begin
13435   StartProgram(false);
13436   Add([
13437   'type',
13438   '  IUnknown = interface',
13439   '    procedure DoIt; virtual;',
13440   '  end;',
13441   'begin']);
13442   CheckParserException('Fields are not allowed in interface',nParserNoFieldsAllowed);
13443 end;
13444 
13445 procedure TTestResolver.TestClassInterface_Overloads;
13446 begin
13447   StartProgram(false);
13448   Add([
13449   'type',
13450   '  IUnknown = interface',
13451   '    procedure DoIt(i: longint);',
13452   '    procedure DoIt(s: string);',
13453   '  end;',
13454   '  IBird = interface',
13455   '    procedure DoIt(b: boolean); overload;',
13456   '  end;',
13457   '  TObject = class end;',
13458   '  TBird = class(TObject,IBird)',
13459   '    procedure DoIt(i: longint); virtual; abstract;',
13460   '    procedure DoIt(s: string); virtual; abstract;',
13461   '    procedure DoIt(b: boolean); virtual; abstract;',
13462   '  end;',
13463   'var i: IBird;',
13464   'begin',
13465   '  i.DoIt(3);',
13466   '  i.DoIt(''abc'');',
13467   '  i.DoIt(true);',
13468   '']);
13469   ParseProgram;
13470   CheckResolverUnexpectedHints();
13471 end;
13472 
13473 procedure TTestResolver.TestClassInterface_OverloadHint;
13474 begin
13475   StartProgram(false);
13476   Add([
13477   'type',
13478   '  IUnknown = interface',
13479   '    procedure DoIt;',
13480   '  end;',
13481   '  IBird = interface',
13482   '    procedure DoIt;',
13483   '  end;',
13484   'begin']);
13485   ParseProgram;
13486   CheckResolverHint(mtHint,nMethodHidesNonVirtualMethodExactly,
13487     'method hides identifier at "afile.pp(4,19)". Use reintroduce');
13488 end;
13489 
13490 procedure TTestResolver.TestClassInterface_OverloadNoHint;
13491 begin
13492   StartProgram(false);
13493   Add([
13494   'type',
13495   '  IUnknown = interface',
13496   '    procedure DoIt;',
13497   '    procedure DoIt(i: longint);',
13498   '  end;',
13499   'begin']);
13500   ParseProgram;
13501   CheckResolverUnexpectedHints;
13502 end;
13503 
13504 procedure TTestResolver.TestClassInterface_IntfListClassFail;
13505 begin
13506   StartProgram(false);
13507   Add([
13508   'type',
13509   '  TObject = class',
13510   '  end;',
13511   '  TAnimal = class',
13512   '  end;',
13513   '  TBird = class(TObject,TAnimal)',
13514   '  end;',
13515   'begin']);
13516   CheckResolverException('interface type expected, but class type found',nXExpectedButYFound);
13517 end;
13518 
13519 procedure TTestResolver.TestClassInterface_IntfListDuplicateFail;
13520 begin
13521   StartProgram(false);
13522   Add([
13523   'type',
13524   '  IUnknown = interface',
13525   '  end;',
13526   '  IA = interface',
13527   '  end;',
13528   '  IB = IA;',
13529   '  TObject = class(IA,IB)',
13530   '  end;',
13531   'begin']);
13532   CheckResolverException('Duplicate identifier "IB" at 1',nDuplicateIdentifier);
13533 end;
13534 
13535 procedure TTestResolver.TestClassInterface_MissingMethodFail;
13536 begin
13537   StartProgram(false);
13538   Add([
13539   'type',
13540   '  IUnknown = interface',
13541   '    procedure DoIt;',
13542   '  end;',
13543   '  TObject = class(IUnknown)',
13544   '  end;',
13545   'begin']);
13546   CheckResolverException('No matching implementation for interface method "procedure IUnknown.DoIt of Object" found',
13547     nNoMatchingImplForIntfMethodXFound);
13548 end;
13549 
13550 procedure TTestResolver.TestClassInterface_MissingAncestorMethodFail;
13551 begin
13552   StartProgram(false);
13553   Add([
13554   'type',
13555   '  IUnknown = interface',
13556   '    procedure DoIt;',
13557   '  end;',
13558   '  IBird = interface',
13559   '  end;',
13560   '  TObject = class(IBird)',
13561   '  end;',
13562   'begin']);
13563   CheckResolverException('No matching implementation for interface method "procedure IUnknown.DoIt of Object" found',
13564     nNoMatchingImplForIntfMethodXFound);
13565 end;
13566 
13567 procedure TTestResolver.TestClassInterface_DefaultProperty;
13568 begin
13569   StartProgram(false);
13570   Add([
13571   'type',
13572   '  IUnknown = interface',
13573   '  end;',
13574   '  IA = interface',
13575   '    function GetItems(Index: longint): boolean;',
13576   '    procedure SetItems(Index: longint; Value: boolean);',
13577   '    property Items[IndeX: longint]: boolean read GetItems write SetItems; default;',
13578   '  end;',
13579   '  IB = IA;',
13580   '  TObject = class(IB)',
13581   '  strict private',
13582   '    function GetItems(Index: longint): boolean; virtual; abstract;',
13583   '    procedure SetItems(Index: longint; Value: boolean); virtual; abstract;',
13584   '  end;',
13585   'var',
13586   '  a: IA;',
13587   '  b: IB;',
13588   'begin',
13589   '  a[1]:=a[2];',
13590   '  b[3]:=b[4];']);
13591   ParseProgram;
13592 end;
13593 
13594 procedure TTestResolver.TestClassInterface_MethodResolution;
13595 begin
13596   StartProgram(false);
13597   Add([
13598   'type',
13599   '  IUnknown = interface',
13600   '    procedure DoIt(i: longint);',
13601   '    procedure DoIt(s: string);',
13602   '    function DoIt(b: boolean): boolean;',
13603   '    function GetIt: longint;',
13604   '  end;',
13605   '  TObject = class(IUnknown)',
13606   '    procedure IUnknown.DoIt = DoSome;',
13607   '    function IUnknown.GetIt = GetIt;',
13608   '    procedure DoSome(i: longint); virtual; abstract;',
13609   '    procedure DoSome(s: string); virtual; abstract;',
13610   '    function GetIt: longint; virtual; abstract;',
13611   '    function DoIt(b: boolean): boolean; virtual; abstract;',
13612   '  end;',
13613   'begin']);
13614   ParseProgram;
13615 end;
13616 
13617 procedure TTestResolver.TestClassInterface_MethodResolutionDuplicateFail;
13618 begin
13619   StartProgram(false);
13620   Add([
13621   'type',
13622   '  IUnknown = interface',
13623   '    procedure DoIt;',
13624   '  end;',
13625   '  TObject = class(IUnknown)',
13626   '    procedure IUnknown.DoIt = DoSome;',
13627   '    procedure IUnknown.DoIt = DoMore;',
13628   '    procedure DoSome; virtual; abstract;',
13629   '    procedure DoMore; virtual; abstract;',
13630   '  end;',
13631   'begin']);
13632   CheckResolverException('Duplicate identifier "procedure IUnknown.DoIt" at afile.pp(7,14) at afile.pp (8,24)',nDuplicateIdentifier);
13633 end;
13634 
13635 procedure TTestResolver.TestClassInterface_DelegationIntf;
13636 begin
13637   StartProgram(false);
13638   Add([
13639   'type',
13640   '  IUnknown = interface',
13641   '    procedure DoIt;',
13642   '  end;',
13643   '  IBird = interface',
13644   '  end;',
13645   '  TObject = class(IUnknown, IBird)',
13646   '    function GetI: IBird; virtual; abstract;',
13647   '    property MyI: IBird read GetI implements IUnknown, IBird;',
13648   '  end;',
13649   'begin']);
13650   ParseProgram;
13651 end;
13652 
13653 procedure TTestResolver.TestClassInterface_Delegation_DuplPropFail;
13654 begin
13655   StartProgram(false);
13656   Add([
13657   'type',
13658   '  IUnknown = interface',
13659   '    procedure DoIt;',
13660   '  end;',
13661   '  IBird = interface',
13662   '  end;',
13663   '  TObject = class(IUnknown, IBird)',
13664   '    function GetI: IBird; virtual; abstract;',
13665   '    property MyI: IBird read GetI implements IBird;',
13666   '    property MyJ: IBird read GetI implements IBird;',
13667   '  end;',
13668   'begin']);
13669   CheckResolverException('Duplicate implements for interface "IBird" at afile.pp(10,17)',
13670     nDuplicateImplementsForIntf);
13671 end;
13672 
13673 procedure TTestResolver.TestClassInterface_Delegation_MethodResFail;
13674 begin
13675   StartProgram(false);
13676   Add([
13677   'type',
13678   '  IUnknown = interface',
13679   '    procedure DoIt;',
13680   '  end;',
13681   '  IBird = interface',
13682   '  end;',
13683   '  TObject = class(IUnknown, IBird)',
13684   '    function GetI: IBird; virtual; abstract;',
13685   '    procedure IBird.DoIt = DoSome;',
13686   '    procedure DoSome; virtual; abstract;',
13687   '    property MyI: IBird read GetI implements IBird;',
13688   '  end;',
13689   'begin']);
13690   CheckResolverException('Cannot mix method resolution and delegation at afile.pp(12,17)',
13691     nCannotMixMethodResolutionAndDelegationAtX);
13692 end;
13693 
13694 procedure TTestResolver.TestClassInterface_DelegationClass;
13695 begin
13696   StartProgram(false);
13697   Add([
13698   'type',
13699   '  IUnknown = interface',
13700   '    procedure DoIt;',
13701   '  end;',
13702   '  IBird = interface',
13703   '  end;',
13704   '  TObject = class',
13705   '  end;',
13706   '  TBird = class(IBird)',
13707   '    procedure DoIt; virtual; abstract;',
13708   '  end;',
13709   '  TEagle = class(IBird)',
13710   '    FBird: TBird;',
13711   '    property Bird: TBird read FBird implements IBird;',
13712   '  end;',
13713   'begin']);
13714   ParseProgram;
13715 end;
13716 
13717 procedure TTestResolver.TestClassInterface_DelegationFQN;
13718 begin
13719   StartProgram(false);
13720   Add([
13721   'type',
13722   '  IUnknown = interface',
13723   '    procedure DoIt;',
13724   '  end;',
13725   '  TObject = class',
13726   '  end;',
13727   '  TBird = class(IUnknown)',
13728   '    procedure DoIt; virtual; abstract;',
13729   '  end;',
13730   '  TEagle = class(IUnknown)',
13731   '    FBird: TBird;',
13732   '    property Bird: TBird read FBird implements afile.IUnknown;',
13733   '  end;',
13734   'begin']);
13735   ParseProgram;
13736 end;
13737 
13738 procedure TTestResolver.TestClassInterface_Assign;
13739 begin
13740   StartProgram(false);
13741   Add([
13742   'type',
13743   '  IUnknown = interface',
13744   '  end;',
13745   '  IBird = interface',
13746   '    procedure Fly;',
13747   '  end;',
13748   '  IEagle = interface(IBird)',
13749   '  end;',
13750   '  TObject = class',
13751   '  end;',
13752   '  TBird = class(IBird)',
13753   '    procedure Fly; virtual; abstract;',
13754   '  end;',
13755   '  TAlbatros = class(TBird)',
13756   '  end;',
13757   'var',
13758   '  i: IUnknown = nil;',
13759   '  e: IEagle;',
13760   '  b: IBird;',
13761   '  oBird,oBird2: TBird;',
13762   '  o: TObject;',
13763   '  a: TAlbatros;',
13764   '  p: pointer;',
13765   'begin',
13766   '  if Assigned(i) then ;',
13767   '  if TypeInfo(i)=nil then ;',
13768   '  i:=nil;',
13769   '  i:=i;',
13770   '  i:=e;',
13771   '  if i=nil then ;',
13772   '  if i=e then ;',
13773   '  if e=i then ;',
13774   '  e:=IEagle(i);',
13775   '  if i is IEagle then ;',
13776   '  e:=i as IEagle;',
13777   '  b:=oBird;',
13778   '  b:=a;',
13779   '  i:=IBird(oBird);', // FPC needs GUID
13780   '  oBird2:=TBird(i);', // not supported by FPC
13781   '  oBird2:=TBird(e);', // not supported by FPC
13782   '  i:=o as IBird;', // FPC needs GUID
13783   '  oBird2:=i as TBird;',
13784   '  oBird2:=e as TBird;',
13785   '  if o is IBird then ;', // FPC needs GUID
13786   '  if i is TBird then ;',
13787   '  if e is TBird then ;',
13788   '  p:=i;',
13789   '  if p=i then ;',
13790   '  if i=p then ;',
13791   '']);
13792   ParseProgram;
13793 end;
13794 
13795 procedure TTestResolver.TestClassInterface_AssignObjVarIntfVarFail;
13796 begin
13797   StartProgram(false);
13798   Add([
13799   'type',
13800   '  IUnknown = interface',
13801   '  end;',
13802   '  TObject = class(IUnknown)',
13803   '  end;',
13804   'var',
13805   '  i: IUnknown;',
13806   '  o: TObject;',
13807   'begin',
13808   '  o:=i;',
13809   '']);
13810   CheckResolverException('Incompatible types: got "IUnknown" expected "TObject"',nIncompatibleTypesGotExpected);
13811 end;
13812 
13813 procedure TTestResolver.TestClassInterface_AssignDescendentFail;
13814 begin
13815   StartProgram(false);
13816   Add([
13817   'type',
13818   '  IUnknown = interface',
13819   '  end;',
13820   '  IBird = interface',
13821   '  end;',
13822   '  TObject = class(IBird)',
13823   '  end;',
13824   'var',
13825   '  i: IUnknown;',
13826   '  o: TObject;',
13827   'begin',
13828   '  i:=o;',
13829   '']);
13830   CheckResolverException('Incompatible types: got "TObject" expected "IUnknown"',nIncompatibleTypesGotExpected);
13831 end;
13832 
13833 procedure TTestResolver.TestClassInterface_Args;
13834 begin
13835   StartProgram(false);
13836   Add([
13837   'type',
13838   '  IUnknown = interface',
13839   '  end;',
13840   '  IBird = interface',
13841   '  end;',
13842   '  TObject = class',
13843   '  end;',
13844   '  TBird = class(IBird)',
13845   '  end;',
13846   'function GetIt(var u; i: IBird; const j: IBird): IBird;',
13847   'begin',
13848   '  Result:=IBird(u);',
13849   '  Result:=i;',
13850   '  Result:=j;',
13851   'end;',
13852   'procedure Change(var i: IBird; out j: IBird);',
13853   'begin',
13854   '  i:=GetIt(i,i,i);',
13855   'end;',
13856   'var',
13857   '  i: IBird;',
13858   '  o: TBird;',
13859   'begin',
13860   '  i:=GetIt(i,i,i);',
13861   '  Change(i,i);',
13862   '  GetIt(i,o,o);',
13863   '']);
13864   ParseProgram;
13865 end;
13866 
13867 procedure TTestResolver.TestClassInterface_Enumerator;
13868 begin
13869   StartProgram(false);
13870   Add([
13871   'type',
13872   '  TObject = class end;',
13873   '  TItem = TObject;',
13874   '  TEnumerator = class',
13875   '    FCurrent: TItem;',
13876   '    property Current: TItem read FCurrent;',
13877   '    function MoveNext: boolean;',
13878   '  end;',
13879   '  IUnknown = interface end;',
13880   '  IEnumerator = interface',
13881   '    function GetCurrent: TItem;',
13882   '    property Current: TItem read GetCurrent;',
13883   '    function MoveNext: boolean;',
13884   '  end;',
13885   '  IEnumerable = interface',
13886   '    function GetEnumerator: IEnumerator;',
13887   '  end;',
13888   '  IBird = interface',
13889   '    function GetEnumerator: TEnumerator;',
13890   '  end;',
13891   'function TEnumerator.MoveNext: boolean;',
13892   'begin',
13893   'end;',
13894   'var',
13895   '  e: IEnumerable;',
13896   '  b: IBird;',
13897   '  i: TItem;',
13898   '  {#i2}i2: TItem;',
13899   'begin',
13900   '  for i in e do {@i2}i2:=i;',
13901   '  for i in b do {@i2}i2:=i;']);
13902   ParseProgram;
13903 end;
13904 
13905 procedure TTestResolver.TestClassInterface_PassTypecastClassToIntfAsVarParamFail;
13906 begin
13907   StartProgram(false);
13908   Add([
13909   '{$interfaces corba}',
13910   'type',
13911   '  IUnknown = interface end;',
13912   '  TObject = class end;',
13913   '  TBall = class(IUnknown) end;',
13914   'procedure DoIt(var i: IUnknown); begin end;',
13915   'var b: TBall;',
13916   'begin',
13917   '  DoIt(IUnknown(b));']);
13918   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
13919 end;
13920 
13921 procedure TTestResolver.
13922   TestClassInterface_PassTypecastIntfToClassAsVarParamFail;
13923 begin
13924   StartProgram(false);
13925   Add([
13926   '{$interfaces corba}',
13927   'type',
13928   '  IUnknown = interface end;',
13929   '  TObject = class end;',
13930   '  TBall = class(IUnknown) end;',
13931   'procedure DoIt(var i: IUnknown); begin end;',
13932   'var i: IUnknown;',
13933   'begin',
13934   '  DoIt(TBall(i));']);
13935   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
13936 end;
13937 
13938 procedure TTestResolver.TestClassInterface_GUID;
13939 begin
13940   StartProgram(false);
13941   Add([
13942   '{$interfaces corba}',
13943   'type',
13944   '  IUnknown = interface',
13945   '    [''{F31DB68F-3010-D355-4EBA-CDD4EF4A737C}'']',
13946   '  end;',
13947   '  TObject = class end;',
13948   '  TGUID = record D1,D2,D3,D4: word; end;',
13949   '  TAliasGUID = TGUID;',
13950   '  TGUIDString = type string;',
13951   '  TAliasGUIDString = TGUIDString;',
13952   'procedure {#A}DoIt(const g: TAliasGUID); overload;',
13953   'begin end;',
13954   'procedure {#B}DoIt(const s: TAliasGUIDString); overload;',
13955   'begin end;',
13956   'var',
13957   '  i: IUnknown;',
13958   '  g: TAliasGUID = ''{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}'';',
13959   '  s: TAliasGUIDString;',
13960   'begin',
13961   '  {@A}DoIt(IUnknown);',
13962   '  {@A}DoIt(i);',
13963   '  g:=i;',
13964   '  g:=IUnknown;',
13965   '  g:=''{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}'';',
13966   '  s:=g;',
13967   '  s:=IUnknown;',
13968   '  s:=i;',
13969   '  {@B}DoIt(s);',
13970   '  if s=IUnknown then ;',
13971   '  if IUnknown=s then ;',
13972   '  if s=i then ;',
13973   '  if i=s then ;',
13974   '  if g=IUnknown then ;',
13975   '  if IUnknown=g then ;',
13976   '  if g=i then ;',
13977   '  if i=g then ;',
13978   '  if s=g then ;',
13979   '  if g=s then ;',
13980   '']);
13981   ParseProgram;
13982 end;
13983 
13984 procedure TTestResolver.TestPropertyAssign;
13985 begin
13986   StartProgram(false);
13987   Add('type');
13988   Add('  TObject = class');
13989   Add('    FB: longint;');
13990   Add('    property B: longint read FB write FB;');
13991   Add('  end;');
13992   Add('var');
13993   Add('  o: TObject;');
13994   Add('  i: longint;');
13995   Add('begin');
13996   Add('  {#a1_read}o.{#a2_assign}B:=i;');
13997   Add('  i:={#b1_read}o.{#b2_read}B;');
13998   Add('  if i={#c1_read}o.{#c2_read}B then ;');
13999   Add('  if {#d1_read}o.{#d2_read}B=3 then ;');
14000   ParseProgram;
14001   CheckAccessMarkers;
14002 end;
14003 
14004 procedure TTestResolver.TestPropertyAssignReadOnlyFail;
14005 begin
14006   StartProgram(false);
14007   Add('type');
14008   Add('  TObject = class');
14009   Add('    FB: longint;');
14010   Add('    property B: longint read FB;');
14011   Add('  end;');
14012   Add('var');
14013   Add('  o: TObject;');
14014   Add('begin');
14015   Add('  o.B:=3;');
14016   CheckResolverException('No member is provided to access property',nPropertyNotWritable);
14017 end;
14018 
14019 procedure TTestResolver.TestProperty_PassAsParam;
14020 begin
14021   ResolverEngine.Options:=ResolverEngine.Options+[proPropertyAsVarParam];
14022   StartProgram(false);
14023   Add('type');
14024   Add('  TObject = class');
14025   Add('    FA: longint;');
14026   Add('    property A: longint read FA write FA;');
14027   Add('  end;');
14028   Add('procedure DoIt(i: longint; const j: longint; var k: longint; out l: longint);');
14029   Add('begin');
14030   Add('end;');
14031   Add('var');
14032   Add('  o: TObject;');
14033   Add('begin');
14034   Add('  DoIt({#o1_read}o.{#o_a1_read}a,');
14035   Add('    {#o2_read}o.{#o_a2_read}a,');
14036   Add('    {#o3_read}o.{#o_a3_var}a,');
14037   Add('    {#o4_read}o.{#o_a4_out}a);');
14038   Add('  with o do');
14039   Add('    DoIt({#w_a1_read}a,');
14040   Add('      {#w_a2_read}a,');
14041   Add('      {#w_a3_var}a,');
14042   Add('      {#w_a4_out}a);');
14043   ParseProgram;
14044   CheckAccessMarkers;
14045 end;
14046 
14047 procedure TTestResolver.TestPropertyReadNonReadableFail;
14048 begin
14049   StartProgram(false);
14050   Add('type');
14051   Add('  TObject = class');
14052   Add('    FB: longint;');
14053   Add('    property B: longint write FB;');
14054   Add('  end;');
14055   Add('var');
14056   Add('  o: TObject;');
14057   Add('begin');
14058   Add('  if o.B=3 then;');
14059   CheckResolverException('not readable',nNotReadable);
14060 end;
14061 
14062 procedure TTestResolver.TestWithDo1;
14063 begin
14064   StartProgram(false);
14065   Add('type');
14066   Add('  {#TOBJ}TObject = class');
14067   Add('    {#TOBJ_A}A: longint;');
14068   Add('  end;');
14069   Add('var');
14070   Add('  {#o}{=TOBJ}o: TObject;');
14071   Add('  {#a}a: longint;');
14072   Add('begin');
14073   Add('  {@a}a:=1;');
14074   Add('  with {@o}o do');
14075   Add('    {@TOBJ_A}a:=2;');
14076   ParseProgram;
14077 end;
14078 
14079 procedure TTestResolver.TestWithDo2;
14080 begin
14081   StartProgram(false);
14082   Add('type');
14083   Add('  {#TOBJ}TObject = class');
14084   Add('    {#TOBJ_i}i: longint;');
14085   Add('  end;');
14086   Add('  {#TA}TClassA = class');
14087   Add('    {#TA_j}j: longint;');
14088   Add('    {#TA_b}{=TA}b: TClassA;');
14089   Add('  end;');
14090   Add('var');
14091   Add('  {#o}{=TOBJ}o: TObject;');
14092   Add('  {#a}{=TA}a: TClassA;');
14093   Add('  {#i}i: longint;');
14094   Add('begin');
14095   Add('  {@i}i:=1;');
14096   Add('  with {@o}o do');
14097   Add('    {@TOBJ_i}i:=2;');
14098   Add('  {@i}i:=1;');
14099   Add('  with {@o}o,{@a}a do begin');
14100   Add('    {@TOBJ_i}i:=3;');
14101   Add('    {@TA_j}j:=4;');
14102   Add('    {@TA_b}b:={@a}a;');
14103   Add('  end;');
14104   ParseProgram;
14105 end;
14106 
14107 procedure TTestResolver.TestWithDoFuncResult;
14108 begin
14109   StartProgram(false);
14110   Add('type');
14111   Add('  {#TOBJ}TObject = class');
14112   Add('    {#TOBJ_i}i: longint;');
14113   Add('  end;');
14114   Add('  {#TA}TClassA = class');
14115   Add('    {#TA_j}j: longint;');
14116   Add('    {#TA_b}{=TA}b: TClassA;');
14117   Add('  end;');
14118   Add('function {#GiveA}Give: TClassA;');
14119   Add('begin');
14120   Add('end;');
14121   Add('function {#GiveB}Give(i: longint): TClassA;');
14122   Add('begin');
14123   Add('end;');
14124   Add('var');
14125   Add('  {#o}{=TOBJ}o: TObject;');
14126   Add('  {#a}{=TA}a: TClassA;');
14127   Add('  {#i}i: longint;');
14128   Add('begin');
14129   Add('  with {@GiveA}Give do {@TOBJ_i}i:=3;');
14130   Add('  with {@GiveA}Give() do {@TOBJ_i}i:=3;');
14131   Add('  with {@GiveB}Give(2) do {@TOBJ_i}i:=3;');
14132   ParseProgram;
14133 end;
14134 
14135 procedure TTestResolver.TestWithDoConstructor;
14136 begin
14137   StartProgram(false);
14138   Add('type');
14139   Add('  {#TOBJ}TObject = class');
14140   Add('    {#TOBJ_i}i: longint;');
14141   Add('  end;');
14142   Add('  {#TA}TClassA = class');
14143   Add('    {#TA_j}j: longint;');
14144   Add('    {#TA_b}{=TA}b: TClassA;');
14145   Add('    constructor {#A_CreateA}Create;');
14146   Add('    constructor {#A_CreateB}Create(i: longint);');
14147   Add('  end;');
14148   Add('constructor TClassA.Create;');
14149   Add('begin');
14150   Add('end;');
14151   Add('constructor TClassA.Create(i: longint);');
14152   Add('begin');
14153   Add('end;');
14154   Add('var');
14155   Add('  {#o}{=TOBJ}o: TObject;');
14156   Add('  {#a}{=TA}a: TClassA;');
14157   Add('  {#i}i: longint;');
14158   Add('begin');
14159   Add('  with TClassA.{@A_CreateA}Create do {@TOBJ_i}i:=3;');
14160   Add('  with TClassA.{@A_CreateA}Create() do {@TOBJ_i}i:=3;');
14161   Add('  with TClassA.{@A_CreateB}Create(2) do {@TOBJ_i}i:=3;');
14162   ParseProgram;
14163 end;
14164 
14165 procedure TTestResolver.TestDynArrayOfLongint;
14166 begin
14167   StartProgram(false);
14168   Add('type TIntArray = array of longint;');
14169   Add('var a: TIntArray;');
14170   Add('begin');
14171   Add('  a:=nil;');
14172   Add('  if a=nil then ;');
14173   Add('  if nil=a then ;');
14174   Add('  SetLength(a,3);');
14175   Add('  a[0]:=1;');
14176   Add('  a[1]:=length(a);');
14177   Add('  a[2]:=a[0];');
14178   Add('  if a[3]=a[4] then ;');
14179   Add('  a[a[5]]:=a[a[6]];');
14180   ParseProgram;
14181 end;
14182 
14183 procedure TTestResolver.TestDynArrayOfSelfFail;
14184 begin
14185   StartProgram(false);
14186   Add('type TIntArray = array of TIntArray;');
14187   Add('begin');
14188   CheckResolverException(sIllegalExpression,nIllegalExpression);
14189 end;
14190 
14191 procedure TTestResolver.TestStaticArray;
14192 begin
14193   StartProgram(false);
14194   Add('type');
14195   Add('  TArrA = array[1..2] of longint;');
14196   Add('  TArrB = array[char] of boolean;');
14197   Add('  TArrC = array[byte,''a''..''z''] of longint;');
14198   Add('const');
14199   Add('  ArrA: TArrA = (3,4);');
14200   Add('var');
14201   Add('  a: TArrA;');
14202   Add('  b: TArrB;');
14203   Add('  c: TArrC;');
14204   Add('begin');
14205   Add('  a[1]:=1;');
14206   Add('  if a[2]=low(a) then ;');
14207   Add('  b[''x'']:=true;');
14208   Add('  if b[''y''] then ;');
14209   Add('  c[3,''f'']:=1;');
14210   Add('  if c[4,''g'']=a[1] then ;');
14211   ParseProgram;
14212 end;
14213 
14214 procedure TTestResolver.TestStaticArrayOfChar;
14215 begin
14216   ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
14217   StartProgram(false);
14218   Add([
14219   'type',
14220   '  TArrA = array[1..3] of char;',
14221   'const',
14222   '  A: TArrA = (''p'',''a'',''p'');', // duplicate allowed, this bracket is not a set
14223   '  B: TArrA = ''pas'';',
14224   '  Three = length(TArrA);',
14225   '  C: array[1..Three] of char = ''pas'';',
14226   '  D = ''pp'';',
14227   '  E: array[length(D)..Three] of char = D;',
14228   '  F: array[1..2] of widechar = ''äö'';',
14229   '  G: array[1..2] of char = ''ä'';',
14230   '  H: array[1..4] of char = ''äö'';',
14231   '  I: array[1..4] of char = ''ä''+''ö'';',
14232   'begin']);
14233   ParseProgram;
14234 end;
14235 
14236 procedure TTestResolver.TestStaticArrayOfCharDelphi;
14237 begin
14238   ResolverEngine.ExprEvaluator.DefaultStringCodePage:=CP_UTF8;
14239   StartProgram(false);
14240   Add([
14241   '{$mode delphi}',
14242   'type',
14243   '  TArrA = array[1..3] of char;',
14244   'const',
14245   '  A: TArrA = (''p'',''a'',''p'');', // duplicate allowed, this bracket is not a set
14246   '  B: TArrA = ''pas'';',
14247   '  Three = length(TArrA);',
14248   '  C: array[1..Three] of char = ''pas'';',
14249   '  D = ''pp'';',
14250   '  E: array[length(D)..Three] of char = D;',
14251   '  F: array[1..2] of widechar = ''äö'';',
14252   '  G: array[1..2] of char = ''ä'';',
14253   '  H: array[1..4] of char = ''äö'';',
14254   '  I: array[1..4] of char = ''ä''+''ö'';',
14255   'begin']);
14256   ParseProgram;
14257 end;
14258 
14259 procedure TTestResolver.TestStaticArrayOfRangeElCheckFail;
14260 begin
14261   StartProgram(false);
14262   Add('var');
14263   Add('  A: array[1..2] of shortint = (1,300);');
14264   Add('begin');
14265   ParseProgram;
14266   CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
14267     'range check error while evaluating constants (300 is not between -128 and 127)');
14268 end;
14269 
14270 procedure TTestResolver.TestArrayOfChar_String;
14271 begin
14272   StartProgram(false);
14273   Add([
14274   'procedure {#a}Run(const s: string); overload;',
14275   'begin end;',
14276   'procedure {#b}Run(const a: array of char); overload;',
14277   'begin end;',
14278   'var',
14279   '  s: string;',
14280   '  c: char;',
14281   'begin',
14282   '  {@a}Run(''foo'');',
14283   '  {@a}Run(s);',
14284   '  {@a}Run(c);',
14285   '']);
14286   ParseProgram;
14287 end;
14288 
14289 procedure TTestResolver.TestArrayOfArray;
14290 begin
14291   StartProgram(false);
14292   Add('type');
14293   Add('  TArrA = array[byte] of longint;');
14294   Add('  TArrB = array[smallint] of TArrA;');
14295   Add('  TArrC = array of array of longint;');
14296   Add('var');
14297   Add('  b: TArrB;');
14298   Add('  c: TArrC;');
14299   Add('begin');
14300   Add('  b[1][2]:=5;');
14301   Add('  b[1,2]:=5;');
14302   Add('  if b[2,1]=b[0,1] then ;');
14303   Add('  c[3][4]:=c[5,6];');
14304   Add('  Setlength(c[3],7);');
14305   Add('  Setlength(c,8,9);');
14306   ParseProgram;
14307 end;
14308 
14309 procedure TTestResolver.TestArrayOfArray_NameAnonymous;
14310 begin
14311   ResolverEngine.AnonymousElTypePostfix:='$array';
14312   StartProgram(false);
14313   Add('type');
14314   Add('  TArrA = array of array of longint;');
14315   Add('var');
14316   Add('  a: TArrA;');
14317   Add('begin');
14318   Add('  a[1][2]:=5;');
14319   Add('  a[1,2]:=5;');
14320   Add('  if a[2,1]=a[0,1] then ;');
14321   Add('  a[3][4]:=a[5,6];');
14322   ParseProgram;
14323 end;
14324 
14325 procedure TTestResolver.TestFunctionReturningArray;
14326 begin
14327   StartProgram(false);
14328   Add([
14329   'type',
14330   '  TArrA = array[1..20] of longint;',
14331   '  TArrB = array of TArrA;',
14332   'function FuncC: TArrB;',
14333   'begin',
14334   '  SetLength(Result,3);',
14335   'end;',
14336   'begin',
14337   '  FuncC[2,4]:=6;',
14338   '  FuncC()[1,3]:=5;']);
14339   ParseProgram;
14340 end;
14341 
14342 procedure TTestResolver.TestArray_LowHigh;
14343 begin
14344   StartProgram(false);
14345   Add('type');
14346   Add('  TArrA = array[char] of longint;');
14347   Add('  TArrB = array of TArrA;');
14348   Add('var');
14349   Add('  c: char;');
14350   Add('  i: longint;');
14351   Add('begin');
14352   Add('  for c:=low(TArrA) to High(TArrA) do ;');
14353   Add('  for i:=low(TArrB) to High(TArrB) do ;');
14354   ParseProgram;
14355 end;
14356 
14357 procedure TTestResolver.TestArray_LowVarFail;
14358 begin
14359   StartProgram(false);
14360   Add([
14361   'var a: array of longint;',
14362   'const l = length(a);',
14363   'begin']);
14364   CheckResolverException(sConstantExpressionExpected,nConstantExpressionExpected);
14365 end;
14366 
14367 procedure TTestResolver.TestArray_AssignDiffElTypeFail;
14368 begin
14369   StartProgram(false);
14370   Add('type');
14371   Add('  TArrA = array of longint;');
14372   Add('  TArrB = array of byte;');
14373   Add('var');
14374   Add('  a: TArrA;');
14375   Add('  b: TArrB;');
14376   Add('begin');
14377   Add('  a:=b;');
14378   CheckResolverException('Incompatible types: got "array of Longint" expected "array of Byte"',
14379     nIncompatibleTypesGotExpected);
14380 end;
14381 
14382 procedure TTestResolver.TestArray_AssignSameSignatureDelphiFail;
14383 begin
14384   StartProgram(false);
14385   Add('{$mode delphi}');
14386   Add('type');
14387   Add('  TArrA = array of longint;');
14388   Add('  TArrB = array of longint;');
14389   Add('var');
14390   Add('  a: TArrA;');
14391   Add('  b: TArrB;');
14392   Add('begin');
14393   Add('  a:=b;');
14394   CheckResolverException('Incompatible types: got "TArrB" expected "TArrA"',
14395     nIncompatibleTypesGotExpected);
14396 end;
14397 
14398 procedure TTestResolver.TestArray_Assigned;
14399 begin
14400   StartProgram(false);
14401   Add('var a: array of longint;');
14402   Add('begin');
14403   Add('  if Assigned(a) then ;');
14404   ParseProgram;
14405 end;
14406 
14407 procedure TTestResolver.TestPropertyOfTypeArray;
14408 begin
14409   StartProgram(false);
14410   Add('type');
14411   Add('  TArray = array of longint;');
14412   Add('  TObject = class');
14413   Add('    FItems: TArray;');
14414   Add('    function GetItems: TArray;');
14415   Add('    procedure SetItems(Value: TArray);');
14416   Add('    property Items: TArray read FItems write FItems;');
14417   Add('    property Numbers: TArray read GetItems write SetItems;');
14418   Add('  end;');
14419   Add('function TObject.GetItems: TArray;');
14420   Add('begin');
14421   Add('  Result:=FItems;');
14422   Add('end;');
14423   Add('procedure TObject.SetItems(Value: TArray);');
14424   Add('begin');
14425   Add('  FItems:=Value;');
14426   Add('end;');
14427   Add('var Obj: TObject;');
14428   Add('begin');
14429   Add('  Obj.Items[3]:=4;');
14430   Add('  if Obj.Items[5]=6 then;');
14431   Add('  Obj.Numbers[7]:=8;');
14432   Add('  if Obj.Numbers[9]=10 then;');
14433   ParseProgram;
14434 end;
14435 
14436 procedure TTestResolver.TestArrayElementFromFuncResult_AsParams;
14437 var
14438   aMarker: PSrcMarker;
14439   Elements: TFPList;
14440   ActualImplicitCall: Boolean;
14441   i: Integer;
14442   El: TPasElement;
14443   Ref: TResolvedReference;
14444 begin
14445   StartProgram(false);
14446   Add('type Integer = longint;');
14447   Add('type TArrayInt = array of integer;');
14448   Add('function GetArr(vB: integer = 0): tarrayint;');
14449   Add('begin');
14450   Add('end;');
14451   Add('procedure DoIt(vG: integer);');
14452   Add('begin');
14453   Add('end;');
14454   Add('begin');
14455   Add('  doit({#a}getarr[1+1]);');
14456   Add('  doit({#b}getarr()[2+1]);');
14457   Add('  doit({#c}getarr(7)[3+1]);');
14458   ParseProgram;
14459   aMarker:=FirstSrcMarker;
14460   while aMarker<>nil do
14461     begin
14462     //writeln('TTestResolver.TestArrayElementFromFuncResult_AsParams ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
14463     Elements:=FindElementsAt(aMarker);
14464     try
14465       ActualImplicitCall:=false;
14466       for i:=0 to Elements.Count-1 do
14467         begin
14468         El:=TPasElement(Elements[i]);
14469         //writeln('TTestResolver.TestArrayElementFromFuncResult_AsParams ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
14470         if not (El.CustomData is TResolvedReference) then continue;
14471         Ref:=TResolvedReference(El.CustomData);
14472         if rrfImplicitCallWithoutParams in Ref.Flags then
14473           ActualImplicitCall:=true;
14474         break;
14475         end;
14476       case aMarker^.Identifier of
14477       'a':
14478         if not ActualImplicitCall then
14479           RaiseErrorAtSrcMarker('expected rrfImplicitCallWithoutParams at "#'+aMarker^.Identifier+'"',aMarker);
14480       else
14481         if ActualImplicitCall then
14482           RaiseErrorAtSrcMarker('expected no rrfImplicitCallWithoutParams at "#'+aMarker^.Identifier+'"',aMarker);
14483       end;
14484     finally
14485       Elements.Free;
14486     end;
14487     aMarker:=aMarker^.Next;
14488     end;
14489 end;
14490 
14491 procedure TTestResolver.TestArrayEnumTypeRange;
14492 begin
14493   StartProgram(false);
14494   Add('type');
14495   Add('  TEnum = (red,blue);');
14496   Add('  TEnumArray = array[TEnum] of longint;');
14497   Add('var');
14498   Add('  e: TEnum;');
14499   Add('  i: longint;');
14500   Add('  a: TEnumArray;');
14501   Add('  names: array[TEnum] of string = (''red'',''blue'');');
14502   Add('begin');
14503   Add('  e:=low(a);');
14504   Add('  e:=high(a);');
14505   Add('  i:=a[red];');
14506   Add('  a[e]:=a[e];');
14507   ParseProgram;
14508 end;
14509 
14510 procedure TTestResolver.TestArrayEnumTypeConstNotEnoughValuesFail1;
14511 begin
14512   StartProgram(false);
14513   Add('type');
14514   Add('  TEnum = (red,blue);');
14515   Add('var');
14516   Add('  a: array[TEnum] of string = (''red'');');
14517   Add('begin');
14518   CheckResolverException('Expect 2 array elements, but found 1',nExpectXArrayElementsButFoundY);
14519 end;
14520 
14521 procedure TTestResolver.TestArrayEnumTypeConstNotEnoughValuesFail2;
14522 begin
14523   StartProgram(false);
14524   Add('type');
14525   Add('  TEnum = (red,blue,green);');
14526   Add('var');
14527   Add('  a: array[TEnum] of string = (''red'',''blue'');');
14528   Add('begin');
14529   CheckResolverException('Expect 3 array elements, but found 2',nExpectXArrayElementsButFoundY);
14530 end;
14531 
14532 procedure TTestResolver.TestArrayEnumTypeConstWrongTypeFail;
14533 begin
14534   StartProgram(false);
14535   Add('type');
14536   Add('  TEnum = (red,blue);');
14537   Add('var');
14538   Add('  a: array[TEnum] of string = (1,2);');
14539   Add('begin');
14540   CheckResolverException('Incompatible types: got "Longint" expected "String"',
14541     nIncompatibleTypesGotExpected);
14542 end;
14543 
14544 procedure TTestResolver.TestArrayEnumTypeConstNonConstFail;
14545 begin
14546   StartProgram(false);
14547   Add('type');
14548   Add('  TEnum = (red,blue);');
14549   Add('var');
14550   Add('  s: string;');
14551   Add('  a: array[TEnum] of string = (''red'',s);');
14552   Add('begin');
14553   CheckResolverException('Constant expression expected',
14554     nConstantExpressionExpected);
14555 end;
14556 
14557 procedure TTestResolver.TestArrayEnumTypeSetLengthFail;
14558 begin
14559   StartProgram(false);
14560   Add('type');
14561   Add('  TEnum = (red,blue);');
14562   Add('var');
14563   Add('  a: array[TEnum] of longint;');
14564   Add('begin');
14565   Add('  SetLength(a,1);');
14566   CheckResolverException('Incompatible type arg no. 1: Got "static array[] of Longint", expected "string or dynamic array variable"',
14567     nIncompatibleTypeArgNo);
14568 end;
14569 
14570 procedure TTestResolver.TestArrayEnumCustomRange;
14571 begin
14572   StartProgram(false);
14573   Add([
14574   'type',
14575   '  TEnum = (red,blue,green);',
14576   '  TEnumRg = blue..green;',
14577   '  TEnumArray = array[TEnumRg] of longint;',
14578   '  TEnumArray2 = array[blue..green] of longint;',
14579   'var',
14580   '  e: TEnum;',
14581   '  r: TEnumRg;',
14582   '  i: longint;',
14583   '  a: TEnumArray;',
14584   '  b: array[TEnum] of longint;',
14585   '  c: TEnumArray2;',
14586   '  names: array[TEnumRg] of string = (''blue'',''green'');',
14587   'begin',
14588   '  r:=low(a);',
14589   '  r:=high(a);',
14590   '  i:=a[red];',
14591   '  a[e]:=a[e];',
14592   '  a[r]:=a[r];',
14593   '  b[r]:=b[r];',
14594   '  r:=low(c);',
14595   '  r:=high(c);',
14596   '  i:=c[red];',
14597   '  c[e]:=c[e];',
14598   '  c[r]:=c[r];',
14599   '']);
14600   ParseProgram;
14601 end;
14602 
14603 procedure TTestResolver.TestArray_DynArrayConstObjFPC;
14604 begin
14605   Parser.Options:=Parser.Options+[po_cassignments];
14606   StartProgram(false);
14607   Add([
14608   '{$modeswitch arrayoperators}',
14609   'type',
14610   '  integer = longint;',
14611   '  TArrInt = array of integer;',
14612   '  TArrStr = array of string;',
14613   'const',
14614   '  Ints: TArrInt = (1,2,3);',
14615   '  Aliases: TarrStr = (''foo'',''b'');',
14616   '  OneInt: TArrInt = (7);',
14617   '  OneInt2: array of integer = (7);',
14618   '  Chars: array of char = ''aoc'';',
14619   '  Names: array of string = (''a'',''foo'');',
14620   '  NameCount = low(Names)+high(Names)+length(Names);',
14621   'procedure DoIt(Ints: TArrInt);',
14622   'begin',
14623   'end;',
14624   'var i: integer;',
14625   'begin',
14626   '  Ints:= {#a_array}[1,i];',
14627   '  Ints:= {#b1_array}[1,1]+ {#b2_array}[2]+ {#b3_array}[i];',
14628   '  Ints:= {#c_array}[i]+ {#d_array}[2,2];',
14629   '  Ints:=Ints+ {#e_array}[1];',
14630   '  Ints:= {#f_array}[1]+Ints;',
14631   '  Ints:=Ints+OneInt+OneInt2;',
14632   '  Ints+= {#g_array}[i];',
14633   '  Ints+= {#h_array}[1,1];',
14634   '  DoIt( {#i_array}[1,1]);',
14635   '  DoIt( {#j_array}[i]);',
14636   '']);
14637   ParseProgram;
14638   CheckParamsExpr_pkSet_Markers;
14639   CheckResolverUnexpectedHints;
14640 end;
14641 
14642 procedure TTestResolver.TestArray_DynArrayConstDelphi;
14643 begin
14644   StartProgram(false);
14645   Add([
14646   '{$mode delphi}',
14647   'const c= {#c_set}[1,2];',
14648   'type',
14649   '  integer = longint;',
14650   '  TArrInt = array of integer;',
14651   '  TArrStr = array of string;',
14652   '  TArrInt2 = array of TArrInt;',
14653   '  TSetOfEnum = set of (red,blue);',
14654   '  TArrOfSet = array of TSetOfEnum;',
14655   'const',
14656   '  Ints: TArrInt = {#ints_array}[1,2,1];',
14657   '  Aliases: TarrStr = {#aliases_array}[''foo'',''b'',''b''];',
14658   '  OneInt: TArrInt = {#oneint_array}[7];',
14659   '  TwoInt: array of integer = {#twoint1_array}[7]+{#twoint2_array}[8];',
14660   '  Chars: array of char = ''aoc'';',
14661   '  Names: array of string = {#names_array}[''a'',''a''];',
14662   '  NameCount = low(Names)+high(Names)+length(Names);',
14663   'procedure {#DoArrOfSet}DoIt(const s: TArrOfSet); overload; begin end;',
14664   'procedure {#DoArrOfArrInt}DoIt(const a: TArrInt2); overload; begin end;',
14665   'begin',
14666   '  {@DoArrOfSet}DoIt( {#a1_array}[ {#a2_set}[blue], {#a3_set}[red] ]);',
14667   '  {@DoArrOfArrInt}DoIt( {#b1_array}[ {#b2_array}[1], {#b3_array}[2] ]);',
14668   '']);
14669   ParseProgram;
14670   CheckParamsExpr_pkSet_Markers;
14671   CheckResolverUnexpectedHints;
14672 end;
14673 
14674 procedure TTestResolver.TestArray_DynArrAssignStaticDelphiFail;
14675 begin
14676   StartProgram(false);
14677   Add([
14678   '{$mode delphi}',
14679   'type',
14680   '  TIntArr = array[1..3] of longint;',
14681   'var',
14682   '  dyn: array of longint;',
14683   '  sta: TIntArr;',
14684   'begin',
14685   '  dyn:=sta;']);
14686   CheckResolverException('Incompatible types: got "static array" expected "dynamic array"',
14687     nIncompatibleTypesGotExpected);
14688 end;
14689 
14690 procedure TTestResolver.TestArray_Static_Const;
14691 begin
14692   StartProgram(false);
14693   Add([
14694   'type',
14695   '  TIntArr = array[1..3] of longint;',
14696   'const',
14697   '  a = low(TIntArr)+high(TIntArr);',
14698   '  b: array[1..3] of longint = (10,11,12);',
14699   '  c: array[boolean] of TIntArr = ((21,22,23),(31,32,33));',
14700   'begin']);
14701   ParseProgram;
14702   CheckResolverUnexpectedHints;
14703 end;
14704 
14705 procedure TTestResolver.TestArray_Record_Const;
14706 begin
14707   StartProgram(false);
14708   Add([
14709   'type',
14710   '  TPoint = record x, y: longint; end;',
14711   '  TDynArray = array of TPoint;',
14712   '  TStaticArray = array[1..2] of TPoint;',
14713   '  TRecArr = record',
14714   '    DA: TDynArray;',
14715   '    SA: TStaticArray;',
14716   '  end;',
14717   'const',
14718   '  sa: TStaticArray = ( (x:2; y:3), (x:12;y:14) );',
14719   '  da: TDynArray = ( (x:22; y:23), (x:32;y:34) );',
14720   '  ra: TRecArr = (',
14721   '    DA: ( (x:42; y:43), (x:44;y:45) );',
14722   '    SA: ( (x:51; y:52), (x:53;y:54) );',
14723   '  );',
14724   'begin',
14725   '']);
14726   ParseProgram;
14727 end;
14728 
14729 procedure TTestResolver.TestArray_MultiDim_Const;
14730 begin
14731   StartProgram(false);
14732   Add([
14733   '{$modeswitch arrayoperators}',
14734   'type',
14735   '  TDynArray = array of longint;',
14736   '  TDynArray2 = array of TDynArray;',
14737   '  TArrOfArr = array[1..2] of TDynArray;',
14738   '  TMultiDimArr = array[1..2,3..4] of longint;',
14739   'const',
14740   '  AoA: TArrOfArr = ( (1,2), (2,3) );',
14741   '  MultiDimArr: TMultiDimArr = ( (11,12), (13,14) );',
14742   '  A2: TDynArray2 = ( (1,2), (2,3) );',
14743   'var',
14744   '  A: TDynArray;',
14745   'procedure DoIt(const a: TDynArray2); begin end;',
14746   'var i: longint;',
14747   'begin',
14748   '  AoA:= {#a1_array}[ {#a2_array}[1], {#a3_array}[i] ];',
14749   '  AoA:= {#b1_array}[ {#b2_array}[i], A ];',
14750   '  AoA:= {#c1_array}[ {#c2_array}[i,2], {#c3_array}[2,i] ];',
14751   '  MultiDimArr:= {#d1_array}[ {#d2_array}[11,12], [13,14] ];',
14752   '  A2:= {#e1_array}[ {#e2_array}[1,2], {#e3_array}[2,3], {#e4_array}[i] ];',
14753   '  DoIt( {#f1_array}[ {#f2_array}[i,32], {#f3_array}[32,i] ]);',
14754   '  A2:= A2+ {#g1_array}[A];',
14755   '  A2:= {#h1_array}[A]+A2;',
14756   '']);
14757   ParseProgram;
14758   CheckParamsExpr_pkSet_Markers;
14759 end;
14760 
14761 procedure TTestResolver.TestArray_AssignNilToStaticArrayFail1;
14762 begin
14763   StartProgram(false);
14764   Add('type');
14765   Add('  TEnum = (red,blue);');
14766   Add('var');
14767   Add('  a: array[TEnum] of longint;');
14768   Add('begin');
14769   Add('  a:=nil;');
14770   CheckResolverException('Incompatible types: got "nil" expected "static array[] of Longint"',
14771     nIncompatibleTypesGotExpected);
14772 end;
14773 
14774 procedure TTestResolver.TestArray_SetLengthProperty;
14775 begin
14776   ResolverEngine.Options:=ResolverEngine.Options+[proPropertyAsVarParam];
14777   StartProgram(false);
14778   Add('type');
14779   Add('  TArrInt = array of longint;');
14780   Add('  TObject = class');
14781   Add('    function GetColors: TArrInt; external name ''GetColors'';');
14782   Add('    procedure SetColors(const Value: TArrInt); external name ''SetColors'';');
14783   Add('    property Colors: TArrInt read GetColors write SetColors;');
14784   Add('  end;');
14785   Add('procedure DoIt(var i: longint; out j: longint; const k: longint); begin end;');
14786   Add('var Obj: TObject;');
14787   Add('begin');
14788   Add('  SetLength(Obj.Colors,2);');
14789   Add('  DoIt(Obj.Colors[1],Obj.Colors[2],Obj.Colors[3]);');
14790   ParseProgram;
14791 end;
14792 
14793 procedure TTestResolver.TestStaticArray_SetlengthFail;
14794 begin
14795   StartProgram(false);
14796   Add('type');
14797   Add('  TArrInt = array[1..3] of longint;');
14798   Add('var a: TArrInt;');
14799   Add('begin');
14800   Add('  SetLength(a,2);');
14801   CheckResolverException(sIncompatibleTypeArgNo,nIncompatibleTypeArgNo);
14802 end;
14803 
14804 procedure TTestResolver.TestArray_PassArrayElementToVarParam;
14805 begin
14806   StartProgram(false);
14807   Add('type');
14808   Add('  TArrInt = array of longint;');
14809   Add('procedure DoIt(var i: longint; out j: longint; const k: longint); begin end;');
14810   Add('var a: TArrInt;');
14811   Add('begin');
14812   Add('  DoIt(a[1],a[2],a[3]);');
14813   ParseProgram;
14814 end;
14815 
14816 procedure TTestResolver.TestArray_OpenArrayOfString;
14817 begin
14818   StartProgram(false);
14819   Add([
14820   'type TArrStr = array of string;',
14821   'procedure DoIt(const a: array of String);',
14822   'var',
14823   '  i: longint;',
14824   '  s: string;',
14825   'begin',
14826   '  for i:=low(a) to high(a) do s:=a[length(a)-i-1];',
14827   'end;',
14828   'const arr: array[0..1] of string = (''A'', ''B'');',
14829   'var s: string;',
14830   'begin',
14831   '  DoIt([]);',
14832   '  DoIt([s,''foo'','''',s+s]);',
14833   '  DoIt(arr);',
14834   '']);
14835   ParseProgram;
14836 end;
14837 
14838 procedure TTestResolver.TestArray_OpenArrayOfString_IntFail;
14839 begin
14840   StartProgram(false);
14841   Add('procedure DoIt(const a: array of String);');
14842   Add('begin');
14843   Add('end;');
14844   Add('begin');
14845   Add('  DoIt([1]);');
14846   CheckResolverException('Incompatible types: got "Longint" expected "String"',nIncompatibleTypesGotExpected);
14847 end;
14848 
14849 procedure TTestResolver.TestArray_OpenArrayOverride;
14850 begin
14851   StartProgram(false);
14852   Add('type');
14853   Add('  TObject = class');
14854   Add('  end;');
14855   Add('  Exception = class');
14856   Add('    constructor CreateFmt(const Msg: string; const Args: array of string); virtual;');
14857   Add('  end;');
14858   Add('  ESome = class(Exception)');
14859   Add('    constructor CreateFmt(const Msg: string; const Args: array of string); override;');
14860   Add('  end;');
14861   Add('constructor Exception.CreateFmt(const Msg: string; const Args: array of string);');
14862   Add('begin end;');
14863   Add('constructor ESome.CreateFmt(const Msg: string; const Args: array of string);');
14864   Add('begin');
14865   Add('  inherited CreateFmt(Msg,Args);');
14866   Add('end;');
14867   Add('begin');
14868   ParseProgram;
14869 end;
14870 
14871 procedure TTestResolver.TestArray_OpenArrayAsDynArraySetLengthFail;
14872 begin
14873   StartProgram(false);
14874   Add([
14875   'procedure DoIt(a: array of byte);',
14876   'begin',
14877   '  SetLength(a,3);',
14878   'end;',
14879   'begin']);
14880   CheckResolverException('Incompatible type arg no. 1: Got "open array of Byte", expected "string or dynamic array variable"',
14881     nIncompatibleTypeArgNo);
14882 end;
14883 
14884 procedure TTestResolver.TestArray_OpenArrayAsDynArray;
14885 begin
14886   ResolverEngine.Options:=ResolverEngine.Options+[proOpenAsDynArrays];
14887   StartProgram(false);
14888   Add([
14889   '{$modeswitch arrayoperators}',
14890   'type TArrStr = array of string;',
14891   'procedure DoStr(const a: TArrStr); forward;',
14892   'procedure DoIt(a: array of String);',
14893   'var',
14894   '  i: longint;',
14895   '  s: string;',
14896   'begin',
14897   '  SetLength(a,3);',
14898   '  DoStr(a);',
14899   '  DoStr(a+[s]);',
14900   '  DoStr([s]+a);',
14901   'end;',
14902   'procedure DoStr(const a: TArrStr);',
14903   'var s: string;',
14904   'begin',
14905   '  DoIt(a);',
14906   '  DoIt(a+[s]);',
14907   '  DoIt([s]+a);',
14908   'end;',
14909   'begin']);
14910   ParseProgram;
14911 end;
14912 
14913 procedure TTestResolver.TestArray_OpenArrayDelphi;
14914 begin
14915   StartProgram(false);
14916   Add([
14917   '{$mode delphi}',
14918   'type',
14919   '  TDynArrInt = array of byte;',
14920   '  TStaArrInt = array[1..2] of byte;',
14921   'procedure Fly(var a: array of byte);',
14922   'begin',
14923   '  Fly(a);',
14924   'end;',
14925   'procedure DoIt(a: array of byte);',
14926   'var',
14927   '  d: TDynArrInt;',
14928   '  s: TStaArrInt;',
14929   'begin',
14930   '  DoIt(a);',
14931   '  // d:=s; forbidden in delphi', // see TestArray_DynArrAssignStaticDelphiFail
14932   '  // d:=a; forbidden in delphi',
14933   '  DoIt(d);',
14934   '  DoIt(s);',
14935   '  Fly(a);',
14936   '  Fly(d);', // dyn array can be passed to a var open array
14937   'end;',
14938   'begin',
14939   '']);
14940   ParseProgram;
14941 end;
14942 
14943 procedure TTestResolver.TestArray_OpenArrayChar;
14944 begin
14945   StartProgram(false);
14946   Add([
14947   '{$mode delphi}',
14948   'Function CharInSet(Ch: Char;Const CSet : array of char) : Boolean;',
14949   'begin',
14950   'end;',
14951   'var Key: Char;',
14952   'begin',
14953   '  if CharInSet(Key, [^V, ^X, ^C]) then ;',
14954   '  CharInSet(Key,''abc'');',
14955   '  CharInSet(Key,Key);',
14956   '']);
14957   ParseProgram;
14958 end;
14959 
14960 procedure TTestResolver.TestArray_DynArrayChar;
14961 begin
14962   StartProgram(false);
14963   Add([
14964   '{$mode delphi}',
14965   'type TArrChr = array of char;',
14966   'var',
14967   '  Key: Char;',
14968   '  s: string;',
14969   '  a: TArrChr;',
14970   'begin',
14971   '  a:=''Foo'';',
14972   '  a:=Key;',
14973   '  a:=s;',
14974   '']);
14975   ParseProgram;
14976 end;
14977 
14978 procedure TTestResolver.TestArray_CopyConcat;
14979 begin
14980   StartProgram(false);
14981   Add([
14982   '{$modeswitch arrayoperators}',
14983   'type',
14984   '  integer = longint;',
14985   '  TArrayInt = array of integer;',
14986   '  TFlag = (red, blue);',
14987   '  TArrayFlag = array of TFlag;',
14988   'function Get(A: TArrayInt): TArrayInt; begin end;',
14989   'var',
14990   '  i: integer;',
14991   '  A: TArrayInt;',
14992   '  FA: TArrayFlag;',
14993   'begin',
14994   '  A:=Copy(A);',
14995   '  A:=Copy(A,1);',
14996   '  A:=Copy(A,2,3);',
14997   '  A:=Copy(Get(A),2,3);',
14998   '  Get(Copy(A));',
14999   '  A:=Concat(A);',
15000   '  A:=Concat(A,Get(A));',
15001   '  A:=Copy( {#a_array}[1]);',
15002   '  A:=Copy( {#b1_array}[1]+ {#b2_array}[2,3]);',
15003   '  A:=Concat( {#c_array}[1]);',
15004   '  A:=Concat( {#d1_array}[1], {#d2_array}[2,3]);',
15005   '  FA:=concat([red]);',
15006   '  FA:=concat([red],FA);',
15007   '']);
15008   ParseProgram;
15009   CheckParamsExpr_pkSet_Markers;
15010 end;
15011 
15012 procedure TTestResolver.TestStaticArray_CopyConcat;
15013 begin
15014   exit;
15015   //ResolverEngine.Options:=ResolverEngine.Options+[proStaticArrayCopy,proStaticArrayConcat];
15016   StartProgram(false);
15017   Add([
15018   'type',
15019   '  integer = longint;',
15020   '  TArrayInt = array of integer;',
15021   '  TThreeInts = array[1..3] of integer;',
15022   'function Get(A: TThreeInts): TThreeInts; begin end;',
15023   'var',
15024   '  i: integer;',
15025   '  A: TArrayInt;',
15026   '  S: TThreeInts;',
15027   'begin',
15028   '  A:=Copy(S);',
15029   '  A:=Copy(S,1);',
15030   '  A:=Copy(S,2,3);',
15031   '  A:=Copy(Get(S),2,3);',
15032   '  A:=Concat(S,Get(S));']);
15033   ParseProgram;
15034 end;
15035 
15036 procedure TTestResolver.TestArray_CopyMismatchFail;
15037 begin
15038   StartProgram(false);
15039   Add('type');
15040   Add('  integer = longint;');
15041   Add('  TArrayInt = array of integer;');
15042   Add('  TArrayStr = array of string;');
15043   Add('var');
15044   Add('  i: integer;');
15045   Add('  A: TArrayInt;');
15046   Add('  B: TArrayStr;');
15047   Add('begin');
15048   Add('  A:=Copy(B);');
15049   CheckResolverException('Incompatible types: got "array of integer" expected "array of String"',
15050     nIncompatibleTypesGotExpected);
15051 end;
15052 
15053 procedure TTestResolver.TestArray_InsertDeleteAccess;
15054 begin
15055   StartProgram(false);
15056   Add([
15057   '{$modeswitch arrayoperators}',
15058   'type',
15059   '  integer = longint;',
15060   '  TArrayInt = array of integer;',
15061   '  TArrArrInt = array of TArrayInt;',
15062   'var',
15063   '  i: integer;',
15064   '  A: TArrayInt;',
15065   '  A2: TArrArrInt;',
15066   'begin',
15067   '  Insert({#a1_read}i+1,{#a2_var}A,{#a3_read}i+2);',
15068   '  Insert([i],A2,i+2);',
15069   '  Insert(A+[1],A2,i+2);',
15070   '  Delete({#b1_var}A,{#b2_read}i+3,{#b3_read}i+4);']);
15071   ParseProgram;
15072   CheckAccessMarkers;
15073 end;
15074 
15075 procedure TTestResolver.TestArray_InsertArray;
15076 begin
15077   StartProgram(false);
15078   Add([
15079   '{$modeswitch arrayoperators}',
15080   'type',
15081   '  integer = longint;',
15082   '  TArrayInt = array of integer;',
15083   '  TArrArrInt = array of TArrayInt;',
15084   '  TCol = (red,blue);',
15085   '  TSetCol = set of TCol;',
15086   '  TArrayCol = array of TCol;',
15087   '  TArrArrCol = array of TArrayCol;',
15088   '  TArrSetCol = array of TSetCol;',
15089   'var',
15090   '  i: integer;',
15091   '  ArrInt: TArrayInt;',
15092   '  ArrArrInt: TArrArrInt;',
15093   '  ArrArrCol: TArrArrCol;',
15094   '  ArrSetCol: TArrSetCol;',
15095   'begin',
15096   '  Insert( {#a_array}[1], ArrArrInt, i+2);',
15097   '  Insert( {#b_array}[i], ArrArrInt, 3);',
15098   '  Insert( ArrInt+ {#c_array}[1], ArrArrInt, 4);',
15099   '  Insert( {#d_set}[red], ArrSetCol, 5);',
15100   '  Insert( {#e_array}[red], ArrArrCol, 6);',
15101   '']);
15102   ParseProgram;
15103   CheckParamsExpr_pkSet_Markers;
15104 end;
15105 
15106 procedure TTestResolver.TestStaticArray_InsertFail;
15107 begin
15108   StartProgram(false);
15109   Add('type');
15110   Add('  integer = longint;');
15111   Add('  TArrayInt = array[1..3] of integer;');
15112   Add('var');
15113   Add('  i: integer;');
15114   Add('  A: TArrayInt;');
15115   Add('begin');
15116   Add('  Insert(1,A,i);');
15117   CheckResolverException(sIncompatibleTypeArgNo,nIncompatibleTypeArgNo);
15118 end;
15119 
15120 procedure TTestResolver.TestStaticArray_DeleteFail;
15121 begin
15122   StartProgram(false);
15123   Add('type');
15124   Add('  integer = longint;');
15125   Add('  TArrayInt = array[1..3] of integer;');
15126   Add('var');
15127   Add('  i: integer;');
15128   Add('  A: TArrayInt;');
15129   Add('begin');
15130   Add('  Delete(A,i,1);');
15131   CheckResolverException(sIncompatibleTypeArgNo,nIncompatibleTypeArgNo);
15132 end;
15133 
15134 procedure TTestResolver.TestArray_InsertItemMismatchFail;
15135 begin
15136   StartProgram(false);
15137   Add('type');
15138   Add('  TCaption = string;');
15139   Add('  TArrayCap = array of TCaption;');
15140   Add('var');
15141   Add('  i: longint;');
15142   Add('  A: TArrayCap;');
15143   Add('begin');
15144   Add('  Insert(i,{#a2_var}A,2);');
15145   CheckResolverException('Incompatible types: got "Longint" expected "String"',
15146     nIncompatibleTypesGotExpected);
15147 end;
15148 
15149 procedure TTestResolver.TestArray_TypeCast;
15150 begin
15151   StartProgram(false);
15152   Add('type');
15153   Add('  integer = longint;');
15154   Add('  TArrIntA = array of integer;');
15155   Add('  TArrIntB = array of longint;');
15156   Add('  TArrIntC = array of integer;');
15157   Add('var');
15158   Add('  a: TArrIntA;');
15159   Add('  b: TArrIntB;');
15160   Add('  c: TArrIntC;');
15161   Add('begin');
15162   Add('  a:=TArrIntA(a);');
15163   Add('  a:=TArrIntA(b);');
15164   Add('  a:=TArrIntA(c);');
15165   ParseProgram;
15166 end;
15167 
15168 procedure TTestResolver.TestArray_TypeCastWrongElTypeFail;
15169 begin
15170   StartProgram(false);
15171   Add('type');
15172   Add('  integer = longint;');
15173   Add('  TArrInt = array of integer;');
15174   Add('  TArrStr = array of string;');
15175   Add('var');
15176   Add('  a: TArrInt;');
15177   Add('  s: TArrStr;');
15178   Add('begin');
15179   Add('  a:=TArrInt(s);');
15180   CheckResolverException('Illegal type conversion: "TArrStr" to "TArrInt"',
15181     nIllegalTypeConversionTo);
15182 end;
15183 
15184 procedure TTestResolver.TestArray_ConstDynArrayWrite;
15185 begin
15186   StartProgram(false);
15187   Add('type');
15188   Add('  TArrInt = array of longint;');
15189   Add('Procedure DoIt(const a: tarrint);');
15190   Add('begin');
15191   Add('  a[2]:=3;'); // FPC allows this for dynamic arrays
15192   Add('end;');
15193   Add('begin');
15194   ParseProgram;
15195   CheckResolverUnexpectedHints;
15196 end;
15197 
15198 procedure TTestResolver.TestArray_ConstOpenArrayWriteFail;
15199 begin
15200   StartProgram(false);
15201   Add('Procedure DoIt(const a: array of longint);');
15202   Add('begin');
15203   Add('  a[2]:=3;');
15204   Add('end;');
15205   Add('begin');
15206   CheckResolverException('Variable identifier expected',nVariableIdentifierExpected);
15207 end;
15208 
15209 procedure TTestResolver.TestArray_ForIn;
15210 begin
15211   StartProgram(false);
15212   Add([
15213   '{$modeswitch arrayoperators}',
15214   'var',
15215   '  a: array of longint;',
15216   '  s: array[1,2] of longint;',
15217   '  i: longint;',
15218   'begin',
15219   '  for i in a do ;',
15220   '  for i in s do ;',
15221   '  for i in a+ {#a_array}[1] do ;',
15222   '  for i in {#b1_set}[1]+ {#b2_set}[2] do ;',
15223   '  for i in {#c_set}[1,2] do ;',
15224   '']);
15225   ParseProgram;
15226   CheckParamsExpr_pkSet_Markers;
15227 end;
15228 
15229 procedure TTestResolver.TestArray_Arg_AnonymousStaticFail;
15230 begin
15231   StartProgram(false);
15232   Add([
15233   'procedure DoIt(args: array[1..2] of word);',
15234   'begin',
15235   'end;',
15236   'begin']);
15237   CheckParserException('Expected "of"',nParserExpectTokenError);
15238 end;
15239 
15240 procedure TTestResolver.TestArray_Arg_AnonymousMultiDimFail;
15241 begin
15242   StartProgram(false);
15243   Add([
15244   'procedure DoIt(args: array of array of word);',
15245   'begin',
15246   'end;',
15247   'begin']);
15248   CheckParserException(SParserExpectedIdentifier,nParserExpectedIdentifier);
15249 end;
15250 
15251 procedure TTestResolver.TestArrayOfConst;
15252 begin
15253   StartProgram(true,[supTVarRec]);
15254   Add([
15255   'type',
15256   '  TArrOfVarRec = array of TVarRec;',
15257   'procedure DoIt(args: array of const);',
15258   'var',
15259   '  i: longint;',
15260   '  v: TVarRec;',
15261   '  a: TArrOfVarRec;',
15262   '  sa: array[1..2] of TVarRec;',
15263   'begin',
15264   '  DoIt(args);',
15265   '  DoIt(a);',
15266   '  DoIt([]);',
15267   '  DoIt([1]);',
15268   '  DoIt([i]);',
15269   '  DoIt([true,''foo'',''c'',1.3,nil,@DoIt]);',
15270   '  for i:=low(args) to high(args) do begin',
15271   '    v:=args[i];',
15272   '    case args[i].VType of',
15273   '    vtInteger: if length(args)=args[i].VInteger then ;',
15274   '    end;',
15275   '  end;',
15276   '  for v in Args do ;',
15277   '  args:=sa;',
15278   'end;',
15279   'begin']);
15280   ParseProgram;
15281 end;
15282 
15283 procedure TTestResolver.TestArrayOfConst_PassDynArrayOfIntFail;
15284 begin
15285   StartProgram(true,[supTVarRec]);
15286   Add([
15287   'type',
15288   '  TArr = array of word;',
15289   'procedure DoIt(args: array of const);',
15290   'begin',
15291   'end;',
15292   'var a: TArr;',
15293   'begin',
15294   '  DoIt(a)']);
15295   CheckResolverException('Incompatible type arg no. 1: Got "TArr", expected "array of const"',
15296     nIncompatibleTypeArgNo);
15297 end;
15298 
15299 procedure TTestResolver.TestArrayOfConst_AssignNilFail;
15300 begin
15301   StartProgram(true,[supTVarRec]);
15302   Add([
15303   'type',
15304   '  TArr = array of word;',
15305   'procedure DoIt(args: array of const);',
15306   'begin',
15307   '  args:=nil;',
15308   'end;',
15309   'begin']);
15310   CheckResolverException('Incompatible types: got "nil" expected "array of const"',nIncompatibleTypesGotExpected);
15311 end;
15312 
15313 procedure TTestResolver.TestArrayOfConst_SetLengthFail;
15314 begin
15315   StartProgram(true,[supTVarRec]);
15316   Add([
15317   'type',
15318   '  TArr = array of word;',
15319   'procedure DoIt(args: array of const);',
15320   'begin',
15321   '  SetLength(args,2);',
15322   'end;',
15323   'begin']);
15324   CheckResolverException('Incompatible type arg no. 1: Got "array of const", expected "string or dynamic array variable"',
15325     nIncompatibleTypeArgNo);
15326 end;
15327 
15328 procedure TTestResolver.TestArrayIntRange_OutOfRange;
15329 begin
15330   StartProgram(false);
15331   Add([
15332   'type TArr = array[1..2] of longint;',
15333   'var a: TArr;',
15334   'begin',
15335   '  a[0]:=3;',
15336   '']);
15337   ParseProgram;
15338   CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
15339     'range check error while evaluating constants (0 is not between 1 and 2)');
15340   CheckResolverUnexpectedHints;
15341 end;
15342 
15343 procedure TTestResolver.TestArrayIntRange_OutOfRangeError;
15344 begin
15345   StartProgram(false);
15346   Add([
15347   '{$R+}',
15348   'type TArr = array[1..2] of longint;',
15349   'var a: TArr;',
15350   'begin',
15351   '  a[0]:=3;',
15352   '']);
15353   CheckResolverException('range check error while evaluating constants (0 is not between 1 and 2)',
15354     nRangeCheckEvaluatingConstantsVMinMax);
15355 end;
15356 
15357 procedure TTestResolver.TestArrayCharRange_OutOfRange;
15358 begin
15359   StartProgram(false);
15360   Add([
15361   'type TArr = array[''a''..''b''] of longint;',
15362   'var a: TArr;',
15363   'begin',
15364   '  a[''0'']:=3;',
15365   '']);
15366   ParseProgram;
15367   CheckResolverHint(mtWarning,nRangeCheckEvaluatingConstantsVMinMax,
15368     'range check error while evaluating constants (''0'' is not between ''a'' and ''b'')');
15369   CheckResolverUnexpectedHints;
15370 end;
15371 
15372 procedure TTestResolver.TestProcTypesAssignObjFPC;
15373 begin
15374   StartProgram(false);
15375   Add('type');
15376   Add('  TProcedure = procedure;');
15377   Add('  TFunctionInt = function:longint;');
15378   Add('  TFunctionIntFunc = function:TFunctionInt;');
15379   Add('  TFunctionIntFuncFunc = function:TFunctionIntFunc;');
15380   Add('function GetNumber: longint;');
15381   Add('begin');
15382   Add('  Result:=3;');
15383   Add('end;');
15384   Add('function GetNumberFunc: TFunctionInt;');
15385   Add('begin');
15386   Add('  Result:=@GetNumber;');
15387   Add('end;');
15388   Add('function GetNumberFuncFunc: TFunctionIntFunc;');
15389   Add('begin');
15390   Add('  Result:=@GetNumberFunc;');
15391   Add('end;');
15392   Add('var');
15393   Add('  i: longint;');
15394   Add('  f: TFunctionInt;');
15395   Add('  ff: TFunctionIntFunc;');
15396   Add('begin');
15397   Add('  i:=GetNumber; // omit ()');
15398   Add('  i:=GetNumber();');
15399   Add('  i:=GetNumberFunc()();');
15400   Add('  i:=GetNumberFuncFunc()()();');
15401   Add('  if i=GetNumberFunc()() then ;');
15402   Add('  if GetNumberFunc()()=i then ;');
15403   Add('  if i=GetNumberFuncFunc()()() then ;');
15404   Add('  if GetNumberFuncFunc()()()=i then ;');
15405   Add('  f:=nil;');
15406   Add('  if f=nil then ;');
15407   Add('  if nil=f then ;');
15408   Add('  if Assigned(f) then ;');
15409   Add('  f:=f;');
15410   Add('  f:=@GetNumber;');
15411   Add('  f:=GetNumberFunc; // not in Delphi');
15412   Add('  f:=GetNumberFunc(); // not in Delphi');
15413   Add('  f:=GetNumberFuncFunc()();');
15414   Add('  if f=f then ;');
15415   Add('  if i=f then ;');
15416   Add('  if i=f() then ;');
15417   Add('  if f()=i then ;');
15418   Add('  if f()=f() then ;');
15419   Add('  if f=@GetNumber then ;');
15420   Add('  if @GetNumber=f then ;');
15421   Add('  if f=GetNumberFunc then ;');
15422   Add('  if f=GetNumberFunc() then ;');
15423   Add('  if f=GetNumberFuncFunc()() then ;');
15424   Add('  ff:=nil;');
15425   Add('  if ff=nil then ;');
15426   Add('  if nil=ff then ;');
15427   Add('  ff:=ff;');
15428   Add('  if ff=ff then ;');
15429   Add('  ff:=@GetNumberFunc;');
15430   Add('  ff:=GetNumberFuncFunc; // not in Delphi');
15431   Add('  ff:=GetNumberFuncFunc();');
15432   ParseProgram;
15433 end;
15434 
15435 procedure TTestResolver.TestMethodTypesAssignObjFPC;
15436 begin
15437   StartProgram(false);
15438   Add('type');
15439   Add('  TObject = class;');
15440   Add('  TNotifyEvent = procedure(Sender: TObject) of object;');
15441   Add('  TObject = class');
15442   Add('    FOnClick: TNotifyEvent;');
15443   Add('    procedure SetOnClick(const Value: TNotifyEvent);');
15444   Add('    procedure Notify(Sender: TObject);');
15445   Add('    property OnClick: TNotifyEvent read FOnClick write SetOnClick;');
15446   Add('  end;');
15447   Add('procedure TObject.SetOnClick(const Value: TNotifyEvent);');
15448   Add('begin');
15449   Add('  if FOnClick=Value then exit;');
15450   Add('  FOnClick:=Value;');
15451   Add('end;');
15452   Add('procedure TObject.Notify(Sender: TObject);');
15453   Add('begin');
15454   Add('  if Assigned(OnClick) and (OnClick<>@Notify) then begin');
15455   Add('    OnClick(Sender);');
15456   Add('    OnClick(Self);');
15457   Add('    Self.OnClick(nil);');
15458   Add('  end;');
15459   Add('  if OnClick=@Self.Notify then ;');
15460   Add('  if Self.OnClick=@Self.Notify then ;');
15461   Add('end;');
15462   Add('var o: TObject;');
15463   Add('begin');
15464   Add('  o.OnClick:=@o.Notify;');
15465   Add('  o.OnClick(nil);');
15466   Add('  o.OnClick(o);');
15467   Add('  o.SetOnClick(@o.Notify);');
15468   ParseProgram;
15469 end;
15470 
15471 procedure TTestResolver.TestProcTypeCall;
15472 var
15473   aMarker: PSrcMarker;
15474   Elements: TFPList;
15475   ActualImplicitCallWithoutParams: Boolean;
15476   i: Integer;
15477   El: TPasElement;
15478   Ref: TResolvedReference;
15479 begin
15480   StartProgram(false);
15481   Add('type');
15482   Add('  TFuncInt = function(vI: longint = 1):longint;');
15483   Add('  TFuncFuncInt = function(vI: longint = 1): TFuncInt;');
15484   Add('procedure DoI(vI: longint); begin end;');
15485   Add('procedure DoFConst(const vI: tfuncint); begin end;');
15486   Add('procedure DoFVar(var vI: tfuncint); begin end;');
15487   Add('procedure DoFDefault(vI: tfuncint); begin end;');
15488   Add('var');
15489   Add('  i: longint;');
15490   Add('  f: tfuncint;');
15491   Add('begin');
15492   Add('  {#a}f;');
15493   Add('  {#b}f();');
15494   Add('  {#c}f(2);');
15495   Add('  i:={#d}f;');
15496   Add('  i:={#e}f();');
15497   Add('  i:={#f}f(2);');
15498   Add('  doi({#g}f);');
15499   Add('  doi({#h}f());');
15500   Add('  doi({#i}f(2));');
15501   Add('  dofconst({#j}f);');
15502   Add('  if Assigned({#k}f) then;');
15503   Add('  if {#l}f=nil then;');
15504   Add('  if nil={#m}f then;');
15505   ParseProgram;
15506 
15507   aMarker:=FirstSrcMarker;
15508   while aMarker<>nil do
15509     begin
15510     //writeln('TTestResolver.TestProcTypeCall ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
15511     Elements:=FindElementsAt(aMarker);
15512     try
15513       ActualImplicitCallWithoutParams:=false;
15514       for i:=0 to Elements.Count-1 do
15515         begin
15516         El:=TPasElement(Elements[i]);
15517         //writeln('TTestResolver.TestProcTypeCall ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
15518         if not (El.CustomData is TResolvedReference) then continue;
15519         Ref:=TResolvedReference(El.CustomData);
15520         //writeln('TTestResolver.TestProcTypeCall ',GetObjName(Ref.Declaration),' rrfImplicitCallWithoutParams=',rrfImplicitCallWithoutParams in Ref.Flags);
15521         if rrfImplicitCallWithoutParams in Ref.Flags then
15522           ActualImplicitCallWithoutParams:=true;
15523         break;
15524         end;
15525       case aMarker^.Identifier of
15526       'a','d','g':
15527         if not ActualImplicitCallWithoutParams then
15528           RaiseErrorAtSrcMarker('expected implicit call at "#'+aMarker^.Identifier+'"',aMarker);
15529       else
15530         if ActualImplicitCallWithoutParams then
15531           RaiseErrorAtSrcMarker('expected no implicit call at "#'+aMarker^.Identifier+'"',aMarker);
15532       end;
15533     finally
15534       Elements.Free;
15535     end;
15536     aMarker:=aMarker^.Next;
15537     end;
15538 end;
15539 
15540 procedure TTestResolver.TestProcType_FunctionFPC;
15541 begin
15542   StartProgram(false);
15543   Add('type');
15544   Add('  TFuncInt = function(vA: longint = 1): longint;');
15545   Add('function DoIt(vI: longint): longint;');
15546   Add('begin end;');
15547   Add('var');
15548   Add('  b: boolean;');
15549   Add('  vP, vQ: tfuncint;');
15550   Add('begin');
15551   Add('  vp:=nil;');
15552   Add('  vp:=vp;');
15553   Add('  vp:=@doit;'); // ok in fpc and delphi
15554   //Add('  vp:=doit;'); // illegal in fpc, ok in delphi
15555   Add('  vp;'); // ok in fpc and delphi
15556   Add('  vp();');
15557   Add('  vp(2);');
15558   Add('  b:=vp=nil;'); // ok in fpc, illegal in delphi
15559   Add('  b:=nil=vp;'); // ok in fpc, illegal in delphi
15560   Add('  b:=vp=vq;'); // in fpc compare proctypes, in delphi compare results
15561   Add('  b:=vp=@doit;'); // ok in fpc, illegal in delphi
15562   Add('  b:=@doit=vp;'); // ok in fpc, illegal in delphi
15563   //Add('  b:=vp=3;'); // illegal in fpc, ok in delphi
15564   Add('  b:=4=vp;'); // illegal in fpc, ok in delphi
15565   Add('  b:=vp<>nil;'); // ok in fpc, illegal in delphi
15566   Add('  b:=nil<>vp;'); // ok in fpc, illegal in delphi
15567   Add('  b:=vp<>vq;'); // in fpc compare proctypes, in delphi compare results
15568   Add('  b:=vp<>@doit;'); // ok in fpc, illegal in delphi
15569   Add('  b:=@doit<>vp;'); // ok in fpc, illegal in delphi
15570   //Add('  b:=vp<>5;'); // illegal in fpc, ok in delphi
15571   Add('  b:=6<>vp;'); // illegal in fpc, ok in delphi
15572   Add('  b:=Assigned(vp);');
15573   //Add('  doit(vp);'); // illegal in fpc, ok in delphi
15574   Add('  doit(vp());'); // ok in fpc and delphi
15575   Add('  doit(vp(2));'); // ok in fpc and delphi
15576   ParseProgram;
15577 end;
15578 
15579 procedure TTestResolver.TestProcType_FunctionDelphi;
15580 begin
15581   StartProgram(false);
15582   Add('{$mode Delphi}');
15583   Add('type');
15584   Add('  TFuncInt = function(vA: longint = 1): longint;');
15585   Add('function DoIt(vI: longint): longint;');
15586   Add('begin end;');
15587   Add('var');
15588   Add('  b: boolean;');
15589   Add('  vP, vQ: tfuncint;');
15590   Add('  ');
15591   Add('begin');
15592   Add('  vp:=nil;');
15593   Add('  vp:=vp;');
15594   Add('  vp:=@doit;'); // ok in fpc and delphi
15595   Add('  vp:=doit;'); // illegal in fpc, ok in delphi
15596   Add('  vp;'); // ok in fpc and delphi
15597   Add('  vp();');
15598   Add('  vp(2);');
15599   //Add('  b:=vp=nil;'); // ok in fpc, illegal in delphi
15600   //Add('  b:=nil=vp;'); // ok in fpc, illegal in delphi
15601   Add('  b:=vp=vq;'); // in fpc compare proctypes, in delphi compare results
15602   //Add('  b:=vp=@doit;'); // ok in fpc, illegal in delphi
15603   //Add('  b:=@doit=vp;'); // ok in fpc, illegal in delphi
15604   Add('  b:=vp=3;'); // illegal in fpc, ok in delphi
15605   Add('  b:=4=vp;'); // illegal in fpc, ok in delphi
15606   //Add('  b:=vp<>nil;'); // ok in fpc, illegal in delphi
15607   //Add('  b:=nil<>vp;'); // ok in fpc, illegal in delphi
15608   Add('  b:=vp<>vq;'); // in fpc compare proctypes, in delphi compare results
15609   //Add('  b:=vp<>@doit;'); // ok in fpc, illegal in delphi
15610   //Add('  b:=@doit<>vp;'); // ok in fpc, illegal in delphi
15611   Add('  b:=vp<>5;'); // illegal in fpc, ok in delphi
15612   Add('  b:=6<>vp;'); // illegal in fpc, ok in delphi
15613   Add('  b:=Assigned(vp);');
15614   Add('  doit(vp);'); // illegal in fpc, ok in delphi
15615   Add('  doit(vp());'); // ok in fpc and delphi
15616   Add('  doit(vp(2));'); // ok in fpc and delphi  *)
15617   ParseProgram;
15618 end;
15619 
15620 procedure TTestResolver.TestProcType_ProcedureDelphi;
15621 begin
15622   StartProgram(false);
15623   Add('{$mode Delphi}');
15624   Add('type');
15625   Add('  TProc = procedure;');
15626   Add('procedure Doit;');
15627   Add('begin end;');
15628   Add('var');
15629   Add('  b: boolean;');
15630   Add('  vP, vQ: tproc;');
15631   Add('begin');
15632   Add('  vp:=nil;');
15633   Add('  vp:=vp;');
15634   Add('  vp:=vq;');
15635   Add('  vp:=@doit;'); // ok in fpc and delphi, Note that in Delphi type of @F is Pointer, while in FPC it is the proc type
15636   Add('  vp:=doit;'); // illegal in fpc, ok in delphi
15637   //Add('  vp:=@doit;'); // illegal in fpc, ok in delphi (because Delphi treats @F as Pointer), not supported by resolver
15638   Add('  vp;'); // ok in fpc and delphi
15639   Add('  vp();');
15640 
15641   // equal
15642   //Add('  b:=vp=nil;'); // ok in fpc, illegal in delphi
15643   Add('  b:=@@vp=nil;'); // ok in fpc delphi mode, ok in delphi
15644   //Add('  b:=nil=vp;'); // ok in fpc, illegal in delphi
15645   Add('  b:=nil=@@vp;'); // ok in fpc delphi mode, ok in delphi
15646   Add('  b:=@@vp=@@vq;'); // ok in fpc delphi mode, ok in Delphi
15647   //Add('  b:=vp=vq;'); // in fpc compare proctypes, in delphi compare results
15648   //Add('  b:=vp=@doit;'); // ok in fpc, illegal in delphi
15649   Add('  b:=@@vp=@doit;'); // ok in fpc delphi mode, ok in delphi
15650   //Add('  b:=@doit=vp;'); // ok in fpc, illegal in delphi
15651   Add('  b:=@doit=@@vp;'); // ok in fpc delphi mode, ok in delphi
15652 
15653   // unequal
15654   //Add('  b:=vp<>nil;'); // ok in fpc, illegal in delphi
15655   Add('  b:=@@vp<>nil;'); // ok in fpc mode delphi, ok in delphi
15656   //Add('  b:=nil<>vp;'); // ok in fpc, illegal in delphi
15657   Add('  b:=nil<>@@vp;'); // ok in fpc mode delphi, ok in delphi
15658   //Add('  b:=vp<>vq;'); // in fpc compare proctypes, in delphi compare results
15659   Add('  b:=@@vp<>@@vq;'); // ok in fpc mode delphi, ok in delphi
15660   //Add('  b:=vp<>@doit;'); // ok in fpc, illegal in delphi
15661   Add('  b:=@@vp<>@doit;'); // ok in fpc mode delphi, illegal in delphi
15662   //Add('  b:=@doit<>vp;'); // ok in fpc, illegal in delphi
15663   Add('  b:=@doit<>@@vp;'); // ok in fpc mode delphi, illegal in delphi
15664 
15665   Add('  b:=Assigned(vp);');
15666   ParseProgram;
15667 end;
15668 
15669 procedure TTestResolver.TestProcType_MethodFPC;
15670 begin
15671   StartProgram(false);
15672   Add('type');
15673   Add('  TFuncInt = function(vA: longint = 1): longint of object;');
15674   Add('  TObject = class');
15675   Add('    function DoIt(vA: longint = 1): longint;');
15676   Add('  end;');
15677   Add('function tobject.doit(vA: longint): longint;');
15678   Add('begin');
15679   Add('end;');
15680   Add('var');
15681   Add('  Obj: TObject;');
15682   Add('  vP: tfuncint;');
15683   Add('  b: boolean;');
15684   Add('begin');
15685   Add('  vp:=@obj.doit;'); // ok in fpc and delphi
15686   //Add('  vp:=obj.doit;'); // illegal in fpc, ok in delphi
15687   Add('  vp;'); // ok in fpc and delphi
15688   Add('  vp();');
15689   Add('  vp(2);');
15690   Add('  b:=vp=@obj.doit;'); // ok in fpc, illegal in delphi
15691   Add('  b:=@obj.doit=vp;'); // ok in fpc, illegal in delphi
15692   Add('  b:=vp<>@obj.doit;'); // ok in fpc, illegal in delphi
15693   Add('  b:=@obj.doit<>vp;'); // ok in fpc, illegal in delphi
15694   ParseProgram;
15695 end;
15696 
15697 procedure TTestResolver.TestProcType_MethodDelphi;
15698 begin
15699   StartProgram(false);
15700   Add('{$mode delphi}');
15701   Add('type');
15702   Add('  TFuncInt = function(vA: longint = 1): longint of object;');
15703   Add('  TObject = class');
15704   Add('    function DoIt(vA: longint = 1): longint;');
15705   Add('  end;');
15706   Add('function tobject.doit(vA: longint): longint;');
15707   Add('begin');
15708   Add('end;');
15709   Add('var');
15710   Add('  Obj: TObject;');
15711   Add('  vP: tfuncint;');
15712   Add('  b: boolean;');
15713   Add('begin');
15714   Add('  vp:=@obj.doit;'); // ok in fpc and delphi
15715   Add('  vp:=obj.doit;'); // illegal in fpc, ok in delphi
15716   Add('  vp;'); // ok in fpc and delphi
15717   Add('  vp();');
15718   Add('  vp(2);');
15719   //Add('  b:=vp=@obj.doit;'); // ok in fpc, illegal in delphi
15720   //Add('  b:=@obj.doit=vp;'); // ok in fpc, illegal in delphi
15721   //Add('  b:=vp<>@obj.doit;'); // ok in fpc, illegal in delphi
15722   //Add('  b:=@obj.doit<>vp;'); // ok in fpc, illegal in delphi
15723   ParseProgram;
15724 end;
15725 
15726 procedure TTestResolver.TestAssignProcToMethodFail;
15727 begin
15728   StartProgram(false);
15729   Add('type');
15730   Add('  TObject = class end;');
15731   Add('  TNotifyEvent = procedure(Sender: TObject) of object;');
15732   Add('procedure ProcA(Sender: TObject);');
15733   Add('begin end;');
15734   Add('var n: TNotifyEvent;');
15735   Add('begin');
15736   Add('  n:=@ProcA;');
15737   CheckResolverException('procedural type modifier "of Object" mismatch',
15738     nXModifierMismatchY);
15739 end;
15740 
15741 procedure TTestResolver.TestAssignMethodToProcFail;
15742 begin
15743   StartProgram(false);
15744   Add('type');
15745   Add('  TObject = class');
15746   Add('    procedure ProcA(Sender: TObject);');
15747   Add('  end;');
15748   Add('  TNotifyProc = procedure(Sender: TObject);');
15749   Add('procedure TObject.ProcA(Sender: TObject);');
15750   Add('begin end;');
15751   Add('var');
15752   Add('  n: TNotifyProc;');
15753   Add('  o: TObject;');
15754   Add('begin');
15755   Add('  n:=@o.ProcA;');
15756   CheckResolverException('procedural type modifier "of Object" mismatch',
15757     nXModifierMismatchY);
15758 end;
15759 
15760 procedure TTestResolver.TestAssignProcToFunctionFail;
15761 begin
15762   StartProgram(false);
15763   Add('type');
15764   Add('  TFuncInt = function(i: longint): longint;');
15765   Add('procedure ProcA(i: longint);');
15766   Add('begin end;');
15767   Add('var p: TFuncInt;');
15768   Add('begin');
15769   Add('  p:=@ProcA;');
15770   CheckResolverException(
15771     'Incompatible types: got "procedural type" expected "functional type"',
15772     nIncompatibleTypesGotExpected);
15773 end;
15774 
15775 procedure TTestResolver.TestAssignProcWrongArgsFail;
15776 begin
15777   StartProgram(false);
15778   Add('type');
15779   Add('  TProcInt = procedure(i: longint);');
15780   Add('procedure ProcA(i: string);');
15781   Add('begin end;');
15782   Add('var p: TProcInt;');
15783   Add('begin');
15784   Add('  p:=@ProcA;');
15785   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "String"',
15786     nIncompatibleTypeArgNo);
15787 end;
15788 
15789 procedure TTestResolver.TestAssignProcWrongArgAccessFail;
15790 begin
15791   StartProgram(false);
15792   Add('type');
15793   Add('  TProcInt = procedure(i: longint);');
15794   Add('procedure ProcA(const i: longint);');
15795   Add('begin end;');
15796   Add('var p: TProcInt;');
15797   Add('begin');
15798   Add('  p:=@ProcA;');
15799   CheckResolverException('Incompatible type arg no. 1: Got "access modifier const", expected "default"',
15800     nIncompatibleTypeArgNo);
15801 end;
15802 
15803 procedure TTestResolver.TestProcType_SameSignatureObjFPC;
15804 begin
15805   StartProgram(false);
15806   Add([
15807   '{$mode objfpc}',
15808   'type',
15809   '  TRun = procedure(a: Word);',
15810   '  TRunIt = procedure(a: TRun);',
15811   '  TFly = procedure(a: Word);',
15812   'procedure FlyIt(a: TFly);',
15813   'begin',
15814   'end;',
15815   'var RunIt: TRunIt;',
15816   'begin',
15817   '  RunIt:=@FlyIt;',
15818   '']);
15819   ParseProgram;
15820 end;
15821 
15822 procedure TTestResolver.TestProcType_AssignNestedProcFail;
15823 begin
15824   StartProgram(false);
15825   Add('type');
15826   Add('  TProcInt = procedure(i: longint);');
15827   Add('procedure ProcA;');
15828   Add('var p: TProcInt;');
15829   Add('  procedure SubProc(i: longint);');
15830   Add('  begin');
15831   Add('  end;');
15832   Add('begin');
15833   Add('  p:=@SubProc;');
15834   Add('end;');
15835   Add('begin');
15836   CheckResolverException('procedural type modifier "is nested" mismatch',
15837     nXModifierMismatchY);
15838 end;
15839 
15840 procedure TTestResolver.TestArrayOfProc;
15841 begin
15842   StartProgram(false);
15843   Add([
15844   'type',
15845   '  TObject = class end;',
15846   '  TNotifyProc = function(Sender: TObject = nil): longint;',
15847   '  TProcArray = array of TNotifyProc;',
15848   'function ProcA(Sender: TObject): longint;',
15849   'begin end;',
15850   'procedure DoIt(const a: TProcArray);',
15851   'begin end;',
15852   'var',
15853   '  a: TProcArray;',
15854   '  p: TNotifyProc;',
15855   'begin',
15856   '  a[0]:=@ProcA;',
15857   '  if a[1]=@ProcA then ;',
15858   '  if @ProcA=a[2] then ;',
15859   // '  a[3];', ToDo
15860   '  a[3](nil);',
15861   '  if a[4](nil)=5 then ;',
15862   '  if 6=a[7](nil) then ;',
15863   '  a[8]:=a[9];',
15864   '  p:=a[10];',
15865   '  a[11]:=p;',
15866   '  if a[12]=p then ;',
15867   '  if p=a[13] then ;',
15868   '  DoIt([@ProcA]);',
15869   '  DoIt([nil]);',
15870   '  DoIt([nil,@ProcA]);',
15871   '  DoIt([p]);',
15872   '']);
15873   ParseProgram;
15874 end;
15875 
15876 procedure TTestResolver.TestProcType_Assigned;
15877 begin
15878   StartProgram(false);
15879   Add('type');
15880   Add('  TFuncInt = function(i: longint): longint;');
15881   Add('function ProcA(i: longint): longint;');
15882   Add('begin end;');
15883   Add('var');
15884   Add('  a: array of TFuncInt;');
15885   Add('  p: TFuncInt;');
15886   Add('begin');
15887   Add('  if Assigned(p) then ;');
15888   Add('  if Assigned(a[1]) then ;');
15889   ParseProgram;
15890 end;
15891 
15892 procedure TTestResolver.TestProcType_TNotifyEvent;
15893 begin
15894   StartProgram(true,[supTObject]);
15895   Add('type');
15896   Add('  TNotifyEvent = procedure(Sender: TObject) of object;');
15897   Add('  TButton = class(TObject)');
15898   Add('  private');
15899   Add('    FOnClick: TNotifyEvent;');
15900   Add('  published');
15901   Add('    property OnClick: TNotifyEvent read FOnClick write FOnClick;');
15902   Add('  end;');
15903   Add('  TApplication = class(TObject)');
15904   Add('    procedure BtnClickHandler(Sender: TObject); external name ''BtnClickHandler'';');
15905   Add('  end;');
15906   Add('var ');
15907   Add('  App: TApplication;');
15908   Add('  Button1: TButton;');
15909   Add('begin');
15910   Add('  Button1.OnClick := @App.BtnClickHandler;');
15911   ParseProgram;
15912 end;
15913 
15914 procedure TTestResolver.TestProcType_TNotifyEvent_NoAtFPC_Fail1;
15915 begin
15916   StartProgram(true,[supTObject]);
15917   Add('type');
15918   Add('  TNotifyEvent = procedure(Sender: TObject) of object;');
15919   Add('  TButton = class(TObject)');
15920   Add('  private');
15921   Add('    FOnClick: TNotifyEvent;');
15922   Add('  published');
15923   Add('    property OnClick: TNotifyEvent read FOnClick write FOnClick;');
15924   Add('  end;');
15925   Add('  TApplication = class(TObject)');
15926   Add('    procedure BtnClickHandler(Sender: TObject); external name ''BtnClickHandler'';');
15927   Add('  end;');
15928   Add('var ');
15929   Add('  App: TApplication;');
15930   Add('  Button1: TButton;');
15931   Add('begin');
15932   Add('  Button1.OnClick := App.BtnClickHandler;');
15933   CheckResolverException(
15934     'Wrong number of parameters specified for call to "BtnClickHandler"',
15935     nWrongNumberOfParametersForCallTo);
15936 end;
15937 
15938 procedure TTestResolver.TestProcType_TNotifyEvent_NoAtFPC_Fail2;
15939 begin
15940   StartProgram(true,[supTObject]);
15941   Add('type');
15942   Add('  TNotifyEvent = procedure(Sender: TObject) of object;');
15943   Add('  TButton = class(TObject)');
15944   Add('  private');
15945   Add('    FOnClick: TNotifyEvent;');
15946   Add('  published');
15947   Add('    property OnClick: TNotifyEvent read FOnClick write FOnClick;');
15948   Add('  end;');
15949   Add('  TApplication = class(TObject)');
15950   Add('    procedure BtnClickHandler(Sender: TObject); external name ''BtnClickHandler'';');
15951   Add('  end;');
15952   Add('var ');
15953   Add('  App: TApplication;');
15954   Add('  Button1: TButton;');
15955   Add('begin');
15956   Add('  Button1.OnClick := App.BtnClickHandler();');
15957   CheckResolverException(
15958     'Wrong number of parameters specified for call to "procedure BtnClickHandler(TObject) of Object"',
15959     nWrongNumberOfParametersForCallTo);
15960 end;
15961 
15962 procedure TTestResolver.TestProcType_TNotifyEvent_NoAtFPC_Fail3;
15963 begin
15964   StartProgram(true,[supTObject]);
15965   Add('type');
15966   Add('  TNotifyEvent = procedure(Sender: TObject) of object;');
15967   Add('  TButton = class(TObject)');
15968   Add('  private');
15969   Add('    FOnClick: TNotifyEvent;');
15970   Add('  published');
15971   Add('    property OnClick: TNotifyEvent read FOnClick write FOnClick;');
15972   Add('  end;');
15973   Add('  TApplication = class(TObject)');
15974   Add('    procedure BtnClickHandler(Sender: TObject); external name ''BtnClickHandler'';');
15975   Add('  end;');
15976   Add('var ');
15977   Add('  App: TApplication;');
15978   Add('  Button1: TButton;');
15979   Add('begin');
15980   Add('  Button1.OnClick := @App.BtnClickHandler();');
15981   CheckResolverException(
15982     'Wrong number of parameters specified for call to "procedure BtnClickHandler(TObject) of Object"',
15983     nWrongNumberOfParametersForCallTo);
15984 end;
15985 
15986 procedure TTestResolver.TestProcType_WhileListCompare;
15987 begin
15988   StartProgram(false);
15989   Add('type');
15990   Add('  integer = longint;');
15991   Add('  TArrInt = array of Integer;');
15992   Add('  TListCompare = function(Item1, Item2: Integer): integer;');
15993   Add('procedure Sort(P: Integer; const List: TArrInt; const Compare: TListCompare);');
15994   Add('begin');
15995   Add('  while Compare(P,List[0])>0 do ;');
15996   Add('end;');
15997   Add('begin');
15998   ParseProgram;
15999 end;
16000 
16001 procedure TTestResolver.TestProcType_IsNested;
16002 begin
16003   StartProgram(false);
16004   Add('{$modeswitch nestedprocvars}');
16005   Add('type');
16006   Add('  integer = longint;');
16007   Add('  TNestedProc = procedure(i: integer) is nested;');
16008   Add('procedure DoIt(i: integer);');
16009   Add('var p: TNestedProc;');
16010   Add('  procedure Sub(i: integer);');
16011   Add('  var SubP: TNestedProc;');
16012   Add('    procedure SubSub(i: integer);');
16013   Add('    begin');
16014   Add('      p:=@Sub;');
16015   Add('      p:=@SubSub;');
16016   Add('      SubP:=@Sub;');
16017   Add('      SubP:=@SubSub;');
16018   Add('    end;');
16019   Add('  begin');
16020   Add('    p:=@Sub;');
16021   Add('    p:=@SubSub;');
16022   Add('    SubP:=@Sub;');
16023   Add('    SubP:=@SubSub;');
16024   Add('  end;');
16025   Add('begin');
16026   Add('  p:=@Sub;');
16027   Add('end;');
16028   Add('begin');
16029   ParseProgram;
16030 end;
16031 
16032 procedure TTestResolver.TestProcType_IsNested_AssignProcFail;
16033 begin
16034   StartProgram(false);
16035   Add('{$modeswitch nestedprocvars}');
16036   Add('type');
16037   Add('  integer = longint;');
16038   Add('  TNestedProc = procedure(i: integer) is nested;');
16039   Add('procedure DoIt(i: integer); begin end;');
16040   Add('var p: TNestedProc;');
16041   Add('begin');
16042   Add('  p:=@DoIt;');
16043   CheckResolverException('procedural type modifier "is nested" mismatch',nXModifierMismatchY);
16044 end;
16045 
16046 procedure TTestResolver.TestProcType_ReferenceTo;
16047 begin
16048   StartProgram(false);
16049   Add([
16050   'type',
16051   '  TProcRef = reference to procedure(i: longint = 0);',
16052   '  TFuncRef = reference to function(i: longint = 0): longint;',
16053   '  TObject = class',
16054   '    function Grow(s: longint): longint;',
16055   '  end;',
16056   'var',
16057   '  p: TProcRef;',
16058   '  f: TFuncRef;',
16059   'function tobject.Grow(s: longint): longint;',
16060   '  function GrowSub(i: longint): longint;',
16061   '  begin',
16062   '    f:=@Grow;',
16063   '    f:=@GrowSub;',
16064   '    f;',
16065   '    f();',
16066   '    f(1);',
16067   '  end;',
16068   'begin',
16069   '  f:=@Grow;',
16070   '  f:=@GrowSub;',
16071   '  f;',
16072   '  f();',
16073   '  f(1);',
16074   'end;',
16075   'procedure DoIt(i: longint);',
16076   'begin',
16077   'end;',
16078   'function GetIt(i: longint): longint;',
16079   '  function Sub(i: longint): longint;',
16080   '  begin',
16081   '    p:=@DoIt;',
16082   '    f:=@GetIt;',
16083   '    f:=@Sub;',
16084   '  end;',
16085   'begin',
16086   '  p:=@DoIt;',
16087   '  f:=@GetIt;',
16088   '  f;',
16089   '  f();',
16090   '  f(1);',
16091   'end;',
16092   'begin',
16093   '  p:=@DoIt;',
16094   '  f:=@GetIt;',
16095   '  f;',
16096   '  f();',
16097   '  f(1);',
16098   '  p:=TProcRef(f);',
16099   '']);
16100   ParseProgram;
16101 end;
16102 
16103 procedure TTestResolver.TestProcType_AllowNested;
16104 begin
16105   ResolverEngine.Options:=ResolverEngine.Options+[proProcTypeWithoutIsNested];
16106   StartProgram(false);
16107   Add('type');
16108   Add('  integer = longint;');
16109   Add('  TProc = procedure(i: integer);');
16110   Add('procedure DoIt(i: integer);');
16111   Add('var p: TProc;');
16112   Add('  procedure Sub(i: integer);');
16113   Add('  var SubP: TProc;');
16114   Add('    procedure SubSub(i: integer);');
16115   Add('    begin');
16116   Add('      p:=@DoIt;');
16117   Add('      p:=@Sub;');
16118   Add('      p:=@SubSub;');
16119   Add('      SubP:=@DoIt;');
16120   Add('      SubP:=@Sub;');
16121   Add('      SubP:=@SubSub;');
16122   Add('    end;');
16123   Add('  begin');
16124   Add('    p:=@DoIt;');
16125   Add('    p:=@Sub;');
16126   Add('    p:=@SubSub;');
16127   Add('    SubP:=@DoIt;');
16128   Add('    SubP:=@Sub;');
16129   Add('    SubP:=@SubSub;');
16130   Add('  end;');
16131   Add('begin');
16132   Add('  p:=@DoIt;');
16133   Add('  p:=@Sub;');
16134   Add('end;');
16135   Add('begin');
16136   ParseProgram;
16137 end;
16138 
16139 procedure TTestResolver.TestProcType_AllowNestedOfObject;
16140 begin
16141   ResolverEngine.Options:=ResolverEngine.Options+[proProcTypeWithoutIsNested];
16142   StartProgram(false);
16143   Add('type');
16144   Add('  integer = longint;');
16145   Add('  TMethodProc = procedure(i: integer) of object;');
16146   Add('  TObject = class');
16147   Add('    procedure DoIt(i: integer);');
16148   Add('  end;');
16149   Add('procedure TObject.DoIt(i: integer);');
16150   Add('var p: TMethodProc;');
16151   Add('  procedure Sub(i: integer);');
16152   Add('  var SubP: TMethodProc;');
16153   Add('    procedure SubSub(i: integer);');
16154   Add('    begin');
16155   Add('      p:=@DoIt;');
16156   Add('      p:=@Sub;');
16157   Add('      p:=@SubSub;');
16158   Add('      SubP:=@DoIt;');
16159   Add('      SubP:=@Sub;');
16160   Add('      SubP:=@SubSub;');
16161   Add('    end;');
16162   Add('  begin');
16163   Add('    p:=@DoIt;');
16164   Add('    p:=@Sub;');
16165   Add('    p:=@SubSub;');
16166   Add('    SubP:=@DoIt;');
16167   Add('    SubP:=@Sub;');
16168   Add('    SubP:=@SubSub;');
16169   Add('  end;');
16170   Add('begin');
16171   Add('  p:=@DoIt;');
16172   Add('  p:=@Sub;');
16173   Add('end;');
16174   Add('begin');
16175   ParseProgram;
16176 end;
16177 
16178 procedure TTestResolver.TestProcType_AsArgOtherUnit;
16179 begin
16180   AddModuleWithIntfImplSrc('unit2.pas',
16181     LinesToStr([
16182     'type',
16183     '  JSInteger = longint;',
16184     '  TObject = class;',
16185     '  TJSArrayCallBack = function (element : JSInteger) : Boolean;',
16186     '  TObject = class',
16187     '  public',
16188     '    procedure forEach(const aCallBack : TJSArrayCallBack); virtual; abstract;',
16189     '  end;',
16190     '']),
16191     '');
16192   StartProgram(true);
16193   Add('uses unit2;');
16194   Add('function showElement(el : JSInteger) : boolean  ;');
16195   Add('begin');
16196   Add('  result:=true;');
16197   Add('end;');
16198   Add('var a: TObject;');
16199   Add('begin');
16200   Add('  a.forEach(@ShowElement);');
16201   ParseProgram;
16202 end;
16203 
16204 procedure TTestResolver.TestProcType_Property;
16205 begin
16206   StartProgram(false);
16207   Add([
16208   'type',
16209   '  TObject = class end;',
16210   '  TNotifyEvent = procedure(Sender: TObject) of object;',
16211   '  TControl = class',
16212   '    FOnClick: TNotifyEvent;',
16213   '    property OnClick: TNotifyEvent read FOnClick write FOnClick;',
16214   '    procedure Click(Sender: TObject);',
16215   '  end;',
16216   '  TButton = class(TControl)',
16217   '    property OnClick;',
16218   '  end;',
16219   'procedure TControl.Click(Sender: TObject);',
16220   'begin',
16221   '  if Assigned(OnClick) then ;',
16222   '  OnClick:=@Click;',
16223   '  OnClick(Sender);',
16224   '  Self.OnClick(Sender);',
16225   '  with Self do OnClick(Sender);',
16226   'end;',
16227   'var',
16228   '  Ctrl: TControl;',
16229   '  Btn: TButton;',
16230   'begin',
16231   '  if Assigned(Ctrl.OnClick) then ;',
16232   '  Ctrl.OnClick(Ctrl);',
16233   '  with Ctrl do OnClick(Ctrl);',
16234   '  if Assigned(Btn.OnClick) then ;',
16235   '  Btn.OnClick(Btn);',
16236   '  with Btn do OnClick(Btn);',
16237   '']);
16238   ParseProgram;
16239 end;
16240 
16241 procedure TTestResolver.TestProcType_PropertyCallWrongArgFail;
16242 begin
16243   StartProgram(false);
16244   Add('type');
16245   Add('  TObject = class end;');
16246   Add('  TNotifyEvent = procedure(Sender: TObject) of object;');
16247   Add('  TControl = class');
16248   Add('    FOnClick: TNotifyEvent;');
16249   Add('    property OnClick: TNotifyEvent read FOnClick write FOnClick;');
16250   Add('  end;');
16251   Add('var Btn: TControl;');
16252   Add('begin');
16253   Add('  Btn.OnClick(3);');
16254   CheckResolverException('Incompatible type arg no. 1: Got "Longint", expected "TObject"',
16255     nIncompatibleTypeArgNo);
16256 end;
16257 
16258 procedure TTestResolver.TestProcType_Typecast;
16259 begin
16260   StartProgram(false);
16261   Add('type');
16262   Add('  TNotifyEvent = procedure(Sender: Pointer) of object;');
16263   Add('  TEvent = procedure of object;');
16264   Add('  TProcA = procedure(i: longint);');
16265   Add('  TFuncB = function(i, j: longint): longint;');
16266   Add('var');
16267   Add('  Notify: TNotifyEvent;');
16268   Add('  Event: TEvent;');
16269   Add('  ProcA: TProcA;');
16270   Add('  FuncB: TFuncB;');
16271   Add('  p: pointer;');
16272   Add('begin');
16273   Add('  Notify:=TNotifyEvent(Event);');
16274   Add('  Event:=TEvent(Event);');
16275   Add('  Event:=TEvent(Notify);');
16276   Add('  ProcA:=TProcA(FuncB);');
16277   Add('  FuncB:=TFuncB(FuncB);');
16278   Add('  FuncB:=TFuncB(ProcA);');
16279   Add('  ProcA:=TProcA(p);');
16280   Add('  FuncB:=TFuncB(p);');
16281   ParseProgram;
16282 end;
16283 
16284 procedure TTestResolver.TestProcType_InsideFunction;
16285 begin
16286   StartProgram(false);
16287   Add([
16288   'function GetIt: longint;',
16289   'type TGetter = function: longint;',
16290   'var',
16291   '  p: Pointer;',
16292   'begin',
16293   '  Result:=TGetter(p)();',
16294   'end;',
16295   'begin',
16296   '']);
16297   ParseProgram;
16298 end;
16299 
16300 procedure TTestResolver.TestProcType_PassProcToUntyped;
16301 var
16302   aMarker: PSrcMarker;
16303   Elements: TFPList;
16304   ActualImplicitCallWithoutParams: Boolean;
16305   i: Integer;
16306   El: TPasElement;
16307   Ref: TResolvedReference;
16308 begin
16309   StartProgram(false);
16310   Add([
16311   'type',
16312   '  TEvent = procedure of object;',
16313   '  TFunc = function: longint of object;',
16314   'procedure DoIt; varargs; begin end;',
16315   'procedure DoSome(const a; var b; c: pointer); begin end;',
16316   'var',
16317   '  E: TEvent;',
16318   '  F: TFunc;',
16319   'begin',
16320   '  DoIt({#a1}E,{#a2}F);',
16321   '  DoSome({#b1}E,{#b2}E,{#b3}E);',
16322   '  DoSome({#c1}F,{#c2}F,{#c3}F);',
16323   '']);
16324   ParseProgram;
16325 
16326   aMarker:=FirstSrcMarker;
16327   while aMarker<>nil do
16328     begin
16329     //writeln('TTestResolver.TestProcType_PassProcToUntyped ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
16330     Elements:=FindElementsAt(aMarker);
16331     try
16332       ActualImplicitCallWithoutParams:=false;
16333       for i:=0 to Elements.Count-1 do
16334         begin
16335         El:=TPasElement(Elements[i]);
16336         //writeln('TTestResolver.TestProcType_PassProcToUntyped ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
16337         if not (El.CustomData is TResolvedReference) then continue;
16338         Ref:=TResolvedReference(El.CustomData);
16339         //writeln('TTestResolver.TestProcType_PassProcToUntyped ',GetObjName(Ref.Declaration),' rrfImplicitCallWithoutParams=',rrfImplicitCallWithoutParams in Ref.Flags);
16340         if rrfImplicitCallWithoutParams in Ref.Flags then
16341           ActualImplicitCallWithoutParams:=true;
16342         break;
16343         end;
16344       if ActualImplicitCallWithoutParams then
16345         RaiseErrorAtSrcMarker('expected no implicit call at "#'+aMarker^.Identifier+'"',aMarker);
16346     finally
16347       Elements.Free;
16348     end;
16349     aMarker:=aMarker^.Next;
16350     end;
16351 end;
16352 
16353 procedure TTestResolver.TestPointer;
16354 begin
16355   StartProgram(false);
16356   Add([
16357   'type',
16358   '  TObject = class end;',
16359   '  TClass = class of TObject;',
16360   '  TMyPtr = pointer;',
16361   '  TArrInt = array of longint;',
16362   '  TFunc = function: longint;',
16363   'procedure DoIt; begin end;',
16364   'var',
16365   '  p: TMyPtr;',
16366   '  Obj: TObject;',
16367   '  Cl: TClass;',
16368   '  a: tarrint;',
16369   '  f: TFunc;',
16370   '  s: string;',
16371   '  u: unicodestring;',
16372   'begin',
16373   '  p:=nil;',
16374   '  if p=nil then;',
16375   '  if nil=p then;',
16376   '  if Assigned(p) then;',
16377   '  p:=obj;',
16378   '  p:=cl;',
16379   '  p:=a;',
16380   '  p:=Pointer(f);',
16381   '  p:=@DoIt;',
16382   '  p:=Pointer(@DoIt);',
16383   '  obj:=TObject(p);',
16384   '  cl:=TClass(p);',
16385   '  a:=TArrInt(p);',
16386   '  p:=Pointer(a);',
16387   '  p:=Pointer(s);',
16388   '  s:=String(p);',
16389   '  p:=pointer(u);',
16390   '  u:=UnicodeString(p);']);
16391   ParseProgram;
16392 end;
16393 
16394 procedure TTestResolver.TestPointer_AnonymousSetFail;
16395 begin
16396   StartProgram(false);
16397   Add([
16398   'type p = ^(red, green);',
16399   'begin']);
16400   CheckParserException('Expected "Identifier" at token "(" in file afile.pp at line 2 column 11',
16401     nParserExpectTokenError);
16402 end;
16403 
16404 procedure TTestResolver.TestPointer_AssignPointerToClassFail;
16405 begin
16406   StartProgram(false);
16407   Add('type');
16408   Add('  TObject = class end;');
16409   Add('var');
16410   Add('  Obj: TObject;');
16411   Add('  p: pointer;');
16412   Add('begin');
16413   Add('  obj:=p;');
16414   CheckResolverException('Incompatible types: got "Pointer" expected "TObject"',
16415     nIncompatibleTypesGotExpected);
16416 end;
16417 
16418 procedure TTestResolver.TestPointer_TypecastToMethodTypeFail;
16419 begin
16420   StartProgram(false);
16421   Add('type');
16422   Add('  TEvent = procedure of object;');
16423   Add('var');
16424   Add('  p: pointer;');
16425   Add('  e: TEvent;');
16426   Add('begin');
16427   Add('  e:=TEvent(p);');
16428   CheckResolverException('Illegal type conversion: "Pointer" to "procedure type of Object"',
16429     nIllegalTypeConversionTo);
16430 end;
16431 
16432 procedure TTestResolver.TestPointer_TypecastFromMethodTypeFail;
16433 begin
16434   StartProgram(false);
16435   Add('type');
16436   Add('  TEvent = procedure of object;');
16437   Add('var');
16438   Add('  p: pointer;');
16439   Add('  e: TEvent;');
16440   Add('begin');
16441   Add('  p:=Pointer(e);');
16442   CheckResolverException('Illegal type conversion: "procedural type of Object" to "Pointer"',
16443     nIllegalTypeConversionTo);
16444 end;
16445 
16446 procedure TTestResolver.TestPointer_TypecastMethod_proMethodAddrAsPointer;
16447 begin
16448   ResolverEngine.Options:=ResolverEngine.Options+[proMethodAddrAsPointer];
16449   StartProgram(false);
16450   Add('type');
16451   Add('  TEvent = procedure of object;');
16452   Add('var');
16453   Add('  p: pointer;');
16454   Add('  e: TEvent;');
16455   Add('begin');
16456   Add('  e:=TEvent(p);');
16457   Add('  p:=Pointer(e);');
16458   ParseProgram;
16459 end;
16460 
16461 procedure TTestResolver.TestPointer_OverloadSignature;
16462 begin
16463   StartProgram(false);
16464   Add('type');
16465   Add('  TObject = class end;');
16466   Add('  TClass = class of TObject;');
16467   Add('  TBird = class(TObject) end;');
16468   Add('  TBirds = class of TBird;');
16469   Add('procedure {#pointer}DoIt(p: Pointer); begin end;');
16470   Add('procedure {#tobject}DoIt(o: TObject); begin end;');
16471   Add('procedure {#tclass}DoIt(c: TClass); begin end;');
16472   Add('var');
16473   Add('  p: pointer;');
16474   Add('  o: TObject;');
16475   Add('  c: TClass;');
16476   Add('  b: TBird;');
16477   Add('  bc: TBirds;');
16478   Add('begin');
16479   Add('  {@pointer}DoIt(p);');
16480   Add('  {@tobject}DoIt(o);');
16481   Add('  {@tclass}DoIt(c);');
16482   Add('  {@tobject}DoIt(b);');
16483   Add('  {@tclass}DoIt(bc);');
16484   ParseProgram;
16485 end;
16486 
16487 procedure TTestResolver.TestPointer_Assign;
16488 begin
16489   StartProgram(false);
16490   Add([
16491   'type',
16492   '  TPtr = pointer;',
16493   '  TClass = class of TObject;',
16494   '  TObject = class end;',
16495   'var',
16496   '  p: TPtr;',
16497   '  o: TObject;',
16498   '  c: TClass;',
16499   'begin',
16500   '  p:=o;',
16501   '  if p=o then ;',
16502   '  if o=p then ;',
16503   '  p:=c;',
16504   '  if p=c then ;',
16505   '  if c=p then ;',
16506   '']);
16507   ParseProgram;
16508 end;
16509 
16510 procedure TTestResolver.TestPointerTyped;
16511 begin
16512   StartProgram(false);
16513   Add([
16514   'type',
16515   '  PBoolean = ^boolean;',
16516   '  PPInteger = ^PInteger;',
16517   '  PInteger = ^integer;',
16518   '  integer = longint;',
16519   'var',
16520   '  i: integer;',
16521   '  p1: PInteger;',
16522   '  p2: ^Integer;',
16523   '  p3: ^PInteger;',
16524   '  a: array of integer;',
16525   'begin',
16526   '  p1:=@i;',
16527   '  p1:=p2;',
16528   '  p2:=@i;',
16529   '  p3:=@p1;',
16530   '  p1:=@a[1];',
16531   '  p1^:=i;',
16532   '  i:=(@i)^;',
16533   '  i:=p1^;',
16534   '  i:=p2^;',
16535   '  i:=p3^^;',
16536   '  i:=PInteger(p3)^;',
16537   '  if p1=@i then ;',
16538   '  if @i=p1 then ;',
16539   '  if p1=p2 then ;',
16540   '  if p2=p1 then ;',
16541   '  if p2=@i then ;',
16542   '  if @i=p2 then ;',
16543   '  if p1=@a[2] then ;',
16544   '  if @a[3]=p1 then ;',
16545   '  if i=p1^ then ;',
16546   '  if p1^=i then ;',
16547   '  i:=p1[1];',
16548   '  i:=(@i)[1];',
16549   '  i:=p2[2];',
16550   '  i:=p3[3][4];',
16551   '']);
16552   ParseProgram;
16553 end;
16554 
16555 procedure TTestResolver.TestPointerTypedForwardMissingFail;
16556 begin
16557   StartProgram(false);
16558   Add([
16559   'type',
16560   '  PInteger = ^integer;',
16561   'var',
16562   '  i: integer;',
16563   'begin',
16564   '']);
16565   CheckResolverException('identifier not found "integer"',nIdentifierNotFound);
16566 end;
16567 
16568 procedure TTestResolver.TestPointerTyped_CycleFail;
16569 begin
16570   StartProgram(false);
16571   Add([
16572   'type',
16573   '  PInteger = ^integer;',
16574   '  integer = PInteger;',
16575   'var',
16576   '  i: integer;',
16577   '  p1: PInteger;',
16578   'begin',
16579   '']);
16580   CheckResolverException(sTypeCycleFound,nTypeCycleFound);
16581 end;
16582 
16583 procedure TTestResolver.TestPointerTyped_AssignMismatchFail;
16584 begin
16585   StartProgram(false);
16586   Add([
16587   'type',
16588   '  PInt = ^longint;',
16589   '  PBool = ^boolean;',
16590   'var',
16591   '  pi: Pint;',
16592   '  pb: PBool;',
16593   'begin',
16594   '  pi:=pb;',
16595   '']);
16596   CheckResolverException('Incompatible types: got "PBool" expected "PInt"',nIncompatibleTypesGotExpected);
16597 end;
16598 
16599 procedure TTestResolver.TestPointerTyped_AddrAddrFail;
16600 begin
16601   StartProgram(false);
16602   Add([
16603   'type',
16604   '  PInt = ^longint;',
16605   '  PPInt = ^PInt;',
16606   'var',
16607   '  i: longint;',
16608   '  p: PPint;',
16609   'begin',
16610   '  p:=@(@i);',
16611   '']);
16612   CheckResolverException('illegal qualifier "@" in front of "Pointer"',nIllegalQualifierInFrontOf);
16613 end;
16614 
16615 procedure TTestResolver.TestPointerTyped_RecordObjFPC;
16616 begin
16617   StartProgram(false);
16618   Add([
16619   'type',
16620   '  PRec = ^TRec;',
16621   '  TRec = record x: longint; end;',
16622   'var',
16623   '  r: TRec;',
16624   '  p: PRec;',
16625   '  i: longint;',
16626   '  Ptr: pointer;',
16627   'begin',
16628   '  p:=@r;',
16629   '  i:=p^.x;',
16630   '  p^.x:=i;',
16631   '  if i=p^.x then;',
16632   '  if p^.x=i then;',
16633   '  ptr:=p;',
16634   '  p:=PRec(ptr);',
16635   '']);
16636   ParseProgram;
16637 end;
16638 
16639 procedure TTestResolver.TestPointerTyped_RecordDelphi;
16640 begin
16641   StartProgram(false);
16642   Add([
16643   '{$mode delphi}',
16644   'type',
16645   '  PRec = ^TRec;',
16646   '  TRec = record x: longint; end;',
16647   'procedure DoIt(const p: PRec);',
16648   'begin',
16649   '  p.x:=p.x;',
16650   '  with p^ do',
16651   '    x:=x;',
16652   'end;',
16653   'var',
16654   '  r: TRec;',
16655   '  p: PRec;',
16656   '  i: longint;',
16657   'begin',
16658   '  i:=p.x;',
16659   '  p.x:=i;',
16660   '  if i=p.x then;',
16661   '  if p.x=i then;',
16662   '  DoIt(@r);',
16663   '']);
16664   ParseProgram;
16665 end;
16666 
16667 procedure TTestResolver.TestPointerTyped_Arithmetic;
16668 begin
16669   StartProgram(false);
16670   Add([
16671   'type',
16672   '  PInt = ^longint;',
16673   'var',
16674   '  i: longint;',
16675   '  p: PInt;',
16676   'begin',
16677   '  inc(p);',
16678   '  inc(p,2);',
16679   '  p:=p+3;',
16680   '  p:=4+p;',
16681   '  p:=@i+5;',
16682   '  p:=6+@i;',
16683   '  i:=(p+7)^;',
16684   '  i:=(@i+8)^;',
16685   '']);
16686   ParseProgram;
16687 end;
16688 
16689 procedure TTestResolver.TestResourcestring;
16690 begin
16691   StartProgram(false);
16692   Add([
16693   'const Foo = ''foo'';',
16694   'Resourcestring',
16695   '  Bar = foo;',
16696   '  Red = ''Red'';',
16697   '  r = ''Rd''+foo;',
16698   'procedure DoIt(s: string; const h: string); begin end;',
16699   'begin',
16700   '  if bar=red then ;',
16701   '  if bar=''a'' then ;',
16702   '  doit(r,r);',
16703   '']);
16704   ParseProgram;
16705 end;
16706 
16707 procedure TTestResolver.TestResourcestringAssignFail;
16708 begin
16709   StartProgram(false);
16710   Add([
16711   'Resourcestring Foo = ''bar'';',
16712   'begin',
16713   '  Foo:=''a'';',
16714   '']);
16715   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
16716 end;
16717 
16718 procedure TTestResolver.TestResourcestringLocalFail;
16719 begin
16720   StartProgram(false);
16721   Add([
16722   'procedure DoIt;',
16723   'Resourcestring Foo = ''bar'';',
16724   'begin end;',
16725   'begin;',
16726   '']);
16727   CheckParserException(SParserResourcestringsMustBeGlobal,nParserResourcestringsMustBeGlobal);
16728 end;
16729 
16730 procedure TTestResolver.TestResourcestringInConstFail;
16731 begin
16732   StartProgram(false);
16733   Add([
16734   'Resourcestring Foo = ''foo'';',
16735   'const Bar = ''Prefix''+Foo;',
16736   'begin',
16737   '']);
16738   CheckResolverException(sConstantExpressionExpected,nConstantExpressionExpected);
16739 end;
16740 
16741 procedure TTestResolver.TestResourcestringPassVarArgFail;
16742 begin
16743   StartProgram(false);
16744   Add([
16745   'Resourcestring Bar = ''foo'';',
16746   'procedure DoIt(var s: string); begin end;',
16747   'begin',
16748   '  doit(bar);',
16749   '']);
16750   CheckResolverException(sVariableIdentifierExpected,nVariableIdentifierExpected);
16751 end;
16752 
16753 procedure TTestResolver.TestHint_ElementHints;
16754 begin
16755   StartProgram(false);
16756   Add([
16757   'type',
16758   '  TDeprecated = longint deprecated;',
16759   '  TLibrary = longint library;',
16760   '  TPlatform = longint platform;',
16761   '  TExperimental = longint experimental;',
16762   '  TUnimplemented = longint unimplemented;',
16763   'var',
16764   '  vDeprecated: TDeprecated;',
16765   '  vLibrary: TLibrary;',
16766   '  vPlatform: TPlatform;',
16767   '  vExperimental: TExperimental;',
16768   '  vUnimplemented: TUnimplemented;',
16769   'begin',
16770   '']);
16771   ParseProgram;
16772   CheckResolverHint(mtWarning,nSymbolXIsDeprecated,'Symbol "TDeprecated" is deprecated');
16773   CheckResolverHint(mtWarning,nSymbolXBelongsToALibrary,'Symbol "TLibrary" belongs to a library');
16774   CheckResolverHint(mtWarning,nSymbolXIsNotPortable,'Symbol "TPlatform" is not portable');
16775   CheckResolverHint(mtWarning,nSymbolXIsExperimental,'Symbol "TExperimental" is experimental');
16776   CheckResolverHint(mtWarning,nSymbolXIsNotImplemented,'Symbol "TUnimplemented" is not implemented');
16777   CheckResolverUnexpectedHints;
16778 end;
16779 
16780 procedure TTestResolver.TestHint_ElementHintsMsg;
16781 begin
16782   StartProgram(false);
16783   Add([
16784   'type',
16785   '  TDeprecated = longint deprecated ''foo'';',
16786   'var',
16787   '  vDeprecated: TDeprecated;',
16788   'begin',
16789   '']);
16790   ParseProgram;
16791   CheckResolverHint(mtWarning,nSymbolXIsDeprecatedY,'Symbol "TDeprecated" is deprecated: ''foo''');
16792   CheckResolverUnexpectedHints;
16793 end;
16794 
16795 procedure TTestResolver.TestHint_ElementHintsAlias;
16796 var
16797   aMarker: PSrcMarker;
16798 begin
16799   StartProgram(false);
16800   Add([
16801   'type',
16802   '  TPlatform = longint platform;',
16803   '  {#a}TAlias = TPlatform;',
16804   'var',
16805   '  {#b}vB: TPlatform;',
16806   '  {#c}vC: TAlias;',
16807   'function {#d}DoIt: TPlatform;',
16808   'begin',
16809   '  Result:=0;',
16810   'end;',
16811   'function {#e}DoSome: TAlias;',
16812   'begin',
16813   '  Result:=0;',
16814   'end;',
16815   'begin',
16816   '']);
16817   ParseProgram;
16818   //WriteSources('afile.pp',3,4);
16819 
16820   aMarker:=FirstSrcMarker;
16821   while aMarker<>nil do
16822     begin
16823     //writeln('TTestResolver.TestHint_ElementHintsAlias Marker "',aMarker^.Identifier,'" ',aMarker^.StartCol,'..',aMarker^.EndCol);
16824     CheckResolverHint(mtWarning,nSymbolXIsNotPortable,'Symbol "TPlatform" is not portable',aMarker);
16825     aMarker:=aMarker^.Next;
16826     end;
16827 
16828   CheckResolverUnexpectedHints(true);
16829 end;
16830 
16831 procedure TTestResolver.TestHint_ElementHints_WarnOff_SymbolDeprecated;
16832 begin
16833   StartProgram(false);
16834   Add([
16835   '{$warn symbol_deprecated off}',
16836   'var',
16837   '  i: byte deprecated;',
16838   'begin',
16839   '  if i=3 then ;']);
16840   ParseProgram;
16841   CheckResolverUnexpectedHints(true);
16842 end;
16843 
16844 procedure TTestResolver.TestHint_Garbage;
16845 begin
16846   StartProgram(false);
16847   Add([
16848   'begin',
16849   'end.']);
16850   ParseProgram;
16851   CheckResolverHint(mtHint,nTextAfterFinalIgnored,sTextAfterFinalIgnored);
16852   CheckResolverUnexpectedHints(true);
16853 end;
16854 
16855 procedure TTestResolver.TestClassHelper;
16856 begin
16857   StartProgram(false);
16858   Add([
16859   'type',
16860   '  TObject = class',
16861   '  end;',
16862   '  TObjectHelper = class helper for TObject',
16863   '  type T = word;',
16864   '  const',
16865   '    c: T = 3;',
16866   '    k: T = 4;',
16867   '  class var',
16868   '    v: T;',
16869   '    w: T;',
16870   '  end;',
16871   '  TBird = class(TObject)',
16872   '  end;',
16873   '  TBirdHelper = class helper for TBird',
16874   '  end;',
16875   '  TExtObjHelper = class helper(TObjectHelper) for TBird',
16876   '  end;',
16877   'begin',
16878   '']);
16879   ParseProgram;
16880 end;
16881 
16882 procedure TTestResolver.TestClassHelper_AncestorIsNotHelperForDescendantFail;
16883 begin
16884   StartProgram(false);
16885   Add([
16886   'type',
16887   '  TObject = class',
16888   '  end;',
16889   '  TBird = class(TObject)',
16890   '  end;',
16891   '  TBirdHelper = class helper for TBird',
16892   '  end;',
16893   '  TFish = class(TObject)',
16894   '  end;',
16895   '  THelper = class helper(TBirdHelper) for TFish',
16896   '  end;',
16897   'begin',
16898   '']);
16899   CheckResolverException('Derived class helper must extend a subclass of "TBird" or the class itself',
16900     nDerivedXMustExtendASubClassY);
16901 end;
16902 
16903 procedure TTestResolver.TestClassHelper_HelperForParentFail;
16904 begin
16905   StartProgram(false);
16906   Add([
16907   'type',
16908   '  TObject = class',
16909   '  end;',
16910   '  TBird = class(TObject)',
16911   '  type',
16912   '    TBirdHelper = class helper for TBird',
16913   '    end;',
16914   '  end;',
16915   'begin',
16916   '']);
16917   CheckResolverException(sTypeXIsNotYetCompletelyDefined,
16918     nTypeXIsNotYetCompletelyDefined);
16919 end;
16920 
16921 procedure TTestResolver.TestClassHelper_ForInterfaceFail;
16922 begin
16923   StartProgram(false);
16924   Add([
16925   'type',
16926   '  IUnknown = interface',
16927   '    procedure DoIt;',
16928   '  end;',
16929   '  TBirdHelper = class helper for IUnknown',
16930   '  end;',
16931   'begin',
16932   '']);
16933   CheckResolverException('class type expected, but IUnknown found',
16934     nXExpectedButYFound);
16935 end;
16936 
16937 procedure TTestResolver.TestClassHelper_FieldFail;
16938 begin
16939   StartProgram(false);
16940   Add([
16941   'type',
16942   '  TObject = class',
16943   '  end;',
16944   '  TObjHelper = class helper for TObject',
16945   '    F: word;',
16946   '  end;',
16947   'begin',
16948   '']);
16949   CheckParserException('Fields are not allowed in class helper',
16950     nParserNoFieldsAllowed);
16951 end;
16952 
16953 procedure TTestResolver.TestClassHelper_AbstractFail;
16954 begin
16955   StartProgram(false);
16956   Add([
16957   '{$mode delphi}',
16958   'type',
16959   '  TObject = class',
16960   '  end;',
16961   '  TObjHelper = class helper for TObject',
16962   '    procedure DoIt; virtual; abstract;',
16963   '  end;',
16964   'begin',
16965   '']);
16966   CheckResolverException('Invalid class helper procedure modifier abstract',
16967     nInvalidXModifierY);
16968 end;
16969 
16970 procedure TTestResolver.TestClassHelper_VirtualObjFPCFail;
16971 begin
16972   StartProgram(false);
16973   Add([
16974   'type',
16975   '  TObject = class',
16976   '  end;',
16977   '  TObjHelper = class helper for TObject',
16978   '    procedure DoIt; virtual;',
16979   '  end;',
16980   'procedure TObjHelper.DoIt;',
16981   'begin end;',
16982   'begin',
16983   '']);
16984   CheckResolverException('Invalid class helper procedure modifier virtual',
16985     nInvalidXModifierY);
16986 end;
16987 
16988 procedure TTestResolver.TestClassHelper_VirtualDelphiFail;
16989 begin
16990   StartProgram(false);
16991   Add([
16992   '{$mode delphi}',
16993   'type',
16994   '  TObject = class',
16995   '  end;',
16996   '  TObjHelper = class helper for TObject',
16997   '    procedure DoIt; virtual;',
16998   '  end;',
16999   'procedure TObjHelper.DoIt;',
17000   'begin end;',
17001   'begin',
17002   '']);
17003   CheckResolverException('Invalid class helper procedure modifier virtual',
17004     nInvalidXModifierY);
17005 end;
17006 
17007 procedure TTestResolver.TestClassHelper_DestructorFail;
17008 begin
17009   StartProgram(false);
17010   Add([
17011   'type',
17012   '  TObject = class',
17013   '  end;',
17014   '  TObjHelper = class helper for TObject',
17015   '    destructor Destroyer;',
17016   '  end;',
17017   'destructor TObjHelper.Destroyer;',
17018   'begin end;',
17019   'begin',
17020   '']);
17021   CheckParserException('destructor is not allowed in class helper',
17022     nParserXNotAllowedInY);
17023 end;
17024 
17025 procedure TTestResolver.TestClassHelper_ClassRefersToTypeHelperOfAncestor;
17026 begin
17027   StartProgram(false);
17028   Add([
17029   'type',
17030   '  TObject = class',
17031   '  end;',
17032   '  TObjHelper = class helper for TObject',
17033   '  type',
17034   '    TInt = word;',
17035   '    function GetSize: TInt;',
17036   '  end;',
17037   '  TAnt = class',
17038   '    procedure SetSize(Value: TInt);',
17039   '    property Size: TInt read GetSize write SetSize;',
17040   '  end;',
17041   'function Tobjhelper.getSize: TInt;',
17042   'begin',
17043   'end;',
17044   'procedure TAnt.SetSize(Value: TInt);',
17045   'begin',
17046   'end;',
17047   'begin',
17048   '']);
17049   ParseProgram;
17050 end;
17051 
17052 procedure TTestResolver.TestClassHelper_InheritedObjFPC;
17053 begin
17054   StartProgram(false);
17055   Add([
17056   'type',
17057   '  TObject = class',
17058   '    procedure {#TObject_Fly}Fly;',
17059   '  end;',
17060   '  TObjHelper = class helper for TObject',
17061   '    procedure {#TObjHelper_Fly}Fly;',
17062   '  end;',
17063   '  TBird = class',
17064   '    procedure {#TBird_Fly}Fly;',
17065   '  end;',
17066   '  TBirdHelper = class helper for TBird',
17067   '    procedure {#TBirdHelper_Fly}Fly;',
17068   '    procedure {#TBirdHelper_Walk}Walk;',
17069   '  end;',
17070   '  TEagleHelper = class helper(TBirdHelper) for TBird',
17071   '    procedure {#TEagleHelper_Fly}Fly;',
17072   '    procedure {#TEagleHelper_Walk}Walk;',
17073   '  end;',
17074   'procedure Tobject.fly;',
17075   'begin',
17076   '  inherited;', // ignore
17077   'end;',
17078   'procedure Tobjhelper.fly;',
17079   'begin',
17080   '  {@TObject_Fly}inherited;',
17081   '  inherited {@TObject_Fly}Fly;',
17082   'end;',
17083   'procedure Tbird.fly;',
17084   'begin',
17085   '  {@TObjHelper_Fly}inherited;',
17086   '  inherited {@TObjHelper_Fly}Fly;',
17087   'end;',
17088   'procedure Tbirdhelper.fly;',
17089   'begin',
17090   '  {@TBird_Fly}inherited;',
17091   '  inherited {@TBird_Fly}Fly;',
17092   'end;',
17093   'procedure Tbirdhelper.walk;',
17094   'begin',
17095   'end;',
17096   'procedure teagleHelper.fly;',
17097   'begin',
17098   '  {@TBird_Fly}inherited;',
17099   '  inherited {@TBird_Fly}Fly;',
17100   'end;',
17101   'procedure teagleHelper.walk;',
17102   'begin',
17103   '  {@TBirdHelper_Walk}inherited;',
17104   '  inherited {@TBirdHelper_Walk}Walk;',
17105   'end;',
17106   'var',
17107   '  o: TObject;',
17108   '  b: TBird;',
17109   'begin',
17110   '  o.{@TObjHelper_Fly}Fly;',
17111   '  b.{@TEagleHelper_Fly}Fly;',
17112   '']);
17113   ParseProgram;
17114 end;
17115 
17116 procedure TTestResolver.TestClassHelper_InheritedObjFPC2;
17117 begin
17118   StartProgram(false);
17119   Add([
17120   'type',
17121   '  TObject = class',
17122   '    procedure {#TObject_Fly}Fly;',
17123   '  end;',
17124   '  TObjHelper = class helper for TObject',
17125   '    procedure {#TObjHelper_Walk}Walk;',
17126   '  end;',
17127   '  TBird = class',
17128   '    procedure {#TBird_Fly}Fly;',
17129   '  end;',
17130   '  TBirdHelper = class helper for TBird',
17131   '    procedure {#TBirdHelper_Walk}Walk;',
17132   '  end;',
17133   '  TEagleHelper = class helper(TBirdHelper) for TBird',
17134   '    procedure {#TEagleHelper_Walk}Walk;',
17135   '  end;',
17136   'procedure Tobject.fly;',
17137   'begin',
17138   '  inherited;', // ignore
17139   'end;',
17140   'procedure Tobjhelper.walk;',
17141   'begin',
17142   '  inherited;', // ignore
17143   'end;',
17144   'procedure Tbird.fly;',
17145   'begin',
17146   '  {@TObject_Fly}inherited;', // no helper, search further in ancestor
17147   '  inherited {@TObject_Fly}Fly;', // no helper, search further in ancestor
17148   'end;',
17149   'procedure Tbirdhelper.walk;',
17150   'begin',
17151   '  {@TObjHelper_Walk}inherited;',
17152   '  inherited {@TObjHelper_Walk}Walk;',
17153   'end;',
17154   'procedure teagleHelper.walk;',
17155   'begin',
17156   '  {@TObjHelper_Walk}inherited;',
17157   '  inherited {@TObjHelper_Walk}Walk;',
17158   'end;',
17159   'begin',
17160   '']);
17161   ParseProgram;
17162 end;
17163 
17164 procedure TTestResolver.TestClassHelper_InheritedObjFPCStrictPrivateFail;
17165 begin
17166   StartProgram(false);
17167   Add([
17168   'type',
17169   '  TObject = class',
17170   '  strict private i: word;',
17171   '  end;',
17172   '  THelper = class helper for TObject',
17173   '    property a: word read i;',
17174   '  end;',
17175   'begin',
17176   '']);
17177   CheckResolverException('Can''t access strict private member i',nCantAccessXMember);
17178 end;
17179 
17180 procedure TTestResolver.TestClassHelper_InheritedClassObjFPC;
17181 begin
17182   StartProgram(false);
17183   Add([
17184   'type',
17185   '  TObject = class',
17186   '    class procedure {#TObject_Fly}Fly;',
17187   '  end;',
17188   '  TObjHelper = class helper for TObject',
17189   '    class procedure {#TObjHelper_Fly}Fly;',
17190   '  end;',
17191   '  TBird = class',
17192   '    class procedure {#TBird_Fly}Fly;',
17193   '  end;',
17194   '  TBirdHelper = class helper for TBird',
17195   '    class procedure {#TBirdHelper_Fly}Fly;',
17196   '    class procedure {#TBirdHelper_Walk}Walk;',
17197   '  end;',
17198   '  TEagleHelper = class helper(TBirdHelper) for TBird',
17199   '    class procedure {#TEagleHelper_Fly}Fly;',
17200   '    class procedure {#TEagleHelper_Walk}Walk;',
17201   '  end;',
17202   'class procedure Tobject.fly;',
17203   'begin',
17204   '  inherited;', // ignore
17205   'end;',
17206   'class procedure Tobjhelper.fly;',
17207   'begin',
17208   '  {@TObject_Fly}inherited;',
17209   '  inherited {@TObject_Fly}Fly;',
17210   'end;',
17211   'class procedure Tbird.fly;',
17212   'begin',
17213   '  {@TObjHelper_Fly}inherited;',
17214   '  inherited {@TObjHelper_Fly}Fly;',
17215   'end;',
17216   'class procedure Tbirdhelper.fly;',
17217   'begin',
17218   '  {@TBird_Fly}inherited;',
17219   '  inherited {@TBird_Fly}Fly;',
17220   'end;',
17221   'class procedure Tbirdhelper.walk;',
17222   'begin',
17223   'end;',
17224   'class procedure teagleHelper.fly;',
17225   'begin',
17226   '  {@TBird_Fly}inherited;',
17227   '  inherited {@TBird_Fly}Fly;',
17228   'end;',
17229   'class procedure teagleHelper.walk;',
17230   'begin',
17231   '  {@TBirdHelper_Walk}inherited;',
17232   '  inherited {@TBirdHelper_Walk}Walk;',
17233   'end;',
17234   'var',
17235   '  o: TObject;',
17236   '  b: TBird;',
17237   'begin',
17238   '  o.{@TObjHelper_Fly}Fly;',
17239   '  TObject.{@TObjHelper_Fly}Fly;',
17240   '  b.{@TEagleHelper_Fly}Fly;',
17241   '  TBird.{@TEagleHelper_Fly}Fly;',
17242   '']);
17243   ParseProgram;
17244 end;
17245 
17246 procedure TTestResolver.TestClassHelper_InheritedDelphi;
17247 begin
17248   StartProgram(false);
17249   Add([
17250   '{$mode delphi}',
17251   'type',
17252   '  TObject = class',
17253   '    procedure {#TObject_Fly}Fly;',
17254   '  end;',
17255   '  TObjHelper = class helper for TObject',
17256   '    procedure {#TObjHelper_Fly}Fly;',
17257   '  end;',
17258   '  TBird = class',
17259   '    procedure {#TBird_Fly}Fly;',
17260   '  end;',
17261   '  TBirdHelper = class helper for TBird',
17262   '    procedure {#TBirdHelper_Fly}Fly;',
17263   '    procedure {#TBirdHelper_Walk}Walk;',
17264   '  end;',
17265   '  TEagleHelper = class helper(TBirdHelper) for TBird',
17266   '    procedure {#TEagleHelper_Fly}Fly;',
17267   '    procedure {#TEagleHelper_Walk}Walk;',
17268   '  end;',
17269   'procedure Tobject.fly;',
17270   'begin',
17271   '  inherited;', // ignore
17272   'end;',
17273   'procedure Tobjhelper.fly;',
17274   'begin',
17275   '  inherited;', // ignore
17276   '  inherited {@TObject_Fly}Fly;',
17277   'end;',
17278   'procedure Tbird.fly;',
17279   'begin',
17280   '  {@TObjHelper_Fly}inherited;',
17281   '  inherited {@TObjHelper_Fly}Fly;',
17282   'end;',
17283   'procedure Tbirdhelper.fly;',
17284   'begin',
17285   '  {@TObjHelper_Fly}inherited;',// skip helperfortype too
17286   '  inherited {@TBird_Fly}Fly;',
17287   'end;',
17288   'procedure Tbirdhelper.walk;',
17289   'begin',
17290   'end;',
17291   'procedure teagleHelper.fly;',
17292   'begin',
17293   '  {@TObjHelper_Fly}inherited;',// skip helperfortype too
17294   '  inherited {@TBird_Fly}Fly;',
17295   'end;',
17296   'procedure teagleHelper.walk;',
17297   'begin',
17298   '  inherited;', // ignore
17299   '  inherited {@TBirdHelper_Walk}Walk;',
17300   'end;',
17301   'var',
17302   '  o: TObject;',
17303   '  b: TBird;',
17304   'begin',
17305   '  o.{@TObjHelper_Fly}Fly;',
17306   '  b.{@TEagleHelper_Fly}Fly;',
17307   '']);
17308   ParseProgram;
17309 end;
17310 
17311 procedure TTestResolver.TestClassHelper_NestedInheritedParentFail;
17312 begin
17313   StartProgram(false);
17314   Add([
17315   'type',
17316   '  TObject = class',
17317   '  end;',
17318   '  TBird = class',
17319   '    procedure Fly;',
17320   '  type',
17321   '    TBirdHelper = class helper for TObject',
17322   '      procedure Fly;',
17323   '    end;',
17324   '  end;',
17325   'procedure TBird.fly;',
17326   'begin',
17327   'end;',
17328   'procedure TBird.Tbirdhelper.fly;',
17329   'begin',
17330   '  inherited Fly;',
17331   'end;',
17332   'begin',
17333   '']);
17334   CheckResolverException('identifier not found "Fly"',nIdentifierNotFound);
17335 end;
17336 
17337 procedure TTestResolver.TestClassHelper_AccessFields;
17338 begin
17339   StartProgram(false);
17340   Add([
17341   'type',
17342   '  TObject = class end;',
17343   '  TBird = class',
17344   '    Size: word;',
17345   '    FItems: array of word;',
17346   '  end;',
17347   '  TBirdHelper = class helper for TBird',
17348   '    procedure Fly;',
17349   '  end;',
17350   'procedure TBirdHelper.Fly;',
17351   'begin',
17352   '  Size:=FItems[0];',
17353   '  Self.Size:=Self.FItems[0];',
17354   'end;',
17355   'var',
17356   '  b: TBird;',
17357   'begin',
17358   '  b.Fly;',
17359   '  b.Fly()',
17360   '']);
17361   ParseProgram;
17362 end;
17363 
17364 procedure TTestResolver.TestClassHelper_HelperDotClassMethodFail;
17365 begin
17366   StartProgram(false);
17367   Add([
17368   'type',
17369   '  TObject = class end;',
17370   '  THelper = class helper for TObject',
17371   '    class procedure Fly;',
17372   '  end;',
17373   'class procedure THelper.Fly;',
17374   'begin',
17375   'end;',
17376   'begin',
17377   '  THelper.Fly;',
17378   '']);
17379   CheckResolverException(sHelpersCannotBeUsedAsTypes,nHelpersCannotBeUsedAsTypes);
17380 end;
17381 
17382 procedure TTestResolver.TestClassHelper_WithDoHelperFail;
17383 begin
17384   StartProgram(false);
17385   Add([
17386   'type',
17387   '  TObject = class end;',
17388   '  THelper = class helper for TObject',
17389   '  end;',
17390   'begin',
17391   '  with THelper do ;',
17392   '']);
17393   CheckResolverException(sHelpersCannotBeUsedAsTypes,nHelpersCannotBeUsedAsTypes);
17394 end;
17395 
17396 procedure TTestResolver.TestClassHelper_AsTypeFail;
17397 begin
17398   StartProgram(false);
17399   Add([
17400   'type',
17401   '  TObject = class end;',
17402   '  THelper = class helper for TObject',
17403   '  end;',
17404   'var h: THelper;',
17405   'begin',
17406   '']);
17407   CheckResolverException(sHelpersCannotBeUsedAsTypes,nHelpersCannotBeUsedAsTypes);
17408 end;
17409 
17410 procedure TTestResolver.TestClassHelper_WithDo;
17411 var
17412   aMarker: PSrcMarker;
17413   Elements: TFPList;
17414   ActualWith, ExpectedWith: Boolean;
17415   i: Integer;
17416   El: TPasElement;
17417   Ref: TResolvedReference;
17418 begin
17419   StartProgram(false);
17420   Add([
17421   'type',
17422   '  TObject = class end;',
17423   '  TBird = class',
17424   '    procedure Run;',
17425   '  end;',
17426   '  THelper = class helper for TBird',
17427   '    procedure Foo(w: word = 1);',
17428   '  end;',
17429   'procedure TBird.Run;',
17430   'var b: TBird;',
17431   'begin',
17432   '  b.{#a1_not}Foo;',
17433   '  b.{#b1_not}Foo();',
17434   '  b.{#c1_not}Foo(2);',
17435   '  with b do begin',
17436   '    {#d1_with}Foo;',
17437   '    {#e1_with}Foo();',
17438   '    {#f1_with}Foo(3);',
17439   '  end;',
17440   'end;',
17441   'procedure THelper.Foo(w: word);',
17442   'var b: TBird;',
17443   'begin',
17444   '  b.{#a2_not}Foo;',
17445   '  b.{#b2_not}Foo();',
17446   '  b.{#c2_not}Foo(2);',
17447   '  with b do begin',
17448   '    {#d2_with}Foo;',
17449   '    {#e2_with}Foo();',
17450   '    {#f2_with}Foo(3);',
17451   '  end;',
17452   'end;',
17453   'var b: TBird;',
17454   'begin',
17455   '  b.{#a3_not}Foo;',
17456   '  b.{#b3_not}Foo();',
17457   '  b.{#c3_not}Foo(4);',
17458   '  with b do begin',
17459   '    {#d3_with}Foo;',
17460   '    {#e3_with}Foo();',
17461   '    {#f3_with}Foo(5);',
17462   '  end;',
17463   '']);
17464   ParseProgram;
17465 
17466   aMarker:=FirstSrcMarker;
17467   while aMarker<>nil do
17468     begin
17469     //writeln('TTestResolver.TestClassHelper_WithDo ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
17470     Elements:=FindElementsAt(aMarker);
17471     try
17472       ActualWith:=false;
17473       for i:=0 to Elements.Count-1 do
17474         begin
17475         El:=TPasElement(Elements[i]);
17476         writeln('TTestResolver.TestClassHelper_WithDo ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
17477         if not (El.CustomData is TResolvedReference) then continue;
17478         Ref:=TResolvedReference(El.CustomData);
17479         if Ref.WithExprScope<>nil then
17480           ActualWith:=true;
17481         break;
17482         end;
17483       ExpectedWith:=RightStr(aMarker^.Identifier,5)='_with';
17484       if ActualWith<>ExpectedWith then
17485         if ExpectedWith then
17486           RaiseErrorAtSrcMarker('expected Ref.WithExprScope<>nil at "#'+aMarker^.Identifier+'"',aMarker)
17487         else
17488           RaiseErrorAtSrcMarker('expected Ref.WithExprScope=nil at "#'+aMarker^.Identifier+'"',aMarker);
17489     finally
17490       Elements.Free;
17491     end;
17492     aMarker:=aMarker^.Next;
17493     end;
17494 end;
17495 
17496 procedure TTestResolver.TestClassHelper_ClassMethod;
17497 begin
17498   StartProgram(false);
17499   Add([
17500   'type',
17501   '  TObject = class end;',
17502   '  THelper = class helper for TObject',
17503   '    class procedure Fly(w: word = 1);',
17504   '    class procedure Run(w: word = 1); static;',
17505   '  end;',
17506   'class procedure THelper.Fly(w: word = 1);',
17507   'begin',
17508   '  Fly;',
17509   '  Fly();',
17510   '  Run;',
17511   '  Run();',
17512   '  Self.Fly;',
17513   '  Self.Fly();',
17514   '  Self.Run;',
17515   '  Self.Run();',
17516   '  with Self do begin',
17517   '    Fly;',
17518   '    Fly();',
17519   '    Run;',
17520   '    Run();',
17521   '  end;',
17522   'end;',
17523   'class procedure THelper.Run(w: word = 1);',
17524   'begin',
17525   '  Fly;',
17526   '  Fly();',
17527   '  Run;',
17528   '  Run();',
17529   'end;',
17530   'var o: TObject;',
17531   'begin',
17532   '  o.Fly;',
17533   '  o.Fly();',
17534   '  o.Run;',
17535   '  o.Run();',
17536   '  with o do begin',
17537   '    Fly;',
17538   '    Fly();',
17539   '    Run;',
17540   '    Run();',
17541   '  end;',
17542   '  TObject.Fly;',
17543   '  TObject.Fly();',
17544   '  TObject.Run;',
17545   '  TObject.Run();',
17546   '  with TObject do begin',
17547   '    Fly;',
17548   '    Fly();',
17549   '    Run;',
17550   '    Run();',
17551   '  end;',
17552   '']);
17553   ParseProgram;
17554 end;
17555 
17556 procedure TTestResolver.TestClassHelper_Enumerator;
17557 begin
17558   StartProgram(false);
17559   Add([
17560   'type',
17561   '  TObject = class end;',
17562   '  TItem = TObject;',
17563   '  TEnumerator = class',
17564   '    FCurrent: TItem;',
17565   '    property Current: TItem read FCurrent;',
17566   '    function MoveNext: boolean;',
17567   '  end;',
17568   '  TBird = class',
17569   '    FItems: array of TItem;',
17570   '  end;',
17571   '  TBirdHelper = class helper for TBird',
17572   '    function GetEnumerator: TEnumerator;',
17573   '  end;',
17574   'function TEnumerator.MoveNext: boolean;',
17575   'begin',
17576   'end;',
17577   'function TBirdHelper.GetEnumerator: TEnumerator;',
17578   'begin',
17579   '  Result.FCurrent:=FItems[0];',
17580   '  Result.FCurrent:=Self.FItems[0];',
17581   'end;',
17582   'var',
17583   '  b: TBird;',
17584   '  i: TItem;',
17585   '  {#i2}i2: TItem;',
17586   'begin',
17587   '  for i in b do {@i2}i2:=i;']);
17588   ParseProgram;
17589 end;
17590 
17591 procedure TTestResolver.TestClassHelper_FromUnitInterface;
17592 begin
17593   AddModuleWithIntfImplSrc('unit2.pas',
17594     LinesToStr([
17595     'type',
17596     '  TObject = class',
17597     '  public',
17598     '    Id: word;',
17599     '    FSize: string;',
17600     '  end;',
17601     '  TOb21Helper = class helper for TObject',
17602     '    property Size: string read FSize write FSize;',
17603     '  end;',
17604     '']),
17605     '');
17606   AddModuleWithIntfImplSrc('unit3.pas',
17607     LinesToStr([
17608     'uses unit2;',
17609     'type',
17610     '  TOb3Helper = class helper for TObject',
17611     '    property Size: word read ID write ID;',
17612     '  end;',
17613     '']),
17614     '');
17615   StartProgram(true);
17616   Add([
17617   'uses unit2, unit3;',
17618   'var o: TObject;',
17619   'begin',
17620   '  o.Size:=3;', // last unit wins
17621   '  o.Size:=o.Size;']);
17622   ParseProgram;
17623 end;
17624 
17625 procedure TTestResolver.TestClassHelper_Constructor_NewInstance;
17626 var
17627   aMarker: PSrcMarker;
17628   Elements: TFPList;
17629   i: Integer;
17630   El: TPasElement;
17631   Ref: TResolvedReference;
17632   ActualNewInstance, ActualImplicitCallWithoutParams: Boolean;
17633 begin
17634   StartProgram(false);
17635   Add([
17636   'type',
17637   '  TObject = class',
17638   '  end;',
17639   '  THelper = class helper for TObject',
17640   '    constructor Create;',
17641   '    class function DoSome: TObject;',
17642   '  end;',
17643   'constructor THelper.Create;',
17644   'begin',
17645   '  {#a}Create; // normal call',
17646   '  TObject.{#b}Create; // new instance',
17647   'end;',
17648   'class function THelper.DoSome: TObject;',
17649   'begin',
17650   '  Result:={#c}Create; // new instance',
17651   'end;',
17652   'var',
17653   '  o: TObject;',
17654   'begin',
17655   '  TObject.{#p}Create; // new object',
17656   '  o:=TObject.{#q}Create; // new object',
17657   '  with TObject do begin',
17658   '    {#r}Create; // new object',
17659   '    o:={#s}Create; // new object',
17660   '  end;',
17661   '  o.{#t}Create; // normal call',
17662   '  o:=o.{#u}Create; // normal call',
17663   '  with o do begin',
17664   '    {#v}Create; // normal call',
17665   '    o:={#w}Create; // normal call',
17666   '  end;',
17667   '']);
17668   ParseProgram;
17669   aMarker:=FirstSrcMarker;
17670   while aMarker<>nil do
17671     begin
17672     //writeln('TTestResolver.TestClassHelper_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
17673     Elements:=FindElementsAt(aMarker);
17674     try
17675       ActualNewInstance:=false;
17676       ActualImplicitCallWithoutParams:=false;
17677       for i:=0 to Elements.Count-1 do
17678         begin
17679         El:=TPasElement(Elements[i]);
17680         //writeln('TTestResolver.TestClassHelper_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
17681         if not (El.CustomData is TResolvedReference) then continue;
17682         Ref:=TResolvedReference(El.CustomData);
17683         if not (Ref.Declaration is TPasProcedure) then continue;
17684         //writeln('TTestResolver.TestClassHelper_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
17685         if (Ref.Declaration is TPasConstructor) then
17686           ActualNewInstance:=rrfNewInstance in Ref.Flags;
17687         ActualImplicitCallWithoutParams:=rrfImplicitCallWithoutParams in Ref.Flags;
17688         break;
17689         end;
17690       if not ActualImplicitCallWithoutParams then
17691         RaiseErrorAtSrcMarker('expected implicit call at "#'+aMarker^.Identifier+', but got function ref"',aMarker);
17692       case aMarker^.Identifier of
17693       'a','t','u','v','w':// should be normal call
17694         if ActualNewInstance then
17695           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
17696       else // should be newinstance
17697         if not ActualNewInstance then
17698           RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
17699       end;
17700     finally
17701       Elements.Free;
17702     end;
17703     aMarker:=aMarker^.Next;
17704     end;
17705 end;
17706 
17707 procedure TTestResolver.TestClassHelper_ReintroduceHides_CallFail;
17708 begin
17709   StartProgram(false);
17710   Add([
17711   'type',
17712   '  TObject = class',
17713   '    constructor Create(o: tobject);',
17714   '  end;',
17715   '  TBird = class helper for TObject',
17716   '    constructor Create(i: longint); reintroduce;',
17717   '  end;',
17718   'constructor tobject.Create(o: tobject); begin end;',
17719   'constructor tbird.Create(i: longint); begin end;',
17720   'var o: TObject;',
17721   'begin',
17722   '  o:=TObject.Create(nil);',
17723   '']);
17724   CheckResolverException('Incompatible type arg no. 1: Got "Nil", expected "Longint"',
17725     nIncompatibleTypeArgNo);
17726 end;
17727 
17728 procedure TTestResolver.TestClassHelper_DefaultProperty;
17729 begin
17730   StartProgram(false);
17731   Add([
17732   'type',
17733   '  TObject = class',
17734   '    function GetB(Index: longint): longint;',
17735   '    procedure SetB(Index: longint; Value: longint);',
17736   '  end;',
17737   '  THelper = class helper for TObject',
17738   '    property B[Index: longint]: longint read GetB write SetB; default;',
17739   '  end;',
17740   'function TObject.GetB(Index: longint): longint;',
17741   'begin',
17742   'end;',
17743   'procedure TObject.SetB(Index: longint; Value: longint);',
17744   'begin',
17745   '  if Value=Self[Index] then ;',
17746   '  Self[Index]:=Value;',
17747   'end;',
17748   'var o: TObject;',
17749   'begin',
17750   '  o[3]:=4;',
17751   '  if o[5]=6 then;',
17752   '  if 7=o[8] then;',
17753   '']);
17754   ParseProgram;
17755 end;
17756 
17757 procedure TTestResolver.TestClassHelper_DefaultClassProperty;
17758 begin
17759   StartProgram(false);
17760   Add([
17761   'type',
17762   '  TClass = class of TObject;',
17763   '  TObject = class',
17764   '    class function GetB(Index: longint): longint; static;',
17765   '    class procedure SetB(Index: longint; Value: longint); static;',
17766   '  end;',
17767   '  THelper = class helper for TObject',
17768   '    class property B[Index: longint]: longint read GetB write SetB; default;',
17769   '  end;',
17770   'class function TObject.GetB(Index: longint): longint;',
17771   'begin',
17772   'end;',
17773   'class procedure TObject.SetB(Index: longint; Value: longint);',
17774   'begin',
17775   '  if Value=TObject[Index] then ;',
17776   '  TObject[Index]:=Value;',
17777   'end;',
17778   'var c: TClass;',
17779   'begin',
17780   '  c[3]:=4;',
17781   '  if c[5]=6 then;',
17782   '  if 7=c[8] then;',
17783   '']);
17784   ParseProgram;
17785 end;
17786 
17787 procedure TTestResolver.TestClassHelper_MultiHelpers;
17788 begin
17789   StartProgram(false);
17790   Add([
17791   '{$modeswitch multihelpers}',
17792   'type',
17793   '  TObject = class',
17794   '  end;',
17795   '  TFlyHelper = class helper for TObject',
17796   '    procedure {#Fly}Fly;',
17797   '    procedure {#FlyMove}Move;',
17798   '  end;',
17799   '  TRunHelper = class helper for TObject',
17800   '    procedure {#Run}Run;',
17801   '    procedure {#RunMove}Move;',
17802   '    procedure {#RunBack}Back;',
17803   '  end;',
17804   '  TSwimHelper = class helper for TObject',
17805   '    procedure {#Swim}Swim;',
17806   '    procedure {#SwimBack}Back;',
17807   '  end;',
17808   'procedure TFlyHelper.Fly; begin end;',
17809   'procedure TFlyHelper.Move; begin end;',
17810   'procedure TRunHelper.Run; begin end;',
17811   'procedure TRunHelper.Move; begin end;',
17812   'procedure TRunHelper.Back; begin end;',
17813   'procedure TSwimHelper.Swim; begin end;',
17814   'procedure TSwimHelper.Back; begin end;',
17815   'var o: TObject;',
17816   'begin',
17817   '  o.{@Fly}Fly;',
17818   '  o.{@Run}Run;',
17819   '  o.{@Swim}Swim;',
17820   '  o.{@RunMove}Move;',
17821   '  o.{@SwimBack}Back;',
17822   '']);
17823   ParseProgram;
17824 end;
17825 
17826 procedure TTestResolver.TestRecordHelper;
17827 begin
17828   StartProgram(false);
17829   Add([
17830   '{$mode delphi}',
17831   'type',
17832   '  TProc = procedure of object;',
17833   '  TRec = record',
17834   '    x: word;',
17835   '  end;',
17836   '  TRecHelper = record helper for TRec',
17837   '  type T = word;',
17838   '  const',
17839   '    c: T = 3;',
17840   '    k: T = 4;',
17841   '  class var',
17842   '    v: T;',
17843   '    w: T;',
17844   '    procedure Fly;',
17845   '  end;',
17846   '  TAnt = word;',
17847   '  TAntHelper = record helper for TAnt',
17848   '  end;',
17849   'procedure TRecHelper.Fly;',
17850   'var',
17851   '  r: TRec;',
17852   '  p: TProc;',
17853   'begin',
17854   '  Self:=r;',
17855   '  r:=Self;',
17856   '  c:=v+x;',
17857   '  x:=k+w;',
17858   '  p:=Fly;',
17859   'end;',
17860   'var',
17861   '  r: TRec;',
17862   '  p: TProc;',
17863   'begin',
17864   '  p:=r.Fly;',
17865   '']);
17866   ParseProgram;
17867 end;
17868 
17869 procedure TTestResolver.TestRecordHelper_ForByteFail;
17870 begin
17871   StartProgram(false);
17872   Add([
17873   '{$mode objfpc}',
17874   'type',
17875   '  TRecHelper = record helper for byte',
17876   '    class var Glob: word;',
17877   '  end;',
17878   'begin',
17879   '']);
17880   CheckResolverException('Type "Byte" cannot be extended by a record helper',nTypeXCannotBeExtendedByARecordHelper);
17881 end;
17882 
17883 procedure TTestResolver.TestRecordHelper_ClassNonStaticFail;
17884 begin
17885   StartProgram(false);
17886   Add([
17887   '{$mode delphi}',
17888   'type',
17889   '  TRec = record',
17890   '    x: word;',
17891   '  end;',
17892   '  TRecHelper = record helper for TRec',
17893   '    class procedure Fly;',
17894   '  end;',
17895   'class procedure TRecHelper.Fly;',
17896   'begin',
17897   'end;',
17898   'begin',
17899   '']);
17900   CheckResolverException('Class methods must be static in record helper',nClassMethodsMustBeStaticInX);
17901 end;
17902 
17903 procedure TTestResolver.TestRecordHelper_InheritedObjFPC;
17904 begin
17905   StartProgram(false);
17906   Add([
17907   '{$mode objfpc}',
17908   '{$modeswitch advancedrecords}',
17909   'type',
17910   '  TRec = record',
17911   '    procedure {#TRec_Fly}Fly;',
17912   '  end;',
17913   '  TRecHelper = record helper for TRec',
17914   '    procedure {#TRecHelper_Fly}Fly;',
17915   '    procedure {#TRecHelper_Walk}Walk;',
17916   '    procedure {#TRecHelper_Run}Run;',
17917   '  end;',
17918   '  TEagleHelper = record helper(TRecHelper) for TRec',
17919   '    procedure {#TEagleHelper_Fly}Fly;',
17920   '    procedure {#TEagleHelper_Run}Run;',
17921   '  end;',
17922   'procedure TRec.fly;',
17923   'begin',
17924   'end;',
17925   'procedure TRechelper.fly;',
17926   'begin',
17927   '  {@TRec_Fly}inherited;',
17928   '  inherited {@TRec_Fly}Fly;',
17929   'end;',
17930   'procedure TRechelper.walk;',
17931   'begin',
17932   '  inherited;', // ignore
17933   'end;',
17934   'procedure TRechelper.run;',
17935   'begin',
17936   '  inherited;', // ignore
17937   'end;',
17938   'procedure teagleHelper.fly;',
17939   'begin',
17940   '  {@TRec_Fly}inherited;',
17941   '  inherited {@TRec_Fly}Fly;',
17942   'end;',
17943   'procedure teagleHelper.run;',
17944   'begin',
17945   '  {@TRecHelper_Run}inherited;',
17946   '  inherited {@TRecHelper_Run}Run;',
17947   'end;',
17948   'var',
17949   '  r: TRec;',
17950   'begin',
17951   '  r.{@TEagleHelper_Fly}Fly;',
17952   '  r.{@TRecHelper_Walk}Walk;',
17953   '  r.{@TEagleHelper_Run}Run;',
17954   '']);
17955   ParseProgram;
17956 end;
17957 
17958 procedure TTestResolver.TestRecordHelper_Constructor_NewInstance;
17959 var
17960   aMarker: PSrcMarker;
17961   Elements: TFPList;
17962   ActualNewInstance: Boolean;
17963   i: Integer;
17964   El: TPasElement;
17965   Ref: TResolvedReference;
17966 begin
17967   StartProgram(false);
17968   Add([
17969   '{$modeswitch advancedrecords}',
17970   '{$modeswitch typehelpers}',
17971   'type',
17972   '  TRec = record',
17973   '    constructor Create(w: word);',
17974   '    class function DoSome: TRec; static;',
17975   '  end;',
17976   'constructor TRec.Create(w: word);',
17977   'begin',
17978   '  {#a}Create(1); // normal call',
17979   '  TRec.{#b}Create(2); // new instance',
17980   'end;',
17981   'class function TRec.DoSome: TRec;',
17982   'begin',
17983   '  Result:={#c}Create(3); // new instance',
17984   'end;',
17985   'var',
17986   '  r: TRec;',
17987   'begin',
17988   '  TRec.{#p}Create(4); // new object',
17989   '  r:=TRec.{#q}Create(5); // new object',
17990   '  with TRec do begin',
17991   '    {#r}Create(6); // new object',
17992   '    r:={#s}Create(7); // new object',
17993   '  end;',
17994   '  r.{#t}Create(8); // normal call',
17995   '  r:=r.{#u}Create(9); // normal call',
17996   '  with r do begin',
17997   '    {#v}Create(10); // normal call',
17998   '    r:={#w}Create(11); // normal call',
17999   '  end;',
18000   '']);
18001   ParseProgram;
18002   aMarker:=FirstSrcMarker;
18003   while aMarker<>nil do
18004     begin
18005     //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
18006     Elements:=FindElementsAt(aMarker);
18007     try
18008       ActualNewInstance:=false;
18009       for i:=0 to Elements.Count-1 do
18010         begin
18011         El:=TPasElement(Elements[i]);
18012         //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
18013         if not (El.CustomData is TResolvedReference) then continue;
18014         Ref:=TResolvedReference(El.CustomData);
18015         if not (Ref.Declaration is TPasProcedure) then continue;
18016         //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
18017         if (Ref.Declaration is TPasConstructor) then
18018           ActualNewInstance:=rrfNewInstance in Ref.Flags;
18019         if rrfImplicitCallWithoutParams in Ref.Flags then
18020           RaiseErrorAtSrcMarker('unexpected implicit call at "#'+aMarker^.Identifier+' ref"',aMarker);
18021         break;
18022         end;
18023       case aMarker^.Identifier of
18024       'a','t','u','v','w':// should be normal call
18025         if ActualNewInstance then
18026           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
18027       else // should be newinstance
18028         if not ActualNewInstance then
18029           RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
18030       end;
18031     finally
18032       Elements.Free;
18033     end;
18034     aMarker:=aMarker^.Next;
18035     end;
18036 end;
18037 
18038 procedure TTestResolver.TestTypeHelper;
18039 begin
18040   StartProgram(false);
18041   Add([
18042   '{$modeswitch typehelpers}',
18043   'type',
18044   '  TStringHelper = type helper for string',
18045   '  end;',
18046   '  TCaption = string;',
18047   '  TCapHelper = type helper(TStringHelper) for TCaption',
18048   '    procedure Fly;',
18049   '  end;',
18050   '  TProc = procedure of object;',
18051   'procedure TCapHelper.Fly; begin end;',
18052   'var',
18053   '  c: TCaption;',
18054   '  p: TProc;',
18055   'begin',
18056   '  c.Fly;',
18057   '  p:=@c.Fly;',
18058   '']);
18059   ParseProgram;
18060 end;
18061 
18062 procedure TTestResolver.TestTypeHelper_HelperForProcTypeFail;
18063 begin
18064   StartProgram(false);
18065   Add([
18066   '{$modeswitch typehelpers}',
18067   'type',
18068   '  TProc = procedure;',
18069   '  THelper = type helper for TProc',
18070   '  end;',
18071   'begin',
18072   '']);
18073   CheckResolverException('Type "TProc" cannot be extended by a type helper',
18074     nTypeXCannotBeExtendedByATypeHelper);
18075 end;
18076 
18077 procedure TTestResolver.TestTypeHelper_DefaultPropertyFail;
18078 begin
18079   StartProgram(false);
18080   Add([
18081   '{$modeswitch typehelpers}',
18082   'type',
18083   '  TStringHelper = type helper for string',
18084   '  end;',
18085   '  TCaption = string;',
18086   '  TCapHelper = type helper(TStringHelper) for TCaption',
18087   '    function GetItems(Index: boolean): boolean;',
18088   '    property Items[Index: boolean]: boolean read GetItems; default;',
18089   '  end;',
18090   'function TCapHelper.GetItems(Index: boolean): boolean; begin end;',
18091   'begin',
18092   '']);
18093   CheckResolverException('Default property not allowed in helper for TCaption',
18094     nDefaultPropertyNotAllowedInHelperForX);
18095 end;
18096 
18097 procedure TTestResolver.TestTypeHelper_Enum;
18098 begin
18099   StartProgram(false);
18100   Add([
18101   '{$modeswitch typehelpers}',
18102   'type',
18103   '  TFlag = (Red, Green, Blue);',
18104   '  THelper = type helper for TFlag',
18105   '    function toString: string;',
18106   '    class procedure Fly; static;',
18107   '  end;',
18108   'function THelper.toString: string;',
18109   'begin',
18110   '  Self:=Red;',
18111   '  if Self=TFlag.Blue then ;',
18112   '  Result:=str(Self);',
18113   'end;',
18114   'class procedure THelper.Fly;',
18115   'begin',
18116   'end;',
18117   'var',
18118   '  f: TFlag;',
18119   'begin',
18120   '  f.toString;',
18121   '  green.toString;',
18122   '  TFlag.green.toString;',
18123   '  TFlag.Fly;',
18124   '']);
18125   ParseProgram;
18126 end;
18127 
18128 procedure TTestResolver.TestTypeHelper_EnumDotValueFail;
18129 begin
18130   StartProgram(false);
18131   Add([
18132   '{$modeswitch typehelpers}',
18133   'type',
18134   '  TFlag = (Red, Green, Blue);',
18135   '  THelper = type helper for TFlag',
18136   '  end;',
18137   'var',
18138   '  f: TFlag;',
18139   'begin',
18140   '  f:=f.red;',
18141   '']);
18142   CheckResolverException('identifier not found "red"',nIdentifierNotFound);
18143 end;
18144 
18145 procedure TTestResolver.TestTypeHelper_EnumHelperDotProcFail;
18146 begin
18147   StartProgram(false);
18148   Add([
18149   '{$modeswitch typehelpers}',
18150   'type',
18151   '  TFlag = (Red, Green, Blue);',
18152   '  THelper = type helper for TFlag',
18153   '    procedure Fly;',
18154   '  end;',
18155   'procedure THelper.Fly;',
18156   'begin',
18157   'end;',
18158   'begin',
18159   '  TFlag.Fly;',
18160   '']);
18161   CheckResolverException('Instance member "Fly" inaccessible here',
18162     nInstanceMemberXInaccessible);
18163 end;
18164 
18165 procedure TTestResolver.TestTypeHelper_Set;
18166 begin
18167   StartProgram(false);
18168   Add([
18169   '{$modeswitch typehelpers}',
18170   'type',
18171   '  TEnum = (Red, Green, Blue);',
18172   '  TSetOfEnum = set of TEnum;',
18173   '  THelper = type helper for TSetOfEnum',
18174   '    procedure Fly;',
18175   '    class procedure Run; static;',
18176   '  end;',
18177   'procedure THelper.Fly;',
18178   'begin',
18179   '  Self:=[];',
18180   '  Self:=[green];',
18181   '  Include(Self,blue);',
18182   'end;',
18183   'class procedure THelper.Run;',
18184   'begin',
18185   'end;',
18186   'var s: TSetOfEnum;',
18187   'begin',
18188   '  s.Fly;',
18189   //'  with s do Fly;',
18190   '  TSetOfEnum.Run;',
18191   //'  with TSetOfEnum do Run;',
18192   //'  [green].Fly', not supported
18193   '']);
18194   ParseProgram;
18195 end;
18196 
18197 procedure TTestResolver.TestTypeHelper_Enumerator;
18198 begin
18199   StartProgram(false);
18200   Add([
18201   '{$modeswitch typehelpers}',
18202   'type',
18203   '  TObject = class end;',
18204   '  TItem = byte;',
18205   '  TEnumerator = class',
18206   '    FCurrent: TItem;',
18207   '    property Current: TItem read FCurrent;',
18208   '    function MoveNext: boolean;',
18209   '  end;',
18210   '  TWordHelper = type helper for Word',
18211   '    function GetEnumerator: TEnumerator;',
18212   '  end;',
18213   'function TEnumerator.MoveNext: boolean;',
18214   'begin',
18215   'end;',
18216   'function TWordHelper.GetEnumerator: TEnumerator;',
18217   'begin',
18218   '  if Self=2 then ;',
18219   '  Self:=Self+3;',
18220   'end;',
18221   'var',
18222   '  w: word;',
18223   '  i: TItem;',
18224   '  {#i2}i2: TItem;',
18225   'begin',
18226   '  w.GetEnumerator;',
18227   '  for i in w do {@i2}i2:=i;']);
18228   ParseProgram;
18229 end;
18230 
18231 procedure TTestResolver.TestTypeHelper_String;
18232 begin
18233   StartProgram(false);
18234   Add([
18235   '{$modeswitch typehelpers}',
18236   'type',
18237   '  TStringHelper = type helper for String',
18238   '    procedure DoIt;',
18239   '  end;',
18240   '  TCharHelper = type helper for char',
18241   '    procedure Fly;',
18242   '  end;',
18243   'procedure TStringHelper.DoIt;',
18244   'begin',
18245   '  Self[1]:=Self[2];',
18246   'end;',
18247   'procedure TCharHelper.Fly;',
18248   'begin',
18249   '  Self:=''c'';',
18250   '  Self:=Self;',
18251   'end;',
18252   'begin',
18253   '  ''abc''.DoIt;',
18254   '  ''xyz''.DoIt();',
18255   '  ''c''.Fly;',
18256   '']);
18257   ParseProgram;
18258 end;
18259 
18260 procedure TTestResolver.TestTypeHelper_StringOtherUnit;
18261 begin
18262   AddModuleWithIntfImplSrc('unit2.pas',
18263     LinesToStr([
18264     '{$modeswitch typehelpers}',
18265     'type',
18266     '  TStringHelper = type helper for String',
18267     '    procedure DoIt;',
18268     '  end;',
18269     '  TCharHelper = type helper for char',
18270     '    procedure Fly;',
18271     '  end;',
18272     '']),
18273     LinesToStr([
18274     'procedure TStringHelper.DoIt;',
18275     'begin',
18276     '  Self[1]:=Self[2];',
18277     'end;',
18278     'procedure TCharHelper.Fly;',
18279     'begin',
18280     '  Self:=''c'';',
18281     '  Self:=Self;',
18282     'end;',
18283     '']));
18284   StartProgram(true);
18285   Add([
18286   'uses unit2;',
18287   'var s: string;',
18288   'begin',
18289   '  ''abc''.DoIt;',
18290   '  ''xyz''.DoIt();',
18291   '  ''c''.Fly;',
18292   '  s.DoIt;',
18293   '']);
18294   ParseProgram;
18295 end;
18296 
18297 procedure TTestResolver.TestTypeHelper_Boolean;
18298 begin
18299   StartProgram(false);
18300   Add([
18301   '{$modeswitch typehelpers}',
18302   'type',
18303   '  THelper = type helper for boolean',
18304   '    procedure DoIt;',
18305   '  end;',
18306   'procedure THelper.DoIt;',
18307   'begin',
18308   '  Self:=not Self;',
18309   'end;',
18310   'begin',
18311   '  false.DoIt;',
18312   '  true.DoIt();']);
18313   ParseProgram;
18314 end;
18315 
18316 procedure TTestResolver.TestTypeHelper_Double;
18317 begin
18318   StartProgram(false);
18319   Add([
18320   '{$modeswitch typehelpers}',
18321   'type',
18322   '  Float = double;',
18323   '  THelper = type helper for float',
18324   '    const NPI = 3.141592;',
18325   '    function ToStr: String;',
18326   '  end;',
18327   'function THelper.ToStr: String;',
18328   'begin',
18329   'end;',
18330   'var',
18331   '  a,b: Float;',
18332   '  s: string;',
18333   'begin',
18334   '  s:=(a * b.NPI).ToStr;',
18335   '  s:=(a * float.NPI).ToStr;',
18336   '  s:=float.NPI.ToStr;',
18337   '  s:=3.2.ToStr;',
18338   '']);
18339   ParseProgram;
18340 end;
18341 
18342 procedure TTestResolver.TestTypeHelper_DoubleAlias;
18343 begin
18344   StartProgram(false);
18345   Add([
18346   '{$modeswitch typehelpers}',
18347   'type',
18348   '  Float = type double;',
18349   '  THelper = type helper for float',
18350   '    const NPI = 3.141592;',
18351   '    function ToStr: String;',
18352   '  end;',
18353   'function THelper.ToStr: String;',
18354   'begin',
18355   'end;',
18356   'var',
18357   '  a,b: Float;',
18358   '  s: string;',
18359   'begin',
18360   '  s:=(a * b.NPI).ToStr;',
18361   '  s:=(a * float.NPI).ToStr;',
18362   '']);
18363   ParseProgram;
18364 end;
18365 
18366 procedure TTestResolver.TestTypeHelper_Constructor_NewInstance;
18367 var
18368   aMarker: PSrcMarker;
18369   Elements: TFPList;
18370   ActualNewInstance: Boolean;
18371   i: Integer;
18372   El: TPasElement;
18373   Ref: TResolvedReference;
18374 begin
18375   StartProgram(false);
18376   Add([
18377   '{$modeswitch typehelpers}',
18378   'type',
18379   '  TInt = type word;',
18380   '  THelper = type helper for TInt',
18381   '    constructor Create(w: TInt);',
18382   '    class function DoSome: TInt; static;',
18383   '  end;',
18384   'constructor THelper.Create(w: TInt);',
18385   'begin',
18386   '  {#a}Create(1); // normal call',
18387   '  TInt.{#b}Create(2); // new instance',
18388   'end;',
18389   'class function THelper.DoSome: TInt;',
18390   'begin',
18391   '  Result:={#c}Create(3); // new instance',
18392   'end;',
18393   'var',
18394   '  r: TInt;',
18395   'begin',
18396   '  TInt.{#p}Create(4); // new object',
18397   '  r:=TInt.{#q}Create(5); // new object',
18398   '  with TInt do begin',
18399   '    {#r}Create(6); // new object',
18400   '    r:={#s}Create(7); // new object',
18401   '  end;',
18402   '  r.{#t}Create(8); // normal call',
18403   '  r:=r.{#u}Create(9); // normal call',
18404   '  with r do begin',
18405   '    {#v}Create(10); // normal call',
18406   '    r:={#w}Create(11); // normal call',
18407   '  end;',
18408   '']);
18409   ParseProgram;
18410   aMarker:=FirstSrcMarker;
18411   while aMarker<>nil do
18412     begin
18413     //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',aMarker^.StartCol,' ',aMarker^.EndCol);
18414     Elements:=FindElementsAt(aMarker);
18415     try
18416       ActualNewInstance:=false;
18417       for i:=0 to Elements.Count-1 do
18418         begin
18419         El:=TPasElement(Elements[i]);
18420         //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',aMarker^.Identifier,' ',i,'/',Elements.Count,' El=',GetObjName(El),' ',GetObjName(El.CustomData));
18421         if not (El.CustomData is TResolvedReference) then continue;
18422         Ref:=TResolvedReference(El.CustomData);
18423         if not (Ref.Declaration is TPasProcedure) then continue;
18424         //writeln('TTestResolver.TestAdvRecord_Constructor_NewInstance ',GetObjName(Ref.Declaration),' rrfNewInstance=',rrfNewInstance in Ref.Flags);
18425         if (Ref.Declaration is TPasConstructor) then
18426           ActualNewInstance:=rrfNewInstance in Ref.Flags;
18427         if rrfImplicitCallWithoutParams in Ref.Flags then
18428           RaiseErrorAtSrcMarker('unexpected implicit call at "#'+aMarker^.Identifier+' ref"',aMarker);
18429         break;
18430         end;
18431       case aMarker^.Identifier of
18432       'a','t','u','v','w':// should be normal call
18433         if ActualNewInstance then
18434           RaiseErrorAtSrcMarker('expected normal call at "#'+aMarker^.Identifier+', but got newinstance"',aMarker);
18435       else // should be newinstance
18436         if not ActualNewInstance then
18437           RaiseErrorAtSrcMarker('expected newinstance at "#'+aMarker^.Identifier+', but got normal call"',aMarker);
18438       end;
18439     finally
18440       Elements.Free;
18441     end;
18442     aMarker:=aMarker^.Next;
18443     end;
18444 end;
18445 
18446 procedure TTestResolver.TestTypeHelper_Interface;
18447 begin
18448   StartProgram(false);
18449   Add([
18450   '{$modeswitch typehelpers}',
18451   'type',
18452   '  IUnknown = interface',
18453   '    function GetSizes(Index: word): word;',
18454   '    procedure SetSizes(Index: word; value: word);',
18455   '  end;',
18456   '  TObject = class(IUnknown)',
18457   '    function GetSizes(Index: word): word; virtual; abstract;',
18458   '    procedure SetSizes(Index: word; value: word); virtual; abstract;',
18459   '  end;',
18460   '  THelper = type helper for IUnknown',
18461   '    procedure Fly;',
18462   '    class procedure Run; static;',
18463   '    property Sizes[Index: word]: word read GetSizes write SetSizes; default;',
18464   '  end;',
18465   'var',
18466   '  i: IUnknown;',
18467   '  o: TObject;',
18468   'procedure THelper.Fly;',
18469   'begin',
18470   '  i:=Self;',
18471   '  o:=Self as TObject;',
18472   '  Self:=nil;',
18473   '  Self:=i;',
18474   '  Self:=o;',
18475   'end;',
18476   'class procedure THelper.Run;',
18477   'begin',
18478   'end;',
18479   'begin',
18480   '  i.Fly;',
18481   '  i.Fly();',
18482   '  i.Run;',
18483   '  i.Run();',
18484   '  i.Sizes[3]:=i.Sizes[4];',
18485   '  i[5]:=i[6];',
18486   '  IUnknown.Run;',
18487   '  IUnknown.Run();',
18488   '']);
18489   ParseProgram;
18490 end;
18491 
18492 procedure TTestResolver.TestTypeHelper_Interface_ConstructorFail;
18493 begin
18494   StartProgram(false);
18495   Add([
18496   '{$modeswitch typehelpers}',
18497   'type',
18498   '  IUnknown = interface',
18499   '  end;',
18500   '  THelper = type helper for IUnknown',
18501   '    constructor Fly;',
18502   '  end;',
18503   'constructor THelper.Fly;',
18504   'begin',
18505   'end;',
18506   'begin',
18507   '']);
18508   CheckResolverException('constructor is not supported',nXIsNotSupported);
18509 end;
18510 
18511 procedure TTestResolver.TestTypeHelper_TypeAliasType;
18512 begin
18513   StartProgram(false);
18514   Add([
18515   '{$modeswitch typehelpers}',
18516   'type',
18517   '  TEnum = type longint;',
18518   '  TIntHelper = type helper for longint',
18519   '    procedure Run;',
18520   '  end;',
18521   '  TEnumHelper = type helper for TEnum',
18522   '    procedure Fly;',
18523   '  end;',
18524   'procedure TIntHelper.Run;',
18525   'begin',
18526   'end;',
18527   'procedure TEnumHelper.Fly;',
18528   'begin',
18529   'end;',
18530   'var',
18531   '  e: TEnum;',
18532   '  i: longint;',
18533   'begin',
18534   '  i.Run;',
18535   '  e.Fly;',
18536   '  with i do Run;',
18537   '  with e do Fly;',
18538   '']);
18539   ParseProgram;
18540 end;
18541 
18542 procedure TTestResolver.TestAttributes_Globals;
18543 begin
18544   StartProgram(false);
18545   Add([
18546   '{$modeswitch prefixedattributes}',
18547   'type',
18548   '  TObject = class',
18549   '    constructor {#TObject_Create}Create;',
18550   '  end;',
18551   '  {#Custom}TCustomAttribute = class',
18552   '  end;',
18553   '  {#Red}RedAttribute = class(TCustomAttribute)',
18554   '    constructor {#Red_A}Create(Id: word = 3; Deep: boolean = false); overload;',
18555   '    constructor {#Red_B}Create(Size: double); overload;',
18556   '  end;',
18557   '  Red = word;',
18558   'constructor TObject.Create; begin end;',
18559   'constructor RedAttribute.Create(Id: word; Deep: boolean); begin end;',
18560   'constructor RedAttribute.Create(Size: double); begin end;',
18561   'var',
18562   '  [{#Attr__Custom__TObject_Create}TCustom]',
18563   '  [{#Attr__Red__Red_A__1}Red,afile.{#Attr__Red__Red_A__2}Red]',
18564   '  o: TObject;',
18565   'const',
18566   '  [{#Attr__Red__Red_B}RedAttribute(1.3)]',
18567   '  c = 3;',
18568   'begin',
18569   '']);
18570   ParseProgram;
18571   CheckAttributeMarkers;
18572   CheckResolverUnexpectedHints;
18573 end;
18574 
18575 procedure TTestResolver.TestAttributes_NonConstParam_Fail;
18576 begin
18577   StartProgram(false);
18578   Add([
18579   '{$modeswitch prefixedattributes}',
18580   'type',
18581   '  TObject = class',
18582   '    constructor Create(w: word);',
18583   '  end;',
18584   '  TCustomAttribute = class',
18585   '  end;',
18586   'constructor TObject.Create(w: word);',
18587   'begin',
18588   'end;',
18589   'var',
18590   '  w: word;',
18591   '  [TCustom(w)]',
18592   '  o: TObject;',
18593   'begin',
18594   '']);
18595   CheckResolverException(sConstantExpressionExpected,nConstantExpressionExpected);
18596 end;
18597 
18598 procedure TTestResolver.TestAttributes_UnknownAttrWarning;
18599 begin
18600   StartProgram(false);
18601   Add([
18602   '{$modeswitch prefixedattributes}',
18603   'type',
18604   '  TObject = class',
18605   '  end;',
18606   '  TCustomAttribute = class',
18607   '  end;',
18608   'var',
18609   '  [Red]',
18610   '  o: TObject;',
18611   'begin',
18612   '']);
18613   ParseProgram;
18614   CheckResolverHint(mtWarning,nUnknownCustomAttributeX,'Unknown custom attribute "Red"');
18615 end;
18616 
18617 procedure TTestResolver.TestAttributes_Members;
18618 begin
18619   StartProgram(false);
18620   Add([
18621   '{$modeswitch prefixedattributes}',
18622   'type',
18623   '  TObject = class',
18624   '    constructor {#create}Create;',
18625   '  end;',
18626   '  {#custom}TCustomAttribute = class',
18627   '  end;',
18628   '  TMyClass = class',
18629   '    [{#attr__custom__create__cl}TCustom]',
18630   '    Field: word;',
18631   '  end;',
18632   '  TMyRecord = record',
18633   '    [{#attr__custom__create__rec}TCustom]',
18634   '    Field: word;',
18635   '  end;',
18636   'constructor TObject.Create;',
18637   'begin',
18638   'end;',
18639   'begin',
18640   '']);
18641   ParseProgram;
18642   CheckAttributeMarkers;
18643 end;
18644 
18645 initialization
18646   RegisterTests([TTestResolver]);
18647 
18648 end.
18649 
18650