]> granicus.if.org Git - clang/commitdiff
Vastly improve PredefinedExpr output, both in Sema and CodeGen. Patch by Sam Weinig!
authorAnders Carlsson <andersca@mac.com>
Tue, 8 Sep 2009 18:24:21 +0000 (18:24 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 8 Sep 2009 18:24:21 +0000 (18:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81237 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/AST/Decl.h
include/clang/AST/DeclObjC.h
include/clang/AST/Expr.h
lib/AST/Decl.cpp
lib/AST/DeclObjC.cpp
lib/AST/Expr.cpp
lib/CodeGen/CGExpr.cpp
lib/Sema/SemaExpr.cpp
test/CodeGen/predefined-expr.c [new file with mode: 0644]
test/CodeGenCXX/predefined-expr.cpp [new file with mode: 0644]
test/CodeGenObjC/predefined-expr-in-method.m [deleted file]
test/CodeGenObjC/predefined-expr.m [new file with mode: 0644]

index 765d04947ca8debd2c2e4e297d81ceab6e51bca2..b91816e2adfb8d3c0474d008717d8af0756d0dbd 100644 (file)
@@ -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
index cab76c3ee2da093ceff7ac5b1f900a0b2087bec7..5faa5d54b3e3a9f4d4c0d2b53b456e273be95f3c 100644 (file)
@@ -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; }
   
index b42c736432d156d25e6d90b84c22fa9e7c71630a..9c376c50a39804f1345737dcd904e818e2a5070f 100644 (file)
@@ -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) { 
index ca1ae63ff85fafbc4e42f0296e00d1857c83de41..4e07b957a7d05f180fe254a0629bd5fece069303 100644 (file)
@@ -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");
 
index 8338c48c0bea73ddab49c72a9d8ad42450bb77cb..ee2b81560d76ee1d834c936524d0e62abae061c0 100644 (file)
@@ -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;
index daa98aeeabcdc5d1d56e768e02930f04cdfe741b..7171c79c44ffc3505d1c4579687e4d2d546a456f 100644 (file)
@@ -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.
index 4a8253d9cd9bec11ac2cc9a66a4228894ae0aaf4..d39e10f1f075489e10c906a2a8025be2cc35f468 100644 (file)
@@ -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 = 
index 7d2e308349f9ee4e93a5eb0fb3cfc3fa867a9217..17708346ab8154ec48663d1d35b20c929d4f3f9f 100644 (file)
@@ -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 (file)
index 0000000..0c6e213
--- /dev/null
@@ -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;
+}
diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp
new file mode 100644 (file)
index 0000000..733e0ef
--- /dev/null
@@ -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;
+}
diff --git a/test/CodeGenObjC/predefined-expr-in-method.m b/test/CodeGenObjC/predefined-expr-in-method.m
deleted file mode 100644 (file)
index 812ef97..0000000
+++ /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 (file)
index 0000000..6e55428
--- /dev/null
@@ -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