https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118277

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Calling cxx_constant_value on a random expression when processing_template_decl
is wrong, the function to call when processing_template_decl is
fold_non_dependent_expr instead.  If it returns the desired constant expression
(non-dependent), great, it can be used as is, otherwise it should be saved and
the cxx_constant_value and extraction etc. repeated only during instantiation
time.

In many places, if some expressions are non-dependent when
processing_template_decl,
a lot of routines try to use them (to be able to diagnose errors already when
parsing
a template rather than only when instantiating it), but in the end usually for
the processing_template_decl case it will build something with the original
expressions and then repeat from pt.cc (which can be again with
processing_template_decl if it is partial specialization, or with
!processing_template_decl otherwise).

In the finish_asm_stmt case we actually don't bother though, for
processing_template_decl most of the function is actually skipped and it just
builds ASM_EXPR at the end.

So, I'd suggest to move most of the cp_parser_asm_string_expression handling to
the start of finish_asm_stmt (right into the if (!processing_template_decl)
block).
cp_parser_asm_string_expression should just handle the STRING_CST case as it
was handling it before, and for the CPP_OPEN_PAREN case just similarly to the
static_assert handling just ensure that string from it will never be a
STRING_CST.
So, in cp_parser_asm_string_expression just:
  if (tok->type == CPP_OPEN_PAREN)
    { 
      matching_parens parens;
      parens.consume_open (parser);
      tree string = cp_parser_constant_expression (parser);
      if (TREE_CODE (string) == STRING_CST)
        string = build1_loc (tok->location, PAREN_EXPR, TREE_TYPE (string),
                             string);
      parens.require_close (parser);
      return string;
    }
and in finish_asm_stmt call a helper function which will do the
      if (string != error_mark_node)
        string = cxx_constant_value (string, tf_error);
      cexpr_str cstr (string);
      if (!cstr.type_check (tok->location))
        return error_mark_node;
      if (!cstr.extract (tok->location, string))
        string = error_mark_node;
handling if TREE_CODE (string) != STRING_CST.  But needs to do it not just in
the case of the asm template string, but all the clobbers and constraints.

It isn't that easy though, because cp_parser_asm_string_expression isn't used
just for asm statements with extended and basic syntax (i.e. asm ((...) : ...);
and asm ((...));) but also in cp_parser_asm_specification_opt.
That is mostly for declarations,
void foo (int) asm ("bar");
I'm not really sure if that was intentionally changed, I don't see that covered
in the testsuite, stuff like
template <typename T>
constexpr S<T> bar () { ... }
template <typename T>
void foo (T, T) asm ((bar<T> ());
void baz () { foo (0, 0); }
and the like.  If you want to handle it, you'll need to handle it during
instantiation in all the places into which the cp_parser_asm_specification_opt
result is stored (plus add testcases).

BTW, another possibility would be to keep doing the
cp_parser_asm_string_expression extra part I've left out by calling the helper
function in there too for !processing_template_decl, but that could only hide
that it needs to be repeated at instantiation time if it was skipped during
parsing time.

Reply via email to