SlaterLatiao updated this revision to Diff 545291.
SlaterLatiao marked 2 inline comments as done.
SlaterLatiao added a comment.
Revert last commit.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D156546/new/
https://reviews.llvm.org/D156546
Files:
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaType.cpp
clang/test/CodeGenCXX/packed_data_member.cpp
Index: clang/test/CodeGenCXX/packed_data_member.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/packed_data_member.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 --std=c++20 %s -emit-llvm -o - -triple x86_64-linux | FileCheck %s --check-prefixes=CHECK
+
+// Tests declaration of packed data members.
+template<typename... Ts> struct S1 {
+ Ts... ts;
+};
+
+template<typename T, typename... Ts> struct S2 {
+ T t[2];
+ Ts... ts;
+};
+
+// CHECK: %struct.S1 = type { i32 }
+S1<int> s1;
+// CHECK-NEXT: %struct.S1.0 = type { i32, float, double }
+S1<int, float, double> s2;
+// Test template args as the last arg.
+// CHECK-NEXT: %struct.S2 = type { [2 x i32], float, double }
+S2<int, float, double> s3;
+// Test nested template args.
+// CHECK-NEXT: %struct.S1.1 = type { i32, float, %struct.S1.2 }
+// CHECK-NEXT: %struct.S1.2 = type { double, double }
+S1<int, float, S1<double, double>> s4;
+// Test empty template arg.
+// CHECK-NEXT: %struct.S1.3 = type { i8 }
+S1<> s5;
\ No newline at end of file
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -5927,6 +5927,8 @@
/*ExpectPackInType=*/false);
}
break;
+ case DeclaratorContext::Member:
+ // Expand for packed data members.
case DeclaratorContext::TemplateParam:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
@@ -5944,7 +5946,6 @@
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
break;
-
case DeclaratorContext::File:
case DeclaratorContext::KNRTypeList:
case DeclaratorContext::ObjCParameter: // FIXME: special diagnostic here?
@@ -5954,7 +5955,6 @@
case DeclaratorContext::CXXNew:
case DeclaratorContext::AliasDecl:
case DeclaratorContext::AliasTemplate:
- case DeclaratorContext::Member:
case DeclaratorContext::Block:
case DeclaratorContext::ForInit:
case DeclaratorContext::SelectionInit:
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3267,42 +3267,75 @@
continue;
}
- Decl *NewMember = Instantiator.Visit(Member);
- if (NewMember) {
- if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
- Fields.push_back(Field);
- } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
- // C++11 [temp.inst]p1: The implicit instantiation of a class template
- // specialization causes the implicit instantiation of the definitions
- // of unscoped member enumerations.
- // Record a point of instantiation for this implicit instantiation.
- if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() &&
- Enum->isCompleteDefinition()) {
- MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo();
- assert(MSInfo && "no spec info for member enum specialization");
- MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
- MSInfo->setPointOfInstantiation(PointOfInstantiation);
- }
- } else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(NewMember)) {
- if (SA->isFailed()) {
- // A static_assert failed. Bail out; instantiating this
- // class is probably not meaningful.
- Instantiation->setInvalidDecl();
- break;
+ // Instantiate packed data members.
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(Member);
+ Field && isa<PackExpansionType>(Field->getType().getTypePtr())) {
+ QualType PatternType = Field->getType()
+ ->castAs<PackExpansionType>()
+ ->getPattern();
+ std::optional<unsigned> NumArgumentsInExpansion =
+ getNumArgumentsInExpansion(Field->getType(), TemplateArgs);
+ assert(NumArgumentsInExpansion && "should not see unknown template argument here");
+ for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
+ // Generate a new field from PackExpansion field.
+ Decl *NewMember = Instantiator.Visit(Member);
+ if (NewMember) {
+ FieldDecl *PackedField = dyn_cast<FieldDecl>(NewMember);
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, Arg);
+ QualType T =
+ SubstType(PatternType, TemplateArgs, PackedField->getLocation(),
+ PackedField->getDeclName());
+ PackedField->setType(T);
+ Fields.push_back(PackedField);
+ if (NewMember->isInvalidDecl())
+ Instantiation->setInvalidDecl();
+ } else {
+ // FIXME: Eventually, a NULL return will mean that one of the
+ // instantiations was a semantic disaster, and we'll want to mark
+ // the declaration invalid. For now, we expect to skip some members
+ // that we can't yet handle.
}
- } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewMember)) {
- if (MD->isConstexpr() && !MD->getFriendObjectKind() &&
- (MD->isVirtualAsWritten() || Instantiation->getNumBases()))
- MightHaveConstexprVirtualFunctions = true;
}
-
- if (NewMember->isInvalidDecl())
- Instantiation->setInvalidDecl();
} else {
- // FIXME: Eventually, a NULL return will mean that one of the
- // instantiations was a semantic disaster, and we'll want to mark the
- // declaration invalid.
- // For now, we expect to skip some members that we can't yet handle.
+ Decl *NewMember = Instantiator.Visit(Member);
+ if (NewMember) {
+ if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
+ Fields.push_back(Field);
+ } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
+ // C++11 [temp.inst]p1: The implicit instantiation of a class template
+ // specialization causes the implicit instantiation of the definitions
+ // of unscoped member enumerations.
+ // Record a point of instantiation for this implicit instantiation.
+ if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() &&
+ Enum->isCompleteDefinition()) {
+ MemberSpecializationInfo *MSInfo =
+ Enum->getMemberSpecializationInfo();
+ assert(MSInfo && "no spec info for member enum specialization");
+ MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
+ } else if (StaticAssertDecl *SA =
+ dyn_cast<StaticAssertDecl>(NewMember)) {
+ if (SA->isFailed()) {
+ // A static_assert failed. Bail out; instantiating this
+ // class is probably not meaningful.
+ Instantiation->setInvalidDecl();
+ break;
+ }
+ } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewMember)) {
+ if (MD->isConstexpr() && !MD->getFriendObjectKind() &&
+ (MD->isVirtualAsWritten() || Instantiation->getNumBases()))
+ MightHaveConstexprVirtualFunctions = true;
+ }
+
+ if (NewMember->isInvalidDecl())
+ Instantiation->setInvalidDecl();
+ } else {
+ // FIXME: Eventually, a NULL return will mean that one of the
+ // instantiations was a semantic disaster, and we'll want to mark the
+ // declaration invalid.
+ // For now, we expect to skip some members that we can't yet handle.
+ }
}
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits