r372359 - Model converted constant expressions as full-expressions.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 19 15:00:16 PDT 2019
Author: rsmith
Date: Thu Sep 19 15:00:16 2019
New Revision: 372359
URL: http://llvm.org/viewvc/llvm-project?rev=372359&view=rev
Log:
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.
Modified:
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=372359&r1=372358&r2=372359&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Sep 19 15:00:16 2019
@@ -4678,8 +4678,10 @@ void Parser::ParseEnumBody(SourceLocatio
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);
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=372359&r1=372358&r2=372359&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Sep 19 15:00:16 2019
@@ -257,8 +257,18 @@ isPointerConversionToVoidPointer(ASTCont
/// 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
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
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
(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 CheckConvertedConstant
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;
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=372359&r1=372358&r2=372359&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Sep 19 15:00:16 2019
@@ -430,45 +430,44 @@ Sema::ActOnCaseExpr(SourceLocation CaseL
// 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();
-
- auto CheckAndFinish = [&](Expr *E) {
- if (CondType->isDependentType() || E->isTypeDependent())
- return ExprResult(E);
-
- 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 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;
- };
-
- ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
- if (Converted.get() == Val.get())
- Converted = CheckAndFinish(Val.get());
- if (Converted.isInvalid())
- return ExprError();
- Val = Converted;
- }
-
- return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
- getLangOpts().CPlusPlus11);
+ if (getCurFunction()->SwitchStack.empty())
+ return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
+ getLangOpts().CPlusPlus11);
+
+ Expr *CondExpr =
+ getCurFunction()->SwitchStack.back().getPointer()->getCond();
+ if (!CondExpr)
+ return ExprError();
+ QualType CondType = CondExpr->getType();
+
+ auto CheckAndFinish = [&](Expr *E) {
+ if (CondType->isDependentType() || E->isTypeDependent())
+ return ExprResult(E);
+
+ 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 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;
+ };
+
+ ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
+ if (Converted.get() == Val.get())
+ Converted = CheckAndFinish(Val.get());
+ return Converted;
}
StmtResult
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=372359&r1=372358&r2=372359&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Sep 19 15:00:16 2019
@@ -6431,8 +6431,11 @@ ExprResult Sema::CheckTemplateArgument(N
}
// 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)
More information about the cfe-commits
mailing list