Revert "Revert "Revert "Modify FPFeatures to use delta not absolute settings"""

This reverts commit 9518763d710bfbbf9315fa88972c55898be44a0e.
Memory sanitizer fails in CGFPOptionsRAII::CGFPOptionsRAII dtor
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index a47be2d..8b96e20 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6676,7 +6676,7 @@
   return UnaryOperator::Create(
       Importer.getToContext(), ToSubExpr, E->getOpcode(), ToType,
       E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->canOverflow(),
-      E->getFPOptionsOverride());
+      E->getFPFeatures(Importer.getFromContext().getLangOpts()));
 }
 
 ExpectedStmt
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 96a7030..ebb1134 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4468,7 +4468,7 @@
 BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
                                Opcode opc, QualType ResTy, ExprValueKind VK,
                                ExprObjectKind OK, SourceLocation opLoc,
-                               FPOptionsOverride FPFeatures)
+                               FPOptions FPFeatures)
     : Expr(BinaryOperatorClass, ResTy, VK, OK) {
   BinaryOperatorBits.Opc = opc;
   assert(!isCompoundAssignmentOp() &&
@@ -4476,7 +4476,8 @@
   BinaryOperatorBits.OpLoc = opLoc;
   SubExprs[LHS] = lhs;
   SubExprs[RHS] = rhs;
-  BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+  BinaryOperatorBits.HasFPFeatures =
+      FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
   if (BinaryOperatorBits.HasFPFeatures)
     *getTrailingFPFeatures() = FPFeatures;
   setDependence(computeDependence(this));
@@ -4485,7 +4486,7 @@
 BinaryOperator::BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
                                Opcode opc, QualType ResTy, ExprValueKind VK,
                                ExprObjectKind OK, SourceLocation opLoc,
-                               FPOptionsOverride FPFeatures, bool dead2)
+                               FPOptions FPFeatures, bool dead2)
     : Expr(CompoundAssignOperatorClass, ResTy, VK, OK) {
   BinaryOperatorBits.Opc = opc;
   assert(isCompoundAssignmentOp() &&
@@ -4493,7 +4494,8 @@
   BinaryOperatorBits.OpLoc = opLoc;
   SubExprs[LHS] = lhs;
   SubExprs[RHS] = rhs;
-  BinaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+  BinaryOperatorBits.HasFPFeatures =
+      FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
   if (BinaryOperatorBits.HasFPFeatures)
     *getTrailingFPFeatures() = FPFeatures;
   setDependence(computeDependence(this));
@@ -4511,8 +4513,8 @@
                                        Expr *rhs, Opcode opc, QualType ResTy,
                                        ExprValueKind VK, ExprObjectKind OK,
                                        SourceLocation opLoc,
-                                       FPOptionsOverride FPFeatures) {
-  bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
+                                       FPOptions FPFeatures) {
+  bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
   unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
   void *Mem =
       C.Allocate(sizeof(BinaryOperator) + Extra, alignof(BinaryOperator));
@@ -4528,13 +4530,11 @@
   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,
-                               FPOptionsOverride FPFeatures,
-                               QualType CompLHSType, QualType CompResultType) {
-  bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
+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());
   unsigned Extra = sizeOfTrailingObjects(HasFPFeatures);
   void *Mem = C.Allocate(sizeof(CompoundAssignOperator) + Extra,
                          alignof(CompoundAssignOperator));
@@ -4545,7 +4545,7 @@
 
 UnaryOperator *UnaryOperator::CreateEmpty(const ASTContext &C,
                                           bool hasFPFeatures) {
-  void *Mem = C.Allocate(totalSizeToAlloc<FPOptionsOverride>(hasFPFeatures),
+  void *Mem = C.Allocate(totalSizeToAlloc<FPOptions>(hasFPFeatures),
                          alignof(UnaryOperator));
   return new (Mem) UnaryOperator(hasFPFeatures, EmptyShell());
 }
@@ -4553,12 +4553,13 @@
 UnaryOperator::UnaryOperator(const ASTContext &Ctx, Expr *input, Opcode opc,
                              QualType type, ExprValueKind VK, ExprObjectKind OK,
                              SourceLocation l, bool CanOverflow,
-                             FPOptionsOverride FPFeatures)
+                             FPOptions FPFeatures)
     : Expr(UnaryOperatorClass, type, VK, OK), Val(input) {
   UnaryOperatorBits.Opc = opc;
   UnaryOperatorBits.CanOverflow = CanOverflow;
   UnaryOperatorBits.Loc = l;
-  UnaryOperatorBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
+  UnaryOperatorBits.HasFPFeatures =
+      FPFeatures.requiresTrailingStorage(Ctx.getLangOpts());
   setDependence(computeDependence(this));
 }
 
@@ -4566,9 +4567,9 @@
                                      Opcode opc, QualType type,
                                      ExprValueKind VK, ExprObjectKind OK,
                                      SourceLocation l, bool CanOverflow,
-                                     FPOptionsOverride FPFeatures) {
-  bool HasFPFeatures = FPFeatures.requiresTrailingStorage();
-  unsigned Size = totalSizeToAlloc<FPOptionsOverride>(HasFPFeatures);
+                                     FPOptions FPFeatures) {
+  bool HasFPFeatures = FPFeatures.requiresTrailingStorage(C.getLangOpts());
+  unsigned Size = totalSizeToAlloc<FPOptions>(HasFPFeatures);
   void *Mem = C.Allocate(Size, alignof(UnaryOperator));
   return new (Mem)
       UnaryOperator(C, input, opc, type, VK, OK, l, CanOverflow, FPFeatures);
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 2889604..f9f825b 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -525,27 +525,27 @@
                                          Expr *Fn, ArrayRef<Expr *> Args,
                                          QualType Ty, ExprValueKind VK,
                                          SourceLocation OperatorLoc,
-                                         FPOptionsOverride FPFeatures,
+                                         FPOptions 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,
-                            FPOptionsOverride FPFeatures, ADLCallKind UsesADL) {
+CXXOperatorCallExpr *CXXOperatorCallExpr::Create(
+    const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn,
+    ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
+    SourceLocation OperatorLoc, FPOptions FPFeatures, ADLCallKind UsesADL) {
   // Allocate storage for the trailing objects of CallExpr.
   unsigned NumArgs = Args.size();
   unsigned SizeOfTrailingObjects =
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index f9f0553..e10fbce 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -116,17 +116,18 @@
                                          QualType Ty) {
   return BinaryOperator::Create(
       C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
-      VK_RValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
+      VK_RValue, OK_Ordinary, SourceLocation(), FPOptions(C.getLangOpts()));
 }
 
 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(),
-      FPOptionsOverride());
+  return BinaryOperator::Create(C, const_cast<Expr *>(LHS),
+                                const_cast<Expr *>(RHS), Op,
+                                C.getLogicalOperationType(), VK_RValue,
+                                OK_Ordinary, SourceLocation(),
+                                FPOptions(C.getLangOpts()));
 }
 
 CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
@@ -147,7 +148,8 @@
 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, FPOptionsOverride());
+                               /*CanOverflow*/ false,
+                               FPOptions(C.getLangOpts()));
 }
 
 ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) {
@@ -295,7 +297,7 @@
       /*QualType=*/C.VoidTy,
       /*ExprValueType=*/VK_RValue,
       /*SourceLocation=*/SourceLocation(),
-      /*FPFeatures=*/FPOptionsOverride());
+      /*FPFeatures=*/FPOptions(C.getLangOpts()));
 }
 
 /// Create a fake body for std::call_once.
@@ -455,7 +457,7 @@
       /* QualType=*/C.IntTy,
       /* ExprValueKind=*/VK_RValue,
       /* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
-      /* CanOverflow*/ false, FPOptionsOverride());
+      /* CanOverflow*/ false, FPOptions(C.getLangOpts()));
 
   // Create assignment.
   BinaryOperator *FlagAssignment = M.makeAssignment(
@@ -520,7 +522,7 @@
   Expr *DoneValue =
       UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
                             C.LongTy, VK_RValue, OK_Ordinary, SourceLocation(),
-                            /*CanOverflow*/ false, FPOptionsOverride());
+                            /*CanOverflow*/ false, FPOptions(C.getLangOpts()));
 
   BinaryOperator *B =
     M.makeAssignment(
diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp
index c08670c..a74efdc 100644
--- a/clang/lib/Basic/LangOptions.cpp
+++ b/clang/lib/Basic/LangOptions.cpp
@@ -24,7 +24,7 @@
 #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 = static_cast<unsigned>(Default);
+  Name = Default;
 #include "clang/Basic/LangOptions.def"
 
   // These options do not affect AST generation.
@@ -53,17 +53,6 @@
   return result;
 }
 
-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";
+bool FPOptions::requiresTrailingStorage(const LangOptions &LO) {
+  return getAsOpaqueInt() != defaultWithoutTrailingStorage(LO).getAsOpaqueInt();
 }
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 1bbfc27..f48f718 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2389,7 +2389,7 @@
     if (!E->canOverflow())
       return Builder.CreateNSWAdd(InVal, Amount, Name);
     return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
-        E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
+        E, InVal, IsInc, E->getFPFeatures(CGF.getLangOpts())));
   }
   llvm_unreachable("Unknown SignedOverflowBehaviorTy");
 }
@@ -2536,7 +2536,7 @@
     } else if (E->canOverflow() && type->isUnsignedIntegerType() &&
                CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
       value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
-          E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
+          E, value, isInc, E->getFPFeatures(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 @@
   BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType());
   BinOp.Ty = E->getType();
   BinOp.Opcode = BO_Sub;
-  BinOp.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
+  BinOp.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
   BinOp.E = E;
   return EmitSub(BinOp);
 }
@@ -2757,7 +2757,7 @@
     Value *Result;
     if (Oper->getType()->isFPOrFPVectorTy()) {
       CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
-          CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
+          CGF, E->getFPFeatures(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 @@
   Result.RHS = Visit(E->getRHS());
   Result.Ty  = E->getType();
   Result.Opcode = E->getOpcode();
-  Result.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
+  Result.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
   Result.E = E;
   return Result;
 }
@@ -2980,7 +2980,7 @@
   OpInfo.RHS = Visit(E->getRHS());
   OpInfo.Ty = E->getComputationResultType();
   OpInfo.Opcode = E->getOpcode();
-  OpInfo.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
+  OpInfo.FPFeatures = E->getFPFeatures(CGF.getLangOpts());
   OpInfo.E = E;
   // Load/convert the LHS.
   LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
@@ -4214,7 +4214,7 @@
     Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
     if (LHS->getType()->isFPOrFPVectorTy()) {
       CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
-          CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
+          CGF, E->getFPFeatures(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 *Zero = llvm::ConstantAggregateZero::get(LHS->getType());
     if (LHS->getType()->isFPOrFPVectorTy()) {
       CodeGenFunction::CGFPOptionsRAII FPOptsRAII(
-          CGF, E->getFPFeaturesInEffect(CGF.getLangOpts()));
+          CGF, E->getFPFeatures(CGF.getLangOpts()));
       LHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, LHS, Zero, "cmp");
       RHS = Builder.CreateFCmp(llvm::CmpInst::FCMP_UNE, RHS, Zero, "cmp");
     } else {
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 158a548..4c5311c 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1493,7 +1493,8 @@
 
   BinaryOperator *assign = BinaryOperator::Create(
       getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue,
-      OK_Ordinary, SourceLocation(), FPOptionsOverride());
+      OK_Ordinary, SourceLocation(),
+      FPOptions(getContext().getLangOpts()));
   EmitStmt(assign);
 }
 
