- Figured out how to fix PR17161.

Hi pcc, rnk, cdavis5x, timurrrr, whunt,

http://llvm-reviews.chandlerc.com/D1627

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1627?vs=4132&id=4133#toc

Files:
  lib/AST/MicrosoftMangle.cpp
  test/CodeGenCXX/mangle-ms-extern-local.cpp
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -29,6 +29,40 @@
 
 namespace {
 
+/// \brief Retrieve the declaration context that should be used when mangling 
+/// the given declaration.
+static const DeclContext *getEffectiveDeclContext(const Decl *D) {
+  // The ABI assumes that lambda closure types that occur within
+  // default arguments live in the context of the function. However, due to
+  // the way in which Clang parses and creates function declarations, this is
+  // not the case: the lambda closure type ends up living in the context
+  // where the function itself resides, because the function declaration itself
+  // had not yet been created. Fix the context here.
+  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+    if (RD->isLambda())
+      if (ParmVarDecl *ContextParam =
+              dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+        return ContextParam->getDeclContext();
+  }
+
+  // Perform the same check for block literals.
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+    if (ParmVarDecl *ContextParam =
+            dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
+      return ContextParam->getDeclContext();
+  }
+
+  const DeclContext *DC = D->getDeclContext();
+  if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC))
+    return getEffectiveDeclContext(CD);
+
+  return DC;
+}
+
+static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
+  return getEffectiveDeclContext(cast<Decl>(DC));
+}
+
 static const FunctionDecl *getStructor(const FunctionDecl *fn) {
   if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
     return ftd->getTemplatedDecl();
@@ -81,10 +115,11 @@
 
   raw_ostream &getStream() const { return Out; }
 
-  void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
-  void mangleName(const NamedDecl *ND);
+  void mangle(const NamedDecl *D, StringRef Prefix = "\01?",
+              bool IsForTemplateArg = false);
+  void mangleName(const NamedDecl *ND, bool IsForTemplateArg = false);
   void mangleDeclaration(const NamedDecl *ND);
-  void mangleFunctionEncoding(const FunctionDecl *FD);
+  void mangleFunctionEncoding(const FunctionDecl *FD, bool IsForTemplateArg);
   void mangleVariableEncoding(const VarDecl *VD);
   void mangleNumber(int64_t Number);
   void mangleNumber(const llvm::APSInt &Value);
@@ -100,7 +135,7 @@
   }
   void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
   void mangleSourceName(const IdentifierInfo *II);
-  void manglePostfix(const DeclContext *DC, bool NoFunction=false);
+  void manglePostfix(const DeclContext *DC, bool NoFunction = false);
   void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
   void mangleCXXDtorType(CXXDtorType T);
   void mangleQualifiers(Qualifiers Quals, bool IsMember);
@@ -135,15 +170,15 @@
 
   void mangleTemplateArgs(const TemplateDecl *TD,
                           const TemplateArgumentList &TemplateArgs);
-  void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA);
+  void mangleTemplateArg(const TemplateArgument &TA);
 };
 
 /// MicrosoftMangleContext - Overrides the default MangleContext for the
 /// Microsoft Visual C++ ABI.
 class MicrosoftMangleContext : public MangleContext {
 public:
-  MicrosoftMangleContext(ASTContext &Context,
-                   DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
+  MicrosoftMangleContext(ASTContext &Context, DiagnosticsEngine &Diags)
+      : MangleContext(Context, Diags) {}
   virtual bool shouldMangleDeclName(const NamedDecl *D);
   virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
   virtual void mangleThunk(const CXXMethodDecl *MD,
@@ -174,17 +209,6 @@
 
 }
 
-static bool isInCLinkageSpecification(const Decl *D) {
-  D = D->getCanonicalDecl();
-  for (const DeclContext *DC = D->getDeclContext();
-       !DC->isTranslationUnit(); DC = DC->getParent()) {
-    if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
-      return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
-  }
-
-  return false;
-}
-
 bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
   // In C, functions with no attributes never need to be mangled. Fastpath them.
   if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
@@ -195,34 +219,53 @@
   if (D->hasAttr<AsmLabelAttr>())
     return true;
 
-  // Clang's "overloadable" attribute extension to C/C++ implies name mangling
-  // (always) as does passing a C++ member function and a function
-  // whose name is not a simple identifier.
   const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
-  if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
-             !FD->getDeclName().isIdentifier()))
-    return true;
+  if (FD) {
+    LanguageLinkage L = FD->getLanguageLinkage();
+    // Overloadable functions need mangling.
+    if (FD->hasAttr<OverloadableAttr>())
+      return true;
+
+    // "main" is not mangled.
+    if (FD->isMain())
+      return false;
+
+    // C++ functions and those whose names are not a simple identifier need
+    // mangling.
+    if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage)
+      return true;
+
+    // C functions are not mangled.
+    if (L == CLanguageLinkage)
+      return false;
+  }
 
   // Otherwise, no mangling is done outside C++ mode.
   if (!getASTContext().getLangOpts().CPlusPlus)
     return false;
 
