aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h7
-rw-r--r--include/clang/AST/DeclCXX.h17
-rw-r--r--include/clang/AST/ExprCXX.h8
-rw-r--r--include/clang/AST/LambdaMangleContext.h36
-rw-r--r--include/clang/Sema/Sema.h5
-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
-rw-r--r--lib/Parse/ParseExprCXX.cpp3
-rw-r--r--lib/Sema/SemaLambda.cpp14
-rw-r--r--lib/Sema/TreeTransform.h3
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp1
-rw-r--r--lib/Serialization/ASTWriter.cpp1
-rw-r--r--test/CodeGenCXX/lambda-expressions.cpp32
-rw-r--r--test/CodeGenCXX/mangle-lambdas.cpp22
17 files changed, 206 insertions, 29 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 9ed70dfb4b..1082806834 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -21,6 +21,7 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/VersionTuple.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/LambdaMangleContext.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateName.h"
@@ -326,6 +327,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// expression used to copy the lambda object.
llvm::DenseMap<const CXXConversionDecl *, Expr *> LambdaBlockPointerInits;
+ /// \brief Mapping from each declaration context to its corresponding lambda
+ /// mangling context.
+ llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts;
+
friend class CXXConversionDecl;
/// \brief Mapping that stores parameterIndex values for ParmVarDecls
@@ -1765,6 +1770,8 @@ public:
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
+ /// \brief Retrieve the lambda mangling number for a lambda expression.
+ unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator);
/// \brief Used by ParmVarDecl to store on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 5db16ed1dc..15c37813de 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -569,8 +569,12 @@ class CXXRecordDecl : public RecordDecl {
unsigned NumCaptures : 16;
/// \brief The number of explicit captures in this lambda.
- unsigned NumExplicitCaptures : 15;
+ unsigned NumExplicitCaptures : 16;
+ /// \brief The number used to indicate this lambda expression for name
+ /// mangling in the Itanium C++ ABI.
+ unsigned ManglingNumber;
+
/// \brief The "extra" data associated with the lambda, including
/// captures, capture initializers, the body of the lambda, and the
/// array-index variables for array captures.
@@ -1442,6 +1446,17 @@ public:
/// actually abstract.
bool mayBeAbstract() const;
+ /// \brief If this is the closure type of a lambda expression, retrieve the
+ /// number to be used for name mangling in the Itanium C++ ABI.
+ ///
+ /// Zero indicates that this closure type has internal linkage, so the
+ /// mangling number does not matter, while a non-zero value indicates which
+ /// lambda expression this is in this particular context.
+ unsigned getLambdaManglingNumber() const {
+ assert(isLambda() && "Not a lambda closure type!");
+ return getLambdaData().ManglingNumber;
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
return K >= firstCXXRecord && K <= lastCXXRecord;
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 458c96f3b5..0d3b86269f 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1166,7 +1166,8 @@ private:
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace);
+ SourceLocation ClosingBrace,
+ unsigned ManglingNumber);
/// \brief Construct an empty lambda expression.
LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
@@ -1204,7 +1205,8 @@ public:
ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace);
+ SourceLocation ClosingBrace,
+ unsigned ManglingNumber);
/// \brief Construct a new lambda expression that will be deserialized from
/// an external source.
@@ -1296,7 +1298,7 @@ public:
/// \brief Whether this lambda had its result type explicitly specified.
bool hasExplicitResultType() const { return ExplicitResultType; }
-
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == LambdaExprClass;
}
diff --git a/include/clang/AST/LambdaMangleContext.h b/include/clang/AST/LambdaMangleContext.h
new file mode 100644
index 0000000000..3e2fbad2f8
--- /dev/null
+++ b/include/clang/AST/LambdaMangleContext.h
@@ -0,0 +1,36 @@
+//===--- LambdaMangleContext.h - 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 interface, which keeps track of
+// the Itanium C++ ABI mangling numbers for lambda expressions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H
+#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class CXXMethodDecl;
+class FunctionProtoType;
+
+/// \brief Keeps track of the mangled names of lambda expressions within a
+/// particular context.
+class LambdaMangleContext {
+ llvm::DenseMap<const FunctionProtoType *, unsigned> ManglingNumbers;
+
+public:
+ /// \brief Retrieve the mangling number of a new lambda expression with the
+ /// given call operator within this lambda context.
+ unsigned getManglingNumber(CXXMethodDecl *CallOperator);
+};
+
+} // end namespace clang
+#endif
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index bd285c78b9..5df80891f3 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -3555,7 +3555,10 @@ public:
/// ActOnLambdaExpr - This is called when the body of a lambda expression
/// was successfully completed.
ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
- Scope *CurScope, bool IsInstantiation = false);
+ Scope *CurScope,
+ llvm::Optional<unsigned> ManglingNumber
+ = llvm::Optional<unsigned>(),
+ bool IsInstantiation = false);
/// \brief Define the "body" of the conversion from a lambda object to a
/// function pointer.
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>()];
+}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 0d33e30183..fecf7b7765 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -886,8 +886,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
BodyScope.Exit();
if (!Stmt.isInvalid())
- return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(),
- getCurScope());
+ return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), getCurScope());
Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope());
return ExprError();
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 1a362d48e2..d1f87a2c18 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -483,7 +483,9 @@ static void addBlockPointerConversion(Sema &S,
}
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
- Scope *CurScope, bool IsInstantiation) {
+ Scope *CurScope,
+ llvm::Optional<unsigned> ManglingNumber,
+ bool IsInstantiation) {
// Leave the expression-evaluation context.
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
@@ -633,11 +635,19 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
if (LambdaExprNeedsCleanups)
ExprNeedsCleanups = true;
+ // If we don't already have a mangling number for this lambda expression,
+ // allocate one now.
+ if (!ManglingNumber) {
+ // FIXME: Default arguments, data member initializers are special.
+ ManglingNumber = Context.getLambdaManglingNumber(CallOperator);
+ }
+
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
CaptureDefault, Captures,
ExplicitParams, ExplicitResultType,
CaptureInits, ArrayIndexVars,
- ArrayIndexStarts, Body->getLocEnd());
+ ArrayIndexStarts, Body->getLocEnd(),
+ *ManglingNumber);
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 8a47a37d1c..7e095f7336 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -7769,8 +7769,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
return ExprError();
}
+ unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(),
- /*CurScope=*/0,
+ /*CurScope=*/0, ManglingNumber,
/*IsInstantiation=*/true);
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 6e044fd0db..b7d6a91dfe 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1105,6 +1105,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
= static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
Lambda.NumCaptures = Record[Idx++];
Lambda.NumExplicitCaptures = Record[Idx++];
+ Lambda.ManglingNumber = Record[Idx++];
Lambda.Captures
= (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
Capture *ToCapture = Lambda.Captures;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 48b14e3bd7..add89ea8e2 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -4332,6 +4332,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData();
Record.push_back(Lambda.NumCaptures);
Record.push_back(Lambda.NumExplicitCaptures);
+ Record.push_back(Lambda.ManglingNumber);
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
LambdaExpr::Capture &Capture = Lambda.Captures[I];
AddSourceLocation(Capture.getLocation(), Record);
diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp
index e1aab1889c..203ca4d805 100644
--- a/test/CodeGenCXX/lambda-expressions.cpp
+++ b/test/CodeGenCXX/lambda-expressions.cpp
@@ -2,8 +2,8 @@
int a() { return []{ return 1; }(); }
// CHECK: define i32 @_Z1av
-// CHECK: call i32 @"_ZZ1avENK3$_0clEv"
-// CHECK: define internal i32 @"_ZZ1avENK3$_0clEv"
+// CHECK: call i32 @_ZZ1avENKUlvE_clEv
+// CHECK: define internal i32 @_ZZ1avENKUlvE_clEv
// CHECK: ret i32 1
int b(int x) { return [x]{return x;}(); }
@@ -11,8 +11,8 @@ int b(int x) { return [x]{return x;}(); }
// CHECK: store i32
// CHECK: load i32*
// CHECK: store i32
-// CHECK: call i32 @"_ZZ1biENK3$_1clEv"
-// CHECK: define internal i32 @"_ZZ1biENK3$_1clEv"
+// CHECK: call i32 @_ZZ1biENKUlvE_clEv
+// CHECK: define internal i32 @_ZZ1biENKUlvE_clEv
// CHECK: load i32*
// CHECK: ret i32
@@ -20,8 +20,8 @@ int c(int x) { return [&x]{return x;}(); }
// CHECK: define i32 @_Z1ci
// CHECK: store i32
// CHECK: store i32*
-// CHECK: call i32 @"_ZZ1ciENK3$_2clEv"
-// CHECK: define internal i32 @"_ZZ1ciENK3$_2clEv"
+// CHECK: call i32 @_ZZ1ciENKUlvE_clEv
+// CHECK: define internal i32 @_ZZ1ciENKUlvE_clEv
// CHECK: load i32**
// CHECK: load i32*
// CHECK: ret i32
@@ -33,8 +33,8 @@ int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
// CHECK: call void @_ZN1DC1Ev
// CHECK: icmp ult i64 %{{.*}}, 10
// CHECK: call void @_ZN1DC1ERKS_
-// CHECK: call i32 @"_ZZ1diENK3$_3clEv"
-// CHECK: define internal i32 @"_ZZ1diENK3$_3clEv"
+// CHECK: call i32 @_ZZ1diENKUlvE_clEv
+// CHECK: define internal i32 @_ZZ1diENKUlvE_clEv
// CHECK: load i32*
// CHECK: load i32*
// CHECK: ret i32
@@ -44,29 +44,29 @@ int e(E a, E b, bool cond) { [a,b,cond](){ return (cond ? a : b).x; }(); }
// CHECK: define i32 @_Z1e1ES_b
// CHECK: call void @_ZN1EC1ERKS_
// CHECK: invoke void @_ZN1EC1ERKS_
-// CHECK: invoke i32 @"_ZZ1e1ES_bENK3$_4clEv"
-// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev"
-// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev"
+// CHECK: invoke i32 @_ZZ1e1ES_bENKUlvE_clEv
+// CHECK: call void @_ZZ1e1ES_bENUlvE_D1Ev
+// CHECK: call void @_ZZ1e1ES_bENUlvE_D1Ev
-// CHECK: define internal i32 @"_ZZ1e1ES_bENK3$_4clEv"
+// CHECK: define internal i32 @_ZZ1e1ES_bENKUlvE_clEv
// CHECK: trunc i8
// CHECK: load i32*
// CHECK: ret i32
void f() {
// CHECK: define void @_Z1fv()
- // CHECK: {{call.*_5cvPFiiiEEv}}
+ // CHECK: {{call.*@_ZZ1fvENKUliiE_cvPFiiiEEv}}
// CHECK-NEXT: store i32 (i32, i32)*
// CHECK-NEXT: ret void
int (*fp)(int, int) = [](int x, int y){ return x + y; };
}
-// CHECK: define internal i32 @"_ZZ1fvEN3$_58__invokeEii"
+// CHECK: define internal i32 @_ZZ1fvENUliiE_8__invokeEii
// CHECK: store i32
// CHECK-NEXT: store i32
// CHECK-NEXT: load i32*
// CHECK-NEXT: load i32*
-// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_5clEii"
+// CHECK-NEXT: call i32 @_ZZ1fvENKUliiE_clEii
// CHECK-NEXT: ret i32
-// CHECK: define internal void @"_ZZ1e1ES_bEN3$_4D2Ev"
+// CHECK: define internal void @_ZZ1e1ES_bENUlvE_D2Ev
diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp
new file mode 100644
index 0000000000..b2376648c2
--- /dev/null
+++ b/test/CodeGenCXX/mangle-lambdas.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: define linkonce_odr void @_Z11inline_funci
+inline void inline_func(int n) {
+ // CHECK: call i32 @_ZZ11inline_funciENKUlvE_clEv
+ int i = []{ return 1; }();
+
+ // CHECK: call i32 @_ZZ11inline_funciENKUlvE0_clEv
+ int j = [=] { return n + i; }();
+
+ // CHECK: call double @_ZZ11inline_funciENKUlvE1_clEv
+ int k = [=] () -> double { return n + i; }();
+
+ // CHECK: call i32 @_ZZ11inline_funciENKUliE_clEi
+ int l = [=] (int x) -> int { return x + i; }(n);
+
+ // CHECK: ret void
+}
+
+void call_inline_func() {
+ inline_func(17);
+}