diff options
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 49 | 
1 files changed, 37 insertions, 12 deletions
| diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1bb252d2d1c..ddc48de2c67 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1437,7 +1437,8 @@ static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,                                      EvalInfo &Info);  static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);  static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); -static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info); +static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result, +                           EvalInfo &Info);  static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result);  //===----------------------------------------------------------------------===// @@ -4743,7 +4744,10 @@ public:      case CK_AtomicToNonAtomic: {        APValue AtomicVal; -      if (!EvaluateAtomic(E->getSubExpr(), AtomicVal, Info)) +      // This does not need to be done in place even for class/array types: +      // atomic-to-non-atomic conversion implies copying the object +      // representation. +      if (!Evaluate(AtomicVal, Info, E->getSubExpr()))          return false;        return DerivedSuccess(AtomicVal, E);      } @@ -9689,10 +9693,11 @@ bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) {  namespace {  class AtomicExprEvaluator :      public ExprEvaluatorBase<AtomicExprEvaluator> { +  const LValue *This;    APValue &Result;  public: -  AtomicExprEvaluator(EvalInfo &Info, APValue &Result) -      : ExprEvaluatorBaseTy(Info), Result(Result) {} +  AtomicExprEvaluator(EvalInfo &Info, const LValue *This, APValue &Result) +      : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {}    bool Success(const APValue &V, const Expr *E) {      Result = V; @@ -9702,7 +9707,10 @@ public:    bool ZeroInitialization(const Expr *E) {      ImplicitValueInitExpr VIE(          E->getType()->castAs<AtomicType>()->getValueType()); -    return Evaluate(Result, Info, &VIE); +    // For atomic-qualified class (and array) types in C++, initialize the +    // _Atomic-wrapped subobject directly, in-place. +    return This ? EvaluateInPlace(Result, Info, *This, &VIE) +                : Evaluate(Result, Info, &VIE);    }    bool VisitCastExpr(const CastExpr *E) { @@ -9710,15 +9718,17 @@ public:      default:        return ExprEvaluatorBaseTy::VisitCastExpr(E);      case CK_NonAtomicToAtomic: -      return Evaluate(Result, Info, E->getSubExpr()); +      return This ? EvaluateInPlace(Result, Info, *This, E->getSubExpr()) +                  : Evaluate(Result, Info, E->getSubExpr());      }    }  };  } // end anonymous namespace -static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info) { +static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result, +                           EvalInfo &Info) {    assert(E->isRValue() && E->getType()->isAtomicType()); -  return AtomicExprEvaluator(Info, Result).Visit(E); +  return AtomicExprEvaluator(Info, This, Result).Visit(E);  }  //===----------------------------------------------------------------------===// @@ -9823,8 +9833,17 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {      if (!EvaluateVoid(E, Info))        return false;    } else if (T->isAtomicType()) { -    if (!EvaluateAtomic(E, Result, Info)) -      return false; +    QualType Unqual = T.getAtomicUnqualifiedType(); +    if (Unqual->isArrayType() || Unqual->isRecordType()) { +      LValue LV; +      LV.set(E, Info.CurrentCall->Index); +      APValue &Value = Info.CurrentCall->createTemporary(E, false); +      if (!EvaluateAtomic(E, &LV, Value, Info)) +        return false; +    } else { +      if (!EvaluateAtomic(E, nullptr, Result, Info)) +        return false; +    }    } else if (Info.getLangOpts().CPlusPlus11) {      Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType();      return false; @@ -9849,10 +9868,16 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This,    if (E->isRValue()) {      // Evaluate arrays and record types in-place, so that later initializers can      // refer to earlier-initialized members of the object. -    if (E->getType()->isArrayType()) +    QualType T = E->getType(); +    if (T->isArrayType())        return EvaluateArray(E, This, Result, Info); -    else if (E->getType()->isRecordType()) +    else if (T->isRecordType())        return EvaluateRecord(E, This, Result, Info); +    else if (T->isAtomicType()) { +      QualType Unqual = T.getAtomicUnqualifiedType(); +      if (Unqual->isArrayType() || Unqual->isRecordType()) +        return EvaluateAtomic(E, &This, Result, Info); +    }    }    // For any other type, in-place evaluation is unimportant. | 

