diff --git a/src/comp/CCSyntax.hs b/src/comp/CCSyntax.hs index b1428f201..c85629ace 100644 --- a/src/comp/CCSyntax.hs +++ b/src/comp/CCSyntax.hs @@ -675,10 +675,24 @@ instance PPrint CCFragment where pPrint d p (CPPInclude file True) = text ("#include <" ++ file ++ ">") pPrint d p (CPPInclude file False) = text ("#include \"" ++ file ++ "\"") pPrint d p (CIf c th Nothing) = - (text "if (") <> (pp c) <> (text ")") $+$ (printClauseOrBlock th) + -- If the true-arm is a nested if-stmt with an else-clause, + -- possibly under layers of for-stmts with single elements, + -- then braces are needed to avoid an ambiguous-else warning + let needsBraces (CIf _ _ (Just _)) = True + needsBraces (CFor _ _ _ b) = needsBraces b + needsBraces _ = False + th' = if (needsBraces th) then CBlock [th] else th + in (text "if (") <> (pp c) <> (text ")") $+$ (printClauseOrBlock th') pPrint d p (CIf c th (Just el)) = - (text "if (") <> (pp c) <> (text ")") $+$ - (printClauseOrBlock th) $+$ (text "else") $+$ (printClauseOrBlock el) + -- If the true-arm is a nested if-stmt without an else-clause, + -- possibly under layers of for-stmts with single elements, + -- then braces are needed for correct parsing + let needsBraces (CIf _ _ Nothing) = True + needsBraces (CFor _ _ _ b) = needsBraces b + needsBraces _ = False + th' = if (needsBraces th) then CBlock [th] else th + in (text "if (") <> (pp c) <> (text ")") $+$ + (printClauseOrBlock th') $+$ (text "else") $+$ (printClauseOrBlock el) pPrint d p (CSwitch idx arms deflt) = let ppArm (n, blk) = (text "case") <+> (pp n) <> (text ":") $+$ nest 2 (vsep (map printStmt blk)) diff --git a/testsuite/bsc.bluesim/misc/NestedIfBraces.bsv b/testsuite/bsc.bluesim/misc/NestedIfBraces.bsv new file mode 100644 index 000000000..310f064dd --- /dev/null +++ b/testsuite/bsc.bluesim/misc/NestedIfBraces.bsv @@ -0,0 +1,28 @@ + + +ActionValue #(Bit #(32)) cur_cycle = actionvalue + Bit #(32) t <- $stime; + if (genVerilog) + t = t + 5; + return t / 10; + endactionvalue; + +(* synthesize *) +module sysNestedIfBraces (); + + Reg #(Bit #(4)) cfg_verbosity <- mkReg (1); + + Reg #(Bool) rg_state <- mkReg (False); + + rule rl_display (! rg_state); + if (cfg_verbosity != 0) + $display ("%0d: display", cur_cycle); + rg_state <= True; + endrule + + rule rl_finish (rg_state); + $finish (0); + endrule + +endmodule + diff --git a/testsuite/bsc.bluesim/misc/misc.exp b/testsuite/bsc.bluesim/misc/misc.exp index 1adc4f7cc..ef5ee29b8 100644 --- a/testsuite/bsc.bluesim/misc/misc.exp +++ b/testsuite/bsc.bluesim/misc/misc.exp @@ -90,3 +90,13 @@ compile_object_pass AVMethBDPIWithReset.bsv copy c_func.c.keep c_func.c link_objects_pass {} sysAVMethBDPIWithReset {c_func.c} } + +# GitHub #442: Nested if-else needs braces when possible ambiguity +# This tests "if (!RST) if (cond) e1 else e2" in the code for +# executing system tasks. +if {$ctest == 1} { + compile_object_pass NestedIfBraces.bsv + link_objects_pass {} sysNestedIfBraces + # Test that there were no warnings during C++ compilation + compare_file [make_bsc_ccomp_output_name sysNestedIfBraces] +} diff --git a/testsuite/bsc.bluesim/misc/sysNestedIfBraces.bsc-ccomp-out.expected b/testsuite/bsc.bluesim/misc/sysNestedIfBraces.bsc-ccomp-out.expected new file mode 100644 index 000000000..535018a67 --- /dev/null +++ b/testsuite/bsc.bluesim/misc/sysNestedIfBraces.bsc-ccomp-out.expected @@ -0,0 +1,4 @@ +Bluesim object created: sysNestedIfBraces.{h,o} +Bluesim object created: model_sysNestedIfBraces.{h,o} +Simulation shared library created: sysNestedIfBraces.cexe.so +Simulation executable created: sysNestedIfBraces.cexe