[clang] Diagnose noreturn calls from a const or pure function (PR #206134)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 26 10:54:50 PDT 2026


================
@@ -64,3 +64,84 @@ __attribute__((pure)) int func8(void);
   return 12;
 }
 
+[[noreturn]] void direct_noreturn(void);
+// FIXME: the cast should not be necessary.
+void (*indirect_noreturn)(void) __attribute__((noreturn)) = (__typeof__(indirect_noreturn)) direct_noreturn;
+void returns_okay();
+
+__attribute__((const)) int noreturn_test1(void) {
+  returns_okay();
+  return 12;
+}
+
+__attribute__((const)) int noreturn_test2(void) { // expected-note {{function declared 'const' here}}
+  direct_noreturn(); // expected-warning {{alling a 'noreturn' function from a function with the 'const' attribute is undefined behavior}}
+  return 12;
+}
+
+__attribute__((const)) int noreturn_test3(void) { // expected-note {{function declared 'const' here}}
+  indirect_noreturn(); // expected-warning {{alling a 'noreturn' function from a function with the 'const' attribute is undefined behavior}}
+  return 12;
+}
+
+__attribute__((const)) int noreturn_test4(void) {
+  // This should not be diagnosed.
+  (void)sizeof((direct_noreturn(), 1));
+
+#ifdef __cplusplus
+  if constexpr(false) {
+	// This should not be diagnosed.
+    direct_noreturn();
+  }
+#endif // __cplusplus
+
+  if (0) {
+	// This should not be diagnosed.
+    direct_noreturn();
+  }
+
+  return 12;
+}
+
+__attribute__((pure)) int noreturn_test5(int x) { // expected-note {{function declared 'pure' here}}
+  if (x)
+    direct_noreturn(); // expected-warning {{calling a 'noreturn' function from a function with the 'pure' attribute is undefined behavior}}
+  return 12;
+}
+
+// FIXME: should this be diagnosed because of the noreturn call?
+[[gnu::pure]] int noreturn_test6(int array[(direct_noreturn(), 1)]);
+
+#ifdef __cplusplus
+
+template <typename Ty>
+int noreturn_test7(void) {
+  direct_noreturn(); // okay
+  return 12;
+}
+
+template <>
+__attribute__((const)) int noreturn_test7<int>() { // expected-note {{function declared 'const' here}}
+  direct_noreturn(); // expected-warning {{calling a 'noreturn' function from a function with the 'const' attribute is undefined behavior}}
+  return 12;
+}
+
+template <typename Ty>
+__attribute__((pure)) int noreturn_test8() { // expected-note {{function declared 'pure' here}}
+  // Diagnosed even though noreturn_test8 is not instantiated
+  direct_noreturn(); // expected-warning {{calling a 'noreturn' function from a function with the 'pure' attribute is undefined behavior}}
+  return 12;
+}
+
+template <typename T>
+[[gnu::pure]] int noreturn_test9() {
+  // No diagnostic expected without an instantiation because the call cannot be
+  // resolved yet.
+  T::nrcall();
+  return 12;
+}
+
+struct S {
+  [[noreturn]] void nrcall();
----------------
erichkeane wrote:

Er, sorry, my intent was to make sure that this properly diagnoses when instantiated...

https://github.com/llvm/llvm-project/pull/206134


More information about the cfe-commits mailing list