aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-20 19:44:39 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-20 19:44:39 +0000
commit9e8c92a9c9b949bbb0408fbbd9a58e34894b6efc (patch)
tree9579005bf62f65f14d6478c74c2c36096d691398 /lib/AST
parent86211df4d28f6fb3c48ab09f02a011e8570d8b1c (diff)
Basic support for name mangling of C++11 lambda expressions. Because
name mangling in the Itanium C++ ABI for lambda expressions is so dependent on context, we encode the number used to encode each lambda as part of the lambda closure type, and maintain this value within Sema. Note that there are a several pieces still missing: - We still get the linkage of lambda expressions wrong - We aren't properly numbering or mangling lambda expressions that occur in default function arguments or in data member initializers. - We aren't (de-)serializing the lambda numbering tables git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150982 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTContext.cpp7
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/ExprCXX.cpp9
-rw-r--r--lib/AST/ItaniumMangle.cpp39
-rw-r--r--lib/AST/LambdaMangleContext.cpp30
5 files changed, 83 insertions, 3 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index cc651f9c9c..e0056da60b 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -6748,6 +6748,13 @@ size_t ASTContext::getSideTableAllocatedMemory() const {
+ llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
}
+unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) {
+ CXXRecordDecl *Lambda = CallOperator->getParent();
+ return LambdaMangleContexts[Lambda->getDeclContext()]
+ .getManglingNumber(CallOperator);
+}
+
+
void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
ParamIndices[D] = index;
}
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 1f0100a580..651bcc4857 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -28,6 +28,7 @@ add_clang_library(clangAST
InheritViz.cpp
ItaniumCXXABI.cpp
ItaniumMangle.cpp
+ LambdaMangleContext.cpp
Mangle.cpp
MicrosoftCXXABI.cpp
MicrosoftMangle.cpp
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index f52f881050..cbc5950f83 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -764,7 +764,8 @@ LambdaExpr::LambdaExpr(QualType T,
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace)
+ SourceLocation ClosingBrace,
+ unsigned ManglingNumber)
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
T->isDependentType(), T->isDependentType(), T->isDependentType(),
/*ContainsUnexpandedParameterPack=*/false),
@@ -785,6 +786,7 @@ LambdaExpr::LambdaExpr(QualType T,
ASTContext &Context = Class->getASTContext();
Data.NumCaptures = NumCaptures;
Data.NumExplicitCaptures = 0;
+ Data.ManglingNumber = ManglingNumber;
Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures);
Capture *ToCapture = Data.Captures;
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
@@ -824,7 +826,8 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace) {
+ SourceLocation ClosingBrace,
+ unsigned ManglingNumber) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
QualType T = Context.getTypeDeclType(Class);
@@ -837,7 +840,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault,
Captures, ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars, ArrayIndexStarts,
- ClosingBrace);
+ ClosingBrace, ManglingNumber);
}
LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures,
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 4843716909..a0bb6c74c3 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -122,6 +122,13 @@ public:
}
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
+ // Lambda closure types with external linkage (indicated by a
+ // non-zero lambda mangling number) have their own numbering scheme, so
+ // they do not need a discriminator.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND))
+ if (RD->isLambda() && RD->getLambdaManglingNumber() > 0)
+ return false;
+
unsigned &discriminator = Uniquifier[ND];
if (!discriminator)
discriminator = ++Discriminator;
@@ -1076,6 +1083,38 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
break;
}
+ // <unnamed-type-name> ::= <closure-type-name>
+ //
+ // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
+ // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'.
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
+ if (Record->isLambda()) {
+ // FIXME: Figure out if we're in a function body, default argument,
+ // or initializer for a class member.
+
+ Out << "Ul";
+ DeclarationName Name
+ = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
+ const FunctionProtoType *Proto
+ = cast<CXXMethodDecl>(*Record->lookup(Name).first)->getType()->
+ getAs<FunctionProtoType>();
+ mangleBareFunctionType(Proto, /*MangleReturnType=*/false);
+ Out << "E";
+
+ // The number is omitted for the first closure type with a given
+ // <lambda-sig> in a given context; it is n-2 for the nth closure type
+ // (in lexical order) with that same <lambda-sig> and context.
+ //
+ // The AST keeps track of the number for us.
+ if (unsigned Number = Record->getLambdaManglingNumber()) {
+ if (Number > 1)
+ mangleNumber(Number - 2);
+ }
+ Out << '_';
+ break;
+ }
+ }
+
// Get a unique id for the anonymous struct.
uint64_t AnonStructId = Context.getAnonymousStructId(TD);
diff --git a/lib/AST/LambdaMangleContext.cpp b/lib/AST/LambdaMangleContext.cpp
new file mode 100644
index 0000000000..f5272a7fdb
--- /dev/null
+++ b/lib/AST/LambdaMangleContext.cpp
@@ -0,0 +1,30 @@
+//===--- LambdaMangleContext.cpp - Context for mangling lambdas -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LambdaMangleContext class, which keeps track of
+// the Itanium C++ ABI mangling numbers for lambda expressions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/LambdaMangleContext.h"
+#include "clang/AST/DeclCXX.h"
+
+using namespace clang;
+
+unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl *CallOperator) {
+ const FunctionProtoType *Proto
+ = CallOperator->getType()->getAs<FunctionProtoType>();
+ ASTContext &Context = CallOperator->getASTContext();
+
+ QualType Key = Context.getFunctionType(Context.VoidTy,
+ Proto->arg_type_begin(),
+ Proto->getNumArgs(),
+ FunctionProtoType::ExtProtoInfo());
+ Key = Context.getCanonicalType(Key);
+ return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
+}