diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-06-28 19:03:57 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-06-28 19:03:57 +0000 |
commit | 5179eb78210a2ad01a18c37b75048ccfe78414ac (patch) | |
tree | 194b7981ca2f1dc43a513f016c1374bf1b31aabb /clang/lib/AST/ItaniumMangle.cpp | |
parent | a5c7adcb38e89cd23ed3cbbc813d2da2546a9161 (diff) | |
download | bcm5719-llvm-5179eb78210a2ad01a18c37b75048ccfe78414ac.tar.gz bcm5719-llvm-5179eb78210a2ad01a18c37b75048ccfe78414ac.zip |
P0136R1, DR1573, DR1645, DR1715, DR1736, DR1903, DR1941, DR1959, DR1991:
Replace inheriting constructors implementation with new approach, voted into
C++ last year as a DR against C++11.
Instead of synthesizing a set of derived class constructors for each inherited
base class constructor, we make the constructors of the base class visible to
constructor lookup in the derived class, using the normal rules for
using-declarations.
For constructors, UsingShadowDecl now has a ConstructorUsingShadowDecl derived
class that tracks the requisite additional information. We create shadow
constructors (not found by name lookup) in the derived class to model the
actual initialization, and have a new expression node,
CXXInheritedCtorInitExpr, to model the initialization of a base class from such
a constructor. (This initialization is special because it performs real perfect
forwarding of arguments.)
In cases where argument forwarding is not possible (for inalloca calls,
variadic calls, and calls with callee parameter cleanup), the shadow inheriting
constructor is not emitted and instead we directly emit the initialization code
into the caller of the inherited constructor.
Note that this new model is not perfectly compatible with the old model in some
corner cases. In particular:
* if B inherits a private constructor from A, and C uses that constructor to
construct a B, then we previously required that A befriends B and B
befriends C, but the new rules require A to befriend C directly, and
* if a derived class has its own constructors (and so its implicit default
constructor is suppressed), it may still inherit a default constructor from
a base class
llvm-svn: 274049
Diffstat (limited to 'clang/lib/AST/ItaniumMangle.cpp')
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index fcce9d23686..8d49c6f586b 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -397,7 +397,7 @@ private: void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); - void mangleCXXCtorType(CXXCtorType T); + void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom); void mangleCXXDtorType(CXXDtorType T); void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs, @@ -502,6 +502,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { FunctionTypeDepth.pop(Saved); } + // When mangling an inheriting constructor, the bare function type used is + // that of the inherited constructor. + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) + if (auto Inherited = CD->getInheritedConstructor()) + FD = Inherited.getConstructor(); + // Whether the mangling of a function type includes the return type depends on // the context and the nature of the function. The rules for deciding whether // the return type is included are: @@ -562,7 +568,7 @@ static bool isStdNamespace(const DeclContext *DC) { static const TemplateDecl * isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { // Check if we have a function template. - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){ + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { TemplateArgs = FD->getTemplateSpecializationArgs(); return TD; @@ -1048,16 +1054,31 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, case DeclarationName::ObjCMultiArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); - case DeclarationName::CXXConstructorName: + case DeclarationName::CXXConstructorName: { + const CXXRecordDecl *InheritedFrom = nullptr; + const TemplateArgumentList *InheritedTemplateArgs = nullptr; + if (auto Inherited = + cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) { + InheritedFrom = Inherited.getConstructor()->getParent(); + InheritedTemplateArgs = + Inherited.getConstructor()->getTemplateSpecializationArgs(); + } + if (ND == Structor) // If the named decl is the C++ constructor we're mangling, use the type // we were given. - mangleCXXCtorType(static_cast<CXXCtorType>(StructorType)); + mangleCXXCtorType(static_cast<CXXCtorType>(StructorType), InheritedFrom); else // Otherwise, use the complete constructor name. This is relevant if a // class with a constructor is declared within a constructor. - mangleCXXCtorType(Ctor_Complete); + mangleCXXCtorType(Ctor_Complete, InheritedFrom); + + // FIXME: The template arguments are part of the enclosing prefix or + // nested-name, but it's more convenient to mangle them here. + if (InheritedTemplateArgs) + mangleTemplateArgs(*InheritedTemplateArgs); break; + } case DeclarationName::CXXDestructorName: if (ND == Structor) @@ -2909,6 +2930,7 @@ recurse: case Expr::MSPropertySubscriptExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. case Expr::OMPArraySectionExprClass: + case Expr::CXXInheritedCtorInitExprClass: llvm_unreachable("unexpected statement kind"); // FIXME: invent manglings for all these. @@ -3688,25 +3710,33 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) { Out << '_'; } -void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { +void CXXNameMangler::mangleCXXCtorType(CXXCtorType T, + const CXXRecordDecl *InheritedFrom) { // <ctor-dtor-name> ::= C1 # complete object constructor // ::= C2 # base object constructor + // ::= CI1 <type> # complete inheriting constructor + // ::= CI2 <type> # base inheriting constructor // // In addition, C5 is a comdat name with C1 and C2 in it. + Out << 'C'; + if (InheritedFrom) + Out << 'I'; switch (T) { case Ctor_Complete: - Out << "C1"; + Out << '1'; break; case Ctor_Base: - Out << "C2"; + Out << '2'; break; case Ctor_Comdat: - Out << "C5"; + Out << '5'; break; case Ctor_DefaultClosure: case Ctor_CopyingClosure: llvm_unreachable("closure constructors don't exist for the Itanium ABI!"); } + if (InheritedFrom) + mangleName(InheritedFrom); } void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { |