- 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