@@ -3555,18 +3556,18 @@
   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, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(C.getLangOpts()));
 
   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, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(C.getLangOpts()));
 
   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(), FPOptionsOverride());
+      VK_LValue, SourceLocation(), FPOptions(C.getLangOpts()));
 
   EmitStmt(TheCall);
 
@@ -3640,7 +3641,7 @@
 
   UnaryOperator *SRC = UnaryOperator::Create(
       C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
-      SourceLocation(), false, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(C.getLangOpts()));
 
   CXXConstructExpr *CXXConstExpr =
     cast<CXXConstructExpr>(PID->getGetterCXXConstructor());
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 7904d4a..b380143 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -3328,11 +3328,11 @@
     // Generate condition for loop.
     BinaryOperator *Cond = BinaryOperator::Create(
         C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, OK_Ordinary,
-        S.getBeginLoc(), FPOptionsOverride());
+        S.getBeginLoc(), FPOptions(C.getLangOpts()));
     // Increment for loop counter.
     UnaryOperator *Inc = UnaryOperator::Create(
         C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
-        S.getBeginLoc(), true, FPOptionsOverride());
+        S.getBeginLoc(), true, FPOptions(C.getLangOpts()));
     auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
       // Iterate through all sections and emit a switch construct:
       // switch (IV) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index cfd32d1..23208b2 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -117,12 +117,12 @@
 
 void CodeGenFunction::SetFastMathFlags(FPOptions FPFeatures) {
   llvm::FastMathFlags FMF;
-  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.setAllowReassoc(FPFeatures.allowAssociativeMath());
+  FMF.setNoNaNs(FPFeatures.noHonorNaNs());
+  FMF.setNoInfs(FPFeatures.noHonorInfs());
+  FMF.setNoSignedZeros(FPFeatures.noSignedZeros());
+  FMF.setAllowReciprocal(FPFeatures.allowReciprocalMath());
+  FMF.setApproxFunc(FPFeatures.allowApproximateFunctions());
   FMF.setAllowContract(FPFeatures.allowFPContractAcrossStatement());
   Builder.setFastMathFlags(FMF);
 }
@@ -137,12 +137,10 @@
 
   FMFGuard.emplace(CGF.Builder);
 
-  llvm::RoundingMode NewRoundingBehavior =
-      static_cast<llvm::RoundingMode>(FPFeatures.getRoundingMode());
+  auto NewRoundingBehavior = FPFeatures.getRoundingMode();
   CGF.Builder.setDefaultConstrainedRounding(NewRoundingBehavior);
   auto NewExceptionBehavior =
-      ToConstrainedExceptMD(static_cast<LangOptions::FPExceptionModeKind>(
-          FPFeatures.getFPExceptionMode()));
+      ToConstrainedExceptMD(FPFeatures.getExceptionMode());
   CGF.Builder.setDefaultConstrainedExcept(NewExceptionBehavior);
 
   CGF.SetFastMathFlags(FPFeatures);
@@ -161,13 +159,13 @@
     if (OldValue != NewValue)
       CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
   };
-  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());
+  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());
 }
 
 CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() {
diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index e122b10..bb195ad 100644
--- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -2590,7 +2590,7 @@
   Expr *Unop = UnaryOperator::Create(
       const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
       Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(Context->getLangOpts()));
   // cast to NSConstantString *
   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
                                             CK_CPointerToObjCPointerCast, Unop);
@@ -3287,7 +3287,7 @@
       SuperRep = UnaryOperator::Create(
           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
           Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptionsOverride());
+          SourceLocation(), false, FPOptions(Context->getLangOpts()));
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                           Context->getPointerType(superType),
                                           CK_BitCast, SuperRep);
@@ -3305,7 +3305,7 @@
       SuperRep = UnaryOperator::Create(
           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
           Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptionsOverride());
+          SourceLocation(), false, FPOptions(Context->getLangOpts()));
     }
     MsgExprs.push_back(SuperRep);
     break;
@@ -3382,7 +3382,7 @@
       SuperRep = UnaryOperator::Create(
           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
           Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptionsOverride());
+          SourceLocation(), false, FPOptions(Context->getLangOpts()));
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                Context->getPointerType(superType),
                                CK_BitCast, SuperRep);
@@ -4706,9 +4706,10 @@
   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, FPOptionsOverride());
+  Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
+                                    UO_Deref, DRE->getType(), VK_LValue,
+                                    OK_Ordinary, DRE->getLocation(), false,
+                                    FPOptions(Context->getLangOpts()));
   // Need parens to enforce precedence.
   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
                                           Exp);
@@ -5299,7 +5300,7 @@
       new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
                                 VK_LValue, SourceLocation()),
       UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
-      OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
+      OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
   InitExprs.push_back(DescRefExpr);
 
   // Add initializers for any closure decl refs.
@@ -5316,9 +5317,10 @@
         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, FPOptionsOverride());
+          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
+                                      SourceLocation(), false,
+                                      FPOptions(Context->getLangOpts()));
         }
       } else if (isTopLevelBlockPointerType((*I)->getType())) {
         FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -5333,9 +5335,10 @@
         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, FPOptionsOverride());
+          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
+                                      SourceLocation(), false,
+                                      FPOptions(Context->getLangOpts()));
         }
 
       }
