Skip to content

Commit

Permalink
[c++20] For P0732R2 / P1907R1: Basic code generation and name
Browse files Browse the repository at this point in the history
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
  • Loading branch information
zygoloid committed Nov 10, 2020
1 parent 892605b commit b637148
Show file tree
Hide file tree
Showing 14 changed files with 1,222 additions and 90 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Expand Up @@ -2298,6 +2298,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
const ObjCImplementationDecl *ID,
const ObjCIvarDecl *Ivar) const;

/// Find the 'this' offset for the member path in a pointer-to-member
/// APValue.
CharUnits getMemberPointerPathAdjustment(const APValue &MP) const;

bool isNearlyEmpty(const CXXRecordDecl *RD) const;

VTableContextBase *getVTableContext();
Expand Down
98 changes: 98 additions & 0 deletions clang/lib/AST/APValue.cpp
Expand Up @@ -11,10 +11,12 @@
//===----------------------------------------------------------------------===//

#include "clang/AST/APValue.h"
#include "Linkage.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -977,3 +979,99 @@ void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
for (unsigned I = 0; I != Path.size(); ++I)
InternalPath[I] = Path[I]->getCanonicalDecl();
}

LinkageInfo LinkageComputer::getLVForValue(const APValue &V,
LVComputationKind computation) {
LinkageInfo LV = LinkageInfo::external();

auto MergeLV = [&](LinkageInfo MergeLV) {
LV.merge(MergeLV);
return LV.getLinkage() == InternalLinkage;
};
auto Merge = [&](const APValue &V) {
return MergeLV(getLVForValue(V, computation));
};

switch (V.getKind()) {
case APValue::None:
case APValue::Indeterminate:
case APValue::Int:
case APValue::Float:
case APValue::FixedPoint:
case APValue::ComplexInt:
case APValue::ComplexFloat:
case APValue::Vector:
break;

case APValue::AddrLabelDiff:
// Even for an inline function, it's not reasonable to treat a difference
// between the addresses of labels as an external value.
return LinkageInfo::internal();

case APValue::Struct: {
for (unsigned I = 0, N = V.getStructNumBases(); I != N; ++I)
if (Merge(V.getStructBase(I)))
break;
for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I)
if (Merge(V.getStructField(I)))
break;
break;
}

case APValue::Union:
if (const auto *FD = V.getUnionField())
Merge(V.getUnionValue());
break;

case APValue::Array: {
for (unsigned I = 0, N = V.getArrayInitializedElts(); I != N; ++I)
if (Merge(V.getArrayInitializedElt(I)))
break;
if (V.hasArrayFiller())
Merge(V.getArrayFiller());
break;
}

case APValue::LValue: {
if (!V.getLValueBase()) {
// Null or absolute address: this is external.
} else if (const auto *VD =
V.getLValueBase().dyn_cast<const ValueDecl *>()) {
if (VD && MergeLV(getLVForDecl(VD, computation)))
break;
} else if (const auto TI = V.getLValueBase().dyn_cast<TypeInfoLValue>()) {
if (MergeLV(getLVForType(*TI.getType(), computation)))
break;
} else if (const Expr *E = V.getLValueBase().dyn_cast<const Expr *>()) {
// Almost all expression bases are internal. The exception is
// lifetime-extended temporaries.
// FIXME: These should be modeled as having the
// LifetimeExtendedTemporaryDecl itself as the base.
// FIXME: If we permit Objective-C object literals in template arguments,
// they should not imply internal linkage.
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
if (!MTE || MTE->getStorageDuration() == SD_FullExpression)
return LinkageInfo::internal();
if (MergeLV(getLVForDecl(MTE->getExtendingDecl(), computation)))
break;
} else {
assert(V.getLValueBase().is<DynamicAllocLValue>() &&
"unexpected LValueBase kind");
return LinkageInfo::internal();
}
// The lvalue path doesn't matter: pointers to all subobjects always have
// the same visibility as pointers to the complete object.
break;
}

case APValue::MemberPointer:
if (const NamedDecl *D = V.getMemberPointerDecl())
MergeLV(getLVForDecl(D, computation));
// Note that we could have a base-to-derived conversion here to a member of
// a derived class with less linkage/visibility. That's covered by the
// linkage and visibility of the value's type.
break;
}

return LV;
}
19 changes: 19 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Expand Up @@ -2487,6 +2487,25 @@ CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const {
return Offset;
}

CharUnits ASTContext::getMemberPointerPathAdjustment(const APValue &MP) const {
const ValueDecl *MPD = MP.getMemberPointerDecl();
CharUnits ThisAdjustment = CharUnits::Zero();
ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
bool DerivedMember = MP.isMemberPointerToDerivedMember();
const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
const CXXRecordDecl *Base = RD;
const CXXRecordDecl *Derived = Path[I];
if (DerivedMember)
std::swap(Base, Derived);
ThisAdjustment += getASTRecordLayout(Derived).getBaseClassOffset(Base);
RD = Path[I];
}
if (DerivedMember)
ThisAdjustment = -ThisAdjustment;
return ThisAdjustment;
}

/// DeepCollectObjCIvars -
/// This routine first collects all declared, but not synthesized, ivars in
/// super class and then collects all ivars, including those synthesized for
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/Decl.cpp
Expand Up @@ -1395,6 +1395,15 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,

break;
}

case Decl::TemplateParamObject: {
// The template parameter object can be referenced from anywhere its type
// and value can be referenced.
auto *TPO = cast<TemplateParamObjectDecl>(D);
LinkageInfo LV = getLVForType(*TPO->getType(), computation);
LV.merge(getLVForValue(TPO->getValue(), computation));
return LV;
}
}

// Handle linkage for namespace-scope names.
Expand Down

0 comments on commit b637148

Please sign in to comment.