[cfe-commits] r151011 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclCXX.h include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/AST/ExprCXX.cpp lib/AST/ItaniumMangle.cpp lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDecl.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaLambda.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp test/CodeGenCXX/mangle-lambdas.cpp

Douglas Gregor dgregor at apple.com
Mon Feb 20 16:37:25 PST 2012


Author: dgregor
Date: Mon Feb 20 18:37:24 2012
New Revision: 151011

URL: http://llvm.org/viewvc/llvm-project?rev=151011&view=rev
Log:
Implement name mangling for lambda expressions that occur within the
default arguments of function parameters. This simple-sounding task is
complicated greatly by two issues:

  (1) Default arguments aren't actually a real context, so we need to
  maintain extra state within lambda expressions to track when a
  lambda was actually in a default argument.
  (2) At the time that we parse a default argument, the FunctionDecl
  doesn't exist yet, so lambda closure types end up in the enclosing
  context. It's not clear that we ever want to change that, so instead
  we introduce the notion of the "effective" context of a declaration
  for the purposes of name mangling.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Feb 20 18:37:24 2012
@@ -327,12 +327,12 @@
   /// expression used to copy the lambda object.
   llvm::DenseMap<const CXXConversionDecl *, Expr *> LambdaBlockPointerInits;
   
+  friend class CXXConversionDecl;
+  
   /// \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
   /// when that value exceeds the bitfield size of
   /// ParmVarDeclBits.ParameterIndex.

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Feb 20 18:37:24 2012
@@ -561,7 +561,9 @@
     typedef LambdaExpr::Capture Capture;
     
     LambdaDefinitionData(CXXRecordDecl *D) 
-      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), Captures(0) { 
+      : DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), 
+        ContextDecl(0), Captures(0) 
+    {
       IsLambda = true;
     }
 
@@ -575,9 +577,14 @@
     /// 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.
+    /// \brief The declaration that provides context for this lambda, if the
+    /// actual DeclContext does not suffice. This is used for lambdas that
+    /// occur within default arguments of function parameters within the class
+    /// or within a data member initializer.
+    Decl *ContextDecl;
+    
+    /// \brief The list of captures, both explicit and implicit, for this 
+    /// lambda.
     Capture *Captures;    
   };
 
@@ -1457,6 +1464,20 @@
     return getLambdaData().ManglingNumber;
   }
   
+  /// \brief Retrieve the declaration that provides additional context for a 
+  /// lambda, when the normal declaration context is not specific enough.
+  ///
+  /// Certain contexts (default arguments of in-class function parameters and 
+  /// the initializers of data members) have separate name mangling rules for
+  /// lambdas within the Itanium C++ ABI. For these cases, this routine provides
+  /// the declaration in which the lambda occurs, e.g., the function parameter 
+  /// or the non-static data member. Otherwise, it returns NULL to imply that
+  /// the declaration context suffices.
+  Decl *getLambdaContextDecl() const {
+    assert(isLambda() && "Not a lambda closure type!");
+    return getLambdaData().ContextDecl;    
+  }
+  
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) {
     return K >= firstCXXRecord && K <= lastCXXRecord;

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Feb 20 18:37:24 2012
@@ -1167,7 +1167,8 @@
              ArrayRef<VarDecl *> ArrayIndexVars,
              ArrayRef<unsigned> ArrayIndexStarts,
              SourceLocation ClosingBrace,
-             unsigned ManglingNumber);
+             unsigned ManglingNumber,
+             Decl *ContextDecl);
 
   /// \brief Construct an empty lambda expression.
   LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
@@ -1206,7 +1207,8 @@
                             ArrayRef<VarDecl *> ArrayIndexVars,
                             ArrayRef<unsigned> ArrayIndexStarts,
                             SourceLocation ClosingBrace,
-                            unsigned ManglingNumber);
+                            unsigned ManglingNumber,
+                            Decl *ContextDecl);
 
   /// \brief Construct a new lambda expression that will be deserialized from
   /// an external source.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Feb 20 18:37:24 2012
@@ -572,11 +572,37 @@
     /// is indeed an unevaluated context.
     llvm::SmallVector<LambdaExpr *, 2> Lambdas;
 
+    /// \brief The declaration that provides context for the lambda expression
+    /// if the normal declaration context does not suffice, e.g., in a 
+    /// default function argument.
+    Decl *LambdaContextDecl;
+    
+    /// \brief The context information used to mangle lambda expressions
+    /// within this context.
+    ///
+    /// This mangling information is allocated lazily, since most contexts
+    /// do not have lambda expressions.
+    LambdaMangleContext *LambdaMangle;
+    
     ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
                                       unsigned NumCleanupObjects,