@@ -5376,7 +5379,7 @@
         Exp = UnaryOperator::Create(
             const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
             Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
-            SourceLocation(), false, FPOptionsOverride());
+            SourceLocation(), false, FPOptions(Context->getLangOpts()));
       Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
       InitExprs.push_back(Exp);
     }
@@ -5403,7 +5406,7 @@
   NewRep = UnaryOperator::Create(
       const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
       Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(Context->getLangOpts()));
   NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
                                     NewRep);
   // Put Paren around the call.
@@ -7491,7 +7494,7 @@
       BinaryOperator *addExpr = BinaryOperator::Create(
           *Context, castExpr, DRE, BO_Add,
           Context->getPointerType(Context->CharTy), VK_RValue, OK_Ordinary,
-          SourceLocation(), FPOptionsOverride());
+          SourceLocation(), FPOptions(Context->getLangOpts()));
       // Don't forget the parens to enforce the proper binding.
       ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
                                               SourceLocation(),
@@ -7542,9 +7545,10 @@
                                           CK_BitCast,
                                           PE);
 
-      Expr *Exp = UnaryOperator::Create(
-          const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,
-          VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
+      Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context),
+                                        castExpr, UO_Deref, IvarT, VK_LValue,
+                                        OK_Ordinary, SourceLocation(), false,
+                                        FPOptions(Context->getLangOpts()));
       PE = new (Context) ParenExpr(OldRange.getBegin(),
                                    OldRange.getEnd(),
                                    Exp);
diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 3f320dc..8b618d9 100644
--- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -2517,7 +2517,7 @@
   Expr *Unop = UnaryOperator::Create(
       const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
       Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(Context->getLangOpts()));
   // cast to NSConstantString *
   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
                                             CK_CPointerToObjCPointerCast, Unop);
@@ -2718,7 +2718,7 @@
       SuperRep = UnaryOperator::Create(
           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
           Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptionsOverride());
+          SourceLocation(), false, FPOptions(Context->getLangOpts()));
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                           Context->getPointerType(superType),
                                           CK_BitCast, SuperRep);
@@ -2736,7 +2736,7 @@
       SuperRep = UnaryOperator::Create(
           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
           Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptionsOverride());
+          SourceLocation(), false, FPOptions(Context->getLangOpts()));
     }
     MsgExprs.push_back(SuperRep);
     break;
@@ -2813,7 +2813,7 @@
       SuperRep = UnaryOperator::Create(
           const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
           Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
-          SourceLocation(), false, FPOptionsOverride());
+          SourceLocation(), false, FPOptions(Context->getLangOpts()));
       SuperRep = NoTypeInfoCStyleCastExpr(Context,
                                Context->getPointerType(superType),
                                CK_BitCast, SuperRep);
@@ -2999,7 +2999,7 @@
                                                    SourceLocation());
     BinaryOperator *lessThanExpr = BinaryOperator::Create(
         *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_RValue,
-        OK_Ordinary, SourceLocation(), FPOptionsOverride());
+        OK_Ordinary, SourceLocation(), FPOptions(Context->getLangOpts()));
     // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
     ConditionalOperator *CondExpr =
       new (Context) ConditionalOperator(lessThanExpr,
@@ -3052,7 +3052,7 @@
   Expr *DerefExpr = UnaryOperator::Create(
       const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
       Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(Context->getLangOpts()));
   CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
                                                 CK_BitCast,
                                                 DerefExpr);
@@ -3877,9 +3877,10 @@
   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, FPOptionsOverride());
+  Expr *Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), DRE,
+                                    UO_Deref, DRE->getType(), VK_LValue,
+                                    OK_Ordinary, DRE->getLocation(), false,
+                                    FPOptions(Context->getLangOpts()));
   // Need parens to enforce precedence.
   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
                                           Exp);
@@ -4439,7 +4440,7 @@
       new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
                                 VK_LValue, SourceLocation()),
       UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
-      OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
+      OK_Ordinary, SourceLocation(), false, FPOptions(Context->getLangOpts()));
   InitExprs.push_back(DescRefExpr);
 
   // Add initializers for any closure decl refs.
@@ -4456,9 +4457,10 @@
         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, FPOptionsOverride());
+          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
+                                      SourceLocation(), false,
+                                      FPOptions(Context->getLangOpts()));
         }
       } else if (isTopLevelBlockPointerType((*I)->getType())) {
         FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -4473,9 +4475,10 @@
         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, FPOptionsOverride());
+          Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+                                      UO_AddrOf, QT, VK_RValue, OK_Ordinary,
+                                      SourceLocation(), false,
+                                      FPOptions(Context->getLangOpts()));
         }
       }
       InitExprs.push_back(Exp);
@@ -4515,7 +4518,7 @@
         Exp = UnaryOperator::Create(
             const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
             Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
-            SourceLocation(), false, FPOptionsOverride());
+            SourceLocation(), false, FPOptions(Context->getLangOpts()));
       Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
       InitExprs.push_back(Exp);
     }
@@ -4534,7 +4537,7 @@
   NewRep = UnaryOperator::Create(
       const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
       Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
-      SourceLocation(), false, FPOptionsOverride());
+      SourceLocation(), false, FPOptions(Context->getLangOpts()));
   NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
                                     NewRep);
   BlockDeclRefs.clear();
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index ab94e4c..06ac545 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3371,10 +3371,8 @@
     // to the levels specified on the command line.  Previous level
     // will be restored when the RAII object is destroyed.
     Sema::FPFeaturesStateRAII SaveFPFeaturesState(Actions);
-    FPOptionsOverride NewOverrides;
-    Actions.CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
-    Actions.FpPragmaStack.Act(Tok.getLocation(), Sema::PSK_Reset, StringRef(),
-                              0 /*unused*/);
+    FPOptions fpOptions(getLangOpts());
+    Actions.CurFPFeatures.getFromOpaqueInt(fpOptions.getAsOpaqueInt());
 
     SourceLocation SavedPrevTokLocation = PrevTokLocation;
     ParseLexedPragmas(getCurrentClass());
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index 6402b31..eacb54e 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -654,8 +654,8 @@
     break;
   }
 
