Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1258,6 +1258,9 @@ if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, + StartingScope); + ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); @@ -1491,6 +1494,9 @@ 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,12 @@ +// 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 struct A { struct __attribute__((abi_tag("ATAG"))) X { }; }; +A::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv + +// ...a member class template +template struct B { template struct __attribute__((abi_tag("BTAG"))) X { }; }; +B::X* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv