mirror of https://github.com/microsoft/clang.git
Try contextually converting condition of constexpr if to Boolean value
Summary: C++1z 6.4.1/p2: If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool [...] C++1z 5.20/p4: [...] A contextually converted constant expression of type bool is an expression, contextually converted to bool (Clause4), where the converted expression is a constant expression and the conversion sequence contains only the conversions above. [...] Contextually converting result of an expression `e` to a Boolean value requires `bool t(e)` to be well-formed. An explicit conversion function is only considered as a user-defined conversion for direct-initialization, which is essentially what //contextually converted to bool// requires. Also, fixes PR28470. Reviewers: rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D24158 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@280838 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f86c1678e6
commit
8a4ab9f7f7
|
@ -5164,12 +5164,18 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
|
||||||
// implicitly converted to type T, where the converted
|
// implicitly converted to type T, where the converted
|
||||||
// expression is a constant expression and the implicit conversion
|
// expression is a constant expression and the implicit conversion
|
||||||
// sequence contains only [... list of conversions ...].
|
// sequence contains only [... list of conversions ...].
|
||||||
|
// C++1z [stmt.if]p2:
|
||||||
|
// If the if statement is of the form if constexpr, the value of the
|
||||||
|
// condition shall be a contextually converted constant expression of type
|
||||||
|
// bool.
|
||||||
ImplicitConversionSequence ICS =
|
ImplicitConversionSequence ICS =
|
||||||
TryCopyInitialization(S, From, T,
|
CCE == Sema::CCEK_ConstexprIf
|
||||||
/*SuppressUserConversions=*/false,
|
? TryContextuallyConvertToBool(S, From)
|
||||||
/*InOverloadResolution=*/false,
|
: TryCopyInitialization(S, From, T,
|
||||||
/*AllowObjcWritebackConversion=*/false,
|
/*SuppressUserConversions=*/false,
|
||||||
/*AllowExplicit=*/false);
|
/*InOverloadResolution=*/false,
|
||||||
|
/*AllowObjcWritebackConversion=*/false,
|
||||||
|
/*AllowExplicit=*/false);
|
||||||
StandardConversionSequence *SCS = nullptr;
|
StandardConversionSequence *SCS = nullptr;
|
||||||
switch (ICS.getKind()) {
|
switch (ICS.getKind()) {
|
||||||
case ImplicitConversionSequence::StandardConversion:
|
case ImplicitConversionSequence::StandardConversion:
|
||||||
|
|
|
@ -46,6 +46,11 @@ namespace ccce {
|
||||||
if constexpr (N) {} // expected-error {{cannot be narrowed}}
|
if constexpr (N) {} // expected-error {{cannot be narrowed}}
|
||||||
}
|
}
|
||||||
template void g<5>(); // expected-note {{instantiation of}}
|
template void g<5>(); // expected-note {{instantiation of}}
|
||||||
|
void h() {
|
||||||
|
if constexpr (4.3) {} // expected-error{{conversion from 'double' to 'bool' is not allowed in a converted constant expression}}
|
||||||
|
constexpr void *p = nullptr;
|
||||||
|
if constexpr (p) {} // expected-error{{conversion from 'void *const' to 'bool' is not allowed in a converted constant expression}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace generic_lambda {
|
namespace generic_lambda {
|
||||||
|
|
|
@ -2,7 +2,15 @@
|
||||||
|
|
||||||
void should_be_used_1();
|
void should_be_used_1();
|
||||||
void should_be_used_2();
|
void should_be_used_2();
|
||||||
|
void should_be_used_3();
|
||||||
void should_not_be_used();
|
void should_not_be_used();
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
constexpr explicit operator bool() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void f() {
|
void f() {
|
||||||
if constexpr (false)
|
if constexpr (false)
|
||||||
should_not_be_used();
|
should_not_be_used();
|
||||||
|
@ -15,7 +23,12 @@ void f() {
|
||||||
goto foo;
|
goto foo;
|
||||||
foo: should_not_be_used();
|
foo: should_not_be_used();
|
||||||
}
|
}
|
||||||
|
if constexpr (A())
|
||||||
|
should_be_used_3();
|
||||||
|
else
|
||||||
|
should_not_be_used();
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: should_be_used_1
|
// CHECK: should_be_used_1
|
||||||
// CHECK: should_be_used_2
|
// CHECK: should_be_used_2
|
||||||
|
// CHECK: should_be_used_3
|
||||||
|
|
Loading…
Reference in New Issue