https://github.com/AZero13 updated 
https://github.com/llvm/llvm-project/pull/209836

>From db3c47b3c22c96d711f500c52af0ecb4e338e23f Mon Sep 17 00:00:00 2001
From: AZero13 <[email protected]>
Date: Wed, 15 Jul 2026 13:15:11 -0400
Subject: [PATCH] [clang][Sema] Allow abstract declarators to specify
 cv-qualified function types

Exempted DeclaratorContext::TypeName from the check. Abstract declarator 
contexts (used by typeof, sizeof, C-style casts) now properly bypass this 
restricted rule, matching how TemplateArg was already correctly exempted.
---
 clang/lib/Sema/SemaType.cpp                   |  3 +-
 clang/test/CXX/drs/cwg14xx.cpp                | 12 +++++
 .../SemaCXX/qualified-function-typeof.cpp     | 46 +++++++++++++++++++
 clang/www/cxx_dr_status.html                  |  2 +-
 4 files changed, 61 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/qualified-function-typeof.cpp

diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 5161db6ac1a99..b49a0a80e41d4 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5601,7 +5601,8 @@ static TypeSourceInfo 
*GetFullTypeForDeclarator(TypeProcessingState &state,
          (D.getContext() == clang::DeclaratorContext::Member &&
           D.isStaticMember())) &&
         !IsTypedefName && D.getContext() != DeclaratorContext::TemplateArg &&
-        D.getContext() != DeclaratorContext::TemplateTypeArg) {
+        D.getContext() != DeclaratorContext::TemplateTypeArg &&
+        D.getContext() != DeclaratorContext::TypeName) {
       SourceLocation Loc = D.getBeginLoc();
       SourceRange RemovalRange;
       unsigned I;
diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp
index afa4bc9d8179a..33c32a92061ae 100644
--- a/clang/test/CXX/drs/cwg14xx.cpp
+++ b/clang/test/CXX/drs/cwg14xx.cpp
@@ -50,6 +50,18 @@ namespace cwg1413 { // cwg1413: 12
   };
 } // namespace cwg1413
 
+namespace cwg1417 { // cwg1417: 24
+  template<typename T> struct S {
+    typedef T F;
+    typedef T *P;
+    // expected-error@-1 {{pointer to function type 'void () const' cannot 
have 'const' qualifier}}
+      // expected-note@#cwg1417-s {{in instantiation of template class 
'cwg1417::S<void () const>' requested here}}
+    typedef T &R;
+    // expected-error@-1 {{reference to function type 'void () const' cannot 
have 'const' qualifier}}
+  };
+  S<void() const> s; // #cwg1417-s
+}
+
 namespace cwg1423 { // cwg1423: 11
 #if __cplusplus >= 201103L
   bool b1 = nullptr;
diff --git a/clang/test/SemaCXX/qualified-function-typeof.cpp 
b/clang/test/SemaCXX/qualified-function-typeof.cpp
new file mode 100644
index 0000000000000..d9aea33e40ea4
--- /dev/null
+++ b/clang/test/SemaCXX/qualified-function-typeof.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 %s
+
+using F = void() const;
+
+struct S {
+  using F = void() const;
+};
+
+void testTypeOf() {
+  using T1 = __typeof__(F);
+  using T2 = __typeof__(S::F);
+  using T3 = __typeof_unqual__(F);
+  using T4 = __typeof_unqual__(S::F);
+}
+
+template <typename T>
+struct TypeIdentity {
+  using type = T;
+};
+
+void testTemplateArg() {
+  using U1 = TypeIdentity<F>::type;
+  using U2 = TypeIdentity<S::F>::type;
+}
+
+namespace std { class type_info; }
+
+namespace test_other_contexts {
+  void test() {
+    auto &a = typeid(F); // expected-error {{type operand 'F' (aka 'void () 
const') of 'typeid' cannot have 'const' qualifier}}
+    auto &b = typeid(void() const); // expected-error {{type operand 'void () 
const' of 'typeid' cannot have 'const' qualifier}}
+
+    unsigned s1 = sizeof(F); // expected-error {{invalid application of 
'sizeof' to a function type}}
+    unsigned s2 = sizeof(void() const); // expected-error {{invalid 
application of 'sizeof' to a function type}}
+    unsigned a1 = alignof(F); // expected-error {{invalid application of 
'alignof' to a function type}}
+    unsigned a2 = alignof(void() const); // expected-error {{invalid 
application of 'alignof' to a function type}}
+
+    auto c1 = (F)nullptr; // expected-error {{C-style cast from 
'std::nullptr_t' to 'F' (aka 'void () const') is not allowed}}
+    auto c2 = (void() const)nullptr; // expected-error {{C-style cast from 
'std::nullptr_t' to 'void () const' is not allowed}}
+
+    auto n1 = new F; // expected-error {{non-member function of type 'F' (aka 
'void () const') cannot have 'const' qualifier}} \
+                     // expected-error {{cannot allocate function type 'void 
()' with new}}
+    auto n2 = new (void() const); // expected-error {{non-member function 
cannot have 'const' qualifier}} \
+                                  // expected-error {{cannot allocate function 
type 'void ()' with new}}
+  }
+}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index af91ac559d274..7367f6443a3ae 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -9696,7 +9696,7 @@ <h2 id="cxxdr">C++ defect report implementation 
status</h2>
     <td>[<a href="https://wg21.link/dcl.fct";>dcl.fct</a>]</td>
     <td>C++14</td>
     <td>Pointers/references to functions with cv-qualifiers or 
<I>ref-qualifier</I></td>
-    <td class="unknown" align="center">Unknown</td>
+    <td class="unreleased" align="center">Clang 24</td>
   </tr>
   <tr id="1418">
     <td><a 
href="https://cplusplus.github.io/CWG/issues/1418.html";>1418</a></td>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to