diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 7 | ||||
-rw-r--r-- | lib/AST/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 9 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 39 | ||||
-rw-r--r-- | lib/AST/LambdaMangleContext.cpp | 30 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 3 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 1 |
10 files changed, 100 insertions, 8 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>()]; +} 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); |