forked from OSchip/llvm-project
[-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:
parent
80d28de87a
commit
8eaab6ff8e
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(), '-', '_');
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue