Add support for MSVC's __FUNCSIG__
It is very similar to GCC's __PRETTY_FUNCTION__, except it prints the calling convention. Reviewers: majnemer Differential Revision: http://reviews.llvm.org/D3311 llvm-svn: 205780
This commit is contained in:
parent
d88fec3d3a
commit
52edddaea5
|
@ -1164,6 +1164,7 @@ public:
|
|||
Function,
|
||||
LFunction, // Same as Function, but as wide string.
|
||||
FuncDName,
|
||||
FuncSig,
|
||||
PrettyFunction,
|
||||
/// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
|
||||
/// 'virtual' keyword is omitted for virtual member functions.
|
||||
|
|
|
@ -365,6 +365,7 @@ KEYWORD(typeof , KEYGNU)
|
|||
|
||||
// MS Extensions
|
||||
KEYWORD(__FUNCDNAME__ , KEYMS)
|
||||
KEYWORD(__FUNCSIG__ , KEYMS)
|
||||
KEYWORD(L__FUNCTION__ , KEYMS)
|
||||
TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS)
|
||||
TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
|
||||
|
|
|
@ -1684,6 +1684,7 @@ void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
|
|||
case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break;
|
||||
case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break;
|
||||
case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
|
||||
case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -478,7 +478,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
|
|||
return "";
|
||||
}
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
|
||||
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual)
|
||||
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
|
||||
return FD->getNameAsString();
|
||||
|
||||
SmallString<256> Name;
|
||||
|
@ -494,7 +494,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
|
|||
PrintingPolicy Policy(Context.getLangOpts());
|
||||
std::string Proto;
|
||||
llvm::raw_string_ostream POut(Proto);
|
||||
FD->printQualifiedName(POut, Policy);
|
||||
|
||||
const FunctionDecl *Decl = FD;
|
||||
if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern())
|
||||
|
@ -504,6 +503,19 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
|
|||
if (FD->hasWrittenPrototype())
|
||||
FT = dyn_cast<FunctionProtoType>(AFT);
|
||||
|
||||
if (IT == FuncSig) {
|
||||
switch (FT->getCallConv()) {
|
||||
case CC_C: POut << "__cdecl "; break;
|
||||
case CC_X86StdCall: POut << "__stdcall "; break;
|
||||
case CC_X86FastCall: POut << "__fastcall "; break;
|
||||
case CC_X86ThisCall: POut << "__thiscall "; break;
|
||||
// Only bother printing the conventions that MSVC knows about.
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
FD->printQualifiedName(POut, Policy);
|
||||
|
||||
POut << "(";
|
||||
if (FT) {
|
||||
for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
|
||||
|
|
|
@ -789,6 +789,9 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
|
|||
case PredefinedExpr::FuncDName:
|
||||
OS << "__FUNCDNAME__";
|
||||
break;
|
||||
case PredefinedExpr::FuncSig:
|
||||
OS << "__FUNCSIG__";
|
||||
break;
|
||||
case PredefinedExpr::LFunction:
|
||||
OS << "L__FUNCTION__";
|
||||
break;
|
||||
|
|
|
@ -1953,33 +1953,27 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
|
|||
case PredefinedExpr::Function:
|
||||
case PredefinedExpr::LFunction:
|
||||
case PredefinedExpr::FuncDName:
|
||||
case PredefinedExpr::FuncSig:
|
||||
case PredefinedExpr::PrettyFunction: {
|
||||
PredefinedExpr::IdentType IdentType = E->getIdentType();
|
||||
std::string GlobalVarName;
|
||||
std::string GVName;
|
||||
|
||||
// FIXME: We should use the string literal mangling for the Microsoft C++
|
||||
// ABI so that strings get merged.
|
||||
switch (IdentType) {
|
||||
default: llvm_unreachable("Invalid type");
|
||||
case PredefinedExpr::Func:
|
||||
GlobalVarName = "__func__.";
|
||||
break;
|
||||
case PredefinedExpr::Function:
|
||||
GlobalVarName = "__FUNCTION__.";
|
||||
break;
|
||||
case PredefinedExpr::FuncDName:
|
||||
GlobalVarName = "__FUNCDNAME__.";
|
||||
break;
|
||||
case PredefinedExpr::LFunction:
|
||||
GlobalVarName = "L__FUNCTION__.";
|
||||
break;
|
||||
case PredefinedExpr::PrettyFunction:
|
||||
GlobalVarName = "__PRETTY_FUNCTION__.";
|
||||
break;
|
||||
case PredefinedExpr::Func: GVName = "__func__."; break;
|
||||
case PredefinedExpr::Function: GVName = "__FUNCTION__."; break;
|
||||
case PredefinedExpr::FuncDName: GVName = "__FUNCDNAME__."; break;
|
||||
case PredefinedExpr::FuncSig: GVName = "__FUNCSIG__."; break;
|
||||
case PredefinedExpr::LFunction: GVName = "L__FUNCTION__."; break;
|
||||
case PredefinedExpr::PrettyFunction: GVName = "__PRETTY_FUNCTION__."; break;
|
||||
}
|
||||
|
||||
StringRef FnName = CurFn->getName();
|
||||
if (FnName.startswith("\01"))
|
||||
FnName = FnName.substr(1);
|
||||
GlobalVarName += FnName;
|
||||
GVName += FnName;
|
||||
|
||||
// If this is outside of a function use the top level decl.
|
||||
const Decl *CurDecl = CurCodeDecl;
|
||||
|
@ -2010,15 +2004,13 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
|
|||
getContext().getTypeSizeInChars(ElemType).getQuantity(),
|
||||
FunctionName, RawChars);
|
||||
C = GetAddrOfConstantWideString(RawChars,
|
||||
GlobalVarName.c_str(),
|
||||
GVName.c_str(),
|
||||
getContext(),
|
||||
E->getType(),
|
||||
E->getLocation(),
|
||||
CGM);
|
||||
} else {
|
||||
C = CGM.GetAddrOfConstantCString(FunctionName,
|
||||
GlobalVarName.c_str(),
|
||||
1);
|
||||
C = CGM.GetAddrOfConstantCString(FunctionName, GVName.c_str(), 1);
|
||||
}
|
||||
return MakeAddrLValue(C, E->getType());
|
||||
}
|
||||
|
|
|
@ -835,6 +835,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
|
||||
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
|
||||
case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]
|
||||
case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]
|
||||
case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]
|
||||
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
|
||||
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
|
||||
|
|
|
@ -936,6 +936,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
|
|||
case tok::kw___real:
|
||||
case tok::kw___FUNCTION__:
|
||||
case tok::kw___FUNCDNAME__:
|
||||
case tok::kw___FUNCSIG__:
|
||||
case tok::kw_L__FUNCTION__:
|
||||
case tok::kw___PRETTY_FUNCTION__:
|
||||
case tok::kw___uuidof:
|
||||
|
|
|
@ -2872,6 +2872,7 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
|
|||
case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
|
||||
case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
|
||||
case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
|
||||
case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS]
|
||||
case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
|
||||
case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// RUN: %clang_cc1 -std=c++11 %s -fms-extensions -fno-rtti -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// Similar to predefined-expr.cpp, but not as exhaustive, since it's basically
|
||||
// equivalent to __PRETTY_FUNCTION__.
|
||||
|
||||
extern "C" int printf(const char *, ...);
|
||||
|
||||
void freeFunc(int *, char) {
|
||||
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
|
||||
}
|
||||
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00"
|
||||
|
||||
struct TopLevelClass {
|
||||
void topLevelMethod(int *, char);
|
||||
};
|
||||
void TopLevelClass::topLevelMethod(int *, char) {
|
||||
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
|
||||
}
|
||||
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00"
|
||||
|
||||
namespace NS {
|
||||
struct NamespacedClass {
|
||||
void namespacedMethod(int *, char);
|
||||
};
|
||||
void NamespacedClass::namespacedMethod(int *, char) {
|
||||
printf("__FUNCSIG__ %s\n\n", __FUNCSIG__);
|
||||
}
|
||||
// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00"
|
||||
}
|
Loading…
Reference in New Issue