[PATCH] [-cxx-abi microsoft] Mangle declarations inside extern "C"
David Majnemer
david.majnemer at gmail.com
Wed Sep 11 20:30:23 PDT 2013
Hi timurrrr, pcc, cdavis5x,
This is a first step to getting extern "C" working properly inside
clang. There are a number of quirks but mangling declarations inside
such a function are a good first step.
http://llvm-reviews.chandlerc.com/D1655
Files:
lib/AST/MicrosoftMangle.cpp
test/CodeGenCXX/mangle-ms.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();
@@ -180,17 +214,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())
@@ -201,28 +224,48 @@
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 non-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;
}
@@ -269,10 +312,6 @@
// 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();
@@ -288,10 +327,16 @@
InStructor = true;
}
- // First, the function class.
- mangleFunctionClass(FD);
+ // 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 (Context.shouldMangleDeclName(FD)) {
+ // First, the function class.
+ mangleFunctionClass(FD);
- mangleFunctionType(FT, FD, InStructor, InInstMethod);
+ mangleFunctionType(FT, FD, InStructor, InInstMethod);
+ } else
+ Out << '9';
}
void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
Index: test/CodeGenCXX/mangle-ms.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms.cpp
+++ test/CodeGenCXX/mangle-ms.cpp
@@ -35,6 +35,8 @@
// X64: @"\01?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@"
// X64: @"\01?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@"
// X64: @"\01?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@"
+// CHECK: @"\01?local@?1??extern_c_func@@9 at 4HA"
+// X64: @"\01?local@?1??extern_c_func@@9 at 4HA"
int a;
@@ -245,3 +247,11 @@
return s0[0] + s1[0] + s2[0] + s3[0] + s4[0] + s5[0] + s6[0][0];
}
}
+
+extern "C" inline void extern_c_func() {
+ static int local;
+}
+
+void call_extern_c_func() {
+ extern_c_func();
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1655.1.patch
Type: text/x-patch
Size: 6373 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130911/610adf19/attachment.bin>
More information about the cfe-commits
mailing list