refactor: use Exit(X) shorthand for Result-then-Exit early returns

Now that Exit(X) is supported (0f63626), replace the historical
'Result := X; Exit;' workaround with the Exit(X) function-result shorthand
across compiler, runtime, and stdlib (305 sites).

Only same-indentation pairs are merged: a 'Result := X;' immediately followed
by an 'Exit;' at the same indentation level. Sites where the trailing 'Exit;'
is less-indented than the assignment are left untouched — there the Exit
belongs to an enclosing for/else/if block, not to the assignment, so merging
would change control flow (e.g. the xor/and numeric-result branch in
uSemantic falling through to the Boolean-operand check). 14 such sites are
deliberately not converted.

Three converted sites sit inside a real try/finally (uSemantic overload/
generic resolution); each try body already contained bare Exit; statements
and its finally body is a plain local-list Free, so control flow is unchanged.
A new e2e test (TestRun_ExitValueThroughFinally) confirms Exit(X) from inside
a try/finally runs the finally body and returns the value.

Self-hosting fixpoint verified clean (stage-2 IR == stage-3 IR).
This commit is contained in:
Graeme Geldenhuys 2026-06-03 00:33:40 +01:00
parent 0f63626397
commit 99b7761bf4
20 changed files with 342 additions and 610 deletions

View file

@ -175,8 +175,7 @@ begin
Arg := ParamStr(I); Arg := ParamStr(I);
if (Length(Arg) >= 2) and (StrAt(Arg, 0) = Ord('-')) and (StrAt(Arg, 1) <> Ord('-')) then if (Length(Arg) >= 2) and (StrAt(Arg, 0) = Ord('-')) and (StrAt(Arg, 1) <> Ord('-')) then
begin begin
Result := True; Exit(True);
Exit;
end; end;
end; end;
end; end;

View file

@ -145,8 +145,7 @@ function IntByteSize(AType: TTypeDesc): Integer;
begin begin
if AType = nil then if AType = nil then
begin begin
Result := 4; Exit(4);
Exit;
end; end;
case AType.Kind of case AType.Kind of
tyByte, tyBoolean: Result := 1; tyByte, tyBoolean: Result := 1;
@ -165,8 +164,7 @@ function IsUnsignedInt(AType: TTypeDesc): Boolean;
begin begin
if AType = nil then if AType = nil then
begin begin
Result := False; Exit(False);
Exit;
end; end;
Result := AType.Kind in [tyByte, tyBoolean, tyWord, tyUInt32, tyUInt64, tyEnum]; Result := AType.Kind in [tyByte, tyBoolean, tyWord, tyUInt32, tyUInt64, tyEnum];
end; end;
@ -404,8 +402,7 @@ begin
T := Self.GlobalType(TIdentExpr(AExpr).Name); T := Self.GlobalType(TIdentExpr(AExpr).Name);
if T <> nil then if T <> nil then
begin begin
Result := T; Exit(T);
Exit;
end; end;
end; end;
Result := AExpr.ResolvedType; Result := AExpr.ResolvedType;

View file

@ -143,8 +143,7 @@ begin
for I := 0 to (AIndex - Seen) - 1 do for I := 0 to (AIndex - Seen) - 1 do
Entry := Pointer(Entry) + 16; { skip name + addr pair } Entry := Pointer(Entry) + 16; { skip name + addr pair }
EntName := Entry^; EntName := Entry^;
Result := string(PChar(EntName)); Exit(string(PChar(EntName)));
Exit;
end; end;
Seen := Seen + Local; Seen := Seen + Local;
end; end;
@ -238,8 +237,7 @@ var
begin begin
if (AFilters = nil) or (AFilters.Count = 0) then if (AFilters = nil) or (AFilters.Count = 0) then
begin begin
Result := True; Exit(True);
Exit;
end; end;
for I := 0 to AFilters.Count - 1 do for I := 0 to AFilters.Count - 1 do
begin begin
@ -248,8 +246,7 @@ begin
Continue; Continue;
if (FMethod = '') or (FMethod = AMethod) then if (FMethod = '') or (FMethod = AMethod) then
begin begin
Result := True; Exit(True);
Exit;
end; end;
end; end;
Result := False; Result := False;
@ -267,16 +264,14 @@ var
begin begin
if (AFilters = nil) or (AFilters.Count = 0) then if (AFilters = nil) or (AFilters.Count = 0) then
begin begin
Result := True; Exit(True);
Exit;
end; end;
for I := 0 to AFilters.Count - 1 do for I := 0 to AFilters.Count - 1 do
begin begin
SplitSuiteSpec(AFilters.Strings[I], FSuite, FMethod); SplitSuiteSpec(AFilters.Strings[I], FSuite, FMethod);
if FSuite = ASuite then if FSuite = ASuite then
begin begin
Result := True; Exit(True);
Exit;
end; end;
end; end;
Result := False; Result := False;

File diff suppressed because it is too large Load diff

View file

@ -223,8 +223,7 @@ var
begin begin
if AType = nil then if AType = nil then
begin begin
Result := 'Pointer'; Exit('Pointer');
Exit;
end; end;
case AType.Kind of case AType.Kind of
tyString: tyString:

View file

