================
@@ -165,6 +166,53 @@ bool BugSuppression::isSuppressed(const BugReport &R) {
isSuppressed(UniqueingLocation, DeclWithIssue, {});
}
+static const ClassTemplateDecl *
+walkInstantiatedFromChain(const ClassTemplateDecl *Tmpl) {
+ // For nested member templates (e.g., S2 inside S1<T>), getInstantiatedFrom
+ // may return the member template as instantiated within an outer
+ // specialization (e.g., S2 as it appears in S1<int>). That instantiated
+ // member template has no definition redeclaration itself; we need to walk
+ // up the member template chain to reach the primary template definition.
+ // \code
+ // template <class> struct S1 {
+ // template <class> struct S2 {
+ // int i;
+ // template <class T> int m(const S2<T>& s2) {
+ // return s2.i;
+ // }
+ // };
+ // }
+ // /code
+ while (auto *MemberTmpl = Tmpl->getInstantiatedFromMemberTemplate()) {
+ if (Tmpl->isMemberSpecialization())
+ break;
+ Tmpl = MemberTmpl;
+ }
+ return Tmpl;
+}
+
+static const ClassTemplatePartialSpecializationDecl *walkInstantiatedFromChain(
+ const ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ while (auto *MemberPS = PartialSpec->getInstantiatedFromMember()) {
+ if (PartialSpec->isMemberSpecialization())
+ break;
+ PartialSpec = MemberPS;
+ }
+ return PartialSpec;
+}
+
+template <class T> static const auto *chooseDefinitionRedecl(const T *Tmpl) {
+ static_assert(llvm::is_one_of<T, ClassTemplateDecl,
+
ClassTemplatePartialSpecializationDecl>::value);
+ for (const auto *Redecl : Tmpl->redecls()) {
+ if (const auto *D = cast<T>(Redecl); D->isThisDeclarationADefinition()) {
+ return D;
----------------
NagyDonat wrote:
Style nitpick: I think the use of `auto` makes this code harder to understand,
especially in the case of `Redecl` where the real type isn't spelled out
anywhere nearby.
In the other two cases it is not very hard to see that `auto` stands for `T`,
but I would still prefer using `T` because it is shorter and simpler:
```suggestion
template <class T> static const T *chooseDefinitionRedecl(const T *Tmpl) {
static_assert(llvm::is_one_of<T, ClassTemplateDecl,
ClassTemplatePartialSpecializationDecl>::value);
for (const auto *Redecl : Tmpl->redecls()) {
if (const T *D = cast<T>(Redecl); D->isThisDeclarationADefinition()) {
return D;
```
https://github.com/llvm/llvm-project/pull/183727
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits