aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-21 04:17:39 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-21 04:17:39 +0000
commit5878cbcfaa90b8515550db86033fd5a0efab971d (patch)
tree7cb574e300ff00ea50204363fbc09578a8f8f9f9 /lib
parent702afbc68b933af520420688cdf6783b411a8f70 (diff)
Implement non-internal linkage for lambda closure types that need a
stable mangling, since these lambdas can end up in multiple translation units. Sema is responsible for deciding when this is the case, because it's already responsible for choosing the mangling number. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151029 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp26
-rw-r--r--lib/AST/ExprCXX.cpp5
-rw-r--r--lib/AST/ItaniumMangle.cpp12
-rw-r--r--lib/Sema/SemaLambda.cpp39
4 files changed, 70 insertions, 12 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d80e06b322..4d1b562c59 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -734,6 +734,32 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
return LinkageInfo::external();
+
+ case Decl::CXXRecord: {
+ const CXXRecordDecl *Record = cast<CXXRecordDecl>(D);
+ if (Record->isLambda()) {
+ if (!Record->getLambdaManglingNumber()) {
+ // This lambda has no mangling number, so it's internal.
+ return LinkageInfo::internal();
+ }
+
+ // This lambda has its linkage/visibility determined by its owner.
+ const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+ if (Decl *ContextDecl = Record->getLambdaContextDecl()) {
+ if (isa<ParmVarDecl>(ContextDecl))
+ DC = ContextDecl->getDeclContext()->getRedeclContext();
+ else
+ return getLVForDecl(cast<NamedDecl>(ContextDecl), Flags);
+ }
+
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
+ return getLVForDecl(ND, Flags);
+
+ return LinkageInfo::external();
+ }
+
+ break;
+ }
}
// Handle linkage for namespace-scope names.
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 98664b2a7c..7ef3417e6d 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -815,7 +815,10 @@ LambdaExpr::LambdaExpr(QualType T,
memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(),
sizeof(unsigned) * Captures.size());
getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
- }
+ }
+
+ if (ManglingNumber)
+ Class->ClearLinkageCache();
}
LambdaExpr *LambdaExpr::Create(ASTContext &Context,
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 47f50cf078..5e167f58dc 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -52,7 +52,7 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
if (RD->isLambda())
if (ParmVarDecl *ContextParam
- = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+ = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
return ContextParam->getDeclContext();
}
@@ -1114,7 +1114,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// <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()) {
+ if (Record->isLambda() && Record->getLambdaManglingNumber()) {
mangleLambda(Record);
break;
}
@@ -1347,10 +1347,10 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
// (in lexical order) with that same <lambda-sig> and context.
//
// The AST keeps track of the number for us.
- if (unsigned Number = Lambda->getLambdaManglingNumber()) {
- if (Number > 1)
- mangleNumber(Number - 2);
- }
+ unsigned Number = Lambda->getLambdaManglingNumber();
+ assert(Number > 0 && "Lambda should be mangled as an unnamed class");
+ if (Number > 1)
+ mangleNumber(Number - 2);
Out << '_';
}
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 7b729e7018..867049d456 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -13,6 +13,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Lex/Preprocessor.h"
@@ -482,6 +483,20 @@ static void addBlockPointerConversion(Sema &S,
Class->addDecl(Conversion);
}
+/// \brief Determine whether the given context is or is enclosed in an inline
+/// function.
+static bool isInInlineFunction(const DeclContext *DC) {
+ while (!DC->isFileContext()) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
+ if (FD->isInlined())
+ return true;
+
+ DC = DC->getLexicalParent();
+ }
+
+ return false;
+}
+
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope,
llvm::Optional<unsigned> ManglingNumber,
@@ -644,7 +659,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
enum ContextKind {
Normal,
DefaultArgument,
- DataMember
+ DataMember,
+ StaticDataMember,
} Kind = Normal;
// Default arguments of member function parameters that appear in a class
@@ -658,7 +674,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Kind = DefaultArgument;
} else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
if (Var->getDeclContext()->isRecord())
- Kind = DataMember;
+ Kind = StaticDataMember;
} else if (isa<FieldDecl>(ContextDecl)) {
Kind = DataMember;
}
@@ -666,12 +682,25 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
switch (Kind) {
case Normal:
- ManglingNumber = Context.getLambdaManglingNumber(CallOperator);
- ContextDecl = 0;
+ if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
+ ManglingNumber = Context.getLambdaManglingNumber(CallOperator);
+ else
+ ManglingNumber = 0;
+
+ // There is no special context for this lambda.
+ ContextDecl = 0;
break;
- case DefaultArgument:
+ case StaticDataMember:
+ if (!CurContext->isDependentContext()) {
+ ManglingNumber = 0;
+ ContextDecl = 0;
+ break;
+ }
+ // Fall through to assign a mangling number.
+
case DataMember:
+ case DefaultArgument:
ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
.getManglingNumber(CallOperator);
break;