-  // Variables at global scope with internal linkage are not mangled.
-  if (!FD) {
-    const DeclContext *DC = D->getDeclContext();
-    if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage)
+  const VarDecl *VD = dyn_cast<VarDecl>(D);
+  if (VD) {
+    // C variables are not mangled.
+    if (VD->isExternC())
       return false;
-  }
 
-  // C functions and "main" are not mangled.
-  if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
-    return false;
+    // Variables at global scope with internal linkage are not mangled
+    const DeclContext *DC = getEffectiveDeclContext(D);
+    // Check for extern variable declared locally.
+    if (DC->isFunctionOrMethod() && D->hasLinkage())
+      while (!DC->isNamespace() && !DC->isTranslationUnit())
+        DC = getEffectiveParentContext(DC);
+    if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage &&
+        !isa<VarTemplateSpecializationDecl>(D))
+      return false;
+  }
 
   return true;
 }
 
-void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
-                                     StringRef Prefix) {
+void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix,
+                                     bool IsForTemplateArg) {
   // MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
   // Therefore it's really important that we don't decorate the
   // name with leading underscores or leading/trailing at signs. So, by
@@ -237,11 +280,17 @@
     return;
   }
 
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    if (FD->isMain()) {
+      Out << "$1main";
+      return;
+    }
+
   // <mangled-name> ::= ? <name> <type-encoding>
   Out << Prefix;
-  mangleName(D);
+  mangleName(D, IsForTemplateArg);
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
-    mangleFunctionEncoding(FD);
+    mangleFunctionEncoding(FD, IsForTemplateArg);
   else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
     mangleVariableEncoding(VD);
   else {
@@ -255,18 +304,15 @@
   }
 }
 
-void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD,
+                                                     bool IsForTemplateArg) {
   // <type-encoding> ::= <function-class> <function-type>
 
   // Since MSVC operates on the type as written and not the canonical type, it
   // actually matters which decl we have here.  MSVC appears to choose the
   // first, since it is most likely to be the declaration in a header file.
   FD = FD->getFirstDeclaration();
 
-  // Don't mangle in the type if this isn't a decl we should typically mangle.
-  if (!Context.shouldMangleDeclName(FD))
-    return;
-  
   // We should never ever see a FunctionNoProtoType at this point.
   // We don't even know how to mangle their types anyway :).
   TypeSourceInfo *TSI = FD->getTypeSourceInfo();
@@ -282,10 +328,14 @@
       InStructor = true;
   }
 
-  // First, the function class.
-  mangleFunctionClass(FD);
-
-  mangleFunctionType(FT, FD, InStructor, InInstMethod);
+  // extern "C" functions can hold entities that must be mangled.
+  // As it stands, these functions still need to get expressed in the full
+  // external name.  They have their class and type omitted, replaced with '9'.
+  if (IsForTemplateArg || Context.shouldMangleDeclName(FD)) {
+    mangleFunctionClass(FD);
+    mangleFunctionType(FT, FD, InStructor, InInstMethod);
+  } else
+    Out << '9';
 }
 
 void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
