Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The explicitly specialized primary template class shall supress consideration of other partial specialization #51051

Open
xmh0511 mannequin opened this issue Sep 2, 2021 · 2 comments
Labels
bugzilla Issues migrated from bugzilla c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party

Comments

@xmh0511
Copy link
Mannequin

xmh0511 mannequin commented Sep 2, 2021

Bugzilla Link 51709
Version trunk
OS All
CC @DougGregor,@zygoloid

Extended Description

template<class T> struct A {
  template<class T2> struct B {
     static const int value = 1;
  };                               // #&#8203;1
  template<class T2> struct B<T2*> {
     static const int value = 2;
  };                          // #&#8203;2
};

template<> template<class T2> struct A<short>::B {
    static const int value = 3;
};            // #&#8203;3
int main(){
   std::cout<< A<short>::B<int*>::value;  // shall be 3
}

Clang give 2, as per [temp.spec.partial.member] p2.

If a member template of a class template is partially specialized, the member template partial specializations are member templates of the enclosing class template; if the enclosing class template is instantiated ([temp.inst], [temp.explicit]), a declaration for every member template partial specialization is also instantiated as part of creating the members of the class template specialization. If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template. If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template.

We explicitly specialized the primary template class B for enclosing class template specialization A<short>, hence the other partial specialization shall not be considered anymore.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
@llvmbot llvmbot added the confirmed Verified by a second party label Jan 26, 2022
@Endilll Endilll added the clang:to-be-triaged Should not be used for new issues label Jul 18, 2024
@cor3ntin cor3ntin added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed clang:to-be-triaged Should not be used for new issues labels Jul 21, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 21, 2024

@llvm/issue-subscribers-clang-frontend

Author: None (8084cac4-606c-41d3-baea-106d693787ba)

| | | | --- | --- | | Bugzilla Link | [51709](https://llvm.org/bz51709) | | Version | trunk | | OS | All | | CC | @DougGregor,@zygoloid |

Extended Description

template&lt;class T&gt; struct A {
  template&lt;class T2&gt; struct B {
     static const int value = 1;
  };                               // #&amp;#<!-- -->8203;1
  template&lt;class T2&gt; struct B&lt;T2*&gt; {
     static const int value = 2;
  };                          // #&amp;#<!-- -->8203;2
};

template&lt;&gt; template&lt;class T2&gt; struct A&lt;short&gt;::B {
    static const int value = 3;
};            // #&amp;#<!-- -->8203;3
int main(){
   std::cout&lt;&lt; A&lt;short&gt;::B&lt;int*&gt;::value;  // shall be 3
}

Clang give 2, as per [temp.spec.partial.member] p2.

> If a member template of a class template is partially specialized, the member template partial specializations are member templates of the enclosing class template; if the enclosing class template is instantiated ([temp.inst], [temp.explicit]), a declaration for every member template partial specialization is also instantiated as part of creating the members of the class template specialization. If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template. If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template.

We explicitly specialized the primary template class B for enclosing class template specialization A&lt;short&gt;, hence the other partial specialization shall not be considered anymore.

@cor3ntin
Copy link
Contributor

sdkrystian added a commit that referenced this issue Oct 30, 2024
…ates explicitly specialized for an implicitly instantiated class template specialization (#113464)

Consider the following:
```
template<typename T>
struct A {
  template<typename U>
  struct B {
    static constexpr int x = 0; // #1
  };

  template<typename U>
  struct B<U*> {
    static constexpr int x = 1; // #2
  };
};

template<>
template<typename U>
struct A<long>::B {
  static constexpr int x = 2; // #3
};

static_assert(A<short>::B<int>::y == 0); // uses #1
static_assert(A<short>::B<int*>::y == 1); // uses #2

static_assert(A<long>::B<int>::y == 2); // uses #3
static_assert(A<long>::B<int*>::y == 2); // uses #3
```

According to [temp.spec.partial.member] p2:
> If the primary member template is explicitly specialized for a given
(implicit) specialization of the enclosing class template, the partial
specializations of the member template are ignored for this
specialization of the enclosing class template.
If a partial specialization of the member template is explicitly
specialized for a given (implicit) specialization of the enclosing class
template, the primary member template and its other partial
specializations are still considered for this specialization of the
enclosing class template.

The example above fails to compile because we currently don't implement
[temp.spec.partial.member] p2. This patch implements the wording, fixing #51051.
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this issue Nov 4, 2024
…ates explicitly specialized for an implicitly instantiated class template specialization (llvm#113464)

Consider the following:
```
template<typename T>
struct A {
  template<typename U>
  struct B {
    static constexpr int x = 0; // llvm#1
  };

  template<typename U>
  struct B<U*> {
    static constexpr int x = 1; // llvm#2
  };
};

template<>
template<typename U>
struct A<long>::B {
  static constexpr int x = 2; // llvm#3
};

static_assert(A<short>::B<int>::y == 0); // uses llvm#1
static_assert(A<short>::B<int*>::y == 1); // uses llvm#2

static_assert(A<long>::B<int>::y == 2); // uses llvm#3
static_assert(A<long>::B<int*>::y == 2); // uses llvm#3
```

According to [temp.spec.partial.member] p2:
> If the primary member template is explicitly specialized for a given
(implicit) specialization of the enclosing class template, the partial
specializations of the member template are ignored for this
specialization of the enclosing class template.
If a partial specialization of the member template is explicitly
specialized for a given (implicit) specialization of the enclosing class
template, the primary member template and its other partial
specializations are still considered for this specialization of the
enclosing class template.

The example above fails to compile because we currently don't implement
[temp.spec.partial.member] p2. This patch implements the wording, fixing llvm#51051.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party
Projects
None yet
Development

No branches or pull requests

3 participants