{"url":"https://api.github.com/repos/llvm/llvm-project/issues/93873","repository_url":"https://api.github.com/repos/llvm/llvm-project","labels_url":"https://api.github.com/repos/llvm/llvm-project/issues/93873/labels{/name}","comments_url":"https://api.github.com/repos/llvm/llvm-project/issues/93873/comments","events_url":"https://api.github.com/repos/llvm/llvm-project/issues/93873/events","html_url":"https://github.com/llvm/llvm-project/pull/93873","id":2326477471,"node_id":"PR_kwDOBITxeM5xDfMi","number":93873,"title":"[Clang][Sema] Diagnose variable template explicit specializations with storage-class-specifiers","user":{"login":"sdkrystian","id":16629302,"node_id":"MDQ6VXNlcjE2NjI5MzAy","avatar_url":"https://avatars.githubusercontent.com/u/16629302?v=4","gravatar_id":"","url":"https://api.github.com/users/sdkrystian","html_url":"https://github.com/sdkrystian","followers_url":"https://api.github.com/users/sdkrystian/followers","following_url":"https://api.github.com/users/sdkrystian/following{/other_user}","gists_url":"https://api.github.com/users/sdkrystian/gists{/gist_id}","starred_url":"https://api.github.com/users/sdkrystian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdkrystian/subscriptions","organizations_url":"https://api.github.com/users/sdkrystian/orgs","repos_url":"https://api.github.com/users/sdkrystian/repos","events_url":"https://api.github.com/users/sdkrystian/events{/privacy}","received_events_url":"https://api.github.com/users/sdkrystian/received_events","type":"User","user_view_type":"public","site_admin":false},"labels":[{"id":1958965060,"node_id":"MDU6TGFiZWwxOTU4OTY1MDYw","url":"https://api.github.com/repos/llvm/llvm-project/labels/clang","name":"clang","color":"79b5d1","default":false,"description":"Clang issues not falling into any other category"},{"id":1958998266,"node_id":"MDU6TGFiZWwxOTU4OTk4MjY2","url":"https://api.github.com/repos/llvm/llvm-project/labels/clang:frontend","name":"clang:frontend","color":"3b12ce","default":false,"description":"Language frontend issues, e.g. anything involving \"Sema\""},{"id":1958998827,"node_id":"MDU6TGFiZWwxOTU4OTk4ODI3","url":"https://api.github.com/repos/llvm/llvm-project/labels/clang:modules","name":"clang:modules","color":"3b12ce","default":false,"description":"C++20 modules and Clang Header Modules"}],"state":"closed","locked":false,"assignees":[],"milestone":null,"comments":15,"created_at":"2024-05-30T20:24:58Z","updated_at":"2024-07-02T19:10:03Z","closed_at":"2024-06-18T17:40:31Z","assignee":null,"author_association":"MEMBER","issue_field_values":[],"type":null,"active_lock_reason":null,"draft":false,"pull_request":{"url":"https://api.github.com/repos/llvm/llvm-project/pulls/93873","html_url":"https://github.com/llvm/llvm-project/pull/93873","diff_url":"https://github.com/llvm/llvm-project/pull/93873.diff","patch_url":"https://github.com/llvm/llvm-project/pull/93873.patch","merged_at":"2024-06-18T17:40:31Z"},"body":"According to [[temp.expl.spec] p2](http://eel.is/c++draft/temp.expl.spec#2):\r\n> The declaration in an _explicit-specialization_ shall not be an _export-declaration_. An explicit specialization shall not use a _storage-class-specifier_ other than `thread_local`.\r\n\r\nClang partially implements this, but a number of issues exist:\r\n1. We don't diagnose class scope explicit specializations of variable templates with _storage-class-specifiers_, e.g.\r\n    ```cpp\r\n    struct A\r\n    {\r\n        template<typename T>\r\n        static constexpr int x = 0;\r\n\r\n        template<>\r\n        static constexpr int x<void> = 1; // ill-formed, but clang accepts\r\n    };\r\n    ````\r\n2. We incorrectly reject class scope explicit specializations of variable templates when `static` is not used, e.g.\r\n    ```cpp\r\n    struct A\r\n    {\r\n        template<typename T>\r\n        static constexpr int x = 0;\r\n\r\n        template<>\r\n        constexpr int x<void> = 1; // error: non-static data member cannot be constexpr; did you intend to make it static?\r\n    };\r\n    ````\r\n3. We don't diagnose dependent class scope explicit specializations of function templates with storage class specifiers, e.g.\r\n    ```cpp\r\n    template<typename T>\r\n    struct A\r\n    {\r\n        template<typename U>\r\n        static void f();\r\n\r\n        template<>\r\n        static void f<int>(); // ill-formed, but clang accepts\r\n    };\r\n    ````\r\n\r\nThis patch addresses these issues as follows:\r\n- [#1]() is fixed by issuing a diagnostic when an explicit specialization of a variable template has storage class specifier\r\n- [#2]() is fixed by considering any non-function declaration with any template parameter lists at class scope to be a static data member. This also allows for better error recovery (it's more likely the user intended to declare a variable template than a \"field template\").\r\n- [#3]() is fixed by checking whether a function template explicit specialization has a storage class specifier even when the primary template is not yet known. \r\n\r\nOne thing to note is that it would be far simpler to diagnose this when parsing the _decl-specifier-seq_, but such an implementation would necessitate a refactor of `ParsedTemplateInfo` which I believe to be outside the scope of this patch.\r\n","closed_by":{"login":"sdkrystian","id":16629302,"node_id":"MDQ6VXNlcjE2NjI5MzAy","avatar_url":"https://avatars.githubusercontent.com/u/16629302?v=4","gravatar_id":"","url":"https://api.github.com/users/sdkrystian","html_url":"https://github.com/sdkrystian","followers_url":"https://api.github.com/users/sdkrystian/followers","following_url":"https://api.github.com/users/sdkrystian/following{/other_user}","gists_url":"https://api.github.com/users/sdkrystian/gists{/gist_id}","starred_url":"https://api.github.com/users/sdkrystian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdkrystian/subscriptions","organizations_url":"https://api.github.com/users/sdkrystian/orgs","repos_url":"https://api.github.com/users/sdkrystian/repos","events_url":"https://api.github.com/users/sdkrystian/events{/privacy}","received_events_url":"https://api.github.com/users/sdkrystian/received_events","type":"User","user_view_type":"public","site_admin":false},"reactions":{"url":"https://api.github.com/repos/llvm/llvm-project/issues/93873/reactions","total_count":1,"+1":1,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"timeline_url":"https://api.github.com/repos/llvm/llvm-project/issues/93873/timeline","performed_via_github_app":null,"state_reason":null}