Skip to content

Commit 5049e02

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 65ae09e commit 5049e02

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
@@ -842,6 +842,8 @@ class FPOptions {
842842
/// Return difference with the given option set.
843843
FPOptionsOverride getChangesFrom(const FPOptions &Base) const;
844844

845+
void applyChanges(FPOptionsOverride FPO);
846+
845847
// We can define most of the accessors automatically:
846848
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
847849
TYPE get##NAME() const { \
@@ -923,6 +925,11 @@ class FPOptionsOverride {
923925
setAllowFPContractAcrossStatement();
924926
}
925927

928+
void setDisallowOptimizations() {
929+
setFPPreciseEnabled(true);
930+
setDisallowFPContract();
931+
}
932+
926933
storage_type getAsOpaqueInt() const {
927934
return (static_cast<storage_type>(Options.getAsOpaqueInt())
928935
<< FPOptions::StorageBitSize) |
@@ -979,6 +986,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const
979986
return getChangesSlow(Base);
980987
}
981988

989+
inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
990+
*this = FPO.applyOverrides(*this);
991+
}
992+
982993
/// Describes the kind of translation unit being processed.
983994
enum TranslationUnitKind {
984995
/// 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
@@ -3222,6 +3222,7 @@ class Sema final {
32223222
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
32233223
SkipBodyInfo *SkipBody = nullptr,
32243224
FnBodyKind BodyKind = FnBodyKind::Other);
3225+
void applyFunctionAttributesBeforeParsingBody(Decl *FD);
32253226

32263227
/// Determine whether we can delay parsing the body of a function or
32273228
/// 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
@@ -15919,6 +15919,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
1591915919
return D;
1592015920
}
1592115921

15922+
void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) {
15923+
if (FD && FD->hasAttr<OptimizeNoneAttr>()) {
15924+
FPOptionsOverride FPO;
15925+
FPO.setDisallowOptimizations();
15926+
CurFPFeatures.applyChanges(FPO);
15927+
FpPragmaStack.CurrentValue =
15928+
CurFPFeatures.getChangesFrom(FPOptions(LangOpts));
15929+
}
15930+
}
15931+
1592215932
/// Given the set of return statements within a function body,
1592315933
/// compute the variables that are subject to the named return value
1592415934
/// 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)