[-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

llvm-svn: 188252
This commit is contained in:
David Majnemer 2013-08-13 06:32:20 +00:00
parent 80d28de87a
commit 8eaab6ff8e
5 changed files with 62 additions and 13 deletions

View File

@ -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; }

View File

@ -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;

View File

@ -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<UnaryOperator>(E)) {
if (UO->getOpcode() == UO_AddrOf)
UE = dyn_cast<CXXUuidofExpr>(UO->getSubExpr());
} else
UE = dyn_cast<CXXUuidofExpr>(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,

View File

@ -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(), '-', '_');

View File

@ -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<typename T>
class Class {
@ -201,3 +201,17 @@ struct type1 {
extern const record inst;
void recref(type1<inst>) {}
// CHECK: "\01?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z"
struct _GUID {};
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
template <typename T, const _GUID *G = &__uuidof(T)>
struct UUIDType1 {};
template <typename T, const _GUID &G = __uuidof(T)>
struct UUIDType2 {};
void fun(UUIDType1<uuid> a) {}
// CHECK: "\01?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"
void fun(UUIDType2<uuid> b) {}
// CHECK: "\01?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z"