[clang] 6c8041a - [AST][FPEnv] Keep FP options in trailing storage of CastExpr
Serge Pavlov via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 12 00:32:01 PDT 2020
Author: Serge Pavlov
Date: 2020-09-12T14:30:44+07:00
New Revision: 6c8041aa0ffed827636935e59c489b1e390c8542
URL: https://github.com/llvm/llvm-project/commit/6c8041aa0ffed827636935e59c489b1e390c8542
DIFF: https://github.com/llvm/llvm-project/commit/6c8041aa0ffed827636935e59c489b1e390c8542.diff
LOG: [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
Added:
Modified:
clang/include/clang/AST/Expr.h
clang/include/clang/AST/ExprCXX.h
clang/include/clang/AST/ExprObjC.h
clang/include/clang/AST/Stmt.h
clang/include/clang/AST/TextNodeDumper.h
clang/include/clang/Basic/LangOptions.h
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprCXX.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/Analysis/BodyFarm.cpp
clang/lib/CodeGen/CGBlocks.cpp
clang/lib/CodeGen/CGObjC.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
clang/lib/Frontend/Rewrite/RewriteObjC.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaExprObjC.cpp
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaLambda.cpp
clang/lib/Sema/SemaObjCProperty.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaStmt.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/test/AST/ast-dump-fpfeatures.cpp
Removed:
################################################################################
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 @@ class CastExpr : public Expr {
"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<CastExpr *>(this)->getTrailingFPFeatures();
+ }
+
public:
CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
void setCastKind(CastKind K) { CastExprBits.Kind = K; }
@@ -3506,6 +3518,28 @@ class CastExpr : public Expr {
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 @@ class CastExpr : public Expr {
/// @endcode
class ImplicitCastExpr final
: public CastExpr,
- private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *,
+ FPOptionsOverride> {
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<CXXBaseSpecifier *>) 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 @@ class ImplicitCastExpr final
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 @@ class ExplicitCastExpr : public CastExpr {
/// (Type)expr. For example: @c (int)f.
class CStyleCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *,
+ FPOptionsOverride> {
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<CXXBaseSpecifier *>) 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 @@ class CXXNamedCastExpr : public ExplicitCastExpr {
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 @@ class CXXNamedCastExpr : public ExplicitCastExpr {
/// \c static_cast<int>(1.0).
class CXXStaticCastExpr final
: public CXXNamedCastExpr,
- private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *,
+ FPOptionsOverride> {
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<CXXBaseSpecifier *>) 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 @@ class CXXStaticCastExpr final
class CXXDynamicCastExpr final
: public CXXNamedCastExpr,
private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
- 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,
CXXBaseSpecifier *> {
- 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 @@ class CXXInheritedCtorInitExpr : public Expr {
/// \endcode
class CXXFunctionalCastExpr final
: public ExplicitCastExpr,
- private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> {
+ private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *,
+ FPOptionsOverride> {
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,
+ bool HasFPFeatures)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize,
+ HasFPFeatures) {}
- explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {}
+ unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) 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 @@ class BuiltinBitCastExpr final
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 @@ class ObjCBridgedCastExpr final
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 @@ class alignas(void *) Stmt {
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 @@ class TextNodeDumper
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 @@ class FPOptionsOverride {
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<CXXStaticCastExpr>(E)) {
+ if (auto CCE = dyn_cast<CXXStaticCastExpr>(E)) {
return CXXStaticCastExpr::Create(
Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
- ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
+ ToTypeInfoAsWritten, CCE->getFPFeatures(), ToOperatorLoc, ToRParenLoc,
+ ToAngleBrackets);
} else if (isa<CXXDynamicCastExpr>(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<ImplicitCastExpr *>(this)
+ ->getTrailingObjects<FPOptionsOverride>();
+ case CStyleCastExprClass:
+ return static_cast<CStyleCastExpr *>(this)
+ ->getTrailingObjects<FPOptionsOverride>();
+ case CXXFunctionalCastExprClass:
+ return static_cast<CXXFunctionalCastExpr *>(this)
+ ->getTrailingObjects<FPOptionsOverride>();
+ case CXXStaticCastExprClass:
+ return static_cast<CXXStaticCastExpr *>(this)
+ ->getTrailingObjects<FPOptionsOverride>();
+ 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<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<CXXBaseSpecifier *>());
@@ -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<CXXBaseSpecifier *>(PathSize));
- return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
+ unsigned PathSize,
+ bool HasFPFeatures) {
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<CXXBaseSpecifier *>(PathSize));
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<CXXBaseSpecifier *>());
@@ -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<CXXBaseSpecifier *>(PathSize));
- return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
+ unsigned PathSize,
+ bool HasFPFeatures) {
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<CXXBaseSpecifier *>(PathSize));
- auto *E =
- new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
- RParenLoc, AngleBrackets);
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<CXXBaseSpecifier *>());
@@ -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<CXXBaseSpecifier *>(PathSize));
- return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
+ unsigned PathSize,
+ bool HasFPFeatures) {
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<CXXBaseSpecifier *>(PathSize));
- auto *E =
- new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<CXXBaseSpecifier *>());
return E;
}
-CXXFunctionalCastExpr *
-CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
- return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
+CXXFunctionalCastExpr *CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C,
+ unsigned PathSize,
+ bool HasFPFeatures) {
+ void *Buffer =
+ C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+ 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<Expr *>(Arg),
- /* CXXCastPath=*/ nullptr,
- /* ExprValueKind=*/ VK_RValue);
+ /* CastKind=*/CK,
+ /* Expr=*/const_cast<Expr *>(Arg),
+ /* CXXCastPath=*/nullptr,
+ /* ExprValueKind=*/VK_RValue,
+ /* FPFeatures */ FPOptionsOverride());
}
Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
if (Arg->getType() == Ty)
return const_cast<Expr*>(Arg);
-
- return ImplicitCastExpr::Create(C, Ty, CK_IntegralCast,
- const_cast<Expr*>(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<Expr*>(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
diff er 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<FunctionType>();
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<FunctionType>();
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<CXXConstructExpr>(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<AtomicType>()) {
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<Expr *, 8> 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<AtomicType>()) {
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<ReturnStmt*> returns,
ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(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<GenericSelectionExpr>(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' <FloatingToIntegral> 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<float>(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
+
More information about the cfe-commits
mailing list