Index: include/clang/Basic/ABI.h =================================================================== --- include/clang/Basic/ABI.h +++ include/clang/Basic/ABI.h @@ -22,10 +22,11 @@ /// \brief C++ constructor types. enum CXXCtorType { - Ctor_Complete, ///< Complete object ctor - Ctor_Base, ///< Base object ctor - Ctor_Comdat, ///< The COMDAT used for ctors - Ctor_Closure, ///< Closure variant of a ctor + Ctor_Complete, ///< Complete object ctor + Ctor_Base, ///< Base object ctor + Ctor_Comdat, ///< The COMDAT used for ctors + Ctor_CopyingClosure, ///< Copying closure variant of a ctor + Ctor_DefaultClosure, ///< Default closure variant of a ctor }; /// \brief C++ destructor types. Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -3442,7 +3442,8 @@ case Ctor_Comdat: Out << "C5"; break; - case Ctor_Closure: + case Ctor_DefaultClosure: + case Ctor_CopyingClosure: llvm_unreachable("closure constructors don't exist for the Itanium ABI!"); } } Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -67,11 +67,15 @@ return getEffectiveDeclContext(cast(DC)); } -static const FunctionDecl *getStructor(const FunctionDecl *fn) { - if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) - return ftd->getTemplatedDecl(); +static const FunctionDecl *getStructor(const NamedDecl *ND) { + if (const auto *FTD = dyn_cast(ND)) + return FTD->getTemplatedDecl(); - return fn; + const auto *FD = cast(ND); + if (const auto *FTD = FD->getPrimaryTemplate()) + return FTD->getTemplatedDecl(); + + return FD; } static bool isLambda(const NamedDecl *ND) { @@ -777,19 +781,18 @@ llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: - if (Structor == ND && StructorType == Ctor_Closure) { - const auto *CD = cast(ND); - if (CD->isDefaultConstructor()) { - Out << "?_F"; - } else if (CD->isCopyConstructor()) { + if (Structor == getStructor(ND)) { + if (StructorType == Ctor_CopyingClosure) { Out << "?_O"; - } else { - llvm_unreachable("unexpected constructor closure!"); + return; + } + if (StructorType == Ctor_DefaultClosure) { + Out << "?_F"; + return; } - } else { - Out << "?0"; } - break; + Out << "?0"; + return; case DeclarationName::CXXDestructorName: if (ND == Structor) @@ -1589,7 +1592,9 @@ IsStructor = true; } else if (isa(MD)) { IsStructor = true; - IsCtorClosure = MD == Structor && StructorType == Ctor_Closure; + IsCtorClosure = (StructorType == Ctor_CopyingClosure || + StructorType == Ctor_DefaultClosure) && + getStructor(MD) == Structor; if (IsCtorClosure) CC = getASTContext().getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true); @@ -1620,16 +1625,14 @@ return; } if (IsCtorClosure) { - const auto *CD = cast(D); - // Default constructor closure and copy constructor closure both return // void. Out << 'X'; - if (CD->isDefaultConstructor()) { + if (StructorType == Ctor_DefaultClosure) { // Default constructor closure always has no arguments. Out << 'X'; - } else if (CD->isCopyConstructor()) { + } else if (StructorType == Ctor_CopyingClosure) { // Copy constructor closure always takes an unqualified reference. mangleArgumentType(getASTContext().getLValueReferenceType( Proto->getParamType(0) Index: lib/CodeGen/CodeGenTypes.h =================================================================== --- lib/CodeGen/CodeGenTypes.h +++ lib/CodeGen/CodeGenTypes.h @@ -82,7 +82,8 @@ return StructorType::Base; case Ctor_Comdat: llvm_unreachable("not expecting a COMDAT"); - case Ctor_Closure: + case Ctor_CopyingClosure: + case Ctor_DefaultClosure: llvm_unreachable("not expecting a closure"); } llvm_unreachable("not a CXXCtorType"); Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -3227,7 +3227,7 @@ // Calculate the mangled name. SmallString<256> ThunkName; llvm::raw_svector_ostream Out(ThunkName); - getMangleContext().mangleCXXCtor(CD, Ctor_Closure, Out); + getMangleContext().mangleCXXCtor(CD, Ctor_CopyingClosure, Out); Out.flush(); // If the thunk has been generated previously, just return it. @@ -3328,13 +3328,10 @@ if (CD) { CallingConv ExpectedCallingConv = getContext().getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true); - CallingConv ActualCallingConv = CD->getType() - ->getCanonicalTypeUnqualified() - .getAs() - ->getExtInfo() - .getCC(); + CallingConv ActualCallingConv = + CD->getType()->getAs()->getCallConv(); if (ExpectedCallingConv != ActualCallingConv || CD->getNumParams() != 1) - CT = Ctor_Closure; + CT = Ctor_CopyingClosure; } uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity(); @@ -3355,7 +3352,7 @@ // exception is caught by value. llvm::Constant *CopyCtor; if (CD) { - if (CT == Ctor_Closure) + if (CT == Ctor_CopyingClosure) CopyCtor = getAddrOfCXXCopyCtorClosure(CD); else CopyCtor = CGM.getAddrOfCXXStructor(CD, StructorType::Complete); Index: test/CodeGenCXX/microsoft-abi-throw.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-throw.cpp +++ test/CodeGenCXX/microsoft-abi-throw.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 %s -fcxx-exceptions | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions | FileCheck %s // CHECK-DAG: @"\01??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat // CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"\01??0Y@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat @@ -13,6 +13,8 @@ // CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.5 { i32 5, [5 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8", %eh.CatchableType* @"_CT??_R0?AUZ@@@81", %eh.CatchableType* @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z44", %eh.CatchableType* @"_CT??_R0?AUM@@@818", %eh.CatchableType* @"_CT??_R0?AUV@@@81044"] }, section ".xdata", comdat // CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAE@XZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat // CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat +// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat +// CHECK-DAG: @"_CT??_R0?AUBad@@@8??$?_OH@Bad@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor9* @"\01??_R0?AUBad@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Bad*, %struct.Bad*)* @"\01??$?_OH@Bad@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat struct N { ~N(); }; @@ -54,3 +56,34 @@ void h(Default &d) { throw d; } + +struct Variadic { + Variadic(Variadic &, ...); +}; + +void i(Variadic &v) { + throw v; +} + +// CHECK-LABEL: @"\01??_OVariadic@@QAEXAAU0@@Z" +// CHECK: %[[src_addr:.*]] = alloca +// CHECK: %[[this_addr:.*]] = alloca +// CHECK: store {{.*}} %src, {{.*}} %[[src_addr:.*]], align +// CHECK: store {{.*}} %this, {{.*}} %[[this_addr:.*]], align +// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]] +// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]] +// CHECK: %call = call {{.*}} @"\01??0Variadic@@QAA@AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]]) +// CHECK: ret void + +struct Bad { + template + static int f() { + return 0; + } + template + Bad(Bad &, T = f()); +}; + +void j(Bad &bad) { + throw bad; +}