// Parse the non-empty comma-separated list of expressions.
do {
- bool ShouldEnter = attributeParsedArgsUnevaluated(*AttrName);
+ bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
EnterExpressionEvaluationContext Unevaluated(
- Actions, Sema::Unevaluated, /*LambdaContextDecl=*/nullptr,
- /*IsDecltype=*/false, ShouldEnter);
+ Actions, Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated,
+ /*LambdaContextDecl=*/nullptr,
+ /*IsDecltype=*/false);
ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
const EnableIfAttr *A, const Decl *Tmpl, Decl *New) {
Expr *Cond = nullptr;
{
- EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ ContextRAII SwitchContext(*this, cast<FunctionDecl>(New));
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated);
ExprResult Result = S.SubstExpr(A->getCond(), TemplateArgs);
if (Result.isInvalid())
return;
Foo<double>().bar(1);
}
}
+
+namespace instantiate_constexpr_in_enable_if {
+ template<typename T> struct X {
+ static constexpr bool ok() { return true; }
+ void f() __attribute__((enable_if(ok(), "")));
+ };
+ void g() { X<int>().f(); }
+}