From bc5b5ea037dbadd281c59248ae9d2742b51c69ed Mon Sep 17 00:00:00 2001 From: Melanie Blower Date: Thu, 29 Jul 2021 12:02:20 -0400 Subject: [PATCH] [clang][patch][FPEnv] Make initialization of C++ globals strictfp aware @kpn pointed out that the global variable initialization functions didn't have the "strictfp" metadata set correctly, and @rjmccall said that there was buggy code in SetFPModel and StartFunction, this patch is to solve those problems. When Sema creates a FunctionDecl, it sets the FunctionDeclBits.UsesFPIntrin to "true" if the lexical FP settings (i.e. a combination of command line options and #pragma float_control settings) correspond to ConstrainedFP mode. That bit is used when CodeGen starts codegen for a llvm function, and it translates into the "strictfp" function attribute. See bugs.llvm.org/show_bug.cgi?id=44571 Reviewed By: Aaron Ballman Differential Revision: https://reviews.llvm.org/D102343 --- clang/include/clang/AST/Decl.h | 34 +++++--- clang/include/clang/AST/DeclCXX.h | 63 ++++++++------- clang/lib/AST/ASTImporter.cpp | 26 +++--- clang/lib/AST/Decl.cpp | 28 +++---- clang/lib/AST/DeclCXX.cpp | 81 +++++++++---------- clang/lib/CodeGen/CGObjC.cpp | 4 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 3 +- clang/lib/CodeGen/CodeGenFunction.cpp | 26 +++--- clang/lib/CodeGen/CodeGenFunction.h | 3 - clang/lib/Sema/SemaDecl.cpp | 46 ++++++----- clang/lib/Sema/SemaDeclAttr.cpp | 5 +- clang/lib/Sema/SemaDeclCXX.cpp | 23 +++--- clang/lib/Sema/SemaExpr.cpp | 17 ++-- clang/lib/Sema/SemaExprCXX.cpp | 5 +- clang/lib/Sema/SemaLambda.cpp | 5 +- clang/lib/Sema/SemaLookup.cpp | 3 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 25 +++--- clang/test/CodeGen/fp-floatcontrol-class.cpp | 4 +- clang/test/CodeGen/fp-floatcontrol-stack.cpp | 55 +++++++++---- .../unittests/Sema/ExternalSemaSourceTest.cpp | 3 +- 20 files changed, 249 insertions(+), 210 deletions(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 510bf8978985..30923a4fa05c 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1990,8 +1990,8 @@ private: protected: FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified, - ConstexprSpecKind ConstexprKind, + TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin, + bool isInlineSpecified, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause = nullptr); using redeclarable_base = Redeclarable; @@ -2025,23 +2025,23 @@ public: static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified = false, - bool hasWrittenPrototype = true, + TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin = false, + bool isInlineSpecified = false, bool hasWrittenPrototype = true, ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified, Expr *TrailingRequiresClause = nullptr) { DeclarationNameInfo NameInfo(N, NLoc); return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC, - isInlineSpecified, hasWrittenPrototype, - ConstexprKind, TrailingRequiresClause); + UsesFPIntrin, isInlineSpecified, + hasWrittenPrototype, ConstexprKind, + TrailingRequiresClause); } - static FunctionDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, - bool isInlineSpecified, bool hasWrittenPrototype, - ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause); + static FunctionDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified, + bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause); static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2594,6 +2594,14 @@ public: FunctionDeclBits.IsInline = I; } + /// Determine whether the function was declared in source context + /// that requires constrained FP intrinsics + bool UsesFPIntrin() const { return FunctionDeclBits.UsesFPIntrin; } + + /// Set whether the function was declared in source context + /// that requires constrained FP intrinsics + void setUsesFPIntrin(bool I) { FunctionDeclBits.UsesFPIntrin = I; } + /// Flag that this function is implicitly inline. void setImplicitlyInline(bool I = true) { FunctionDeclBits.IsInline = I; } diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 0d5ad40fc19e..cc7bfc86a521 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1857,7 +1857,7 @@ private: TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor) : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, - SC_None, false, ConstexprSpecKind::Unspecified), + SC_None, false, false, ConstexprSpecKind::Unspecified), Ctor(Ctor), ExplicitSpec(ES) { if (EndLocation.isValid()) setRangeEnd(EndLocation); @@ -1952,23 +1952,22 @@ protected: CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, + bool UsesFPIntrin, bool isInline, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr) - : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, isInline, - ConstexprKind, TrailingRequiresClause) { + : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, + isInline, ConstexprKind, TrailingRequiresClause) { if (EndLocation.isValid()) setRangeEnd(EndLocation); } public: - static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, StorageClass SC, - bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr); + static CXXMethodDecl * + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool UsesFPIntrin, bool isInline, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr); static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2413,7 +2412,8 @@ class CXXConstructorDecl final CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline, + TypeSourceInfo *TInfo, ExplicitSpecifier ES, + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, Expr *TrailingRequiresClause); @@ -2456,8 +2456,8 @@ public: static CXXConstructorDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, + ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited = InheritedConstructor(), Expr *TrailingRequiresClause = nullptr); @@ -2676,25 +2676,24 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, bool isInline, + TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause) { + SC_None, UsesFPIntrin, isInline, ConstexprKind, + SourceLocation(), TrailingRequiresClause) { setImplicit(isImplicitlyDeclared); } void anchor() override; public: - static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause = nullptr); + static CXXDestructorDecl * + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause = nullptr); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); @@ -2732,12 +2731,13 @@ public: class CXXConversionDecl : public CXXMethodDecl { CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, - TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES, - ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, + ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, EndLocation, - TrailingRequiresClause), + SC_None, UsesFPIntrin, isInline, ConstexprKind, + EndLocation, TrailingRequiresClause), ExplicitSpec(ES) {} void anchor() override; @@ -2750,8 +2750,9 @@ public: static CXXConversionDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); + bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr); static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); ExplicitSpecifier getExplicitSpecifier() { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 787e02029dae..e7d02b69c9d7 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3461,8 +3461,8 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), - ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->isInlineSpecified(), - D->isImplicit(), D->getConstexprKind(), + ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->UsesFPIntrin(), + D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), InheritedConstructor(), // FIXME: Properly import inherited // constructor info TrailingRequiresClause)) @@ -3477,9 +3477,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); if (GetImportedOrCreateDecl( - ToFunction, D, Importer.getToContext(), cast(DC), - ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), - D->isImplicit(), D->getConstexprKind(), TrailingRequiresClause)) + ToFunction, D, Importer.getToContext(), cast(DC), + ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(), + D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), + TrailingRequiresClause)) return ToFunction; CXXDestructorDecl *ToDtor = cast(ToFunction); @@ -3493,15 +3494,16 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), - ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), ESpec, - D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) + ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(), + D->isInlineSpecified(), ESpec, D->getConstexprKind(), + SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Method = dyn_cast(D)) { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), - Method->isInlineSpecified(), D->getConstexprKind(), - SourceLocation(), TrailingRequiresClause)) + Method->UsesFPIntrin(), Method->isInlineSpecified(), + D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Guide = dyn_cast(D)) { ExplicitSpecifier ESpec = @@ -3519,9 +3521,9 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, - NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->getConstexprKind(), - TrailingRequiresClause)) + NameInfo, T, TInfo, D->getStorageClass(), D->UsesFPIntrin(), + D->isInlineSpecified(), D->hasWrittenPrototype(), + D->getConstexprKind(), TrailingRequiresClause)) return ToFunction; } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 8f2ecb7bcf2a..aa9fba519642 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2852,7 +2852,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, - bool isInlineSpecified, + bool UsesFPIntrin, bool isInlineSpecified, ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, @@ -2878,7 +2878,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, FunctionDeclBits.ConstexprKind = static_cast(ConstexprKind); FunctionDeclBits.InstantiationIsPending = false; FunctionDeclBits.UsesSEHTry = false; - FunctionDeclBits.UsesFPIntrin = false; + FunctionDeclBits.UsesFPIntrin = UsesFPIntrin; FunctionDeclBits.HasSkippedBody = false; FunctionDeclBits.WillHaveBody = false; FunctionDeclBits.IsMultiVersion = false; @@ -4857,18 +4857,16 @@ ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other); } -FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, bool isInlineSpecified, - bool hasWrittenPrototype, - ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause) { - FunctionDecl *New = - new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo, - SC, isInlineSpecified, ConstexprKind, - TrailingRequiresClause); +FunctionDecl * +FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, + bool isInlineSpecified, bool hasWrittenPrototype, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) { + FunctionDecl *New = new (C, DC) FunctionDecl( + Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, + isInlineSpecified, ConstexprKind, TrailingRequiresClause); New->setHasWrittenPrototype(hasWrittenPrototype); return New; } @@ -4876,7 +4874,7 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) FunctionDecl( Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), - nullptr, SC_None, false, ConstexprSpecKind::Unspecified, nullptr); + nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index aeee35d9c74f..82243f6b8d0c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2178,25 +2178,23 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, return FinalOverriders.size() == 1 ? FinalOverriders.front() : nullptr; } -CXXMethodDecl *CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - StorageClass SC, bool isInline, - ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, - Expr *TrailingRequiresClause) { - return new (C, RD) - CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, - isInline, ConstexprKind, EndLocation, - TrailingRequiresClause); +CXXMethodDecl * +CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, + bool isInline, ConstexprSpecKind ConstexprKind, + SourceLocation EndLocation, + Expr *TrailingRequiresClause) { + return new (C, RD) CXXMethodDecl( + CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, + isInline, ConstexprKind, EndLocation, TrailingRequiresClause); } CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - return new (C, ID) - CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(), - DeclarationNameInfo(), QualType(), nullptr, SC_None, false, - ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); + return new (C, ID) CXXMethodDecl( + CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(), + QualType(), nullptr, SC_None, false, false, + ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); } CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, @@ -2568,12 +2566,12 @@ SourceRange CXXCtorInitializer::getSourceRange() const { CXXConstructorDecl::CXXConstructorDecl( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, - Expr *TrailingRequiresClause) + ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, + InheritedConstructor Inherited, Expr *TrailingRequiresClause) : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause) { + SC_None, UsesFPIntrin, isInline, ConstexprKind, + SourceLocation(), TrailingRequiresClause) { setNumCtorInitializers(0); setInheritingConstructor(static_cast(Inherited)); setImplicit(isImplicitlyDeclared); @@ -2596,7 +2594,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, isInheritingConstructor, hasTrailingExplicit); auto *Result = new (C, ID, Extra) CXXConstructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - ExplicitSpecifier(), false, false, ConstexprSpecKind::Unspecified, + ExplicitSpecifier(), false, false, false, ConstexprSpecKind::Unspecified, InheritedConstructor(), nullptr); Result->setInheritingConstructor(isInheritingConstructor); Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier = @@ -2608,19 +2606,18 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, CXXConstructorDecl *CXXConstructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, - Expr *TrailingRequiresClause) { + ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, + InheritedConstructor Inherited, Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); unsigned Extra = additionalSizeToAlloc( Inherited ? 1 : 0, ES.getExpr() ? 1 : 0); - return new (C, RD, Extra) - CXXConstructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, ES, isInline, - isImplicitlyDeclared, ConstexprKind, Inherited, - TrailingRequiresClause); + return new (C, RD, Extra) CXXConstructorDecl( + C, RD, StartLoc, NameInfo, T, TInfo, ES, UsesFPIntrin, isInline, + isImplicitlyDeclared, ConstexprKind, Inherited, TrailingRequiresClause); } CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { @@ -2737,21 +2734,20 @@ CXXDestructorDecl * CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXDestructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, false, ConstexprSpecKind::Unspecified, nullptr); + false, false, false, ConstexprSpecKind::Unspecified, nullptr); } CXXDestructorDecl *CXXDestructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause) { + bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, + ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); - return new (C, RD) - CXXDestructorDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, - isImplicitlyDeclared, ConstexprKind, - TrailingRequiresClause); + return new (C, RD) CXXDestructorDecl( + C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline, + isImplicitlyDeclared, ConstexprKind, TrailingRequiresClause); } void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { @@ -2770,21 +2766,22 @@ CXXConversionDecl * CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) CXXConversionDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, + false, false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); } CXXConversionDecl *CXXConversionDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation, Expr *TrailingRequiresClause) { + bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); - return new (C, RD) - CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo, isInline, ES, - ConstexprKind, EndLocation, TrailingRequiresClause); + return new (C, RD) CXXConversionDecl( + C, RD, StartLoc, NameInfo, T, TInfo, UsesFPIntrin, isInline, ES, + ConstexprKind, EndLocation, TrailingRequiresClause); } bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 937a0e8a3b69..2dcbdd337ed7 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -3697,7 +3697,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( FunctionDecl *FD = FunctionDecl::Create( C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, - FunctionTy, nullptr, SC_Static, false, false); + FunctionTy, nullptr, SC_Static, false, false, false); FunctionArgList args; ParmVarDecl *Params[2]; @@ -3787,7 +3787,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( FunctionDecl *FD = FunctionDecl::Create( C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, - FunctionTy, nullptr, SC_Static, false, false); + FunctionTy, nullptr, SC_Static, false, false, false); FunctionArgList args; ParmVarDecl *Params[2]; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index f6233b791182..f71f7b24a36a 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -450,7 +450,8 @@ static llvm::Function *emitOutlinedFunctionPrologue( Ctx, Ctx.getTranslationUnitDecl(), FO.S->getBeginLoc(), SourceLocation(), DeclarationName(), FunctionTy, Ctx.getTrivialTypeSourceInfo(FunctionTy), SC_Static, - /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false); + /*UsesFPIntrin=*/false, /*isInlineSpecified=*/false, + /*hasWrittenPrototype=*/false); } for (const FieldDecl *FD : RD->fields()) { QualType ArgType = FD->getType(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index a2384456ea94..f5eed8572daa 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -78,7 +78,6 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) EHStack.setCGF(this); SetFastMathFlags(CurFPFeatures); - SetFPModel(); } CodeGenFunction::~CodeGenFunction() { @@ -109,17 +108,6 @@ clang::ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind) { llvm_unreachable("Unsupported FP Exception Behavior"); } -void CodeGenFunction::SetFPModel() { - llvm::RoundingMode RM = getLangOpts().getFPRoundingMode(); - auto fpExceptionBehavior = ToConstrainedExceptMD( - getLangOpts().getFPExceptionMode()); - - Builder.setDefaultConstrainedRounding(RM); - Builder.setDefaultConstrainedExcept(fpExceptionBehavior); - Builder.setIsFPConstrained(fpExceptionBehavior != llvm::fp::ebIgnore || - RM != llvm::RoundingMode::NearestTiesToEven); -} - void CodeGenFunction::SetFastMathFlags(FPOptions FPFeatures) { llvm::FastMathFlags FMF; FMF.setAllowReassoc(FPFeatures.getAllowFPReassociate()); @@ -947,10 +935,16 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, (getLangOpts().CUDA && FD->hasAttr()))) Fn->addFnAttr(llvm::Attribute::NoRecurse); - if (FD) { - Builder.setIsFPConstrained(FD->hasAttr()); - if (FD->hasAttr()) - Fn->addFnAttr(llvm::Attribute::StrictFP); + llvm::RoundingMode RM = getLangOpts().getFPRoundingMode(); + llvm::fp::ExceptionBehavior FPExceptionBehavior = + ToConstrainedExceptMD(getLangOpts().getFPExceptionMode()); + Builder.setDefaultConstrainedRounding(RM); + Builder.setDefaultConstrainedExcept(FPExceptionBehavior); + if ((FD && (FD->UsesFPIntrin() || FD->hasAttr())) || + (!FD && (FPExceptionBehavior != llvm::fp::ebIgnore || + RM != llvm::RoundingMode::NearestTiesToEven))) { + Builder.setIsFPConstrained(true); + Fn->addFnAttr(llvm::Attribute::StrictFP); } // If a custom alignment is used, force realigning to this alignment on diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4e087ce51e37..0baa45e6b9f2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4588,9 +4588,6 @@ public: /// point operation, expressed as the maximum relative error in ulp. void SetFPAccuracy(llvm::Value *Val, float Accuracy); - /// SetFPModel - Control floating point behavior via fp-model settings. - void SetFPModel(); - /// Set the codegen fast-math flags. void SetFastMathFlags(FPOptions FPFeatures); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 205f58000302..3367f0f9744a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2113,8 +2113,9 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, } FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type, - /*TInfo=*/nullptr, SC_Extern, false, - Type->isFunctionProtoType()); + /*TInfo=*/nullptr, SC_Extern, + getCurFPFeatures().isFPConstrained(), + false, Type->isFunctionProtoType()); New->setImplicit(); New->addAttr(BuiltinAttr::CreateImplicit(Context, ID)); @@ -8552,10 +8553,11 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!R->getAsAdjusted() && R->isFunctionProtoType()); - NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, - R, TInfo, SC, isInline, HasPrototype, - ConstexprSpecKind::Unspecified, - /*TrailingRequiresClause=*/nullptr); + NewFD = FunctionDecl::Create( + SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, + SemaRef.getCurFPFeatures().isFPConstrained(), isInline, HasPrototype, + ConstexprSpecKind::Unspecified, + /*TrailingRequiresClause=*/nullptr); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -8591,9 +8593,9 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, R = SemaRef.CheckConstructorDeclarator(D, R, SC); return CXXConstructorDecl::Create( SemaRef.Context, cast(DC), D.getBeginLoc(), NameInfo, R, - TInfo, ExplicitSpecifier, isInline, - /*isImplicitlyDeclared=*/false, ConstexprKind, InheritedConstructor(), - TrailingRequiresClause); + TInfo, ExplicitSpecifier, SemaRef.getCurFPFeatures().isFPConstrained(), + isInline, /*isImplicitlyDeclared=*/false, ConstexprKind, + InheritedConstructor(), TrailingRequiresClause); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. @@ -8602,7 +8604,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, CXXRecordDecl *Record = cast(DC); CXXDestructorDecl *NewDD = CXXDestructorDecl::Create( SemaRef.Context, Record, D.getBeginLoc(), NameInfo, R, TInfo, - isInline, /*isImplicitlyDeclared=*/false, ConstexprKind, + SemaRef.getCurFPFeatures().isFPConstrained(), isInline, + /*isImplicitlyDeclared=*/false, ConstexprKind, TrailingRequiresClause); // If the destructor needs an implicit exception specification, set it @@ -8620,11 +8623,10 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // Create a FunctionDecl to satisfy the function definition parsing // code path. - return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), - D.getIdentifierLoc(), Name, R, TInfo, SC, - isInline, - /*hasPrototype=*/true, ConstexprKind, - TrailingRequiresClause); + return FunctionDecl::Create( + SemaRef.Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), Name, R, + TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline, + /*hasPrototype=*/true, ConstexprKind, TrailingRequiresClause); } } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { @@ -8641,7 +8643,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, IsVirtualOkay = true; return CXXConversionDecl::Create( SemaRef.Context, cast(DC), D.getBeginLoc(), NameInfo, R, - TInfo, isInline, ExplicitSpecifier, ConstexprKind, SourceLocation(), + TInfo, SemaRef.getCurFPFeatures().isFPConstrained(), isInline, + ExplicitSpecifier, ConstexprKind, SourceLocation(), TrailingRequiresClause); } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { @@ -8670,8 +8673,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // This is a C++ method declaration. CXXMethodDecl *Ret = CXXMethodDecl::Create( SemaRef.Context, cast(DC), D.getBeginLoc(), NameInfo, R, - TInfo, SC, isInline, ConstexprKind, SourceLocation(), - TrailingRequiresClause); + TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline, + ConstexprKind, SourceLocation(), TrailingRequiresClause); IsVirtualOkay = !Ret->isStatic(); return Ret; } else { @@ -8683,9 +8686,10 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), - return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, - R, TInfo, SC, isInline, true /*HasPrototype*/, - ConstexprKind, TrailingRequiresClause); + return FunctionDecl::Create( + SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, + SemaRef.getCurFPFeatures().isFPConstrained(), isInline, + true /*HasPrototype*/, ConstexprKind, TrailingRequiresClause); } } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index bb4ce8d4962e..5cc5e5fb2441 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8592,8 +8592,9 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, NewFD = FunctionDecl::Create( FD->getASTContext(), FD->getDeclContext(), Loc, Loc, DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None, - false /*isInlineSpecified*/, FD->hasPrototype(), - ConstexprSpecKind::Unspecified, FD->getTrailingRequiresClause()); + getCurFPFeatures().isFPConstrained(), false /*isInlineSpecified*/, + FD->hasPrototype(), ConstexprSpecKind::Unspecified, + FD->getTrailingRequiresClause()); NewD = NewFD; if (FD->getQualifier()) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 83c97626ff7e..72b277821978 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13234,6 +13234,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(), /*TInfo=*/nullptr, ExplicitSpecifier(), + getCurFPFeatures().isFPConstrained(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified); @@ -13355,7 +13356,8 @@ Sema::findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, - BaseCtor->getExplicitSpecifier(), /*isInline=*/true, + BaseCtor->getExplicitSpecifier(), getCurFPFeatures().isFPConstrained(), + /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? BaseCtor->getConstexprKind() : ConstexprSpecKind::Unspecified, InheritedConstructor(Shadow, BaseCtor), @@ -13510,12 +13512,13 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXDestructorDecl *Destructor = - CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, - QualType(), nullptr, /*isInline=*/true, - /*isImplicitlyDeclared=*/true, - Constexpr ? ConstexprSpecKind::Constexpr - : ConstexprSpecKind::Unspecified); + CXXDestructorDecl *Destructor = CXXDestructorDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, QualType(), nullptr, + getCurFPFeatures().isFPConstrained(), + /*isInline=*/true, + /*isImplicitlyDeclared=*/true, + Constexpr ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); Destructor->setAccess(AS_public); Destructor->setDefaulted(); @@ -14151,6 +14154,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, + getCurFPFeatures().isFPConstrained(), /*isInline=*/true, Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified, SourceLocation()); @@ -14485,6 +14489,7 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, + getCurFPFeatures().isFPConstrained(), /*isInline=*/true, Constexpr ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified, SourceLocation()); @@ -14864,7 +14869,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // member of its class. CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, - ExplicitSpecifier(), + ExplicitSpecifier(), getCurFPFeatures().isFPConstrained(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? ConstexprSpecKind::Constexpr @@ -15004,7 +15009,7 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // member of its class. CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, - ExplicitSpecifier(), + ExplicitSpecifier(), getCurFPFeatures().isFPConstrained(), /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr ? ConstexprSpecKind::Constexpr diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ee9979087e35..5ce5d122c219 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6280,14 +6280,12 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, QualType OverloadTy = Context.getFunctionType(FT->getReturnType(), OverloadParams, EPI); DeclContext *Parent = FDecl->getParent(); - FunctionDecl *OverloadDecl = FunctionDecl::Create(Context, Parent, - FDecl->getLocation(), - FDecl->getLocation(), - FDecl->getIdentifier(), - OverloadTy, - /*TInfo=*/nullptr, - SC_Extern, false, - /*hasPrototype=*/true); + FunctionDecl *OverloadDecl = FunctionDecl::Create( + Context, Parent, FDecl->getLocation(), FDecl->getLocation(), + FDecl->getIdentifier(), OverloadTy, + /*TInfo=*/nullptr, SC_Extern, Sema->getCurFPFeatures().isFPConstrained(), + false, + /*hasPrototype=*/true); SmallVector Params; FT = cast(OverloadTy); for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { @@ -19529,7 +19527,8 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { FunctionDecl *NewFD = FunctionDecl::Create( S.Context, FD->getDeclContext(), Loc, Loc, FD->getNameInfo().getName(), DestType, FD->getTypeSourceInfo(), - SC_None, false /*isInlineSpecified*/, FD->hasPrototype(), + SC_None, S.getCurFPFeatures().isFPConstrained(), + false /*isInlineSpecified*/, FD->hasPrototype(), /*ConstexprKind*/ ConstexprSpecKind::Unspecified); if (FD->getQualifier()) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 52338ce46d04..14484147e041 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3057,8 +3057,9 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, auto CreateAllocationFunctionDecl = [&](Attr *ExtraAttr) { QualType FnType = Context.getFunctionType(Return, Params, EPI); FunctionDecl *Alloc = FunctionDecl::Create( - Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, - FnType, /*TInfo=*/nullptr, SC_None, false, true); + Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, FnType, + /*TInfo=*/nullptr, SC_None, getCurFPFeatures().isFPConstrained(), false, + true); Alloc->setImplicit(); // Global allocation functions should always be visible. Alloc->setVisibleDespiteOwningModule(); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index eb1e9c3e5f7e..3784938847b0 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -392,7 +392,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, Context, Class, EndLoc, DeclarationNameInfo(MethodName, IntroducerRange.getBegin(), MethodNameLoc), - MethodType, MethodTypeInfo, SC_None, + MethodType, MethodTypeInfo, SC_None, getCurFPFeatures().isFPConstrained(), /*isInline=*/true, ConstexprKind, EndLoc, TrailingRequiresClause); Method->setAccess(AS_public); if (!TemplateParams) @@ -1447,6 +1447,7 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, + S.getCurFPFeatures().isFPConstrained(), /*isInline=*/true, ExplicitSpecifier(), S.getLangOpts().CPlusPlus17 ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified, @@ -1488,6 +1489,7 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXMethodDecl *Invoke = CXXMethodDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, + S.getCurFPFeatures().isFPConstrained(), /*isInline=*/true, ConstexprSpecKind::Unspecified, CallOperator->getBody()->getEndLoc()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) @@ -1556,6 +1558,7 @@ static void addBlockPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), + S.getCurFPFeatures().isFPConstrained(), /*isInline=*/true, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 5e8c4de61e5d..a88bf52b4d8b 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -859,7 +859,8 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, for (const auto &FTy : FunctionList) { NewOpenCLBuiltin = FunctionDecl::Create( Context, Parent, Loc, Loc, II, FTy, /*TInfo=*/nullptr, SC_Extern, - false, FTy->isFunctionProtoType()); + S.getCurFPFeatures().isFPConstrained(), false, + FTy->isFunctionProtoType()); NewOpenCLBuiltin->setImplicit(); // Create Decl objects for each parameter, adding them to the diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index be4c51930789..d33c2545b484 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2051,8 +2051,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( } else { Function = FunctionDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo, - D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->getConstexprKind(), + D->getCanonicalDecl()->getStorageClass(), D->UsesFPIntrin(), + D->isInlineSpecified(), D->hasWrittenPrototype(), D->getConstexprKind(), TrailingRequiresClause); Function->setRangeEnd(D->getSourceRange().getEnd()); } @@ -2407,15 +2407,16 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( if (CXXConstructorDecl *Constructor = dyn_cast(D)) { Method = CXXConstructorDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false, + InstantiatedExplicitSpecifier, Constructor->UsesFPIntrin(), + Constructor->isInlineSpecified(), false, Constructor->getConstexprKind(), InheritedConstructor(), TrailingRequiresClause); Method->setRangeEnd(Constructor->getEndLoc()); } else if (CXXDestructorDecl *Destructor = dyn_cast(D)) { Method = CXXDestructorDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Destructor->isInlineSpecified(), false, Destructor->getConstexprKind(), - TrailingRequiresClause); + Destructor->UsesFPIntrin(), Destructor->isInlineSpecified(), false, + Destructor->getConstexprKind(), TrailingRequiresClause); Method->setRangeEnd(Destructor->getEndLoc()); Method->setDeclName(SemaRef.Context.DeclarationNames.getCXXDestructorName( SemaRef.Context.getCanonicalType( @@ -2423,15 +2424,15 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } else if (CXXConversionDecl *Conversion = dyn_cast(D)) { Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier, - Conversion->getConstexprKind(), Conversion->getEndLoc(), - TrailingRequiresClause); + Conversion->UsesFPIntrin(), Conversion->isInlineSpecified(), + InstantiatedExplicitSpecifier, Conversion->getConstexprKind(), + Conversion->getEndLoc(), TrailingRequiresClause); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; - Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, - T, TInfo, SC, D->isInlineSpecified(), - D->getConstexprKind(), D->getEndLoc(), - TrailingRequiresClause); + Method = CXXMethodDecl::Create( + SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, SC, + D->UsesFPIntrin(), D->isInlineSpecified(), D->getConstexprKind(), + D->getEndLoc(), TrailingRequiresClause); } if (D->isInlined()) diff --git a/clang/test/CodeGen/fp-floatcontrol-class.cpp b/clang/test/CodeGen/fp-floatcontrol-class.cpp index db600eee6a08..8c2e60c2a9c3 100644 --- a/clang/test/CodeGen/fp-floatcontrol-class.cpp +++ b/clang/test/CodeGen/fp-floatcontrol-class.cpp @@ -8,13 +8,13 @@ float z(); class ON { float w = 2 + y() * z(); // CHECK-LABEL: define {{.*}} @_ZN2ONC2Ev{{.*}} - //CHECK: call float {{.*}}llvm.fmuladd + // CHECK: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict }; ON on; #pragma float_control(except, off) class OFF { float w = 2 + y() * z(); // CHECK-LABEL: define {{.*}} @_ZN3OFFC2Ev{{.*}} - //CHECK: call float {{.*}}llvm.fmuladd + // CHECK-NOT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict }; OFF off; diff --git a/clang/test/CodeGen/fp-floatcontrol-stack.cpp b/clang/test/CodeGen/fp-floatcontrol-stack.cpp index 122c621b4cbc..35908dbc579f 100644 --- a/clang/test/CodeGen/fp-floatcontrol-stack.cpp +++ b/clang/test/CodeGen/fp-floatcontrol-stack.cpp @@ -6,6 +6,10 @@ #define FUN(n) \ (float z) { return n * z + n; } +// CHECK-DDEFAULT Function Attrs: noinline nounwind optnone mustprogress +// CHECK-DEBSTRICT Function Attrs: noinline nounwind optnone strictfp mustprogress +// CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone +// CHECK-NOHONOR Function Attrs: noinline nounwind optnone mustprogress float fun_default FUN(1) //CHECK-LABEL: define {{.*}} @_Z11fun_defaultf{{.*}} #if DEFAULT @@ -28,6 +32,10 @@ float fun_default FUN(1) // Rule: precise must be enabled #pragma float_control(except, on) #endif + // CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone + // CHECK-DDEFAULT Function Attrs: noinline nounwind optnone strictfp mustprogress + // CHECK-DEBSTRICT Function Attrs: noinline nounwind optnone strictfp mustprogress + // CHECK-NOHONOR Function Attrs: noinline nounwind optnone strictfp mustprogress float exc_on FUN(2) //CHECK-LABEL: define {{.*}} @_Z6exc_onf{{.*}} #if DEFAULT @@ -46,7 +54,11 @@ float fun_default FUN(1) #endif #pragma float_control(pop) - float exc_pop FUN(5) + // CHECK-DDEFAULT Function Attrs: noinline nounwind optnone mustprogress + // CHECK-DEBSTRICT Function Attrs: noinline nounwind optnone strictfp mustprogress + // CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone + // CHECK-NOHONOR Function Attrs: noinline nounwind optnone mustprogress + float exc_pop FUN(5) //CHECK-LABEL: define {{.*}} @_Z7exc_popf{{.*}} #if DEFAULT //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} @@ -63,7 +75,7 @@ float fun_default FUN(1) #endif #pragma float_control(except, off) - float exc_off FUN(5) + float exc_off FUN(5) //CHECK-LABEL: define {{.*}} @_Z7exc_offf{{.*}} #if DEFAULT //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}} @@ -80,7 +92,7 @@ float fun_default FUN(1) #endif #pragma float_control(precise, on, push) - float precise_on FUN(3) + float precise_on FUN(3) //CHECK-LABEL: define {{.*}} @_Z10precise_onf{{.*}} #if DEFAULT //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} @@ -97,7 +109,7 @@ float fun_default FUN(1) #endif #pragma float_control(pop) - float precise_pop FUN(3) + float precise_pop FUN(3) //CHECK-LABEL: define {{.*}} @_Z11precise_popf{{.*}} #if DEFAULT //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}} @@ -113,7 +125,7 @@ float fun_default FUN(1) //CHECK-FAST: fadd fast float #endif #pragma float_control(precise, off) - float precise_off FUN(4) + float precise_off FUN(4) //CHECK-LABEL: define {{.*}} @_Z11precise_offf{{.*}} #if DEFAULT // Note: precise_off enables fp_contract=fast and the instructions @@ -137,7 +149,7 @@ float fun_default FUN(1) #endif #pragma float_control(precise, on) - float precise_on2 FUN(3) + float precise_on2 FUN(3) //CHECK-LABEL: define {{.*}} @_Z11precise_on2f{{.*}} #if DEFAULT //CHECK-DDEFAULT: llvm.fmuladd{{.*}} @@ -154,7 +166,7 @@ float fun_default FUN(1) #endif #pragma float_control(push) - float precise_push FUN(3) + float precise_push FUN(3) //CHECK-LABEL: define {{.*}} @_Z12precise_pushf{{.*}} #if DEFAULT //CHECK-DDEFAULT: llvm.fmuladd{{.*}} @@ -170,7 +182,7 @@ float fun_default FUN(1) #endif #pragma float_control(precise, off) - float precise_off2 FUN(4) + float precise_off2 FUN(4) //CHECK-LABEL: define {{.*}} @_Z12precise_off2f{{.*}} #if DEFAULT //CHECK-DDEFAULT: fmul fast float @@ -191,7 +203,7 @@ float fun_default FUN(1) #endif #pragma float_control(pop) - float precise_pop2 FUN(3) + float precise_pop2 FUN(3) //CHECK-LABEL: define {{.*}} @_Z12precise_pop2f{{.*}} #if DEFAULT //CHECK-DDEFAULT: llvm.fmuladd{{.*}} @@ -210,27 +222,34 @@ float fun_default FUN(1) // Rule: precise must be enabled #pragma float_control(except, on) #endif - float y(); + float y(); +// CHECK-DDEFAULT Function Attrs: noinline nounwind optnone mustprogress +// CHECK-DEBSTRICT Function Attrs: noinline nounwind optnone strictfp mustprogress +// CHECK-FAST: Function Attrs: mustprogress noinline nounwind optnone +// CHECK-NOHONOR Function Attrs: noinline nounwind optnone mustprogress class ON { // Settings for top level class initializer use program source setting. float z = 2 + y() * 7; //CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}} #if DEFAULT -//CHECK-DDEFAULT: call float {{.*}}llvm.fmuladd +// CHECK-DDEFAULT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict #endif #if EBSTRICT -//Currently, same as default [command line options not considered] -//CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd +// CHECK-DEBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict #endif #if NOHONOR -//CHECK-NOHONOR: call float {{.*}}llvm.fmuladd +// CHECK-NOHONOR: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict #endif #if FAST -//CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} +// CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}} #endif }; ON on; #pragma float_control(except, off) +// CHECK-DDEFAULT Function Attrs: noinline nounwind optnone +// CHECK-DEBSTRICT Function Attrs: noinline nounwind optnone +// CHECK-FAST: Function Attrs: noinline nounwind optnone +// CHECK-NOHONOR Function Attrs: noinline nounwind optnone class OFF { float w = 2 + y() * 7; //CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}} @@ -259,3 +278,9 @@ MyComplex useAdd() { MyComplex b (2, 4); return a + b; } + +// CHECK-DDEFAULT Function Attrs: noinline nounwind +// CHECK-DEBSTRICT Function Attrs: noinline nounwind strictfp +// CHECK-FAST: Function Attrs: noinline nounwind +// CHECK-NOHONOR Function Attrs: noinline nounwind +// CHECK-LABEL: define{{.*}} @_GLOBAL__sub_I_fp_floatcontrol_stack diff --git a/clang/unittests/Sema/ExternalSemaSourceTest.cpp b/clang/unittests/Sema/ExternalSemaSourceTest.cpp index 842eb83eb3d9..2a86f948abc5 100644 --- a/clang/unittests/Sema/ExternalSemaSourceTest.cpp +++ b/clang/unittests/Sema/ExternalSemaSourceTest.cpp @@ -163,7 +163,8 @@ public: CurrentSema->getPreprocessor().getIdentifierInfo(CorrectTo); auto *NewFunction = FunctionDecl::Create( Context, DestContext, SourceLocation(), SourceLocation(), ToIdent, - Context.getFunctionType(Context.VoidTy, {}, {}), nullptr, SC_Static); + Context.getFunctionType(Context.VoidTy, {}, {}), nullptr, SC_Static, + /*UsesFPIntrin*/ false); DestContext->addDecl(NewFunction); TypoCorrection Correction(ToIdent); Correction.addCorrectionDecl(NewFunction);