This is an archive of the discontinued LLVM Phabricator instance.

[Clang] Copy strictfp attribute from pattern to instantiation
ClosedPublic

Authored by sepavloff on Feb 13 2023, 8:01 AM.

Details

Summary

If a template function contained a pragma that made it strictfp, code
generation for such function crashed, because the instantiation did not
have strictfp attribute. As a solution this attribute is copied from the
template to instantiation.

Diff Detail

Event Timeline

sepavloff created this revision.Feb 13 2023, 8:01 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 13 2023, 8:01 AM
sepavloff requested review of this revision.Feb 13 2023, 8:01 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 13 2023, 8:01 AM

We have code somewhere to generically copy attributes from function templates to instantiations, right? Why do we need to explicitly copy StrictFPAttr in particular, separate from that?

We have code somewhere to generically copy attributes from function templates to instantiations, right? Why do we need to explicitly copy StrictFPAttr in particular, separate from that?

Could you please point me out to this code? I didn't find it.

rjmccall added a comment.EditedFeb 13 2023, 12:20 PM

We have code somewhere to generically copy attributes from function templates to instantiations, right? Why do we need to explicitly copy StrictFPAttr in particular, separate from that?

Could you please point me out to this code? I didn't find it.

It's the call to InstantiateAttrs in InitFunctionInstantiation. InstantiateAttrs hard-codes a list of attributes to clone, which seems like a bad design, but it's easy enough to add your attribute as another case to that list.

sepavloff updated this revision to Diff 497609.Feb 15 2023, 2:52 AM

Changed the way to copy strictfp attribute

We have code somewhere to generically copy attributes from function templates to instantiations, right? Why do we need to explicitly copy StrictFPAttr in particular, separate from that?

Could you please point me out to this code? I didn't find it.

It's the call to InstantiateAttrs in InitFunctionInstantiation. InstantiateAttrs hard-codes a list of attributes to clone, which seems like a bad design, but it's easy enough to add your attribute as another case to that list.

Thanks!
InstantiateAttrs is updated accordingly. It solves the problem but not for late-parsed templates. Strictfp is evaluated based on function body, but when a declaration for late-parsed template is instantiated, the body is absent yet. A new method is added to Sema to make attribute update when template body is available.

If the "strictfp" attribute is based on the contents of the function body, should we recompute it when the function is instantiated, as opposed to copying it? For example, say you have a pragma inside an "if constexpr"; should that set the strictfp attribute if it's discarded?

Otherwise, I guess updateAttrsForLateParsedTemplate makes sense.

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
817

Is this necessary? The non-delayed-parsed case seems to work correctly on trunk without any changes, so I suspect the autogenerated sema::instantiateTemplateAttribute is doing the right thing.

If the "strictfp" attribute is based on the contents of the function body, should we recompute it when the function is instantiated, as opposed to copying it? For example, say you have a pragma inside an "if constexpr"; should that set the strictfp attribute if it's discarded?

Otherwise, I guess updateAttrsForLateParsedTemplate makes sense.

Recomputing is certainly a better solution, as it would provide actual properties. It however should be applied to all instantiations, not only late parsed. With this change the code:

template <typename T, bool F>
T templ_01(T x, T y) {
  if constexpr (F) {
    #pragma STDC FENV_ACCESS ON
    return x - y;
  } else
  return x + y;
}

float func_02(float x, float y) {
  return templ_01<float, true>(x, y);
}

float func_03(float x, float y) {
  return templ_01<float, false>(x, y);
}

compiled without late parsing produces func_03 with strictfp attribute. However constarined intrinsics in it are semantically equivalent to non-constrained operations. Adding unneeded strictfp attribute is not an error.

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
817

Yes, it is necessary. Without it the code from the added test crashes, as constrained intrinsic is used in a function without strictfp attribute.

efriedma added inline comments.Feb 16 2023, 6:02 PM
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
817

https://godbolt.org/z/MvPrejY75 indicates this is only an issue with -fdelayed-template-parsing; am I missing something?

sepavloff updated this revision to Diff 498248.Feb 16 2023, 9:19 PM

Remove copying StrictFPAttr from InstantiateAttrs

sepavloff added inline comments.Feb 16 2023, 9:21 PM
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
817

Indeed. I used Windows where this flag is on by default. Thank you for the catch.
Removed.

This revision is now accepted and ready to land.Feb 17 2023, 11:22 AM