mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-12-28 05:55:27 +01:00
Pull in r295886 from upstream clang trunk (by Richard Smith):
PR32034: Evaluate _Atomic(T) in-place when T is a class or array type. This is necessary in order for the evaluation of an _Atomic initializer for those types to have an associated object, which an initializer for class or array type needs. This fixes an assertion when building recent versions of LinuxCNC. Reported by: trasz PR: 220883 MFC after: 1 week
This commit is contained in:
parent
5eedcb0969
commit
754301e94f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=321342
@ -1404,7 +1404,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);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -4691,7 +4692,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);
|
||||
}
|
||||
@ -9565,10 +9569,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;
|
||||
@ -9578,7 +9583,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) {
|
||||
@ -9586,15 +9594,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);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -9699,8 +9709,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))
|
||||
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;
|
||||
@ -9725,10 +9744,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.
|
||||
|
Loading…
Reference in New Issue
Block a user