From 6c8041aa0ffed827636935e59c489b1e390c8542 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Sat, 12 Sep 2020 14:30:44 +0700 Subject: [PATCH] [AST][FPEnv] Keep FP options in trailing storage of CastExpr This change allow a CastExpr to have optional FPOptionsOverride object, stored in trailing storage. Of all cast nodes only ImplicitCastExpr, CStyleCastExpr, CXXFunctionalCastExpr and CXXStaticCastExpr are allowed to have FPOptions. Differential Revision: https://reviews.llvm.org/D85960 --- clang/include/clang/AST/Expr.h | 117 +++++++++++---- clang/include/clang/AST/ExprCXX.h | 139 +++++++++++------- clang/include/clang/AST/ExprObjC.h | 4 +- clang/include/clang/AST/Stmt.h | 3 + clang/include/clang/AST/TextNodeDumper.h | 1 + clang/include/clang/Basic/LangOptions.h | 2 + clang/lib/AST/ASTImporter.cpp | 15 +- clang/lib/AST/Expr.cpp | 55 +++++-- clang/lib/AST/ExprCXX.cpp | 61 ++++---- clang/lib/AST/TextNodeDumper.cpp | 10 ++ clang/lib/Analysis/BodyFarm.cpp | 16 +- clang/lib/CodeGen/CGBlocks.cpp | 2 +- clang/lib/CodeGen/CGObjC.cpp | 13 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 2 +- .../Frontend/Rewrite/RewriteModernObjC.cpp | 7 +- clang/lib/Frontend/Rewrite/RewriteObjC.cpp | 7 +- clang/lib/Sema/Sema.cpp | 3 +- clang/lib/Sema/SemaCast.cpp | 28 ++-- clang/lib/Sema/SemaDecl.cpp | 8 +- clang/lib/Sema/SemaDeclCXX.cpp | 9 +- clang/lib/Sema/SemaExpr.cpp | 11 +- clang/lib/Sema/SemaExprCXX.cpp | 13 +- clang/lib/Sema/SemaExprObjC.cpp | 15 +- clang/lib/Sema/SemaInit.cpp | 30 ++-- clang/lib/Sema/SemaLambda.cpp | 5 +- clang/lib/Sema/SemaObjCProperty.cpp | 14 +- clang/lib/Sema/SemaOpenMP.cpp | 12 +- clang/lib/Sema/SemaOverload.cpp | 23 +-- clang/lib/Sema/SemaStmt.cpp | 8 +- clang/lib/Sema/SemaTemplate.cpp | 2 +- clang/lib/Serialization/ASTReaderStmt.cpp | 28 +++- clang/lib/Serialization/ASTWriterDecl.cpp | 1 + clang/lib/Serialization/ASTWriterStmt.cpp | 6 +- clang/test/AST/ast-dump-fpfeatures.cpp | 45 ++++++ 34 files changed, 462 insertions(+), 253 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 26e52ad367f8..1672fd707c6d 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -3440,9 +3440,11 @@ class CastExpr : public Expr { } CXXBaseSpecifier **path_buffer(); + friend class ASTStmtReader; + protected: CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, - Expr *op, unsigned BasePathSize) + Expr *op, unsigned BasePathSize, bool HasFPFeatures) : Expr(SC, ty, VK, OK_Ordinary), Op(op) { CastExprBits.Kind = kind; CastExprBits.PartOfExplicitCast = false; @@ -3451,17 +3453,27 @@ protected: "BasePathSize overflow!"); setDependence(computeDependence(this)); assert(CastConsistency()); + CastExprBits.HasFPFeatures = HasFPFeatures; } /// Construct an empty cast. - CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) - : Expr(SC, Empty) { + CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize, + bool HasFPFeatures) + : Expr(SC, Empty) { CastExprBits.PartOfExplicitCast = false; CastExprBits.BasePathSize = BasePathSize; + CastExprBits.HasFPFeatures = HasFPFeatures; assert((CastExprBits.BasePathSize == BasePathSize) && "BasePathSize overflow!"); } + /// Return a pointer to the trailing FPOptions. + /// \pre hasStoredFPFeatures() == true + FPOptionsOverride *getTrailingFPFeatures(); + const FPOptionsOverride *getTrailingFPFeatures() const { + return const_cast(this)->getTrailingFPFeatures(); + } + public: CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } void setCastKind(CastKind K) { CastExprBits.Kind = K; } @@ -3506,6 +3518,28 @@ public: return getTargetFieldForToUnionCast(getType(), getSubExpr()->getType()); } + bool hasStoredFPFeatures() const { return CastExprBits.HasFPFeatures; } + + /// Get FPOptionsOverride from trailing storage. + FPOptionsOverride getStoredFPFeatures() const { + assert(hasStoredFPFeatures()); + return *getTrailingFPFeatures(); + } + + // Get the FP features status of this operation. Only meaningful for + // operations on floating point types. + FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { + if (hasStoredFPFeatures()) + return getStoredFPFeatures().applyOverrides(LO); + return FPOptions::defaultWithoutTrailingStorage(LO); + } + + FPOptionsOverride getFPFeatures() const { + if (hasStoredFPFeatures()) + return getStoredFPFeatures(); + return FPOptionsOverride(); + } + static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType, QualType opType); static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD, @@ -3543,21 +3577,35 @@ public: /// @endcode class ImplicitCastExpr final : public CastExpr, - private llvm::TrailingObjects { + private llvm::TrailingObjects { ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, - unsigned BasePathLength, ExprValueKind VK) - : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { } + unsigned BasePathLength, FPOptionsOverride FPO, + ExprValueKind VK) + : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength, + FPO.requiresTrailingStorage()) { + if (hasStoredFPFeatures()) + *getTrailingFPFeatures() = FPO; + } /// Construct an empty implicit cast. - explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) - : CastExpr(ImplicitCastExprClass, Shell, PathSize) { } + explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize, + bool HasFPFeatures) + : CastExpr(ImplicitCastExprClass, Shell, PathSize, HasFPFeatures) {} + + unsigned numTrailingObjects(OverloadToken) const { + return path_size(); + } public: enum OnStack_t { OnStack }; ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op, - ExprValueKind VK) - : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { + ExprValueKind VK, FPOptionsOverride FPO) + : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0, + FPO.requiresTrailingStorage()) { + if (hasStoredFPFeatures()) + *getTrailingFPFeatures() = FPO; } bool isPartOfExplicitCast() const { return CastExprBits.PartOfExplicitCast; } @@ -3568,10 +3616,10 @@ public: static ImplicitCastExpr *Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, - ExprValueKind Cat); + ExprValueKind Cat, FPOptionsOverride FPO); static ImplicitCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); + unsigned PathSize, bool HasFPFeatures); SourceLocation getBeginLoc() const LLVM_READONLY { return getSubExpr()->getBeginLoc(); @@ -3612,12 +3660,14 @@ class ExplicitCastExpr : public CastExpr { protected: ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK, CastKind kind, Expr *op, unsigned PathSize, - TypeSourceInfo *writtenTy) - : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {} + bool HasFPFeatures, TypeSourceInfo *writtenTy) + : CastExpr(SC, exprTy, VK, kind, op, PathSize, HasFPFeatures), + TInfo(writtenTy) {} /// Construct an empty explicit cast. - ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) - : CastExpr(SC, Shell, PathSize) { } + ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize, + bool HasFPFeatures) + : CastExpr(SC, Shell, PathSize, HasFPFeatures) {} public: /// getTypeInfoAsWritten - Returns the type source info for the type @@ -3640,29 +3690,38 @@ public: /// (Type)expr. For example: @c (int)f. class CStyleCastExpr final : public ExplicitCastExpr, - private llvm::TrailingObjects { + private llvm::TrailingObjects { SourceLocation LPLoc; // the location of the left paren SourceLocation RPLoc; // the location of the right paren CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op, - unsigned PathSize, TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation r) - : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize, - writtenTy), LPLoc(l), RPLoc(r) {} + unsigned PathSize, FPOptionsOverride FPO, + TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation r) + : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize, + FPO.requiresTrailingStorage(), writtenTy), + LPLoc(l), RPLoc(r) { + if (hasStoredFPFeatures()) + *getTrailingFPFeatures() = FPO; + } /// Construct an empty C-style explicit cast. - explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) - : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } + explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize, + bool HasFPFeatures) + : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize, HasFPFeatures) {} + + unsigned numTrailingObjects(OverloadToken) const { + return path_size(); + } public: - static CStyleCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, CastKind K, - Expr *Op, const CXXCastPath *BasePath, - TypeSourceInfo *WrittenTy, SourceLocation L, - SourceLocation R); + static CStyleCastExpr * + Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, + Expr *Op, const CXXCastPath *BasePath, FPOptionsOverride FPO, + TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R); static CStyleCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); + unsigned PathSize, bool HasFPFeatures); SourceLocation getLParenLoc() const { return LPLoc; } void setLParenLoc(SourceLocation L) { LPLoc = L; } diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 6b4b57eca9be..0ba5e417fd58 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -374,16 +374,17 @@ private: protected: friend class ASTStmtReader; - CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, - CastKind kind, Expr *op, unsigned PathSize, + CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, CastKind kind, + Expr *op, unsigned PathSize, bool HasFPFeatures, TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc, - SourceRange AngleBrackets) - : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l), - RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} + SourceLocation RParenLoc, SourceRange AngleBrackets) + : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, HasFPFeatures, + writtenTy), + Loc(l), RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} - explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) - : ExplicitCastExpr(SC, Shell, PathSize) {} + explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize, + bool HasFPFeatures) + : ExplicitCastExpr(SC, Shell, PathSize, HasFPFeatures) {} public: const char *getCastName() const; @@ -419,29 +420,39 @@ public: /// \c static_cast(1.0). class CXXStaticCastExpr final : public CXXNamedCastExpr, - private llvm::TrailingObjects { + private llvm::TrailingObjects { CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation RParenLoc, - SourceRange AngleBrackets) + FPOptionsOverride FPO, SourceLocation l, + SourceLocation RParenLoc, SourceRange AngleBrackets) : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, - writtenTy, l, RParenLoc, AngleBrackets) {} + FPO.requiresTrailingStorage(), writtenTy, l, RParenLoc, + AngleBrackets) { + if (hasStoredFPFeatures()) + *getTrailingFPFeatures() = FPO; + } - explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) - : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {} + explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize, + bool HasFPFeatures) + : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize, + HasFPFeatures) {} + + unsigned numTrailingObjects(OverloadToken) const { + return path_size(); + } public: friend class CastExpr; friend TrailingObjects; - static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, CastKind K, Expr *Op, - const CXXCastPath *Path, - TypeSourceInfo *Written, SourceLocation L, - SourceLocation RParenLoc, - SourceRange AngleBrackets); + static CXXStaticCastExpr * + Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, + Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, + FPOptionsOverride FPO, SourceLocation L, SourceLocation RParenLoc, + SourceRange AngleBrackets); static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); + unsigned PathSize, bool hasFPFeatures); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXStaticCastExprClass; @@ -456,15 +467,17 @@ public: class CXXDynamicCastExpr final : public CXXNamedCastExpr, private llvm::TrailingObjects { - CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, - Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, + CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, + unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, - writtenTy, l, RParenLoc, AngleBrackets) {} + /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, + AngleBrackets) {} explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) - : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {} + : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize, + /*HasFPFeatures*/ false) {} public: friend class CastExpr; @@ -499,16 +512,17 @@ class CXXReinterpretCastExpr final : public CXXNamedCastExpr, private llvm::TrailingObjects { - CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, - Expr *op, unsigned pathSize, - TypeSourceInfo *writtenTy, SourceLocation l, - SourceLocation RParenLoc, + CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, + unsigned pathSize, TypeSourceInfo *writtenTy, + SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, - pathSize, writtenTy, l, RParenLoc, AngleBrackets) {} + pathSize, /*HasFPFeatures*/ false, writtenTy, l, + RParenLoc, AngleBrackets) {} CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {} + : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize, + /*HasFPFeatures*/ false) {} public: friend class CastExpr; @@ -541,11 +555,13 @@ class CXXConstCastExpr final CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, - 0, writtenTy, l, RParenLoc, AngleBrackets) {} + : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, 0, + /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, + AngleBrackets) {} explicit CXXConstCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {} + : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0, + /*HasFPFeatures*/ false) {} public: friend class CastExpr; @@ -578,10 +594,12 @@ class CXXAddrspaceCastExpr final TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) : CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK, Kind, op, 0, - writtenTy, l, RParenLoc, AngleBrackets) {} + /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, + AngleBrackets) {} explicit CXXAddrspaceCastExpr(EmptyShell Empty) - : CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0) {} + : CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0, + /*HasFPFeatures*/ false) {} public: friend class CastExpr; @@ -1693,34 +1711,43 @@ public: /// \endcode class CXXFunctionalCastExpr final : public ExplicitCastExpr, - private llvm::TrailingObjects { + private llvm::TrailingObjects { SourceLocation LParenLoc; SourceLocation RParenLoc; CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, - TypeSourceInfo *writtenTy, - CastKind kind, Expr *castExpr, unsigned pathSize, - SourceLocation lParenLoc, SourceLocation rParenLoc) - : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, - castExpr, pathSize, writtenTy), - LParenLoc(lParenLoc), RParenLoc(rParenLoc) {} + TypeSourceInfo *writtenTy, CastKind kind, + Expr *castExpr, unsigned pathSize, + FPOptionsOverride FPO, SourceLocation lParenLoc, + SourceLocation rParenLoc) + : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, castExpr, + pathSize, FPO.requiresTrailingStorage(), writtenTy), + LParenLoc(lParenLoc), RParenLoc(rParenLoc) { + if (hasStoredFPFeatures()) + *getTrailingFPFeatures() = FPO; + } - explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) - : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {} + explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize, + bool HasFPFeatures) + : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize, + HasFPFeatures) {} + + unsigned numTrailingObjects(OverloadToken) const { + return path_size(); + } public: friend class CastExpr; friend TrailingObjects; - static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T, - ExprValueKind VK, - TypeSourceInfo *Written, - CastKind Kind, Expr *Op, - const CXXCastPath *Path, - SourceLocation LPLoc, - SourceLocation RPLoc); - static CXXFunctionalCastExpr *CreateEmpty(const ASTContext &Context, - unsigned PathSize); + static CXXFunctionalCastExpr * + Create(const ASTContext &Context, QualType T, ExprValueKind VK, + TypeSourceInfo *Written, CastKind Kind, Expr *Op, + const CXXCastPath *Path, FPOptionsOverride FPO, SourceLocation LPLoc, + SourceLocation RPLoc); + static CXXFunctionalCastExpr * + CreateEmpty(const ASTContext &Context, unsigned PathSize, bool HasFPFeatures); SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } @@ -4828,11 +4855,11 @@ public: BuiltinBitCastExpr(QualType T, ExprValueKind VK, CastKind CK, Expr *SrcExpr, TypeSourceInfo *DstType, SourceLocation KWLoc, SourceLocation RParenLoc) - : ExplicitCastExpr(BuiltinBitCastExprClass, T, VK, CK, SrcExpr, 0, + : ExplicitCastExpr(BuiltinBitCastExprClass, T, VK, CK, SrcExpr, 0, false, DstType), KWLoc(KWLoc), RParenLoc(RParenLoc) {} BuiltinBitCastExpr(EmptyShell Empty) - : ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0) {} + : ExplicitCastExpr(BuiltinBitCastExprClass, Empty, 0, false) {} SourceLocation getBeginLoc() const LLVM_READONLY { return KWLoc; } SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index 4b39d9ab96a6..17eec5172697 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -1639,12 +1639,12 @@ public: CastKind CK, SourceLocation BridgeKeywordLoc, TypeSourceInfo *TSInfo, Expr *Operand) : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue, - CK, Operand, 0, TSInfo), + CK, Operand, 0, false, TSInfo), LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {} /// Construct an empty Objective-C bridged cast. explicit ObjCBridgedCastExpr(EmptyShell Shell) - : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) {} + : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0, false) {} SourceLocation getLParenLoc() const { return LParenLoc; } diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 1e04e64727a0..4a6e8182e5a0 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -521,6 +521,9 @@ protected: unsigned Kind : 6; unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr. + /// True if the call expression has some floating-point features. + unsigned HasFPFeatures : 1; + /// The number of CXXBaseSpecifiers in the cast. 14 bits would be enough /// here. ([implimits] Direct and indirect base classes [16384]). unsigned BasePathSize; diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index f68a5dbfc2a0..15ca348f4766 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -270,6 +270,7 @@ public: void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); void VisitCXXThisExpr(const CXXThisExpr *Node); void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); + void VisitCXXStaticCastExpr(const CXXStaticCastExpr *Node); void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node); void VisitCXXConstructExpr(const CXXConstructExpr *Node); void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 2c8bb55cb5d9..3614496ded96 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -497,6 +497,8 @@ public: FPOptionsOverride() {} FPOptionsOverride(const LangOptions &LO) : Options(LO), OverrideMask(OverrideMaskBits) {} + FPOptionsOverride(FPOptions FPO) + : Options(FPO), OverrideMask(OverrideMaskBits) {} bool requiresTrailingStorage() const { return OverrideMask != 0; } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 7334d5b659e2..dd3c8518c2a3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6930,7 +6930,7 @@ ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { return ImplicitCastExpr::Create( Importer.getToContext(), *ToTypeOrErr, E->getCastKind(), *ToSubExprOrErr, - &(*ToBasePathOrErr), E->getValueKind()); + &(*ToBasePathOrErr), E->getValueKind(), E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { @@ -6957,8 +6957,8 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { return ToRParenLocOrErr.takeError(); return CStyleCastExpr::Create( Importer.getToContext(), ToType, E->getValueKind(), E->getCastKind(), - ToSubExpr, ToBasePath, ToTypeInfoAsWritten, *ToLParenLocOrErr, - *ToRParenLocOrErr); + ToSubExpr, ToBasePath, CCE->getFPFeatures(), ToTypeInfoAsWritten, + *ToLParenLocOrErr, *ToRParenLocOrErr); } case Stmt::CXXFunctionalCastExprClass: { @@ -6971,8 +6971,8 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { return ToRParenLocOrErr.takeError(); return CXXFunctionalCastExpr::Create( Importer.getToContext(), ToType, E->getValueKind(), ToTypeInfoAsWritten, - E->getCastKind(), ToSubExpr, ToBasePath, *ToLParenLocOrErr, - *ToRParenLocOrErr); + E->getCastKind(), ToSubExpr, ToBasePath, FCE->getFPFeatures(), + *ToLParenLocOrErr, *ToRParenLocOrErr); } case Stmt::ObjCBridgedCastExprClass: { @@ -7815,10 +7815,11 @@ ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { if (!ToBasePathOrErr) return ToBasePathOrErr.takeError(); - if (isa(E)) { + if (auto CCE = dyn_cast(E)) { return CXXStaticCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), - ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); + ToTypeInfoAsWritten, CCE->getFPFeatures(), ToOperatorLoc, ToRParenLoc, + ToAngleBrackets); } else if (isa(E)) { return CXXDynamicCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 15f3df0fd216..b664224aa732 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1892,19 +1892,42 @@ const FieldDecl *CastExpr::getTargetFieldForToUnionCast(const RecordDecl *RD, return nullptr; } +FPOptionsOverride *CastExpr::getTrailingFPFeatures() { + assert(hasStoredFPFeatures()); + switch (getStmtClass()) { + case ImplicitCastExprClass: + return static_cast(this) + ->getTrailingObjects(); + case CStyleCastExprClass: + return static_cast(this) + ->getTrailingObjects(); + case CXXFunctionalCastExprClass: + return static_cast(this) + ->getTrailingObjects(); + case CXXStaticCastExprClass: + return static_cast(this) + ->getTrailingObjects(); + default: + llvm_unreachable("Cast does not have FPFeatures"); + } +} + ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, - ExprValueKind VK) { + ExprValueKind VK, + FPOptionsOverride FPO) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, FPO.requiresTrailingStorage())); // Per C++ [conv.lval]p3, lvalue-to-rvalue conversions on class and // std::nullptr_t have special semantics not captured by CK_LValueToRValue. assert((Kind != CK_LValueToRValue || !(T->isNullPtrType() || T->getAsCXXRecordDecl())) && "invalid type for lvalue-to-rvalue conversion"); ImplicitCastExpr *E = - new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK); + new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, FPO, VK); if (PathSize) std::uninitialized_copy_n(BasePath->data(), BasePath->size(), E->getTrailingObjects()); @@ -1912,21 +1935,26 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T, } ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C, - unsigned PathSize) { - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); - return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize); + unsigned PathSize, + bool HasFPFeatures) { + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, HasFPFeatures)); + return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize, HasFPFeatures); } - CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, + FPOptionsOverride FPO, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, FPO.requiresTrailingStorage())); CStyleCastExpr *E = - new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R); + new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, FPO, WrittenTy, L, R); if (PathSize) std::uninitialized_copy_n(BasePath->data(), BasePath->size(), E->getTrailingObjects()); @@ -1934,9 +1962,12 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T, } CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C, - unsigned PathSize) { - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); - return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize); + unsigned PathSize, + bool HasFPFeatures) { + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, HasFPFeatures)); + return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize, HasFPFeatures); } /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 3d61496f30e2..3f3f2303587d 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -690,19 +690,18 @@ const char *CXXNamedCastExpr::getCastName() const { } } -CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T, - ExprValueKind VK, - CastKind K, Expr *Op, - const CXXCastPath *BasePath, - TypeSourceInfo *WrittenTy, - SourceLocation L, - SourceLocation RParenLoc, - SourceRange AngleBrackets) { +CXXStaticCastExpr * +CXXStaticCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, + CastKind K, Expr *Op, const CXXCastPath *BasePath, + TypeSourceInfo *WrittenTy, FPOptionsOverride FPO, + SourceLocation L, SourceLocation RParenLoc, + SourceRange AngleBrackets) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); - auto *E = - new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, - RParenLoc, AngleBrackets); + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, FPO.requiresTrailingStorage())); + auto *E = new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, + FPO, L, RParenLoc, AngleBrackets); if (PathSize) std::uninitialized_copy_n(BasePath->data(), BasePath->size(), E->getTrailingObjects()); @@ -710,9 +709,12 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T, } CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C, - unsigned PathSize) { - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); - return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize); + unsigned PathSize, + bool HasFPFeatures) { + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, HasFPFeatures)); + return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize, HasFPFeatures); } CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T, @@ -823,25 +825,30 @@ CXXAddrspaceCastExpr *CXXAddrspaceCastExpr::CreateEmpty(const ASTContext &C) { return new (C) CXXAddrspaceCastExpr(EmptyShell()); } -CXXFunctionalCastExpr * -CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK, - TypeSourceInfo *Written, CastKind K, Expr *Op, - const CXXCastPath *BasePath, - SourceLocation L, SourceLocation R) { +CXXFunctionalCastExpr *CXXFunctionalCastExpr::Create( + const ASTContext &C, QualType T, ExprValueKind VK, TypeSourceInfo *Written, + CastKind K, Expr *Op, const CXXCastPath *BasePath, FPOptionsOverride FPO, + SourceLocation L, SourceLocation R) { unsigned PathSize = (BasePath ? BasePath->size() : 0); - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); - auto *E = - new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R); + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, FPO.requiresTrailingStorage())); + auto *E = new (Buffer) + CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, FPO, L, R); if (PathSize) std::uninitialized_copy_n(BasePath->data(), BasePath->size(), E->getTrailingObjects()); return E; } -CXXFunctionalCastExpr * -CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) { - void *Buffer = C.Allocate(totalSizeToAlloc(PathSize)); - return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize); +CXXFunctionalCastExpr *CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, + unsigned PathSize, + bool HasFPFeatures) { + void *Buffer = + C.Allocate(totalSizeToAlloc( + PathSize, HasFPFeatures)); + return new (Buffer) + CXXFunctionalCastExpr(EmptyShell(), PathSize, HasFPFeatures); } SourceLocation CXXFunctionalCastExpr::getBeginLoc() const { diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 16c4c3736a4a..acbc0434931d 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -964,6 +964,8 @@ void TextNodeDumper::VisitCastExpr(const CastExpr *Node) { } dumpBasePath(OS, Node); OS << ">"; + if (Node->hasStoredFPFeatures()) + printFPOptions(Node->getFPFeatures()); } void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) { @@ -1132,6 +1134,14 @@ void TextNodeDumper::VisitCXXFunctionalCastExpr( const CXXFunctionalCastExpr *Node) { OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <" << Node->getCastKindName() << ">"; + if (Node->hasStoredFPFeatures()) + printFPOptions(Node->getFPFeatures()); +} + +void TextNodeDumper::VisitCXXStaticCastExpr(const CXXStaticCastExpr *Node) { + VisitCXXNamedCastExpr(Node); + if (Node->hasStoredFPFeatures()) + printFPOptions(Node->getFPFeatures()); } void TextNodeDumper::VisitCXXUnresolvedConstructExpr( diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp index f68b06487f98..603da6715625 100644 --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -166,23 +166,21 @@ ASTMaker::makeLvalueToRvalue(const VarDecl *Arg, ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty, CastKind CK) { return ImplicitCastExpr::Create(C, Ty, - /* CastKind=*/ CK, - /* Expr=*/ const_cast(Arg), - /* CXXCastPath=*/ nullptr, - /* ExprValueKind=*/ VK_RValue); + /* CastKind=*/CK, + /* Expr=*/const_cast(Arg), + /* CXXCastPath=*/nullptr, + /* ExprValueKind=*/VK_RValue, + /* FPFeatures */ FPOptionsOverride()); } Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) { if (Arg->getType() == Ty) return const_cast(Arg); - - return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast, - const_cast(Arg), nullptr, VK_RValue); + return makeImplicitCast(Arg, Ty, CK_IntegralCast); } ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) { - return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean, - const_cast(Arg), nullptr, VK_RValue); + return makeImplicitCast(Arg, C.BoolTy, CK_IntegralToBoolean); } ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) { diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 615b78235041..74de3df9d900 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1024,7 +1024,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { type, VK_LValue, SourceLocation()); ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, - &declRef, VK_RValue); + &declRef, VK_RValue, CurFPFeatures); // FIXME: Pass a specific location for the expr init so that the store is // attributed to a reasonable location - otherwise it may be attributed to // locations of subexpressions in the initialization. diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 26dfb6259a29..f2807eefd7f3 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1449,9 +1449,9 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, ValueDecl *selfDecl = setterMethod->getSelfDecl(); DeclRefExpr self(getContext(), selfDecl, false, selfDecl->getType(), VK_LValue, SourceLocation()); - ImplicitCastExpr selfLoad(ImplicitCastExpr::OnStack, - selfDecl->getType(), CK_LValueToRValue, &self, - VK_RValue); + ImplicitCastExpr selfLoad(ImplicitCastExpr::OnStack, selfDecl->getType(), + CK_LValueToRValue, &self, VK_RValue, + FPOptionsOverride(CurFPFeatures)); ObjCIvarRefExpr ivarRef(ivar, ivar->getType().getNonReferenceType(), SourceLocation(), SourceLocation(), &selfLoad, true, true); @@ -1462,7 +1462,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, SourceLocation()); ImplicitCastExpr argLoad(ImplicitCastExpr::OnStack, argType.getUnqualifiedType(), CK_LValueToRValue, - &arg, VK_RValue); + &arg, VK_RValue, CurFPFeatures); // The property type can differ from the ivar type in some situations with // Objective-C pointer types, we can always bit cast the RHS in these cases. @@ -1483,9 +1483,8 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, } else if (ivarRef.getType()->isPointerType()) { argCK = CK_BitCast; } - ImplicitCastExpr argCast(ImplicitCastExpr::OnStack, - ivarRef.getType(), argCK, &argLoad, - VK_RValue); + ImplicitCastExpr argCast(ImplicitCastExpr::OnStack, ivarRef.getType(), argCK, + &argLoad, VK_RValue, CurFPFeatures); Expr *finalArg = &argLoad; if (!getContext().hasSameUnqualifiedType(ivarRef.getType(), argLoad.getType())) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index b9260892bd21..19dc9a87f239 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -4137,7 +4137,7 @@ createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, PrivateVD->setInitStyle(VarDecl::CInit); PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue, InitRef, /*BasePath=*/nullptr, - VK_RValue)); + VK_RValue, FPOptionsOverride())); Data.FirstprivateVars.emplace_back(OrigRef); Data.FirstprivateCopies.emplace_back(PrivateRef); Data.FirstprivateInits.emplace_back(InitRef); diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 8c41e71ef018..c0c81221b234 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -586,7 +586,8 @@ namespace { CastKind Kind, Expr *E) { TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr, - TInfo, SourceLocation(), SourceLocation()); + FPOptionsOverride(), TInfo, + SourceLocation(), SourceLocation()); } bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const { @@ -2105,8 +2106,8 @@ RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD, // Now, we cast the reference to a pointer to the objc_msgSend type. QualType pToFunc = Context->getPointerType(msgSendType); ImplicitCastExpr *ICE = - ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, - DRE, nullptr, VK_RValue); + ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, + DRE, nullptr, VK_RValue, FPOptionsOverride()); const auto *FT = msgSendType->castAs(); CallExpr *Exp = diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp index 4ecd6e95de10..990509a84b06 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -492,7 +492,8 @@ namespace { CastKind Kind, Expr *E) { TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr, - TInfo, SourceLocation(), SourceLocation()); + FPOptionsOverride(), TInfo, + SourceLocation(), SourceLocation()); } StringLiteral *getStringLiteral(StringRef Str) { @@ -2022,8 +2023,8 @@ RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD, // Now, we cast the reference to a pointer to the objc_msgSend type. QualType pToFunc = Context->getPointerType(msgSendType); ImplicitCastExpr *ICE = - ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, - DRE, nullptr, VK_RValue); + ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, + DRE, nullptr, VK_RValue, FPOptionsOverride()); const auto *FT = msgSendType->castAs(); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 47484c5be9c9..375fe3b28dec 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -586,7 +586,8 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, } } - return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK); + return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK, + CurFPFeatureOverrides()); } /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 726900c59f20..5222722e7181 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -105,10 +105,9 @@ namespace { // If this is an unbridged cast, wrap the result in an implicit // cast that yields the unbridged-cast placeholder type. if (IsARCUnbridgedCast) { - castExpr = ImplicitCastExpr::Create(Self.Context, - Self.Context.ARCUnbridgedCastTy, - CK_Dependent, castExpr, nullptr, - castExpr->getValueKind()); + castExpr = ImplicitCastExpr::Create( + Self.Context, Self.Context.ARCUnbridgedCastTy, CK_Dependent, + castExpr, nullptr, castExpr->getValueKind(), FPOptionsOverride()); } updatePartOfExplicitCastFlags(castExpr); return castExpr; @@ -361,11 +360,10 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); } - return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, Op.Kind, Op.SrcExpr.get(), - &Op.BasePath, DestTInfo, - OpLoc, Parens.getEnd(), - AngleBrackets)); + return Op.complete(CXXStaticCastExpr::Create( + Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(), + &Op.BasePath, DestTInfo, CurFPFeatureOverrides(), OpLoc, + Parens.getEnd(), AngleBrackets)); } } } @@ -3033,9 +3031,9 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, // -Wcast-qual DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType); - return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, Op.Kind, Op.SrcExpr.get(), - &Op.BasePath, CastTypeInfo, LPLoc, RPLoc)); + return Op.complete(CStyleCastExpr::Create( + Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(), + &Op.BasePath, CurFPFeatureOverrides(), CastTypeInfo, LPLoc, RPLoc)); } ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, @@ -3058,7 +3056,7 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, if (auto *ConstructExpr = dyn_cast(SubExpr)) ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc)); - return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType, - Op.ValueKind, CastTypeInfo, Op.Kind, - Op.SrcExpr.get(), &Op.BasePath, LPLoc, RPLoc)); + return Op.complete(CXXFunctionalCastExpr::Create( + Context, Op.ResultType, Op.ValueKind, CastTypeInfo, Op.Kind, + Op.SrcExpr.get(), &Op.BasePath, CurFPFeatureOverrides(), LPLoc, RPLoc)); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a9e6113dc7bb..99e6678be51c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18172,11 +18172,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, // Adjust the Expr initializer and type. if (ECD->getInitExpr() && !Context.hasSameType(NewTy, ECD->getInitExpr()->getType())) - ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy, - CK_IntegralCast, - ECD->getInitExpr(), - /*base paths*/ nullptr, - VK_RValue)); + ECD->setInitExpr(ImplicitCastExpr::Create( + Context, NewTy, CK_IntegralCast, ECD->getInitExpr(), + /*base paths*/ nullptr, VK_RValue, CurFPFeatureOverrides())); if (getLangOpts().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 0a4f75ad341b..3a8a7708949e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1185,7 +1185,8 @@ static bool checkTupleLikeDecomposition(Sema &S, // an xvalue otherwise if (!Src->getType()->isLValueReferenceType()) E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp, - E.get(), nullptr, VK_XValue); + E.get(), nullptr, VK_XValue, + S.CurFPFeatureOverrides()); TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument( @@ -14869,9 +14870,9 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( // (since it's unusable otherwise); in the case where we inline the // block literal, it has block literal lifetime semantics. if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount) - BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(), - CK_CopyAndAutoreleaseBlockObject, - BuildBlock.get(), nullptr, VK_RValue); + BuildBlock = ImplicitCastExpr::Create( + Context, BuildBlock.get()->getType(), CK_CopyAndAutoreleaseBlockObject, + BuildBlock.get(), nullptr, VK_RValue, CurFPFeatureOverrides()); if (BuildBlock.isInvalid()) { Diag(CurrentLocation, diag::note_lambda_to_block_conv); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d6f0a12106fe..a33d6e2a83a1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -695,7 +695,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // C++ [conv.lval]p3: // If T is cv std::nullptr_t, the result is a null pointer constant. CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue; - Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue); + Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue, + CurFPFeatureOverrides()); // C11 6.3.2.1p2: // ... if the lvalue has atomic type, the value has the non-atomic version @@ -703,7 +704,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (const AtomicType *Atomic = T->getAs()) { T = Atomic->getValueType().getUnqualifiedType(); Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(), - nullptr, VK_RValue); + nullptr, VK_RValue, CurFPFeatureOverrides()); } return Res; @@ -6960,9 +6961,9 @@ void Sema::maybeExtendBlockObject(ExprResult &E) { // Only do this in an r-value context. if (!getLangOpts().ObjCAutoRefCount) return; - E = ImplicitCastExpr::Create(Context, E.get()->getType(), - CK_ARCExtendBlockObject, E.get(), - /*base path*/ nullptr, VK_RValue); + E = ImplicitCastExpr::Create( + Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(), + /*base path*/ nullptr, VK_RValue, CurFPFeatureOverrides()); Cleanup.setExprNeedsCleanups(true); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d1fcdf354527..09976197194a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1503,7 +1503,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); Result = CXXFunctionalCastExpr::Create( Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, - Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd()); + Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides(), + Locs.getBegin(), Locs.getEnd()); } return Result; @@ -2204,7 +2205,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, SizeTy, SourceLocation()); ImplicitCastExpr DesiredAlignment(ImplicitCastExpr::OnStack, AlignValT, CK_IntegralCast, &AlignmentLiteral, - VK_RValue); + VK_RValue, CurFPFeatureOverrides()); // Adjust placement args by prepending conjured size and alignment exprs. llvm::SmallVector CallArgs; @@ -3915,7 +3916,8 @@ static ExprResult BuildCXXCastArgument(Sema &S, // Record usage of conversion in an implicit cast. Result = ImplicitCastExpr::Create(S.Context, Result.get()->getType(), CK_UserDefinedConversion, Result.get(), - nullptr, Result.get()->getValueKind()); + nullptr, Result.get()->getValueKind(), + S.CurFPFeatureOverrides()); return S.MaybeBindToTemporary(Result.get()); } @@ -4096,7 +4098,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (const AtomicType *FromAtomic = FromType->getAs()) { FromType = FromAtomic->getValueType().getUnqualifiedType(); From = ImplicitCastExpr::Create(Context, FromType, CK_AtomicToNonAtomic, - From, /*BasePath=*/nullptr, VK_RValue); + From, /*BasePath=*/nullptr, VK_RValue, + CurFPFeatureOverrides()); } break; @@ -6840,7 +6843,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject : CK_ARCReclaimReturnedObject); return ImplicitCastExpr::Create(Context, E->getType(), ck, E, nullptr, - VK_RValue); + VK_RValue, CurFPFeatureOverrides()); } if (E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct) diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 228a1ec3ba1f..9a0c4e2d4320 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -4462,8 +4462,8 @@ Sema::CheckObjCConversion(SourceRange castRange, QualType castType, // If the result is +1, consume it here. case ACC_plusOne: castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), - CK_ARCConsumeObject, castExpr, - nullptr, VK_RValue); + CK_ARCConsumeObject, castExpr, nullptr, + VK_RValue, CurFPFeatureOverrides()); Cleanup.setExprNeedsCleanups(true); return ACR_okay; } @@ -4689,9 +4689,9 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, case OBC_BridgeRetained: // Produce the object before casting it. - SubExpr = ImplicitCastExpr::Create(Context, FromType, - CK_ARCProduceObject, - SubExpr, nullptr, VK_RValue); + SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject, + SubExpr, nullptr, VK_RValue, + CurFPFeatureOverrides()); break; case OBC_BridgeTransfer: { @@ -4729,8 +4729,9 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, if (MustConsume) { Cleanup.setExprNeedsCleanups(true); - Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, - nullptr, VK_RValue); + Result = + ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, + nullptr, VK_RValue, CurFPFeatureOverrides()); } return Result; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index f63d600032ce..b6bd6cff4d77 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2891,7 +2891,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, - Init, nullptr, VK_RValue); + Init, nullptr, VK_RValue, + SemaRef.CurFPFeatureOverrides()); StructuredList->updateInit(Context, i, Init); } } else { @@ -2913,7 +2914,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, - Init, nullptr, VK_RValue); + Init, nullptr, VK_RValue, + SemaRef.CurFPFeatureOverrides()); StructuredList->updateInit(Context, i, Init); } } @@ -8019,9 +8021,9 @@ ExprResult InitializationSequence::Perform(Sema &S, (Step->Kind == SK_CastDerivedToBaseXValue ? VK_XValue : VK_RValue); - CurInit = - ImplicitCastExpr::Create(S.Context, Step->Type, CK_DerivedToBase, - CurInit.get(), &BasePath, VK); + CurInit = ImplicitCastExpr::Create( + S.Context, Step->Type, CK_DerivedToBase, CurInit.get(), &BasePath, VK, + S.CurFPFeatureOverrides()); break; } @@ -8150,9 +8152,9 @@ ExprResult InitializationSequence::Perform(Sema &S, if (CreatedObject && checkAbstractType(CurInit.get()->getType())) return ExprError(); - CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(), - CastKind, CurInit.get(), nullptr, - CurInit.get()->getValueKind()); + CurInit = ImplicitCastExpr::Create( + S.Context, CurInit.get()->getType(), CastKind, CurInit.get(), nullptr, + CurInit.get()->getValueKind(), S.CurFPFeatureOverrides()); if (shouldBindAsTemporary(Entity)) // The overall entity is temporary, so this expression should be @@ -8493,9 +8495,9 @@ ExprResult InitializationSequence::Perform(Sema &S, break; case SK_ProduceObjCObject: - CurInit = - ImplicitCastExpr::Create(S.Context, Step->Type, CK_ARCProduceObject, - CurInit.get(), nullptr, VK_RValue); + CurInit = ImplicitCastExpr::Create( + S.Context, Step->Type, CK_ARCProduceObject, CurInit.get(), nullptr, + VK_RValue, S.CurFPFeatureOverrides()); break; case SK_StdInitializerList: { @@ -8549,9 +8551,9 @@ ExprResult InitializationSequence::Perform(Sema &S, // Case 1b and 1c // No cast from integer to sampler is needed. if (!Var->hasGlobalStorage()) { - CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, - CK_LValueToRValue, Init, - /*BasePath=*/nullptr, VK_RValue); + CurInit = ImplicitCastExpr::Create( + S.Context, Step->Type, CK_LValueToRValue, Init, + /*BasePath=*/nullptr, VK_RValue, S.CurFPFeatureOverrides()); break; } // Case 1a diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index c9f2854f7acc..a870d822b42f 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -680,8 +680,9 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef returns, ExprWithCleanups *cleanups = dyn_cast(retValue); Expr *E = (cleanups ? cleanups->getSubExpr() : retValue); - E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, - E, /*base path*/ nullptr, VK_RValue); + E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, E, + /*base path*/ nullptr, VK_RValue, + S.CurFPFeatureOverrides()); if (cleanups) { cleanups->setSubExpr(E); } else { diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index e301c62dd2c0..f6ed3e65f94c 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1464,10 +1464,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, PropertyDiagLoc); MarkDeclRefReferenced(SelfExpr); - Expr *LoadSelfExpr = - ImplicitCastExpr::Create(Context, SelfDecl->getType(), - CK_LValueToRValue, SelfExpr, nullptr, - VK_RValue); + Expr *LoadSelfExpr = ImplicitCastExpr::Create( + Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, + VK_RValue, CurFPFeatureOverrides()); Expr *IvarRefExpr = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getUsageType(SelfDecl->getType()), @@ -1528,10 +1527,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, PropertyDiagLoc); MarkDeclRefReferenced(SelfExpr); - Expr *LoadSelfExpr = - ImplicitCastExpr::Create(Context, SelfDecl->getType(), - CK_LValueToRValue, SelfExpr, nullptr, - VK_RValue); + Expr *LoadSelfExpr = ImplicitCastExpr::Create( + Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, + VK_RValue, CurFPFeatureOverrides()); Expr *lhs = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getUsageType(SelfDecl->getType()), diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 352f52d2f626..4a444b38a0aa 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -15388,12 +15388,12 @@ static bool actOnOMPReductionKindClause( if (!BasePath.empty()) { LHS = S.DefaultLvalueConversion(LHS.get()); RHS = S.DefaultLvalueConversion(RHS.get()); - LHS = ImplicitCastExpr::Create(Context, PtrRedTy, - CK_UncheckedDerivedToBase, LHS.get(), - &BasePath, LHS.get()->getValueKind()); - RHS = ImplicitCastExpr::Create(Context, PtrRedTy, - CK_UncheckedDerivedToBase, RHS.get(), - &BasePath, RHS.get()->getValueKind()); + LHS = ImplicitCastExpr::Create( + Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath, + LHS.get()->getValueKind(), S.CurFPFeatureOverrides()); + RHS = ImplicitCastExpr::Create( + Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath, + RHS.get()->getValueKind(), S.CurFPFeatureOverrides()); } FunctionProtoType::ExtProtoInfo EPI; QualType Params[] = {PtrRedTy, PtrRedTy}; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 71341e5688fe..fa68f3a4deab 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5862,7 +5862,8 @@ diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, // Record usage of conversion in an implicit cast. From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), CK_UserDefinedConversion, Result.get(), - nullptr, Result.get()->getValueKind()); + nullptr, Result.get()->getValueKind(), + SemaRef.CurFPFeatureOverrides()); } return false; } @@ -5891,7 +5892,8 @@ static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From, // Record usage of conversion in an implicit cast. From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(), CK_UserDefinedConversion, Result.get(), - nullptr, Result.get()->getValueKind()); + nullptr, Result.get()->getValueKind(), + SemaRef.CurFPFeatureOverrides()); return false; } @@ -7296,8 +7298,8 @@ void Sema::AddConversionCandidate( VK_LValue, From->getBeginLoc()); ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, Context.getPointerType(Conversion->getType()), - CK_FunctionToPointerDecay, - &ConversionRef, VK_RValue); + CK_FunctionToPointerDecay, &ConversionRef, + VK_RValue, CurFPFeatureOverrides()); QualType ConversionType = Conversion->getConversionType(); if (!isCompleteType(From->getBeginLoc(), ConversionType)) { @@ -14422,9 +14424,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (Call.isInvalid()) return ExprError(); // Record usage of conversion in an implicit cast. - Call = ImplicitCastExpr::Create(Context, Call.get()->getType(), - CK_UserDefinedConversion, Call.get(), - nullptr, VK_RValue); + Call = ImplicitCastExpr::Create( + Context, Call.get()->getType(), CK_UserDefinedConversion, Call.get(), + nullptr, VK_RValue, CurFPFeatureOverrides()); return BuildCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc); } @@ -14829,10 +14831,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (SubExpr == ICE->getSubExpr()) return ICE; - return ImplicitCastExpr::Create(Context, ICE->getType(), - ICE->getCastKind(), - SubExpr, nullptr, - ICE->getValueKind()); + return ImplicitCastExpr::Create(Context, ICE->getType(), ICE->getCastKind(), + SubExpr, nullptr, ICE->getValueKind(), + CurFPFeatureOverrides()); } if (auto *GSE = dyn_cast(E)) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index c44636ad1b39..e461ad448481 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3095,7 +3095,8 @@ static void TryMoveInitialization(Sema& S, bool ConvertingConstructorsOnly, ExprResult &Res) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), - CK_NoOp, Value, VK_XValue); + CK_NoOp, Value, VK_XValue, + S.CurFPFeatureOverrides()); Expr *InitExpr = &AsRvalue; @@ -3150,8 +3151,9 @@ static void TryMoveInitialization(Sema& S, // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. - Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, - Value, nullptr, VK_XValue); + Value = + ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, Value, + nullptr, VK_XValue, S.CurFPFeatureOverrides()); // Complete type-checking the initialization of the return type // using the constructor we found. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6721b0725329..e1a563850970 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -7478,7 +7478,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, // FIXME: This is a hack. We need a better way to handle substituted // non-type template parameters. E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E, - nullptr, + nullptr, CurFPFeatureOverrides(), Context.getTrivialTypeSourceInfo(OrigT, Loc), Loc, Loc); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index e261044f7cb1..48897cd2d822 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1082,6 +1082,8 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { VisitExpr(E); unsigned NumBaseSpecs = Record.readInt(); assert(NumBaseSpecs == E->path_size()); + unsigned HasFPFeatures = Record.readInt(); + assert(E->hasStoredFPFeatures() == HasFPFeatures); E->setSubExpr(Record.readSubExpr()); E->setCastKind((CastKind)Record.readInt()); CastExpr::path_iterator BaseI = E->path_begin(); @@ -1090,6 +1092,8 @@ void ASTStmtReader::VisitCastExpr(CastExpr *E) { *BaseSpec = Record.readCXXBaseSpecifier(); *BaseI++ = BaseSpec; } + if (HasFPFeatures) + *E->getTrailingFPFeatures() = FPOptionsOverride::getFromOpaqueInt(Record.readInt()); } void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) { @@ -2893,13 +2897,17 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_IMPLICIT_CAST: - S = ImplicitCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); + S = ImplicitCastExpr::CreateEmpty( + Context, + /*PathSize*/ Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); break; case EXPR_CSTYLE_CAST: - S = CStyleCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); + S = CStyleCastExpr::CreateEmpty( + Context, + /*PathSize*/ Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); break; case EXPR_COMPOUND_LITERAL: @@ -3501,8 +3509,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CXX_STATIC_CAST: - S = CXXStaticCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); + S = CXXStaticCastExpr::CreateEmpty( + Context, + /*PathSize*/ Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); break; case EXPR_CXX_DYNAMIC_CAST: @@ -3524,8 +3534,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CXX_FUNCTIONAL_CAST: - S = CXXFunctionalCastExpr::CreateEmpty(Context, - /*PathSize*/ Record[ASTStmtReader::NumExprFields]); + S = CXXFunctionalCastExpr::CreateEmpty( + Context, + /*PathSize*/ Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]); break; case EXPR_BUILTIN_BIT_CAST: diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 2d250674057c..911fcb409547 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2346,6 +2346,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind // CastExpr Abv->Add(BitCodeAbbrevOp(0)); // PathSize + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasFPFeatures Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast // ImplicitCastExpr diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 4e3e1fdc346f..0121f2583207 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -946,12 +946,16 @@ void ASTStmtWriter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) { void ASTStmtWriter::VisitCastExpr(CastExpr *E) { VisitExpr(E); Record.push_back(E->path_size()); + Record.push_back(E->hasStoredFPFeatures()); Record.AddStmt(E->getSubExpr()); Record.push_back(E->getCastKind()); // FIXME: stable encoding for (CastExpr::path_iterator PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI) Record.AddCXXBaseSpecifier(**PI); + + if (E->hasStoredFPFeatures()) + Record.push_back(E->getFPFeatures().getAsOpaqueInt()); } void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) { @@ -1003,7 +1007,7 @@ void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { VisitCastExpr(E); Record.push_back(E->isPartOfExplicitCast()); - if (E->path_size() == 0) + if (E->path_size() == 0 && !E->hasStoredFPFeatures()) AbbrevToUse = Writer.getExprImplicitCastAbbrev(); Code = serialization::EXPR_IMPLICIT_CAST; diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp b/clang/test/AST/ast-dump-fpfeatures.cpp index f3925aebbe75..830623ff4852 100644 --- a/clang/test/AST/ast-dump-fpfeatures.cpp +++ b/clang/test/AST/ast-dump-fpfeatures.cpp @@ -36,6 +36,51 @@ float func_03(float x) { // CHECK-NEXT: ReturnStmt // CHECK-NEXT: CallExpr {{.*}} FPContractMode=0 +int func_04(float x) { +#pragma STDC FP_CONTRACT ON + return x; +} + +// CHECK: FunctionDecl {{.*}} func_04 'int (float)' +// CHECK-NEXT: ParmVarDecl {{.*}} x 'float' +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ReturnStmt +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' FPContractMode=1 + +float func_05(double x) { +#pragma STDC FP_CONTRACT ON + return (float)x; +} + +// CHECK: FunctionDecl {{.*}} func_05 'float (double)' +// CHECK-NEXT: ParmVarDecl {{.*}} x 'double' +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ReturnStmt +// CHECK-NEXT: CStyleCastExpr {{.*}} FPContractMode=1 + +float func_06(double x) { +#pragma STDC FP_CONTRACT ON + return float(x); +} + +// CHECK: FunctionDecl {{.*}} func_06 'float (double)' +// CHECK-NEXT: ParmVarDecl {{.*}} x 'double' +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ReturnStmt +// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} FPContractMode=1 + +float func_07(double x) { +#pragma STDC FP_CONTRACT ON + return static_cast(x); +} + +// CHECK: FunctionDecl {{.*}} func_07 'float (double)' +// CHECK-NEXT: ParmVarDecl {{.*}} x 'double' +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ReturnStmt +// CHECK-NEXT: CXXStaticCastExpr {{.*}} FPContractMode=1 +// CHECK-NEXT: CallExpr {{.*}} FPContractMode=0 +