Skip to content

[Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being ON for both definition and instantiation #64605

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hubert-reinterpretcast opened this issue Aug 10, 2023 · 28 comments · Fixed by llvm/llvm-project-release-prs#627 or llvm/llvm-project-release-prs#666
Assignees
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" floating-point Floating-point math miscompilation regression release:backport release:merged

Comments

@hubert-reinterpretcast
Copy link
Collaborator

Consider:

#pragma STDC FENV_ACCESS ON
template <typename>
int b() {
  int x;
  if ((float)0xFFFFFFFF != (float)0x100000000) {
    x = 1;
  }
  return x;
}
int f() { return b<void>(); }

Clang 16 generates the floating-point operations (as is appropriate for FENV_ACCESS being ON):

f():                                  # @f()
        mov     eax, 4294967295
        cvtsi2ss        xmm0, rax
        movabs  rax, 4294967296
        cvtsi2ss        xmm1, rax
        ucomiss xmm0, xmm1
        mov     eax, 1
        ret

Clang "17" currently generates no floating-point operations:

f(): # @f()
  ret

Compiler Explorer: https://godbolt.org/z/PcoaaxzKn

Reverting fde5924 restores the previous behaviour.

@hubert-reinterpretcast hubert-reinterpretcast added clang:frontend Language frontend issues, e.g. anything involving "Sema" regression miscompilation floating-point Floating-point math labels Aug 10, 2023
@github-project-automation github-project-automation bot moved this to Needs Triage in LLVM Release Status Aug 10, 2023
@llvmbot
Copy link
Member

llvmbot commented Aug 10, 2023

@llvm/issue-subscribers-clang-frontend

@spavloff
Copy link
Collaborator

This defect is not caused by fde5924. The reason is the elimination of ImplicitCastExpr when a template is instantiated, see comment:

TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
// Implicit casts are eliminated during transformation, since they
// will be recomputed by semantic analysis after transformation.
ImplicitCastExpr keeps FP options, including rounding direction. Removing them results in FPOptions loss, they are taken from the current Sema state, which is incorrect behavior.

Revert of fde5924 accidentally fixed the behavior, because FP options used to generate code were taken from Sema state (and nof from AST node) and they were the same as at the point of the template definition. If, for example, #pragma STDC FENV_ACCESS OFF is put at the end of the file, the problem would be observed with the commit reverted.

I will prepare a fix soon.

@AaronBallman
Copy link
Collaborator

FWIW, rc3 is supposed to go out in about a week and I believe we're hoping that's one of the last rcs, so we don't have much bake time for a fix. If the fix ends up being trivial and obviously correct, then I think it may still be able to make 17.x. I'm a bit more worried about it not being a trivial change though. It sounds like fde5924 accidentally exposed an issue that is causing more miscompiles and a revert of it would get us back to the same stability as Clang 16.x, even though it's not actually a "fix" per se. Am I correct? If so, we may want to consider doing that revert from the 17.x branch so we don't introduce more miscompilations and then do the real fix for 18.x with plenty of time for testing fallout.

@spavloff
Copy link
Collaborator

I put a patch https://reviews.llvm.org/D158158, which should fix the issue.It is not a full-fledged solution (it does not support variable templates), but it should be enough for this issue. It is small and obvious, hopefully this can facilitate the review.

fde5924 fixes #63542, so revert of it exposes that issue.

@AaronBallman
Copy link
Collaborator

fde5924 fixes #63542, so revert of it exposes that issue.

To make sure I'm on the same page -- a revert would bring us back to the Clang 16 behavior (bugs and all)?

@hubert-reinterpretcast
Copy link
Collaborator Author

It is not a full-fledged solution (it does not support variable templates), but it should be enough for this issue.

It seems variable templates have another layer of problems to begin with.

Clang 16 will not generate a call to foo for the following:

#include <float.h>
struct ChangeRounding {
  ChangeRounding();
  ~ChangeRounding();
};
int foo(), bar();

#pragma STDC FENV_ACCESS ON

template <typename T>
int var = (ChangeRounding(), (T)0xFFFFFFFF != (T)0x100000000 ? foo() : bar());

int main() {
  return var<float>;
}

https://godbolt.org/z/Mnq5PoP8o

@tru tru moved this from Needs Triage to Done in LLVM Release Status Aug 21, 2023
@AaronBallman
Copy link
Collaborator

Those changes do seem quite simple and I think they're safe for a backport to 17.x, but I'd appreciate a few opinions from @hubert-reinterpretcast and @jcranmer-intel to see if they agree we should backport. The alternatives are: leave the regression in Clang 16, or revert the original changes from just the 17.x branch so we're back in the (previously also bad) state we were in for 16.

@spavloff
Copy link
Collaborator

The change 0baf85c requires also 73e5a70. The latter fixes a test from the former.

@hubert-reinterpretcast
Copy link
Collaborator Author

Those changes do seem quite simple and I think they're safe for a backport to 17.x

I agree, and I think we should backport. The original changes fixed an issue in Clang 16 that was encountered by multiple parties (so reverting is not my first choice). With the additional changes, the "regressions" known to me are addressed.

@AaronBallman
Copy link
Collaborator

Excellent, thank you @hubert-reinterpretcast

@spavloff, can you handle the backport for both commits to 17.x? (I think it's fine to squash them into one commit and only put up one PR)

spavloff added a commit to spavloff/llvm-project that referenced this issue Aug 22, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158

(cherry picked from commit 0baf85c)
(cherry picked from commit 73e5a70)
@spavloff
Copy link
Collaborator

/cherry-pick 0baf85c
/cherry-pick 73e5a70

@llvmbot
Copy link
Member

llvmbot commented Aug 22, 2023

/branch llvm/llvm-project-release-prs/issue64605

llvmbot pushed a commit to llvm/llvm-project-release-prs that referenced this issue Aug 22, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm/llvm-project#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158

(cherry picked from commit 0baf85c331090fbe2d2b42214ed0664d55feb0b5)
@llvmbot
Copy link
Member

llvmbot commented Aug 22, 2023

/pull-request llvm/llvm-project-release-prs#627

@spavloff
Copy link
Collaborator

/cherry-pick 0baf85c 73e5a70

@tru tru moved this from Needs Merge to Done in LLVM Release Status Aug 25, 2023
@dyung
Copy link
Collaborator

dyung commented Aug 27, 2023

Not sure where to put this, but ever since 73e5a70 was cherry-picked to the release/17.x branch as 73e5a70, the test clang/test/SemaCXX/template-64605.cpp has been failing on multiple release bots:

@tru
Copy link
Collaborator

tru commented Aug 27, 2023

Not sure where to put this, but ever since 73e5a70 was cherry-picked to the release/17.x branch as 73e5a70, the test clang/test/SemaCXX/template-64605.cpp has been failing on multiple release bots:

This should be fixed, I just forgot to push the commit. Will do that now.

Never mind, I thought about another issue. Yes this seems like a problem. @spavloff can you have a look?

@tru
Copy link
Collaborator

tru commented Aug 28, 2023

I ran the tests locally now and I needed to revert both e54f483 and f1d5ea3 in order for the tests to pass again. I have pushed the revert commits to the release branch for now. I will re-open this issue and hope that @spavloff can have a look at fixing the tests and re-cherry-pick the fix.

@tru tru reopened this Aug 28, 2023
@tru
Copy link
Collaborator

tru commented Aug 28, 2023

0638df0
baae3c3

@tru tru moved this from Done to Needs Pull Request in LLVM Release Status Aug 28, 2023
@jonathonpenix
Copy link
Contributor

jonathonpenix commented Aug 28, 2023

Hi, apologies in advance if this has already been addressed/mentioned elsewhere/is obvious, but in case it is helpful: I ran into this downstream and I think the failing test might just need the "implicit_instantiation" bit removed (or another commit brought in). IIUC, the ability to output this was added in 3bfafc4 which is present in main but not the release_17.x branch--template-64605.cpp was added after 3bfafc4 in main, so it expectedly has the "implicit_instantation" bit, but we don't know how to generate this in the release branch.

Again though, apologies in advance if I'm misunderstanding something/this has already been handled!

@AaronBallman
Copy link
Collaborator

Again though, apologies in advance if I'm misunderstanding something/this has already been handled!

I think you nailed the problem!

@spavloff
Copy link
Collaborator

@jpenix-quic Thank you for your analysis!

spavloff added a commit that referenced this issue Aug 30, 2023
A check pattern in clang/test/SemaCXX/template-64605.cpp contains template
specialization kind (the text "implicit_instantiation"). It does not need to
be checked and can be safely removed.

Presence of this text in the check pattern prevents from backporting some
commits to the release branch: #64605.
It has only recently been printed and the relevant commit is not present in
the release/17.x branch.
@spavloff
Copy link
Collaborator

/cherry-pick 0baf85c 73e5a70 8859c64

@llvmbot
Copy link
Member

llvmbot commented Aug 30, 2023

/branch llvm/llvm-project-release-prs/issue64605

llvmbot pushed a commit to llvm/llvm-project-release-prs that referenced this issue Aug 30, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm/llvm-project#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158

(cherry picked from commit 0baf85c331090fbe2d2b42214ed0664d55feb0b5)
llvmbot pushed a commit to llvm/llvm-project-release-prs that referenced this issue Aug 30, 2023
A check pattern in clang/test/SemaCXX/template-64605.cpp contains template
specialization kind (the text "implicit_instantiation"). It does not need to
be checked and can be safely removed.

Presence of this text in the check pattern prevents from backporting some
commits to the release branch: llvm/llvm-project#64605.
It has only recently been printed and the relevant commit is not present in
the release/17.x branch.

(cherry picked from commit 8859c644ede4898f90f77dcad2286de08a9ba62e)
@llvmbot
Copy link
Member

llvmbot commented Aug 30, 2023

/pull-request llvm/llvm-project-release-prs#666

@tru tru moved this from Needs Pull Request to Needs Review in LLVM Release Status Aug 30, 2023
tru pushed a commit to llvm/llvm-project-release-prs that referenced this issue Aug 30, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm/llvm-project#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158

(cherry picked from commit 0baf85c331090fbe2d2b42214ed0664d55feb0b5)
tru pushed a commit to llvm/llvm-project-release-prs that referenced this issue Aug 30, 2023
A check pattern in clang/test/SemaCXX/template-64605.cpp contains template
specialization kind (the text "implicit_instantiation"). It does not need to
be checked and can be safely removed.

Presence of this text in the check pattern prevents from backporting some
commits to the release branch: llvm/llvm-project#64605.
It has only recently been printed and the relevant commit is not present in
the release/17.x branch.

(cherry picked from commit 8859c644ede4898f90f77dcad2286de08a9ba62e)
@tru tru moved this from Needs Review to Done in LLVM Release Status Aug 30, 2023
razmser pushed a commit to SuduIDE/llvm-project that referenced this issue Oct 2, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158
razmser pushed a commit to SuduIDE/llvm-project that referenced this issue Oct 2, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158
razmser pushed a commit to SuduIDE/llvm-project that referenced this issue Oct 2, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158
razmser pushed a commit to SuduIDE/llvm-project that referenced this issue Oct 3, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158
razmser pushed a commit to SuduIDE/llvm-project that referenced this issue Oct 3, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158
razmser pushed a commit to SuduIDE/llvm-project that referenced this issue Oct 6, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158
razmser pushed a commit to SuduIDE/llvm-project that referenced this issue Oct 11, 2023
When an expression is instantiated, TreeTransform skips ImplicitCastExpr
nodes, assuming they are recreated when the instantiated expression is
built. It breaks functions that use non-default floating-point options,
because they are kept in these ImplicitCastExprs. In this case the
recreated ImplicitCastExpr takes FP options from the current Sema state
and not from AST node.

To fix this issue the FP options in Sema object are set when a compound
statement is cloned in TreeTransform.

This change fixes llvm#64605
([Regression 16 -> 17] Template instantiation ignores FENV_ACCESS being
ON for both definition and instantiation).

Differential Revision: https://reviews.llvm.org/D158158
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" floating-point Floating-point math miscompilation regression release:backport release:merged
Projects
9 participants