Unknown members
If you write sq.scal(2.0), where sq is a handle (a variable that refers to a class object, such as sq in square sq;) and the class square has no scal, a simulator rejects it only when it elaborates the design
(builds it before running). The Unknown member of a class or struct inspection (a check the IDE runs as you type and
shows in the editor) underlines it at once. It marks a name after . that the type does not declare, where the IDE knows
every member the type can have. It is on by default, at level Error (change the level under Settings | Editor | Inspections | SystemVerilog).
Try it
Section titled “Try it”The steps use the sample project; open it and wait for indexing first.
- Open
classes/shapes.sv, findsq.scale(2.0);inshapes_demo(⌘F / Ctrl+F) and change it tosq.scal(2.0);. scalis underlined in red. Hover over it to read the message:'scal' is not a member of class 'square'; did you mean 'scale'?- Put the caret (the text cursor) on
scal, press ⌥Enter (macOS) / Alt+Enter (Windows/Linux) and choose Change to ‘scale’: the line readssq.scale(2.0);again and the underline is gone. (Or undo with ⌘Z / Ctrl+Z until the line readssq.scale(2.0);again.)
If nothing is underlined, see Nothing underlined?.
What it reports
Section titled “What it reports”Each row is a one-line excerpt. Rows 1 and 3 misspell a name that exists (scb_chek for scb_check, adr for addr); the others name
something the type does not have; the middle column shows what the IDE sees declared.
| Code | Where the name is declared | Reported |
|---|---|---|
cfg.scb_chek = 1; |
my_cfg cfg;, my_cfg and its base classes declare scb_check |
'scb_chek' is not a member of class 'my_cfg'; did you mean 'scb_check'? |
cfg.seq_cfg.check_mem_post = 1; |
seq_cfg_c seq_cfg; in the configuration class |
'check_mem_post' is not a member of class 'seq_cfg_c' |
op.adr = 1; |
typedef struct { int addr; int data; } op_t; op_t op; |
'adr' is not a field of 'op_t' |
s.b = 1; |
struct { int a; } s; |
'b' is not a field of the struct |
assign t = u_sub.no_such_sig; |
sub u_sub (…);, module sub does not declare no_such_sig |
'no_such_sig' is not declared in module 'sub' |
When the name you typed is one edit away from a member (one character added, removed or changed, or two
neighbouring characters swapped), or two edits if your name has five characters or more, the message suggests that member and
⌥Enter / Alt+Enter offers Change to ‘…’, which writes it. If several members are equally close, the
class’s own member comes before a base class’s, then the one declared first. Names of three characters or fewer get no
suggestion (adr above), and neither does a name no member is that close to (check_mem_post). The distance rule
is the same as for undeclared names. Candidates are:
- for a class, the members of the class and its base classes that this code may use (not a base class’s
localmember; built-in methods such asrandomizeincluded); - for a struct, its fields;
- for an instance, the names its module, interface or program declares.
Members include covergroups declared in a class (w.err_cg.sample(1), where w is a handle to a class that declares the
covergroup err_cg) and constraints (item.stop_bit_c.constraint_mode(0), where item is a handle to a class with a
constraint stop_bit_c). Built-in class methods are not reported: randomize, srandom, get_randstate,
set_randstate, rand_mode, constraint_mode, pre_randomize and post_randomize. (The language rules behind the checks are IEEE 1800-2017 §8.4 for classes and §7.2 for structs.)
Handles typed by a type parameter
Section titled “Handles typed by a type parameter”A handle typed by a class type parameter is checked, in a subclass, against the class that subclass binds it to. CFG_T below is a placeholder type that each subclass fills in; here my_vseq fills it with my_cfg (a class that declares scb_check, not scb_chek), so the inherited handle cfg is checked against my_cfg:
class base_vseq #(type CFG_T = base_cfg); CFG_T cfg;endclass
class my_vseq extends base_vseq #(.CFG_T(my_cfg)); function void f(); cfg.scb_chek = 1; // 'scb_chek' is not a member of class 'my_cfg' endfunctionendclassThis includes defaults that name another parameter (type RSP = REQ). Inside a parameterized class that passes its own
parameter on (class my_drv #(type REQ = item) extends uvm_driver #(REQ)), the handle is not checked: the class may be
used with another type.
Names after an instance
Section titled “Names after an instance”A name after an instance (for an instance u_sub of a module sub, u_sub.x is reported when sub has no x; also u_arr[0].x and g_subs[1].u_g.x) is checked against the module, interface or
program the instance is of (called a unit below; §23.6): its ports, parameters, signals, instances, generate block
names, tasks and functions. To avoid false errors, it stays silent when:
- that unit is defined more than once (two libraries) or not found;
- the unit itself writes the name (an implicit net, an assertion label), or it is an unnamed generate block’s
genblk1; - the unit’s inactive
`ifdefcode, its macro calls or its included files may declare the name (as for undeclared names); - a
bindanywhere in the project writes the name (a bind adds an instance to the unit, §23.11).
Nothing underlined?
Section titled “Nothing underlined?”A name is reported only where the IDE sees every member the type can have. The most likely reasons it is not:
| Likely cause | What to do |
|---|---|
A base class is not in the project (for example the UVM library, when the class extends uvm_object) |
Add the library sources to the project; see Known limitations |
A macro or an `include in the class, which the IDE cannot expand or find |
Check the macro is defined and the file is found; see Macros |
The name is in code an `ifdef switches off |
See Conditional compilation |
| The inspection is turned off | Check Settings (⌘, / Ctrl+Alt+S) | Editor | Inspections | SystemVerilog | Unknown member of a class or struct |
| Indexing (the IDE scanning your files) is not finished | Wait for the progress bar at the bottom right to disappear |
If the name is underlined but ⌥Enter / Alt+Enter shows no Change to ‘…’: the caret is not on the underlined name, or no member is close enough to suggest (the message then has no “did you mean”). Put the caret on the name, or correct it by hand.
The full list of cases that are not reported
The chain below is the class and its base classes.
It is not reported when:
- a class in the chain extends a class the IDE cannot find;
- a class in the chain has a macro it cannot expand, or an
`includein its body; - the name is written in an inactive
`ifdefbranch of a class in the chain, or that branch calls a macro; - the name is written in code of a class in the chain that does not parse, or in a macro expansion that does not
parse on its own (UVM’s
`uvm_field_*macros parse only together with`uvm_object_utils_begin); - a struct body has a macro call (
`FIELD(x)); - the handle’s type is a class type parameter that no subclass binds, or binds to a type the IDE cannot find (a generated register block that is not in the checkout);
- the handle’s type cannot be found;
- the handle is an array (
q.size()is an array method); - the handle is a virtual interface;
- the name follows
this.orsuper.; - the name is inside a macro’s arguments, unless every
`defineof the macro writes that argument as code (`DV_CHECK_EQ(cfg.scb_chek, 1)is checked). Not checked: an argument a definition only stringifies with`"…`", pastes with``, passes on to another macro or writes only inside an`ifdef; an argument whose first name the body writes itself (the body may declare it:begin cfg_t cfg = …; S end); any argument of a macro whose body haswith(arandomize() withscope looks names up in the object first); a call inside another call’s arguments.