forked from OSchip/llvm-project
Model converted constant expressions as full-expressions.
This is groundwork for C++20's P0784R7, where non-trivial destructors can be constexpr, so we need ExprWithCleanups markers in constant expressions. No functionality change intended. llvm-svn: 372359
This commit is contained in:
parent
0c3d4cfbad
commit
40c3d6e335
|
@ -4678,8 +4678,10 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
|
|||
ExprResult AssignedVal;
|
||||
EnumAvailabilityDiags.emplace_back(*this);
|
||||
|
||||
EnterExpressionEvaluationContext ConstantEvaluated(
|
||||
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
||||
if (TryConsumeToken(tok::equal, EqualLoc)) {
|
||||
AssignedVal = ParseConstantExpression();
|
||||
AssignedVal = ParseConstantExpressionInExprEvalContext();
|
||||
if (AssignedVal.isInvalid())
|
||||
SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
|
||||
}
|
||||
|
|
|
@ -257,8 +257,18 @@ isPointerConversionToVoidPointer(ASTContext& Context) const {
|
|||
|
||||
/// Skip any implicit casts which could be either part of a narrowing conversion
|
||||
/// or after one in an implicit conversion.
|
||||
static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
|
||||
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Converted)) {
|
||||
static const Expr *IgnoreNarrowingConversion(ASTContext &Ctx,
|
||||
const Expr *Converted) {
|
||||
// We can have cleanups wrapping the converted expression; these need to be
|
||||
// preserved so that destructors run if necessary.
|
||||
if (auto *EWC = dyn_cast<ExprWithCleanups>(Converted)) {
|
||||
Expr *Inner =
|
||||
const_cast<Expr *>(IgnoreNarrowingConversion(Ctx, EWC->getSubExpr()));
|
||||
return ExprWithCleanups::Create(Ctx, Inner, EWC->cleanupsHaveSideEffects(),
|
||||
EWC->getObjects());
|
||||
}
|
||||
|
||||
while (auto *ICE = dyn_cast<ImplicitCastExpr>(Converted)) {
|
||||
switch (ICE->getCastKind()) {
|
||||
case CK_NoOp:
|
||||
case CK_IntegralCast:
|
||||
|
@ -332,7 +342,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
|
|||
if (IgnoreFloatToIntegralConversion)
|
||||
return NK_Not_Narrowing;
|
||||
llvm::APSInt IntConstantValue;
|
||||
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
|
||||
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
|
||||
assert(Initializer && "Unknown conversion expression");
|
||||
|
||||
// If it's value-dependent, we can't tell whether it's narrowing.
|
||||
|
@ -370,7 +380,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
|
|||
if (FromType->isRealFloatingType() && ToType->isRealFloatingType() &&
|
||||
Ctx.getFloatingTypeOrder(FromType, ToType) == 1) {
|
||||
// FromType is larger than ToType.
|
||||
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
|
||||
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
|
||||
|
||||
// If it's value-dependent, we can't tell whether it's narrowing.
|
||||
if (Initializer->isValueDependent())
|
||||
|
@ -416,7 +426,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
|
|||
(FromSigned && !ToSigned)) {
|
||||
// Not all values of FromType can be represented in ToType.
|
||||
llvm::APSInt InitializerValue;
|
||||
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
|
||||
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
|
||||
|
||||
// If it's value-dependent, we can't tell whether it's narrowing.
|
||||
if (Initializer->isValueDependent())
|
||||
|
@ -5465,6 +5475,14 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
|
|||
if (Result.isInvalid())
|
||||
return Result;
|
||||
|
||||
// C++2a [intro.execution]p5:
|
||||
// A full-expression is [...] a constant-expression [...]
|
||||
Result =
|
||||
S.ActOnFinishFullExpr(Result.get(), From->getExprLoc(),
|
||||
/*DiscardedValue=*/false, /*IsConstexpr=*/true);
|
||||
if (Result.isInvalid())
|
||||
return Result;
|
||||
|
||||
// Check for a narrowing implicit conversion.
|
||||
APValue PreNarrowingValue;
|
||||
QualType PreNarrowingType;
|
||||
|
|
|
@ -430,45 +430,44 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
|
|||
|
||||
// If we're not inside a switch, let the 'case' statement handling diagnose
|
||||
// this. Just clean up after the expression as best we can.
|
||||
if (!getCurFunction()->SwitchStack.empty()) {
|
||||
Expr *CondExpr =
|
||||
getCurFunction()->SwitchStack.back().getPointer()->getCond();
|
||||
if (!CondExpr)
|
||||
return ExprError();
|
||||
QualType CondType = CondExpr->getType();
|
||||
if (getCurFunction()->SwitchStack.empty())
|
||||
return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
|
||||
getLangOpts().CPlusPlus11);
|
||||
|
||||
auto CheckAndFinish = [&](Expr *E) {
|
||||
if (CondType->isDependentType() || E->isTypeDependent())
|
||||
return ExprResult(E);
|
||||
Expr *CondExpr =
|
||||
getCurFunction()->SwitchStack.back().getPointer()->getCond();
|
||||
if (!CondExpr)
|
||||
return ExprError();
|
||||
QualType CondType = CondExpr->getType();
|
||||
|
||||
if (getLangOpts().CPlusPlus11) {
|
||||
// C++11 [stmt.switch]p2: the constant-expression shall be a converted
|
||||
// constant expression of the promoted type of the switch condition.
|
||||
llvm::APSInt TempVal;
|
||||
return CheckConvertedConstantExpression(E, CondType, TempVal,
|
||||
CCEK_CaseValue);
|
||||
}
|
||||
auto CheckAndFinish = [&](Expr *E) {
|
||||
if (CondType->isDependentType() || E->isTypeDependent())
|
||||
return ExprResult(E);
|
||||
|
||||
ExprResult ER = E;
|
||||
if (!E->isValueDependent())
|
||||
ER = VerifyIntegerConstantExpression(E);
|
||||
if (!ER.isInvalid())
|
||||
ER = DefaultLvalueConversion(ER.get());
|
||||
if (!ER.isInvalid())
|
||||
ER = ImpCastExprToType(ER.get(), CondType, CK_IntegralCast);
|
||||
return ER;
|
||||
};
|
||||
if (getLangOpts().CPlusPlus11) {
|
||||
// C++11 [stmt.switch]p2: the constant-expression shall be a converted
|
||||
// constant expression of the promoted type of the switch condition.
|
||||
llvm::APSInt TempVal;
|
||||
return CheckConvertedConstantExpression(E, CondType, TempVal,
|
||||
CCEK_CaseValue);
|
||||
}
|
||||
|
||||
ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
|
||||
if (Converted.get() == Val.get())
|
||||
Converted = CheckAndFinish(Val.get());
|
||||
if (Converted.isInvalid())
|
||||
return ExprError();
|
||||
Val = Converted;
|
||||
}
|
||||
ExprResult ER = E;
|
||||
if (!E->isValueDependent())
|
||||
ER = VerifyIntegerConstantExpression(E);
|
||||
if (!ER.isInvalid())
|
||||
ER = DefaultLvalueConversion(ER.get());
|
||||
if (!ER.isInvalid())
|
||||
ER = ImpCastExprToType(ER.get(), CondType, CK_IntegralCast);
|
||||
if (!ER.isInvalid())
|
||||
ER = ActOnFinishFullExpr(ER.get(), ER.get()->getExprLoc(), false);
|
||||
return ER;
|
||||
};
|
||||
|
||||
return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
|
||||
getLangOpts().CPlusPlus11);
|
||||
ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
|
||||
if (Converted.get() == Val.get())
|
||||
Converted = CheckAndFinish(Val.get());
|
||||
return Converted;
|
||||
}
|
||||
|
||||
StmtResult
|
||||
|
|
|
@ -6431,8 +6431,11 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
}
|
||||
|
||||
// If either the parameter has a dependent type or the argument is
|
||||
// type-dependent, there's nothing we can check now.
|
||||
if (ParamType->isDependentType() || Arg->isTypeDependent()) {
|
||||
// type-dependent, there's nothing we can check now. The argument only
|
||||
// contains an unexpanded pack during partial ordering, and there's
|
||||
// nothing more we can check in that case.
|
||||
if (ParamType->isDependentType() || Arg->isTypeDependent() ||
|
||||
Arg->containsUnexpandedParameterPack()) {
|
||||
// Force the argument to the type of the parameter to maintain invariants.
|
||||
auto *PE = dyn_cast<PackExpansionExpr>(Arg);
|
||||
if (PE)
|
||||
|
|
Loading…
Reference in New Issue