[clang] [clang] Validate return type when instantiating `returns_nonnull` atttribute (PR #200117)

Iris Shi via cfe-commits cfe-commits at lists.llvm.org
Wed May 27 23:28:15 PDT 2026


https://github.com/el-ev created https://github.com/llvm/llvm-project/pull/200117

Resolves #197206

During template instantiation, check that the return type is a valid pointer type before adding a `ReturnsNonNullAttr`.

>From a9908518b9c45f86f6e9c0c4f12911b179714777 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 28 May 2026 14:23:36 +0800
Subject: [PATCH] [clang] Validate return type when instantiating
 `returns_nonnull` attribute

---
 clang/docs/ReleaseNotes.rst                   |  1 +
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 11 ++++++++++
 .../returns-nonnull-nonptr-crash.cpp          | 21 +++++++++++++++++++
 3 files changed, 33 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/returns-nonnull-nonptr-crash.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f3865672120e0..5ede3047a7e59 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -655,6 +655,7 @@ Bug Fixes to Attribute Support
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 - Fixed a behavioral discrepancy between deleted functions and private members when checking the ``enable_if`` attribute. (#GH175895)
 - Fixed ``init_priority`` attribute by delaying type checks until after the type is deduced.
+- Fixed a crash in optimized builds when ``returns_nonnull`` was applied to a non-pointer return type. (#GH197206)
 
 Bug Fixes to C++ Support
 ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c9bc613a7c4ea..0b20cc44e9f19 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1013,6 +1013,17 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
       continue;
     }
 
+    if (auto *A = dyn_cast<ReturnsNonNullAttr>(TmplAttr)) {
+      auto *FD = cast<FunctionDecl>(New);
+      QualType ResultType = getFunctionOrMethodResultType(FD);
+      if (!isValidPointerAttrType(ResultType))
+        Diag(A->getLocation(), diag::warn_attribute_return_pointers_only)
+            << A << SourceRange() << getFunctionOrMethodResultSourceRange(FD);
+      else if (!New->hasAttr<ReturnsNonNullAttr>())
+        New->addAttr(A->clone(Context));
+      continue;
+    }
+
     if (auto *A = dyn_cast<OwnerAttr>(TmplAttr)) {
       if (!New->hasAttr<OwnerAttr>())
         New->addAttr(A->clone(Context));
diff --git a/clang/test/CodeGenCXX/returns-nonnull-nonptr-crash.cpp b/clang/test/CodeGenCXX/returns-nonnull-nonptr-crash.cpp
new file mode 100644
index 0000000000000..06659746a6cb9
--- /dev/null
+++ b/clang/test/CodeGenCXX/returns-nonnull-nonptr-crash.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++17 -O1 -emit-obj -Wno-ignored-attributes -o /dev/null %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+
+// Regression test for issue #197206
+
+class A {};
+
+template <typename B> class C {
+  // expected-warning at +1 {{'returns_nonnull' attribute only applies to return values that are pointers}}
+  friend B D(C) __attribute__((returns_nonnull)) {
+    B E;
+    return E;
+  }
+};
+
+template <typename>
+C<A> F();
+
+C<A> H = F<int>(); // expected-note {{in instantiation of template class 'C<A>' requested here}}
+
+void G() { D(H); }



More information about the cfe-commits mailing list