From 7276d2da27ae7cfd5bfc6326c0f90cf1b391d43d Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 22 Aug 2014 04:22:50 +0000 Subject: [PATCH] MS ABI: Don't use the Itanium scheme for numbering lambdas The Itanium ABI will give out the same mangling number for two different lambdas if their call operators have different types. The MS ABI cannot do the same because it does not mangle the return type into it's lambdas. This fixes PR20719. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216259 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/MangleNumberingContext.h | 13 +++---- lib/AST/CMakeLists.txt | 1 - lib/AST/ItaniumCXXABI.cpp | 26 ++++++++++++- lib/AST/MangleNumberingContext.cpp | 45 ---------------------- lib/AST/MicrosoftCXXABI.cpp | 21 ++++++++++ test/CodeGenCXX/pr20719.cpp | 35 +++++++++++++++++ 6 files changed, 85 insertions(+), 56 deletions(-) delete mode 100644 lib/AST/MangleNumberingContext.cpp create mode 100644 test/CodeGenCXX/pr20719.cpp diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h index 56aec73f24..7a818557fd 100644 --- a/include/clang/AST/MangleNumberingContext.h +++ b/include/clang/AST/MangleNumberingContext.h @@ -30,23 +30,20 @@ class VarDecl; /// \brief Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. -class MangleNumberingContext - : public RefCountedBase { - llvm::DenseMap ManglingNumbers; - +class MangleNumberingContext : public RefCountedBase { public: virtual ~MangleNumberingContext() {} /// \brief Retrieve the mangling number of a new lambda expression with the /// given call operator within this context. - unsigned getManglingNumber(const CXXMethodDecl *CallOperator); + virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0; /// \brief Retrieve the mangling number of a new block literal within this /// context. - unsigned getManglingNumber(const BlockDecl *BD); + virtual unsigned getManglingNumber(const BlockDecl *BD) = 0; /// Static locals are numbered by source order. - unsigned getStaticLocalNumber(const VarDecl *VD); + virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0; /// \brief Retrieve the mangling number of a static local variable within /// this context. @@ -58,6 +55,6 @@ public: virtual unsigned getManglingNumber(const TagDecl *TD, unsigned MSLocalManglingNumber) = 0; }; - + } // end namespace clang #endif diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 9006be64f7..6ce347b4a3 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -35,7 +35,6 @@ add_clang_library(clangAST ItaniumCXXABI.cpp ItaniumMangle.cpp Mangle.cpp - MangleNumberingContext.cpp MicrosoftCXXABI.cpp MicrosoftMangle.cpp NestedNameSpecifier.cpp diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp index b5f8c0f4bc..03428bfa79 100644 --- a/lib/AST/ItaniumCXXABI.cpp +++ b/lib/AST/ItaniumCXXABI.cpp @@ -32,10 +32,32 @@ namespace { /// \brief Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class ItaniumNumberingContext : public MangleNumberingContext { - llvm::DenseMap VarManglingNumbers; - llvm::DenseMap TagManglingNumbers; + llvm::DenseMap ManglingNumbers; + llvm::DenseMap VarManglingNumbers; + llvm::DenseMap TagManglingNumbers; public: + unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { + const FunctionProtoType *Proto = + CallOperator->getType()->getAs(); + ASTContext &Context = CallOperator->getASTContext(); + + QualType Key = + Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), + FunctionProtoType::ExtProtoInfo()); + Key = Context.getCanonicalType(Key); + return ++ManglingNumbers[Key->castAs()]; + } + + unsigned getManglingNumber(const BlockDecl *BD) { + const Type *Ty = nullptr; + return ++ManglingNumbers[Ty]; + } + + unsigned getStaticLocalNumber(const VarDecl *VD) override { + return 0; + } + /// Variable decls are numbered by identifier. unsigned getManglingNumber(const VarDecl *VD, unsigned) override { return ++VarManglingNumbers[VD->getIdentifier()]; diff --git a/lib/AST/MangleNumberingContext.cpp b/lib/AST/MangleNumberingContext.cpp deleted file mode 100644 index 5f40f0347d..0000000000 --- a/lib/AST/MangleNumberingContext.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===--- MangleNumberingContext.cpp - Context for mangling numbers --------===// -// -// 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/MangleNumberingContext.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" - -using namespace clang; - -unsigned -MangleNumberingContext::getManglingNumber(const CXXMethodDecl *CallOperator) { - const FunctionProtoType *Proto - = CallOperator->getType()->getAs(); - ASTContext &Context = CallOperator->getASTContext(); - - QualType Key = Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), - FunctionProtoType::ExtProtoInfo()); - Key = Context.getCanonicalType(Key); - return ++ManglingNumbers[Key->castAs()]; -} - -unsigned -MangleNumberingContext::getManglingNumber(const BlockDecl *BD) { - // FIXME: Compute a BlockPointerType? Not obvious how. - const Type *Ty = nullptr; - return ++ManglingNumbers[Ty]; -} - -unsigned -MangleNumberingContext::getStaticLocalNumber(const VarDecl *VD) { - // FIXME: Compute a BlockPointerType? Not obvious how. - const Type *Ty = nullptr; - return ++ManglingNumbers[Ty]; -} diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index 6870315b21..64b3c1f152 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -28,7 +28,28 @@ namespace { /// \brief Numbers things which need to correspond across multiple TUs. /// Typically these are things like static locals, lambdas, or blocks. class MicrosoftNumberingContext : public MangleNumberingContext { + llvm::DenseMap ManglingNumbers; + unsigned LambdaManglingNumber; + unsigned StaticLocalNumber; + public: + MicrosoftNumberingContext() + : MangleNumberingContext(), LambdaManglingNumber(0), + StaticLocalNumber(0) {} + + unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override { + return ++LambdaManglingNumber; + } + + unsigned getManglingNumber(const BlockDecl *BD) { + const Type *Ty = nullptr; + return ++ManglingNumbers[Ty]; + } + + unsigned getStaticLocalNumber(const VarDecl *VD) override { + return ++StaticLocalNumber; + } + unsigned getManglingNumber(const VarDecl *VD, unsigned MSLocalManglingNumber) override { return MSLocalManglingNumber; diff --git a/test/CodeGenCXX/pr20719.cpp b/test/CodeGenCXX/pr20719.cpp new file mode 100644 index 0000000000..208d111358 --- /dev/null +++ b/test/CodeGenCXX/pr20719.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++11 -o - %s | FileCheck %s + +// Make sure that we emit H's constructor twice: once with the first lambda +// inside of 'lep' and again with the second lambda inside of 'lep'. +// CHECK-DAG: @"\01??0?$H@V@??$lep@X@@YAXXZ@@@QAE@XZ" +// CHECK-DAG: @"\01??0?$H@V@??$lep@X@@YAXXZ@@@QAE@XZ" + +template +struct H { + H() {} +}; + +template +int K_void(const Fx &) { + H callee; + return 0; +} +template +int K_int(const Fx &) { + H callee; + return 0; +} + +struct pair { + pair(int, int); +}; + +struct E1; + +template +void lep() { + pair x(K_void([] {}), K_int([] {})); +} + +auto z = lep; -- 2.40.0