Skip to content

Commit 6658db5

Browse files
committed
[clang] Fix timing of propagation of MSInheritanceAttr for template instantiation declarations.
This change addresses three issues: 1) A failure to propagate a MSInheritanceAttr prior to it being required by an explicit class template instantiation definition. 2) The same MSInheritanceAttr attribute being attached to the same ClassTemplateSpecializationDecl twice. 3) MSInheritanceAttr attributes were not being cloned nor marked as inherited when added to new template instantiation declarations. Sema::ActOnExplicitInstantiation() is responsible for the construction of ClassTemplateSpecializationDecl nodes for explicit template instantiation declarations and definitions. When invoked when a prior declaration node corresponding to an implicit instantiation exists, the prior declaration node is repurposed to represent the explicit instantiation declaration or definition. When no previous declaration node exists or when the previous node corresponds to an explicit declaration, a new node is allocated. Previously, in either case, the function attempted to propagate any existing MSInheritanceAttr attribute from the previous node, but did so regardless of whether the previous node was reused (in which case the repurposed previous node would gain a second attachment of the attribute; the second issue listed above) or a new node was created. In the latter case, the attribute was not propagated before it was required to be present when compiling for C++17 or later (the first issue listed above). The absent attribute resulted in an assertion failure that occurred during instantiation of the specialization definition when attempting to complete the definition in order to determine its alignment so as to resolve a lookup for a deallocation function for a virtual destructor. This change addresses both issues by propagating the attribute closer in time to when a new ClassTemplateSpecializationDecl node is created and only when such a node is newly created. Reviewed By: aaron.ballman, rnk Differential Revision: https://reviews.llvm.org/D158869
1 parent 9734b22 commit 6658db5

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ Arm and AArch64 Support
292292

293293
Windows Support
294294
^^^^^^^^^^^^^^^
295+
- Fixed an assertion failure that occurred due to a failure to propagate
296+
``MSInheritanceAttr`` attributes to class template instantiations created
297+
for explicit template instantiation declarations.
295298

296299
LoongArch Support
297300
^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10110,6 +10110,17 @@ DeclResult Sema::ActOnExplicitInstantiation(
1011010110
ClassTemplate, CanonicalConverted, PrevDecl);
1011110111
SetNestedNameSpecifier(*this, Specialization, SS);
1011210112

10113+
// A MSInheritanceAttr attached to the previous declaration must be
10114+
// propagated to the new node prior to instantiation.
10115+
if (PrevDecl) {
10116+
if (const auto *A = PrevDecl->getAttr<MSInheritanceAttr>()) {
10117+
auto *Clone = A->clone(getASTContext());
10118+
Clone->setInherited(true);
10119+
Specialization->addAttr(Clone);
10120+
Consumer.AssignInheritanceModel(Specialization);
10121+
}
10122+
}
10123+
1011310124
if (!HasNoEffect && !PrevDecl) {
1011410125
// Insert the new specialization.
1011510126
ClassTemplate->AddSpecialization(Specialization, InsertPos);
@@ -10226,11 +10237,6 @@ DeclResult Sema::ActOnExplicitInstantiation(
1022610237
dllExportImportClassTemplateSpecialization(*this, Def);
1022710238
}
1022810239

10229-
if (Def->hasAttr<MSInheritanceAttr>()) {
10230-
Specialization->addAttr(Def->getAttr<MSInheritanceAttr>());
10231-
Consumer.AssignInheritanceModel(Specialization);
10232-
}
10233-
1023410240
// Set the template specialization kind. Make sure it is set before
1023510241
// instantiating the members which will trigger ASTConsumer callbacks.
1023610242
Specialization->setTemplateSpecializationKind(TSK);

clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck -allow-deprecated-dag-overlap %s
22
// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
3+
// RUN: %clang_cc1 -std=c++17 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
34
// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
45
// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
56

@@ -934,3 +935,32 @@ class A {
934935
void A::printd() { JSMethod<A, &A::printd>(); }
935936
// CHECK-LABEL: @"??$JSMethod@VA@PMFInTemplateArgument@@$1?printd@12@AAEHH@Z@PMFInTemplateArgument@@YAXXZ"(
936937
}
938+
939+
namespace MissingMSInheritanceAttr {
940+
// This is a regression test for an assertion failure that occurred when
941+
// compiling for C++17. The issue concerned a failure to propagate a
942+
// MSInheritanceAttr attribute for the explicit template instantiation
943+
// definition prior to it being required to complete the specialization
944+
// definition in order to determine its alignment so as to resolve a
945+
// lookup for a deallocation function for the virtual destructor.
946+
template <typename>
947+
class a;
948+
struct b {
949+
typedef void (a<int>::*f)();
950+
f d;
951+
};
952+
template <typename>
953+
class a {
954+
virtual ~a();
955+
b e;
956+
};
957+
extern template class a<int>;
958+
template class a<int>;
959+
#ifdef _WIN64
960+
static_assert(sizeof(b::d) == 24, "");
961+
static_assert(sizeof(void (a<int>::*)()) == 24, "");
962+
#else
963+
static_assert(sizeof(b::d) == 16, "");
964+
static_assert(sizeof(void (a<int>::*)()) == 16, "");
965+
#endif
966+
}

0 commit comments

Comments
 (0)