diff options
author | David Majnemer <david.majnemer@gmail.com> | 2013-08-13 06:32:20 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2013-08-13 06:32:20 +0000 |
commit | 8eaab6ff8e80a95e1da7b49cda81cf0ef5094be8 (patch) | |
tree | 94520101a9519eb34ebdbf4bc53884f6faa4f5cf /clang | |
parent | 80d28de87a2d8d1f1bf72418a7523e4debe0e948 (diff) | |
download | bcm5719-llvm-8eaab6ff8e80a95e1da7b49cda81cf0ef5094be8.tar.gz bcm5719-llvm-8eaab6ff8e80a95e1da7b49cda81cf0ef5094be8.zip |
[-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
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 2 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 15 | ||||
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 28 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 12 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-ms-templates.cpp | 18 |
5 files changed, 62 insertions, 13 deletions
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 2fec242829e..4a6cfae0681 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/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/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 496697fc55b..055fc3b8142 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/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/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 765b14d49e5..9f4df3a4548 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/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<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, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 297e2dadd4f..9b6d3a50e92 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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/clang/test/CodeGenCXX/mangle-ms-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-templates.cpp index e65279aa0da..57a33740cc7 100644 --- a/clang/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/clang/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<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" |