-  SourceLocation PragmaLoc = ConsumeAnnotationToken();
-  Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
+  Actions.ActOnPragmaFPContract(FPC);
+  ConsumeAnnotationToken();
 }
 
 void Parser::HandlePragmaFloatControl() {
@@ -2935,8 +2935,8 @@
       reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
 
   if (AnnotValue->FlagKind == TokFPAnnotValue::Reassociate)
-    Actions.ActOnPragmaFPReassociate(
-        Tok.getLocation(), AnnotValue->FlagValue == TokFPAnnotValue::On);
+    Actions.ActOnPragmaFPReassociate(AnnotValue->FlagValue ==
+                                     TokFPAnnotValue::On);
   else {
     LangOptions::FPModeKind FPC;
     switch (AnnotValue->FlagValue) {
@@ -2950,7 +2950,7 @@
       FPC = LangOptions::FPM_Fast;
       break;
     }
-    Actions.ActOnPragmaFPContract(Tok.getLocation(), FPC);
+    Actions.ActOnPragmaFPContract(FPC);
   }
   ConsumeAnnotationToken();
 }
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 2f2b521..fc3fb52 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -159,8 +159,9 @@
           LangOpts.getMSPointerToMemberRepresentationMethod()),
       VtorDispStack(LangOpts.getVtorDispMode()), PackStack(0),
       DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
-      CodeSegStack(nullptr), FpPragmaStack(0xffffffff), CurInitSeg(nullptr),
-      VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
+      CodeSegStack(nullptr), FpPragmaStack(CurFPFeatures.getAsOpaqueInt()),
+      CurInitSeg(nullptr), VisContext(nullptr),
+      PragmaAttributeCurrentTargetDecl(nullptr),
       IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
       LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
       StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index a51d1c3..977e924 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -417,10 +417,8 @@
 void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
                                    PragmaMsStackAction Action,
                                    PragmaFloatControlKind Value) {
-  unsigned NewValue = FpPragmaStack.hasValue()
-                          ? FpPragmaStack.CurrentValue
-                          : CurFPFeatureOverrides().getAsOpaqueInt();
-  FPOptionsOverride NewFPFeatures(NewValue);
+  auto NewValue = FpPragmaStack.CurrentValue;
+  FPOptions 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.
@@ -431,34 +429,38 @@
   default:
     llvm_unreachable("invalid pragma float_control kind");
   case PFC_Precise:
-    NewFPFeatures.setFPPreciseEnabled(true);
-    NewValue = NewFPFeatures.getAsOpaqueInt();
+    CurFPFeatures.setFPPreciseEnabled(true);
+    NewValue = CurFPFeatures.getAsOpaqueInt();
     FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
     break;
   case PFC_NoPrecise:
-    if (CurFPFeatures.getFPExceptionMode() == LangOptions::FPE_Strict)
+    if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict)
       Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept);
-    else if (CurFPFeatures.getAllowFEnvAccess())
+    else if (CurFPFeatures.allowFEnvAccess())
       Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv);
     else
-      NewFPFeatures.setFPPreciseEnabled(false);
-    NewValue = NewFPFeatures.getAsOpaqueInt();
+      CurFPFeatures.setFPPreciseEnabled(false);
+    NewValue = CurFPFeatures.getAsOpaqueInt();
     FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
     break;
   case PFC_Except:
     if (!isPreciseFPEnabled())
       Diag(Loc, diag::err_pragma_fc_except_requires_precise);
     else
-      NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Strict);
-    NewValue = NewFPFeatures.getAsOpaqueInt();
+      CurFPFeatures.setExceptionMode(LangOptions::FPE_Strict);
+    NewValue = CurFPFeatures.getAsOpaqueInt();
     FpPragmaStack.Act(Loc, Action, StringRef(), NewValue);
     break;
   case PFC_NoExcept:
-    NewFPFeatures.setFPExceptionModeOverride(LangOptions::FPE_Ignore);
-    NewValue = NewFPFeatures.getAsOpaqueInt();
+    CurFPFeatures.setExceptionMode(LangOptions::FPE_Ignore);
+    NewValue = CurFPFeatures.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;
@@ -470,12 +472,9 @@
     }
     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(
@@ -1004,70 +1003,33 @@
   }
 }
 
-void Sema::ActOnPragmaFPContract(SourceLocation Loc,
-                                 LangOptions::FPModeKind FPC) {
-  unsigned NewValue = FpPragmaStack.hasValue()
-                          ? FpPragmaStack.CurrentValue
-                          : CurFPFeatureOverrides().getAsOpaqueInt();
-  FPOptionsOverride NewFPFeatures(NewValue);
+void Sema::ActOnPragmaFPContract(LangOptions::FPModeKind FPC) {
   switch (FPC) {
   case LangOptions::FPM_On:
-    NewFPFeatures.setAllowFPContractWithinStatement();
+    CurFPFeatures.setAllowFPContractWithinStatement();
     break;
   case LangOptions::FPM_Fast:
-    NewFPFeatures.setAllowFPContractAcrossStatement();
+    CurFPFeatures.setAllowFPContractAcrossStatement();
     break;
   case LangOptions::FPM_Off:
-    NewFPFeatures.setDisallowFPContract();
+    CurFPFeatures.setDisallowFPContract();
     break;
   }
-  CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
-  FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(),
-                    NewFPFeatures.getAsOpaqueInt());
 }
 
