[-cxx-abi microsoft] Mangle __uuidof correctly into template parameters
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 13 Aug 2013 06:32:20 +0000 (06:32 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 13 Aug 2013 06:32:20 +0000 (06:32 +0000)
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

clang/include/clang/AST/ExprCXX.h
clang/lib/AST/ExprCXX.cpp
clang/lib/AST/MicrosoftMangle.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGenCXX/mangle-ms-templates.cpp

index 2fec242829eabc9b61644a9138ae437c0e1344d7..4a6cfae0681f8685a967c1289df056522db1ab0f 100644 (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; }
index 496697fc55b933c56ce29b11d04e02b78d10be4f..055fc3b8142b160c59093f9e55da34d323601c0f 100644 (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;
index 765b14d49e5e4a22288d79ead6988a085e587026..9f4df3a45489c765c0ddca9928a3b2460565de45 100644 (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,
index 297e2dadd4f7579de7c30a64a77475d1c716983a..9b6d3a50e92689f76799cb1d12cdc2c356ede85b 100644 (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(), '-', '_');
 
index e65279aa0da8e3185139c9e1cd9f4f25f5f4cc97..57a33740cc73d5630ce38ea6045885c101b2bed4 100644 (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"