forked from OSchip/llvm-project
Revert "Revert "Modify FPFeatures to use delta not absolute settings""
This reverts commit b55d723ed6
.
Reapply Modify FPFeatures to use delta not absolute settings
To solve https://bugs.llvm.org/show_bug.cgi?id=46166 where the
floating point settings in PCH files aren't compatible, rewrite
FPFeatures to use a delta in the settings rather than absolute settings.
With this patch, these floating point options can be benign.
Reviewers: rjmccall
Differential Revision: https://reviews.llvm.org/D81869
This commit is contained in:
parent
e086a39c11
commit
9518763d71
|
@ -2118,21 +2118,21 @@ public:
|
|||
///
|
||||
class UnaryOperator final
|
||||
: public Expr,
|
||||
private llvm::TrailingObjects<UnaryOperator, FPOptions> {
|
||||
private llvm::TrailingObjects<UnaryOperator, FPOptionsOverride> {
|
||||
Stmt *Val;
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<FPOptions>) const {
|
||||
size_t numTrailingObjects(OverloadToken<FPOptionsOverride>) const {
|
||||
return UnaryOperatorBits.HasFPFeatures ? 1 : 0;
|
||||
}
|
||||
|
||||
FPOptions &getTrailingFPFeatures() {
|
||||
FPOptionsOverride &getTrailingFPFeatures() {
|
||||
assert(UnaryOperatorBits.HasFPFeatures);
|
||||
return *getTrailingObjects<FPOptions>();
|
||||
return *getTrailingObjects<FPOptionsOverride>();
|
||||
}
|
||||
|
||||
const FPOptions &getTrailingFPFeatures() const {
|
||||
const FPOptionsOverride &getTrailingFPFeatures() const {
|
||||
assert(UnaryOperatorBits.HasFPFeatures);
|
||||
return *getTrailingObjects<FPOptions>();
|
||||
return *getTrailingObjects<FPOptionsOverride>();
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -2141,7 +2141,7 @@ public:
|
|||
protected:
|
||||
UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc, QualType type,
|
||||
ExprValueKind VK, ExprObjectKind OK, SourceLocation l,
|
||||
bool CanOverflow, FPOptions FPFeatures);
|
||||
bool CanOverflow, FPOptionsOverride FPFeatures);
|
||||
|
||||
/// Build an empty unary operator.
|
||||
explicit UnaryOperator(bool HasFPFeatures, EmptyShell Empty)
|
||||
|
@ -2156,7 +2156,7 @@ public:
|
|||
static UnaryOperator *Create(const ASTContext &C, Expr *input, Opcode opc,
|
||||
QualType type, ExprValueKind VK,
|
||||
ExprObjectKind OK, SourceLocation l,
|
||||
bool CanOverflow, FPOptions FPFeatures);
|
||||
bool CanOverflow, FPOptionsOverride FPFeatures);
|
||||
|
||||
Opcode getOpcode() const {
|
||||
return static_cast<Opcode>(UnaryOperatorBits.Opc);
|
||||
|
@ -2182,13 +2182,13 @@ public:
|
|||
// Get the FP contractability status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
bool isFPContractableWithinStatement(const LangOptions &LO) const {
|
||||
return getFPFeatures(LO).allowFPContractWithinStatement();
|
||||
return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
|
||||
}
|
||||
|
||||
// Get the FENV_ACCESS status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
bool isFEnvAccessOn(const LangOptions &LO) const {
|
||||
return getFPFeatures(LO).allowFEnvAccess();
|
||||
return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
|
||||
}
|
||||
|
||||
/// isPostfix - Return true if this is a postfix operation, like x++.
|
||||
|
@ -2263,18 +2263,25 @@ public:
|
|||
|
||||
protected:
|
||||
/// Get FPFeatures from trailing storage
|
||||
FPOptions getStoredFPFeatures() const { return getTrailingFPFeatures(); }
|
||||
FPOptionsOverride getStoredFPFeatures() const {
|
||||
return getTrailingFPFeatures();
|
||||
}
|
||||
|
||||
/// Set FPFeatures in trailing storage, used only by Serialization
|
||||
void setStoredFPFeatures(FPOptions F) { getTrailingFPFeatures() = F; }
|
||||
void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
|
||||
|
||||
public:
|
||||
// Get the FP features status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
FPOptions getFPFeatures(const LangOptions &LO) const {
|
||||
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
|
||||
if (UnaryOperatorBits.HasFPFeatures)
|
||||
return getStoredFPFeatures().applyOverrides(LO);
|
||||
return FPOptions::defaultWithoutTrailingStorage(LO);
|
||||
}
|
||||
FPOptionsOverride getFPOptionsOverride() const {
|
||||
if (UnaryOperatorBits.HasFPFeatures)
|
||||
return getStoredFPFeatures();
|
||||
return FPOptions::defaultWithoutTrailingStorage(LO);
|
||||
return FPOptionsOverride();
|
||||
}
|
||||
|
||||
friend TrailingObjects;
|
||||
|
@ -3633,14 +3640,14 @@ protected:
|
|||
size_t offsetOfTrailingStorage() const;
|
||||
|
||||
/// Return a pointer to the trailing FPOptions
|
||||
FPOptions *getTrailingFPFeatures() {
|
||||
FPOptionsOverride *getTrailingFPFeatures() {
|
||||
assert(BinaryOperatorBits.HasFPFeatures);
|
||||
return reinterpret_cast<FPOptions *>(reinterpret_cast<char *>(this) +
|
||||
offsetOfTrailingStorage());
|
||||
return reinterpret_cast<FPOptionsOverride *>(
|
||||
reinterpret_cast<char *>(this) + offsetOfTrailingStorage());
|
||||
}
|
||||
const FPOptions *getTrailingFPFeatures() const {
|
||||
const FPOptionsOverride *getTrailingFPFeatures() const {
|
||||
assert(BinaryOperatorBits.HasFPFeatures);
|
||||
return reinterpret_cast<const FPOptions *>(
|
||||
return reinterpret_cast<const FPOptionsOverride *>(
|
||||
reinterpret_cast<const char *>(this) + offsetOfTrailingStorage());
|
||||
}
|
||||
|
||||
|
@ -3648,7 +3655,7 @@ protected:
|
|||
/// allocated for the trailing objects when needed.
|
||||
BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
|
||||
QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation opLoc, FPOptions FPFeatures);
|
||||
SourceLocation opLoc, FPOptionsOverride FPFeatures);
|
||||
|
||||
/// Construct an empty binary operator.
|
||||
explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) {
|
||||
|
@ -3661,7 +3668,7 @@ public:
|
|||
static BinaryOperator *Create(const ASTContext &C, Expr *lhs, Expr *rhs,
|
||||
Opcode opc, QualType ResTy, ExprValueKind VK,
|
||||
ExprObjectKind OK, SourceLocation opLoc,
|
||||
FPOptions FPFeatures);
|
||||
FPOptionsOverride FPFeatures);
|
||||
SourceLocation getExprLoc() const { return getOperatorLoc(); }
|
||||
SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; }
|
||||
void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; }
|
||||
|
@ -3808,40 +3815,48 @@ public:
|
|||
bool hasStoredFPFeatures() const { return BinaryOperatorBits.HasFPFeatures; }
|
||||
|
||||
/// Get FPFeatures from trailing storage
|
||||
FPOptions getStoredFPFeatures() const {
|
||||
FPOptionsOverride getStoredFPFeatures() const {
|
||||
assert(hasStoredFPFeatures());
|
||||
return *getTrailingFPFeatures();
|
||||
}
|
||||
/// Set FPFeatures in trailing storage, used only by Serialization
|
||||
void setStoredFPFeatures(FPOptions F) {
|
||||
void setStoredFPFeatures(FPOptionsOverride F) {
|
||||
assert(BinaryOperatorBits.HasFPFeatures);
|
||||
*getTrailingFPFeatures() = F;
|
||||
}
|
||||
|
||||
// Get the FP features status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
FPOptions getFPFeatures(const LangOptions &LO) const {
|
||||
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
|
||||
if (BinaryOperatorBits.HasFPFeatures)
|
||||
return getStoredFPFeatures().applyOverrides(LO);
|
||||
return FPOptions::defaultWithoutTrailingStorage(LO);
|
||||
}
|
||||
|
||||
// This is used in ASTImporter
|
||||
FPOptionsOverride getFPFeatures(const LangOptions &LO) const {
|
||||
if (BinaryOperatorBits.HasFPFeatures)
|
||||
return getStoredFPFeatures();
|
||||
return FPOptions::defaultWithoutTrailingStorage(LO);
|
||||
return FPOptionsOverride();
|
||||
}
|
||||
|
||||
// Get the FP contractability status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
bool isFPContractableWithinStatement(const LangOptions &LO) const {
|
||||
return getFPFeatures(LO).allowFPContractWithinStatement();
|
||||
return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
|
||||
}
|
||||
|
||||
// Get the FENV_ACCESS status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
bool isFEnvAccessOn(const LangOptions &LO) const {
|
||||
return getFPFeatures(LO).allowFEnvAccess();
|
||||
return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
|
||||
}
|
||||
|
||||
protected:
|
||||
BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
|
||||
QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation opLoc, FPOptions FPFeatures, bool dead2);
|
||||
SourceLocation opLoc, FPOptionsOverride FPFeatures,
|
||||
bool dead2);
|
||||
|
||||
/// Construct an empty BinaryOperator, SC is CompoundAssignOperator.
|
||||
BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
|
||||
|
@ -3851,7 +3866,7 @@ protected:
|
|||
/// Return the size in bytes needed for the trailing objects.
|
||||
/// Used to allocate the right amount of storage.
|
||||
static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
|
||||
return HasFPFeatures * sizeof(FPOptions);
|
||||
return HasFPFeatures * sizeof(FPOptionsOverride);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3873,7 +3888,7 @@ class CompoundAssignOperator : public BinaryOperator {
|
|||
protected:
|
||||
CompoundAssignOperator(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc,
|
||||
QualType ResType, ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation OpLoc, FPOptions FPFeatures,
|
||||
SourceLocation OpLoc, FPOptionsOverride FPFeatures,
|
||||
QualType CompLHSType, QualType CompResultType)
|
||||
: BinaryOperator(C, lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures,
|
||||
true),
|
||||
|
@ -3889,7 +3904,7 @@ public:
|
|||
static CompoundAssignOperator *
|
||||
Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
|
||||
ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc,
|
||||
FPOptions FPFeatures, QualType CompLHSType = QualType(),
|
||||
FPOptionsOverride FPFeatures, QualType CompLHSType = QualType(),
|
||||
QualType CompResultType = QualType());
|
||||
|
||||
// The two computation types are the type the LHS is converted
|
||||
|
|
|
@ -84,6 +84,7 @@ 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.
|
||||
|
@ -92,7 +93,7 @@ class CXXOperatorCallExpr final : public CallExpr {
|
|||
|
||||
CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn,
|
||||
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
|
||||
SourceLocation OperatorLoc, FPOptions FPFeatures,
|
||||
SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
|
||||
ADLCallKind UsesADL);
|
||||
|
||||
CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty);
|
||||
|
@ -101,7 +102,7 @@ public:
|
|||
static CXXOperatorCallExpr *
|
||||
Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
|
||||
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
|
||||
SourceLocation OperatorLoc, FPOptions FPFeatures,
|
||||
SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
|
||||
ADLCallKind UsesADL = NotADL);
|
||||
|
||||
static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx,
|
||||
|
@ -164,20 +165,10 @@ public:
|
|||
return T->getStmtClass() == CXXOperatorCallExprClass;
|
||||
}
|
||||
|
||||
// Set the FP contractability status of this operator. Only meaningful for
|
||||
// Set the FPFeatures status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
void setFPFeatures(FPOptions F) {
|
||||
CXXOperatorCallExprBits.FPFeatures = F.getAsOpaqueInt();
|
||||
}
|
||||
FPOptions getFPFeatures() const {
|
||||
return FPOptions(CXXOperatorCallExprBits.FPFeatures);
|
||||
}
|
||||
|
||||
// Get the FP contractability status of this operator. Only meaningful for
|
||||
// operations on floating point types.
|
||||
bool isFPContractableWithinStatement() const {
|
||||
return getFPFeatures().allowFPContractWithinStatement();
|
||||
}
|
||||
void setFPFeatures(FPOptionsOverride F) { Overrides = F; }
|
||||
FPOptionsOverride getFPFeatures() const { return Overrides; }
|
||||
};
|
||||
|
||||
/// Represents a call to a member function that
|
||||
|
|
|
@ -614,9 +614,6 @@ protected:
|
|||
/// The kind of this overloaded operator. One of the enumerator
|
||||
/// value of OverloadedOperatorKind.
|
||||
unsigned OperatorKind : 6;
|
||||
|
||||
// Only meaningful for floating point types.
|
||||
unsigned FPFeatures : 14;
|
||||
};
|
||||
|
||||
class CXXRewrittenBinaryOperatorBitfields {
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
//===--- FPOptions.def - Floating Point Options database --------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This file defines the Floating Point language options. Users of this file
|
||||
// must define the FPOPT macro to make use of this information.
|
||||
#ifndef OPTION
|
||||
# error Define the OPTION macro to handle floating point language options
|
||||
#endif
|
||||
|
||||
// OPTION(name, type, width, previousName)
|
||||
OPTION(FPContractMode, LangOptions::FPModeKind, 2, First)
|
||||
OPTION(RoundingMode, RoundingMode, 3, FPContractMode)
|
||||
OPTION(FPExceptionMode, LangOptions::FPExceptionModeKind, 2, RoundingMode)
|
||||
OPTION(AllowFEnvAccess, bool, 1, FPExceptionMode)
|
||||
OPTION(AllowFPReassociate, bool, 1, AllowFEnvAccess)
|
||||
OPTION(NoHonorNaNs, bool, 1, AllowFPReassociate)
|
||||
OPTION(NoHonorInfs, bool, 1, NoHonorNaNs)
|
||||
OPTION(NoSignedZero, bool, 1, NoHonorInfs)
|
||||
OPTION(AllowReciprocal, bool, 1, NoSignedZero)
|
||||
OPTION(AllowApproxFunc, bool, 1, AllowReciprocal)
|
||||
#undef OPTION
|
|
@ -193,12 +193,12 @@ COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro")
|
|||
COMPATIBLE_LANGOPT(FastMath , 1, 0, "fast FP math optimizations, and __FAST_MATH__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(UnsafeFPMath , 1, 0, "Unsafe Floating Point Math")
|
||||
COMPATIBLE_LANGOPT(AllowFPReassoc , 1, 0, "Permit Floating Point reassociation")
|
||||
COMPATIBLE_LANGOPT(NoHonorNaNs , 1, 0, "Permit Floating Point optimization without regard to NaN")
|
||||
COMPATIBLE_LANGOPT(NoHonorInfs , 1, 0, "Permit Floating Point optimization without regard to infinities")
|
||||
COMPATIBLE_LANGOPT(NoSignedZero , 1, 0, "Permit Floating Point optimization without regard to signed zeros")
|
||||
COMPATIBLE_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal")
|
||||
COMPATIBLE_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation")
|
||||
BENIGN_LANGOPT(AllowFPReassoc , 1, 0, "Permit Floating Point reassociation")
|
||||
BENIGN_LANGOPT(NoHonorNaNs , 1, 0, "Permit Floating Point optimization without regard to NaN")
|
||||
BENIGN_LANGOPT(NoHonorInfs , 1, 0, "Permit Floating Point optimization without regard to infinities")
|
||||
BENIGN_LANGOPT(NoSignedZero , 1, 0, "Permit Floating Point optimization without regard to signed zeros")
|
||||
BENIGN_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal")
|
||||
BENIGN_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation")
|
||||
|
||||
BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
|
||||
|
||||
|
@ -271,9 +271,9 @@ BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking")
|
|||
LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants")
|
||||
LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math")
|
||||
/// FP_CONTRACT mode (on/off/fast).
|
||||
ENUM_LANGOPT(DefaultFPContractMode, FPModeKind, 2, FPM_Off, "FP contraction type")
|
||||
ENUM_LANGOPT(FPRoundingMode, RoundingMode, 3, RoundingMode::NearestTiesToEven, "FP Rounding Mode type")
|
||||
ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP Exception Behavior Mode type")
|
||||
BENIGN_ENUM_LANGOPT(DefaultFPContractMode, FPModeKind, 2, FPM_Off, "FP contraction type")
|
||||
BENIGN_ENUM_LANGOPT(FPRoundingMode, RoundingMode, 3, RoundingMode::NearestTiesToEven, "FP Rounding Mode type")
|
||||
BENIGN_ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP Exception Behavior Mode type")
|
||||
LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
|
||||
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
|
||||
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
|
||||
|
|
|
@ -366,175 +366,175 @@ public:
|
|||
};
|
||||
|
||||
/// Floating point control options
|
||||
class FPOptionsOverride;
|
||||
class FPOptions {
|
||||
public:
|
||||
// We start by defining the layout.
|
||||
using storage_type = uint16_t;
|
||||
|
||||
using RoundingMode = llvm::RoundingMode;
|
||||
|
||||
public:
|
||||
FPOptions()
|
||||
: fp_contract(LangOptions::FPM_Off), fenv_access(LangOptions::FPM_Off),
|
||||
rounding(LangOptions::FPR_ToNearest),
|
||||
exceptions(LangOptions::FPE_Ignore), allow_reassoc(0), no_nans(0),
|
||||
no_infs(0), no_signed_zeros(0), allow_reciprocal(0), approx_func(0) {}
|
||||
// Define a fake option named "First" so that we have a PREVIOUS even for the
|
||||
// real first option.
|
||||
static constexpr storage_type FirstShift = 0, FirstWidth = 0;
|
||||
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
||||
static constexpr storage_type NAME##Shift = \
|
||||
PREVIOUS##Shift + PREVIOUS##Width; \
|
||||
static constexpr storage_type NAME##Width = WIDTH; \
|
||||
static constexpr storage_type NAME##Mask = ((1 << NAME##Width) - 1) \
|
||||
<< NAME##Shift;
|
||||
#include "clang/Basic/FPOptions.def"
|
||||
|
||||
private:
|
||||
storage_type Value;
|
||||
|
||||
public:
|
||||
FPOptions() : Value(0) {
|
||||
setFPContractMode(LangOptions::FPM_Off);
|
||||
setRoundingMode(static_cast<RoundingMode>(LangOptions::FPR_ToNearest));
|
||||
setFPExceptionMode(LangOptions::FPE_Ignore);
|
||||
}
|
||||
// Used for serializing.
|
||||
explicit FPOptions(unsigned I) { getFromOpaqueInt(I); }
|
||||
|
||||
explicit FPOptions(const LangOptions &LangOpts)
|
||||
: fp_contract(LangOpts.getDefaultFPContractMode()),
|
||||
fenv_access(LangOptions::FPM_Off),
|
||||
rounding(static_cast<unsigned>(LangOpts.getFPRoundingMode())),
|
||||
exceptions(LangOpts.getFPExceptionMode()),
|
||||
allow_reassoc(LangOpts.AllowFPReassoc), no_nans(LangOpts.NoHonorNaNs),
|
||||
no_infs(LangOpts.NoHonorInfs), no_signed_zeros(LangOpts.NoSignedZero),
|
||||
allow_reciprocal(LangOpts.AllowRecip),
|
||||
approx_func(LangOpts.ApproxFunc) {}
|
||||
// FIXME: Use getDefaultFEnvAccessMode() when available.
|
||||
|
||||
void setFastMath(bool B = true) {
|
||||
allow_reassoc = no_nans = no_infs = no_signed_zeros = approx_func =
|
||||
allow_reciprocal = B;
|
||||
explicit FPOptions(const LangOptions &LO) {
|
||||
setFPContractMode(LO.getDefaultFPContractMode());
|
||||
setRoundingMode(LO.getFPRoundingMode());
|
||||
setFPExceptionMode(LO.getFPExceptionMode());
|
||||
setAllowFEnvAccess(LangOptions::FPM_Off),
|
||||
setAllowFPReassociate(LO.AllowFPReassoc);
|
||||
setNoHonorNaNs(LO.NoHonorNaNs);
|
||||
setNoHonorInfs(LO.NoHonorInfs);
|
||||
setNoSignedZero(LO.NoSignedZero);
|
||||
setAllowReciprocal(LO.AllowRecip);
|
||||
setAllowApproxFunc(LO.ApproxFunc);
|
||||
}
|
||||
|
||||
bool allowFPContractWithinStatement() const {
|
||||
return getFPContractMode() == LangOptions::FPM_On;
|
||||
}
|
||||
void setAllowFPContractWithinStatement() {
|
||||
setFPContractMode(LangOptions::FPM_On);
|
||||
}
|
||||
|
||||
bool allowFPContractAcrossStatement() const {
|
||||
return getFPContractMode() == LangOptions::FPM_Fast;
|
||||
}
|
||||
void setAllowFPContractAcrossStatement() {
|
||||
setFPContractMode(LangOptions::FPM_Fast);
|
||||
}
|
||||
|
||||
bool isFPConstrained() const {
|
||||
return getRoundingMode() !=
|
||||
static_cast<unsigned>(RoundingMode::NearestTiesToEven) ||
|
||||
getFPExceptionMode() != LangOptions::FPE_Ignore ||
|
||||
getAllowFEnvAccess();
|
||||
}
|
||||
|
||||
bool operator==(FPOptions other) const { return Value == other.Value; }
|
||||
|
||||
/// Return the default value of FPOptions that's used when trailing
|
||||
/// storage isn't required.
|
||||
static FPOptions defaultWithoutTrailingStorage(const LangOptions &LO);
|
||||
|
||||
/// Does this FPOptions require trailing storage when stored in various
|
||||
/// AST nodes, or can it be recreated using `defaultWithoutTrailingStorage`?
|
||||
bool requiresTrailingStorage(const LangOptions &LO);
|
||||
storage_type getAsOpaqueInt() const { return Value; }
|
||||
void getFromOpaqueInt(storage_type value) { Value = value; }
|
||||
|
||||
bool allowFPContractWithinStatement() const {
|
||||
return fp_contract == LangOptions::FPM_On;
|
||||
// We can define most of the accessors automatically:
|
||||
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
||||
unsigned get##NAME() const { \
|
||||
return static_cast<unsigned>(TYPE((Value & NAME##Mask) >> NAME##Shift)); \
|
||||
} \
|
||||
void set##NAME(TYPE value) { \
|
||||
Value = (Value & ~NAME##Mask) | (storage_type(value) << NAME##Shift); \
|
||||
}
|
||||
#include "clang/Basic/FPOptions.def"
|
||||
LLVM_DUMP_METHOD void dump();
|
||||
};
|
||||
|
||||
bool allowFPContractAcrossStatement() const {
|
||||
return fp_contract == LangOptions::FPM_Fast;
|
||||
}
|
||||
/// The FPOptions override type is value of the new FPOptions
|
||||
/// plus a mask showing which fields are actually set in it:
|
||||
class FPOptionsOverride {
|
||||
FPOptions Options;
|
||||
FPOptions::storage_type OverrideMask = 0;
|
||||
|
||||
public:
|
||||
using RoundingMode = llvm::RoundingMode;
|
||||
FPOptionsOverride() {}
|
||||
|
||||
// Used for serializing.
|
||||
explicit FPOptionsOverride(unsigned I) { getFromOpaqueInt(I); }
|
||||
|
||||
bool requiresTrailingStorage() const { return OverrideMask != 0; }
|
||||
|
||||
void setAllowFPContractWithinStatement() {
|
||||
fp_contract = LangOptions::FPM_On;
|
||||
setFPContractModeOverride(LangOptions::FPM_On);
|
||||
}
|
||||
|
||||
void setAllowFPContractAcrossStatement() {
|
||||
fp_contract = LangOptions::FPM_Fast;
|
||||
setFPContractModeOverride(LangOptions::FPM_Fast);
|
||||
}
|
||||
|
||||
void setDisallowFPContract() { fp_contract = LangOptions::FPM_Off; }
|
||||
|
||||
bool allowFEnvAccess() const { return fenv_access == LangOptions::FPM_On; }
|
||||
|
||||
void setAllowFEnvAccess() { fenv_access = LangOptions::FPM_On; }
|
||||
void setDisallowFPContract() {
|
||||
setFPContractModeOverride(LangOptions::FPM_Off);
|
||||
}
|
||||
|
||||
void setFPPreciseEnabled(bool Value) {
|
||||
if (Value) {
|
||||
setAllowFPReassociateOverride(!Value);
|
||||
setNoHonorNaNsOverride(!Value);
|
||||
setNoHonorInfsOverride(!Value);
|
||||
setNoSignedZeroOverride(!Value);
|
||||
setAllowReciprocalOverride(!Value);
|
||||
setAllowApproxFuncOverride(!Value);
|
||||
if (Value)
|
||||
/* Precise mode implies fp_contract=on and disables ffast-math */
|
||||
setFastMath(false);
|
||||
setAllowFPContractWithinStatement();
|
||||
} else {
|
||||
/* Precise mode implies fp_contract=fast and enables ffast-math */
|
||||
setFastMath(true);
|
||||
else
|
||||
/* Precise mode disabled sets fp_contract=fast and enables ffast-math */
|
||||
setAllowFPContractAcrossStatement();
|
||||
}
|
||||
}
|
||||
|
||||
void setDisallowFEnvAccess() { fenv_access = LangOptions::FPM_Off; }
|
||||
|
||||
RoundingMode getRoundingMode() const {
|
||||
return static_cast<RoundingMode>(rounding);
|
||||
}
|
||||
|
||||
void setRoundingMode(RoundingMode RM) {
|
||||
rounding = static_cast<unsigned>(RM);
|
||||
}
|
||||
|
||||
LangOptions::FPExceptionModeKind getExceptionMode() const {
|
||||
return static_cast<LangOptions::FPExceptionModeKind>(exceptions);
|
||||
}
|
||||
|
||||
void setExceptionMode(LangOptions::FPExceptionModeKind EM) {
|
||||
exceptions = EM;
|
||||
}
|
||||
|
||||
/// FMF Flag queries
|
||||
bool allowAssociativeMath() const { return allow_reassoc; }
|
||||
bool noHonorNaNs() const { return no_nans; }
|
||||
bool noHonorInfs() const { return no_infs; }
|
||||
bool noSignedZeros() const { return no_signed_zeros; }
|
||||
bool allowReciprocalMath() const { return allow_reciprocal; }
|
||||
bool allowApproximateFunctions() const { return approx_func; }
|
||||
|
||||
/// Flag setters
|
||||
void setAllowAssociativeMath(bool B = true) { allow_reassoc = B; }
|
||||
void setNoHonorNaNs(bool B = true) { no_nans = B; }
|
||||
void setNoHonorInfs(bool B = true) { no_infs = B; }
|
||||
void setNoSignedZeros(bool B = true) { no_signed_zeros = B; }
|
||||
void setAllowReciprocalMath(bool B = true) { allow_reciprocal = B; }
|
||||
void setAllowApproximateFunctions(bool B = true) { approx_func = B; }
|
||||
|
||||
bool isFPConstrained() const {
|
||||
return getRoundingMode() != RoundingMode::NearestTiesToEven ||
|
||||
getExceptionMode() != LangOptions::FPE_Ignore ||
|
||||
allowFEnvAccess();
|
||||
}
|
||||
|
||||
/// Used to serialize this.
|
||||
unsigned getAsOpaqueInt() const {
|
||||
return fp_contract | (fenv_access << 2) | (rounding << 3) |
|
||||
(exceptions << 6) | (allow_reassoc << 8) | (no_nans << 9) |
|
||||
(no_infs << 10) | (no_signed_zeros << 11) |
|
||||
(allow_reciprocal << 12) | (approx_func << 13);
|
||||
return Options.getAsOpaqueInt() << 16 | OverrideMask;
|
||||
}
|
||||
|
||||
/// Used with getAsOpaqueInt() to manage the float_control pragma stack.
|
||||
void getFromOpaqueInt(unsigned I) {
|
||||
fp_contract = (static_cast<LangOptions::FPModeKind>(I & 3));
|
||||
fenv_access = ((I >> 2) & 1);
|
||||
rounding = static_cast<unsigned>(static_cast<RoundingMode>((I >> 3) & 7));
|
||||
exceptions = (static_cast<LangOptions::FPExceptionModeKind>((I >> 6) & 3));
|
||||
allow_reassoc = ((I >> 8) & 1);
|
||||
no_nans = ((I >> 9) & 1);
|
||||
no_infs = ((I >> 10) & 1);
|
||||
no_signed_zeros = ((I >> 11) & 1);
|
||||
allow_reciprocal = ((I >> 12) & 1);
|
||||
approx_func = ((I >> 13) & 1);
|
||||
OverrideMask = I & 0xffff;
|
||||
Options.getFromOpaqueInt(I >> 16);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Adjust BinaryOperatorBitfields::FPFeatures and
|
||||
/// CXXOperatorCallExprBitfields::FPFeatures to match the total bit-field size
|
||||
/// of these fields.
|
||||
unsigned fp_contract : 2;
|
||||
unsigned fenv_access : 1;
|
||||
unsigned rounding : 3;
|
||||
unsigned exceptions : 2;
|
||||
/// Allow reassociation transformations for floating-point instructions
|
||||
/// across multiple statements.
|
||||
unsigned allow_reassoc : 1;
|
||||
/// No NaNs - Allow optimizations to assume the arguments and result
|
||||
/// are not NaN. If an argument is a nan, or the result would be a nan,
|
||||
/// it produces a :ref:`poison value <poisonvalues>` instead.
|
||||
unsigned no_nans : 1;
|
||||
/// No Infs - Allow optimizations to assume the arguments and result
|
||||
/// are not +/-Inf. If an argument is +/-Inf, or the result would be +/-Inf,
|
||||
/// it produces a :ref:`poison value <poisonvalues>` instead.
|
||||
unsigned no_infs : 1;
|
||||
/// No Signed Zeros - Allow optimizations to treat the sign of a zero
|
||||
/// argument or result as insignificant.
|
||||
unsigned no_signed_zeros : 1;
|
||||
/// Allow Reciprocal - Allow optimizations to use the reciprocal
|
||||
/// of an argument rather than perform division.
|
||||
unsigned allow_reciprocal : 1;
|
||||
/// Approximate functions - Allow substitution of approximate calculations
|
||||
/// for functions (sin, log, sqrt, etc).
|
||||
unsigned approx_func : 1;
|
||||
};
|
||||
FPOptions applyOverrides(const LangOptions &LO) {
|
||||
FPOptions Base(LO);
|
||||
FPOptions result((Base.getAsOpaqueInt() & ~OverrideMask) |
|
||||
(Options.getAsOpaqueInt() & OverrideMask));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool operator==(FPOptions LHS, FPOptions RHS) {
|
||||
return LHS.getAsOpaqueInt() == RHS.getAsOpaqueInt();
|
||||
}
|
||||
inline bool operator!=(FPOptions LHS, FPOptions RHS) {
|
||||
return LHS.getAsOpaqueInt() != RHS.getAsOpaqueInt();
|
||||
}
|
||||
bool operator==(FPOptionsOverride other) const {
|
||||
return Options == other.Options && OverrideMask == other.OverrideMask;
|
||||
}
|
||||
bool operator!=(FPOptionsOverride other) const { return !(*this == other); }
|
||||
|
||||
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
||||
bool has##NAME##Override() const { \
|
||||
return OverrideMask & FPOptions::NAME##Mask; \
|
||||
} \
|
||||
unsigned get##NAME##Override() const { \
|
||||
assert(has##NAME##Override()); \
|
||||
return Options.get##NAME(); \
|
||||
} \
|
||||
void clear##NAME##Override() { \
|
||||
/* Clear the actual value so that we don't have spurious differences when \
|
||||
* testing equality. */ \
|
||||
Options.set##NAME(TYPE(0)); \
|
||||
OverrideMask &= ~FPOptions::NAME##Mask; \
|
||||
} \
|
||||
void set##NAME##Override(TYPE value) { \
|
||||
Options.set##NAME(value); \
|
||||
OverrideMask |= FPOptions::NAME##Mask; \
|
||||
}
|
||||
#include "clang/Basic/FPOptions.def"
|
||||
LLVM_DUMP_METHOD void dump();
|
||||
};
|
||||
|
||||
/// Describes the kind of translation unit being processed.
|
||||
enum TranslationUnitKind {
|
||||
|
|
|
@ -557,6 +557,15 @@ public:
|
|||
|
||||
// This stack tracks the current state of Sema.CurFPFeatures.
|
||||
PragmaStack<unsigned> FpPragmaStack;
|
||||
FPOptionsOverride CurFPFeatureOverrides() {
|
||||
FPOptionsOverride result;
|
||||
if (!FpPragmaStack.hasValue()) {
|
||||
result = FPOptionsOverride();
|
||||
} else {
|
||||
result = FPOptionsOverride(FpPragmaStack.CurrentValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// RAII object to push / pop sentinel slots for all MS #pragma stacks.
|
||||
// Actions should be performed only if we enter / exit a C++ method body.
|
||||
|
@ -1358,12 +1367,19 @@ public:
|
|||
/// statements.
|
||||
class FPFeaturesStateRAII {
|
||||
public:
|
||||
FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.CurFPFeatures) {}
|
||||
~FPFeaturesStateRAII() { S.CurFPFeatures = OldFPFeaturesState; }
|
||||
FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.CurFPFeatures) {
|
||||
OldOverrides = S.FpPragmaStack.CurrentValue;
|
||||
}
|
||||
~FPFeaturesStateRAII() {
|
||||
S.CurFPFeatures = OldFPFeaturesState;
|
||||
S.FpPragmaStack.CurrentValue = OldOverrides;
|
||||
}
|
||||
unsigned getOverrides() { return OldOverrides; }
|
||||
|
||||
private:
|
||||
Sema& S;
|
||||
FPOptions OldFPFeaturesState;
|
||||
unsigned OldOverrides;
|
||||
};
|
||||
|
||||
void addImplicitTypedef(StringRef Name, QualType T);
|
||||
|
@ -9606,10 +9622,10 @@ public:
|
|||
|
||||
/// Are precise floating point semantics currently enabled?
|
||||
bool isPreciseFPEnabled() {
|
||||
return !CurFPFeatures.allowAssociativeMath() &&
|
||||
!CurFPFeatures.noSignedZeros() &&
|
||||
!CurFPFeatures.allowReciprocalMath() &&
|
||||
!CurFPFeatures.allowApproximateFunctions();
|
||||
return !CurFPFeatures.getAllowFPReassociate() &&
|
||||
!CurFPFeatures.getNoSignedZero() &&
|
||||
!CurFPFeatures.getAllowReciprocal() &&
|
||||
!CurFPFeatures.getAllowApproxFunc();
|
||||
}
|
||||
|
||||
/// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
|
||||
|
@ -9652,21 +9668,21 @@ public:
|
|||
/// ActOnPragmaFPContract - Called on well formed
|
||||
/// \#pragma {STDC,OPENCL} FP_CONTRACT and
|
||||
/// \#pragma clang fp contract
|
||||
void ActOnPragmaFPContract(LangOptions::FPModeKind FPC);
|
||||
void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
|
||||
|
||||
/// Called on well formed
|
||||
/// \#pragma clang fp reassociate
|
||||
void ActOnPragmaFPReassociate(bool IsEnabled);
|
||||
void ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled);
|
||||
|
||||
/// ActOnPragmaFenvAccess - Called on well formed
|
||||
/// \#pragma STDC FENV_ACCESS
|
||||
void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
|
||||
|
||||
/// Called to set rounding mode for floating point operations.
|
||||
void setRoundingMode(llvm::RoundingMode);
|
||||
void setRoundingMode(SourceLocation Loc, llvm::RoundingMode);
|
||||
|
||||
/// Called to set exception behavior for floating point operations.
|
||||
void setExceptionMode(LangOptions::FPExceptionModeKind);
|
||||
void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
|
||||
|
||||
/// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
|
||||
/// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
|
||||
|
|
|
@ -62,6 +62,7 @@ class CXXRecordDecl;
|
|||
class CXXTemporary;
|
||||
class FileEntry;
|
||||
class FPOptions;
|
||||
class FPOptionsOverride;
|
||||
class FunctionDecl;
|
||||
class HeaderSearch;
|
||||
class HeaderSearchOptions;
|
||||
|
@ -506,7 +507,7 @@ private:
|
|||
bool IsModule);
|
||||
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
|
||||
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
|
||||
void WriteFPPragmaOptions(const FPOptions &Opts);
|
||||
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
|
||||
void WriteOpenCLExtensions(Sema &SemaRef);
|
||||
void WriteOpenCLExtensionTypes(Sema &SemaRef);
|
||||
void WriteOpenCLExtensionDecls(Sema &SemaRef);
|
||||
|
|
|
@ -54,6 +54,7 @@ module Clang_Basic {
|
|||
textual header "Basic/CodeGenOptions.def"
|
||||
textual header "Basic/DiagnosticOptions.def"
|
||||
textual header "Basic/Features.def"
|
||||
textual header "Basic/FPOptions.def"
|
||||
textual header "Basic/MSP430Target.def"
|
||||
textual header "Basic/LangOptions.def"
|
||||
textual header "Basic/OpenCLExtensions.def"
|
||||
|
|
|
@ -6676,7 +6676,7 @@ ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
|
|||
return UnaryOperator::Create(
|
||||
Importer.getToContext(), ToSubExpr, E->getOpcode(), ToType,
|
||||
E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->canOverflow(),
|
||||
E->getFPFeatures(Importer.getFromContext().getLangOpts()));
|
||||
E->getFPOptionsOverride());
|
||||
}
|
||||
|
||||
ExpectedStmt
|
||||
|
|
|
@ -4468,7 +4468,7 @@ ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx,
|
|||
BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
|
||||
Opcode opc, QualType ResTy, ExprValueKind VK,
|
||||
ExprObjectKind OK, SourceLocation opLoc,
|
||||
FPOptions FPFeatures)
|
||||
FPOptionsOverride FPFeatures)
|
||||
: Expr(BinaryOperatorClass, ResTy, VK, OK) {
|
||||
BinaryOperatorBits.Opc = opc;
|
||||
assert(!isCompoundAssignmentOp() &&
|
||||
|
@ -4476,8 +4476,7 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
|
|||
BinaryOperatorBits.OpLoc = opLoc;
|
||||
SubExprs[LHS] = lhs;
|
||||
SubExprs[RHS] = rhs;
|
||||
BinaryOperatorBits.HasFPFeatures =
|
||||
FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
|
||||
BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
|
||||
if (BinaryOperatorBits.HasFPFeatures)
|
||||
*getTrailingFPFeatures() = FPFeatures;
|
||||
setDependence(computeDependence(this));
|
||||
|
@ -4486,7 +4485,7 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
|
|||
BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
|
||||
Opcode opc, QualType ResTy, ExprValueKind VK,
|
||||
ExprObjectKind OK, SourceLocation opLoc,
|
||||
FPOptions FPFeatures, bool dead2)
|
||||
FPOptionsOverride FPFeatures, bool dead2)
|
||||
: Expr(CompoundAssignOperatorClass, ResTy, VK, OK) {
|
||||
BinaryOperatorBits.Opc = opc;
|
||||
assert(isCompoundAssignmentOp() &&
|
||||
|
@ -4494,8 +4493,7 @@ BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
|
|||
BinaryOperatorBits.OpLoc = opLoc;
|
||||
SubExprs[LHS] = lhs;
|
||||
SubExprs[RHS] = rhs;
|
||||
BinaryOperatorBits.HasFPFeatures =
|
||||
FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
|
||||
BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
|
||||
if (BinaryOperatorBits.HasFPFeatures)
|
||||
*getTrailingFPFeatures() = FPFeatures;
|
||||
setDependence(computeDependence(this));
|
||||
|
@ -4513,8 +4511,8 @@ BinaryOperator *BinaryOperator::Create(const ASTContext &C, Expr *lhs,
|
|||
Expr *rhs, Opcode opc, QualType ResTy,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation opLoc,
|
||||
FPOptions FPFeatures) {
|
||||
bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
|
||||
FPOptionsOverride FPFeatures) {
|
||||
bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
|
||||
unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
|
||||
void *Mem =
|
||||
C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator));
|
||||
|
@ -4530,11 +4528,13 @@ CompoundAssignOperator::CreateEmpty(const ASTContext &C, bool HasFPFeatures) {
|
|||
return new (Mem) CompoundAssignOperator(C, EmptyShell(), HasFPFeatures);
|
||||
}
|
||||
|
||||
CompoundAssignOperator *CompoundAssignOperator::Create(
|
||||
const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
|
||||
ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc,
|
||||
FPOptions FPFeatures, QualType CompLHSType, QualType CompResultType) {
|
||||
bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
|
||||
CompoundAssignOperator *
|
||||
CompoundAssignOperator::Create(const ASTContext &C, Expr *lhs, Expr *rhs,
|
||||
Opcode opc, QualType ResTy, ExprValueKind VK,
|
||||
ExprObjectKind OK, SourceLocation opLoc,
|
||||
FPOptionsOverride FPFeatures,
|
||||
QualType CompLHSType, QualType CompResultType) {
|
||||
bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
|
||||
unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
|
||||
void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra,
|
||||
alignof(CompoundAssignOperator));
|
||||
|
@ -4545,7 +4545,7 @@ CompoundAssignOperator *CompoundAssignOperator::Create(
|
|||
|
||||
UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C,
|
||||
bool hasFPFeatures) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<FPOptions>(hasFPFeatures),
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures),
|
||||
alignof(UnaryOperator));
|
||||
return new (Mem) UnaryOperator(hasFPFeatures, EmptyShell());
|
||||
}
|
||||
|
@ -4553,13 +4553,12 @@ UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C,
|
|||
UnaryOperator::UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc,
|
||||
QualType type, ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation l, bool CanOverflow,
|
||||
FPOptions FPFeatures)
|
||||
FPOptionsOverride FPFeatures)
|
||||
: Expr(UnaryOperatorClass, type, VK, OK), Val(input) {
|
||||
UnaryOperatorBits.Opc = opc;
|
||||
UnaryOperatorBits.CanOverflow = CanOverflow;
|
||||
UnaryOperatorBits.Loc = l;
|
||||
UnaryOperatorBits.HasFPFeatures =
|
||||
FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
|
||||
UnaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
|
@ -4567,9 +4566,9 @@ UnaryOperator *UnaryOperator::Create(const ASTContext &C, Expr *input,
|
|||
Opcode opc, QualType type,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation l, bool CanOverflow,
|
||||
FPOptions FPFeatures) {
|
||||
bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
|
||||
unsigned Size = totalSizeToAlloc<FPOptions>(HasFPFeatures);
|
||||
FPOptionsOverride FPFeatures) {
|
||||
bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
|
||||
unsigned Size = totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures);
|
||||
void *Mem = C.Allocate(Size, alignof(UnaryOperator));
|
||||
return new (Mem)
|
||||
UnaryOperator(C, input, opc, type, VK, OK, l, CanOverflow, FPFeatures);
|
||||
|
|
|
@ -525,27 +525,27 @@ CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind,
|
|||
Expr *Fn, ArrayRef<Expr *> Args,
|
||||
QualType Ty, ExprValueKind VK,
|
||||
SourceLocation OperatorLoc,
|
||||
FPOptions FPFeatures,
|
||||
FPOptionsOverride FPFeatures,
|
||||
ADLCallKind UsesADL)
|
||||
: CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
|
||||
OperatorLoc, /*MinNumArgs=*/0, UsesADL) {
|
||||
CXXOperatorCallExprBits.OperatorKind = OpKind;
|
||||
CXXOperatorCallExprBits.FPFeatures = FPFeatures.getAsOpaqueInt();
|
||||
assert(
|
||||
(CXXOperatorCallExprBits.OperatorKind == static_cast<unsigned>(OpKind)) &&
|
||||
"OperatorKind overflow!");
|
||||
assert((CXXOperatorCallExprBits.FPFeatures == FPFeatures.getAsOpaqueInt()) &&
|
||||
"FPFeatures overflow!");
|
||||
Range = getSourceRangeImpl();
|
||||
Overrides = FPFeatures;
|
||||
}
|
||||
|
||||
CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty)
|
||||
: CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
|
||||
|
||||
CXXOperatorCallExpr *CXXOperatorCallExpr::Create(
|
||||
const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
|
||||
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
|
||||
SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) {
|
||||
CXXOperatorCallExpr *
|
||||
CXXOperatorCallExpr::Create(const ASTContext &Ctx,
|
||||
OverloadedOperatorKind OpKind, Expr *Fn,
|
||||
ArrayRef<Expr *> Args, QualType Ty,
|
||||
ExprValueKind VK, SourceLocation OperatorLoc,
|
||||
FPOptionsOverride FPFeatures, ADLCallKind UsesADL) {
|
||||
// Allocate storage for the trailing objects of CallExpr.
|
||||
unsigned NumArgs = Args.size();
|
||||
unsigned SizeOfTrailingObjects =
|
||||
|
|
|
@ -116,18 +116,17 @@ BinaryOperator *ASTMaker::makeAssignment(const Expr *LHS, const Expr *RHS,
|
|||
QualType Ty) {
|
||||
return BinaryOperator::Create(
|
||||
C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
|
||||
VK_RValue, OK_Ordinary, SourceLocation(), FPOptions(C.getLangOpts()));
|
||||
VK_RValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
|
||||
}
|
||||
|
||||
BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
|
||||
BinaryOperator::Opcode Op) {
|
||||
assert(BinaryOperator::isLogicalOp(Op) ||
|
||||
BinaryOperator::isComparisonOp(Op));
|
||||
return BinaryOperator::Create(C, const_cast<Expr *>(LHS),
|
||||
const_cast<Expr *>(RHS), Op,
|
||||
C.getLogicalOperationType(), VK_RValue,
|
||||
OK_Ordinary, SourceLocation(),
|
||||
FPOptions(C.getLangOpts()));
|
||||
return BinaryOperator::Create(
|
||||
C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), Op,
|
||||
C.getLogicalOperationType(), VK_RValue, OK_Ordinary, SourceLocation(),
|
||||
FPOptionsOverride());
|
||||
}
|
||||
|
||||
CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
|
||||
|
@ -148,8 +147,7 @@ DeclRefExpr *ASTMaker::makeDeclRefExpr(
|
|||
UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) {
|
||||
return UnaryOperator::Create(C, const_cast<Expr *>(Arg), UO_Deref, Ty,
|
||||
VK_LValue, OK_Ordinary, SourceLocation(),
|
||||
/*CanOverflow*/ false,
|
||||
FPOptions(C.getLangOpts()));
|
||||
/*CanOverflow*/ false, FPOptionsOverride());
|
||||
}
|
||||
|
||||
ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
|
||||
|
@ -297,7 +295,7 @@ static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
|
|||
/*QualType=*/C.VoidTy,
|
||||
/*ExprValueType=*/VK_RValue,
|
||||
/*SourceLocation=*/SourceLocation(),
|
||||
/*FPFeatures=*/FPOptions(C.getLangOpts()));
|
||||
/*FPFeatures=*/FPOptionsOverride());
|
||||
}
|
||||
|
||||
/// Create a fake body for std::call_once.
|
||||
|
@ -457,7 +455,7 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
|
|||
/* QualType=*/C.IntTy,
|
||||
/* ExprValueKind=*/VK_RValue,
|
||||
/* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
|
||||
/* CanOverflow*/ false, FPOptions(C.getLangOpts()));
|
||||
/* CanOverflow*/ false, FPOptionsOverride());
|
||||
|
||||
// Create assignment.
|
||||
BinaryOperator *FlagAssignment = M.makeAssignment(
|
||||
|
@ -522,7 +520,7 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
|
|||
Expr *DoneValue =
|
||||
UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
|
||||
C.LongTy, VK_RValue, OK_Ordinary, SourceLocation(),
|
||||
/*CanOverflow*/ false, FPOptions(C.getLangOpts()));
|
||||
/*CanOverflow*/ false, FPOptionsOverride());
|
||||
|
||||
BinaryOperator *B =
|
||||
M.makeAssignment(
|
||||
|
|
|
@ -24,7 +24,7 @@ void LangOptions::resetNonModularOptions() {
|
|||
#define LANGOPT(Name, Bits, Default, Description)
|
||||
#define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default;
|
||||
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
|
||||
Name = Default;
|
||||
Name = static_cast<unsigned>(Default);
|
||||
#include "clang/Basic/LangOptions.def"
|
||||
|
||||
// These options do not affect AST generation.
|
||||
|
@ -53,6 +53,17 @@ FPOptions FPOptions::defaultWithoutTrailingStorage(const LangOptions &LO) {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool FPOptions::requiresTrailingStorage(const LangOptions &LO) {
|
||||
return getAsOpaqueInt() != defaultWithoutTrailingStorage(LO).getAsOpaqueInt();
|
||||
LLVM_DUMP_METHOD void FPOptions::dump() {
|
||||
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
||||
llvm::errs() << "\n " #NAME " " << get##NAME();
|
||||
#include "clang/Basic/FPOptions.def"
|
||||
llvm::errs() << "\n";
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD void FPOptionsOverride::dump() {
|
||||
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
||||
if (has##NAME##Override()) \
|
||||
llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override();
|
||||
#include "clang/Basic/FPOptions.def"
|
||||
llvm::errs() << "\n";
|
||||
}
|
||||
|
|
|
@ -2389,7 +2389,7 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
|
|||
if (!E->canOverflow())
|
||||
return Builder.CreateNSWAdd(InVal, Amount, Name);
|
||||
return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
|
||||
E, InVal, IsInc, E->getFPFeatures(CGF.getLangOpts())));
|
||||
E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
|
||||
}
|
||||
llvm_unreachable("Unknown SignedOverflowBehaviorTy");
|
||||
}
|
||||
|
@ -2536,7 +2536,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
|
|||
} else if (E->canOverflow() && type->isUnsignedIntegerType() &&
|
||||
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
|
||||
value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
|
||||
E, value, isInc, E->getFPFeatures(CGF.getLangOpts())));
|
||||
E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
|
||||
} else {
|
||||
llvm::Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
|
||||
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
|
||||
|
@ -2736,7 +2736,7 @@ Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
|
|||
BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType());
|
||||
BinOp.Ty = E->getType();
|
||||
BinOp.Opcode = BO_Sub;
|
||||
BinOp.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
|
||||
BinOp.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
|
||||
BinOp.E = E;
|
||||
return EmitSub(BinOp);
|
||||
}
|
||||
|
@ -2757,7 +2757,7 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
|
|||
Value *Result;
|
||||
if (Oper->getType()->isFPOrFPVectorTy()) {
|
||||
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
|
||||
CGF, E->getFPFeatures(CGF.getLangOpts()));
|
||||
CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
|
||||
Result = Builder.CreateFCmp(llvm::CmpInst::FCMP_OEQ, Oper, Zero, "cmp");
|
||||
} else
|
||||
Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp");
|
||||
|
@ -2960,7 +2960,7 @@ BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) {
|
|||
Result.RHS = Visit(E->getRHS());
|
||||
Result.Ty = E->getType();
|
||||
Result.Opcode = E->getOpcode();
|
||||
Result.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
|
||||
Result.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
|
||||
Result.E = E;
|
||||
return Result;
|
||||
}
|
||||
|
@ -2980,7 +2980,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
|
|||
OpInfo.RHS = Visit(E->getRHS());
|
||||
OpInfo.Ty = E->getComputationResultType();
|
||||
OpInfo.Opcode = E->getOpcode();
|
||||
OpInfo.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
|
||||
OpInfo.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
|
||||
OpInfo.E = E;
|
||||
// Load/convert the LHS.
|
||||
LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
|
||||
|
@ -4214,7 +4214,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
|
|||
Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
|
||||
if (LHS->getType()->isFPOrFPVectorTy()) {
|
||||
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
|
||||
CGF, E->getFPFeatures(CGF.getLangOpts()));
|
||||
CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
|
||||
LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
|
||||
RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
|
||||
} else {
|
||||
|
@ -4300,7 +4300,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
|
|||
Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
|
||||
if (LHS->getType()->isFPOrFPVectorTy()) {
|
||||
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
|
||||
CGF, E->getFPFeatures(CGF.getLangOpts()));
|
||||
CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
|
||||
LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
|
||||
RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
|
||||
} else {
|
||||
|
|
|
@ -1493,8 +1493,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
|
|||
|
||||
BinaryOperator *assign = BinaryOperator::Create(
|
||||
getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue,
|
||||
OK_Ordinary, SourceLocation(),
|
||||
FPOptions(getContext().getLangOpts()));
|
||||
OK_Ordinary, SourceLocation(), FPOptionsOverride());
|
||||
EmitStmt(assign);
|
||||
}
|
||||
|
||||
|
@ -3556,18 +3555,18 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
|
|||
DeclRefExpr DstExpr(C, &DstDecl, false, DestTy, VK_RValue, SourceLocation());
|
||||
UnaryOperator *DST = UnaryOperator::Create(
|
||||
C, &DstExpr, UO_Deref, DestTy->getPointeeType(), VK_LValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(C.getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
|
||||
DeclRefExpr SrcExpr(C, &SrcDecl, false, SrcTy, VK_RValue, SourceLocation());
|
||||
UnaryOperator *SRC = UnaryOperator::Create(
|
||||
C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(C.getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
|
||||
Expr *Args[2] = {DST, SRC};
|
||||
CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
|
||||
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
|
||||
C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(),
|
||||
VK_LValue, SourceLocation(), FPOptions(C.getLangOpts()));
|
||||
VK_LValue, SourceLocation(), FPOptionsOverride());
|
||||
|
||||
EmitStmt(TheCall);
|
||||
|
||||
|
@ -3641,7 +3640,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
|
|||
|
||||
UnaryOperator *SRC = UnaryOperator::Create(
|
||||
C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(C.getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
|
||||
CXXConstructExpr *CXXConstExpr =
|
||||
cast<CXXConstructExpr>(PID->getGetterCXXConstructor());
|
||||
|
|
|
@ -3328,11 +3328,11 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
|
|||
// Generate condition for loop.
|
||||
BinaryOperator *Cond = BinaryOperator::Create(
|
||||
C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, OK_Ordinary,
|
||||
S.getBeginLoc(), FPOptions(C.getLangOpts()));
|
||||
S.getBeginLoc(), FPOptionsOverride());
|
||||
// Increment for loop counter.
|
||||
UnaryOperator *Inc = UnaryOperator::Create(
|
||||
C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
|
||||
S.getBeginLoc(), true, FPOptions(C.getLangOpts()));
|
||||
S.getBeginLoc(), true, FPOptionsOverride());
|
||||
auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
|
||||
// Iterate through all sections and emit a switch construct:
|
||||
// switch (IV) {
|
||||
|
|
|
@ -117,12 +117,12 @@ void CodeGenFunction::SetFPModel() {
|
|||
|
||||
void CodeGenFunction::SetFastMathFlags(FPOptions FPFeatures) {
|
||||
llvm::FastMathFlags FMF;
|
||||
FMF.setAllowReassoc(FPFeatures.allowAssociativeMath());
|
||||
FMF.setNoNaNs(FPFeatures.noHonorNaNs());
|
||||
FMF.setNoInfs(FPFeatures.noHonorInfs());
|
||||
FMF.setNoSignedZeros(FPFeatures.noSignedZeros());
|
||||
FMF.setAllowReciprocal(FPFeatures.allowReciprocalMath());
|
||||
FMF.setApproxFunc(FPFeatures.allowApproximateFunctions());
|
||||
FMF.setAllowReassoc(FPFeatures.getAllowFPReassociate());
|
||||
FMF.setNoNaNs(FPFeatures.getNoHonorNaNs());
|
||||
FMF.setNoInfs(FPFeatures.getNoHonorInfs());
|
||||
FMF.setNoSignedZeros(FPFeatures.getNoSignedZero());
|
||||
FMF.setAllowReciprocal(FPFeatures.getAllowReciprocal());
|
||||
FMF.setApproxFunc(FPFeatures.getAllowApproxFunc());
|
||||
FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement());
|
||||
Builder.setFastMathFlags(FMF);
|
||||
}
|
||||
|
@ -137,10 +137,12 @@ CodeGenFunction::CGFPOptionsRAII::CGFPOptionsRAII(CodeGenFunction &CGF,
|
|||
|
||||
FMFGuard.emplace(CGF.Builder);
|
||||
|
||||
auto NewRoundingBehavior = FPFeatures.getRoundingMode();
|
||||
llvm::RoundingMode NewRoundingBehavior =
|
||||
static_cast<llvm::RoundingMode>(FPFeatures.getRoundingMode());
|
||||
CGF.Builder.setDefaultConstrainedRounding(NewRoundingBehavior);
|
||||
auto NewExceptionBehavior =
|
||||
ToConstrainedExceptMD(FPFeatures.getExceptionMode());
|
||||
ToConstrainedExceptMD(static_cast<LangOptions::FPExceptionModeKind>(
|
||||
FPFeatures.getFPExceptionMode()));
|
||||
CGF.Builder.setDefaultConstrainedExcept(NewExceptionBehavior);
|
||||
|
||||
CGF.SetFastMathFlags(FPFeatures);
|
||||
|
@ -159,13 +161,13 @@ CodeGenFunction::CGFPOptionsRAII::CGFPOptionsRAII(CodeGenFunction &CGF,
|
|||
if (OldValue != NewValue)
|
||||
CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
|
||||
};
|
||||
mergeFnAttrValue("no-infs-fp-math", FPFeatures.noHonorInfs());
|
||||
mergeFnAttrValue("no-nans-fp-math", FPFeatures.noHonorNaNs());
|
||||
mergeFnAttrValue("no-signed-zeros-fp-math", FPFeatures.noSignedZeros());
|
||||
mergeFnAttrValue(
|
||||
"unsafe-fp-math",
|
||||
FPFeatures.allowAssociativeMath() && FPFeatures.allowReciprocalMath() &&
|
||||
FPFeatures.allowApproximateFunctions() && FPFeatures.noSignedZeros());
|
||||
mergeFnAttrValue("no-infs-fp-math", FPFeatures.getNoHonorInfs());
|
||||
mergeFnAttrValue("no-nans-fp-math", FPFeatures.getNoHonorNaNs());
|
||||
mergeFnAttrValue("no-signed-zeros-fp-math", FPFeatures.getNoSignedZero());
|
||||
mergeFnAttrValue("unsafe-fp-math", FPFeatures.getAllowFPReassociate() &&
|
||||
FPFeatures.getAllowReciprocal() &&
|
||||
FPFeatures.getAllowApproxFunc() &&
|
||||
FPFeatures.getNoSignedZero());
|
||||
}
|
||||
|
||||
CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() {
|
||||
|
|
|
@ -2590,7 +2590,7 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
|
|||
Expr *Unop = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
|
||||
Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
// cast to NSConstantString *
|
||||
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
|
||||
CK_CPointerToObjCPointerCast, Unop);
|
||||
|
@ -3287,7 +3287,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
SuperRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
|
||||
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
SuperRep = NoTypeInfoCStyleCastExpr(Context,
|
||||
Context->getPointerType(superType),
|
||||
CK_BitCast, SuperRep);
|
||||
|
@ -3305,7 +3305,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
SuperRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
|
||||
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
}
|
||||
MsgExprs.push_back(SuperRep);
|
||||
break;
|
||||
|
@ -3382,7 +3382,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
SuperRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
|
||||
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
SuperRep = NoTypeInfoCStyleCastExpr(Context,
|
||||
Context->getPointerType(superType),
|
||||
CK_BitCast, SuperRep);
|
||||
|
@ -4706,10 +4706,9 @@ Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
|
|||
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
|
||||
if (!ImportedLocalExternalDecls.count(Var))
|
||||
return DRE;
|
||||
Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
|
||||
UO_Deref, DRE->getType(), VK_LValue,
|
||||
OK_Ordinary, DRE->getLocation(), false,
|
||||
FPOptions(Context->getLangOpts()));
|
||||
Expr *Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),
|
||||
VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());
|
||||
// Need parens to enforce precedence.
|
||||
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
|
||||
Exp);
|
||||
|
@ -5300,7 +5299,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
|
||||
VK_LValue, SourceLocation()),
|
||||
UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
|
||||
OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
|
||||
InitExprs.push_back(DescRefExpr);
|
||||
|
||||
// Add initializers for any closure decl refs.
|
||||
|
@ -5317,10 +5316,9 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
if (HasLocalVariableExternalStorage(*I)) {
|
||||
QualType QT = (*I)->getType();
|
||||
QT = Context->getPointerType(QT);
|
||||
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
|
||||
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false,
|
||||
FPOptions(Context->getLangOpts()));
|
||||
Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
|
||||
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
|
||||
}
|
||||
} else if (isTopLevelBlockPointerType((*I)->getType())) {
|
||||
FD = SynthBlockInitFunctionDecl((*I)->getName());
|
||||
|
@ -5335,10 +5333,9 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
if (HasLocalVariableExternalStorage(*I)) {
|
||||
QualType QT = (*I)->getType();
|
||||
QT = Context->getPointerType(QT);
|
||||
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
|
||||
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false,
|
||||
FPOptions(Context->getLangOpts()));
|
||||
Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
|
||||
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5379,7 +5376,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
|
||||
Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
|
||||
InitExprs.push_back(Exp);
|
||||
}
|
||||
|
@ -5406,7 +5403,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
NewRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
|
||||
Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
|
||||
NewRep);
|
||||
// Put Paren around the call.
|
||||
|
@ -7494,7 +7491,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
|
|||
BinaryOperator *addExpr = BinaryOperator::Create(
|
||||
*Context, castExpr, DRE, BO_Add,
|
||||
Context->getPointerType(Context->CharTy), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), FPOptionsOverride());
|
||||
// Don't forget the parens to enforce the proper binding.
|
||||
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
|
||||
SourceLocation(),
|
||||
|
@ -7545,10 +7542,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
|
|||
CK_BitCast,
|
||||
PE);
|
||||
|
||||
Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context),
|
||||
castExpr, UO_Deref, IvarT, VK_LValue,
|
||||
OK_Ordinary, SourceLocation(), false,
|
||||
FPOptions(Context->getLangOpts()));
|
||||
Expr *Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,
|
||||
VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
|
||||
PE = new (Context) ParenExpr(OldRange.getBegin(),
|
||||
OldRange.getEnd(),
|
||||
Exp);
|
||||
|
|
|
@ -2517,7 +2517,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
|
|||
Expr *Unop = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
|
||||
Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
// cast to NSConstantString *
|
||||
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
|
||||
CK_CPointerToObjCPointerCast, Unop);
|
||||
|
@ -2718,7 +2718,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
SuperRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
|
||||
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
SuperRep = NoTypeInfoCStyleCastExpr(Context,
|
||||
Context->getPointerType(superType),
|
||||
CK_BitCast, SuperRep);
|
||||
|
@ -2736,7 +2736,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
SuperRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
|
||||
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
}
|
||||
MsgExprs.push_back(SuperRep);
|
||||
break;
|
||||
|
@ -2813,7 +2813,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
SuperRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
|
||||
Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
SuperRep = NoTypeInfoCStyleCastExpr(Context,
|
||||
Context->getPointerType(superType),
|
||||
CK_BitCast, SuperRep);
|
||||
|
@ -2999,7 +2999,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
SourceLocation());
|
||||
BinaryOperator *lessThanExpr = BinaryOperator::Create(
|
||||
*Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_RValue,
|
||||
OK_Ordinary, SourceLocation(), FPOptions(Context->getLangOpts()));
|
||||
OK_Ordinary, SourceLocation(), FPOptionsOverride());
|
||||
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
|
||||
ConditionalOperator *CondExpr =
|
||||
new (Context) ConditionalOperator(lessThanExpr,
|
||||
|
@ -3052,7 +3052,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
|
|||
Expr *DerefExpr = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
|
||||
Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
|
||||
CK_BitCast,
|
||||
DerefExpr);
|
||||
|
@ -3877,10 +3877,9 @@ Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
|
|||
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
|
||||
if (!ImportedLocalExternalDecls.count(Var))
|
||||
return DRE;
|
||||
Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
|
||||
UO_Deref, DRE->getType(), VK_LValue,
|
||||
OK_Ordinary, DRE->getLocation(), false,
|
||||
FPOptions(Context->getLangOpts()));
|
||||
Expr *Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),
|
||||
VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());
|
||||
// Need parens to enforce precedence.
|
||||
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
|
||||
Exp);
|
||||
|
@ -4440,7 +4439,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
|
||||
VK_LValue, SourceLocation()),
|
||||
UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
|
||||
OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
|
||||
InitExprs.push_back(DescRefExpr);
|
||||
|
||||
// Add initializers for any closure decl refs.
|
||||
|
@ -4457,10 +4456,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
if (HasLocalVariableExternalStorage(*I)) {
|
||||
QualType QT = (*I)->getType();
|
||||
QT = Context->getPointerType(QT);
|
||||
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
|
||||
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false,
|
||||
FPOptions(Context->getLangOpts()));
|
||||
Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
|
||||
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
|
||||
}
|
||||
} else if (isTopLevelBlockPointerType((*I)->getType())) {
|
||||
FD = SynthBlockInitFunctionDecl((*I)->getName());
|
||||
|
@ -4475,10 +4473,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
if (HasLocalVariableExternalStorage(*I)) {
|
||||
QualType QT = (*I)->getType();
|
||||
QT = Context->getPointerType(QT);
|
||||
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
|
||||
UO_AddrOf, QT, VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false,
|
||||
FPOptions(Context->getLangOpts()));
|
||||
Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
|
||||
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
|
||||
}
|
||||
}
|
||||
InitExprs.push_back(Exp);
|
||||
|
@ -4518,7 +4515,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
Exp = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
|
||||
Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
|
||||
InitExprs.push_back(Exp);
|
||||
}
|
||||
|
@ -4537,7 +4534,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
NewRep = UnaryOperator::Create(
|
||||
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
|
||||
Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
|
||||
SourceLocation(), false, FPOptions(Context->getLangOpts()));
|
||||
SourceLocation(), false, FPOptionsOverride());
|
||||
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
|
||||
NewRep);
|
||||
BlockDeclRefs.clear();
|
||||
|
|
|
@ -3371,8 +3371,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
|
|||
// to the levels specified on the command line. Previous level
|
||||
// will be restored when the RAII object is destroyed.
|
||||
Sema::FPFeaturesStateRAII SaveFPFeaturesState(Actions);
|
||||
FPOptions fpOptions(getLangOpts());
|
||||
Actions.CurFPFeatures.getFromOpaqueInt(fpOptions.getAsOpaqueInt());
|
||||
FPOptionsOverride NewOverrides;
|
||||
Actions.CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
|
||||
Actions.FpPragmaStack.Act(Tok.getLocation(), Sema::PSK_Reset, StringRef(),
|
||||
0 /*unused*/);
|
||||
|
||||
SourceLocation SavedPrevTokLocation = PrevTokLocation;
|
||||
ParseLexedPragmas(getCurrentClass());
|
||||
|
|
|
@ -654,8 +654,8 @@ void Parser::HandlePragmaFPContract() {
|
|||
break;
|
||||
}
|
||||
|
||||
Actions.ActOnPragmaFPContract(FPC);
|
||||
ConsumeAnnotationToken();
|
||||
SourceLocation PragmaLoc = ConsumeAnnotationToken();
|
||||
Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
|
||||
}
|
||||
|
||||
void Parser::HandlePragmaFloatControl() {
|
||||
|
@ -2935,8 +2935,8 @@ void Parser::HandlePragmaFP() {
|
|||
reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
|
||||
|
||||
if (AnnotValue->FlagKind == TokFPAnnotValue::Reassociate)
|
||||
Actions.ActOnPragmaFPReassociate(AnnotValue->FlagValue ==
|
||||
TokFPAnnotValue::On);
|
||||
Actions.ActOnPragmaFPReassociate(
|
||||
Tok.getLocation(), AnnotValue->FlagValue == TokFPAnnotValue::On);
|
||||
else {
|
||||
LangOptions::FPModeKind FPC;
|
||||
switch (AnnotValue->FlagValue) {
|
||||
|
@ -2950,7 +2950,7 @@ void Parser::HandlePragmaFP() {
|
|||
FPC = LangOptions::FPM_Fast;
|
||||
break;
|
||||
}
|
||||
Actions.ActOnPragmaFPContract(FPC);
|
||||
Actions.ActOnPragmaFPContract(Tok.getLocation(), FPC);
|
||||
}
|
||||
ConsumeAnnotationToken();
|
||||
}
|
||||
|
|
|
@ -159,9 +159,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
|||
LangOpts.getMSPointerToMemberRepresentationMethod()),
|
||||
VtorDispStack(LangOpts.getVtorDispMode()), PackStack(0),
|
||||
DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
|
||||
CodeSegStack(nullptr), FpPragmaStack(CurFPFeatures.getAsOpaqueInt()),
|
||||
CurInitSeg(nullptr), VisContext(nullptr),
|
||||
PragmaAttributeCurrentTargetDecl(nullptr),
|
||||
CodeSegStack(nullptr), FpPragmaStack(0xffffffff), CurInitSeg(nullptr),
|
||||
VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
|
||||
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
|
||||
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
|
||||
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
|
||||
|
|
|
@ -417,8 +417,10 @@ void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
|
|||
void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
|
||||
PragmaMsStackAction Action,
|
||||
PragmaFloatControlKind Value) {
|
||||
auto NewValue = FpPragmaStack.CurrentValue;
|
||||
FPOptions NewFPFeatures(NewValue);
|
||||
unsigned NewValue = FpPragmaStack.hasValue()
|
||||
? FpPragmaStack.CurrentValue
|
||||
: CurFPFeatureOverrides().getAsOpaqueInt();
|
||||
FPOptionsOverride NewFPFeatures(NewValue);
|
||||
if ((Action == PSK_Push_Set || Action == PSK_Push || Action == PSK_Pop) &&
|
||||
!(CurContext->isTranslationUnit()) && !CurContext->isNamespace()) {
|
||||
// Push and pop can only occur at file or namespace scope.
|
||||
|
@ -429,38 +431,34 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
|
|||
default:
|
||||
llvm_unreachable("invalid pragma float_control kind");
|
||||
case PFC_Precise:
|
||||
CurFPFeatures.setFPPreciseEnabled(true);
|
||||
NewValue = CurFPFeatures.getAsOpaqueInt();
|
||||
NewFPFeatures.setFPPreciseEnabled(true);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
|
||||
break;
|
||||
case PFC_NoPrecise:
|
||||
if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict)
|
||||
if (CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Strict)
|
||||
Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept);
|
||||
else if (CurFPFeatures.allowFEnvAccess())
|
||||
else if (CurFPFeatures.getAllowFEnvAccess())
|
||||
Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv);
|
||||
else
|
||||
CurFPFeatures.setFPPreciseEnabled(false);
|
||||
NewValue = CurFPFeatures.getAsOpaqueInt();
|
||||
NewFPFeatures.setFPPreciseEnabled(false);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
|
||||
break;
|
||||
case PFC_Except:
|
||||
if (!isPreciseFPEnabled())
|
||||
Diag(Loc, diag::err_pragma_fc_except_requires_precise);
|
||||
else
|
||||
CurFPFeatures.setExceptionMode(LangOptions::FPE_Strict);
|
||||
NewValue = CurFPFeatures.getAsOpaqueInt();
|
||||
NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
|
||||
break;
|
||||
case PFC_NoExcept:
|
||||
CurFPFeatures.setExceptionMode(LangOptions::FPE_Ignore);
|
||||
NewValue = CurFPFeatures.getAsOpaqueInt();
|
||||
NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
|
||||
break;
|
||||
case PFC_Push:
|
||||
if (FpPragmaStack.Stack.empty()) {
|
||||
FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(),
|
||||
CurFPFeatures.getAsOpaqueInt());
|
||||
}
|
||||
FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(),
|
||||
NewFPFeatures.getAsOpaqueInt());
|
||||
break;
|
||||
|
@ -472,9 +470,12 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
|
|||
}
|
||||
FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures.getAsOpaqueInt());
|
||||
NewValue = FpPragmaStack.CurrentValue;
|
||||
CurFPFeatures.getFromOpaqueInt(NewValue);
|
||||
break;
|
||||
}
|
||||
FPOptionsOverride NewOverrides;
|
||||
if (NewValue != FpPragmaStack.DefaultValue)
|
||||
NewOverrides.getFromOpaqueInt(NewValue);
|
||||
CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaMSPointersToMembers(
|
||||
|
@ -1003,33 +1004,70 @@ void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
|
|||
}
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaFPContract(LangOptions::FPModeKind FPC) {
|
||||
void Sema::ActOnPragmaFPContract(SourceLocation Loc,
|
||||
LangOptions::FPModeKind FPC) {
|
||||
unsigned NewValue = FpPragmaStack.hasValue()
|
||||
? FpPragmaStack.CurrentValue
|
||||
: CurFPFeatureOverrides().getAsOpaqueInt();
|
||||
FPOptionsOverride NewFPFeatures(NewValue);
|
||||
switch (FPC) {
|
||||
case LangOptions::FPM_On:
|
||||
CurFPFeatures.setAllowFPContractWithinStatement();
|
||||
NewFPFeatures.setAllowFPContractWithinStatement();
|
||||
break;
|
||||
case LangOptions::FPM_Fast:
|
||||
CurFPFeatures.setAllowFPContractAcrossStatement();
|
||||
NewFPFeatures.setAllowFPContractAcrossStatement();
|
||||
break;
|
||||
case LangOptions::FPM_Off:
|
||||
CurFPFeatures.setDisallowFPContract();
|
||||
NewFPFeatures.setDisallowFPContract();
|
||||
break;
|
||||
}
|
||||
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
|
||||
FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(),
|
||||
NewFPFeatures.getAsOpaqueInt());
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaFPReassociate(bool IsEnabled) {
|
||||
CurFPFeatures.setAllowAssociativeMath(IsEnabled);
|
||||
void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) {
|
||||
unsigned NewValue = FpPragmaStack.hasValue()
|
||||
? FpPragmaStack.CurrentValue
|
||||
: CurFPFeatureOverrides().getAsOpaqueInt();
|
||||
FPOptionsOverride NewFPFeatures(NewValue);
|
||||
NewFPFeatures.setAllowFPReassociateOverride(IsEnabled);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
|
||||
FPOptionsOverride NewOverrides(NewValue);
|
||||
CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
|
||||
}
|
||||
|
||||
void Sema::setRoundingMode(llvm::RoundingMode FPR) {
|
||||
CurFPFeatures.setRoundingMode(FPR);
|
||||
void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) {
|
||||
unsigned NewValue = FpPragmaStack.hasValue()
|
||||
? FpPragmaStack.CurrentValue
|
||||
: CurFPFeatureOverrides().getAsOpaqueInt();
|
||||
FPOptionsOverride NewFPFeatures(NewValue);
|
||||
NewFPFeatures.setRoundingModeOverride(FPR);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
|
||||
FPOptionsOverride NewOverrides(NewValue);
|
||||
CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
|
||||
}
|
||||
|
||||
void Sema::setExceptionMode(LangOptions::FPExceptionModeKind FPE) {
|
||||
CurFPFeatures.setExceptionMode(FPE);
|
||||
void Sema::setExceptionMode(SourceLocation Loc,
|
||||
LangOptions::FPExceptionModeKind FPE) {
|
||||
unsigned NewValue = FpPragmaStack.hasValue()
|
||||
? FpPragmaStack.CurrentValue
|
||||
: CurFPFeatureOverrides().getAsOpaqueInt();
|
||||
FPOptionsOverride NewFPFeatures(NewValue);
|
||||
NewFPFeatures.setFPExceptionModeOverride(FPE);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
|
||||
FPOptionsOverride NewOverrides(NewValue);
|
||||
CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {
|
||||
unsigned NewValue = FpPragmaStack.hasValue()
|
||||
? FpPragmaStack.CurrentValue
|
||||
: CurFPFeatureOverrides().getAsOpaqueInt();
|
||||
FPOptionsOverride NewFPFeatures(NewValue);
|
||||
if (IsEnabled) {
|
||||
// Verify Microsoft restriction:
|
||||
// You can't enable fenv_access unless precise semantics are enabled.
|
||||
|
@ -1037,9 +1075,13 @@ void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) {
|
|||
// pragma, or by using the /fp:precise or /fp:strict compiler options
|
||||
if (!isPreciseFPEnabled())
|
||||
Diag(Loc, diag::err_pragma_fenv_requires_precise);
|
||||
CurFPFeatures.setAllowFEnvAccess();
|
||||
NewFPFeatures.setAllowFEnvAccessOverride(true);
|
||||
} else
|
||||
CurFPFeatures.setDisallowFEnvAccess();
|
||||
NewFPFeatures.setAllowFEnvAccessOverride(false);
|
||||
NewValue = NewFPFeatures.getAsOpaqueInt();
|
||||
FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
|
||||
FPOptionsOverride NewOverrides(NewValue);
|
||||
CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
|
||||
}
|
||||
|
||||
void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
|
||||
|
|
|
@ -13526,11 +13526,11 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
|
|||
Expr *From = FromB.build(S, Loc);
|
||||
From = UnaryOperator::Create(
|
||||
S.Context, From, UO_AddrOf, S.Context.getPointerType(From->getType()),
|
||||
VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatures);
|
||||
VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
|
||||
Expr *To = ToB.build(S, Loc);
|
||||
To = UnaryOperator::Create(S.Context, To, UO_AddrOf,
|
||||
S.Context.getPointerType(To->getType()), VK_RValue,
|
||||
OK_Ordinary, Loc, false, S.CurFPFeatures);
|
||||
To = UnaryOperator::Create(
|
||||
S.Context, To, UO_AddrOf, S.Context.getPointerType(To->getType()),
|
||||
VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
|
||||
|
||||
const Type *E = T->getBaseElementTypeUnsafe();
|
||||
bool NeedsCollectableMemCpy =
|
||||
|
@ -13767,14 +13767,14 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
|
|||
Expr *Comparison = BinaryOperator::Create(
|
||||
S.Context, IterationVarRefRVal.build(S, Loc),
|
||||
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE,
|
||||
S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, S.CurFPFeatures);
|
||||
S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, S.CurFPFeatureOverrides());
|
||||
|
||||
// Create the pre-increment of the iteration variable. We can determine
|
||||
// whether the increment will overflow based on the value of the array
|
||||
// bound.
|
||||
Expr *Increment = UnaryOperator::Create(
|
||||
S.Context, IterationVarRef.build(S, Loc), UO_PreInc, SizeType, VK_LValue,
|
||||
OK_Ordinary, Loc, Upper.isMaxValue(), S.CurFPFeatures);
|
||||
OK_Ordinary, Loc, Upper.isMaxValue(), S.CurFPFeatureOverrides());
|
||||
|
||||
// Construct the loop that copies all elements of this array.
|
||||
return S.ActOnForStmt(
|
||||
|
|
|
@ -13630,7 +13630,7 @@ static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
|
|||
BinaryOperatorKind Opc, QualType ResultTy,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
bool IsCompAssign, SourceLocation OpLoc,
|
||||
FPOptions FPFeatures) {
|
||||
FPOptionsOverride FPFeatures) {
|
||||
auto &Context = S.getASTContext();
|
||||
assert((isVector(ResultTy, Context.HalfTy) ||
|
||||
isVector(ResultTy, Context.ShortTy)) &&
|
||||
|
@ -13953,9 +13953,9 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
|
|||
if (CompResultTy.isNull()) {
|
||||
if (ConvertHalfVec)
|
||||
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, false,
|
||||
OpLoc, CurFPFeatures);
|
||||
OpLoc, CurFPFeatureOverrides());
|
||||
return BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc, ResultTy,
|
||||
VK, OK, OpLoc, CurFPFeatures);
|
||||
VK, OK, OpLoc, CurFPFeatureOverrides());
|
||||
}
|
||||
|
||||
// Handle compound assignments.
|
||||
|
@ -13973,11 +13973,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
|
|||
|
||||
if (ConvertHalfVec)
|
||||
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, true,
|
||||
OpLoc, CurFPFeatures);
|
||||
OpLoc, CurFPFeatureOverrides());
|
||||
|
||||
return CompoundAssignOperator::Create(Context, LHS.get(), RHS.get(), Opc,
|
||||
ResultTy, VK, OK, OpLoc, CurFPFeatures,
|
||||
CompLHSTy, CompResultTy);
|
||||
return CompoundAssignOperator::Create(
|
||||
Context, LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, OpLoc,
|
||||
CurFPFeatureOverrides(), CompLHSTy, CompResultTy);
|
||||
}
|
||||
|
||||
/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
|
||||
|
@ -14565,8 +14565,9 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
if (Opc != UO_AddrOf && Opc != UO_Deref)
|
||||
CheckArrayAccess(Input.get());
|
||||
|
||||
auto *UO = UnaryOperator::Create(Context, Input.get(), Opc, resultType, VK,
|
||||
OK, OpLoc, CanOverflow, CurFPFeatures);
|
||||
auto *UO =
|
||||
UnaryOperator::Create(Context, Input.get(), Opc, resultType, VK, OK,
|
||||
OpLoc, CanOverflow, CurFPFeatureOverrides());
|
||||
|
||||
if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
|
||||
!isa<ArrayType>(UO->getType().getDesugaredType(Context)))
|
||||
|
|
|
@ -4487,7 +4487,8 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) {
|
|||
Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
|
||||
return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(),
|
||||
sub->getValueKind(), sub->getObjectKind(),
|
||||
uo->getOperatorLoc(), false, CurFPFeatures);
|
||||
uo->getOperatorLoc(), false,
|
||||
CurFPFeatureOverrides());
|
||||
} else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
|
||||
assert(!gse->isResultDependent());
|
||||
|
||||
|
|
|
@ -13041,7 +13041,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
|
|||
if (Fns.empty())
|
||||
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
|
||||
VK_RValue, OK_Ordinary, OpLoc, false,
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
|
||||
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
|
||||
UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
|
||||
|
@ -13049,7 +13049,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
|
|||
/*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end());
|
||||
return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray,
|
||||
Context.DependentTy, VK_RValue, OpLoc,
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
}
|
||||
|
||||
// Build an empty overload set.
|
||||
|
@ -13123,7 +13123,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
|
|||
Args[0] = Input;
|
||||
CallExpr *TheCall = CXXOperatorCallExpr::Create(
|
||||
Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc,
|
||||
CurFPFeatures, Best->IsADLCandidate);
|
||||
CurFPFeatureOverrides(), Best->IsADLCandidate);
|
||||
|
||||
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
|
||||
return ExprError();
|
||||
|
@ -13292,12 +13292,12 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
|
|||
// If there are no functions to store, just build a dependent
|
||||
// BinaryOperator or CompoundAssignment.
|
||||
if (Opc <= BO_Assign || Opc > BO_OrAssign)
|
||||
return BinaryOperator::Create(Context, Args[0], Args[1], Opc,
|
||||
Context.DependentTy, VK_RValue,
|
||||
OK_Ordinary, OpLoc, CurFPFeatures);
|
||||
return BinaryOperator::Create(
|
||||
Context, Args[0], Args[1], Opc, Context.DependentTy, VK_RValue,
|
||||
OK_Ordinary, OpLoc, CurFPFeatureOverrides());
|
||||
return CompoundAssignOperator::Create(
|
||||
Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
|
||||
OK_Ordinary, OpLoc, CurFPFeatures, Context.DependentTy,
|
||||
OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
|
||||
Context.DependentTy);
|
||||
}
|
||||
|
||||
|
@ -13311,7 +13311,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
|
|||
/*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end());
|
||||
return CXXOperatorCallExpr::Create(Context, Op, Fn, Args,
|
||||
Context.DependentTy, VK_RValue, OpLoc,
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
}
|
||||
|
||||
// Always do placeholder-like conversions on the RHS.
|
||||
|
@ -13480,7 +13480,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
|
|||
|
||||
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
|
||||
Context, ChosenOp, FnExpr.get(), Args, ResultTy, VK, OpLoc,
|
||||
CurFPFeatures, Best->IsADLCandidate);
|
||||
CurFPFeatureOverrides(), Best->IsADLCandidate);
|
||||
|
||||
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
|
||||
FnDecl))
|
||||
|
@ -13748,7 +13748,7 @@ ExprResult Sema::BuildSynthesizedThreeWayComparison(
|
|||
Expr *SyntacticForm = BinaryOperator::Create(
|
||||
Context, OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
|
||||
Result.get()->getValueKind(), Result.get()->getObjectKind(), OpLoc,
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
Expr *SemanticForm[] = {LHS, RHS, Result.get()};
|
||||
return PseudoObjectExpr::Create(Context, SyntacticForm, SemanticForm, 2);
|
||||
}
|
||||
|
@ -13779,7 +13779,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
|
|||
|
||||
return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
|
||||
Context.DependentTy, VK_RValue, RLoc,
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
}
|
||||
|
||||
// Handle placeholders on both operands.
|
||||
|
@ -13852,9 +13852,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
|
|||
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
|
||||
ResultTy = ResultTy.getNonLValueExprType(Context);
|
||||
|
||||
CXXOperatorCallExpr *TheCall =
|
||||
CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(),
|
||||
Args, ResultTy, VK, RLoc, CurFPFeatures);
|
||||
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
|
||||
Context, OO_Subscript, FnExpr.get(), Args, ResultTy, VK, RLoc,
|
||||
CurFPFeatureOverrides());
|
||||
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
|
||||
return ExprError();
|
||||
|
||||
|
@ -14476,9 +14476,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
|
|||
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
|
||||
ResultTy = ResultTy.getNonLValueExprType(Context);
|
||||
|
||||
CXXOperatorCallExpr *TheCall =
|
||||
CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(), MethodArgs,
|
||||
ResultTy, VK, RParenLoc, CurFPFeatures);
|
||||
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
|
||||
Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, VK, RParenLoc,
|
||||
CurFPFeatureOverrides());
|
||||
|
||||
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
|
||||
return true;
|
||||
|
@ -14594,8 +14594,9 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
|
|||
QualType ResultTy = Method->getReturnType();
|
||||
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
|
||||
ResultTy = ResultTy.getNonLValueExprType(Context);
|
||||
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
|
||||
Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, CurFPFeatures);
|
||||
CXXOperatorCallExpr *TheCall =
|
||||
CXXOperatorCallExpr::Create(Context, OO_Arrow, FnExpr.get(), Base,
|
||||
ResultTy, VK, OpLoc, CurFPFeatureOverrides());
|
||||
|
||||
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
|
||||
return ExprError();
|
||||
|
@ -14844,7 +14845,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
|
|||
|
||||
return UnaryOperator::Create(
|
||||
Context, SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary,
|
||||
UnOp->getOperatorLoc(), false, CurFPFeatures);
|
||||
UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
|
||||
}
|
||||
}
|
||||
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
|
||||
|
@ -14852,9 +14853,10 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
|
|||
if (SubExpr == UnOp->getSubExpr())
|
||||
return UnOp;
|
||||
|
||||
return UnaryOperator::Create(
|
||||
Context, SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()),
|
||||
VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(), false, CurFPFeatures);
|
||||
return UnaryOperator::Create(Context, SubExpr, UO_AddrOf,
|
||||
Context.getPointerType(SubExpr->getType()),
|
||||
VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(),
|
||||
false, CurFPFeatureOverrides());
|
||||
}
|
||||
|
||||
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace {
|
|||
return UnaryOperator::Create(
|
||||
S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),
|
||||
uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
|
||||
S.CurFPFeatures);
|
||||
S.CurFPFeatureOverrides());
|
||||
}
|
||||
|
||||
if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
|
||||
|
@ -446,9 +446,10 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
|
|||
ExprResult result;
|
||||
if (opcode == BO_Assign) {
|
||||
result = semanticRHS;
|
||||
syntactic = BinaryOperator::Create(
|
||||
S.Context, syntacticLHS, capturedRHS, opcode, capturedRHS->getType(),
|
||||
capturedRHS->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatures);
|
||||
syntactic = BinaryOperator::Create(S.Context, syntacticLHS, capturedRHS,
|
||||
opcode, capturedRHS->getType(),
|
||||
capturedRHS->getValueKind(), OK_Ordinary,
|
||||
opcLoc, S.CurFPFeatureOverrides());
|
||||
|
||||
} else {
|
||||
ExprResult opLHS = buildGet();
|
||||
|
@ -462,8 +463,9 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
|
|||
|
||||
syntactic = CompoundAssignOperator::Create(
|
||||
S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),
|
||||
result.get()->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatures,
|
||||
opLHS.get()->getType(), result.get()->getType());
|
||||
result.get()->getValueKind(), OK_Ordinary, opcLoc,
|
||||
S.CurFPFeatureOverrides(), opLHS.get()->getType(),
|
||||
result.get()->getType());
|
||||
}
|
||||
|
||||
// The result of the assignment, if not void, is the value set into
|
||||
|
@ -531,7 +533,7 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
|
|||
? S.Context.getTypeSize(resultType) >=
|
||||
S.Context.getTypeSize(S.Context.IntTy)
|
||||
: false,
|
||||
S.CurFPFeatures);
|
||||
S.CurFPFeatureOverrides());
|
||||
return complete(syntactic);
|
||||
}
|
||||
|
||||
|
@ -1553,7 +1555,7 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
|
|||
if (op->isTypeDependent())
|
||||
return UnaryOperator::Create(Context, op, opcode, Context.DependentTy,
|
||||
VK_RValue, OK_Ordinary, opcLoc, false,
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
|
||||
assert(UnaryOperator::isIncrementDecrementOp(opcode));
|
||||
Expr *opaqueRef = op->IgnoreParens();
|
||||
|
@ -1584,7 +1586,7 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
|
|||
if (LHS->isTypeDependent() || RHS->isTypeDependent())
|
||||
return BinaryOperator::Create(Context, LHS, RHS, opcode,
|
||||
Context.DependentTy, VK_RValue, OK_Ordinary,
|
||||
opcLoc, CurFPFeatures);
|
||||
opcLoc, CurFPFeatureOverrides());
|
||||
|
||||
// Filter out non-overload placeholder types in the RHS.
|
||||
if (RHS->getType()->isNonOverloadPlaceholderType()) {
|
||||
|
@ -1640,7 +1642,7 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
|
|||
return UnaryOperator::Create(Context, op, uop->getOpcode(), uop->getType(),
|
||||
uop->getValueKind(), uop->getObjectKind(),
|
||||
uop->getOperatorLoc(), uop->canOverflow(),
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
} else if (CompoundAssignOperator *cop
|
||||
= dyn_cast<CompoundAssignOperator>(syntax)) {
|
||||
Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
|
||||
|
@ -1648,7 +1650,7 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
|
|||
return CompoundAssignOperator::Create(
|
||||
Context, lhs, rhs, cop->getOpcode(), cop->getType(),
|
||||
cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),
|
||||
CurFPFeatures, cop->getComputationLHSType(),
|
||||
CurFPFeatureOverrides(), cop->getComputationLHSType(),
|
||||
cop->getComputationResultType());
|
||||
|
||||
} else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
|
||||
|
@ -1657,7 +1659,7 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
|
|||
return BinaryOperator::Create(Context, lhs, rhs, bop->getOpcode(),
|
||||
bop->getType(), bop->getValueKind(),
|
||||
bop->getObjectKind(), bop->getOperatorLoc(),
|
||||
CurFPFeatures);
|
||||
CurFPFeatureOverrides());
|
||||
|
||||
} else if (isa<CallExpr>(syntax)) {
|
||||
return syntax;
|
||||
|
|
|
@ -10564,8 +10564,10 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
|
|||
return getDerived().RebuildBinaryOperator(
|
||||
E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get());
|
||||
Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
|
||||
getSema().CurFPFeatures = E->getFPFeatures(getSema().getLangOpts());
|
||||
|
||||
FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
|
||||
getSema().CurFPFeatures =
|
||||
NewOverrides.applyOverrides(getSema().getLangOpts());
|
||||
getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
|
||||
return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
|
||||
LHS.get(), RHS.get());
|
||||
}
|
||||
|
@ -10619,7 +10621,10 @@ ExprResult
|
|||
TreeTransform<Derived>::TransformCompoundAssignOperator(
|
||||
CompoundAssignOperator *E) {
|
||||
Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
|
||||
getSema().CurFPFeatures = E->getFPFeatures(getSema().getLangOpts());
|
||||
FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
|
||||
getSema().CurFPFeatures =
|
||||
NewOverrides.applyOverrides(getSema().getLangOpts());
|
||||
getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
|
||||
return getDerived().TransformBinaryOperator(E);
|
||||
}
|
||||
|
||||
|
@ -11094,7 +11099,10 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
|||
return SemaRef.MaybeBindToTemporary(E);
|
||||
|
||||
Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
|
||||
getSema().CurFPFeatures = E->getFPFeatures();
|
||||
FPOptionsOverride NewOverrides(E->getFPFeatures());
|
||||
getSema().CurFPFeatures =
|
||||
NewOverrides.applyOverrides(getSema().getLangOpts());
|
||||
getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
|
||||
|
||||
return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
|
||||
E->getOperatorLoc(),
|
||||
|
|
|
@ -7843,7 +7843,9 @@ void ASTReader::InitializeSema(Sema &S) {
|
|||
// FIXME: What happens if these are changed by a module import?
|
||||
if (!FPPragmaOptions.empty()) {
|
||||
assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");
|
||||
SemaObj->CurFPFeatures = FPOptions(FPPragmaOptions[0]);
|
||||
FPOptionsOverride NewOverrides(FPPragmaOptions[0]);
|
||||
SemaObj->CurFPFeatures =
|
||||
NewOverrides.applyOverrides(SemaObj->getLangOpts());
|
||||
}
|
||||
|
||||
SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
|
||||
|
|
|
@ -706,7 +706,7 @@ void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
|
|||
E->setOperatorLoc(readSourceLocation());
|
||||
E->setCanOverflow(Record.readInt());
|
||||
if (hasFP_Features)
|
||||
E->setStoredFPFeatures(FPOptions(Record.readInt()));
|
||||
E->setStoredFPFeatures(FPOptionsOverride(Record.readInt()));
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
|
||||
|
@ -1089,7 +1089,7 @@ void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) {
|
|||
E->setRHS(Record.readSubExpr());
|
||||
E->setOperatorLoc(readSourceLocation());
|
||||
if (hasFP_Features)
|
||||
E->setStoredFPFeatures(FPOptions(Record.readInt()));
|
||||
E->setStoredFPFeatures(FPOptionsOverride(Record.readInt()));
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
|
||||
|
@ -1657,8 +1657,8 @@ void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
|
|||
void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
||||
VisitCallExpr(E);
|
||||
E->CXXOperatorCallExprBits.OperatorKind = Record.readInt();
|
||||
E->CXXOperatorCallExprBits.FPFeatures = Record.readInt();
|
||||
E->Range = Record.readSourceRange();
|
||||
E->setFPFeatures(FPOptionsOverride(Record.readInt()));
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitCXXRewrittenBinaryOperator(
|
||||
|
|
|
@ -3960,7 +3960,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
|
|||
}
|
||||
|
||||
/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
|
||||
void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
|
||||
void ASTWriter::WriteFPPragmaOptions(const FPOptionsOverride &Opts) {
|
||||
RecordData::value_type Record[] = {Opts.getAsOpaqueInt()};
|
||||
Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
|
||||
}
|
||||
|
@ -4790,7 +4790,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
|
|||
WriteReferencedSelectorsPool(SemaRef);
|
||||
WriteLateParsedTemplates(SemaRef);
|
||||
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
|
||||
WriteFPPragmaOptions(SemaRef.getCurFPFeatures());
|
||||
WriteFPPragmaOptions(SemaRef.CurFPFeatureOverrides());
|
||||
WriteOpenCLExtensions(SemaRef);
|
||||
WriteOpenCLExtensionTypes(SemaRef);
|
||||
WriteCUDAPragmas(SemaRef);
|
||||
|
|
|
@ -1545,8 +1545,8 @@ void ASTStmtWriter::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
|
|||
void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
||||
VisitCallExpr(E);
|
||||
Record.push_back(E->getOperator());
|
||||
Record.push_back(E->getFPFeatures().getAsOpaqueInt());
|
||||
Record.AddSourceRange(E->Range);
|
||||
Record.push_back(E->getFPFeatures().getAsOpaqueInt());
|
||||
Code = serialization::EXPR_CXX_OPERATOR_CALL;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,24 @@ float fma_test1(float a, float b, float c) {
|
|||
return x;
|
||||
}
|
||||
|
||||
#pragma float_control(push)
|
||||
#pragma float_control(precise, on)
|
||||
struct Distance {};
|
||||
Distance operator+(Distance, Distance);
|
||||
|
||||
template <class T>
|
||||
T add(T lhs, T rhs) {
|
||||
#pragma float_control(except, on)
|
||||
return lhs + rhs;
|
||||
}
|
||||
#pragma float_control(pop)
|
||||
|
||||
float test_OperatorCall() {
|
||||
return add(1.0f, 2.0f);
|
||||
//CHECK: llvm.experimental.constrained.fadd{{.*}}fpexcept.strict
|
||||
}
|
||||
// CHECK-LABEL define float {{.*}}test_OperatorCall{{.*}}
|
||||
|
||||
#if FENV_ON
|
||||
// expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
|
||||
#pragma STDC FENV_ACCESS ON
|
||||
|
|
|
@ -5,6 +5,17 @@
|
|||
// RUN: %clang_cc1 %s -emit-llvm -cl-mad-enable -o - | FileCheck %s -check-prefix=MAD
|
||||
// RUN: %clang_cc1 %s -emit-llvm -cl-no-signed-zeros -o - | FileCheck %s -check-prefix=NOSIGNED
|
||||
|
||||
// Check the fp options are correct with PCH.
|
||||
// RUN: %clang_cc1 %s -DGEN_PCH=1 -finclude-default-header -triple spir-unknown-unknown -emit-pch -o %t.pch
|
||||
// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -o - | FileCheck %s -check-prefix=NORMAL
|
||||
// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-fast-relaxed-math -o - | FileCheck %s -check-prefix=FAST
|
||||
// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-finite-math-only -o - | FileCheck %s -check-prefix=FINITE
|
||||
// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-unsafe-math-optimizations -o - | FileCheck %s -check-prefix=UNSAFE
|
||||
// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-mad-enable -o - | FileCheck %s -check-prefix=MAD
|
||||
// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-no-signed-zeros -o - | FileCheck %s -check-prefix=NOSIGNED
|
||||
|
||||
#if !GEN_PCH
|
||||
|
||||
float spscalardiv(float a, float b) {
|
||||
// CHECK: @spscalardiv(
|
||||
|
||||
|
@ -53,3 +64,8 @@ float spscalardiv(float a, float b) {
|
|||
// NOSIGNED: "no-nans-fp-math"="false"
|
||||
// NOSIGNED: "no-signed-zeros-fp-math"="true"
|
||||
// NOSIGNED: "unsafe-fp-math"="false"
|
||||
|
||||
#else
|
||||
// Undefine this to avoid putting it in the PCH.
|
||||
#undef GEN_PCH
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,18 @@
|
|||
// Test with pch.
|
||||
// RUN: %clang_cc1 %s -DSET -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
|
||||
// RUN: %clang_cc1 %s -ffp-contract=on -DSET -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
|
||||
// RUN: %clang_cc1 %s -menable-no-nans -DSET -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
|
||||
// RUN: %clang_cc1 %s -frounding-math -DSET -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
|
||||
// RUN: %clang_cc1 %s -ffp-exception-behavior=maytrap -DSET -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
|
||||
// RUN: %clang_cc1 %s -ffp-contract=fast -DSET -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
|
||||
// RUN: %clang_cc1 %s -DSET -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -ffp-contract=on -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-CONTRACT %s
|
||||
// RUN: %clang_cc1 %s -DPUSH -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -DPUSH -verify -include-pch %t
|
||||
// RUN: %clang_cc1 %s -DPUSH_POP -emit-pch -o %t
|
||||
|
@ -36,6 +48,7 @@ float fun(float a, float b) {
|
|||
// CHECK-LABEL: define float @fun{{.*}}
|
||||
//CHECK-EBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict
|
||||
//CHECK-EBSTRICT: llvm.experimental.constrained.fadd{{.*}}tonearest{{.*}}strict
|
||||
//CHECK-CONTRACT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
|
||||
return a * b + 2;
|
||||
}
|
||||
#pragma float_control(pop) // expected-warning {{#pragma float_control(pop, ...) failed: stack empty}}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// RUN: %clang_cc1 %s -finclude-default-header -triple spir-unknown-unknown -emit-pch -o %t.pch
|
||||
// RUN: %clang_cc1 %s -finclude-default-header -cl-no-signed-zeros -triple spir-unknown-unknown -include-pch %t.pch -fsyntax-only -verify
|
||||
// expected-no-diagnostics
|
||||
|
Loading…
Reference in New Issue