From: David Majnemer Date: Tue, 13 Aug 2013 06:32:20 +0000 (+0000) Subject: [-cxx-abi microsoft] Mangle __uuidof correctly into template parameters X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c80eb46a0f37bee9597f1b466013a0f6271f9318;p=clang [-cxx-abi microsoft] Mangle __uuidof correctly into template parameters Summary: It seems that __uuidof introduces a global extern "C" declaration of type __s_GUID. However, our implementation of __uuidof does not provide such a declaration and thus must open-code the mangling for __uuidof in template parameters. This allows us to codegen scoped COM pointers and other such things. This fixes PR16836. Depends on D1356. Reviewers: rnk, cdavis5x, rsmith Reviewed By: rnk CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1357 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188252 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 2fec242829..4a6cfae068 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -724,6 +724,8 @@ public: Operand = E; } + StringRef getUuidAsStringRef(ASTContext &Context) const; + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 496697fc55..055fc3b814 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -72,6 +72,21 @@ UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT) { return 0; } +StringRef CXXUuidofExpr::getUuidAsStringRef(ASTContext &Context) const { + StringRef Uuid; + if (isTypeOperand()) + Uuid = CXXUuidofExpr::GetUuidAttrOfType(getTypeOperand())->getGuid(); + else { + // Special case: __uuidof(0) means an all-zero GUID. + Expr *Op = getExprOperand(); + if (!Op->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + Uuid = CXXUuidofExpr::GetUuidAttrOfType(Op->getType())->getGuid(); + else + Uuid = "00000000-0000-0000-0000-000000000000"; + } + return Uuid; +} + // CXXScalarValueInitExpr SourceLocation CXXScalarValueInitExpr::getLocStart() const { return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc; diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 765b14d49e..9f4df3a454 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -83,6 +83,7 @@ public: void mangle(const NamedDecl *D, StringRef Prefix = "\01?"); void mangleName(const NamedDecl *ND); + void mangleDeclaration(const NamedDecl *ND); void mangleFunctionEncoding(const FunctionDecl *FD); void mangleVariableEncoding(const VarDecl *VD); void mangleNumber(int64_t Number); @@ -855,6 +856,33 @@ MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { return; } + const CXXUuidofExpr *UE = 0; + if (const UnaryOperator *UO = dyn_cast(E)) { + if (UO->getOpcode() == UO_AddrOf) + UE = dyn_cast(UO->getSubExpr()); + } else + UE = dyn_cast(E); + + if (UE) { + // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from + // const __s_GUID _GUID_{lower case UUID with underscores} + StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext()); + std::string Name = "_GUID_" + Uuid.lower(); + std::replace(Name.begin(), Name.end(), '-', '_'); + + // If we had to peak through an address-of operator, treat this like we are + // dealing with a pointer type. Otherwise, treat it like a const reference. + // + // N.B. This matches up with the handling of TemplateArgument::Declaration + // in mangleTemplateArg + if (UE == E) + Out << "$E?"; + else + Out << "$1?"; + Out << Name << "@@3U__s_GUID@@B"; + return; + } + // As bad as this diagnostic is, it's better than crashing. DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 297e2dadd4..9b6d3a50e9 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1046,17 +1046,7 @@ llvm::Constant *CodeGenModule::GetAddrOfUuidDescriptor( const CXXUuidofExpr* E) { // Sema has verified that IIDSource has a __declspec(uuid()), and that its // well-formed. - StringRef Uuid; - if (E->isTypeOperand()) - Uuid = CXXUuidofExpr::GetUuidAttrOfType(E->getTypeOperand())->getGuid(); - else { - // Special case: __uuidof(0) means an all-zero GUID. - Expr *Op = E->getExprOperand(); - if (!Op->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) - Uuid = CXXUuidofExpr::GetUuidAttrOfType(Op->getType())->getGuid(); - else - Uuid = "00000000-0000-0000-0000-000000000000"; - } + StringRef Uuid = E->getUuidAsStringRef(Context); std::string Name = "_GUID_" + Uuid.lower(); std::replace(Name.begin(), Name.end(), '-', '_'); diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp index e65279aa0d..57a33740cc 100644 --- a/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/test/CodeGenCXX/mangle-ms-templates.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -triple=i386-pc-win32 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -cxx-abi microsoft -fms-extensions -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s template class Class { @@ -201,3 +201,17 @@ struct type1 { extern const record inst; void recref(type1) {} // CHECK: "\01?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z" + +struct _GUID {}; +struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid; + +template +struct UUIDType1 {}; + +template +struct UUIDType2 {}; + +void fun(UUIDType1 a) {} +// CHECK: "\01?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z" +void fun(UUIDType2 b) {} +// CHECK: "\01?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"