ldionne created this revision. ldionne added a reviewer: rsmith. Herald added subscribers: cfe-commits, dexonsmith.
Attributes on member classes of class templates (and other similar entities) are not currently instantiated. This was discovered by Richard Smith here: http://lists.llvm.org/pipermail/cfe-dev/2018-September/059291.html This commit makes sure that attributes are instantiated properly. PR38913 Repository: rC Clang https://reviews.llvm.org/D51997 Files: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaCXX/PR38913.cpp Index: clang/test/SemaCXX/PR38913.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/PR38913.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// PR38913 +// Check that we instantiate attributes on declarations for... + +// ...a member class of a class template specialization +template<class T> struct A { struct __attribute__((abi_tag("ATAG"))) X { }; }; +A<int>::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv + +// ...a member class template +template<class T> struct B { template<class U> struct __attribute__((abi_tag("BTAG"))) X { }; }; +B<int>::X<int>* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv + +// ...a member partial specialization +template<class T> struct C { + template<class U, class V> struct X { }; + template<class V> struct __attribute__((abi_tag("CTAG"))) X<int, V> { }; +}; +C<int>::X<int, long>* c() { return 0; } // CHECK-DAG: @_Z1cB4CTAGv + +// ...a member explicit specialization +template<class T> struct D { + template<class U> struct X { }; + template<> struct __attribute__((abi_tag("DTAG"))) X<int> { }; +}; +D<int>::X<int>* d() { return 0; } // CHECK-DAG: @_Z1dB4DTAGv Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1264,6 +1264,10 @@ assert(!(isFriend && Owner->isDependentContext())); Inst->setPreviousDecl(PrevClassTemplate); + // Instantiate the attributes on both the template declaration and the associated record declaration. + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, Inst, LateAttrs, StartingScope); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, StartingScope); + RecordInst->setDescribedClassTemplate(Inst); if (isFriend) { @@ -1491,6 +1495,8 @@ if (SubstQualifier(D, Record)) return nullptr; + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, StartingScope); + Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access
Index: clang/test/SemaCXX/PR38913.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/PR38913.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// PR38913 +// Check that we instantiate attributes on declarations for... + +// ...a member class of a class template specialization +template<class T> struct A { struct __attribute__((abi_tag("ATAG"))) X { }; }; +A<int>::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv + +// ...a member class template +template<class T> struct B { template<class U> struct __attribute__((abi_tag("BTAG"))) X { }; }; +B<int>::X<int>* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv + +// ...a member partial specialization +template<class T> struct C { + template<class U, class V> struct X { }; + template<class V> struct __attribute__((abi_tag("CTAG"))) X<int, V> { }; +}; +C<int>::X<int, long>* c() { return 0; } // CHECK-DAG: @_Z1cB4CTAGv + +// ...a member explicit specialization +template<class T> struct D { + template<class U> struct X { }; + template<> struct __attribute__((abi_tag("DTAG"))) X<int> { }; +}; +D<int>::X<int>* d() { return 0; } // CHECK-DAG: @_Z1dB4DTAGv Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1264,6 +1264,10 @@ assert(!(isFriend && Owner->isDependentContext())); Inst->setPreviousDecl(PrevClassTemplate); + // Instantiate the attributes on both the template declaration and the associated record declaration. + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, Inst, LateAttrs, StartingScope); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, StartingScope); + RecordInst->setDescribedClassTemplate(Inst); if (isFriend) { @@ -1491,6 +1495,8 @@ if (SubstQualifier(D, Record)) return nullptr; + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, StartingScope); + Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits