24 Commits
Author SHA1 Message Date
Daniel Grunwald 60efa214b9 NullCoalescingInstruction: use a more detailed invariant.
Compute the underlying result type instead of storing it explicitly.
2026-09-05 22:11:12 +02:00
Daniel Grunwald 5526400b17 Extend InferType() to every ILInstruction
Change InferType() to an abstract method and implement for every ILInstruction.
With this change, we now always have enough information to create a variable of an appropriate type to store the result of evaluating the instruction.
This previously was not the case for instructions producing "other value type", for which the stacktype-based fallback incorrectly produced `object`.
2026-08-30 21:25:45 +02:00
Siegfried Pammer 5d49a2f751 Simplify hoisted null-guard fold to reference-type constructor chains
A value-type constructor chains via 'this = new TSelf(...)', an ordinary
body statement, so a hoisted argument null-guard in front of it is legal
C# output as-is; folding it back only bought lifting the chain into a
this(...) initializer. That cosmetic gain does not justify the extra
stobj shape matching, so the guard now stays in the body for structs and
the gate reduces to the ChainedConstructorCallILOffset check.

Assisted-by: Claude:claude-fable-5:Claude Code
2026-07-05 20:42:33 +02:00
Siegfried Pammer a1f9a6b6f5 Fix #3824: fold a hoisted argument null-guard at the ILAst level
When a chained constructor-call argument contains a throwing null-check
(e.g. `value?.Length ?? throw ...`) and the argument is evaluated more
than once, the compiler hoists the null-check in front of the chained
call. The hoisted `if (value == null) throw ...;` then became the first
body statement, so MoveConstructorInitializer could not recognize the
chained call and left it as an illegal in-body `base..ctor(...)` /
`this..ctor(...)` (a parse error).

Fix it in the ILAst, where the `?? throw` shape already lives, rather
than re-deriving it on the C# AST: NullCoalescingTransform folds a guard
that directly precedes the chained call back into the first use of the
parameter as `if.notnull(ldloc param, throw)`. Nothing in a constructor
body can legally run before the chained call, so a statement preceding it
is necessarily compiler-hoisted; matching is by ILVariable identity, not
parameter name. The guard disappears before the AST transforms run, so
they need no change.

Reference types chain via a base/this..ctor CallInstruction; value types
chain via `this = new TSelf(...)`, i.e. stobj(ldthis, newobj TSelf(...)),
which ChainedConstructorCallILOffset does not report -- so the value-type
chain (including the case where this is spilled to a stack slot because
the guard sits between its load and the call) is matched directly.

Assisted-by: Claude:claude-opus-4-8:Claude Code
2026-07-05 10:14:42 +02:00
Peter Crabtree e1e16b64f5 dev: Strip BOM mark from text files 2025-08-28 20:56:19 -04:00
dotnet format 0d9f871a4f #2128: Reformat the whole code base. 2020-08-28 01:05:38 +02:00
Daniel Grunwald 2acc4339df #2058: Mark most transforms as public to help users that use the ILAst directly without decompiling to C#. 2020-07-22 21:25:22 +02:00
Siegfried Pammer 65f9fe1076 Remove unused code. 2019-08-03 21:21:24 +02:00
Siegfried Pammer fd24b5ea26 Simplify check for addresses 2019-08-03 21:08:21 +02:00
Siegfried Pammer c0f954aaa6 Simplify nullable value types throw expression pattern. 2019-08-03 20:52:31 +02:00
Siegfried Pammer 50c4fa1c13 Add two more patterns with throw expressions. 2019-07-30 00:44:42 +02:00
Siegfried Pammer 7d4b4c6433 Implement NullCoalescingTransform with value types. 2019-07-28 15:39:47 +02:00
Siegfried Pammer c6f4f77b57 Reorder code in NullCoalescingTransform.cs 2019-05-10 08:59:55 +02:00
Siegfried Pammer 1e64d37d15 Merge branch 'master' of https://github.com/icsharpcode/ILSpy into throwExpression 2019-05-09 17:19:17 +02:00
Siegfried Pammer 875af13934 Fix #750: Missing recognizer for ?? when rhs is an assignment expression 2018-12-22 11:47:32 +01:00
Daniel Grunwald 58b0ddda9e Add ThrowExpressionConversion. 2018-06-02 09:16:02 +02:00
Daniel Grunwald 21d3881e37 Introduce named arguments only in the statement transform.
Don't use extension method syntax when 'this' parameter of
extension method is named.
2018-06-01 17:13:18 +02:00
Andreas Weizel a254913624 Work for throw expressions. 2018-06-01 13:39:34 +02:00
Daniel Grunwald ca0fa55af8 Implement null propagation transform. 2018-01-12 20:27:49 +01:00
Daniel Grunwald 7017c6f6e6 Replace LoopingBlockTransform with StatementTransform.
This transform interleaves statement-combining transforms so that nested structures can be detected better.
2017-09-27 21:42:17 +02:00
Daniel Grunwald 4830b37ab9 [nullables] Add support for '??' operator on nullables. 2017-09-19 23:52:08 +02:00
Daniel Grunwald 33099c5d65 [nullables] Extend nullable lifting to arbitrary combinations of 'conv' and 'binary.numeric'. 2017-09-18 23:26:51 +02:00
Siegfried Pammer bcaf6db313 Fix use of Clone in NullCoalescingTransform 2017-08-23 10:06:19 +02:00
Siegfried Pammer 5007c660ca Add NullCoalescingInstruction 2017-08-22 20:39:17 +02:00