-                                      bool ParentNeedsCleanups)
+                                      bool ParentNeedsCleanups,
+                                      Decl *LambdaContextDecl)
       : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
-        NumCleanupObjects(NumCleanupObjects) { }
+        NumCleanupObjects(NumCleanupObjects), 
+        LambdaContextDecl(LambdaContextDecl), LambdaMangle() { }
+    
+    ~ExpressionEvaluationContextRecord() {
+      delete LambdaMangle;
+    }
+    
+    /// \brief Retrieve the mangling context for lambdas.
+    LambdaMangleContext &getLambdaMangleContext() {
+      assert(LambdaContextDecl && "Need to have a lambda context declaration");
+      if (!LambdaMangle)
+        LambdaMangle = new LambdaMangleContext;
+      return *LambdaMangle;
+    }
   };
 
   /// A stack of expression evaluation contexts.
@@ -2288,7 +2314,8 @@
   void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
                              Expr **Args, unsigned NumArgs);
 
-  void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
+  void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
+                                       Decl *LambdaContextDecl = 0);
 
   void PopExpressionEvaluationContext();
 
@@ -3558,6 +3585,7 @@
                              Scope *CurScope, 
                              llvm::Optional<unsigned> ManglingNumber 
                                = llvm::Optional<unsigned>(),
+                             Decl *ContextDecl = 0,
                              bool IsInstantiation = false);
 
   /// \brief Define the "body" of the conversion from a lambda object to a 
@@ -6541,9 +6569,10 @@
 
 public:
   EnterExpressionEvaluationContext(Sema &Actions,
-                                   Sema::ExpressionEvaluationContext NewContext)
+                                   Sema::ExpressionEvaluationContext NewContext,
+                                   Decl *LambdaContextDecl = 0)
     : Actions(Actions) {
-    Actions.PushExpressionEvaluationContext(NewContext);
+    Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl);
   }
 
   ~EnterExpressionEvaluationContext() {

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Feb 20 18:37:24 2012
@@ -765,7 +765,8 @@
                        ArrayRef<VarDecl *> ArrayIndexVars,
                        ArrayRef<unsigned> ArrayIndexStarts,
                        SourceLocation ClosingBrace,
-                       unsigned ManglingNumber)
+                       unsigned ManglingNumber,
+                       Decl *ContextDecl)
   : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
          T->isDependentType(), T->isDependentType(), T->isDependentType(),
          /*ContainsUnexpandedParameterPack=*/false),
@@ -787,6 +788,7 @@
   Data.NumCaptures = NumCaptures;
   Data.NumExplicitCaptures = 0;
   Data.ManglingNumber = ManglingNumber;
+  Data.ContextDecl = ContextDecl;
   Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures);
   Capture *ToCapture = Data.Captures;
   for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
@@ -827,7 +829,8 @@
                                ArrayRef<VarDecl *> ArrayIndexVars,
                                ArrayRef<unsigned> ArrayIndexStarts,
                                SourceLocation ClosingBrace,
-                               unsigned ManglingNumber) {
+                               unsigned ManglingNumber,
+                               Decl *ContextDecl) {
   // Determine the type of the expression (i.e., the type of the
   // function object we're creating).
   QualType T = Context.getTypeDeclType(Class);
@@ -840,7 +843,7 @@
   return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, 
                               Captures, ExplicitParams, ExplicitResultType,
                               CaptureInits, ArrayIndexVars, ArrayIndexStarts,
-                              ClosingBrace, ManglingNumber);
+                              ClosingBrace, ManglingNumber, ContextDecl);
 }
 
 LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures,

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Feb 20 18:37:24 2012
@@ -40,14 +40,38 @@
 
 namespace {
 
+/// \brief Retrieve the declaration context that should be used when mangling 
+/// the given declaration.
+static const DeclContext *getEffectiveDeclContext(const Decl *D) {
+  // The ABI assumes that lambda closure types that occur within 
+  // default arguments live in the context of the function. However, due to
+  // the way in which Clang parses and creates function declarations, this is
+  // not the case: the lambda closure type ends up living in the context 
+  // where the function itself resides, because the function declaration itself
+  // had not yet been created. Fix the context here.
+  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+    if (RD->isLambda())
+      if (ParmVarDecl *ContextParam
+          = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+        return ContextParam->getDeclContext();
+  }
+  
+  return D->getDeclContext();
+}
+
+static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
+  return getEffectiveDeclContext(cast<Decl>(DC));
+}
+  
 static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {
   const DeclContext *DC = dyn_cast<DeclContext>(ND);
   if (!DC)
-    DC = ND->getDeclContext();
+    DC = getEffectiveDeclContext(ND);
   while (!DC->isNamespace() && !DC->isTranslationUnit()) {
-    if (isa<FunctionDecl>(DC->getParent()))
+    const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC));
+    if (isa<FunctionDecl>(Parent))
       return dyn_cast<CXXRecordDecl>(DC);
-    DC = DC->getParent();
+    DC = Parent;
   }
   return 0;
 }
@@ -63,7 +87,7 @@
   const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl);
   return (fn ? getStructor(fn) : decl);
 }
-
+                                                    
 static const unsigned UnknownArity = ~0U;
 
 class ItaniumMangleContext : public MangleContext {
@@ -279,6 +303,7 @@
   void mangleUnscopedTemplateName(TemplateName);
   void mangleSourceName(const IdentifierInfo *II);
   void mangleLocalName(const NamedDecl *ND);
+  void mangleLambda(const CXXRecordDecl *Lambda);
   void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
                         bool NoFunction=false);
   void mangleNestedName(const TemplateDecl *TD,
@@ -339,8 +364,8 @@
 
 static bool isInCLinkageSpecification(const Decl *D) {
   D = D->getCanonicalDecl();
-  for (const DeclContext *DC = D->getDeclContext();
-       !DC->isTranslationUnit(); DC = DC->getParent()) {
+  for (const DeclContext *DC = getEffectiveDeclContext(D);
+       !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) {
     if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
       return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
   }
@@ -372,17 +397,17 @@
 
   // Variables at global scope with non-internal linkage are not mangled
   if (!FD) {
-    const DeclContext *DC = D->getDeclContext();
+    const DeclContext *DC = getEffectiveDeclContext(D);
     // Check for extern variable declared locally.
     if (DC->isFunctionOrMethod() && D->hasLinkage())
       while (!DC->isNamespace() && !DC->isTranslationUnit())
-        DC = DC->getParent();
+        DC = getEffectiveParentContext(DC);
     if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)
       return false;
   }
 
   // Class members are always mangled.
-  if (D->getDeclContext()->isRecord())
+  if (getEffectiveDeclContext(D)->isRecord())
     return true;
 
   // C functions and "main" are not mangled.
@@ -465,7 +490,7 @@
 
 static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
   while (isa<LinkageSpecDecl>(DC)) {
-    DC = DC->getParent();
+    DC = getEffectiveParentContext(DC);
   }
 
   return DC;
@@ -473,7 +498,8 @@
 
 /// isStd - Return whether a given namespace is the 'std' namespace.
 static bool isStd(const NamespaceDecl *NS) {
-  if (!IgnoreLinkageSpecDecls(NS->getParent())->isTranslationUnit())
+  if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
+                                ->isTranslationUnit())
     return false;
   
   const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
@@ -515,20 +541,20 @@
   //         ::= <unscoped-template-name> <template-args>
   //         ::= <local-name>
   //
-  const DeclContext *DC = ND->getDeclContext();
+  const DeclContext *DC = getEffectiveDeclContext(ND);
 
   // If this is an extern variable declared locally, the relevant DeclContext
   // is that of the containing namespace, or the translation unit.
   if (isa<FunctionDecl>(DC) && ND->hasLinkage())
     while (!DC->isNamespace() && !DC->isTranslationUnit())
-      DC = DC->getParent();
+      DC = getEffectiveParentContext(DC);
   else if (GetLocalClassDecl(ND)) {
     mangleLocalName(ND);
     return;
   }
 
   while (isa<LinkageSpecDecl>(DC))
-    DC = DC->getParent();
+    DC = getEffectiveParentContext(DC);
 
   if (DC->isTranslationUnit() || isStdNamespace(DC)) {
     // Check if we have a template.
@@ -554,7 +580,7 @@
 void CXXNameMangler::mangleName(const TemplateDecl *TD,
                                 const TemplateArgument *TemplateArgs,
                                 unsigned NumTemplateArgs) {
-  const DeclContext *DC = IgnoreLinkageSpecDecls(TD->getDeclContext());
+  const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));
 
   if (DC->isTranslationUnit() || isStdNamespace(DC)) {
     mangleUnscopedTemplateName(TD);
@@ -568,7 +594,7 @@
 void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) {
   //  <unscoped-name> ::= <unqualified-name>
   //                  ::= St <unqualified-name>   # ::std::
-  if (isStdNamespace(ND->getDeclContext()))
+  if (isStdNamespace(getEffectiveDeclContext(ND)))
     Out << "St";
 
   mangleUnqualifiedName(ND);
@@ -1028,7 +1054,7 @@
       // This naming convention is the same as that followed by GCC,
       // though it shouldn't actually matter.
       if (ND && ND->getLinkage() == InternalLinkage &&
-          ND->getDeclContext()->isFileContext())
+          getEffectiveDeclContext(ND)->isFileContext())
         Out << 'L';
 
       mangleSourceName(II);
@@ -1089,28 +1115,7 @@
     // <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 << '_';
+        mangleLambda(Record);
         break;
       }
     }
@@ -1243,8 +1248,10 @@
 void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
   // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
   //              := Z <function encoding> E s [<discriminator>]
+  // <local-name> := Z <function encoding> E d [ <parameter number> ] 
+  //                 _ <entity name>
   // <discriminator> := _ <non-negative number>
-  const DeclContext *DC = ND->getDeclContext();
+  const DeclContext *DC = getEffectiveDeclContext(ND);
   if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) {
     // Don't add objc method name mangling to locally declared function
     mangleUnqualifiedName(ND);
@@ -1256,23 +1263,46 @@
   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) {
    mangleObjCMethodName(MD);
   } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) {
-    mangleFunctionEncoding(cast<FunctionDecl>(RD->getDeclContext()));
+    mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD)));
     Out << 'E';
 
+    // The parameter number is omitted for the last parameter, 0 for the 
+    // second-to-last parameter, 1 for the third-to-last parameter, etc. The 
+    // <entity name> will of course contain a <closure-type-name>: Its 
+    // numbering will be local to the particular argument in which it appears
+    // -- other default arguments do not affect its encoding.
+    bool SkipDiscriminator = false;
+    if (RD->isLambda()) {
+      if (const ParmVarDecl *Parm
+                 = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) {
+        if (const FunctionDecl *Func
+              = dyn_cast<FunctionDecl>(Parm->getDeclContext())) {
+          Out << 'd';
+          unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex();
+          if (Num > 1)
+            mangleNumber(Num - 2);
+          Out << '_';
+          SkipDiscriminator = true;
+        }
+      }
+    }
+    
     // Mangle the name relative to the closest enclosing function.
     if (ND == RD) // equality ok because RD derived from ND above
       mangleUnqualifiedName(ND);
     else
       mangleNestedName(ND, DC, true /*NoFunction*/);
 
-    unsigned disc;
-    if (Context.getNextDiscriminator(RD, disc)) {
-      if (disc < 10)
-        Out << '_' << disc;
-      else
-        Out << "__" << disc << '_';
+    if (!SkipDiscriminator) {
+      unsigned disc;
+      if (Context.getNextDiscriminator(RD, disc)) {
+        if (disc < 10)
+          Out << '_' << disc;
+        else
+          Out << "__" << disc << '_';
+      }
     }
-
+    
     return;
   }
   else
@@ -1282,6 +1312,31 @@
   mangleUnqualifiedName(ND);
 }
 
+void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
+  // 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>(*Lambda->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 = Lambda->getLambdaManglingNumber()) {
+    if (Number > 1)
+      mangleNumber(Number - 2);
+  }
+  Out << '_';  
+}
+
 void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
   switch (qualifier->getKind()) {
   case NestedNameSpecifier::Global:
@@ -1322,13 +1377,13 @@
   //           ::= <substitution>
 
   while (isa<LinkageSpecDecl>(DC))
-    DC = DC->getParent();
+    DC = getEffectiveParentContext(DC);
 
   if (DC->isTranslationUnit())
     return;
 
   if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
-    manglePrefix(DC->getParent(), NoFunction);    
+    manglePrefix(getEffectiveParentContext(DC), NoFunction);    
     SmallString<64> Name;
     llvm::raw_svector_ostream NameStream(Name);
     Context.mangleBlock(Block, NameStream);
@@ -1352,7 +1407,7 @@
   else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
     mangleObjCMethodName(Method);
   else {
-    manglePrefix(DC->getParent(), NoFunction);
+    manglePrefix(getEffectiveParentContext(DC), NoFunction);
     mangleUnqualifiedName(cast<NamedDecl>(DC));
   }
 
@@ -1399,7 +1454,7 @@
     return;
   }
 
