From: Anders Carlsson Date: Tue, 8 Sep 2009 18:24:21 +0000 (+0000) Subject: Vastly improve PredefinedExpr output, both in Sema and CodeGen. Patch by Sam Weinig! X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3a082d81006e7a2e01a6e431a22e21c78490ff8f;p=clang Vastly improve PredefinedExpr output, both in Sema and CodeGen. Patch by Sam Weinig! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81237 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 765d04947c..b91816e2ad 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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 diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index cab76c3ee2..5faa5d54b3 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -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; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index b42c736432..9c376c50a3 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index ca1ae63ff8..4e07b957a7 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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 Names; std::string QualName; const DeclContext *Ctx = getDeclContext(); @@ -232,12 +236,11 @@ std::string NamedDecl::getQualifiedNameAsString() const { if (const ClassTemplateSpecializationDecl *Spec = dyn_cast(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(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"); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 8338c48c0b..ee2b81560d 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -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(getDeclContext())) - length += CID->getNameAsString().size()+1; - length += getSelector().getAsString().size(); // selector name - return length; -} - ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { if (ObjCInterfaceDecl *ID = dyn_cast(getDeclContext())) return ID; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index daa98aeeab..7171c79c44 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -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 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(CurrentDecl)) { + if (IT != PrettyFunction) + return FD->getNameAsString(); + + llvm::SmallString<256> Name; + llvm::raw_svector_ostream Out(Name); + + if (const CXXMethodDecl *MD = dyn_cast(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(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(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(MD->getDeclContext())) { + Out << '('; + Out << CID->getNameAsString(); + Out << ')'; + } + Out << ' '; + Out << MD->getSelector().getAsString(); + Out << ']'; + + Out.flush(); + return Name.str().str(); + } + if (isa(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. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 4a8253d9cd..d39e10f1f0 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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(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 = diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7d2e308349..17708346ab 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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); diff --git a/test/CodeGen/predefined-expr.c b/test/CodeGen/predefined-expr.c new file mode 100644 index 0000000000..0c6e213b86 --- /dev/null +++ b/test/CodeGen/predefined-expr.c @@ -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 + +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; +} diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp new file mode 100644 index 0000000000..733e0ef663 --- /dev/null +++ b/test/CodeGenCXX/predefined-expr.cpp @@ -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::classTemplateFunction()" = private constant [60 x i8] c"void NS::ClassTemplate::classTemplateFunction()\00" +// CHECK: @"__PRETTY_FUNCTION__.void NS::ClassTemplate::classTemplateFunction()" = private constant [53 x i8] c"void NS::ClassTemplate::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::functionReturingTemplate2()" = private constant [64 x i8] c"ClassTemplate NS::Base::functionReturingTemplate2()\00" + +// CHECK: @__func__.functionReturingTemplate1 = private constant [26 x i8] c"functionReturingTemplate1\00" +// CHECK: @"__PRETTY_FUNCTION__.ClassTemplate NS::Base::functionReturingTemplate1()" = private constant [57 x i8] c"ClassTemplate NS::Base::functionReturingTemplate1()\00" + +// CHECK: @__func__.withTemplateParameter2 = private constant [23 x i8] c"withTemplateParameter2\00" +// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::withTemplateParameter2(ClassTemplate)" = private constant [65 x i8] c"void NS::Base::withTemplateParameter2(ClassTemplate)\00" + +// CHECK: @__func__.withTemplateParameter1 = private constant [23 x i8] c"withTemplateParameter1\00" +// CHECK: @"__PRETTY_FUNCTION__.void NS::Base::withTemplateParameter1(ClassTemplate)" = private constant [58 x i8] c"void NS::Base::withTemplateParameter1(ClassTemplate)\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 + +namespace NS { + +template +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) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + void withTemplateParameter2(ClassTemplate) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + ClassTemplate functionReturingTemplate1() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return ClassTemplate(); + } + + ClassTemplate functionReturingTemplate2() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return ClassTemplate(); + } + + template + 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()); + b.withTemplateParameter2(NS::ClassTemplate()); + b.functionReturingTemplate1(); + b.functionReturingTemplate2(); + b.functionTemplate1(0); + b.functionTemplate1(0); + + NS::Derived d; + d.virtualFunction(); + + NS::ClassTemplate t1; + t1.classTemplateFunction(); + NS::ClassTemplate t2; + t2.classTemplateFunction(); + + NS::Constructor c1; + NS::Constructor c2(0); + NS::Constructor c3((NS::Base *)0); + + { + NS::Destructor destructor; + } + + NS::externFunction(); + + return 0; +} diff --git a/test/CodeGenObjC/predefined-expr-in-method.m b/test/CodeGenObjC/predefined-expr-in-method.m deleted file mode 100644 index 812ef97252..0000000000 --- a/test/CodeGenObjC/predefined-expr-in-method.m +++ /dev/null @@ -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; -} diff --git a/test/CodeGenObjC/predefined-expr.m b/test/CodeGenObjC/predefined-expr.m new file mode 100644 index 0000000000..6e55428177 --- /dev/null +++ b/test/CodeGenObjC/predefined-expr.m @@ -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 + +@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