-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::ActOnPragmaFPReassociate(bool IsEnabled) {
+  CurFPFeatures.setAllowAssociativeMath(IsEnabled);
 }
 
-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::setRoundingMode(llvm::RoundingMode FPR) {
+  CurFPFeatures.setRoundingMode(FPR);
 }
 
-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::setExceptionMode(LangOptions::FPExceptionModeKind FPE) {
+  CurFPFeatures.setExceptionMode(FPE);
 }
 
 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.
@@ -1075,13 +1037,9 @@
     // pragma, or by using the /fp:precise or /fp:strict compiler options
     if (!isPreciseFPEnabled())
       Diag(Loc, diag::err_pragma_fenv_requires_precise);
-    NewFPFeatures.setAllowFEnvAccessOverride(true);
+    CurFPFeatures.setAllowFEnvAccess();
   } else
-    NewFPFeatures.setAllowFEnvAccessOverride(false);
-  NewValue = NewFPFeatures.getAsOpaqueInt();
-  FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewValue);
-  FPOptionsOverride NewOverrides(NewValue);
-  CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
+    CurFPFeatures.setDisallowFEnvAccess();
 }
 
 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ef55578..a2ada20 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13526,11 +13526,11 @@
   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.CurFPFeatureOverrides());
+      VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatures);
   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.CurFPFeatureOverrides());
+  To = UnaryOperator::Create(S.Context, To, UO_AddrOf,
+                             S.Context.getPointerType(To->getType()), VK_RValue,
+                             OK_Ordinary, Loc, false, S.CurFPFeatures);
 
   const Type *E = T->getBaseElementTypeUnsafe();
   bool NeedsCollectableMemCpy =
@@ -13767,14 +13767,14 @@
   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.CurFPFeatureOverrides());
+      S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, S.CurFPFeatures);
 
   // 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.CurFPFeatureOverrides());
+      OK_Ordinary, Loc, Upper.isMaxValue(), S.CurFPFeatures);
 
   // Construct the loop that copies all elements of this array.
   return S.ActOnForStmt(
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e1433d2..bc02487 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13630,7 +13630,7 @@
                                       BinaryOperatorKind Opc, QualType ResultTy,
                                       ExprValueKind VK, ExprObjectKind OK,
                                       bool IsCompAssign, SourceLocation OpLoc,
-                                      FPOptionsOverride FPFeatures) {
+                                      FPOptions FPFeatures) {
   auto &Context = S.getASTContext();
   assert((isVector(ResultTy, Context.HalfTy) ||
           isVector(ResultTy, Context.ShortTy)) &&
@@ -13953,9 +13953,9 @@
   if (CompResultTy.isNull()) {
     if (ConvertHalfVec)
       return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, false,
-                                 OpLoc, CurFPFeatureOverrides());
+                                 OpLoc, CurFPFeatures);
     return BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc, ResultTy,
-                                  VK, OK, OpLoc, CurFPFeatureOverrides());
+                                  VK, OK, OpLoc, CurFPFeatures);
   }
 
   // Handle compound assignments.
@@ -13973,11 +13973,11 @@
 
   if (ConvertHalfVec)
     return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, true,
-                               OpLoc, CurFPFeatureOverrides());
+                               OpLoc, CurFPFeatures);
 
-  return CompoundAssignOperator::Create(
-      Context, LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, OpLoc,
-      CurFPFeatureOverrides(), CompLHSTy, CompResultTy);
+  return CompoundAssignOperator::Create(Context, LHS.get(), RHS.get(), Opc,
+                                        ResultTy, VK, OK, OpLoc, CurFPFeatures,
+                                        CompLHSTy, CompResultTy);
 }
 
 /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
@@ -14565,9 +14565,8 @@
   if (Opc != UO_AddrOf && Opc != UO_Deref)
     CheckArrayAccess(Input.get());
 
-  auto *UO =
-      UnaryOperator::Create(Context, Input.get(), Opc, resultType, VK, OK,
-                            OpLoc, CanOverflow, CurFPFeatureOverrides());
+  auto *UO = UnaryOperator::Create(Context, Input.get(), Opc, resultType, VK,
+                                   OK, OpLoc, CanOverflow, CurFPFeatures);
 
   if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
       !isa<ArrayType>(UO->getType().getDesugaredType(Context)))
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 192e418..474aba6 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -4487,8 +4487,7 @@
     Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
     return UnaryOperator::Create(Context, sub, UO_Extension, sub->getType(),
                                  sub->getValueKind(), sub->getObjectKind(),
-                                 uo->getOperatorLoc(), false,
-                                 CurFPFeatureOverrides());
+                                 uo->getOperatorLoc(), false, CurFPFeatures);
   } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
     assert(!gse->isResultDependent());
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 038b814..e57264d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -13041,7 +13041,7 @@
     if (Fns.empty())
       return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
                                    VK_RValue, OK_Ordinary, OpLoc, false,
-                                   CurFPFeatureOverrides());
+                                   CurFPFeatures);
 
     CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
     UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
@@ -13049,7 +13049,7 @@
         /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end());
     return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray,
                                        Context.DependentTy, VK_RValue, OpLoc,
-                                       CurFPFeatureOverrides());
+                                       CurFPFeatures);
   }
 
   // Build an empty overload set.
@@ -13123,7 +13123,7 @@
       Args[0] = Input;
       CallExpr *TheCall = CXXOperatorCallExpr::Create(
           Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc,
-          CurFPFeatureOverrides(), Best->IsADLCandidate);
+          CurFPFeatures, Best->IsADLCandidate);
 
       if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
         return ExprError();
@@ -13292,12 +13292,12 @@
       // 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, CurFPFeatureOverrides());
