Add check for explicit lifetime when initialising static variables.
If a static variable declared in a task, function, or block has an
initialisation expression, SystemVerilog requires the declaration to
have an explicit static lifetime. This is supposed to be a compile
error, but for now just output a warning.
Implementing this required adding support in the parser for explicit
lifetimes in variable declarations. For now, just output an error if
the user asks for a lifetime that isn't the default for that scope.
(cherry picked from commit 9538c81d34)
This commit is contained in:
parent
7d2eeb0137
commit
5bbb054173
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
# include "PScope.h"
|
||||
|
||||
bool LexicalScope::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
: LexicalScope(parent), name_(n)
|
||||
{
|
||||
|
|
@ -58,4 +63,3 @@ PScopeExtra::PScopeExtra(perm_string n)
|
|||
PScopeExtra::~PScopeExtra()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
7
PScope.h
7
PScope.h
|
|
@ -53,11 +53,12 @@ class NetScope;
|
|||
class LexicalScope {
|
||||
|
||||
public:
|
||||
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
|
||||
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||
|
||||
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
|
||||
// A virtual destructor is so that dynamic_cast can work.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||
lifetime_t default_lifetime;
|
||||
|
||||
struct range_t {
|
||||
|
|
@ -124,6 +125,8 @@ class LexicalScope {
|
|||
|
||||
LexicalScope* parent_scope() const { return parent_; }
|
||||
|
||||
virtual bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
protected:
|
||||
void dump_typedefs_(ostream&out, unsigned indent) const;
|
||||
|
||||
|
|
|
|||
5
PTask.cc
5
PTask.cc
|
|
@ -30,6 +30,11 @@ PTaskFunc::~PTaskFunc()
|
|||
{
|
||||
}
|
||||
|
||||
bool PTaskFunc::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return default_lifetime == STATIC;
|
||||
}
|
||||
|
||||
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
|
|
|
|||
2
PTask.h
2
PTask.h
|
|
@ -41,6 +41,8 @@ class PTaskFunc : public PScope, public LineInfo {
|
|||
PTaskFunc(perm_string name, LexicalScope*parent);
|
||||
~PTaskFunc();
|
||||
|
||||
bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
void set_ports(std::vector<pform_tf_port_t>*p);
|
||||
|
||||
void set_this(class_type_t*use_type, PWire*this_wire);
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ PBlock::~PBlock()
|
|||
delete list_[idx];
|
||||
}
|
||||
|
||||
bool PBlock::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return default_lifetime == STATIC;
|
||||
}
|
||||
|
||||
PChainConstructor* PBlock::extract_chain_constructor()
|
||||
{
|
||||
if (list_.empty())
|
||||
|
|
|
|||
|
|
@ -183,6 +183,8 @@ class PBlock : public PScope, public Statement {
|
|||
|
||||
BL_TYPE bl_type() const { return bl_type_; }
|
||||
|
||||
bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
// This is only used if this block is the statement list for a
|
||||
// constructor. We look for a PChainConstructor as the first
|
||||
// statement, and if it is there, extract it.
|
||||
|
|
|
|||
45
parse.y
45
parse.y
|
|
@ -65,6 +65,10 @@ static PTask* current_task = 0;
|
|||
static PFunction* current_function = 0;
|
||||
static stack<PBlock*> current_block_stack;
|
||||
|
||||
/* The variable declaration rules need to know if a lifetime has been
|
||||
specified. */
|
||||
static LexicalScope::lifetime_t var_lifetime;
|
||||
|
||||
static pform_name_t* pform_create_this(void)
|
||||
{
|
||||
name_component_t name (perm_string::literal("@"));
|
||||
|
|
@ -667,7 +671,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
%type <int_val> atom2_type
|
||||
%type <int_val> module_start module_end
|
||||
|
||||
%type <lifetime> lifetime_opt
|
||||
%type <lifetime> lifetime lifetime_opt
|
||||
|
||||
%token K_TAND
|
||||
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
||||
|
|
@ -1369,10 +1373,14 @@ jump_statement /* IEEE1800-2005: A.6.5 */
|
|||
}
|
||||
;
|
||||
|
||||
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
|
||||
lifetime /* IEEE1800-2005: A.2.1.3 */
|
||||
: K_automatic { $$ = LexicalScope::AUTOMATIC; }
|
||||
| K_static { $$ = LexicalScope::STATIC; }
|
||||
| { $$ = LexicalScope::INHERITED; }
|
||||
;
|
||||
|
||||
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
|
||||
: lifetime { $$ = $1; }
|
||||
| { $$ = LexicalScope::INHERITED; }
|
||||
;
|
||||
|
||||
/* Loop statements are kinds of statements. */
|
||||
|
|
@ -2254,6 +2262,19 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
|
|||
}
|
||||
;
|
||||
|
||||
variable_lifetime
|
||||
: lifetime
|
||||
{ if (!gn_system_verilog()) {
|
||||
yyerror(@1, "error: overriding the default variable lifetime "
|
||||
"requires SystemVerilog.");
|
||||
} else if ($1 != pform_peek_scope()->default_lifetime) {
|
||||
yyerror(@1, "sorry: overriding the default variable lifetime "
|
||||
"is not yet supported.");
|
||||
}
|
||||
var_lifetime = $1;
|
||||
}
|
||||
;
|
||||
|
||||
/* Verilog-2001 supports attribute lists, which can be attached to a
|
||||
variety of different objects. The syntax inside the (* *) is a
|
||||
comma separated list of names or names with assigned values. */
|
||||
|
|
@ -2328,10 +2349,20 @@ block_item_decl
|
|||
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
|
||||
}
|
||||
|
||||
| variable_lifetime data_type register_variable_list ';'
|
||||
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||
var_lifetime = LexicalScope::INHERITED;
|
||||
}
|
||||
|
||||
| K_reg data_type register_variable_list ';'
|
||||
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||
}
|
||||
|
||||
| variable_lifetime K_reg data_type register_variable_list ';'
|
||||
{ if ($3) pform_set_data_type(@3, $3, $4, NetNet::REG, attributes_in_context);
|
||||
var_lifetime = LexicalScope::INHERITED;
|
||||
}
|
||||
|
||||
| K_event event_variable_list ';'
|
||||
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
||||
}
|
||||
|
|
@ -5492,7 +5523,13 @@ register_variable
|
|||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER dimensions_opt '=' expression
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
{ if (pform_peek_scope()->var_init_needs_explicit_lifetime()
|
||||
&& (var_lifetime == LexicalScope::INHERITED)) {
|
||||
cerr << @3 << ": warning: Static variable initialization requires "
|
||||
"explicit lifetime in this context." << endl;
|
||||
warn_count += 1;
|
||||
}
|
||||
perm_string name = lex_strings.make($1);
|
||||
pform_makewire(@1, name, NetNet::REG,
|
||||
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
||||
pform_set_reg_idx(name, $2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue