Skip to content
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

[clang] Set correct FPOptions if attribute 'optnone' presents #85605

Merged
merged 4 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,8 @@ class FPOptions {
/// Return difference with the given option set.
FPOptionsOverride getChangesFrom(const FPOptions &Base) const;

void applyChanges(FPOptionsOverride FPO);

// We can define most of the accessors automatically:
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
TYPE get##NAME() const { \
Expand Down Expand Up @@ -954,6 +956,11 @@ class FPOptionsOverride {
setAllowFPContractAcrossStatement();
}

void setDisallowOptimizations() {
setFPPreciseEnabled(true);
setDisallowFPContract();
}

storage_type getAsOpaqueInt() const {
return (static_cast<storage_type>(Options.getAsOpaqueInt())
<< FPOptions::StorageBitSize) |
Expand Down Expand Up @@ -1010,6 +1017,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const
return getChangesSlow(Base);
}

inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
*this = FPO.applyOverrides(*this);
}

/// Describes the kind of translation unit being processed.
enum TranslationUnitKind {
/// The translation unit is a complete translation unit.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -3072,6 +3072,7 @@ class Sema final : public SemaBase {
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
SkipBodyInfo *SkipBody = nullptr,
FnBodyKind BodyKind = FnBodyKind::Other);
void applyFunctionAttributesBeforeParsingBody(Decl *FD);

/// Determine whether we can delay parsing the body of a function or
/// function template until it is used, assuming we don't care about emitting
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Parse/ParseCXXInlineMethods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// to be re-used for method bodies as well.
ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);

if (Tok.is(tok::kw_try)) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Parse/ParseObjc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3736,6 +3736,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

// Tell the actions module that we have entered a method or c-function definition
// with the specified Declarator for the method/function.
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
return Actions.ActOnFinishFunctionBody(Res, nullptr, false);
}

Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

if (Tok.is(tok::kw_try))
return ParseFunctionTryBlock(Res, BodyScope);

Expand Down
19 changes: 19 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15899,6 +15899,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
FD->setInvalidDecl();
return D;
}

// Some function attributes (like OptimizeNoneAttr) need actions before
// parsing body started.
applyFunctionAttributesBeforeParsingBody(D);

// We want to attach documentation to original Decl (which might be
// a function template).
ActOnDocumentableDecl(D);
Expand All @@ -15910,6 +15915,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
return D;
}

void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) {
if (!FD || FD->isInvalidDecl())
return;
if (auto *TD = dyn_cast<FunctionTemplateDecl>(FD))
FD = TD->getTemplatedDecl();
if (FD && FD->hasAttr<OptimizeNoneAttr>()) {
FPOptionsOverride FPO;
FPO.setDisallowOptimizations();
CurFPFeatures.applyChanges(FPO);
FpPragmaStack.CurrentValue =
CurFPFeatures.getChangesFrom(FPOptions(LangOpts));
}
}

/// Given the set of return statements within a function body,
/// compute the variables that are subject to the named return value
/// optimization.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaDeclObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
}
}
}

// Some function attributes (like OptimizeNoneAttr) need actions before
// parsing body started.
applyFunctionAttributesBeforeParsingBody(D);
}

namespace {
Expand Down
68 changes: 65 additions & 3 deletions clang/test/AST/ast-dump-fpfeatures.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Test without serialization:
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -ast-dump %s \
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -ast-dump %s \
// RUN: | FileCheck --strict-whitespace %s

// Test with serialization:
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -fcxx-exceptions -o %t %s
// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -fcxx-exceptions -ast-dump-all /dev/null \
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
// RUN: | FileCheck --strict-whitespace %s

Expand Down Expand Up @@ -187,3 +187,65 @@ float func_18(float x, float y) {
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} ConstRoundingMode=downward

#pragma float_control(precise, off)

__attribute__((optnone))
float func_19(float x, float y) {
return x + y;
}

// CHECK-LABEL: FunctionDecl {{.*}} func_19 'float (float, float)'
// CHECK: CompoundStmt {{.*}} MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

__attribute__((optnone))
float func_20(float x, float y) try {
return x + y;
} catch (...) {
return 1.0;
}

// CHECK-LABEL: FunctionDecl {{.*}} func_20 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

struct C21 {
C21(float x, float y);
__attribute__((optnone)) float a_method(float x, float y) {
return x * y;
}
float member;
};

// CHECK-LABEL: CXXMethodDecl {{.*}} a_method 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '*' ConstRoundingMode=downward MathErrno=1

__attribute__((optnone)) C21::C21(float x, float y) : member(x + y) {}

// CHECK-LABEL: CXXConstructorDecl {{.*}} C21 'void (float, float)'
// CHECK: CXXCtorInitializer {{.*}} 'member' 'float'
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

template <typename T>
__attribute__((optnone)) T func_22(T x, T y) {
return x + y;
}

// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22
// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1
// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

float func_23(float x, float y) {
return func_22(x, y);
}
29 changes: 29 additions & 0 deletions clang/test/AST/ast-dump-fpfeatures.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Test without serialization:
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -ast-dump %s \
// RUN: | FileCheck --strict-whitespace %s

// Test with serialization:
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
// RUN: %clang_cc1 -x objective-c -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
// RUN: | FileCheck --strict-whitespace %s


@interface Adder
- (float) sum: (float)x with: (float)y __attribute((optnone));
@end

#pragma float_control(precise, off)

@implementation Adder
- (float) sum: (float)x with: (float)y __attribute((optnone)) {
return x + y;
}

@end

// CHECK-LABEL: ObjCImplementationDecl {{.*}} Adder
// CHECK: ObjCMethodDecl {{.*}} - sum:with: 'float'
// CHECK: CompoundStmt {{.*}} MathErrno=1
// CHECK-NEXT: ReturnStmt
// CHECK-NEXT: BinaryOperator {{.*}} 'float' '+' MathErrno=1
24 changes: 24 additions & 0 deletions clang/test/AST/ast-dump-late-parsing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -ast-dump %s \
// RUN: | FileCheck %s

#pragma STDC FENV_ROUND FE_DOWNWARD
#pragma float_control(precise, off)

template <typename T>
__attribute__((optnone)) T func_22(T x, T y) {
return x + y;
}

// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22
// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1
// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

float func_23(float x, float y) {
return func_22(x, y);
}