summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaOverload.cpp16
-rw-r--r--clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp5
-rw-r--r--clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp13
3 files changed, 29 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 37552b57d66..183fdf4272e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5164,12 +5164,18 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
// implicitly converted to type T, where the converted
// expression is a constant expression and the implicit conversion
// 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 =
- TryCopyInitialization(S, From, T,
- /*SuppressUserConversions=*/false,
- /*InOverloadResolution=*/false,
- /*AllowObjcWritebackConversion=*/false,
- /*AllowExplicit=*/false);
+ CCE == Sema::CCEK_ConstexprIf
+ ? TryContextuallyConvertToBool(S, From)
+ : TryCopyInitialization(S, From, T,
+ /*SuppressUserConversions=*/false,
+ /*InOverloadResolution=*/false,
+ /*AllowObjcWritebackConversion=*/false,
+ /*AllowExplicit=*/false);
StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
diff --git a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
index d6a2169a5ba..c33bf0eba23 100644
--- a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
+++ b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
@@ -46,6 +46,11 @@ namespace ccce {
if constexpr (N) {} // expected-error {{cannot be narrowed}}
}
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 {
diff --git a/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp b/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp
index 80a397f51e9..14695363b33 100644
--- a/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp
+++ b/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp
@@ -2,7 +2,15 @@
void should_be_used_1();
void should_be_used_2();
+void should_be_used_3();
void should_not_be_used();
+
+struct A {
+ constexpr explicit operator bool() const {
+ return true;
+ }
+};
+
void f() {
if constexpr (false)
should_not_be_used();
@@ -15,7 +23,12 @@ void f() {
goto foo;
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_2
+// CHECK: should_be_used_3
OpenPOWER on IntegriCloud