Mordante updated this revision to Diff 224753.
Mordante added a comment.
Removed the language version test.
I also added `clang/test/CXX/conv/conv.fctptr/template-noreturn.cpp` to show
this is not enough to allow `noreturn` to all language versions, so this file
should not be committed.
Do you want me to look at a way to allow the `noreturn` for C++98/C++11? If yes
I prefer to make that a separate commit.
AFAIK the `[[noreturn]]` conversion is a clang extension, should I file a DR
for the standard? AFAIK there isn't one yet.
If you still like the patch could you commit it (except
`clang/test/CXX/conv/conv.fctptr/template-noreturn.cpp`) since I don't have
commit access?
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D64874/new/
https://reviews.llvm.org/D64874
Files:
clang/lib/Sema/SemaTemplate.cpp
clang/test/CXX/conv/conv.fctptr/template-noexcept.cpp
clang/test/CXX/conv/conv.fctptr/template-noreturn.cpp
Index: clang/test/CXX/conv/conv.fctptr/template-noreturn.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/conv/conv.fctptr/template-noreturn.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s
+
+typedef int (*fp)();
+typedef int (*fpnr)() __attribute__((noreturn));
+#if __cplusplus < 201703L
+// expected-note@+2 {{template parameter is declared here}}
+#endif
+template <fp>
+struct FP {};
+
+#if __cplusplus < 201703L
+// expected-note@+2 {{template parameter is declared here}}
+#endif
+template <fpnr>
+struct FPNR {};
+
+int f();
+int fnr() __attribute__((noreturn));
+
+FP<&f> fp_valid;
+FPNR<&fnr> fpnr_valid;
+
+#if __cplusplus < 201703L
+// expected-error@+2 {{non-type template argument of type 'int (*)() __attribute__((noreturn))' cannot be converted to a value of type 'fp' (aka 'int (*)()')}}
+#endif
+FP<&fnr> fp_invalid_before_cxx17;
+
+#if __cplusplus < 201703L
+// expected-error@+4 {{non-type template argument of type 'int (*)()' cannot be converted to a value of type 'fpnr' (aka 'int (*)() __attribute__((noreturn))')}}
+#else
+// expected-error@+2 {{value of type 'int (*)()' is not implicitly convertible to 'fpnr' (aka 'int (*)() __attribute__((noreturn))')}}
+#endif
+FPNR<&f> fpnr_invalid;
Index: clang/test/CXX/conv/conv.fctptr/template-noexcept.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/conv/conv.fctptr/template-noexcept.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s
+
+// Starting with C++17 the noexcept is part of the function signature but
+// a noexcept function can be converted to a noexcept(false) function.
+// The tests were added for PR40024.
+
+#if __cplusplus < 201703L
+// expected-no-diagnostics
+#endif
+
+namespace valid_conversion {
+struct S {
+ int f(void) noexcept { return 110; }
+} s;
+
+template <int (S::*a)(void)>
+int f10(void) { return (s.*a)(); }
+
+int foo(void) {
+ return f10<&S::f>();
+}
+} // namespace valid_conversion
+
+namespace invalid_conversion {
+struct S {
+ int f(void) { return 110; }
+} s;
+
+#if __cplusplus >= 201703L
+// expected-note@+3 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'a'}}
+#endif
+template <int (S::*a)(void) noexcept>
+int f10(void) { return (s.*a)(); }
+
+#if __cplusplus >= 201703L
+// expected-error@+3 {{no matching function for call to 'f10'}}
+#endif
+int foo(void) {
+ return f10<&S::f>();
+}
+} // namespace invalid_conversion
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -6991,6 +6991,13 @@
ObjCLifetimeConversion))
RefExpr = ImpCastExprToType(RefExpr.get(), ParamType.getUnqualifiedType(), CK_NoOp);
+ // Starting with C++17 the noexcept is part of the function signature but
+ // a noexcept function can be converted to a noexcept(false) function.
+ QualType ResultTy;
+ if (IsFunctionConversion(((Expr *)RefExpr.get())->getType(),
+ ParamType.getUnqualifiedType(), ResultTy))
+ RefExpr = ImpCastExprToType(RefExpr.get(), ResultTy, CK_NoOp);
+
assert(!RefExpr.isInvalid() &&
Context.hasSameType(((Expr*) RefExpr.get())->getType(),
ParamType.getUnqualifiedType()));
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits