forked from OSchip/llvm-project
Vastly improve PredefinedExpr output, both in Sema and CodeGen. Patch by Sam Weinig!
llvm-svn: 81237
This commit is contained in:
parent
0c79736553
commit
2fb0824197
|
@ -121,6 +121,7 @@ public:
|
|||
/// Creating this name is expensive, so it should be called only when
|
||||
/// performance doesn't matter.
|
||||
std::string getQualifiedNameAsString() const;
|
||||
std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const;
|
||||
|
||||
/// declarationReplaces - Determine whether this declaration, if
|
||||
/// known to be well-formed within its context, will replace the
|
||||
|
|
|
@ -195,7 +195,7 @@ public:
|
|||
}
|
||||
|
||||
Selector getSelector() const { return getDeclName().getObjCSelector(); }
|
||||
unsigned getSynthesizedMethodSize() const;
|
||||
|
||||
QualType getResultType() const { return MethodDeclType; }
|
||||
void setResultType(QualType T) { MethodDeclType = T; }
|
||||
|
||||
|
|
|
@ -375,11 +375,9 @@ public:
|
|||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
||||
// FIXME: The logic for computing the value of a predefined expr should go
|
||||
// into a method here that takes the inner-most code decl (a block, function
|
||||
// or objc method) that the expr lives in. This would allow sema and codegen
|
||||
// to be consistent for things like sizeof(__func__) etc.
|
||||
|
||||
static std::string ComputeName(ASTContext &Context, IdentType IT,
|
||||
const Decl *CurrentDecl);
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
|
|
|
@ -216,6 +216,10 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
std::string NamedDecl::getQualifiedNameAsString() const {
|
||||
return getQualifiedNameAsString(getASTContext().getLangOptions());
|
||||
}
|
||||
|
||||
std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
|
||||
std::vector<std::string> Names;
|
||||
std::string QualName;
|
||||
const DeclContext *Ctx = getDeclContext();
|
||||
|
@ -232,12 +236,11 @@ std::string NamedDecl::getQualifiedNameAsString() const {
|
|||
if (const ClassTemplateSpecializationDecl *Spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
|
||||
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
||||
PrintingPolicy Policy(getASTContext().getLangOptions());
|
||||
std::string TemplateArgsStr
|
||||
= TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
TemplateArgs.getFlatArgumentList(),
|
||||
TemplateArgs.flat_size(),
|
||||
Policy);
|
||||
P);
|
||||
Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr);
|
||||
} else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
|
||||
Names.push_back(ND->getNameAsString());
|
||||
|
@ -259,7 +262,6 @@ std::string NamedDecl::getQualifiedNameAsString() const {
|
|||
return QualName;
|
||||
}
|
||||
|
||||
|
||||
bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
|
||||
assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");
|
||||
|
||||
|
|
|
@ -290,23 +290,6 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
|
|||
Context.getObjCSelType()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// getSynthesizedMethodSize - Compute size of synthesized method name
|
||||
/// as done be the rewrite.
|
||||
///
|
||||
unsigned ObjCMethodDecl::getSynthesizedMethodSize() const {
|
||||
// syntesized method name is a concatenation of -/+[class-name selector]
|
||||
// Get length of this name.
|
||||
unsigned length = 3; // _I_ or _C_
|
||||
length += getClassInterface()->getNameAsString().size()+1; // extra for _
|
||||
if (const ObjCCategoryImplDecl *CID =
|
||||
dyn_cast<ObjCCategoryImplDecl>(getDeclContext()))
|
||||
length += CID->getNameAsString().size()+1;
|
||||
length += getSelector().getAsString().size(); // selector name
|
||||
return length;
|
||||
}
|
||||
|
||||
ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
|
||||
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(getDeclContext()))
|
||||
return ID;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
using namespace clang;
|
||||
|
||||
|
@ -29,6 +30,82 @@ using namespace clang;
|
|||
// Primary Expressions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
|
||||
// expr" policy instead.
|
||||
std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT,
|
||||
const Decl *CurrentDecl) {
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
|
||||
if (IT != PrettyFunction)
|
||||
return FD->getNameAsString();
|
||||
|
||||
llvm::SmallString<256> Name;
|
||||
llvm::raw_svector_ostream Out(Name);
|
||||
|
||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
||||
if (MD->isVirtual())
|
||||
Out << "virtual ";
|
||||
}
|
||||
|
||||
PrintingPolicy Policy(Context.getLangOptions());
|
||||
Policy.SuppressTagKind = true;
|
||||
|
||||
std::string Proto = FD->getQualifiedNameAsString(Policy);
|
||||
|
||||
const FunctionType *AFT = FD->getType()->getAsFunctionType();
|
||||
const FunctionProtoType *FT = 0;
|
||||
if (FD->hasWrittenPrototype())
|
||||
FT = dyn_cast<FunctionProtoType>(AFT);
|
||||
|
||||
Proto += "(";
|
||||
if (FT) {
|
||||
llvm::raw_string_ostream POut(Proto);
|
||||
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
|
||||
if (i) POut << ", ";
|
||||
std::string Param;
|
||||
FD->getParamDecl(i)->getType().getAsStringInternal(Param, Policy);
|
||||
POut << Param;
|
||||
}
|
||||
|
||||
if (FT->isVariadic()) {
|
||||
if (FD->getNumParams()) POut << ", ";
|
||||
POut << "...";
|
||||
}
|
||||
}
|
||||
Proto += ")";
|
||||
|
||||
AFT->getResultType().getAsStringInternal(Proto, Policy);
|
||||
|
||||
Out << Proto;
|
||||
|
||||
Out.flush();
|
||||
return Name.str().str();
|
||||
}
|
||||
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) {
|
||||
llvm::SmallString<256> Name;
|
||||
llvm::raw_svector_ostream Out(Name);
|
||||
Out << (MD->isInstanceMethod() ? '-' : '+');
|
||||
Out << '[';
|
||||
Out << MD->getClassInterface()->getNameAsString();
|
||||
if (const ObjCCategoryImplDecl *CID =
|
||||
dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext())) {
|
||||
Out << '(';
|
||||
Out << CID->getNameAsString();
|
||||
Out << ')';
|
||||
}
|
||||
Out << ' ';
|
||||
Out << MD->getSelector().getAsString();
|
||||
Out << ']';
|
||||
|
||||
Out.flush();
|
||||
return Name.str().str();
|
||||
}
|
||||
if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
|
||||
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
|
||||
return "top level";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// getValueAsApproximateDouble - This returns the value as an inaccurate
|
||||
/// double. Note that this may cause loss of precision, but is useful for
|
||||
/// debugging dumps, etc.
|
||||
|
|
|
@ -845,24 +845,13 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
|
|||
GlobalVarName = "__FUNCTION__.";
|
||||
break;
|
||||
case PredefinedExpr::PrettyFunction:
|
||||
// FIXME:: Demangle C++ method names
|
||||
GlobalVarName = "__PRETTY_FUNCTION__.";
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: This isn't right at all. The logic for computing this should go
|
||||
// into a method on PredefinedExpr. This would allow sema and codegen to be
|
||||
// consistent for things like sizeof(__func__) etc.
|
||||
std::string FunctionName;
|
||||
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl)) {
|
||||
FunctionName = CGM.getMangledName(FD);
|
||||
} else {
|
||||
// Just get the mangled name; skipping the asm prefix if it
|
||||
// exists.
|
||||
FunctionName = CurFn->getName();
|
||||
if (FunctionName[0] == '\01')
|
||||
FunctionName = FunctionName.substr(1, std::string::npos);
|
||||
}
|
||||
std::string FunctionName =
|
||||
PredefinedExpr::ComputeName(getContext(), (PredefinedExpr::IdentType)Type,
|
||||
CurCodeDecl);
|
||||
|
||||
GlobalVarName += FunctionName;
|
||||
llvm::Constant *C =
|
||||
|
|
|
@ -1151,17 +1151,15 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
|
|||
|
||||
// Pre-defined identifiers are of type char[x], where x is the length of the
|
||||
// string.
|
||||
unsigned Length;
|
||||
if (FunctionDecl *FD = getCurFunctionDecl())
|
||||
Length = FD->getIdentifier()->getLength();
|
||||
else if (ObjCMethodDecl *MD = getCurMethodDecl())
|
||||
Length = MD->getSynthesizedMethodSize();
|
||||
else {
|
||||
|
||||
Decl *currentDecl = getCurFunctionOrMethodDecl();
|
||||
if (!currentDecl) {
|
||||
Diag(Loc, diag::ext_predef_outside_function);
|
||||
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
|
||||
Length = IT == PredefinedExpr::PrettyFunction ? strlen("top level") : 0;
|
||||
currentDecl = Context.getTranslationUnitDecl();
|
||||
}
|
||||
|
||||
unsigned Length =
|
||||
PredefinedExpr::ComputeName(Context, IT, currentDecl).length();
|
||||
|
||||
llvm::APInt LengthI(32, Length + 1);
|
||||
QualType ResTy = Context.CharTy.getQualifiedType(QualType::Const);
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// CHECK: @__func__.plainFunction = private constant [14 x i8] c"plainFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void plainFunction()" = private constant [21 x i8] c"void plainFunction()\00"
|
||||
// CHECK: @__func__.externFunction = private constant [15 x i8] c"externFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void externFunction()" = private constant [22 x i8] c"void externFunction()\00"
|
||||
// CHECK: @__func__.privateExternFunction = private constant [22 x i8] c"privateExternFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void privateExternFunction()" = private constant [29 x i8] c"void privateExternFunction()\00"
|
||||
// CHECK: @__func__.staticFunction = private constant [15 x i8] c"staticFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void staticFunction()" = private constant [22 x i8] c"void staticFunction()\00"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void plainFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
extern void externFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
__private_extern__ void privateExternFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
static void staticFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
int main() {
|
||||
plainFunction();
|
||||
externFunction();
|
||||
privateExternFunction();
|
||||
staticFunction();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// CHECK: @__func__.externFunction = private constant [15 x i8] c"externFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::externFunction()" = private constant [26 x i8] c"void NS::externFunction()\00"
|
||||
|
||||
// CHECK: @__func__.classTemplateFunction = private constant [22 x i8] c"classTemplateFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::ClassTemplate<NS::Base *>::classTemplateFunction()" = private constant [60 x i8] c"void NS::ClassTemplate<NS::Base *>::classTemplateFunction()\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::ClassTemplate<int>::classTemplateFunction()" = private constant [53 x i8] c"void NS::ClassTemplate<int>::classTemplateFunction()\00"
|
||||
|
||||
// CHECK: @__func__.functionTemplate1 = private constant [18 x i8] c"functionTemplate1\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::functionTemplate1(NS::Base *)" = private constant [45 x i8] c"void NS::Base::functionTemplate1(NS::Base *)\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::functionTemplate1(int)" = private constant [38 x i8] c"void NS::Base::functionTemplate1(int)\00"
|
||||
|
||||
// CHECK: @"__func__.~Destructor" = private constant [12 x i8] c"~Destructor\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Destructor::~Destructor()" = private constant [35 x i8] c"void NS::Destructor::~Destructor()\00"
|
||||
|
||||
// CHECK: @__func__.Constructor = private constant [12 x i8] c"Constructor\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Constructor::Constructor(NS::Base *)" = private constant [46 x i8] c"void NS::Constructor::Constructor(NS::Base *)\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Constructor::Constructor(int)" = private constant [39 x i8] c"void NS::Constructor::Constructor(int)\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Constructor::Constructor()" = private constant [36 x i8] c"void NS::Constructor::Constructor()\00"
|
||||
|
||||
// CHECK: @__func__.virtualFunction = private constant [16 x i8] c"virtualFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.virtual void NS::Derived::virtualFunction()" = private constant [44 x i8] c"virtual void NS::Derived::virtualFunction()\00"
|
||||
|
||||
// CHECK: @__func__.functionReturingTemplate2 = private constant [26 x i8] c"functionReturingTemplate2\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.ClassTemplate<NS::Base *> NS::Base::functionReturingTemplate2()" = private constant [64 x i8] c"ClassTemplate<NS::Base *> NS::Base::functionReturingTemplate2()\00"
|
||||
|
||||
// CHECK: @__func__.functionReturingTemplate1 = private constant [26 x i8] c"functionReturingTemplate1\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.ClassTemplate<int> NS::Base::functionReturingTemplate1()" = private constant [57 x i8] c"ClassTemplate<int> NS::Base::functionReturingTemplate1()\00"
|
||||
|
||||
// CHECK: @__func__.withTemplateParameter2 = private constant [23 x i8] c"withTemplateParameter2\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::withTemplateParameter2(ClassTemplate<NS::Base *>)" = private constant [65 x i8] c"void NS::Base::withTemplateParameter2(ClassTemplate<NS::Base *>)\00"
|
||||
|
||||
// CHECK: @__func__.withTemplateParameter1 = private constant [23 x i8] c"withTemplateParameter1\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::withTemplateParameter1(ClassTemplate<int>)" = private constant [58 x i8] c"void NS::Base::withTemplateParameter1(ClassTemplate<int>)\00"
|
||||
|
||||
// CHECK: @__func__.functionReturningClass = private constant [23 x i8] c"functionReturningClass\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.NS::Base *NS::Base::functionReturningClass()" = private constant [45 x i8] c"NS::Base *NS::Base::functionReturningClass()\00"
|
||||
|
||||
// CHECK: @__func__.functionWithParameters = private constant [23 x i8] c"functionWithParameters\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::functionWithParameters(int, float *, NS::Base *)" = private constant [64 x i8] c"void NS::Base::functionWithParameters(int, float *, NS::Base *)\00"
|
||||
|
||||
// CHECK: @__func__.variadicFunction = private constant [17 x i8] c"variadicFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::variadicFunction(int, ...)" = private constant [42 x i8] c"void NS::Base::variadicFunction(int, ...)\00"
|
||||
|
||||
// CHECK: @"__PRETTY_FUNCTION__.virtual void NS::Base::virtualFunction()" = private constant [41 x i8] c"virtual void NS::Base::virtualFunction()\00"
|
||||
|
||||
// CHECK: @__func__.inlineFunction = private constant [15 x i8] c"inlineFunction\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::inlineFunction()" = private constant [32 x i8] c"void NS::Base::inlineFunction()\00"
|
||||
|
||||
// CHECK: @__func__.staticFunc = private constant [11 x i8] c"staticFunc\00"
|
||||
// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::staticFunc()" = private constant [28 x i8] c"void NS::Base::staticFunc()\00"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace NS {
|
||||
|
||||
template<typename T>
|
||||
class ClassTemplate {
|
||||
public:
|
||||
void classTemplateFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
};
|
||||
|
||||
class Base {
|
||||
public:
|
||||
static void staticFunc() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
inline void inlineFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
virtual void virtualFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void functionWithParameters(int, float*, Base* base) {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
Base *functionReturningClass() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void variadicFunction(int, ...) {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void withTemplateParameter1(ClassTemplate<int>) {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void withTemplateParameter2(ClassTemplate<Base *>) {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
ClassTemplate<int> functionReturingTemplate1() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
return ClassTemplate<int>();
|
||||
}
|
||||
|
||||
ClassTemplate<Base *> functionReturingTemplate2() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
return ClassTemplate<Base *>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void functionTemplate1(T t) {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
};
|
||||
|
||||
class Derived : public Base {
|
||||
public:
|
||||
// Virtual function without being explicitally written.
|
||||
void virtualFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
};
|
||||
|
||||
class Constructor {
|
||||
public:
|
||||
Constructor() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
Constructor(int) {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
Constructor(Base *) {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Destructor {
|
||||
public:
|
||||
~Destructor() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
};
|
||||
|
||||
extern void externFunction() {
|
||||
printf("__func__ %s\n", __func__);
|
||||
printf("__FUNCTION__ %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
NS::Base::staticFunc();
|
||||
|
||||
NS::Base b;
|
||||
b.inlineFunction();
|
||||
b.virtualFunction();
|
||||
b.variadicFunction(0);
|
||||
b.functionWithParameters(0, 0, 0);
|
||||
b.functionReturningClass();
|
||||
|
||||
b.withTemplateParameter1(NS::ClassTemplate<int>());
|
||||
b.withTemplateParameter2(NS::ClassTemplate<NS::Base *>());
|
||||
b.functionReturingTemplate1();
|
||||
b.functionReturingTemplate2();
|
||||
b.functionTemplate1<int>(0);
|
||||
b.functionTemplate1<NS::Base *>(0);
|
||||
|
||||
NS::Derived d;
|
||||
d.virtualFunction();
|
||||
|
||||
NS::ClassTemplate<int> t1;
|
||||
t1.classTemplateFunction();
|
||||
NS::ClassTemplate<NS::Base *> t2;
|
||||
t2.classTemplateFunction();
|
||||
|
||||
NS::Constructor c1;
|
||||
NS::Constructor c2(0);
|
||||
NS::Constructor c3((NS::Base *)0);
|
||||
|
||||
{
|
||||
NS::Destructor destructor;
|
||||
}
|
||||
|
||||
NS::externFunction();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s
|
||||
|
||||
@interface A
|
||||
@end
|
||||
@implementation A
|
||||
+(void) foo {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n", __PRETTY_FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
@end
|
||||
|
||||
int main() {
|
||||
[A foo];
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// CHECK: @"__func__.-[Foo instanceTest1]" = private constant [21 x i8] c"-[Foo instanceTest1]\00"
|
||||
// CHECK: @"__func__.-[Foo instanceTest2:]" = private constant [22 x i8] c"-[Foo instanceTest2:]\00"
|
||||
// CHECK: @"__func__.-[Foo instanceTest3:withB:]" = private constant [28 x i8] c"-[Foo instanceTest3:withB:]\00"
|
||||
// CHECK: @"__func__.-[Foo instanceTest4]" = private constant [21 x i8] c"-[Foo instanceTest4]\00"
|
||||
// CHECK: @"__func__.+[Foo classTest1]" = private constant [18 x i8] c"+[Foo classTest1]\00"
|
||||
// CHECK: @"__func__.+[Foo classTest2:]" = private constant [19 x i8] c"+[Foo classTest2:]\00"
|
||||
// CHECK: @"__func__.+[Foo classTest3:withB:]" = private constant [25 x i8] c"+[Foo classTest3:withB:]\00"
|
||||
// CHECK: @"__func__.+[Foo classTest4]" = private constant [18 x i8] c"+[Foo classTest4]\00"
|
||||
// CHECK: @"__func__.-[Foo(Category) instanceTestWithCategory]" = private constant [42 x i8] c"-[Foo(Category) instanceTestWithCategory]\00"
|
||||
// CHECK: @"__func__.+[Foo(Category) classTestWithCategory]" = private constant [39 x i8] c"+[Foo(Category) classTestWithCategory]\00"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@interface Foo
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
|
||||
- (void)instanceTest1 {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
- (void)instanceTest2:(int)i {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
- (void)instanceTest3:(int)a withB:(double)b {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
- (int)instanceTest4 {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ (void)classTest1 {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
+ (void)classTest2:(int)i {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
+ (void)classTest3:(int)a withB:(double)b {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
+ (int)classTest4 {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface Foo (Category)
|
||||
@end
|
||||
|
||||
@implementation Foo (Category)
|
||||
|
||||
- (void)instanceTestWithCategory {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
+ (void)classTestWithCategory {
|
||||
printf("__func__: %s\n", __func__);
|
||||
printf("__FUNCTION__: %s\n", __FUNCTION__);
|
||||
printf("__PRETTY_FUNCTION__: %s\n\n", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue