Commit 98532e41 authored by Tom Stellard's avatar Tom Stellard
Browse files

Merging r310905 and r310994:

------------------------------------------------------------------------
r310905 | rnk | 2017-08-14 18:17:47 -0700 (Mon, 14 Aug 2017) | 11 lines

Avoid PointerIntPair of constexpr EvalInfo structs

They are stack allocated, so their alignment is not to be trusted.
32-bit MSVC only guarantees 4 byte stack alignment, even though alignof
would tell you otherwise. I tried fixing this with __declspec align, but
that apparently upsets GCC. Hopefully this version will satisfy all
compilers.

See PR32018 for some info about the mingw issues.

Should supercede https://reviews.llvm.org/D34873
------------------------------------------------------------------------

------------------------------------------------------------------------
r310994 | chandlerc | 2017-08-16 00:22:49 -0700 (Wed, 16 Aug 2017) | 6 lines

Fix a UBSan failure where this boolean was copied when uninitialized.

When r310905 moved the pointer and bool out of a PointerIntPair, it made
them end up uninitialized and caused UBSan failures when copying the
uninitialized boolean. However, making the pointer be null should avoid
the reference to the boolean entirely.
------------------------------------------------------------------------

llvm-svn: 318225
parent 9ad76aac
Loading
Loading
Loading
Loading
+11 −13
Original line number Diff line number Diff line
@@ -537,7 +537,7 @@ namespace {
  /// rules.  For example, the RHS of (0 && foo()) is not evaluated.  We can
  /// evaluate the expression regardless of what the RHS is, but C only allows
  /// certain things in certain situations.
  struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EvalInfo {
  struct EvalInfo {
    ASTContext &Ctx;

    /// EvalStatus - Contains information about the evaluation.
@@ -977,24 +977,22 @@ namespace {
  /// RAII object used to optionally suppress diagnostics and side-effects from
  /// a speculative evaluation.
  class SpeculativeEvaluationRAII {
    /// Pair of EvalInfo, and a bit that stores whether or not we were
    /// speculatively evaluating when we created this RAII.
    llvm::PointerIntPair<EvalInfo *, 1, bool> InfoAndOldSpecEval;
    Expr::EvalStatus Old;
    EvalInfo *Info = nullptr;
    Expr::EvalStatus OldStatus;
    bool OldIsSpeculativelyEvaluating;

    void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) {
      InfoAndOldSpecEval = Other.InfoAndOldSpecEval;
      Old = Other.Old;
      Other.InfoAndOldSpecEval.setPointer(nullptr);
      Info = Other.Info;
      OldStatus = Other.OldStatus;
      Other.Info = nullptr;
    }

    void maybeRestoreState() {
      EvalInfo *Info = InfoAndOldSpecEval.getPointer();
      if (!Info)
        return;

      Info->EvalStatus = Old;
      Info->IsSpeculativelyEvaluating = InfoAndOldSpecEval.getInt();
      Info->EvalStatus = OldStatus;
      Info->IsSpeculativelyEvaluating = OldIsSpeculativelyEvaluating;
    }

  public:
@@ -1002,8 +1000,8 @@ namespace {

    SpeculativeEvaluationRAII(
        EvalInfo &Info, SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr)
        : InfoAndOldSpecEval(&Info, Info.IsSpeculativelyEvaluating),
          Old(Info.EvalStatus) {
        : Info(&Info), OldStatus(Info.EvalStatus),
          OldIsSpeculativelyEvaluating(Info.IsSpeculativelyEvaluating) {
      Info.EvalStatus.Diag = NewDiag;
      Info.IsSpeculativelyEvaluating = true;
    }