[clang] 70e7aa4 - [AST][FPEnv] Keep FP options in trailing storage of CallExpr
Serge Pavlov via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 23 22:05:35 PDT 2020
Author: Serge Pavlov
Date: 2020-07-24T12:04:19+07:00
New Revision: 70e7aa4a4ed36a034c43b249d0842f4f273b44e1
URL: https://github.com/llvm/llvm-project/commit/70e7aa4a4ed36a034c43b249d0842f4f273b44e1
DIFF: https://github.com/llvm/llvm-project/commit/70e7aa4a4ed36a034c43b249d0842f4f273b44e1.diff
LOG: [AST][FPEnv] Keep FP options in trailing storage of CallExpr
This change allow a CallExpr to have optional FPOptionsOverride object,
stored in trailing storage. The implementaion is made similar to the way
used in BinaryOperator.
Differential Revision: https://reviews.llvm.org/D84343
Added:
clang/test/AST/ast-dump-fpfeatures.cpp
Modified:
clang/include/clang/AST/Expr.h
clang/include/clang/AST/ExprCXX.h
clang/include/clang/AST/Stmt.h
clang/include/clang/AST/TextNodeDumper.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/Frontend/Rewrite/RewriteModernObjC.cpp
clang/lib/Frontend/Rewrite/RewriteObjC.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 24bface15d3e..96db7bc3be29 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2272,12 +2272,12 @@ class UnaryOperator final
/// Is FPFeatures in Trailing Storage?
bool hasStoredFPFeatures() const { return UnaryOperatorBits.HasFPFeatures; }
-protected:
- /// Get FPFeatures from trailing storage
+ /// Get FPFeatures from trailing storage.
FPOptionsOverride getStoredFPFeatures() const {
return getTrailingFPFeatures();
}
+protected:
/// Set FPFeatures in trailing storage, used only by Serialization
void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
@@ -2787,6 +2787,8 @@ class CallExpr : public Expr {
//
// * An array of getNumArgs() "Stmt *" for the argument expressions.
//
+ // * An optional of type FPOptionsOverride.
+ //
// Note that we store the offset in bytes from the this pointer to the start
// of the trailing objects. It would be perfectly possible to compute it
// based on the dynamic kind of the CallExpr. However 1.) we have plenty of
@@ -2808,6 +2810,15 @@ class CallExpr : public Expr {
/// this pointer to the trailing objects.
static unsigned offsetToTrailingObjects(StmtClass SC);
+ unsigned getSizeOfTrailingStmts() const {
+ return (1 + getNumPreArgs() + getNumArgs()) * sizeof(Stmt *);
+ }
+
+ size_t getOffsetOfTrailingFPFeatures() const {
+ assert(hasStoredFPFeatures());
+ return CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts();
+ }
+
public:
enum class ADLCallKind : bool { NotADL, UsesADL };
static constexpr ADLCallKind NotADL = ADLCallKind::NotADL;
@@ -2818,16 +2829,19 @@ class CallExpr : public Expr {
/// allocated for the trailing objects.
CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL);
+ SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
+ unsigned MinNumArgs, ADLCallKind UsesADL);
/// Build an empty call expression, for deserialization.
CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
- EmptyShell Empty);
+ bool hasFPFeatures, EmptyShell Empty);
/// Return the size in bytes needed for the trailing objects.
/// Used by the derived classes to allocate the right amount of storage.
- static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs) {
- return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *);
+ static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs,
+ bool HasFPFeatures) {
+ return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *) +
+ HasFPFeatures * sizeof(FPOptionsOverride);
}
Stmt *getPreArg(unsigned I) {
@@ -2845,22 +2859,43 @@ class CallExpr : public Expr {
unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
+ /// Return a pointer to the trailing FPOptions
+ FPOptionsOverride *getTrailingFPFeatures() {
+ assert(hasStoredFPFeatures());
+ return reinterpret_cast<FPOptionsOverride *>(
+ reinterpret_cast<char *>(this) + CallExprBits.OffsetToTrailingObjects +
+ getSizeOfTrailingStmts());
+ }
+ const FPOptionsOverride *getTrailingFPFeatures() const {
+ assert(hasStoredFPFeatures());
+ return reinterpret_cast<const FPOptionsOverride *>(
+ reinterpret_cast<const char *>(this) +
+ CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts());
+ }
+
public:
- /// Create a call expression. Fn is the callee expression, Args is the
- /// argument array, Ty is the type of the call expression (which is *not*
- /// the return type in general), VK is the value kind of the call expression
- /// (lvalue, rvalue, ...), and RParenLoc is the location of the right
- /// parenthese in the call expression. MinNumArgs specifies the minimum
- /// number of arguments. The actual number of arguments will be the greater
- /// of Args.size() and MinNumArgs. This is used in a few places to allocate
- /// enough storage for the default arguments. UsesADL specifies whether the
- /// callee was found through argument-dependent lookup.
+ /// Create a call expression.
+ /// \param Fn The callee expression,
+ /// \param Args The argument array,
+ /// \param Ty The type of the call expression (which is *not* the return
+ /// type in general),
+ /// \param VK The value kind of the call expression (lvalue, rvalue, ...),
+ /// \param RParenLoc The location of the right parenthesis in the call
+ /// expression.
+ /// \param FPFeatures Floating-point features associated with the call,
+ /// \param MinNumArgs Specifies the minimum number of arguments. The actual
+ /// number of arguments will be the greater of Args.size()
+ /// and MinNumArgs. This is used in a few places to allocate
+ /// enough storage for the default arguments.
+ /// \param UsesADL Specifies whether the callee was found through
+ /// argument-dependent lookup.
///
/// Note that you can use CreateTemporary if you need a temporary call
/// expression on the stack.
static CallExpr *Create(const ASTContext &Ctx, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation RParenLoc, unsigned MinNumArgs = 0,
+ SourceLocation RParenLoc,
+ FPOptionsOverride FPFeatures, unsigned MinNumArgs = 0,
ADLCallKind UsesADL = NotADL);
/// Create a temporary call expression with no arguments in the memory
@@ -2877,7 +2912,7 @@ class CallExpr : public Expr {
/// Create an empty call expression, for deserialization.
static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
- EmptyShell Empty);
+ bool HasFPFeatures, EmptyShell Empty);
Expr *getCallee() { return cast<Expr>(getTrailingStmts()[FN]); }
const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); }
@@ -2891,6 +2926,8 @@ class CallExpr : public Expr {
}
bool usesADL() const { return getADLCallKind() == UsesADL; }
+ bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; }
+
Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); }
const Decl *getCalleeDecl() const {
return getCallee()->getReferencedDeclOfCallee();
@@ -2983,6 +3020,31 @@ class CallExpr : public Expr {
/// this function call.
unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; }
+ /// Get FPOptionsOverride from trailing storage.
+ FPOptionsOverride getStoredFPFeatures() const {
+ assert(hasStoredFPFeatures());
+ return *getTrailingFPFeatures();
+ }
+ /// Set FPOptionsOverride in trailing storage. Used only by Serialization.
+ void setStoredFPFeatures(FPOptionsOverride F) {
+ assert(hasStoredFPFeatures());
+ *getTrailingFPFeatures() = F;
+ }
+
+ // Get the FP features status of this operator. 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();
+ }
+
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID
/// of the callee. If not, return 0.
unsigned getBuiltinCallee() const;
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 6f0b68479b9d..3f272c96a2d8 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -84,7 +84,6 @@ class CXXOperatorCallExpr final : public CallExpr {
friend class ASTStmtWriter;
SourceRange Range;
- FPOptionsOverride Overrides;
// CXXOperatorCallExpr has some trailing objects belonging
// to CallExpr. See CallExpr for the details.
@@ -96,7 +95,7 @@ class CXXOperatorCallExpr final : public CallExpr {
SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
ADLCallKind UsesADL);
- CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty);
+ CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
public:
static CXXOperatorCallExpr *
@@ -106,7 +105,8 @@ class CXXOperatorCallExpr final : public CallExpr {
ADLCallKind UsesADL = NotADL);
static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx,
- unsigned NumArgs, EmptyShell Empty);
+ unsigned NumArgs, bool HasFPFeatures,
+ EmptyShell Empty);
/// Returns the kind of overloaded operator that this expression refers to.
OverloadedOperatorKind getOperator() const {
@@ -164,11 +164,6 @@ class CXXOperatorCallExpr final : public CallExpr {
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXOperatorCallExprClass;
}
-
- // Set the FPFeatures status of this operator. Only meaningful for
- // operations on floating point types.
- void setFPFeatures(FPOptionsOverride F) { Overrides = F; }
- FPOptionsOverride getFPFeatures() const { return Overrides; }
};
/// Represents a call to a member function that
@@ -184,18 +179,20 @@ class CXXMemberCallExpr final : public CallExpr {
// to CallExpr. See CallExpr for the details.
CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
- ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs);
+ ExprValueKind VK, SourceLocation RP,
+ FPOptionsOverride FPOptions, unsigned MinNumArgs);
- CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty);
+ CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
public:
static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty,
ExprValueKind VK, SourceLocation RP,
+ FPOptionsOverride FPFeatures,
unsigned MinNumArgs = 0);
static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
- EmptyShell Empty);
+ bool HasFPFeatures, EmptyShell Empty);
/// Retrieve the implicit object argument for the member call.
///
@@ -242,18 +239,21 @@ class CUDAKernelCallExpr final : public CallExpr {
CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args,
QualType Ty, ExprValueKind VK, SourceLocation RP,
- unsigned MinNumArgs);
+ FPOptionsOverride FPFeatures, unsigned MinNumArgs);
- CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty);
+ CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
public:
static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
CallExpr *Config, ArrayRef<Expr *> Args,
QualType Ty, ExprValueKind VK,
- SourceLocation RP, unsigned MinNumArgs = 0);
+ SourceLocation RP,
+ FPOptionsOverride FPFeatures,
+ unsigned MinNumArgs = 0);
static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx,
- unsigned NumArgs, EmptyShell Empty);
+ unsigned NumArgs, bool HasFPFeatures,
+ EmptyShell Empty);
const CallExpr *getConfig() const {
return cast_or_null<CallExpr>(getPreArg(CONFIG));
@@ -619,18 +619,20 @@ class UserDefinedLiteral final : public CallExpr {
UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
ExprValueKind VK, SourceLocation LitEndLoc,
- SourceLocation SuffixLoc);
+ SourceLocation SuffixLoc, FPOptionsOverride FPFeatures);
- UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty);
+ UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
public:
static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty,
ExprValueKind VK, SourceLocation LitEndLoc,
- SourceLocation SuffixLoc);
+ SourceLocation SuffixLoc,
+ FPOptionsOverride FPFeatures);
static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx,
- unsigned NumArgs, EmptyShell Empty);
+ unsigned NumArgs, bool HasFPOptions,
+ EmptyShell Empty);
/// The kind of literal operator which is invoked.
enum LiteralOperatorKind {
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index d3fad58fcf59..13f265223ac1 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -464,8 +464,11 @@ class alignas(void *) Stmt {
/// True if the callee of the call expression was found using ADL.
unsigned UsesADL : 1;
+ /// True if the call expression has some floating-point features.
+ unsigned HasFPFeatures : 1;
+
/// Padding used to align OffsetToTrailingObjects to a byte multiple.
- unsigned : 24 - 2 - NumExprBits;
+ unsigned : 24 - 3 - NumExprBits;
/// The offset in bytes from the this pointer to the start of the
/// trailing objects belonging to CallExpr. Intentionally byte sized
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index b4cfb5a380d1..8e8084aec3c1 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -155,6 +155,7 @@ class TextNodeDumper
const comments::CommandTraits *Traits = nullptr;
const char *getCommandName(unsigned CommandID);
+ void printFPOptions(FPOptionsOverride FPO);
void dumpAPValueChildren(const APValue &Value, QualType Ty,
const APValue &(*IdxToChildFun)(const APValue &,
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3779e0cb872b..fcfaba625a72 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -7338,7 +7338,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
return std::move(Err);
return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs,
- ToType, E->getValueKind(), ToRParenLoc);
+ ToType, E->getValueKind(), ToRParenLoc,
+ E->getFPFeatures());
}
ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
@@ -7648,8 +7649,8 @@ ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) {
}
return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType,
- E->getValueKind(), ToRParenLoc, /*MinNumArgs=*/0,
- E->getADLCallKind());
+ E->getValueKind(), ToRParenLoc, E->getFPFeatures(),
+ /*MinNumArgs=*/0, E->getADLCallKind());
}
ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) {
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 213a6d1d1caa..29f96674e174 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1303,8 +1303,8 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation RParenLoc, unsigned MinNumArgs,
- ADLCallKind UsesADL)
+ SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
+ unsigned MinNumArgs, ADLCallKind UsesADL)
: Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) {
NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
unsigned NumPreArgs = PreArgs.size();
@@ -1327,10 +1327,14 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
setArg(I, nullptr);
setDependence(computeDependence(this, PreArgs));
+
+ CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+ if (hasStoredFPFeatures())
+ setStoredFPFeatures(FPFeatures);
}
CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
- EmptyShell Empty)
+ bool HasFPFeatures, EmptyShell Empty)
: Expr(SC, Empty), NumArgs(NumArgs) {
CallExprBits.NumPreArgs = NumPreArgs;
assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
@@ -1339,19 +1343,21 @@ CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects;
assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) &&
"OffsetToTrailingObjects overflow!");
+ CallExprBits.HasFPFeatures = HasFPFeatures;
}
CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation RParenLoc, unsigned MinNumArgs,
+ SourceLocation RParenLoc,
+ FPOptionsOverride FPFeatures, unsigned MinNumArgs,
ADLCallKind UsesADL) {
unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
- unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
+ /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
void *Mem =
Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr));
return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
- RParenLoc, MinNumArgs, UsesADL);
+ RParenLoc, FPFeatures, MinNumArgs, UsesADL);
}
CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
@@ -1360,17 +1366,18 @@ CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
assert(!(reinterpret_cast<uintptr_t>(Mem) % alignof(CallExpr)) &&
"Misaligned memory in CallExpr::CreateTemporary!");
return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty,
- VK, RParenLoc,
+ VK, RParenLoc, FPOptionsOverride(),
/*MinNumArgs=*/0, UsesADL);
}
CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
- EmptyShell Empty) {
+ bool HasFPFeatures, EmptyShell Empty) {
unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPFeatures);
void *Mem =
Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr));
- return new (Mem) CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, Empty);
+ return new (Mem)
+ CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, HasFPFeatures, Empty);
}
unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) {
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 5d99f61c579f..3d61496f30e2 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -528,17 +528,18 @@ CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind,
FPOptionsOverride FPFeatures,
ADLCallKind UsesADL)
: CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
- OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
+ OperatorLoc, FPFeatures, /*MinNumArgs=*/0, UsesADL) {
CXXOperatorCallExprBits.OperatorKind = OpKind;
assert(
(CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) &&
"OperatorKind overflow!");
Range = getSourceRangeImpl();
- Overrides = FPFeatures;
}
-CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty)
- : CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures,
+ EmptyShell Empty)
+ : CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs,
+ HasFPFeatures, Empty) {}
CXXOperatorCallExpr *
CXXOperatorCallExpr::Create(const ASTContext &Ctx,
@@ -548,8 +549,8 @@ CXXOperatorCallExpr::Create(const ASTContext &Ctx,
FPOptionsOverride FPFeatures, ADLCallKind UsesADL) {
// Allocate storage for the trailing objects of CallExpr.
unsigned NumArgs = Args.size();
- unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
+ /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
alignof(CXXOperatorCallExpr));
return new (Mem) CXXOperatorCallExpr(OpKind, Fn, Args, Ty, VK, OperatorLoc,
@@ -558,13 +559,14 @@ CXXOperatorCallExpr::Create(const ASTContext &Ctx,
CXXOperatorCallExpr *CXXOperatorCallExpr::CreateEmpty(const ASTContext &Ctx,
unsigned NumArgs,
+ bool HasFPFeatures,
EmptyShell Empty) {
// Allocate storage for the trailing objects of CallExpr.
unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPFeatures);
void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
alignof(CXXOperatorCallExpr));
- return new (Mem) CXXOperatorCallExpr(NumArgs, Empty);
+ return new (Mem) CXXOperatorCallExpr(NumArgs, HasFPFeatures, Empty);
}
SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
@@ -593,36 +595,43 @@ SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
CXXMemberCallExpr::CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args,
QualType Ty, ExprValueKind VK,
- SourceLocation RP, unsigned MinNumArgs)
+ SourceLocation RP,
+ FPOptionsOverride FPOptions,
+ unsigned MinNumArgs)
: CallExpr(CXXMemberCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, RP,
- MinNumArgs, NotADL) {}
+ FPOptions, MinNumArgs, NotADL) {}
-CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty)
- : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures,
+ EmptyShell Empty)
+ : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, HasFPFeatures,
+ Empty) {}
CXXMemberCallExpr *CXXMemberCallExpr::Create(const ASTContext &Ctx, Expr *Fn,
ArrayRef<Expr *> Args, QualType Ty,
ExprValueKind VK,
SourceLocation RP,
+ FPOptionsOverride FPFeatures,
unsigned MinNumArgs) {
// Allocate storage for the trailing objects of CallExpr.
unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
- unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
+ /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
alignof(CXXMemberCallExpr));
- return new (Mem) CXXMemberCallExpr(Fn, Args, Ty, VK, RP, MinNumArgs);
+ return new (Mem)
+ CXXMemberCallExpr(Fn, Args, Ty, VK, RP, FPFeatures, MinNumArgs);
}
CXXMemberCallExpr *CXXMemberCallExpr::CreateEmpty(const ASTContext &Ctx,
unsigned NumArgs,
+ bool HasFPFeatures,
EmptyShell Empty) {
// Allocate storage for the trailing objects of CallExpr.
unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPFeatures);
void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
alignof(CXXMemberCallExpr));
- return new (Mem) CXXMemberCallExpr(NumArgs, Empty);
+ return new (Mem) CXXMemberCallExpr(NumArgs, HasFPFeatures, Empty);
}
Expr *CXXMemberCallExpr::getImplicitObjectArgument() const {
@@ -846,37 +855,43 @@ SourceLocation CXXFunctionalCastExpr::getEndLoc() const {
UserDefinedLiteral::UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args,
QualType Ty, ExprValueKind VK,
SourceLocation LitEndLoc,
- SourceLocation SuffixLoc)
+ SourceLocation SuffixLoc,
+ FPOptionsOverride FPFeatures)
: CallExpr(UserDefinedLiteralClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
- LitEndLoc, /*MinNumArgs=*/0, NotADL),
+ LitEndLoc, FPFeatures, /*MinNumArgs=*/0, NotADL),
UDSuffixLoc(SuffixLoc) {}
-UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty)
- : CallExpr(UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures,
+ EmptyShell Empty)
+ : CallExpr(UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs,
+ HasFPFeatures, Empty) {}
UserDefinedLiteral *UserDefinedLiteral::Create(const ASTContext &Ctx, Expr *Fn,
ArrayRef<Expr *> Args,
QualType Ty, ExprValueKind VK,
SourceLocation LitEndLoc,
- SourceLocation SuffixLoc) {
+ SourceLocation SuffixLoc,
+ FPOptionsOverride FPFeatures) {
// Allocate storage for the trailing objects of CallExpr.
unsigned NumArgs = Args.size();
- unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
+ /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
alignof(UserDefinedLiteral));
- return new (Mem) UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc);
+ return new (Mem)
+ UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc, FPFeatures);
}
UserDefinedLiteral *UserDefinedLiteral::CreateEmpty(const ASTContext &Ctx,
unsigned NumArgs,
+ bool HasFPOptions,
EmptyShell Empty) {
// Allocate storage for the trailing objects of CallExpr.
unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
+ CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPOptions);
void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
alignof(UserDefinedLiteral));
- return new (Mem) UserDefinedLiteral(NumArgs, Empty);
+ return new (Mem) UserDefinedLiteral(NumArgs, HasFPOptions, Empty);
}
UserDefinedLiteral::LiteralOperatorKind
@@ -1643,34 +1658,39 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config,
ArrayRef<Expr *> Args, QualType Ty,
ExprValueKind VK, SourceLocation RP,
+ FPOptionsOverride FPFeatures,
unsigned MinNumArgs)
: CallExpr(CUDAKernelCallExprClass, Fn, /*PreArgs=*/Config, Args, Ty, VK,
- RP, MinNumArgs, NotADL) {}
+ RP, FPFeatures, MinNumArgs, NotADL) {}
-CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty)
+CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures,
+ EmptyShell Empty)
: CallExpr(CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs,
- Empty) {}
+ HasFPFeatures, Empty) {}
CUDAKernelCallExpr *
CUDAKernelCallExpr::Create(const ASTContext &Ctx, Expr *Fn, CallExpr *Config,
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
- SourceLocation RP, unsigned MinNumArgs) {
+ SourceLocation RP, FPOptionsOverride FPFeatures,
+ unsigned MinNumArgs) {
// Allocate storage for the trailing objects of CallExpr.
unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
- unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs);
+ unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
+ /*NumPreArgs=*/END_PREARG, NumArgs, FPFeatures.requiresTrailingStorage());
void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
alignof(CUDAKernelCallExpr));
- return new (Mem) CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, MinNumArgs);
+ return new (Mem)
+ CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, FPFeatures, MinNumArgs);
}
CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx,
unsigned NumArgs,
+ bool HasFPFeatures,
EmptyShell Empty) {
// Allocate storage for the trailing objects of CallExpr.
- unsigned SizeOfTrailingObjects =
- CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs);
+ unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
+ /*NumPreArgs=*/END_PREARG, NumArgs, HasFPFeatures);
void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
alignof(CUDAKernelCallExpr));
- return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
+ return new (Mem) CUDAKernelCallExpr(NumArgs, HasFPFeatures, Empty);
}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 5b0a0ac392c0..91b984820cd2 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -710,6 +710,13 @@ const char *TextNodeDumper::getCommandName(unsigned CommandID) {
return "<not a builtin command>";
}
+void TextNodeDumper::printFPOptions(FPOptionsOverride FPO) {
+#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
+ if (FPO.has##NAME##Override()) \
+ OS << " " #NAME "=" << FPO.get##NAME##Override();
+#include "clang/Basic/FPOptions.def"
+}
+
void TextNodeDumper::visitTextComment(const comments::TextComment *C,
const comments::FullComment *) {
OS << " Text=\"" << C->getText() << "\"";
@@ -937,6 +944,8 @@ void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) {
void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
if (Node->usesADL())
OS << " adl";
+ if (Node->hasStoredFPFeatures())
+ printFPOptions(Node->getFPFeatures());
}
void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) {
@@ -1053,6 +1062,8 @@ void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
<< UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
if (!Node->canOverflow())
OS << " cannot overflow";
+ if (Node->hasStoredFPFeatures())
+ printFPOptions(Node->getStoredFPFeatures());
}
void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
@@ -1081,6 +1092,8 @@ void TextNodeDumper::VisitExtVectorElementExpr(
void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) {
OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
+ if (Node->hasStoredFPFeatures())
+ printFPOptions(Node->getStoredFPFeatures());
}
void TextNodeDumper::VisitCompoundAssignOperator(
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index f9f0553d28f0..ad2dc8ec7a60 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -267,7 +267,7 @@ static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
}
return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue,
- SourceLocation());
+ SourceLocation(), FPOptionsOverride());
}
static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
@@ -514,7 +514,7 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
/*Args=*/None,
/*QualType=*/C.VoidTy,
/*ExprValueType=*/VK_RValue,
- /*SourceLocation=*/SourceLocation());
+ /*SourceLocation=*/SourceLocation(), FPOptionsOverride());
// (2) Create the assignment to the predicate.
Expr *DoneValue =
@@ -578,8 +578,8 @@ static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
ASTMaker M(C);
DeclRefExpr *DR = M.makeDeclRefExpr(PV);
ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
- CallExpr *CE =
- CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue, SourceLocation());
+ CallExpr *CE = CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue,
+ SourceLocation(), FPOptionsOverride());
return CE;
}
diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index e122b10e76d3..8c41e71ef018 100644
--- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -2109,8 +2109,9 @@ RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
DRE, nullptr, VK_RValue);
const auto *FT = msgSendType->castAs<FunctionType>();
- CallExpr *Exp = CallExpr::Create(
- *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc);
+ CallExpr *Exp =
+ CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
+ VK_RValue, EndLoc, FPOptionsOverride());
return Exp;
}
@@ -2692,7 +2693,7 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
auto *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc);
+ VK_RValue, EndLoc, FPOptionsOverride());
ReplaceStmt(Exp, CE);
return CE;
}
@@ -2732,7 +2733,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
InitExprs.push_back(Exp->getElement(i));
Expr *NSArrayCallExpr =
CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue,
- SourceLocation());
+ SourceLocation(), FPOptionsOverride());
FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -2813,7 +2814,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
const FunctionType *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc);
+ VK_RValue, EndLoc, FPOptionsOverride());
ReplaceStmt(Exp, CE);
return CE;
}
@@ -2861,7 +2862,7 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
// (const id [])objects
Expr *NSValueCallExpr =
CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue,
- SourceLocation());
+ SourceLocation(), FPOptionsOverride());
FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -2879,8 +2880,9 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
CK_BitCast,
DictLiteralValueME);
// (const id <NSCopying> [])keys
- Expr *NSKeyCallExpr = CallExpr::Create(
- *Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation());
+ Expr *NSKeyCallExpr =
+ CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue,
+ SourceLocation(), FPOptionsOverride());
MemberExpr *DictLiteralKeyME =
MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD,
@@ -2964,7 +2966,7 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
const FunctionType *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc);
+ VK_RValue, EndLoc, FPOptionsOverride());
ReplaceStmt(Exp, CE);
return CE;
}
@@ -3175,8 +3177,9 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla
ID, FuncType, nullptr, SC_Extern, false, false);
DeclRefExpr *DRE = new (Context)
DeclRefExpr(*Context, FD, false, castType, VK_RValue, SourceLocation());
- CallExpr *STCE = CallExpr::Create(*Context, DRE, MsgExprs, castType,
- VK_LValue, SourceLocation());
+ CallExpr *STCE =
+ CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue,
+ SourceLocation(), FPOptionsOverride());
FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -3276,8 +3279,9 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
DeclRefExpr *DRE = new (Context)
DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
VK_LValue, SourceLocation());
- SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
- VK_LValue, SourceLocation());
+ SuperRep =
+ CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
+ SourceLocation(), FPOptionsOverride());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -3371,8 +3375,9 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
DeclRefExpr *DRE = new (Context)
DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
VK_LValue, SourceLocation());
- SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
- VK_LValue, SourceLocation());
+ SuperRep =
+ CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
+ SourceLocation(), FPOptionsOverride());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -3537,7 +3542,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
const FunctionType *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc);
+ VK_RValue, EndLoc, FPOptionsOverride());
Stmt *ReplacingStmt = CE;
if (MsgSendStretFlavor) {
// We have the method which returns a struct/union. Must also generate
@@ -4647,8 +4652,9 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp
E = Exp->arg_end(); I != E; ++I) {
BlkExprs.push_back(*I);
}
- CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(),
- VK_RValue, SourceLocation());
+ CallExpr *CE =
+ CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_RValue,
+ SourceLocation(), FPOptionsOverride());
return CE;
}
@@ -5391,7 +5397,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
InitExprs.push_back(FlagExp);
}
NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
- SourceLocation());
+ SourceLocation(), FPOptionsOverride());
if (GlobalBlockExpr) {
assert (!GlobalConstructionExp &&
diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 3f320dc57aa6..4ecd6e95de10 100644
--- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -2027,8 +2027,9 @@ RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
const auto *FT = msgSendType->castAs<FunctionType>();
- CallExpr *Exp = CallExpr::Create(
- *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc);
+ CallExpr *Exp =
+ CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
+ VK_RValue, EndLoc, FPOptionsOverride());
return Exp;
}
@@ -2614,8 +2615,9 @@ CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavo
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
const auto *FT = msgSendType->castAs<FunctionType>();
- CallExpr *STCE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, SourceLocation());
+ CallExpr *STCE =
+ CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue,
+ SourceLocation(), FPOptionsOverride());
return STCE;
}
@@ -2707,8 +2709,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
DeclRefExpr *DRE = new (Context)
DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
VK_LValue, SourceLocation());
- SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
- VK_LValue, SourceLocation());
+ SuperRep =
+ CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
+ SourceLocation(), FPOptionsOverride());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -2802,8 +2805,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
DeclRefExpr *DRE = new (Context)
DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
VK_LValue, SourceLocation());
- SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType,
- VK_LValue, SourceLocation());
+ SuperRep =
+ CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
+ SourceLocation(), FPOptionsOverride());
// The code for super is a little tricky to prevent collision with
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
@@ -2968,7 +2972,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
const auto *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc);
+ VK_RValue, EndLoc, FPOptionsOverride());
Stmt *ReplacingStmt = CE;
if (MsgSendStretFlavor) {
// We have the method which returns a struct/union. Must also generate
@@ -3817,8 +3821,9 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
E = Exp->arg_end(); I != E; ++I) {
BlkExprs.push_back(*I);
}
- CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(),
- VK_RValue, SourceLocation());
+ CallExpr *CE =
+ CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_RValue,
+ SourceLocation(), FPOptionsOverride());
return CE;
}
@@ -4530,7 +4535,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
InitExprs.push_back(FlagExp);
}
NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
- SourceLocation());
+ SourceLocation(), FPOptionsOverride());
NewRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ad44302cea45..bb5a07e8079d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6322,7 +6322,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
}
return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy,
- VK_RValue, RParenLoc);
+ VK_RValue, RParenLoc, CurFPFeatureOverrides());
}
if (Fn->getType() == Context.PseudoObjectTy) {
ExprResult result = CheckPlaceholderExpr(Fn);
@@ -6336,7 +6336,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (ExecConfig) {
return CUDAKernelCallExpr::Create(
Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs,
- Context.DependentTy, VK_RValue, RParenLoc);
+ Context.DependentTy, VK_RValue, RParenLoc, CurFPFeatureOverrides());
} else {
tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
@@ -6344,7 +6344,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
Fn->getBeginLoc());
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
- VK_RValue, RParenLoc);
+ VK_RValue, RParenLoc, CurFPFeatureOverrides());
}
}
@@ -6373,7 +6373,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (!find.HasFormOfMemberPointer) {
if (Expr::hasAnyTypeDependentArguments(ArgExprs))
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
- VK_RValue, RParenLoc);
+ VK_RValue, RParenLoc, CurFPFeatureOverrides());
OverloadExpr *ovl = find.Expression;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
return BuildOverloadedCallExpr(
@@ -6564,12 +6564,13 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (Config) {
assert(UsesADL == ADLCallKind::NotADL &&
"CUDAKernelCallExpr should not use ADL");
- TheCall =
- CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), Args,
- ResultTy, VK_RValue, RParenLoc, NumParams);
+ TheCall = CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config),
+ Args, ResultTy, VK_RValue, RParenLoc,
+ CurFPFeatureOverrides(), NumParams);
} else {
- TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
- RParenLoc, NumParams, UsesADL);
+ TheCall =
+ CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc,
+ CurFPFeatureOverrides(), NumParams, UsesADL);
}
if (!getLangOpts().CPlusPlus) {
@@ -6596,10 +6597,11 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (Config)
TheCall = CUDAKernelCallExpr::Create(
Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_RValue,
- RParenLoc, NumParams);
+ RParenLoc, CurFPFeatureOverrides(), NumParams);
else
- TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
- RParenLoc, NumParams, UsesADL);
+ TheCall =
+ CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc,
+ CurFPFeatureOverrides(), NumParams, UsesADL);
}
// We can now handle the nulled arguments for the default arguments.
TheCall->setNumArgsUnsafe(std::max<unsigned>(Args.size(), NumParams));
@@ -19086,7 +19088,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
CK_BuiltinFnToFnPtr)
.get();
return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy,
- VK_RValue, SourceLocation());
+ VK_RValue, SourceLocation(),
+ FPOptionsOverride());
}
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 3d5cd965980d..fe5ba6a5e87f 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -7619,7 +7619,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
ResultType = ResultType.getNonLValueExprType(Context);
CXXMemberCallExpr *CE = CXXMemberCallExpr::Create(
- Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc());
+ Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc(),
+ CurFPFeatureOverrides());
if (CheckFunctionCall(Method, CE,
Method->getType()->castAs<FunctionProtoType>()))
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 987d88ce18cb..51609e37e20c 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -15321,7 +15321,8 @@ static bool actOnOMPReductionKindClause(
S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
Expr *Args[] = {LHS.get(), RHS.get()};
ReductionOp =
- CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc);
+ CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc,
+ S.CurFPFeatureOverrides());
} else {
ReductionOp = S.BuildBinOp(
Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE);
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 7c6acf011d57..5b4e7a2fdafa 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12797,8 +12797,9 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// then create a type dependent CallExpr. The goal is to postpone name
// lookup to instantiation time to be able to search into type dependent
// base classes.
- CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy,
- VK_RValue, RParenLoc);
+ CallExpr *CE =
+ CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_RValue,
+ RParenLoc, CurFPFeatureOverrides());
CE->markDependentForPostponedNameLookup();
*Result = CE;
return true;
@@ -13978,9 +13979,9 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
- CXXMemberCallExpr *call =
- CXXMemberCallExpr::Create(Context, MemExprE, Args, resultType,
- valueKind, RParenLoc, proto->getNumParams());
+ CXXMemberCallExpr *call = CXXMemberCallExpr::Create(
+ Context, MemExprE, Args, resultType, valueKind, RParenLoc,
+ CurFPFeatureOverrides(), proto->getNumParams());
if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(),
call, nullptr))
@@ -13997,7 +13998,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (isa<CXXPseudoDestructorExpr>(NakedMemExpr))
return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue,
- RParenLoc);
+ RParenLoc, CurFPFeatureOverrides());
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
@@ -14135,9 +14136,9 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
assert(Method && "Member call to something that isn't a method?");
const auto *Proto = Method->getType()->castAs<FunctionProtoType>();
- CXXMemberCallExpr *TheCall =
- CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK,
- RParenLoc, Proto->getNumParams());
+ CXXMemberCallExpr *TheCall = CXXMemberCallExpr::Create(
+ Context, MemExprE, Args, ResultType, VK, RParenLoc,
+ CurFPFeatureOverrides(), Proto->getNumParams());
// Check for a valid return type.
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
@@ -14680,7 +14681,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
UserDefinedLiteral *UDL = UserDefinedLiteral::Create(
Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy,
- VK, LitEndLoc, UDSuffixLoc);
+ VK, LitEndLoc, UDSuffixLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index ae0e9f1119b4..0f83431c94cf 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3500,7 +3500,8 @@ class TreeTransform {
// Build the CallExpr
ExprResult TheCall = CallExpr::Create(
SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(),
- Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc);
+ Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc,
+ FPOptionsOverride());
// Type-check the __builtin_shufflevector expression.
return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.get()));
@@ -10466,6 +10467,15 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
// FIXME: Wrong source location information for the '('.
SourceLocation FakeLParenLoc
= ((Expr *)Callee.get())->getSourceRange().getBegin();
+
+ Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
+ if (E->hasStoredFPFeatures()) {
+ FPOptionsOverride NewOverrides = E->getFPFeatures();
+ getSema().CurFPFeatures =
+ NewOverrides.applyOverrides(getSema().getLangOpts());
+ getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
+ }
+
return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc,
Args,
E->getRParenLoc());
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index a40c5499a6d7..8a7beed229c8 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -991,12 +991,15 @@ void ASTStmtReader::VisitOMPIteratorExpr(OMPIteratorExpr *E) {
void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
unsigned NumArgs = Record.readInt();
+ bool HasFPFeatures = Record.readInt();
assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!");
E->setRParenLoc(readSourceLocation());
E->setCallee(Record.readSubExpr());
for (unsigned I = 0; I != NumArgs; ++I)
E->setArg(I, Record.readSubExpr());
E->setADLCallKind(static_cast<CallExpr::ADLCallKind>(Record.readInt()));
+ if (HasFPFeatures)
+ E->setStoredFPFeatures(FPOptionsOverride(Record.readInt()));
}
void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
@@ -1662,7 +1665,6 @@ void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
E->CXXOperatorCallExprBits.OperatorKind = Record.readInt();
E->Range = Record.readSourceRange();
- E->setFPFeatures(FPOptionsOverride(Record.readInt()));
}
void ASTStmtReader::VisitCXXRewrittenBinaryOperator(
@@ -2977,7 +2979,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CALL:
S = CallExpr::CreateEmpty(
- Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty);
break;
case EXPR_RECOVERY:
@@ -3585,12 +3588,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_OPERATOR_CALL:
S = CXXOperatorCallExpr::CreateEmpty(
- Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty);
break;
case EXPR_CXX_MEMBER_CALL:
S = CXXMemberCallExpr::CreateEmpty(
- Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty);
break;
case EXPR_CXX_REWRITTEN_BINARY_OPERATOR:
@@ -3648,7 +3653,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_USER_DEFINED_LITERAL:
S = UserDefinedLiteral::CreateEmpty(
- Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty);
break;
case EXPR_CXX_STD_INITIALIZER_LIST:
@@ -3831,7 +3837,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CUDA_KERNEL_CALL:
S = CUDAKernelCallExpr::CreateEmpty(
- Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
+ /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty);
break;
case EXPR_ASTYPE:
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 0767b3a24bf2..d2e5d6e44d78 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -848,12 +848,15 @@ void ASTStmtWriter::VisitOMPIteratorExpr(OMPIteratorExpr *E) {
void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
+ Record.push_back(E->hasStoredFPFeatures());
Record.AddSourceLocation(E->getRParenLoc());
Record.AddStmt(E->getCallee());
for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
Arg != ArgEnd; ++Arg)
Record.AddStmt(*Arg);
Record.push_back(static_cast<unsigned>(E->getADLCallKind()));
+ if (E->hasStoredFPFeatures())
+ Record.push_back(E->getFPFeatures().getAsOpaqueInt());
Code = serialization::EXPR_CALL;
}
@@ -1550,7 +1553,6 @@ void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
Record.push_back(E->getOperator());
Record.AddSourceRange(E->Range);
- Record.push_back(E->getFPFeatures().getAsOpaqueInt());
Code = serialization::EXPR_CXX_OPERATOR_CALL;
}
diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp b/clang/test/AST/ast-dump-fpfeatures.cpp
new file mode 100644
index 000000000000..796b0a028382
--- /dev/null
+++ b/clang/test/AST/ast-dump-fpfeatures.cpp
@@ -0,0 +1,37 @@
+// Test without serialization:
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -ast-dump %s \
+// RUN: | FileCheck --strict-whitespace %s
+
+// Test with serialization:
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
+// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \
+// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
+// RUN: | FileCheck --strict-whitespace %s
+
+float func_01(float x);
+
+template <typename T>
+T func_02(T x) {
+#pragma STDC FP_CONTRACT ON
+ return func_01(x);
+}
+
+float func_03(float x) {
+#pragma STDC FP_CONTRACT OFF
+ return func_02(x);
+}
+
+// CHECK: FunctionTemplateDecl {{.*}} func_02
+// CHECK: FunctionDecl {{.*}} func_02 'float (float)'
+// CHECK-NEXT: TemplateArgument type 'float'
+// CHECK-NEXT: BuiltinType {{.*}} 'float'
+// CHECK-NEXT: ParmVarDecl {{.*}} x 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CallExpr {{.*}} FPContractMode=1
+
+// CHECK: FunctionDecl {{.*}} func_03 'float (float)'
+// CHECK-NEXT: ParmVarDecl {{.*}} x 'float'
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: ReturnStmt
+// CHECK-NEXT: CallExpr {{.*}} FPContractMode=0
\ No newline at end of file
More information about the cfe-commits
mailing list