@@ -342,20 +392,29 @@
   }
 }
 
-void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
+void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND, bool IsForTemplateArg) {
   // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
   const DeclContext *DC = ND->getDeclContext();
 
   // Always start with the unqualified name.
-  mangleUnqualifiedName(ND);    
+  mangleUnqualifiedName(ND);
 
   // If this is an extern variable declared locally, the relevant DeclContext
   // is that of the containing namespace, or the translation unit.
   if (isa<FunctionDecl>(DC) && ND->hasLinkage())
     while (!DC->isNamespace() && !DC->isTranslationUnit())
       DC = DC->getParent();
 
-  manglePostfix(DC);
+  // Variables declared inside of extern "C" functions act as-if they were never
+  // inside of a namespace.
+  bool EmitPostfix = true;
+  if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
+    if (LSD->getLanguage() == LinkageSpecDecl::lang_c)
+      if (!IsForTemplateArg)
+        EmitPostfix = false;
+
+  if (EmitPostfix)
+    manglePostfix(DC);
 
   // Terminate the whole name with an '@'.
   Out << '@';
@@ -895,20 +954,17 @@
     << E->getStmtClassName() << E->getSourceRange();
 }
 
-void
-MicrosoftCXXNameMangler::mangleTemplateArgs(const TemplateDecl *TD,
-                                     const TemplateArgumentList &TemplateArgs) {
+void MicrosoftCXXNameMangler::mangleTemplateArgs(
+    const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) {
   // <template-args> ::= {<type> | <integer-literal>}+ @
   unsigned NumTemplateArgs = TemplateArgs.size();
-  for (unsigned i = 0; i < NumTemplateArgs; ++i) {
-    const TemplateArgument &TA = TemplateArgs[i];
-    mangleTemplateArg(TD, TA);
-  }
+  for (unsigned i = 0; i < NumTemplateArgs; ++i)
+    mangleTemplateArg(TemplateArgs[i]);
+
   Out << '@';
 }
 
-void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
-                                                const TemplateArgument &TA) {
+void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateArgument &TA) {
   switch (TA.getKind()) {
   case TemplateArgument::Null:
     llvm_unreachable("Can't mangle null template arguments!");
@@ -921,7 +977,8 @@
   }
   case TemplateArgument::Declaration: {
     const NamedDecl *ND = cast<NamedDecl>(TA.getAsDecl());
-    mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
+    mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?",
+           /*IsForTemplateArg=*/true);
     break;
   }
   case TemplateArgument::Integral:
@@ -938,7 +995,7 @@
     // Unlike Itanium, there is no character code to indicate an argument pack.
     for (TemplateArgument::pack_iterator I = TA.pack_begin(), E = TA.pack_end();
          I != E; ++I)
-      mangleTemplateArg(TD, *I);
+      mangleTemplateArg(*I);
     break;
   case TemplateArgument::Template:
     mangleType(cast<TagDecl>(
Index: test/CodeGenCXX/mangle-ms-extern-local.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/mangle-ms-extern-local.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+// CHECK: @"\01?a@test1@@3U?$x@$1?fun1@test1@@YAXXZ@1@A"
+// CHECK: @"\01?a@test2@@3U?$x@$1main@1@A"
+// CHECK: @"\01?g@?3??fun@B@?1??fun0@@9@SAPAXXZ@4PQA@?1??3@9@HQ4?1??3@9@"
+
+namespace test0 {
+extern "C" inline void *fun0() {
+  struct A;
+  struct B {
+    static void *fun() {
+      static int A::* g;
+      return (void *)&g;
+    }
+  };
+  return B::fun();
+};
+void *h() { return fun0(); }
+}
+
+namespace test1 {
+template <void (*)()> struct x {};
+
+extern "C" inline void fun1() {}
+
+x<fun1> a;
+}
+
+// CHECK: define i32 @main(i32 %argc, i8** %argv)
+int main(int argc, char *argv[]) {}
+
+namespace test2 {
+template <int (*)(int, char * [])> struct x {};
+
+x<main> a;
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to