-  manglePrefix(ND->getDeclContext());
+  manglePrefix(getEffectiveDeclContext(ND));
   mangleUnqualifiedName(ND->getTemplatedDecl());
   addSubstitution(ND);
 }
@@ -3159,7 +3214,7 @@
   if (!SD)
     return false;
 
-  if (!isStdNamespace(SD->getDeclContext()))
+  if (!isStdNamespace(getEffectiveDeclContext(SD)))
     return false;
 
   const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
@@ -3201,7 +3256,7 @@
   }
 
   if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
-    if (!isStdNamespace(TD->getDeclContext()))
+    if (!isStdNamespace(getEffectiveDeclContext(TD)))
       return false;
 
     // <substitution> ::= Sa # ::std::allocator
@@ -3219,7 +3274,7 @@
 
   if (const ClassTemplateSpecializationDecl *SD =
         dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
-    if (!isStdNamespace(SD->getDeclContext()))
+    if (!isStdNamespace(getEffectiveDeclContext(SD)))
       return false;
 
     //    <substitution> ::= Ss # ::std::basic_string<char,

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Mon Feb 20 18:37:24 2012
@@ -297,7 +297,8 @@
                             Scope::FunctionPrototypeScope|Scope::DeclScope);
   for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
     // Introduce the parameter into scope.
-    Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param);
+    Actions.ActOnDelayedCXXMethodParameter(getCurScope(), 
+                                           LM.DefaultArgs[I].Param);
 
     if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
       // Save the current token position.
@@ -317,7 +318,8 @@
       // The argument isn't actually potentially evaluated unless it is
       // used.
       EnterExpressionEvaluationContext Eval(Actions,
-                                            Sema::PotentiallyEvaluatedIfUsed);
+                                            Sema::PotentiallyEvaluatedIfUsed,
+                                            LM.DefaultArgs[I].Param);
 
       ExprResult DefArgResult(ParseAssignmentExpression());
       if (DefArgResult.isInvalid())

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Feb 20 18:37:24 2012
@@ -4520,7 +4520,8 @@
           // The argument isn't actually potentially evaluated unless it is 
           // used.
           EnterExpressionEvaluationContext Eval(Actions,
-                                              Sema::PotentiallyEvaluatedIfUsed);
+                                              Sema::PotentiallyEvaluatedIfUsed,
+                                                Param);
 
           ExprResult DefArgResult(ParseAssignmentExpression());
           if (DefArgResult.isInvalid()) {

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Feb 20 18:37:24 2012
@@ -111,7 +111,7 @@
                                        &Context);
 
   ExprEvalContexts.push_back(
-        ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, false));
+        ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, false, 0));
 
   FunctionScopes.push_back(new FunctionScopeInfo(Diags));
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Feb 20 18:37:24 2012
@@ -9275,11 +9275,13 @@
 }
 
 void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
+Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
+                                      Decl *LambdaContextDecl) {
   ExprEvalContexts.push_back(
              ExpressionEvaluationContextRecord(NewContext,
                                                ExprCleanupObjects.size(),
-                                               ExprNeedsCleanups));
+                                               ExprNeedsCleanups,
+                                               LambdaContextDecl));
   ExprNeedsCleanups = false;
   if (!MaybeODRUseExprs.empty())
     std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 20 18:37:24 2012
@@ -485,6 +485,7 @@
 ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, 
                                  Scope *CurScope, 
                                  llvm::Optional<unsigned> ManglingNumber,
+                                 Decl *ContextDecl,
                                  bool IsInstantiation) {
   // Leave the expression-evaluation context.
   DiscardCleanupsInEvaluationContext();
@@ -638,8 +639,34 @@
   // 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);
+    ContextDecl = ExprEvalContexts.back().LambdaContextDecl;
+    
+    // FIXME: Data member initializers.
+    enum ContextKind {
+      Normal,
+      DefaultArgument
+    } Kind = Normal;
+
+    // Default arguments of member function parameters that appear in a class
+    // definition receive special treatment. Identify them.
+    if (ParmVarDecl *Param = dyn_cast_or_null<ParmVarDecl>(ContextDecl)) {
+      if (const DeclContext *LexicalDC
+            = Param->getDeclContext()->getLexicalParent())
+        if (LexicalDC->isRecord())
+          Kind = DefaultArgument;
+    }
+    
+    switch (Kind) {
+    case Normal:
+      ManglingNumber = Context.getLambdaManglingNumber(CallOperator);
+      ContextDecl = 0;
+      break;
+      
+    case DefaultArgument:
+      ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
+                         .getManglingNumber(CallOperator);
+      break;
+    }
   }
   
   LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
