[clang][patch] Solve PR49479, File scope fp pragma should propagate to functions nested in struct, and initialization expressions

Previously, the CurFPFeatures state was set to command line settings before
semantic analysis of the nested member functions and initialization
expressions, that's not correct, it should use the pragma state which
is in effect at the lexical position.

Reviewed By: Erich Keane, Aaron Ballman

Differential Revision: https://reviews.llvm.org/D98211
This commit is contained in:
Melanie Blower 2021-03-15 10:06:33 -04:00
parent 660728acd4
commit 33b1f3f42c
2 changed files with 26 additions and 27 deletions

View File

@ -3417,15 +3417,6 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// declarations and the lexed inline method definitions, along with any // declarations and the lexed inline method definitions, along with any
// delayed attributes. // delayed attributes.
// Save the state of Sema.FPFeatures, and change the setting
// to the levels specified on the command line. Previous level
// will be restored when the RAII object is destroyed.
Sema::FPFeaturesStateRAII SaveFPFeaturesState(Actions);
FPOptionsOverride NewOverrides;
Actions.CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
Actions.FpPragmaStack.Act(Tok.getLocation(), Sema::PSK_Reset, StringRef(),
{} /*unused*/);
SourceLocation SavedPrevTokLocation = PrevTokLocation; SourceLocation SavedPrevTokLocation = PrevTokLocation;
ParseLexedPragmas(getCurrentClass()); ParseLexedPragmas(getCurrentClass());
ParseLexedAttributes(getCurrentClass()); ParseLexedAttributes(getCurrentClass());

View File

@ -212,8 +212,7 @@ float fun_default FUN(1)
#endif #endif
float y(); float y();
class ON { class ON {
// Settings for top level class initializer revert to command line // Settings for top level class initializer use program source setting.
// source pragma's do not pertain.
float z = 2 + y() * 7; float z = 2 + y() * 7;
//CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}} //CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}}
#if DEFAULT #if DEFAULT
@ -224,11 +223,10 @@ class ON {
//CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd //CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd
#endif #endif
#if NOHONOR #if NOHONOR
//CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}} //CHECK-NOHONOR: call float {{.*}}llvm.fmuladd
#endif #endif
#if FAST #if FAST
//CHECK-FAST: fmul fast float //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}}
//CHECK-FAST: fadd fast float
#endif #endif
}; };
ON on; ON on;
@ -236,18 +234,28 @@ ON on;
class OFF { class OFF {
float w = 2 + y() * 7; float w = 2 + y() * 7;
//CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}} //CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}}
#if DEFAULT //CHECK: call float {{.*}}llvm.fmuladd
//CHECK-DDEFAULT: call float {{.*}}llvm.fmuladd
#endif
#if EBSTRICT
//CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd
#endif
#if NOHONOR
//CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}}
#endif
#if FAST
//CHECK-FAST: fmul fast float
//CHECK-FAST: fadd fast float
#endif
}; };
OFF off; OFF off;
#pragma clang fp reassociate(on)
struct MyComplex {
float xx;
float yy;
MyComplex(float x, float y) {
xx = x;
yy = y;
}
MyComplex() {}
const MyComplex operator+(const MyComplex other) const {
//CHECK-LABEL: define {{.*}} @_ZNK9MyComplexplES_
//CHECK: fadd reassoc float
//CHECK: fadd reassoc float
return MyComplex(xx + other.xx, yy + other.yy);
}
};
MyComplex useAdd() {
MyComplex a (1, 3);
MyComplex b (2, 4);
return a + b;
}