@ -194,8 +194,7 @@ begin
begin begin
Advance; { consume 'class' } Advance; { consume 'class' }
Expect(tkOf); Expect(tkOf);
Result := 'class of ' + Self.ParseTypeName; Exit('class of ' + Self.ParseTypeName);
Exit;
end; end;
if not Check(tkIdent) then if not Check(tkIdent) then
raise EParseError.Create(Format('Expected type name at line %d col %d in %s', raise EParseError.Create(Format('Expected type name at line %d col %d in %s',
@ -1860,38 +1859,32 @@ begin
if Check(tkIf) then if Check(tkIf) then
begin begin
Result := ParseIfStmt; Exit(ParseIfStmt);
Exit;
end; end;
if Check(tkWhile) then if Check(tkWhile) then
begin begin
Result := ParseWhileStmt; Exit(ParseWhileStmt);
Exit;
end; end;
if Check(tkRepeat) then if Check(tkRepeat) then
begin begin
Result := ParseRepeatStmt; Exit(ParseRepeatStmt);
Exit;
end; end;
if Check(tkFor) then if Check(tkFor) then
begin begin
Result := ParseForStmt; Exit(ParseForStmt);
Exit;
end; end;
if Check(tkTry) then if Check(tkTry) then
begin begin
Result := ParseTryStmt; Exit(ParseTryStmt);
Exit;
end; end;
if Check(tkRaise) then if Check(tkRaise) then
begin begin
Result := ParseRaiseStmt; Exit(ParseRaiseStmt);
Exit;
end; end;
if Check(tkExit) then if Check(tkExit) then
@ -1909,8 +1902,7 @@ begin
ExitS.Value := Self.ParseExpr; ExitS.Value := Self.ParseExpr;
Expect(tkRParen); Expect(tkRParen);
end; end;
Result := ExitS; Exit(ExitS);
Exit;
end; end;
if Check(tkBreak) then if Check(tkBreak) then
@ -1933,20 +1925,17 @@ begin
if Check(tkInherited) then if Check(tkInherited) then
begin begin
Result := ParseInheritedStmt; Exit(ParseInheritedStmt);
Exit;
end; end;
if Check(tkCase) then if Check(tkCase) then
begin begin
Result := ParseCaseStmt; Exit(ParseCaseStmt);
Exit;
end; end;
if Check(tkBegin) then if Check(tkBegin) then
begin begin
Result := ParseCompoundStmt; Exit(ParseCompoundStmt);
Exit;
end; end;
if not Check(tkIdent) then if not Check(tkIdent) then
@ -1976,8 +1965,7 @@ begin
SubAssign.Free; SubAssign.Free;
raise; raise;
end; end;
Result := SubAssign; Exit(SubAssign);
Exit;
end; end;
if Check(tkCaret) then if Check(tkCaret) then
@ -2148,8 +2136,7 @@ begin
MCall.Free; MCall.Free;
MCall := nil; MCall := nil;
FldAssign.Expr := ParseExpr; FldAssign.Expr := ParseExpr;
Result := FldAssign; Exit(FldAssign);
Exit;
end; end;
Result := MCall; Result := MCall;
end end
@ -2201,8 +2188,7 @@ begin
if not Check(tkRParen) then if not Check(tkRParen) then
ParseMethodCallArgList(MCall); ParseMethodCallArgList(MCall);
Expect(tkRParen); Expect(tkRParen);
Result := MCall; Exit(MCall);
Exit;
end; end;
FldNode := TFieldAccessExpr.Create; FldNode := TFieldAccessExpr.Create;
FldNode.Line := Line; FldNode.Line := Line;
@ -2222,8 +2208,7 @@ begin
TFieldAccessExpr(CastRcv).Base := nil; TFieldAccessExpr(CastRcv).Base := nil;
CastRcv.Free; CastRcv.Free;
FldAssign.Expr := ParseExpr; FldAssign.Expr := ParseExpr;
Result := FldAssign; Exit(FldAssign);
Exit;
end; end;
raise EParseError.Create(Format( raise EParseError.Create(Format(
'Expected method call or assignment after chain at line %d col %d in %s', 'Expected method call or assignment after chain at line %d col %d in %s',
@ -2291,8 +2276,7 @@ begin
if not Check(tkRParen) then if not Check(tkRParen) then
ParseMethodCallArgList(MCall); ParseMethodCallArgList(MCall);
Expect(tkRParen); Expect(tkRParen);
Result := MCall; Exit(MCall);
Exit;
end; end;
FldNode := TFieldAccessExpr.Create; FldNode := TFieldAccessExpr.Create;
FldNode.Line := Line; FldNode.Line := Line;
@ -2313,8 +2297,7 @@ begin
TFieldAccessExpr(CastRcv).Base := nil; { transfer ownership } TFieldAccessExpr(CastRcv).Base := nil; { transfer ownership }
CastRcv.Free; CastRcv.Free;
FldAssign.Expr := ParseExpr; FldAssign.Expr := ParseExpr;
Result := FldAssign; Exit(FldAssign);
Exit;
end; end;
{ No-arg method call: Func(...).Field treated as Func(...).Method } { No-arg method call: Func(...).Field treated as Func(...).Method }
if CastRcv is TFieldAccessExpr then if CastRcv is TFieldAccessExpr then
@ -2327,8 +2310,7 @@ begin
MCall.ObjExpr := TFieldAccessExpr(CastRcv).Base; MCall.ObjExpr := TFieldAccessExpr(CastRcv).Base;
TFieldAccessExpr(CastRcv).Base := nil; TFieldAccessExpr(CastRcv).Base := nil;
CastRcv.Free; CastRcv.Free;
Result := MCall; Exit(MCall);
Exit;
end; end;
raise EParseError.Create(Format( raise EParseError.Create(Format(
'Expected method call after typecast at line %d col %d in %s', 'Expected method call after typecast at line %d col %d in %s',
@ -2343,8 +2325,7 @@ begin
while FCallNode.Args.Count > 0 do while FCallNode.Args.Count > 0 do
Call.Args.Add(FCallNode.Args.Extract(FCallNode.Args.Items[0])); Call.Args.Add(FCallNode.Args.Extract(FCallNode.Args.Items[0]));
FCallNode.Free; FCallNode.Free;
Result := Call; Exit(Call);
Exit;
end; end;
Call := TProcCall.Create; Call := TProcCall.Create;
Call.Line := Line; Call.Line := Line;

View file

@ -248,8 +248,7 @@ var
begin begin
if SameText(AAttrName, ACanonical) then if SameText(AAttrName, ACanonical) then
begin begin
Result := True; Exit(True);
Exit;
end; end;
Suffix := ACanonical + 'Attribute'; Suffix := ACanonical + 'Attribute';
Result := SameText(AAttrName, Suffix); Result := SameText(AAttrName, Suffix);
@ -261,14 +260,12 @@ var
begin begin
if AAttrs = nil then if AAttrs = nil then
begin begin
Result := False; Exit(False);
Exit;
end; end;
for I := 0 to AAttrs.Count - 1 do for I := 0 to AAttrs.Count - 1 do
if AttrMatches(AAttrs.Strings[I], 'Weak') then if AttrMatches(AAttrs.Strings[I], 'Weak') then
begin begin
Result := True; Exit(True);
Exit;
end; end;
Result := False; Result := False;
end; end;
@ -279,14 +276,12 @@ var
begin begin
if AAttrs = nil then if AAttrs = nil then
begin begin
Result := False; Exit(False);
Exit;
end; end;
for I := 0 to AAttrs.Count - 1 do for I := 0 to AAttrs.Count - 1 do
if AttrMatches(AAttrs.Strings[I], 'Unretained') then if AttrMatches(AAttrs.Strings[I], 'Unretained') then
begin begin
Result := True; Exit(True);
Exit;
end; end;
Result := False; Result := False;
end; end;
@ -307,8 +302,7 @@ begin
begin begin
if SameText(Walk.Name, 'TCustomAttribute') then if SameText(Walk.Name, 'TCustomAttribute') then
begin begin
Result := True; Exit(True);
Exit;
end; end;
Walk := Walk.Parent; Walk := Walk.Parent;
end; end;
@ -325,8 +319,7 @@ begin
if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and
IsCustomAttributeClass(ARawName) then IsCustomAttributeClass(ARawName) then
begin begin
Result := ARawName; Exit(ARawName);
Exit;
end; end;
Sym := FTable.Lookup(ARawName + 'Attribute'); Sym := FTable.Lookup(ARawName + 'Attribute');
if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and
@ -424,8 +417,7 @@ begin
begin begin
if Walk = AExpected then if Walk = AExpected then
begin begin
Result := True; Exit(True);
Exit;
end; end;
Walk := Walk.Parent; Walk := Walk.Parent;
end; end;
@ -1414,14 +1406,12 @@ begin
for I := 0 to AParamNames.Count - 1 do for I := 0 to AParamNames.Count - 1 do
if SameText(Result, AParamNames.Strings[I]) then if SameText(Result, AParamNames.Strings[I]) then
begin begin
Result := AArgs.Strings[I]; Exit(AArgs.Strings[I]);
Exit;
end; end;
{ Prefix caret: ^T → ^Integer, ^^T → ^^Integer, etc. } { Prefix caret: ^T → ^Integer, ^^T → ^^Integer, etc. }
if (Length(Result) > 0) and (StrAt(Result, 0) = Ord('^')) then if (Length(Result) > 0) and (StrAt(Result, 0) = Ord('^')) then
begin begin
Result := '^' + Self.SubstTypeParam(StrCopyTail(Result, 1), AParamNames, AArgs); Exit('^' + Self.SubstTypeParam(StrCopyTail(Result, 1), AParamNames, AArgs));
Exit;
end; end;
{ Generic instantiation: SomeName<T,...> — substitute each type argument } { Generic instantiation: SomeName<T,...> — substitute each type argument }
BrOpen := StrPos('<', Result); BrOpen := StrPos('<', Result);
@ -1856,8 +1846,7 @@ begin
Sym := FTable.Lookup(ATypeName); Sym := FTable.Lookup(ATypeName);
if (Sym <> nil) and (Sym.TypeDesc is TInterfaceTypeDesc) then if (Sym <> nil) and (Sym.TypeDesc is TInterfaceTypeDesc) then
begin begin
Result := TInterfaceTypeDesc(Sym.TypeDesc); Exit(TInterfaceTypeDesc(Sym.TypeDesc));
Exit;
end; end;
{ Build mangled name: IEqualityComparer<Integer> → IEqualityComparer_Integer } { Build mangled name: IEqualityComparer<Integer> → IEqualityComparer_Integer }
@ -3255,8 +3244,7 @@ begin
Idx := FMethodIndex.IndexOf(Key); Idx := FMethodIndex.IndexOf(Key);
if Idx >= 0 then if Idx >= 0 then
begin begin
Result := TMethodDecl(FMethodIndex.Objects[Idx]); Exit(TMethodDecl(FMethodIndex.Objects[Idx]));
Exit;
end; end;
{ Walk to parent } { Walk to parent }
Sym := FTable.Lookup(CurrName); Sym := FTable.Lookup(CurrName);
@ -3344,8 +3332,7 @@ begin
begin begin
if ArityMatch.Count = 1 then if ArityMatch.Count = 1 then
begin begin
Result := TMethodDecl(ArityMatch.Items[0]); Exit(TMethodDecl(ArityMatch.Items[0]));
Exit;
end; end;
Exit; { ambiguous-by-arity-only — caller must score with args } Exit; { ambiguous-by-arity-only — caller must score with args }
end; end;
@ -3758,8 +3745,7 @@ begin
for I := 0 to ADecl.Params.Count - 1 do for I := 0 to ADecl.Params.Count - 1 do
if SameText(TMethodParam(ADecl.Params.Items[I]).ParamName, AName) then if SameText(TMethodParam(ADecl.Params.Items[I]).ParamName, AName) then
begin begin
Result := True; Exit(True);
Exit;
end; end;
end; end;
@ -3792,8 +3778,7 @@ begin
end; end;
if AExpr is TNotExpr then if AExpr is TNotExpr then
begin begin
Result := ExprRejectsInline(TNotExpr(AExpr).Expr, ASelfDecl); Exit(ExprRejectsInline(TNotExpr(AExpr).Expr, ASelfDecl));
Exit;
end; end;
end; end;
@ -3834,15 +3819,13 @@ begin
for I := 0 to Cmp.Stmts.Count - 1 do for I := 0 to Cmp.Stmts.Count - 1 do
if StmtRejectsInline(TASTStmt(Cmp.Stmts.Items[I]), ASelfDecl, AStmtCount) then if StmtRejectsInline(TASTStmt(Cmp.Stmts.Items[I]), ASelfDecl, AStmtCount) then
Exit; Exit;
Result := False; Exit(False);
Exit;
end; end;
if AStmt is TExitStmt then if AStmt is TExitStmt then
begin begin
Inc(AStmtCount); Inc(AStmtCount);
Result := False; Exit(False);
Exit;
end; end;
if AStmt is TIfStmt then if AStmt is TIfStmt then
@ -3853,8 +3836,7 @@ begin
if StmtRejectsInline(Ifs.ThenStmt, ASelfDecl, AStmtCount) then Exit; if StmtRejectsInline(Ifs.ThenStmt, ASelfDecl, AStmtCount) then Exit;
if (Ifs.ElseStmt <> nil) and if (Ifs.ElseStmt <> nil) and
StmtRejectsInline(Ifs.ElseStmt, ASelfDecl, AStmtCount) then Exit; StmtRejectsInline(Ifs.ElseStmt, ASelfDecl, AStmtCount) then Exit;
Result := False; Exit(False);
Exit;
end; end;
if AStmt is TAssignment then if AStmt is TAssignment then
@ -3865,8 +3847,7 @@ begin
{ Assignment to a parameter requires updating the caller-side temp, { Assignment to a parameter requires updating the caller-side temp,
which the simple inliner does not support. Reject. } which the simple inliner does not support. Reject. }
if AssignmentTargetsParameter(Asg.Name, ASelfDecl) then Exit; if AssignmentTargetsParameter(Asg.Name, ASelfDecl) then Exit;
Result := False; Exit(False);
Exit;
end; end;
if AStmt is TProcCall then if AStmt is TProcCall then
@ -3879,8 +3860,7 @@ begin
for I := 0 to TProcCall(AStmt).Args.Count - 1 do for I := 0 to TProcCall(AStmt).Args.Count - 1 do
if ExprRejectsInline(TASTExpr(TProcCall(AStmt).Args.Items[I]), ASelfDecl) then if ExprRejectsInline(TASTExpr(TProcCall(AStmt).Args.Items[I]), ASelfDecl) then
Exit; Exit;
Result := False; Exit(False);
Exit;
end; end;
if AStmt is TCaseStmt then if AStmt is TCaseStmt then
@ -3897,8 +3877,7 @@ begin
end; end;
if (Cs.ElseStmt <> nil) and if (Cs.ElseStmt <> nil) and
StmtRejectsInline(Cs.ElseStmt, ASelfDecl, AStmtCount) then Exit; StmtRejectsInline(Cs.ElseStmt, ASelfDecl, AStmtCount) then Exit;
Result := False; Exit(False);
Exit;
end; end;
{ Unknown statement form: reject conservatively. } { Unknown statement form: reject conservatively. }
@ -5037,8 +5016,7 @@ var
begin begin
if AType = nil then if AType = nil then
begin begin
Result := '?'; Exit('?');
Exit;
end; end;
case AType.Kind of case AType.Kind of
tyInteger: Base := 'i'; tyInteger: Base := 'i';
@ -5098,8 +5076,7 @@ begin
for I := 0 to ADecl.Params.Count - 1 do for I := 0 to ADecl.Params.Count - 1 do
if TMethodParam(ADecl.Params.Items[I]).DefaultValue <> nil then if TMethodParam(ADecl.Params.Items[I]).DefaultValue <> nil then
begin begin
Result := I; Exit(I);
Exit;
end; end;
Result := ADecl.Params.Count; Result := ADecl.Params.Count;
end; end;
@ -5282,15 +5259,13 @@ begin
Elem := TASTExpr(AExpr.Elements.Items[I]); Elem := TASTExpr(AExpr.Elements.Items[I]);
if not (Elem is TIdentExpr) then if not (Elem is TIdentExpr) then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
Sym := FTable.Lookup(TIdentExpr(Elem).Name); Sym := FTable.Lookup(TIdentExpr(Elem).Name);
if (Sym = nil) or (Sym.Kind <> skConstant) or (Sym.TypeDesc = nil) or if (Sym = nil) or (Sym.Kind <> skConstant) or (Sym.TypeDesc = nil) or
(Sym.TypeDesc.Kind <> tyEnum) then (Sym.TypeDesc.Kind <> tyEnum) then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
if Result = nil then if Result = nil then
Result := Sym.TypeDesc Result := Sym.TypeDesc
@ -5346,30 +5321,26 @@ begin
(TOpenArrayTypeDesc(AParam).ElementType = (TOpenArrayTypeDesc(AParam).ElementType =
TOpenArrayTypeDesc(AArg).ElementType) then TOpenArrayTypeDesc(AArg).ElementType) then
begin begin
Result := 2; Exit(2);
Exit;
end; end;
{ Static array coerced to open-array: widening match (score 1) } { Static array coerced to open-array: widening match (score 1) }
if (AParam.Kind = tyOpenArray) and (AArg.Kind = tyStaticArray) and if (AParam.Kind = tyOpenArray) and (AArg.Kind = tyStaticArray) and
(TOpenArrayTypeDesc(AParam).ElementType = (TOpenArrayTypeDesc(AParam).ElementType =
TStaticArrayTypeDesc(AArg).ElementType) then TStaticArrayTypeDesc(AArg).ElementType) then
begin begin
Result := 1; Exit(1);
Exit;
end; end;
{ Same numeric kind = exact match (same kind, just possibly different { Same numeric kind = exact match (same kind, just possibly different
descriptor instance). } descriptor instance). }
if AParam.IsNumeric and AArg.IsNumeric and (AParam.Kind = AArg.Kind) then if AParam.IsNumeric and AArg.IsNumeric and (AParam.Kind = AArg.Kind) then
begin begin
Result := 2; Exit(2);
Exit;
end; end;
{ Numeric widening: both numerics, kinds differ. Captures { Numeric widening: both numerics, kinds differ. Captures
Integer→Int64, Integer→Double, Single→Double, Byte→Integer, etc. } Integer→Int64, Integer→Double, Single→Double, Byte→Integer, etc. }
if AParam.IsNumeric and AArg.IsNumeric then if AParam.IsNumeric and AArg.IsNumeric then
begin begin
Result := 1; Exit(1);
Exit;
end; end;
{ Fall-through: probe full assignability via CheckTypesMatch. This { Fall-through: probe full assignability via CheckTypesMatch. This
covers nil-literal, class subtypes, untyped-Pointer compatibility, covers nil-literal, class subtypes, untyped-Pointer compatibility,
@ -5430,8 +5401,7 @@ begin
begin begin
if ArityMatch.Count = 1 then if ArityMatch.Count = 1 then
begin begin
Result := TMethodDecl(ArityMatch.Items[0]); Exit(TMethodDecl(ArityMatch.Items[0]));
Exit;
end; end;
{ zero-arg ambiguity is impossible — same name + zero params would { zero-arg ambiguity is impossible — same name + zero params would
have been rejected by the symbol-table chain, but be defensive. } have been rejected by the symbol-table chain, but be defensive. }
@ -5817,8 +5787,7 @@ begin
AExpr.Line, AExpr.Col); AExpr.Line, AExpr.Col);
AExpr.IsBuiltinHasClassAttr := True; AExpr.IsBuiltinHasClassAttr := True;
AExpr.ResolvedType := FTable.TypeBoolean; AExpr.ResolvedType := FTable.TypeBoolean;
Result := AExpr.ResolvedType; Exit(AExpr.ResolvedType);
Exit;
end; end;
{ SizeOf(TypeName) or SizeOf(expression) — compile-time byte size, { SizeOf(TypeName) or SizeOf(expression) — compile-time byte size,
@ -6906,8 +6875,7 @@ begin
AExpr.ResolvedMethod := MDecl; AExpr.ResolvedMethod := MDecl;
AExpr.ResolvedClassType := ObjSym.TypeDesc; AExpr.ResolvedClassType := ObjSym.TypeDesc;
AExpr.IsConstructorCall := True; AExpr.IsConstructorCall := True;
Result := ObjSym.TypeDesc; Exit(ObjSym.TypeDesc);
Exit;
end; end;
if not (ObjSym.Kind in [skVariable, skParameter, skVarParameter]) then if not (ObjSym.Kind in [skVariable, skParameter, skVarParameter]) then
@ -7202,15 +7170,13 @@ begin
begin begin
AAccess.IsClassNameAccess := True; AAccess.IsClassNameAccess := True;
AAccess.ResolvedType := FTable.TypeString; AAccess.ResolvedType := FTable.TypeString;
Result := FTable.TypeString; Exit(FTable.TypeString);
Exit;
end; end;
if SameText(AAccess.FieldName, 'ClassType') and (BaseType.Kind = tyClass) then if SameText(AAccess.FieldName, 'ClassType') and (BaseType.Kind = tyClass) then
begin begin
AAccess.IsClassTypeAccess := True; AAccess.IsClassTypeAccess := True;
AAccess.ResolvedType := FTable.TypePointer; { TClass = Pointer for now } AAccess.ResolvedType := FTable.TypePointer; { TClass = Pointer for now }
Result := FTable.TypePointer; Exit(FTable.TypePointer);
Exit;
end; end;
RT := TRecordTypeDesc(BaseType); RT := TRecordTypeDesc(BaseType);
FldInfo := RT.FindField(AAccess.FieldName); FldInfo := RT.FindField(AAccess.FieldName);
@ -7221,8 +7187,7 @@ begin
begin begin
AAccess.FieldName := PropInfo.ReadField; AAccess.FieldName := PropInfo.ReadField;
AAccess.FieldInfo := RT.FindField(PropInfo.ReadField); AAccess.FieldInfo := RT.FindField(PropInfo.ReadField);
Result := PropInfo.TypeDesc; Exit(PropInfo.TypeDesc);
Exit;
end; end;
{ Method-backed property (including indexed: the parser attaches the { Method-backed property (including indexed: the parser attaches the
'[idx]' to AAccess.PropIndexExpr when it parses 'Base.Prop[idx]'). } '[idx]' to AAccess.PropIndexExpr when it parses 'Base.Prop[idx]'). }
@ -7248,8 +7213,7 @@ begin
if AAccess.ResolvedMethod <> nil then if AAccess.ResolvedMethod <> nil then
begin begin
AAccess.IsMethodCall := True; AAccess.IsMethodCall := True;
Result := TMethodDecl(AAccess.ResolvedMethod).ResolvedReturnType; Exit(TMethodDecl(AAccess.ResolvedMethod).ResolvedReturnType);
Exit;
end; end;
{ Built-in TObject.ToString: virtual dispatch yielding string. { Built-in TObject.ToString: virtual dispatch yielding string.
Every class inherits this via vtable slot 1. } Every class inherits this via vtable slot 1. }
@ -7275,8 +7239,7 @@ begin
AAccess.ConstArrayType := Sym.TypeDesc; AAccess.ConstArrayType := Sym.TypeDesc;
end; end;
AAccess.ResolvedType := Sym.TypeDesc; AAccess.ResolvedType := Sym.TypeDesc;
Result := Sym.TypeDesc; Exit(Sym.TypeDesc);
Exit;
end; end;
SemanticError( SemanticError(
Format('Type ''%s'' has no field ''%s''', Format('Type ''%s'' has no field ''%s''',
@ -7441,13 +7404,11 @@ begin
begin begin
AnalyseExpr(AAccess.PropIndexExpr); AnalyseExpr(AAccess.PropIndexExpr);
AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType; AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType;
Result := AAccess.ResolvedType; Exit(AAccess.ResolvedType);
Exit;
end; end;
end; end;
AAccess.ResolvedType := Sym.TypeDesc; AAccess.ResolvedType := Sym.TypeDesc;
Result := Sym.TypeDesc; Exit(Sym.TypeDesc);
Exit;
end; end;
SemanticError( SemanticError(
Format('Unknown class method ''%s'' on type ''%s''', Format('Unknown class method ''%s'' on type ''%s''',
@ -7460,8 +7421,7 @@ begin
AAccess.Line, AAccess.Col); AAccess.Line, AAccess.Col);
AAccess.IsConstructorCall := True; AAccess.IsConstructorCall := True;
AAccess.ResolvedMethod := FindMethodDecl(TRecordTypeDesc(RecSym.TypeDesc).Name, 'Create'); AAccess.ResolvedMethod := FindMethodDecl(TRecordTypeDesc(RecSym.TypeDesc).Name, 'Create');
Result := RecSym.TypeDesc; Exit(RecSym.TypeDesc);
Exit;
end; end;
{ Field access on variable or parameter } { Field access on variable or parameter }
@ -7511,15 +7471,13 @@ begin
begin begin
AAccess.IsClassNameAccess := True; AAccess.IsClassNameAccess := True;
AAccess.ResolvedType := FTable.TypeString; AAccess.ResolvedType := FTable.TypeString;
Result := FTable.TypeString; Exit(FTable.TypeString);
Exit;
end; end;
if SameText(AAccess.FieldName, 'ClassType') and (RecSym.TypeDesc.Kind = tyClass) then if SameText(AAccess.FieldName, 'ClassType') and (RecSym.TypeDesc.Kind = tyClass) then
begin begin
AAccess.IsClassTypeAccess := True; AAccess.IsClassTypeAccess := True;
AAccess.ResolvedType := FTable.TypePointer; AAccess.ResolvedType := FTable.TypePointer;
Result := FTable.TypePointer; Exit(FTable.TypePointer);
Exit;
end; end;
RT := TRecordTypeDesc(RecSym.TypeDesc); RT := TRecordTypeDesc(RecSym.TypeDesc);
@ -7592,13 +7550,11 @@ begin
begin begin
AnalyseExpr(AAccess.PropIndexExpr); AnalyseExpr(AAccess.PropIndexExpr);
AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType; AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType;
Result := AAccess.ResolvedType; Exit(AAccess.ResolvedType);
Exit;
end; end;
end; end;
AAccess.ResolvedType := Sym.TypeDesc; AAccess.ResolvedType := Sym.TypeDesc;
Result := Sym.TypeDesc; Exit(Sym.TypeDesc);
Exit;
end; end;
SemanticError( SemanticError(
Format('Type ''%s'' has no field ''%s''', Format('Type ''%s'' has no field ''%s''',
@ -7724,8 +7680,7 @@ begin
Format('Right operand of ''%s'' must be Boolean, got ''%s''', Format('Right operand of ''%s'' must be Boolean, got ''%s''',
[BinaryOpName(ABin.Op), RType.Name]), [BinaryOpName(ABin.Op), RType.Name]),
ABin.Line, ABin.Col); ABin.Line, ABin.Col);
Result := FTable.TypeBoolean; Exit(FTable.TypeBoolean);
Exit;
end; end;
if IsComparisonOp(ABin.Op) then if IsComparisonOp(ABin.Op) then
@ -7774,20 +7729,17 @@ begin
{ String concatenation: s1 + s2 → string } { String concatenation: s1 + s2 → string }
if (ABin.Op = boAdd) and LType.IsString and RType.IsString then if (ABin.Op = boAdd) and LType.IsString and RType.IsString then
begin begin
Result := FTable.TypeString; Exit(FTable.TypeString);
Exit;
end; end;
{ Pointer arithmetic: Pointer/PChar + Integer or Integer + Pointer → same type } { Pointer arithmetic: Pointer/PChar + Integer or Integer + Pointer → same type }
if (ABin.Op in [boAdd, boSub]) and (LType.Kind in [tyPointer, tyPChar]) and RType.IsNumeric then if (ABin.Op in [boAdd, boSub]) and (LType.Kind in [tyPointer, tyPChar]) and RType.IsNumeric then
begin begin
Result := LType; Exit(LType);
Exit;
end; end;
if (ABin.Op = boAdd) and LType.IsNumeric and (RType.Kind in [tyPointer, tyPChar]) then if (ABin.Op = boAdd) and LType.IsNumeric and (RType.Kind in [tyPointer, tyPChar]) then
begin begin
Result := RType; Exit(RType);
Exit;
end; end;
{ Shift operators: result has the left operand's type; right is the shift amount } { Shift operators: result has the left operand's type; right is the shift amount }
@ -8068,8 +8020,7 @@ begin
ProcDesc.ReturnType := MD.ResolvedReturnType; ProcDesc.ReturnType := MD.ResolvedReturnType;
FldExpr.ResolvedType := ProcDesc; FldExpr.ResolvedType := ProcDesc;
AExpr.ResolvedType := ProcDesc; AExpr.ResolvedType := ProcDesc;
Result := ProcDesc; Exit(ProcDesc);
Exit;
end; end;
end; end;
end; end;
@ -8223,8 +8174,7 @@ begin
SemanticError( SemanticError(
'Expression is not callable — expected procedural type', 'Expression is not callable — expected procedural type',
AExpr.Line, AExpr.Col); AExpr.Line, AExpr.Col);
Result := FTable.TypeInteger; Exit(FTable.TypeInteger);
Exit;
end; end;
ProcDesc := TProceduralTypeDesc(CalleeType); ProcDesc := TProceduralTypeDesc(CalleeType);
AExpr.ResolvedProcType := ProcDesc; AExpr.ResolvedProcType := ProcDesc;
@ -8364,8 +8314,7 @@ begin
if AExpr.Elements.Count = 0 then if AExpr.Elements.Count = 0 then
begin begin
AExpr.ResolvedType := nil; AExpr.ResolvedType := nil;
Result := nil; Exit(nil);
Exit;
end; end;
ElemType := AnalyseExpr(TASTExpr(AExpr.Elements.Items[0])); ElemType := AnalyseExpr(TASTExpr(AExpr.Elements.Items[0]));
for I := 1 to AExpr.Elements.Count - 1 do for I := 1 to AExpr.Elements.Count - 1 do

View file

@ -731,8 +731,7 @@ begin
E := TVTableEntry(FVTable.Items[I]); E := TVTableEntry(FVTable.Items[I]);
if SameText(E.MethName, AMethodName) then if SameText(E.MethName, AMethodName) then
begin begin
Result := I; Exit(I);
Exit;
end; end;
end; end;
end; end;
@ -812,8 +811,7 @@ begin
for I := 0 to Walk.FProperties.Count - 1 do for I := 0 to Walk.FProperties.Count - 1 do
if SameText(TPropertyInfo(Walk.FProperties.Items[I]).Name, AName) then if SameText(TPropertyInfo(Walk.FProperties.Items[I]).Name, AName) then
begin begin
Result := TPropertyInfo(Walk.FProperties.Items[I]); Exit(TPropertyInfo(Walk.FProperties.Items[I]));
Exit;
end; end;
Walk := Walk.Parent; Walk := Walk.Parent;
end; end;
@ -834,8 +832,7 @@ begin
P := TPropertyInfo(Walk.FProperties.Items[I]); P := TPropertyInfo(Walk.FProperties.Items[I]);
if (P.IndexParamName <> '') and (P.ReadMethod <> '') then if (P.IndexParamName <> '') and (P.ReadMethod <> '') then
begin begin
Result := P; Exit(P);
Exit;
end; end;
end; end;
Walk := Walk.Parent; Walk := Walk.Parent;
@ -931,8 +928,7 @@ begin
CurPar := CurPar + 1 CurPar := CurPar + 1
else if CurPar = AParamIndex then else if CurPar = AParamIndex then
begin begin
Result := Flags[Idx] = '1'; Exit(Flags[Idx] = '1');
Exit;
end; end;
Idx := Idx + 1; Idx := Idx + 1;
end; end;
@ -1010,11 +1006,9 @@ begin
Tail := Tail.NextOverload; Tail := Tail.NextOverload;
Tail.NextOverload := ASymbol; Tail.NextOverload := ASymbol;
FSymbols.Add(ASymbol); { take ownership; lookup walks the chain via Existing } FSymbols.Add(ASymbol); { take ownership; lookup walks the chain via Existing }
Result := True; Exit(True);
Exit;
end; end;
Result := False; Exit(False);
Exit;
end; end;
FSymbols.Add(ASymbol); FSymbols.Add(ASymbol);
{ Store the TSymbol pointer directly in the string list's Objects slot. } { Store the TSymbol pointer directly in the string list's Objects slot. }
@ -1072,8 +1066,7 @@ begin
for I := 0 to Members.Count - 1 do for I := 0 to Members.Count - 1 do
if SameText(Members.Strings[I], AMember) then if SameText(Members.Strings[I], AMember) then
begin begin
Result := I; Exit(I);
Exit;
end; end;
Result := -1; Result := -1;
end; end;

View file

@ -100,8 +100,7 @@ begin
Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName; Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName;
if FileExists(Candidate) then if FileExists(Candidate) then
begin begin
Result := Candidate; Exit(Candidate);
Exit;
end; end;
{ Blaise Pos: -1 = not found. `< 0` is the "not present" test. } { Blaise Pos: -1 = not found. `< 0` is the "not present" test. }
if IsWindowsHost and (Pos('.exe', LowerCase(ABaseName)) < 0) then if IsWindowsHost and (Pos('.exe', LowerCase(ABaseName)) < 0) then
@ -109,8 +108,7 @@ begin
Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName + '.exe'; Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName + '.exe';
if FileExists(Candidate) then if FileExists(Candidate) then
begin begin
Result := Candidate; Exit(Candidate);
Exit;
end; end;
end; end;
Result := ''; Result := '';
@ -144,8 +142,7 @@ begin
Hit := TrySingleName(Entry, ABaseName); Hit := TrySingleName(Entry, ABaseName);
if Hit <> '' then if Hit <> '' then
begin begin
Result := Hit; Exit(Hit);
Exit;
end; end;
end; end;
end; end;
@ -181,8 +178,7 @@ begin
EnvPath := GetEnvironmentVariable(AEnvVar); EnvPath := GetEnvironmentVariable(AEnvVar);
if (EnvPath <> '') and FileExists(EnvPath) then if (EnvPath <> '') and FileExists(EnvPath) then
begin begin
Result := EnvPath; Exit(EnvPath);
Exit;
end; end;
end; end;
Hit := TryCandidate(ACandA); Hit := TryCandidate(ACandA);

View file

@ -68,15 +68,13 @@ begin
Path := Base + LowerCase(AName) + '.pas'; Path := Base + LowerCase(AName) + '.pas';
if FileExists(Path) then if FileExists(Path) then
begin begin
Result := Path; Exit(Path);
Exit;
end; end;
{ Fallback: exact case as written in the uses clause } { Fallback: exact case as written in the uses clause }
Path := Base + AName + '.pas'; Path := Base + AName + '.pas';
if FileExists(Path) then if FileExists(Path) then
begin begin
Result := Path; Exit(Path);
Exit;
end; end;
end; end;
Result := ''; Result := '';

View file

@ -37,6 +37,7 @@ type
{ Non-local exit (Exit/Break) must run intervening finally bodies. } { Non-local exit (Exit/Break) must run intervening finally bodies. }
procedure TestRun_ExitThroughFinally; procedure TestRun_ExitThroughFinally;
procedure TestRun_ExitValueThroughFinally;
procedure TestRun_ExitThroughNestedFinally; procedure TestRun_ExitThroughNestedFinally;
procedure TestRun_BreakThroughFinally; procedure TestRun_BreakThroughFinally;
@ -124,6 +125,29 @@ const
end. end.
'''; ''';
{ Exit(X) from inside a try/finally must assign the result, run the finally
body, then return the value to the caller. Guards the refactor that
replaces the 'Result := X; Exit;' workaround with 'Exit(X)' in source
that sits inside try/finally. }
SrcExitValueThroughFinally = '''
program P;
function Pick(b: Boolean): Integer;
begin
Result := -1;
try
if b then Exit(42);
WriteLn('unreached')
finally
WriteLn('in_finally')
end;
Result := 7
end;
begin
WriteLn(Pick(True));
WriteLn(Pick(False))
end.
''';
{ Exit nested two levels deep must run both finally bodies, innermost first. } { Exit nested two levels deep must run both finally bodies, innermost first. }
SrcExitThroughNestedFinally = ''' SrcExitThroughNestedFinally = '''
program P; program P;
@ -350,6 +374,19 @@ begin
'in_try' + LE + 'in_finally' + LE + 'after' + LE, Output); 'in_try' + LE + 'in_finally' + LE + 'after' + LE, Output);
end; end;
procedure TE2EExceptionTests.TestRun_ExitValueThroughFinally;
var Output: string; RCode: Integer;
begin
if not ToolchainAvailable then begin Ignore('toolchain unavailable'); Exit; end;
AssertTrue('compile+run', CompileAndRun(SrcExitValueThroughFinally, Output, RCode));
AssertEquals('exit code', 0, RCode);
{ True: Exit(42) sets Result, runs finally, returns 42.
False: falls through, runs finally, then Result := 7. }
AssertEquals('stdout',
'in_finally' + LE + '42' + LE +
'unreached' + LE + 'in_finally' + LE + '7' + LE, Output);
end;
procedure TE2EExceptionTests.TestRun_ExitThroughNestedFinally; procedure TE2EExceptionTests.TestRun_ExitThroughNestedFinally;
var Output: string; RCode: Integer; var Output: string; RCode: Integer;
begin begin

View file

@ -411,8 +411,7 @@ var
begin begin
if S1 = S2 then if S1 = S2 then
begin begin
Result := 1; Exit(1);
Exit;
end; end;
if S1 = nil then if S1 = nil then
Len1 := 0 Len1 := 0
@ -430,13 +429,11 @@ begin
end; end;
if Len1 <> Len2 then if Len1 <> Len2 then
begin begin
Result := 0; Exit(0);
Exit;
end; end;
if Len1 = 0 then if Len1 = 0 then
begin begin
Result := 1; Exit(1);
Exit;
end; end;
C1 := PChar(S1); { data IS the pointer } C1 := PChar(S1); { data IS the pointer }
C2 := PChar(S2); C2 := PChar(S2);
@ -506,8 +503,7 @@ var
begin begin
if Self = nil then if Self = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
Slot := Self; { instance: first 8 bytes = vptr } Slot := Self; { instance: first 8 bytes = vptr }
VTable := Slot^; { VTable points to vtable data } VTable := Slot^; { VTable points to vtable data }
@ -561,8 +557,7 @@ begin
Entry := Pointer(Entry) + 8; Entry := Pointer(Entry) + 8;
if _StringEquals(EntName, Name) <> 0 then if _StringEquals(EntName, Name) <> 0 then
begin begin
Result := EntAddr; Exit(EntAddr);
Exit;
end; end;
end; end;
end; end;
@ -588,8 +583,7 @@ begin
begin begin
if Current = AParent then if Current = AParent then
begin begin
Result := True; Exit(True);
Exit;
end; end;
TI := Current; { typeinfo[0] = parent pointer } TI := Current; { typeinfo[0] = parent pointer }
Current := TI^; Current := TI^;
@ -690,8 +684,7 @@ begin
begin begin
if Entry^ = AAttrTI then if Entry^ = AAttrTI then
begin begin
Result := True; Exit(True);
Exit;
end; end;
Entry := Pointer(Entry) + 8; Entry := Pointer(Entry) + 8;
end; end;

View file

@ -72,8 +72,7 @@ begin
Base := _BlaiseGetMem(13); Base := _BlaiseGetMem(13);
if Base = nil then if Base = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
RC := Base; RC := Base;
RC^ := 0; RC^ := 0;
@ -140,8 +139,7 @@ begin
Exc := g_current_exception; Exc := g_current_exception;
if Exc = nil then if Exc = nil then
begin begin
Result := ExcStrEmpty; Exit(ExcStrEmpty);
Exit;
end; end;
MsgSlot := Exc + 8; MsgSlot := Exc + 8;
Msg := MsgSlot^; Msg := MsgSlot^;
@ -174,8 +172,7 @@ begin
begin begin
if TI = Target then if TI = Target then
begin begin
Result := 1; Exit(1);
Exit;
end; end;
ParentSlot := TI; ParentSlot := TI;
TI := ParentSlot^; TI := ParentSlot^;
@ -202,8 +199,7 @@ begin
begin begin
if Impl^ = IntfTI then if Impl^ = IntfTI then
begin begin
Result := 1; Exit(1);
Exit;
end; end;
Impl := Pointer(Impl) + 16; Impl := Pointer(Impl) + 16;
end; end;
@ -234,8 +230,7 @@ begin
if Impl^ = IntfTI then if Impl^ = IntfTI then
begin begin
ItabSlot := Pointer(Impl) + 8; ItabSlot := Pointer(Impl) + 8;
Result := ItabSlot^; Exit(ItabSlot^);
Exit;
end; end;
Impl := Pointer(Impl) + 16; Impl := Pointer(Impl) + 16;
end; end;

View file

@ -54,8 +54,7 @@ begin
Base := _BlaiseGetMem(BLAISE_STR_HDR + Cap); Base := _BlaiseGetMem(BLAISE_STR_HDR + Cap);
if Base = nil then if Base = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
RC := Base; RC^ := 1; RC := Base; RC^ := 1;
LN := Base + 4; LN^ := Len; LN := Base + 4; LN^ := Len;
@ -123,8 +122,7 @@ var
begin begin
if X = 0 then if X = 0 then
begin begin
Result := 64; Exit(64);
Exit;
end; end;
N := 0; N := 0;
if (X shr 32) = 0 then begin N := N + 32; X := X shl 32; end; if (X shr 32) = 0 then begin N := N + 32; X := X shl 32; end;
@ -645,8 +643,7 @@ var
begin begin
if E = 0 then if E = 0 then
begin begin
Result := 1.0; Exit(1.0);
Exit;
end; end;
if E < 0 then if E < 0 then
N := -E N := -E
@ -682,8 +679,7 @@ var
begin begin
if S = nil then if S = nil then
begin begin
Result := 0.0; Exit(0.0);
Exit;
end; end;
P := PChar(S); P := PChar(S);
I := 0; I := 0;
@ -710,14 +706,12 @@ begin
Bits := Int64($FFF0000000000000) Bits := Int64($FFF0000000000000)
else else
Bits := Int64($7FF0000000000000); Bits := Int64($7FF0000000000000);
Result := BitsToDouble(Bits); Exit(BitsToDouble(Bits));
Exit;
end; end;
if (C = 110) or (C = 78) then if (C = 110) or (C = 78) then
begin begin
Bits := Int64($7FF8000000000000); Bits := Int64($7FF8000000000000);
Result := BitsToDouble(Bits); Exit(BitsToDouble(Bits));
Exit;
end; end;
{ Parse mantissa digits } { Parse mantissa digits }

View file

@ -172,8 +172,7 @@ begin
Base := MmapAlloc(Int64(ARENA_SIZE)); Base := MmapAlloc(Int64(ARENA_SIZE));
if Base = nil then if Base = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
A := PArena(Base); A := PArena(Base);
A^.Base := Base; A^.Base := Base;
@ -200,15 +199,13 @@ begin
Hdr^.AllocSize := Size; Hdr^.AllocSize := Size;
Hdr^.Flags := FLAG_SMALL; Hdr^.Flags := FLAG_SMALL;
A^.Offset := A^.Offset + Needed; A^.Offset := A^.Offset + Needed;
Result := Pointer(PtrUInt(Hdr) + HEADER_SIZE); Exit(Pointer(PtrUInt(Hdr) + HEADER_SIZE));
Exit;
end; end;
A := AllocArena; A := AllocArena;
if A = nil then if A = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
Hdr := Pointer(PtrUInt(A^.Base) + PtrUInt(A^.Offset)); Hdr := Pointer(PtrUInt(A^.Base) + PtrUInt(A^.Offset));
Hdr^.AllocSize := Size; Hdr^.AllocSize := Size;
@ -231,8 +228,7 @@ begin
FreeLists[Idx] := Node^.Next; FreeLists[Idx] := Node^.Next;
Hdr := PBlockHeader(Pointer(PtrUInt(Node) - HEADER_SIZE)); Hdr := PBlockHeader(Pointer(PtrUInt(Node) - HEADER_SIZE));
Hdr^.AllocSize := Size; Hdr^.AllocSize := Size;
Result := Pointer(Node); Exit(Pointer(Node));
Exit;
end; end;
Result := ArenaAlloc(Size); Result := ArenaAlloc(Size);
@ -273,8 +269,7 @@ begin
Hdr^.TotalMapped := CachedSize; Hdr^.TotalMapped := CachedSize;
Hdr^.AllocSize := Size; Hdr^.AllocSize := Size;
Hdr^.Flags := FLAG_LARGE; Hdr^.Flags := FLAG_LARGE;
Result := Pointer(PtrUInt(Hdr) + LARGE_HEADER); Exit(Pointer(PtrUInt(Hdr) + LARGE_HEADER));
Exit;
end; end;
Base := _libc_mremap(Pointer(Node), CachedSize, Needed, MREMAP_MAYMOVE); Base := _libc_mremap(Pointer(Node), CachedSize, Needed, MREMAP_MAYMOVE);
if not MapFailed(Base) then if not MapFailed(Base) then
@ -283,8 +278,7 @@ begin
Hdr^.TotalMapped := Needed; Hdr^.TotalMapped := Needed;
Hdr^.AllocSize := Size; Hdr^.AllocSize := Size;
Hdr^.Flags := FLAG_LARGE; Hdr^.Flags := FLAG_LARGE;
Result := Pointer(PtrUInt(Base) + LARGE_HEADER); Exit(Pointer(PtrUInt(Base) + LARGE_HEADER));
Exit;
end; end;
_libc_munmap(Pointer(Node), CachedSize); _libc_munmap(Pointer(Node), CachedSize);
end; end;
@ -293,8 +287,7 @@ begin
Base := MmapAlloc(Total); Base := MmapAlloc(Total);
if Base = nil then if Base = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
Hdr := PLargeHeader(Base); Hdr := PLargeHeader(Base);
Hdr^.TotalMapped := Total; Hdr^.TotalMapped := Total;
@ -352,8 +345,7 @@ function _BlaiseGetMem(Size: Integer): Pointer;
begin begin
if Size <= 0 then if Size <= 0 then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
if Size > LARGE_THRESHOLD then if Size > LARGE_THRESHOLD then
Result := LargeGetMem(Size) Result := LargeGetMem(Size)
@ -380,14 +372,12 @@ var
begin begin
if Ptr = nil then if Ptr = nil then
begin begin
Result := _BlaiseGetMem(NewSize); Exit(_BlaiseGetMem(NewSize));
Exit;
end; end;
if NewSize <= 0 then if NewSize <= 0 then
begin begin
_BlaiseFreeMem(Ptr); _BlaiseFreeMem(Ptr);
Result := nil; Exit(nil);
Exit;
end; end;
OldSize := GetAllocSize(Ptr); OldSize := GetAllocSize(Ptr);
if (not IsLarge(Ptr)) and (NewSize <= LARGE_THRESHOLD) then if (not IsLarge(Ptr)) and (NewSize <= LARGE_THRESHOLD) then
@ -396,8 +386,7 @@ begin
begin begin
Hdr := PBlockHeader(Pointer(PtrUInt(Ptr) - HEADER_SIZE)); Hdr := PBlockHeader(Pointer(PtrUInt(Ptr) - HEADER_SIZE));
Hdr^.AllocSize := NewSize; Hdr^.AllocSize := NewSize;
Result := Ptr; Exit(Ptr);
Exit;
end; end;
end; end;
if IsLarge(Ptr) and (NewSize > LARGE_THRESHOLD) then if IsLarge(Ptr) and (NewSize > LARGE_THRESHOLD) then
@ -408,8 +397,7 @@ begin
if NewMapped = OldMapped then if NewMapped = OldMapped then
begin begin
LHdr^.AllocSize := NewSize; LHdr^.AllocSize := NewSize;
Result := Ptr; Exit(Ptr);
Exit;
end; end;
Base := Pointer(LHdr); Base := Pointer(LHdr);
NewBase := _libc_mremap(Base, OldMapped, NewMapped, MREMAP_MAYMOVE); NewBase := _libc_mremap(Base, OldMapped, NewMapped, MREMAP_MAYMOVE);
@ -419,8 +407,7 @@ begin
LHdr^.TotalMapped := NewMapped; LHdr^.TotalMapped := NewMapped;
LHdr^.AllocSize := NewSize; LHdr^.AllocSize := NewSize;
LHdr^.Flags := FLAG_LARGE; LHdr^.Flags := FLAG_LARGE;
Result := Pointer(PtrUInt(NewBase) + LARGE_HEADER); Exit(Pointer(PtrUInt(NewBase) + LARGE_HEADER));
Exit;
end; end;
end; end;
Result := _BlaiseGetMem(NewSize); Result := _BlaiseGetMem(NewSize);

View file

@ -153,8 +153,7 @@ begin
Base := _BlaiseGetMem(Integer(TotalL)); Base := _BlaiseGetMem(Integer(TotalL));
if Base = nil then if Base = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
RC := Base; { RefCount at base+0 } RC := Base; { RefCount at base+0 }
RC^ := 0; RC^ := 0;
@ -191,13 +190,11 @@ begin
SubLen := StrLen(Sub); SubLen := StrLen(Sub);
if SubLen = 0 then if SubLen = 0 then
begin begin
Result := 0; Exit(0);
Exit;
end; end;
if SubLen > SLen then if SubLen > SLen then
begin begin
Result := -1; Exit(-1);
Exit;
end; end;
SData := StrData(S); SData := StrData(S);
SubData := StrData(Sub); SubData := StrData(Sub);
@ -217,8 +214,7 @@ begin
end; end;
if Match then if Match then
begin begin
Result := I; Exit(I);
Exit;
end; end;
Inc(I); Inc(I);
end; end;
@ -241,13 +237,11 @@ begin
SubLen := StrLen(Sub); SubLen := StrLen(Sub);
if SubLen = 0 then if SubLen = 0 then
begin begin
Result := 0; Exit(0);
Exit;
end; end;
if (SubLen > SLen) or (StartPos >= SLen) then if (SubLen > SLen) or (StartPos >= SLen) then
begin begin
Result := -1; Exit(-1);
Exit;
end; end;
SData := StrData(S); SData := StrData(S);
SubData := StrData(Sub); SubData := StrData(Sub);
@ -268,8 +262,7 @@ begin
end; end;
if Match then if Match then
begin begin
Result := I; Exit(I);
Exit;
end; end;
Inc(I); Inc(I);
end; end;
@ -289,8 +282,7 @@ begin
if From < 0 then From := 0; if From < 0 then From := 0;
if From >= SLen then if From >= SLen then
begin begin
Result := StrAlloc(0); Exit(StrAlloc(0));
Exit;
end; end;
{ Avoid signed overflow when Count is large (Copy(S, N, MaxInt) idiom) — { Avoid signed overflow when Count is large (Copy(S, N, MaxInt) idiom) —
compare Count against (SLen - From) instead of (From + Count) > SLen. } compare Count against (SLen - From) instead of (From + Count) > SLen. }
@ -468,8 +460,7 @@ begin
Len2 := StrLen(S2); Len2 := StrLen(S2);
if Len1 <> Len2 then if Len1 <> Len2 then
begin begin
Result := 0; Exit(0);
Exit;
end; end;
D1 := StrData(S1); D1 := StrData(S1);
D2 := StrData(S2); D2 := StrData(S2);
@ -481,8 +472,7 @@ begin
if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32; if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32;
if C1 <> C2 then if C1 <> C2 then
begin begin
Result := 0; Exit(0);
Exit;
end; end;
end; end;
Result := 1; Result := 1;
@ -755,8 +745,7 @@ begin
Len := StrLen(S); Len := StrLen(S);
if (I < 0) or (I >= Len) then if (I < 0) or (I >= Len) then
begin begin
Result := 0; Exit(0);
Exit;
end; end;
Data := StrData(S); Data := StrData(S);
Result := Data[I]; Result := Data[I];
@ -811,8 +800,7 @@ begin
C2 := D2[I]; C2 := D2[I];
if C1 <> C2 then if C1 <> C2 then
begin begin
Result := C1 - C2; Exit(C1 - C2);
Exit;
end; end;
end; end;
Result := Len1 - Len2; Result := Len1 - Len2;
@ -841,8 +829,7 @@ begin
if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32; if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32;
if C1 <> C2 then if C1 <> C2 then
begin begin
Result := C1 - C2; Exit(C1 - C2);
Exit;
end; end;
end; end;
Result := Len1 - Len2; Result := Len1 - Len2;
@ -858,8 +845,7 @@ var
begin begin
if P = nil then if P = nil then
begin begin
Result := StrAlloc(0); Exit(StrAlloc(0));
Exit;
end; end;
Len := 0; Len := 0;
while P[Len] <> 0 do while P[Len] <> 0 do
@ -1115,8 +1101,7 @@ begin
if P[I] = 47 then SlashPos := I; if P[I] = 47 then SlashPos := I;
if SlashPos < 0 then if SlashPos < 0 then
begin begin
Result := StrAlloc(0); Exit(StrAlloc(0));
Exit;
end; end;
Result := StrAlloc(SlashPos + 1); Result := StrAlloc(SlashPos + 1);
if Result <> nil then MemCopy(Result, P, SlashPos + 1); if Result <> nil then MemCopy(Result, P, SlashPos + 1);
@ -1134,8 +1119,7 @@ begin
if P[I] = 47 then SlashPos := I; if P[I] = 47 then SlashPos := I;
if (SlashPos < 0) or (SlashPos = 0) then if (SlashPos < 0) or (SlashPos = 0) then
begin begin
Result := StrAlloc(0); Exit(StrAlloc(0));
Exit;
end; end;
Result := StrAlloc(SlashPos); Result := StrAlloc(SlashPos);
if Result <> nil then MemCopy(Result, P, SlashPos); if Result <> nil then MemCopy(Result, P, SlashPos);
@ -1158,8 +1142,7 @@ begin
end; end;
if (LastDot < 0) or ((LastSep >= 0) and (LastDot < LastSep)) then if (LastDot < 0) or ((LastSep >= 0) and (LastDot < LastSep)) then
begin begin
Result := StrAlloc(0); Exit(StrAlloc(0));
Exit;
end; end;
ExtLen := PLen - LastDot; ExtLen := PLen - LastDot;
Result := StrAlloc(ExtLen); Result := StrAlloc(ExtLen);
@ -1213,8 +1196,7 @@ var
begin begin
if Ptr = nil then if Ptr = nil then
begin begin
Result := 0; Exit(0);
Exit;
end; end;
{ length is stored at offset −4 from data pointer } { length is stored at offset −4 from data pointer }
LenPtr := Ptr - 4; LenPtr := Ptr - 4;
@ -1240,8 +1222,7 @@ begin
begin begin
if Ptr <> nil then if Ptr <> nil then
_BlaiseFreeMem(Ptr - DA_HDR); _BlaiseFreeMem(Ptr - DA_HDR);
Result := nil; Exit(nil);
Exit;
end; end;
DataSz := DA_HDR + NewLen * ElemSize; DataSz := DA_HDR + NewLen * ElemSize;
NewBase := _BlaiseGetMem(DataSz); NewBase := _BlaiseGetMem(DataSz);

View file

@ -85,16 +85,14 @@ begin
begin begin
if E^.Target = ATarget then if E^.Target = ATarget then
begin begin
Result := E; Exit(E);
Exit;
end; end;
E := E^.Next; E := E^.Next;
end; end;
E := PWeakEntry(_BlaiseGetMem(24)); E := PWeakEntry(_BlaiseGetMem(24));
if E = nil then if E = nil then
begin begin
Result := nil; Exit(nil);
Exit;
end; end;
E^.Target := ATarget; E^.Target := ATarget;
E^.Slots := nil; E^.Slots := nil;

View file

@ -1050,8 +1050,7 @@ begin
begin begin
libc_close(P^.PipeFd); libc_close(P^.PipeFd);
P^.PipeFd := -1; P^.PipeFd := -1;
Result := StrAlloc(0); Exit(StrAlloc(0));
Exit;
end; end;
R := StrAlloc(Integer(N)); R := StrAlloc(Integer(N));
if R <> nil then if R <> nil then

View file

@ -310,8 +310,7 @@ begin
for I := 0 to High(Arr) do for I := 0 to High(Arr) do
if Arr[I] = Str then if Arr[I] = Str then
begin begin
Result := I; Exit(I);
Exit;
end; end;
Result := -1; Result := -1;
end; end;
@ -328,8 +327,7 @@ begin
EL := LowerCase(Arr[I]); EL := LowerCase(Arr[I]);
if EL = SL then if EL = SL then
begin begin
Result := I; Exit(I);
Exit;
end; end;
end; end;
Result := -1; Result := -1;
@ -354,8 +352,7 @@ begin
NewLen := Length(NewP); NewLen := Length(NewP);
if (SLen = 0) or (OldLen = 0) then if (SLen = 0) or (OldLen = 0) then
begin begin
Result := S; Exit(S);
Exit;
end; end;
SP := PChar(S); SP := PChar(S);
OP := PChar(OldP); OP := PChar(OldP);
@ -421,8 +418,7 @@ var
begin begin
if (Count <= 0) or (Length(S) = 0) then if (Count <= 0) or (Length(S) = 0) then
begin begin
Result := ''; Exit('');
Exit;
end; end;
SB := TStringBuilder.Create; SB := TStringBuilder.Create;
for I := 1 to Count do for I := 1 to Count do
@ -501,8 +497,7 @@ begin
Len := Length(S); Len := Length(S);
if Len >= Width then if Len >= Width then
begin begin
Result := S; Exit(S);
Exit;
end; end;
PadCount := Width - Len; PadCount := Width - Len;
SB := TStringBuilder.Create; SB := TStringBuilder.Create;
@ -521,8 +516,7 @@ begin
Len := Length(S); Len := Length(S);
if Len >= Width then if Len >= Width then
begin begin
Result := S; Exit(S);
Exit;
end; end;
PadCount := Width - Len; PadCount := Width - Len;
SB := TStringBuilder.Create; SB := TStringBuilder.Create;
@ -604,8 +598,7 @@ var
begin begin
if High(Parts) < 0 then if High(Parts) < 0 then
begin begin
Result := ''; Exit('');
Exit;
end; end;
SB := TStringBuilder.Create; SB := TStringBuilder.Create;
for I := 0 to High(Parts) do for I := 0 to High(Parts) do

View file

@ -81,8 +81,7 @@ var
begin begin
if APath = '' then if APath = '' then
begin begin
Result := GetCurrentDir; Exit(GetCurrentDir);
Exit;
end; end;
{ Determine base: absolute or relative } { Determine base: absolute or relative }