Skip to content

Commit b637148

Browse files
committed
[c++20] For P0732R2 / P1907R1: Basic code generation and name
mangling support for non-type template parameters of class type and template parameter objects. The Itanium side of this follows the approach I proposed in itanium-cxx-abi/cxx-abi#47 on 2020-09-06. The MSVC side of this was determined empirically by observing MSVC's output. Differential Revision: https://reviews.llvm.org/D89998
1 parent 892605b commit b637148

File tree

14 files changed

+1222
-90
lines changed

14 files changed

+1222
-90
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
22982298
const ObjCImplementationDecl *ID,
22992299
const ObjCIvarDecl *Ivar) const;
23002300

2301+
/// Find the 'this' offset for the member path in a pointer-to-member
2302+
/// APValue.
2303+
CharUnits getMemberPointerPathAdjustment(const APValue &MP) const;
2304+
23012305
bool isNearlyEmpty(const CXXRecordDecl *RD) const;
23022306

23032307
VTableContextBase *getVTableContext();

clang/lib/AST/APValue.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "clang/AST/APValue.h"
14+
#include "Linkage.h"
1415
#include "clang/AST/ASTContext.h"
1516
#include "clang/AST/CharUnits.h"
1617
#include "clang/AST/DeclCXX.h"
1718
#include "clang/AST/Expr.h"
19+
#include "clang/AST/ExprCXX.h"
1820
#include "clang/AST/Type.h"
1921
#include "llvm/Support/ErrorHandling.h"
2022
#include "llvm/Support/raw_ostream.h"
@@ -977,3 +979,99 @@ void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
977979
for (unsigned I = 0; I != Path.size(); ++I)
978980
InternalPath[I] = Path[I]->getCanonicalDecl();
979981
}
982+
983+
LinkageInfo LinkageComputer::getLVForValue(const APValue &V,
984+
LVComputationKind computation) {
985+
LinkageInfo LV = LinkageInfo::external();
986+
987+
auto MergeLV = [&](LinkageInfo MergeLV) {
988+
LV.merge(MergeLV);
989+
return LV.getLinkage() == InternalLinkage;
990+
};
991+
auto Merge = [&](const APValue &V) {
992+
return MergeLV(getLVForValue(V, computation));
993+
};
994+
995+
switch (V.getKind()) {
996+
case APValue::None:
997+
case APValue::Indeterminate:
998+
case APValue::Int:
999+
case APValue::Float:
1000+
case APValue::FixedPoint:
1001+
case APValue::ComplexInt:
1002+
case APValue::ComplexFloat:
1003+
case APValue::Vector:
1004+
break;
1005+
1006+
case APValue::AddrLabelDiff:
1007+
// Even for an inline function, it's not reasonable to treat a difference
1008+
// between the addresses of labels as an external value.
1009+
return LinkageInfo::internal();
1010+
1011+
case APValue::Struct: {
1012+
for (unsigned I = 0, N = V.getStructNumBases(); I != N; ++I)
1013+
if (Merge(V.getStructBase(I)))
1014+
break;
1015+
for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I)
1016+
if (Merge(V.getStructField(I)))
1017+
break;
1018+
break;
1019+
}
1020+
1021+
case APValue::Union:
1022+
if (const auto *FD = V.getUnionField())
1023+
Merge(V.getUnionValue());
1024+
break;
1025+
1026+
case APValue::Array: {
1027+
for (unsigned I = 0, N = V.getArrayInitializedElts(); I != N; ++I)
1028+
if (Merge(V.getArrayInitializedElt(I)))
1029+
break;
1030+
if (V.hasArrayFiller())
1031+
Merge(V.getArrayFiller());
1032+
break;
1033+
}
1034+
1035+
case APValue::LValue: {
1036+
if (!V.getLValueBase()) {
1037+
// Null or absolute address: this is external.
1038+
} else if (const auto *VD =
1039+
V.getLValueBase().dyn_cast<const ValueDecl *>()) {
1040+
if (VD && MergeLV(getLVForDecl(VD, computation)))
1041+
break;
1042+
} else if (const auto TI = V.getLValueBase().dyn_cast<TypeInfoLValue>()) {
1043+
if (MergeLV(getLVForType(*TI.getType(), computation)))
1044+
break;
1045+
} else if (const Expr *E = V.getLValueBase().dyn_cast<const Expr *>()) {
1046+
// Almost all expression bases are internal. The exception is
1047+
// lifetime-extended temporaries.
1048+
// FIXME: These should be modeled as having the
1049+
// LifetimeExtendedTemporaryDecl itself as the base.
1050+
// FIXME: If we permit Objective-C object literals in template arguments,
1051+
// they should not imply internal linkage.
1052+
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
1053+
if (!MTE || MTE->getStorageDuration() == SD_FullExpression)
1054+
return LinkageInfo::internal();
1055+
if (MergeLV(getLVForDecl(MTE->getExtendingDecl(), computation)))
1056+
break;
1057+
} else {
1058+
assert(V.getLValueBase().is<DynamicAllocLValue>() &&
1059+
"unexpected LValueBase kind");
1060+
return LinkageInfo::internal();
1061+
}
1062+
// The lvalue path doesn't matter: pointers to all subobjects always have
1063+
// the same visibility as pointers to the complete object.
1064+
break;
1065+
}
1066+
1067+
case APValue::MemberPointer:
1068+
if (const NamedDecl *D = V.getMemberPointerDecl())
1069+
MergeLV(getLVForDecl(D, computation));
1070+
// Note that we could have a base-to-derived conversion here to a member of
1071+
// a derived class with less linkage/visibility. That's covered by the
1072+
// linkage and visibility of the value's type.
1073+
break;
1074+
}
1075+
1076+
return LV;
1077+
}

clang/lib/AST/ASTContext.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,6 +2487,25 @@ CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const {
24872487
return Offset;
24882488
}
24892489

2490+
CharUnits ASTContext::getMemberPointerPathAdjustment(const APValue &MP) const {
2491+
const ValueDecl *MPD = MP.getMemberPointerDecl();
2492+
CharUnits ThisAdjustment = CharUnits::Zero();
2493+
ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
2494+
bool DerivedMember = MP.isMemberPointerToDerivedMember();
2495+
const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
2496+
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
2497+
const CXXRecordDecl *Base = RD;
2498+
const CXXRecordDecl *Derived = Path[I];
2499+
if (DerivedMember)
2500+
std::swap(Base, Derived);
2501+
ThisAdjustment += getASTRecordLayout(Derived).getBaseClassOffset(Base);
2502+
RD = Path[I];
2503+
}
2504+
if (DerivedMember)
2505+
ThisAdjustment = -ThisAdjustment;
2506+
return ThisAdjustment;
2507+
}
2508+
24902509
/// DeepCollectObjCIvars -
24912510
/// This routine first collects all declared, but not synthesized, ivars in
24922511
/// super class and then collects all ivars, including those synthesized for

clang/lib/AST/Decl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,15 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
13951395

13961396
break;
13971397
}
1398+
1399+
case Decl::TemplateParamObject: {
1400+
// The template parameter object can be referenced from anywhere its type
1401+
// and value can be referenced.
1402+
auto *TPO = cast<TemplateParamObjectDecl>(D);
1403+
LinkageInfo LV = getLVForType(*TPO->getType(), computation);
1404+
LV.merge(getLVForValue(TPO->getValue(), computation));
1405+
return LV;
1406+
}
13981407
}
13991408

14001409
// Handle linkage for namespace-scope names.

0 commit comments

Comments
 (0)