Skip to content

Commit 07e171e

Browse files
committed
[clang] Set correct FPOptions if attribute 'optnone' presents
Attribute `optnone` must turn off all optimizations including fast-math ones. Actually AST nodes in the 'optnone' function still had fast-math flags. This change implements fixing FP options before function body is parsed.
1 parent 37b7207 commit 07e171e

File tree

5 files changed

+37
-0
lines changed

5 files changed

+37
-0
lines changed

clang/include/clang/Basic/LangOptions.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,8 @@ class FPOptions {
873873
/// Return difference with the given option set.
874874
FPOptionsOverride getChangesFrom(const FPOptions &Base) const;
875875

876+
void applyChanges(FPOptionsOverride FPO);
877+
876878
// We can define most of the accessors automatically:
877879
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
878880
TYPE get##NAME() const { \
@@ -954,6 +956,11 @@ class FPOptionsOverride {
954956
setAllowFPContractAcrossStatement();
955957
}
956958

959+
void setDisallowOptimizations() {
960+
setFPPreciseEnabled(true);
961+
setDisallowFPContract();
962+
}
963+
957964
storage_type getAsOpaqueInt() const {
958965
return (static_cast<storage_type>(Options.getAsOpaqueInt())
959966
<< FPOptions::StorageBitSize) |
@@ -1010,6 +1017,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const
10101017
return getChangesSlow(Base);
10111018
}
10121019

1020+
inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
1021+
*this = FPO.applyOverrides(*this);
1022+
}
1023+
10131024
/// Describes the kind of translation unit being processed.
10141025
enum TranslationUnitKind {
10151026
/// The translation unit is a complete translation unit.

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3072,6 +3072,7 @@ class Sema final : public SemaBase {
30723072
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
30733073
SkipBodyInfo *SkipBody = nullptr,
30743074
FnBodyKind BodyKind = FnBodyKind::Other);
3075+
void applyFunctionAttributesBeforeParsingBody(Decl *FD);
30753076

30763077
/// Determine whether we can delay parsing the body of a function or
30773078
/// function template until it is used, assuming we don't care about emitting

clang/lib/Parse/ParseStmt.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,10 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
25082508
Sema::PragmaStackSentinelRAII
25092509
PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
25102510

2511+
// Some function attributes (like OptimizeNoneAttr) affect FP options.
2512+
Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
2513+
Actions.applyFunctionAttributesBeforeParsingBody(Decl);
2514+
25112515
// Do not enter a scope for the brace, as the arguments are in the same scope
25122516
// (the function body) as the body itself. Instead, just read the statement
25132517
// list and put it into a CompoundStmt for safe keeping.

clang/lib/Sema/SemaDecl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15910,6 +15910,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
1591015910
return D;
1591115911
}
1591215912

15913+
void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) {
15914+
if (FD && FD->hasAttr<OptimizeNoneAttr>()) {
15915+
FPOptionsOverride FPO;
15916+
FPO.setDisallowOptimizations();
15917+
CurFPFeatures.applyChanges(FPO);
15918+
FpPragmaStack.CurrentValue =
15919+
CurFPFeatures.getChangesFrom(FPOptions(LangOpts));
15920+
}
15921+
}
15922+
1591315923
/// Given the set of return statements within a function body,
1591415924
/// compute the variables that are subject to the named return value
1591515925
/// optimization.

clang/test/AST/ast-dump-fpfeatures.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,14 @@ float func_18(float x, float y) {
187187
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward
188188
// CHECK: ReturnStmt
189189
// CHECK: BinaryOperator {{.*}} ConstRoundingMode=downward
190+
191+
#pragma float_control(precise, off)
192+
__attribute__((optnone))
193+
float func_19(float x, float y) {
194+
return x + y;
195+
}
196+
197+
// CHECK-LABEL: FunctionDecl {{.*}} func_19 'float (float, float)'
198+
// CHECK: CompoundStmt {{.*}} MathErrno=1
199+
// CHECK: ReturnStmt
200+
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

0 commit comments

Comments
 (0)