@@ -647,7 +674,7 @@
                                           ExplicitParams, ExplicitResultType,
                                           CaptureInits, ArrayIndexVars, 
                                           ArrayIndexStarts, Body->getLocEnd(),
-                                          *ManglingNumber);
+                                          *ManglingNumber, ContextDecl);
 
   // C++11 [expr.prim.lambda]p2:
   //   A lambda-expression shall not appear in an unevaluated operand

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Feb 20 18:37:24 2012
@@ -7768,10 +7768,14 @@
                                /*IsInstantiation=*/true);
     return ExprError();    
   }
-  
+
+  // 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();
   return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), 
                                    /*CurScope=*/0, ManglingNumber,
+                                   ContextDecl,
                                    /*IsInstantiation=*/true);
 }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Feb 20 18:37:24 2012
@@ -1110,6 +1110,7 @@
     Lambda.NumCaptures = Record[Idx++];
     Lambda.NumExplicitCaptures = Record[Idx++];
     Lambda.ManglingNumber = Record[Idx++];
+    Lambda.ContextDecl = ReadDecl(Record, Idx);
     Lambda.Captures 
       = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
     Capture *ToCapture = Lambda.Captures;

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Feb 20 18:37:24 2012
@@ -4333,6 +4333,7 @@
     Record.push_back(Lambda.NumCaptures);
     Record.push_back(Lambda.NumExplicitCaptures);
     Record.push_back(Lambda.ManglingNumber);
+    AddDeclRef(Lambda.ContextDecl, Record);
     for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
       LambdaExpr::Capture &Capture = Lambda.Captures[I];
       AddSourceLocation(Capture.getLocation(), Record);

Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=151011&r1=151010&r2=151011&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Mon Feb 20 18:37:24 2012
@@ -14,9 +14,64 @@
   // CHECK: call i32 @_ZZ11inline_funciENKUliE_clEi
   int l = [=] (int x) -> int { return x + i; }(n);
 
-  // CHECK: ret void
+  int inner(int i = []{ return 1; }());
+  // CHECK: call i32 @_ZZ11inline_funciENKUlvE2_clEv
+  // CHECK-NEXT: call i32 @_Z5inneri
+  inner();
+
+  // CHECK-NEXT: ret void
 }
 
 void call_inline_func() {
   inline_func(17);
 }
+
+struct S {
+  void f(int = []{return 1;}()
+             + []{return 2;}(),
+         int = []{return 3;}());
+  void g(int, int);
+};
+
+void S::g(int i = []{return 1;}(),
+          int j = []{return 2; }()) {}
+
+// CHECK: define void @_Z6test_S1S
+void test_S(S s) {
+  // CHECK: call i32 @_ZZN1S1fEiiEd0_NKUlvE_clEv
+  // CHECK-NEXT: call i32 @_ZZN1S1fEiiEd0_NKUlvE0_clEv
+  // CHECK-NEXT: add nsw i32
+  // CHECK-NEXT: call i32 @_ZZN1S1fEiiEd_NKUlvE_clEv
+  // CHECK-NEXT: call void @_ZN1S1fEii
+  s.f();
+
+  // NOTE: These manglings don't actually matter that much, because
+  // the lambdas in the default arguments of g() won't be seen by
+  // multiple translation units. We check them mainly to ensure that they don't 
+  // get the special mangling for lambdas in in-class default arguments.
+  // CHECK: call i32 @_ZNK1SUlvE_clEv
+  // CHECK-NEXT: call i32 @_ZNK1SUlvE0_clEv
+  // CHECK-NEXT: call void @_ZN1S1gEi
+  s.g();
+
+  // CHECK-NEXT: ret void
+}
+
+template<typename T>
+struct ST {
+  void f(T = []{return T() + 1;}()
+           + []{return T() + 2;}(),
+         T = []{return T(3);}());
+};
+
+// 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-NEXT: fadd double
+  // CHECK-NEXT: call double @_ZZN2ST1fET_S0_Ed_NKUlvE_clEv
+  // CHECK-NEXT: call void @_ZN2STIdE1fEdd
+  st.f();
+
+  // CHECK-NEXT: ret void
+}





More information about the cfe-commits mailing list