+        return BinaryOperator::Create(Context, Args[0], Args[1], Opc,
+                                      Context.DependentTy, VK_RValue,
+                                      OK_Ordinary, OpLoc, CurFPFeatures);
       return CompoundAssignOperator::Create(
           Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
-          OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
+          OK_Ordinary, OpLoc, CurFPFeatures, Context.DependentTy,
           Context.DependentTy);
     }
 
@@ -13311,7 +13311,7 @@
         /*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end());
     return CXXOperatorCallExpr::Create(Context, Op, Fn, Args,
                                        Context.DependentTy, VK_RValue, OpLoc,
-                                       CurFPFeatureOverrides());
+                                       CurFPFeatures);
   }
 
   // Always do placeholder-like conversions on the RHS.
@@ -13480,7 +13480,7 @@
 
         CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
             Context, ChosenOp, FnExpr.get(), Args, ResultTy, VK, OpLoc,
-            CurFPFeatureOverrides(), Best->IsADLCandidate);
+            CurFPFeatures, Best->IsADLCandidate);
 
         if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
                                 FnDecl))
@@ -13748,7 +13748,7 @@
   Expr *SyntacticForm = BinaryOperator::Create(
       Context, OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
       Result.get()->getValueKind(), Result.get()->getObjectKind(), OpLoc,
-      CurFPFeatureOverrides());
+      CurFPFeatures);
   Expr *SemanticForm[] = {LHS, RHS, Result.get()};
   return PseudoObjectExpr::Create(Context, SyntacticForm, SemanticForm, 2);
 }
@@ -13779,7 +13779,7 @@
 
     return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
                                        Context.DependentTy, VK_RValue, RLoc,
-                                       CurFPFeatureOverrides());
+                                       CurFPFeatures);
   }
 
   // Handle placeholders on both operands.
@@ -13852,9 +13852,9 @@
         ExprValueKind VK = Expr::getValueKindForType(ResultTy);
         ResultTy = ResultTy.getNonLValueExprType(Context);
 
-        CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
-            Context, OO_Subscript, FnExpr.get(), Args, ResultTy, VK, RLoc,
-            CurFPFeatureOverrides());
+        CXXOperatorCallExpr *TheCall =
+            CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(),
+                                        Args, ResultTy, VK, RLoc, CurFPFeatures);
         if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
           return ExprError();
 
@@ -14476,9 +14476,9 @@
   ExprValueKind VK = Expr::getValueKindForType(ResultTy);
   ResultTy = ResultTy.getNonLValueExprType(Context);
 
-  CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
-      Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, VK, RParenLoc,
-      CurFPFeatureOverrides());
+  CXXOperatorCallExpr *TheCall =
+      CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(), MethodArgs,
+                                  ResultTy, VK, RParenLoc, CurFPFeatures);
 
   if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
     return true;
@@ -14594,9 +14594,8 @@
   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, CurFPFeatureOverrides());
+  CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
+      Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, CurFPFeatures);
 
   if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
     return ExprError();
@@ -14845,7 +14844,7 @@
 
         return UnaryOperator::Create(
             Context, SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary,
-            UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
+            UnOp->getOperatorLoc(), false, CurFPFeatures);
       }
     }
     Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -14853,10 +14852,9 @@
     if (SubExpr == UnOp->getSubExpr())
       return UnOp;
 
-    return UnaryOperator::Create(Context, SubExpr, UO_AddrOf,
-                                 Context.getPointerType(SubExpr->getType()),
-                                 VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(),
-                                 false, CurFPFeatureOverrides());
+    return UnaryOperator::Create(
+        Context, SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()),
+        VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(), false, CurFPFeatures);
   }
 
   if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index d17599a..da77720 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -130,7 +130,7 @@
         return UnaryOperator::Create(
             S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),
             uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
-            S.CurFPFeatureOverrides());
+            S.CurFPFeatures);
       }
 
       if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
@@ -446,10 +446,9 @@
   ExprResult result;
   if (opcode == BO_Assign) {
     result = semanticRHS;
-    syntactic = BinaryOperator::Create(S.Context, syntacticLHS, capturedRHS,
-                                       opcode, capturedRHS->getType(),
-                                       capturedRHS->getValueKind(), OK_Ordinary,
-                                       opcLoc, S.CurFPFeatureOverrides());
+    syntactic = BinaryOperator::Create(
+        S.Context, syntacticLHS, capturedRHS, opcode, capturedRHS->getType(),
+        capturedRHS->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatures);
 
   } else {
     ExprResult opLHS = buildGet();
@@ -463,9 +462,8 @@
 
     syntactic = CompoundAssignOperator::Create(
         S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),
-        result.get()->getValueKind(), OK_Ordinary, opcLoc,
-        S.CurFPFeatureOverrides(), opLHS.get()->getType(),
-        result.get()->getType());
+        result.get()->getValueKind(), OK_Ordinary, opcLoc, S.CurFPFeatures,
+        opLHS.get()->getType(), result.get()->getType());
   }
 
   // The result of the assignment, if not void, is the value set into
@@ -533,7 +531,7 @@
                                 ? S.Context.getTypeSize(resultType) >=
                                       S.Context.getTypeSize(S.Context.IntTy)
                                 : false,
-                            S.CurFPFeatureOverrides());
+                            S.CurFPFeatures);
   return complete(syntactic);
 }
 
@@ -1555,7 +1553,7 @@
   if (op->isTypeDependent())
     return UnaryOperator::Create(Context, op, opcode, Context.DependentTy,
                                  VK_RValue, OK_Ordinary, opcLoc, false,
-                                 CurFPFeatureOverrides());
+                                 CurFPFeatures);
 
   assert(UnaryOperator::isIncrementDecrementOp(opcode));
   Expr *opaqueRef = op->IgnoreParens();
@@ -1586,7 +1584,7 @@
   if (LHS->isTypeDependent() || RHS->isTypeDependent())
     return BinaryOperator::Create(Context, LHS, RHS, opcode,
                                   Context.DependentTy, VK_RValue, OK_Ordinary,
-                                  opcLoc, CurFPFeatureOverrides());
+                                  opcLoc, CurFPFeatures);
 
   // Filter out non-overload placeholder types in the RHS.
   if (RHS->getType()->isNonOverloadPlaceholderType()) {
@@ -1642,7 +1640,7 @@
     return UnaryOperator::Create(Context, op, uop->getOpcode(), uop->getType(),
                                  uop->getValueKind(), uop->getObjectKind(),
                                  uop->getOperatorLoc(), uop->canOverflow(),
-                                 CurFPFeatureOverrides());
+                                 CurFPFeatures);
   } else if (CompoundAssignOperator *cop
                = dyn_cast<CompoundAssignOperator>(syntax)) {
     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
@@ -1650,7 +1648,7 @@
     return CompoundAssignOperator::Create(
         Context, lhs, rhs, cop->getOpcode(), cop->getType(),
         cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),
-        CurFPFeatureOverrides(), cop->getComputationLHSType(),
+        CurFPFeatures, cop->getComputationLHSType(),
         cop->getComputationResultType());
 
   } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
@@ -1659,7 +1657,7 @@
     return BinaryOperator::Create(Context, lhs, rhs, bop->getOpcode(),
                                   bop->getType(), bop->getValueKind(),
                                   bop->getObjectKind(), bop->getOperatorLoc(),
-                                  CurFPFeatureOverrides());
+                                  CurFPFeatures);
 
   } else if (isa<CallExpr>(syntax)) {
     return syntax;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 65d1182..ce9c303 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10564,10 +10564,8 @@
     return getDerived().RebuildBinaryOperator(
         E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get());
   Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
-  FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
-  getSema().CurFPFeatures =
-      NewOverrides.applyOverrides(getSema().getLangOpts());
-  getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
+  getSema().CurFPFeatures = E->getFPFeatures(getSema().getLangOpts());
+
   return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
                                             LHS.get(), RHS.get());
 }
@@ -10621,10 +10619,7 @@
 TreeTransform<Derived>::TransformCompoundAssignOperator(
                                                       CompoundAssignOperator *E) {
   Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
-  FPOptionsOverride NewOverrides(E->getFPFeatures(getSema().getLangOpts()));
-  getSema().CurFPFeatures =
-      NewOverrides.applyOverrides(getSema().getLangOpts());
-  getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
+  getSema().CurFPFeatures = E->getFPFeatures(getSema().getLangOpts());
   return getDerived().TransformBinaryOperator(E);
 }
 
@@ -11099,10 +11094,7 @@
     return SemaRef.MaybeBindToTemporary(E);
 
   Sema::FPFeaturesStateRAII FPFeaturesState(getSema());
-  FPOptionsOverride NewOverrides(E->getFPFeatures());
-  getSema().CurFPFeatures =
-      NewOverrides.applyOverrides(getSema().getLangOpts());
-  getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt();
+  getSema().CurFPFeatures = E->getFPFeatures();
 
   return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
                                                  E->getOperatorLoc(),
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index ac45d1e..4dd2054 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7843,9 +7843,7 @@
   // FIXME: What happens if these are changed by a module import?
   if (!FPPragmaOptions.empty()) {
     assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");
-    FPOptionsOverride NewOverrides(FPPragmaOptions[0]);
-    SemaObj->CurFPFeatures =
-        NewOverrides.applyOverrides(SemaObj->getLangOpts());
+    SemaObj->CurFPFeatures = FPOptions(FPPragmaOptions[0]);
   }
 
   SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 9d4a0b6..0c37983 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -706,7 +706,7 @@
   E->setOperatorLoc(readSourceLocation());
   E->setCanOverflow(Record.readInt());
   if (hasFP_Features)
-    E->setStoredFPFeatures(FPOptionsOverride(Record.readInt()));
+    E->setStoredFPFeatures(FPOptions(Record.readInt()));
 }
 
 void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
@@ -1089,7 +1089,7 @@
   E->setRHS(Record.readSubExpr());
   E->setOperatorLoc(readSourceLocation());
   if (hasFP_Features)
-    E->setStoredFPFeatures(FPOptionsOverride(Record.readInt()));
+    E->setStoredFPFeatures(FPOptions(Record.readInt()));
 }
 
 void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
@@ -1657,8 +1657,8 @@
 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(
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 6f364df..2a17360 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -3960,7 +3960,7 @@
 }
 
 /// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
-void ASTWriter::WriteFPPragmaOptions(const FPOptionsOverride &Opts) {
+void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
   RecordData::value_type Record[] = {Opts.getAsOpaqueInt()};
   Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
 }
@@ -4790,7 +4790,7 @@
   WriteReferencedSelectorsPool(SemaRef);
   WriteLateParsedTemplates(SemaRef);
   WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
-  WriteFPPragmaOptions(SemaRef.CurFPFeatureOverrides());
+  WriteFPPragmaOptions(SemaRef.getCurFPFeatures());
   WriteOpenCLExtensions(SemaRef);
   WriteOpenCLExtensionTypes(SemaRef);
   WriteCUDAPragmas(SemaRef);
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index abc6081..b13d0df 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1545,8 +1545,8 @@
 void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
   VisitCallExpr(E);
   Record.push_back(E->getOperator());
-  Record.AddSourceRange(E->Range);
   Record.push_back(E->getFPFeatures().getAsOpaqueInt());
+  Record.AddSourceRange(E->Range);
   Code = serialization::EXPR_CXX_OPERATOR_CALL;
 }