[PATCH] [ms-cxxabi] Mangle function pointer arguments correctly
Reid Kleckner
rnk at google.com
Mon Jun 3 13:22:43 PDT 2013
Get the correct base, the last diff was wrong.
Hi rsmith, pcc,
http://llvm-reviews.chandlerc.com/D844
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D844?vs=2250&id=2251#toc
Files:
lib/AST/MicrosoftMangle.cpp
test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -125,7 +125,7 @@
void mangleFunctionType(const FunctionType *T, const FunctionDecl *D,
bool IsStructor, bool IsInstMethod);
void mangleDecayedArrayType(const ArrayType *T, bool IsGlobal);
- void mangleArrayType(const ArrayType *T, Qualifiers Quals);
+ void mangleArrayType(const ArrayType *T);
void mangleFunctionClass(const FunctionDecl *FD);
void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
@@ -254,13 +254,20 @@
void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
// <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 :).
- const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
+ TypeSourceInfo *TSI = FD->getTypeSourceInfo();
+ QualType T = TSI ? TSI->getType() : FD->getType();
+ const FunctionProtoType *FT = T->castAs<FunctionProtoType>();
bool InStructor = false, InInstMethod = false;
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
@@ -977,6 +984,8 @@
void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
SourceRange Range) {
+ // MSVC will backreference two canonically equivalent types that have slightly
+ // different manglings when mangled alone.
void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
@@ -1007,16 +1016,18 @@
void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM) {
- // Only operate on the canonical type!
- T = getASTContext().getCanonicalType(T);
+ // Don't use the canonical types. MSVC includes things like 'const' on
+ // pointer arguments to function pointers that canonicalization strips away.
+ T = T.getDesugaredType(getASTContext());
Qualifiers Quals = T.getLocalQualifiers();
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(T)) {
+ if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
+ // If there were any Quals, getAsArrayType() pushed them onto the array
+ // element type.
if (QMM == QMM_Mangle)
Out << 'A';
else if (QMM == QMM_Escape || QMM == QMM_Result)
Out << "$$B";
- mangleArrayType(AT, Quals);
+ mangleArrayType(AT);
return;
}
@@ -1177,6 +1188,9 @@
// <return-type> <argument-list> <throw-spec>
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+ SourceRange Range;
+ if (D) Range = D->getSourceRange();
+
// If this is a C++ instance method, mangle the CVR qualifiers for the
// this pointer.
if (IsInstMethod)
@@ -1198,32 +1212,20 @@
}
Out << '@';
} else {
- mangleType(Proto->getResultType(), SourceRange(), QMM_Result);
+ mangleType(Proto->getResultType(), Range, QMM_Result);
}
// <argument-list> ::= X # void
// ::= <type>+ @
// ::= <type>* Z # varargs
if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
Out << 'X';
} else {
- if (D) {
- // If we got a decl, use the type-as-written to make sure arrays
- // get mangled right. Note that we can't rely on the TSI
- // existing if (for example) the parameter was synthesized.
- for (FunctionDecl::param_const_iterator Parm = D->param_begin(),
- ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
- TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
- QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
- mangleArgumentType(Type, (*Parm)->getSourceRange());
- }
- } else {
- // Happens for function pointer type arguments for example.
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- mangleArgumentType(*Arg, SourceRange());
- }
+ // Happens for function pointer type arguments for example.
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ mangleArgumentType(*Arg, Range);
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
Out << 'Z';
@@ -1428,8 +1430,7 @@
SourceRange) {
llvm_unreachable("Should have been special cased");
}
-void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T,
- Qualifiers Quals) {
+void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
QualType ElementTy(T, 0);
SmallVector<llvm::APInt, 3> Dimensions;
for (;;) {
@@ -1468,8 +1469,7 @@
mangleNumber(Dimensions.size());
for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim)
mangleNumber(Dimensions[Dim].getLimitedValue());
- mangleType(getASTContext().getQualifiedType(ElementTy.getTypePtr(), Quals),
- SourceRange(), QMM_Escape);
+ mangleType(ElementTy, SourceRange(), QMM_Escape);
}
// <type> ::= <pointer-to-member-type>
Index: test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -162,3 +162,45 @@
void foo(Vector*, const Vector, const double) {}
// CHECK: "\01?foo@@YAXPAY02NQBNN at Z"
// X64: "\01?foo@@YAXPEAY02NQEBNN at Z"
+
+typedef void (*ConstFunPtr)(int *const d);
+void foo_fnptrconst(ConstFunPtr f) { }
+// CHECK: "\01?foo_fnptrconst@@YAXP6AXQAH at Z@Z"
+// X64: "\01?foo_fnptrconst@@YAXP6AXQEAH at Z@Z"
+
+typedef void (*ArrayFunPtr)(int d[1]);
+void foo_fnptrarray(ArrayFunPtr f) { }
+// CHECK: "\01?foo_fnptrarray@@YAXP6AXQAH at Z@Z"
+// X64: "\01?foo_fnptrarray@@YAXP6AXQEAH at Z@Z"
+
+void foo_fnptrbackref1(ArrayFunPtr f1, ArrayFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref1@@YAXP6AXQAH at Z1@Z"
+// X64: "\01?foo_fnptrbackref1@@YAXP6AXQEAH at Z1@Z"
+
+void foo_fnptrbackref2(ArrayFunPtr f1, ConstFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref2@@YAXP6AXQAH at Z1@Z"
+// X64: "\01?foo_fnptrbackref2@@YAXP6AXQEAH at Z1@Z"
+
+typedef void (*NormalFunPtr)(int *d);
+void foo_fnptrbackref3(ArrayFunPtr f1, NormalFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref3@@YAXP6AXQAH at Z1@Z"
+// X64: "\01?foo_fnptrbackref3@@YAXP6AXQEAH at Z1@Z"
+
+void foo_fnptrbackref4(NormalFunPtr f1, ArrayFunPtr f2) { }
+// CHECK: "\01?foo_fnptrbackref4@@YAXP6AXPAH at Z1@Z"
+// X64: "\01?foo_fnptrbackref4@@YAXP6AXPEAH at Z1@Z"
+
+ArrayFunPtr ret_fnptrarray() { return 0; }
+// CHECK: "\01?ret_fnptrarray@@YAP6AXQAH at ZXZ"
+// X64: "\01?ret_fnptrarray@@YAP6AXQEAH at ZXZ"
+
+// Test that we mangle the forward decl when we have a redeclaration with a
+// slightly different type.
+void mangle_fwd(char * const x);
+void mangle_fwd(char * x) {}
+// CHECK: "\01?mangle_fwd@@YAXQAD at Z"
+// X64: "\01?mangle_fwd@@YAXQEAD at Z"
+
+void mangle_no_fwd(char * x) {}
+// CHECK: "\01?mangle_no_fwd@@YAXPAD at Z"
+// X64: "\01?mangle_no_fwd@@YAXPEAD at Z"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D844.4.patch
Type: text/x-patch
Size: 7839 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130603/f7c9f921/attachment.bin>
More information about the cfe-commits
mailing list