From 6cf8493ccad352afcd45cf21a58fc290b8c00ba3 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Fri, 3 Feb 2023 20:43:51 +0000 Subject: [PATCH] Fix nested conditional analysis directives. Issue #604 --- src/scan.c | 53 ++++++++++++++++++++++++++++------------- test/parse/issue604.vhd | 16 +++++++++++++ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/scan.c b/src/scan.c index 2e891cf3..b5d4ba9f 100644 --- a/src/scan.c +++ b/src/scan.c @@ -18,6 +18,7 @@ #include "util.h" #include "array.h" #include "diag.h" +#include "option.h" #include "scan.h" #include @@ -26,6 +27,7 @@ #include #include #include +#include #include typedef struct { @@ -44,6 +46,7 @@ static loc_file_ref_t file_ref = FILE_INVALID; static int colno; static int lineno; static int lookahead; +static int pperrors; static cond_stack_t cond_stack; extern int yylex(void); @@ -115,6 +118,7 @@ void input_from_file(const char *file) lineno = 1; colno = 0; lookahead = -1; + pperrors = 0; } hdl_kind_t source_kind(void) @@ -209,11 +213,25 @@ static int pp_yylex(void) return tok; } +static void pp_error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + if (pperrors++ == 0 || opt_get_int(OPT_UNIT_TEST)) { + diag_t *d = diag_new(DIAG_ERROR, &yylloc); + diag_vprintf(d, fmt, ap); + diag_emit(d); + } + + va_end(ap); +} + static bool pp_expect(int expect) { const int got = pp_yylex(); if (got != expect) { - error_at(&yylloc, "expected $yellow$%s$$ while parsing conditional " + pp_error("expected $yellow$%s$$ while parsing conditional " "directive but found $yellow$%s$$", token_str(expect), token_str(got)); return false; @@ -256,8 +274,7 @@ static bool pp_cond_analysis_relation(void) if (pp_expect(tSTRING)) { const char *value = get_cond_analysis_identifier(name); if (value == NULL) - error_at(&yylloc, "undefined conditional analysis " - "identifier %s", name); + pp_error("undefined conditional analysis identifier %s", name); else { char *cmp = yylval.s + 1; cmp[strlen(cmp) - 1] = '\0'; @@ -282,7 +299,7 @@ static bool pp_cond_analysis_relation(void) result = strcmp(value, cmp) >= 0; break; default: - error_at(&yylloc, "expected conditional analysis relation " + pp_error("expected conditional analysis relation " "but found $yellow$%s$$", token_str(rel)); break; } @@ -296,7 +313,7 @@ static bool pp_cond_analysis_relation(void) break; default: - error_at(&yylloc, "unexpected $yellow$%s$$ while parsing conditional " + pp_error("unexpected $yellow$%s$$ while parsing conditional " "analysis relation", token_str(tok)); } @@ -312,7 +329,7 @@ static bool pp_cond_analysis_expr(void) // | conditional_analysis_relation { xnor conditional_analysis_relation } const bool lhs = pp_cond_analysis_relation(); - switch ((lookahead = yylex())) { + switch ((lookahead = pp_yylex())) { case tAND: lookahead = -1; return pp_cond_analysis_relation() && lhs; @@ -336,14 +353,19 @@ int processed_yylex(void) assert(lookahead == -1); for (;;) { - token_t token = lookahead != -1 ? lookahead : yylex(); - lookahead = -1; + token_t token = pp_yylex(); switch (token) { case tCONDIF: { cond_state_t new = { .loc = yylloc }; new.result = new.taken = pp_cond_analysis_expr(); + if (cond_stack.count > 0 && !ATOP(cond_stack).result) { + // Suppress nested conditionals in not-taken branches + new.taken = true; + new.result = false; + } + pp_expect(tTHEN); new.loc.column_delta = @@ -357,14 +379,13 @@ int processed_yylex(void) case tCONDELSIF: { - if (cond_stack.count == 0) { - error_at(&yylloc, "unexpected $yellow$%s$$ outside conditional " + if (cond_stack.count == 0) + pp_error("unexpected $yellow$%s$$ outside conditional " "analysis block", token_str(token)); - (void)pp_cond_analysis_expr(); - } - else { - const bool result = pp_cond_analysis_expr(); + const bool result = pp_cond_analysis_expr(); + + if (cond_stack.count > 0) { if (!ATOP(cond_stack).taken) { ATOP(cond_stack).result = result; ATOP(cond_stack).taken = result; @@ -380,7 +401,7 @@ int processed_yylex(void) case tCONDELSE: { if (cond_stack.count == 0) - error_at(&yylloc, "unexpected $yellow$%s$$ outside conditional " + pp_error("unexpected $yellow$%s$$ outside conditional " "analysis block", token_str(token)); else { cond_state_t *cs = &(cond_stack.items[cond_stack.count - 1]); @@ -392,7 +413,7 @@ int processed_yylex(void) case tCONDEND: { if (cond_stack.count == 0) - error_at(&yylloc, "unexpected $yellow$%s$$ outside conditional " + pp_error("unexpected $yellow$%s$$ outside conditional " "analysis block", token_str(token)); else APOP(cond_stack); diff --git a/test/parse/issue604.vhd b/test/parse/issue604.vhd index 25b0875b..122742c8 100644 --- a/test/parse/issue604.vhd +++ b/test/parse/issue604.vhd @@ -18,4 +18,20 @@ package issue604 is `elsif TOOL_VERSION >= "3000" then `end if +`if TOOL_TYPE = "SYNTHESIS" then + `if TOOL_NAME = "Vivado" then + constant CHECK : string := "x" ; + `else + constant CHECK : string := "UNDEFINED_SYNTH" ; + `end +`else + `if TOOL_NAME = "Riviera-PRO" then + constant CHECK : string := "y" ; + `elsif TOOL_NAME = "nvc" then + constant CHECK : string := "z" ; + `else + constant CHECK : string := "UNDEFINED_SIM" ; + `end +`end + end package; -- 2.39.2