[cfe-commits] r160614 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/TreeTransform.h test/CodeGenCXX/mangle-lambdas.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Sun Jul 22 16:45:10 PDT 2012
Author: rsmith
Date: Sun Jul 22 18:45:10 2012
New Revision: 160614
URL: http://llvm.org/viewvc/llvm-project?rev=160614&view=rev
Log:
PR12917: Remove incorrect assumption that lambda mangling information cannot
change once it's been assigned. It can change in two ways:
1) In a template instantiation, the context declaration should be the
instantiated declaration, not the declaration in the template.
2) If a lambda appears in the pattern of a variadic pack expansion, the
mangling number will depend on the pack length.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaLambda.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=160614&r1=160613&r2=160614&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sun Jul 22 18:45:10 2012
@@ -4014,10 +4014,7 @@
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
SourceLocation EndLoc,
- llvm::ArrayRef<ParmVarDecl *> Params,
- llvm::Optional<unsigned> ManglingNumber
- = llvm::Optional<unsigned>(),
- Decl *ContextDecl = 0);
+ llvm::ArrayRef<ParmVarDecl *> Params);
/// \brief Introduce the scope for a lambda expression.
sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=160614&r1=160613&r2=160614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Jul 22 18:45:10 2012
@@ -3380,6 +3380,9 @@
if (Param->hasUninstantiatedDefaultArg()) {
Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
+ EnterExpressionEvaluationContext EvalContext(*this, PotentiallyEvaluated,
+ Param);
+
// Instantiate the expression.
MultiLevelTemplateArgumentList ArgList
= getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=160614&r1=160613&r2=160614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Sun Jul 22 18:45:10 2012
@@ -54,9 +54,7 @@
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
SourceLocation EndLoc,
- llvm::ArrayRef<ParmVarDecl *> Params,
- llvm::Optional<unsigned> ManglingNumber,
- Decl *ContextDecl) {
+ llvm::ArrayRef<ParmVarDecl *> Params) {
// C++11 [expr.prim.lambda]p5:
// The closure type for a lambda-expression has a public inline function
// call operator (13.5.4) whose parameters and return type are described by
@@ -98,64 +96,76 @@
P != PEnd; ++P)
(*P)->setOwningFunction(Method);
}
-
- // If we don't already have a mangling number for this lambda expression,
- // allocate one now.
- if (!ManglingNumber) {
- ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
-
- enum ContextKind {
- Normal,
- DefaultArgument,
- DataMember,
- StaticDataMember
- } Kind = Normal;
-
- // Default arguments of member function parameters that appear in a class
- // definition, as well as the initializers of data members, receive special
- // treatment. Identify them.
- if (ContextDecl) {
- if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
- if (const DeclContext *LexicalDC
- = Param->getDeclContext()->getLexicalParent())
- if (LexicalDC->isRecord())
- Kind = DefaultArgument;
- } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
- if (Var->getDeclContext()->isRecord())
- Kind = StaticDataMember;
- } else if (isa<FieldDecl>(ContextDecl)) {
- Kind = DataMember;
- }
- }
-
- switch (Kind) {
- case Normal:
- if (CurContext->isDependentContext() || isInInlineFunction(CurContext))
- ManglingNumber = Context.getLambdaManglingNumber(Method);
- else
- ManglingNumber = 0;
-
- // There is no special context for this lambda.
- ContextDecl = 0;
- break;
-
- 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(Method);
- break;
+
+ // Allocate a mangling number for this lambda expression, if the ABI
+ // requires one.
+ Decl *ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
+
+ enum ContextKind {
+ Normal,
+ DefaultArgument,
+ DataMember,
+ StaticDataMember
+ } Kind = Normal;
+
+ // Default arguments of member function parameters that appear in a class
+ // definition, as well as the initializers of data members, receive special
+ // treatment. Identify them.
+ if (ContextDecl) {
+ if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) {
+ if (const DeclContext *LexicalDC
+ = Param->getDeclContext()->getLexicalParent())
+ if (LexicalDC->isRecord())
+ Kind = DefaultArgument;
+ } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) {
+ if (Var->getDeclContext()->isRecord())
+ Kind = StaticDataMember;
+ } else if (isa<FieldDecl>(ContextDecl)) {
+ Kind = DataMember;
}
}
- Class->setLambdaMangling(*ManglingNumber, ContextDecl);
+ // Itanium ABI [5.1.7]:
+ // In the following contexts [...] the one-definition rule requires closure
+ // types in different translation units to "correspond":
+ bool IsInNonspecializedTemplate =
+ !ActiveTemplateInstantiations.empty() || CurContext->isDependentContext();
+ unsigned ManglingNumber;
+ switch (Kind) {
+ case Normal:
+ // -- the bodies of non-exported nonspecialized template functions
+ // -- the bodies of inline functions
+ if ((IsInNonspecializedTemplate &&
+ !(ContextDecl && isa<ParmVarDecl>(ContextDecl))) ||
+ isInInlineFunction(CurContext))
+ ManglingNumber = Context.getLambdaManglingNumber(Method);
+ else
+ ManglingNumber = 0;
+
+ // There is no special context for this lambda.
+ ContextDecl = 0;
+ break;
+
+ case StaticDataMember:
+ // -- the initializers of nonspecialized static members of template classes
+ if (!IsInNonspecializedTemplate) {
+ ManglingNumber = 0;
+ ContextDecl = 0;
+ break;
+ }
+ // Fall through to assign a mangling number.
+
+ case DataMember:
+ // -- the in-class initializers of class members
+ case DefaultArgument:
+ // -- default arguments appearing in class definitions
+ ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
+ .getManglingNumber(Method);
+ break;
+ }
+
+ Class->setLambdaMangling(ManglingNumber, ContextDecl);
+
return Method;
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=160614&r1=160613&r2=160614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Jul 22 18:45:10 2012
@@ -341,9 +341,9 @@
// We already have an initializer in the class.
} else if (D->getInit()) {
if (Var->isStaticDataMember() && !D->isOutOfLine())
- SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated);
+ SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated, D);
else
- SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+ SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, D);
// Instantiate the initializer.
ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs,
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=160614&r1=160613&r2=160614&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sun Jul 22 18:45:10 2012
@@ -7904,15 +7904,11 @@
Invalid = true;
// Build the call operator.
- // Note: Once a lambda mangling number and context declaration have been
- // assigned, they never change.
- unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber();
- Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl();
CXXMethodDecl *CallOperator
= getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
- MethodTy,
+ MethodTy,
E->getCallOperator()->getLocEnd(),
- Params, ManglingNumber, ContextDecl);
+ Params);
getDerived().transformAttrs(E->getCallOperator(), CallOperator);
// FIXME: Instantiation-specific.
Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=160614&r1=160613&r2=160614&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Sun Jul 22 18:45:10 2012
@@ -1,5 +1,10 @@
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s | FileCheck %s
+// CHECK: @_ZZNK7PR12917IJiiEE1nMUlvE_clEvE1n = linkonce_odr global i32 0
+// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd_N1nE = linkonce_odr global i32 0
+// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd0_N1nE = linkonce_odr global i32 0
+// CHECK: @_ZZN7PR12917IJicdEEC1EicdEd1_N1nE = linkonce_odr global i32 0
+
// CHECK: define linkonce_odr void @_Z11inline_funci
inline void inline_func(int n) {
// CHECK: call i32 @_ZZ11inline_funciENKUlvE_clEv
@@ -78,10 +83,10 @@
// CHECK: define void @_Z7test_ST2STIdE
void test_ST(ST<double> st) {
- // CHECK: call double @_ZZN2ST1fET_S0_Ed0_NKUlvE_clEv
- // CHECK-NEXT: call double @_ZZN2ST1fET_S0_Ed0_NKUlvE0_clEv
+ // CHECK: call double @_ZZN2STIdE1fEddEd0_NKUlvE_clEv
+ // CHECK-NEXT: call double @_ZZN2STIdE1fEddEd0_NKUlvE0_clEv
// CHECK-NEXT: fadd double
- // CHECK-NEXT: call double @_ZZN2ST1fET_S0_Ed_NKUlvE_clEv
+ // CHECK-NEXT: call double @_ZZN2STIdE1fEddEd_NKUlvE_clEv
// CHECK-NEXT: call void @_ZN2STIdE1fEdd
st.f();
@@ -89,11 +94,11 @@
}
// Check the linkage of the lambda call operators used in test_ST.
-// CHECK: define linkonce_odr double @_ZZN2ST1fET_S0_Ed0_NKUlvE_clEv
+// CHECK: define linkonce_odr double @_ZZN2STIdE1fEddEd0_NKUlvE_clEv
// CHECK: ret double 1
-// CHECK: define linkonce_odr double @_ZZN2ST1fET_S0_Ed0_NKUlvE0_clEv
+// CHECK: define linkonce_odr double @_ZZN2STIdE1fEddEd0_NKUlvE0_clEv
// CHECK: ret double 2
-// CHECK: define linkonce_odr double @_ZZN2ST1fET_S0_Ed_NKUlvE_clEv
+// CHECK: define linkonce_odr double @_ZZN2STIdE1fEddEd_NKUlvE_clEv
// CHECK: ret double 3
template<typename T>
@@ -150,6 +155,24 @@
func_template<int>();
}
+
+template<typename...T> struct PR12917 {
+ PR12917(T ...t = []{ static int n = 0; return ++n; }());
+
+ static int n[3];
+};
+template<typename...T> int PR12917<T...>::n[3] = {
+ []{ static int n = 0; return ++n; }()
+};
+
+// CHECK: call i32 @_ZZN7PR12917IJicdEEC1EicdEd1_NKUlvE_clEv(
+// CHECK: call i32 @_ZZN7PR12917IJicdEEC1EicdEd0_NKUlvE_clEv(
+// CHECK: call i32 @_ZZN7PR12917IJicdEEC1EicdEd_NKUlvE_clEv(
+// CHECK: call void @_ZN7PR12917IJicdEEC1Eicd(
+PR12917<int, char, double> pr12917;
+int *pr12917_p = PR12917<int, int>::n;
+
+
// CHECK: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_
struct Members {
More information about the cfe-commits
mailing list