Files
iverilog/driver
Lars-Peter Clausen 7616d47c11 Resolve type identifiers during elaboration
`typeref_t` stores the `typedef_t` selected by the parser. This binds a type
identifier before the elaborated scope is available and can select the wrong
declaration. Function and task declarations are visible throughout their
scope, so a later subroutine named `T` in the current scope hides an earlier
`T` type in an outer scope even when the type reference appears before the
subroutine declaration. Parser-time lookup can not handle this correctly.

For example:

    typedef int T;

    module test;
      T value;

      function T;
        T = 0;
      endfunction
    endmodule

The declaration of `value` must be rejected because the local function named
`T` hides the outer typedef. The same applies to a task named `T`.

Type lookup can also depend on information that is not available to the parser.
For example, a parameterized class can extend a type parameter and inherit `T`
from the selected base class:

    class Derived #(type B = DefaultBase) extends B;
      T value;
    endclass

Parameterized classes are not supported yet, but resolving named types during
elaboration is a prerequisite for supporting this case.

Replace `typeref_t` with `type_identifier_t`, which owns a `PEIdent`. Construct
the identifier in the parser, then resolve it through
`PEIdent::elaborate_type()` and `symbol_search()` while elaborating the data
type. Parser-time type lookup is only used to select grammar paths.
`pform_new_ident()` preserves wildcard import activation for the identifier
expression.

Enforce declaration ordering when an identifier occurs in a grammar position
that requires a data type, even when compatibility options relax it for
ordinary variable lookup. A later variable therefore does not hide an outer
type in a declaration, and a later type declaration can not satisfy an earlier
use. Keep ordinary lookup when an identifier can be either a type or a value,
such as an argument to `$bits()`. Add
`SYMBOL_SEARCH_STRICT_DECLARATION_ORDER` and a required-type elaboration context
for the former case.

For example:

    typedef logic [7:0] T;

    module test;
      T value;
      localparam int A = $bits(value);
      localparam int B = $bits(T);

      integer T;
    endmodule

The declaration of `value` uses the outer typedef, so `A` is 8. With relaxed
variable declaration ordering, the ambiguous reference in `$bits(T)` uses the
later integer, so `B` is 32.

Check a constant's declaration position before `get_parameter()` elaborates it
on demand when declaration order is enforced. This keeps a later declaration in
`parameter T T` from recursively selecting itself as the type.

Recover a failed deferred lookup in `type_identifier_t` with a scalar logic type
after reporting the error. This keeps the existing non-null expectations of
type consumers unchanged.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-09-01 16:46:36 -07:00
..
2024-11-26 23:33:52 -08:00
2026-07-20 21:24:03 -07:00
2026-01-13 01:25:01 -08:00