https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/209836
>From cd91c147f37a4772779a06dfedbf1c85807f5ac8 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 Abstract declarator contexts (specifically DeclaratorContext::TypeName) now properly bypass this restricted rule, allowing cv-qualified function types in typeof and template arguments while maintaining restrictions in other contexts like typeid, sizeof, C-style casts, and new expressions per CWG1417. --- clang/docs/ReleaseNotes.md | 2 + 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 +- 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 clang/test/SemaCXX/qualified-function-typeof.cpp diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 7b829db478088..8618f64b858b8 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -362,6 +362,8 @@ features cannot lower the translation-unit ABI level; #### Bug Fixes to C++ Support +- Fixed an issue where `__typeof__` incorrectly rejected cv-qualified function types. + - Fixed an issue where we tried to compare invalid NTTPs for variable declarations, which ended up in hitting an assertion with a constrained non-plain-auto NTTP, which we don't quite implement yet. (#GH208658) - Fixed a crash when a using-declaration naming an unresolvable member of a diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 1e9de3ef19f8e..5d95bf47d3e9d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5600,7 +5600,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..f3b2bab8e7f3a 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: 3.5 + 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 c05fde6a16727..4d29e6b4b32f4 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="full" align="center">Clang 3.5</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
