[clang] a046242 - [clang] Set correct FPOptions if attribute 'optnone' presents (#85605)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 23 00:14:06 PDT 2024
Author: Serge Pavlov
Date: 2024-04-23T14:14:02+07:00
New Revision: a04624206ddf03dc54d5c372e7eac13575b4124b
URL: https://github.com/llvm/llvm-project/commit/a04624206ddf03dc54d5c372e7eac13575b4124b
DIFF: https://github.com/llvm/llvm-project/commit/a04624206ddf03dc54d5c372e7eac13575b4124b.diff
LOG: [clang] Set correct FPOptions if attribute 'optnone' presents (#85605)
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.
Added:
clang/test/AST/ast-dump-fpfeatures.m
clang/test/AST/ast-dump-late-parsing.cpp
Modified:
clang/include/clang/Basic/LangOptions.h
clang/include/clang/Sema/Sema.h
clang/lib/Parse/ParseCXXInlineMethods.cpp
clang/lib/Parse/ParseObjc.cpp
clang/lib/Parse/Parser.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclObjC.cpp
clang/test/AST/ast-dump-fpfeatures.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 75562284ec7de0..ae4715921d1665 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -878,6 +878,8 @@ class FPOptions {
/// Return
diff erence 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 { \
@@ -959,6 +961,11 @@ class FPOptionsOverride {
setAllowFPContractAcrossStatement();
}
+ void setDisallowOptimizations() {
+ setFPPreciseEnabled(true);
+ setDisallowFPContract();
+ }
+
storage_type getAsOpaqueInt() const {
return (static_cast<storage_type>(Options.getAsOpaqueInt())
<< FPOptions::StorageBitSize) |
@@ -1015,6 +1022,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.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 64607b91acbfc9..1ca523ec88c2f9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3084,6 +3084,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
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index d054eda279b8c8..a26568dfd6aae3 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -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)) {
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 671dcb71e51a37..8e54fe012c55d7 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -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.
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index ef46fc74cedc14..adcbe5858bc78e 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 35eac93e324dec..452e00fa32b102 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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);
@@ -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.
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 74d6f0700b0e4f..934ba174a426e4 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -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 {
diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp b/clang/test/AST/ast-dump-fpfeatures.cpp
index da0011602a728e..68144e31a93043 100644
--- a/clang/test/AST/ast-dump-fpfeatures.cpp
+++ b/clang/test/AST/ast-dump-fpfeatures.cpp
@@ -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
@@ -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);
+}
\ No newline at end of file
diff --git a/clang/test/AST/ast-dump-fpfeatures.m b/clang/test/AST/ast-dump-fpfeatures.m
new file mode 100644
index 00000000000000..cf77529a756811
--- /dev/null
+++ b/clang/test/AST/ast-dump-fpfeatures.m
@@ -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
+
+
+ at interface Adder
+- (float) sum: (float)x with: (float)y __attribute((optnone));
+ at end
+
+#pragma float_control(precise, off)
+
+ at implementation Adder
+- (float) sum: (float)x with: (float)y __attribute((optnone)) {
+ return x + y;
+}
+
+ at end
+
+// CHECK-LABEL: ObjCImplementationDecl {{.*}} Adder
+// CHECK: ObjCMethodDecl {{.*}} - sum:with: 'float'
+// CHECK: CompoundStmt {{.*}} MathErrno=1
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: BinaryOperator {{.*}} 'float' '+' MathErrno=1
diff --git a/clang/test/AST/ast-dump-late-parsing.cpp b/clang/test/AST/ast-dump-late-parsing.cpp
new file mode 100644
index 00000000000000..760664efc5f142
--- /dev/null
+++ b/clang/test/AST/ast-dump-late-parsing.cpp
@@ -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);
+}
More information about the cfe-commits
mailing list