r185372 - Fix mangling for block literals.

Nico Weber thakis at chromium.org
Mon Jul 1 13:31:01 PDT 2013


bb-chapuni: build #2569 of ninja-clang-i686-msc17-R is complete: Failure
[failed build_clang]  Build details are at
http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/2569  blamelist:
Eli Friedman <eli.friedman at gmail.com>
g++:
/home/bb/cmake-clang-x86_64-linux/llvm-project/clang/lib/AST/LambdaMangleContext.cpp:
No such file or directory
probably needs some cmake file update



On Mon, Jul 1, 2013 at 1:22 PM, Eli Friedman <eli.friedman at gmail.com> wrote:

> Author: efriedma
> Date: Mon Jul  1 15:22:57 2013
> New Revision: 185372
>
> URL: http://llvm.org/viewvc/llvm-project?rev=185372&view=rev
> Log:
> Fix mangling for block literals.
>
> Blocks, like lambdas, can be written in contexts which are required to be
> treated as the same under ODR.  Unlike lambdas, it isn't possible to
> actually
> take the address of a block, so the mangling of the block itself doesn't
> matter. However, objects like static variables inside a block do need to
> be mangled in a consistent way.
>
> There are basically three components here. One, block literals need a
> consistent numbering.  Two, objects/types inside a block literal need
> to be mangled using it.  Three, objects/types inside a block literal need
> to have their linkage computed correctly.
>
> Added:
>     cfe/trunk/include/clang/AST/MangleNumberingContext.h
>       - copied, changed from r185346,
> cfe/trunk/include/clang/AST/LambdaMangleContext.h
>     cfe/trunk/lib/AST/MangleNumberingContext.cpp
>       - copied, changed from r185346,
> cfe/trunk/lib/AST/LambdaMangleContext.cpp
> Removed:
>     cfe/trunk/include/clang/AST/LambdaMangleContext.h
>     cfe/trunk/lib/AST/LambdaMangleContext.cpp
> Modified:
>     cfe/trunk/include/clang/AST/ASTContext.h
>     cfe/trunk/include/clang/AST/Decl.h
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/lib/AST/ASTContext.cpp
>     cfe/trunk/lib/AST/Decl.cpp
>     cfe/trunk/lib/AST/ItaniumMangle.cpp
>     cfe/trunk/lib/CodeGen/CGDecl.cpp
>     cfe/trunk/lib/CodeGen/CodeGenModule.cpp
>     cfe/trunk/lib/CodeGen/CodeGenModule.h
>     cfe/trunk/lib/Sema/SemaExpr.cpp
>     cfe/trunk/lib/Sema/SemaLambda.cpp
>     cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
>     cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Jul  1 15:22:57 2013
> @@ -19,7 +19,7 @@
>  #include "clang/AST/CanonicalType.h"
>  #include "clang/AST/CommentCommandTraits.h"
>  #include "clang/AST/Decl.h"
> -#include "clang/AST/LambdaMangleContext.h"
> +#include "clang/AST/MangleNumberingContext.h"
>  #include "clang/AST/NestedNameSpecifier.h"
>  #include "clang/AST/PrettyPrinter.h"
>  #include "clang/AST/RawCommentList.h"
> @@ -338,9 +338,11 @@ class ASTContext : public RefCountedBase
>    typedef llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector;
>    llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>
> OverriddenMethods;
>
> -  /// \brief Mapping from each declaration context to its corresponding
> lambda
> -  /// mangling context.
> -  llvm::DenseMap<const DeclContext *, LambdaMangleContext>
> LambdaMangleContexts;
> +  /// \brief Mapping from each declaration context to its corresponding
> +  /// mangling numbering context (used for constructs like lambdas which
> +  /// need to be consistently numbered for the mangler).
> +  llvm::DenseMap<const DeclContext *, MangleNumberingContext>
> +      MangleNumberingContexts;
>
>    llvm::DenseMap<const DeclContext *, unsigned> UnnamedMangleContexts;
>    llvm::DenseMap<const TagDecl *, unsigned> UnnamedMangleNumbers;
> @@ -2087,9 +2089,10 @@ public:
>    void addUnnamedTag(const TagDecl *Tag);
>    int getUnnamedTagManglingNumber(const TagDecl *Tag) const;
>
> -  /// \brief Retrieve the lambda mangling number for a lambda expression.
> -  unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator);
> -
> +  /// \brief Retrieve the context for computing mangling numbers in the
> given
> +  /// DeclContext.
> +  MangleNumberingContext &getManglingNumberContext(DeclContext *DC);
> +
>    /// \brief Used by ParmVarDecl to store on the side the
>    /// index of the parameter when it exceeds the size of the normal
> bitfield.
>    void setParameterIndex(const ParmVarDecl *D, unsigned index);
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Mon Jul  1 15:22:57 2013
> @@ -3115,13 +3115,17 @@ private:
>    Capture *Captures;
>    unsigned NumCaptures;
>
> +  unsigned ManglingNumber;
> +  Decl *ManglingContextDecl;
> +
>  protected:
>    BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
>      : Decl(Block, DC, CaretLoc), DeclContext(Block),
>        IsVariadic(false), CapturesCXXThis(false),
>        BlockMissingReturnType(true), IsConversionFromLambda(false),
>        ParamInfo(0), NumParams(0), Body(0),
> -      SignatureAsWritten(0), Captures(0), NumCaptures(0) {}
> +      SignatureAsWritten(0), Captures(0), NumCaptures(0),
> +      ManglingNumber(0), ManglingContextDecl(0) {}
>
>  public:
>    static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation
> L);
> @@ -3191,6 +3195,18 @@ public:
>                     const Capture *end,
>                     bool capturesCXXThis);
>
> +   unsigned getBlockManglingNumber() const {
> +     return ManglingNumber;
> +   }
> +   Decl *getBlockManglingContextDecl() const {
> +     return ManglingContextDecl;
> +   }
> +
> +  void setBlockMangling(unsigned Number, Decl *Ctx) {
> +    ManglingNumber = Number;
> +    ManglingContextDecl = Ctx;
> +  }
> +
>    virtual SourceRange getSourceRange() const LLVM_READONLY;
>
>    // Implement isa/cast/dyncast/etc.
>
> Removed: cfe/trunk/include/clang/AST/LambdaMangleContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/LambdaMangleContext.h?rev=185371&view=auto
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/LambdaMangleContext.h (original)
> +++ cfe/trunk/include/clang/AST/LambdaMangleContext.h (removed)
> @@ -1,38 +0,0 @@
> -//===--- 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 "clang/Basic/LLVM.h"
> -#include "llvm/ADT/DenseMap.h"
> -#include "llvm/ADT/IntrusiveRefCntPtr.h"
> -
> -namespace clang {
> -
> -class CXXMethodDecl;
> -class FunctionProtoType;
> -
> -/// \brief Keeps track of the mangled names of lambda expressions within a
> -/// particular context.
> -class LambdaMangleContext : public RefCountedBase<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
>
> Copied: cfe/trunk/include/clang/AST/MangleNumberingContext.h (from
> r185346, cfe/trunk/include/clang/AST/LambdaMangleContext.h)
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/MangleNumberingContext.h?p2=cfe/trunk/include/clang/AST/MangleNumberingContext.h&p1=cfe/trunk/include/clang/AST/LambdaMangleContext.h&r1=185346&r2=185372&rev=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/LambdaMangleContext.h (original)
> +++ cfe/trunk/include/clang/AST/MangleNumberingContext.h Mon Jul  1
> 15:22:57 2013
> @@ -1,4 +1,4 @@
> -//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++
> -*-===//
> +//=== MangleNumberingContext.h - Context for mangling numbers ---*- C++
> -*-===//
>  //
>  //                     The LLVM Compiler Infrastructure
>  //
> @@ -7,12 +7,13 @@
>  //
>
>  //===----------------------------------------------------------------------===//
>  //
> -//  This file defines the LambdaMangleContext interface, which keeps
> track of
> -//  the Itanium C++ ABI mangling numbers for lambda expressions.
> +//  This file defines the LambdaBlockMangleContext interface, which keeps
> track
> +//  of the Itanium C++ ABI mangling numbers for lambda expressions and
> block
> +//  literals.
>  //
>
>  //===----------------------------------------------------------------------===//
> -#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H
> -#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H
> +#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
> +#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
>
>  #include "clang/Basic/LLVM.h"
>  #include "llvm/ADT/DenseMap.h"
> @@ -20,18 +21,24 @@
>
>  namespace clang {
>
> +class BlockDecl;
>  class CXXMethodDecl;
> -class FunctionProtoType;
> +class Type;
>
> -/// \brief Keeps track of the mangled names of lambda expressions within a
> -/// particular context.
> -class LambdaMangleContext : public RefCountedBase<LambdaMangleContext> {
> -  llvm::DenseMap<const FunctionProtoType *, unsigned> ManglingNumbers;
> +/// \brief Keeps track of the mangled names of lambda expressions and
> block
> +/// literals within a particular context.
> +class MangleNumberingContext
> +    : public RefCountedBase<MangleNumberingContext> {
> +  llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
>
>  public:
>    /// \brief Retrieve the mangling number of a new lambda expression with
> the
> -  /// given call operator within this lambda context.
> +  /// given call operator within this context.
>    unsigned getManglingNumber(CXXMethodDecl *CallOperator);
> +
> +  /// \brief Retrieve the mangling number of a new block literal within
> this
> +  /// context.
> +  unsigned getManglingNumber(BlockDecl *BD);
>  };
>
>  } // end namespace clang
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Jul  1 15:22:57 2013
> @@ -20,7 +20,7 @@
>  #include "clang/AST/Expr.h"
>  #include "clang/AST/ExprObjC.h"
>  #include "clang/AST/ExternalASTSource.h"
> -#include "clang/AST/LambdaMangleContext.h"
> +#include "clang/AST/MangleNumberingContext.h"
>  #include "clang/AST/NSAPI.h"
>  #include "clang/AST/PrettyPrinter.h"
>  #include "clang/AST/TypeLoc.h"
> @@ -662,17 +662,17 @@ public:
>      /// is indeed an unevaluated context.
>      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 declaration that provides context for lambda
> expressions
> +    /// and block literals if the normal declaration context does not
> +    /// suffice, e.g., in a default function argument.
> +    Decl *ManglingContextDecl;
>
>      /// \brief The context information used to mangle lambda expressions
> -    /// within this context.
> +    /// and block literals within this context.
>      ///
>      /// This mangling information is allocated lazily, since most contexts
> -    /// do not have lambda expressions.
> -    IntrusiveRefCntPtr<LambdaMangleContext> LambdaMangle;
> +    /// do not have lambda expressions or block literals.
> +    IntrusiveRefCntPtr<MangleNumberingContext> MangleNumbering;
>
>      /// \brief If we are processing a decltype type, a set of call
> expressions
>      /// for which we have deferred checking the completeness of the
> return type.
> @@ -685,18 +685,19 @@ public:
>      ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
>                                        unsigned NumCleanupObjects,
>                                        bool ParentNeedsCleanups,
> -                                      Decl *LambdaContextDecl,
> +                                      Decl *ManglingContextDecl,
>                                        bool IsDecltype)
>        : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
>          IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
> -        LambdaContextDecl(LambdaContextDecl), LambdaMangle() { }
> +        ManglingContextDecl(ManglingContextDecl), MangleNumbering() { }
>
> -    /// \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;
> +    /// \brief Retrieve the mangling numbering context, used to
> consistently
> +    /// number constructs like lambdas for mangling.
> +    MangleNumberingContext &getMangleNumberingContext() {
> +      assert(ManglingContextDecl && "Need to have a context declaration");
> +      if (!MangleNumbering)
> +        MangleNumbering = new MangleNumberingContext;
> +      return *MangleNumbering;
>      }
>
>      bool isUnevaluated() const {
> @@ -707,6 +708,18 @@ public:
>    /// A stack of expression evaluation contexts.
>    SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
>
> +  /// \brief Compute the mangling number context for a lambda expression
> or
> +  /// block literal.
> +  ///
> +  /// \param DC - The DeclContext containing the lambda expression or
> +  /// block literal.
> +  /// \param[out] ManglingContextDecl - Returns the ManglingContextDecl
> +  /// associated with the context, if relevant.
> +  MangleNumberingContext *getCurrentMangleNumberContext(
> +    DeclContext *DC,
> +    Decl *&ManglingContextDecl);
> +
> +
>    /// SpecialMemberOverloadResult - The overloading result for a special
> member
>    /// function.
>    ///
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Jul  1 15:22:57 2013
> @@ -8007,13 +8007,10 @@ int ASTContext::getUnnamedTagManglingNum
>    return I != UnnamedMangleNumbers.end() ? I->second : -1;
>  }
>
> -unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator)
> {
> -  CXXRecordDecl *Lambda = CallOperator->getParent();
> -  return LambdaMangleContexts[Lambda->getDeclContext()]
> -           .getManglingNumber(CallOperator);
> +MangleNumberingContext &ASTContext::getManglingNumberContext(DeclContext
> *DC) {
> +  return MangleNumberingContexts[DC];
>  }
>
> -
>  void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int
> index) {
>    ParamIndices[D] = index;
>  }
>
> Modified: cfe/trunk/lib/AST/Decl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Decl.cpp (original)
> +++ cfe/trunk/lib/AST/Decl.cpp Mon Jul  1 15:22:57 2013
> @@ -287,13 +287,12 @@ getLVForTemplateParameterList(const Temp
>  static LinkageInfo getLVForDecl(const NamedDecl *D,
>                                  LVComputationKind computation);
>
> -static const FunctionDecl *getOutermostFunctionContext(const Decl *D) {
> -  const FunctionDecl *Ret = NULL;
> +static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
> +  const Decl *Ret = NULL;
>    const DeclContext *DC = D->getDeclContext();
>    while (DC->getDeclKind() != Decl::TranslationUnit) {
> -    const FunctionDecl *F = dyn_cast<FunctionDecl>(DC);
> -    if (F)
> -      Ret = F;
> +    if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
> +      Ret = cast<Decl>(DC);
>      DC = DC->getParent();
>    }
>    return Ret;
> @@ -996,6 +995,22 @@ NamedDecl::getExplicitVisibility(Explici
>    return None;
>  }
>
> +static LinkageInfo getLVForClosure(const DeclContext *DC, Decl
> *ContextDecl,
> +                                   LVComputationKind computation) {
> +  // This lambda has its linkage/visibility determined by its owner.
> +  if (ContextDecl) {
> +    if (isa<ParmVarDecl>(ContextDecl))
> +      DC = ContextDecl->getDeclContext()->getRedeclContext();
> +    else
> +      return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
> +  }
> +
> +  if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
> +    return getLVForDecl(ND, computation);
> +
> +  return LinkageInfo::external();
> +}
> +
>  static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
>                                       LVComputationKind computation) {
>    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
> @@ -1052,14 +1067,25 @@ static LinkageInfo getLVForLocalDecl(con
>    if (!Context.getLangOpts().CPlusPlus)
>      return LinkageInfo::none();
>
> -  const FunctionDecl *FD = getOutermostFunctionContext(D);
> -  if (!FD)
> +  const Decl *OuterD = getOutermostFuncOrBlockContext(D);
> +  if (!OuterD)
>      return LinkageInfo::none();
>
> -  if (!FD->isInlined() && FD->getTemplateSpecializationKind() ==
> TSK_Undeclared)
> -    return LinkageInfo::none();
> +  LinkageInfo LV;
> +  if (const BlockDecl *BD = dyn_cast<BlockDecl>(OuterD)) {
> +    if (!BD->getBlockManglingNumber())
> +      return LinkageInfo::none();
> +
> +    LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(),
> +                         BD->getBlockManglingContextDecl(), computation);
> +  } else {
> +    const FunctionDecl *FD = cast<FunctionDecl>(OuterD);
> +    if (!FD->isInlined() &&
> +        FD->getTemplateSpecializationKind() == TSK_Undeclared)
> +      return LinkageInfo::none();
>
> -  LinkageInfo LV = getLVForDecl(FD, computation);
> +    LV = getLVForDecl(FD, computation);
> +  }
>    if (!isExternallyVisible(LV.getLinkage()))
>      return LinkageInfo::none();
>    return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
> @@ -1095,20 +1121,10 @@ static LinkageInfo computeLVForDecl(cons
>            // 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),
> computation);
> -        }
>
> -        if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
> -          return getLVForDecl(ND, computation);
> -
> -        return LinkageInfo::external();
> +        // This lambda has its linkage/visibility determined by its owner.
> +        return getLVForClosure(D->getDeclContext()->getRedeclContext(),
> +                               Record->getLambdaContextDecl(),
> computation);
>        }
>
>        break;
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Jul  1 15:22:57 2013
> @@ -1416,15 +1416,22 @@ void CXXNameMangler::manglePrefix(const
>      return;
>
>    if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
> -    // The symbol we're adding a prefix for isn't externally
> -    // visible; make up something sane.
> -    // FIXME: This isn't always true!
> -    SmallString<16> BlockPrefix;
> -    BlockPrefix += "__block_prefix_internal";
> -    unsigned Number = Context.getBlockId(Block, false);
> +    // Reflect the lambda mangling rules, except that we don't have an
> +    // actual function declaration.
> +    if (NoFunction)
> +      return;
> +
> +    manglePrefix(getEffectiveParentContext(DC), NoFunction);
> +    // If we have a block mangling number, use it.
> +    unsigned Number = Block->getBlockManglingNumber();
> +    // Otherwise, just make up a number. It doesn't matter what it is
> because
> +    // the symbol in question isn't externally visible.
> +    if (!Number)
> +      Number = Context.getBlockId(Block, false);
> +    Out << "Ub";
>      if (Number > 1)
> -      BlockPrefix += llvm::utostr_32(Number - 2);
> -    Out << BlockPrefix.size() << BlockPrefix;
> +      Out << Number - 2;
> +    Out << '_';
>      return;
>    } else if (isa<CapturedDecl>(DC)) {
>      // Skip CapturedDecl context.
>
> Removed: cfe/trunk/lib/AST/LambdaMangleContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/LambdaMangleContext.cpp?rev=185371&view=auto
>
> ==============================================================================
> --- cfe/trunk/lib/AST/LambdaMangleContext.cpp (original)
> +++ cfe/trunk/lib/AST/LambdaMangleContext.cpp (removed)
> @@ -1,30 +0,0 @@
> -//===--- 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/ASTContext.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->getArgTypes(),
> -
> FunctionProtoType::ExtProtoInfo());
> -  Key = Context.getCanonicalType(Key);
> -  return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
> -}
>
> Copied: cfe/trunk/lib/AST/MangleNumberingContext.cpp (from r185346,
> cfe/trunk/lib/AST/LambdaMangleContext.cpp)
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MangleNumberingContext.cpp?p2=cfe/trunk/lib/AST/MangleNumberingContext.cpp&p1=cfe/trunk/lib/AST/LambdaMangleContext.cpp&r1=185346&r2=185372&rev=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/LambdaMangleContext.cpp (original)
> +++ cfe/trunk/lib/AST/MangleNumberingContext.cpp Mon Jul  1 15:22:57 2013
> @@ -1,4 +1,4 @@
> -//===--- LambdaMangleContext.cpp - Context for mangling lambdas -*- C++
> -*-===//
> +//===--- MangleNumberingContext.cpp - Context for mangling numbers
> --------===//
>  //
>  //                     The LLVM Compiler Infrastructure
>  //
> @@ -12,13 +12,14 @@
>  //
>
>  //===----------------------------------------------------------------------===//
>
> -#include "clang/AST/LambdaMangleContext.h"
> +#include "clang/AST/MangleNumberingContext.h"
>  #include "clang/AST/ASTContext.h"
>  #include "clang/AST/DeclCXX.h"
>
>  using namespace clang;
>
> -unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl
> *CallOperator) {
> +unsigned
> +MangleNumberingContext::getManglingNumber(CXXMethodDecl *CallOperator) {
>    const FunctionProtoType *Proto
>      = CallOperator->getType()->getAs<FunctionProtoType>();
>    ASTContext &Context = CallOperator->getASTContext();
> @@ -28,3 +29,10 @@ unsigned LambdaMangleContext::getManglin
>    Key = Context.getCanonicalType(Key);
>    return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
>  }
> +
> +unsigned
> +MangleNumberingContext::getManglingNumber(BlockDecl *BD) {
> +  // FIXME: Compute a BlockPointerType?  Not obvious how.
> +  const Type *Ty = 0;
> +  return ++ManglingNumbers[Ty];
> +}
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Mon Jul  1 15:22:57 2013
> @@ -130,9 +130,27 @@ void CodeGenFunction::EmitVarDecl(const
>      if (D.isExternallyVisible()) {
>        const Decl *D = CurCodeDecl;
>        while (true) {
> -        if (isa<BlockDecl>(D)) {
> -          // FIXME: Handle this case properly!  (Should be similar to the
> -          // way we handle lambdas in computeLVForDecl in Decl.cpp.)
> +        if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
> +          if (!BD->getBlockManglingNumber())
> +            break;
> +
> +          // This block has the linkage/visibility of its contained
> variables
> +          // determined by its owner.
> +          const DeclContext *DC = D->getDeclContext()->getRedeclContext();
> +          if (Decl *ContextDecl = BD->getBlockManglingContextDecl()) {
> +            if (isa<ParmVarDecl>(ContextDecl)) {
> +              DC = ContextDecl->getDeclContext()->getRedeclContext();
> +            } else {
> +              D = ContextDecl;
> +              continue;
> +            }
> +          }
> +
> +          if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
> +            D = ND;
> +            continue;
> +          }
> +
>            break;
>          } else if (isa<CapturedDecl>(D)) {
>            D = cast<Decl>(cast<CapturedDecl>(D)->getParent());
> @@ -140,13 +158,26 @@ void CodeGenFunction::EmitVarDecl(const
>            break;
>          }
>        }
> -      // FIXME: Do we really only care about FunctionDecls here?
> +      llvm::GlobalValue::LinkageTypes ParentLinkage;
>        if (isa<FunctionDecl>(D)) {
> -        llvm::GlobalValue::LinkageTypes ParentLinkage =
> -            CGM.getFunctionLinkage(cast<FunctionDecl>(D));
> -        if (llvm::GlobalValue::isWeakForLinker(ParentLinkage))
> -          Linkage = ParentLinkage;
> +        ParentLinkage = CGM.getFunctionLinkage(cast<FunctionDecl>(D));
> +      } else if (isa<VarDecl>(D)) {
> +        // FIXME: I'm pretty sure this is wrong...
> +        ParentLinkage = CGM.GetLLVMLinkageVarDefinition(cast<VarDecl>(D),
> +
>  /*constant*/false);
> +      } else {
> +        assert(isa<FieldDecl>(D) && "Expect function, variable, or
> field");
> +        // FIXME: Is this right?
> +        ParentLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
>        }
> +
> +      if (llvm::GlobalValue::isWeakForLinker(ParentLinkage))
> +        Linkage = ParentLinkage;
> +
> +      // FIXME: We need to force the emission/use of a guard variable for
> +      // some variables even if we can constant-evaluate them because
> +      // we can't guarantee every translation unit will constant-evaluate
> them.
> +      // Also, we might need to fix up the linkage.
>      }
>
>      return EmitStaticVarDecl(D, Linkage);
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Jul  1 15:22:57 2013
> @@ -1797,7 +1797,7 @@ void CodeGenModule::EmitGlobalVarDefinit
>
>    // Set the llvm linkage type as appropriate.
>    llvm::GlobalValue::LinkageTypes Linkage =
> -    GetLLVMLinkageVarDefinition(D, GV);
> +    GetLLVMLinkageVarDefinition(D, GV->isConstant());
>    GV->setLinkage(Linkage);
>    if (Linkage == llvm::GlobalVariable::CommonLinkage)
>      // common vars aren't constant even if declared const.
> @@ -1828,8 +1828,7 @@ void CodeGenModule::EmitGlobalVarDefinit
>  }
>
>  llvm::GlobalValue::LinkageTypes
> -CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
> -                                           llvm::GlobalVariable *GV) {
> +CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool
> isConstant) {
>    GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
>    if (Linkage == GVA_Internal)
>      return llvm::Function::InternalLinkage;
> @@ -1844,7 +1843,7 @@ CodeGenModule::GetLLVMLinkageVarDefiniti
>      // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
>      return llvm::GlobalVariable::WeakODRLinkage;
>    } else if (D->hasAttr<WeakAttr>()) {
> -    if (GV->isConstant())
> +    if (isConstant)
>        return llvm::GlobalVariable::WeakODRLinkage;
>      else
>        return llvm::GlobalVariable::WeakAnyLinkage;
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Jul  1 15:22:57 2013
> @@ -942,8 +942,7 @@ public:
>    /// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global
>    /// variable.
>    llvm::GlobalValue::LinkageTypes
> -  GetLLVMLinkageVarDefinition(const VarDecl *D,
> -                              llvm::GlobalVariable *GV);
> +  GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant);
>
>    /// Emit all the global annotations.
>    void EmitGlobalAnnotations();
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jul  1 15:22:57 2013
> @@ -9810,6 +9810,17 @@ ExprResult Sema::ActOnChooseExpr(SourceL
>  /// ActOnBlockStart - This callback is invoked when a block literal is
> started.
>  void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
>    BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
> +
> +  {
> +    Decl *ManglingContextDecl;
> +    if (MangleNumberingContext *MCtx =
> +            getCurrentMangleNumberContext(Block->getDeclContext(),
> +                                          ManglingContextDecl)) {
> +      unsigned ManglingNumber = MCtx->getManglingNumber(Block);
> +      Block->setBlockMangling(ManglingNumber, ManglingContextDecl);
> +    }
> +  }
> +
>    PushBlockScope(CurScope, Block);
>    CurContext->addDecl(Block);
>    if (CurScope)
> @@ -9929,11 +9940,7 @@ void Sema::ActOnBlockArguments(SourceLoc
>    // Finally we can process decl attributes.
>    ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
>
> -  // Put the parameter variables in scope.  We can bail out immediately
> -  // if we don't have any.
> -  if (Params.empty())
> -    return;
> -
> +  // Put the parameter variables in scope.
>    for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
>           E = CurBlock->TheDecl->param_end(); AI != E; ++AI) {
>      (*AI)->setOwningFunction(CurBlock->TheDecl);
> @@ -10641,8 +10648,8 @@ void
>  Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext
> NewContext,
>                                        ReuseLambdaContextDecl_t,
>                                        bool IsDecltype) {
> -  Decl *LambdaContextDecl = ExprEvalContexts.back().LambdaContextDecl;
> -  PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
> IsDecltype);
> +  Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
> +  PushExpressionEvaluationContext(NewContext, ClosureContextDecl,
> IsDecltype);
>  }
>
>  void Sema::PopExpressionEvaluationContext() {
>
> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Jul  1 15:22:57 2013
> @@ -52,6 +52,72 @@ static bool isInInlineFunction(const Dec
>    return false;
>  }
>
> +MangleNumberingContext *
> +Sema::getCurrentMangleNumberContext(DeclContext *DC,
> +                                    Decl *&ManglingContextDecl) {
> +  // Compute the context for allocating mangling numbers in the current
> +  // expression, if the ABI requires them.
> +  ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl;
> +
> +  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 (ManglingContextDecl) {
> +    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) {
> +      if (const DeclContext *LexicalDC
> +          = Param->getDeclContext()->getLexicalParent())
> +        if (LexicalDC->isRecord())
> +          Kind = DefaultArgument;
> +    } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
> +      if (Var->getDeclContext()->isRecord())
> +        Kind = StaticDataMember;
> +    } else if (isa<FieldDecl>(ManglingContextDecl)) {
> +      Kind = DataMember;
> +    }
> +  }
> +
> +  // 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();
> +  switch (Kind) {
> +  case Normal:
> +    //  -- the bodies of non-exported nonspecialized template functions
> +    //  -- the bodies of inline functions
> +    if ((IsInNonspecializedTemplate &&
> +         !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl)))
> ||
> +        isInInlineFunction(CurContext)) {
> +      ManglingContextDecl = 0;
> +      return &Context.getManglingNumberContext(DC);
> +    }
> +
> +    ManglingContextDecl = 0;
> +    return 0;
> +
> +  case StaticDataMember:
> +    //  -- the initializers of nonspecialized static members of template
> classes
> +    if (!IsInNonspecializedTemplate) {
> +      ManglingContextDecl = 0;
> +      return 0;
> +    }
> +    // Fall through to get the current context.
> +
> +  case DataMember:
> +    //  -- the in-class initializers of class members
> +  case DefaultArgument:
> +    //  -- default arguments appearing in class definitions
> +    return &ExprEvalContexts.back().getMangleNumberingContext();
> +  }
> +}
> +
>  CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
>                   SourceRange IntroducerRange,
>                   TypeSourceInfo *MethodType,
> @@ -98,75 +164,14 @@ CXXMethodDecl *Sema::startLambdaDefiniti
>        (*P)->setOwningFunction(Method);
>    }
>
> -  // 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;
> -    }
> -  }
> -
> -  // 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;
> +  Decl *ManglingContextDecl;
> +  if (MangleNumberingContext *MCtx =
> +          getCurrentMangleNumberContext(Class->getDeclContext(),
> +                                        ManglingContextDecl)) {
> +    unsigned ManglingNumber = MCtx->getManglingNumber(Method);
> +    Class->setLambdaMangling(ManglingNumber, ManglingContextDecl);
>    }
>
> -  Class->setLambdaMangling(ManglingNumber, ContextDecl);
> -
>    return Method;
>  }
>
>
> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/
> blocks-irgen.mm
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm(original)
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mmMon Jul  1 15:22:57 2013
> @@ -14,7 +14,7 @@ namespace PR12746 {
>    }
>
>    // CHECK: define internal zeroext i1 @___ZN7PR127462f1EPi_block_invoke
> -  // CHECK: call zeroext i1 @"_ZNK23__block_prefix_internal3$_0clEv"
> +  // CHECK: call zeroext i1 @"_ZNK7PR127462f1Ub_3$_0clEv"
>
>    bool f2(int *x) {
>      auto outer = [&]() -> bool {
>
> Modified: cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm?rev=185372&r1=185371&r2=185372&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm (original)
> +++ cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm Mon Jul  1 15:22:57 2013
> @@ -1,13 +1,14 @@
>  // RUN: %clang_cc1 -emit-llvm -fblocks -o - -triple x86_64-apple-darwin10
> -fobjc-runtime=macosx-fragile-10.5 %s | FileCheck %s
>
> -// CHECK: @_ZGVN23__block_prefix_internal5valueE = internal global i64 0
> -// CHECK: @_ZN24__block_prefix_internal35namebE = internal global i8*
> +// CHECK: @_ZGVN3fooUb_5valueE = internal global i64 0
> +// CHECK: @_ZN26externally_visible_statics1SUb_1jE = linkonce_odr global
> i32 0
> +// CHECK: @_ZN26externally_visible_statics10inlinefuncUb_1iE =
> linkonce_odr global i32 0
>
>  int f();
>
>  void foo() {
>    // CHECK: define internal i32 @___Z3foov_block_invoke
> -  // CHECK: call i32 @__cxa_guard_acquire(i64*
> @_ZGVN23__block_prefix_internal5valueE
> +  // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN3fooUb_5valueE
>    (void)^(int x) {
>      static int value = f();
>      return x + value;
> @@ -25,7 +26,7 @@ int i = ^(int x) { return x;}(i);
>  - (void)method {
>    // CHECK: define internal signext i8 @"__11-[A method]_block_invoke"
>    (void)^(int x) {
> -    // CHECK: @_ZN24__block_prefix_internal04nameE
> +    // CHECK: @"_ZN11-[A method]Ub0_4nameE"
>      static const char *name = "hello";
>      return name[x];
>    };
> @@ -43,7 +44,7 @@ namespace N {
>    // CHECK: define internal signext i8 @___Z3fooi_block_invoke
>    void bar() {
>      (void)^(int x) {
> -      // CHECK: @_ZN24__block_prefix_internal14nameE
> +      // CHECK: @_ZN1N3barUb2_4nameE
>        static const char *name = "hello";
>        return name[x];
>      };
> @@ -55,8 +56,33 @@ class C {
>  };
>  C::C() {
>    (void)^(int x) {
> -    // CHECK: @_ZN24__block_prefix_internal35namebE
> +    // CHECK: @_ZN1CC1Ub3_5namebE
>      static const char *nameb = "hello";
>      return nameb[x];
>    };
>  }
> +
> +int f();
> +namespace externally_visible_statics {
> +  inline void inlinefunc() {
> +    ^{
> +      static int i = f();
> +    }();
> +  }
> +  struct S {
> +    int x = ^{
> +      static int j = f();
> +      return j;
> +    }();
> +    void foo(int y = ^{ static int k = f(); return k; }()) {}
> +  };
> +  void g() {
> +    inlinefunc();
> +    S s;
> +#if 0
> +    // FIXME: We know how to mangle k, but crash trying to mangle the
> +    // block itself.
> +    s.foo();
> +#endif
> +  }
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130701/682e5824/attachment.html>


More information about the cfe-commits mailing list