Implement code generation for __func__, __FUNCTION__ and __PRETTY_FUNCTION__

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40162 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp
index a3fff02..05d794c 100644
--- a/AST/StmtPrinter.cpp
+++ b/AST/StmtPrinter.cpp
@@ -291,6 +291,22 @@
   OS << Node->getDecl()->getName();
 }
 
+void StmtPrinter::VisitPreDefinedExpr(PreDefinedExpr *Node) {
+  switch (Node->getIdentType()) {
+    default:
+      assert(0 && "unknown case");
+    case PreDefinedExpr::Func:
+      OS << "__func__";
+      break;
+    case PreDefinedExpr::Function:
+      OS << "__FUNCTION__";
+      break;
+    case PreDefinedExpr::PrettyFunction:
+      OS << "__PRETTY_FUNCTION__";
+      break;
+  }
+}
+
 void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
   // FIXME should print an L for wchar_t constants
   unsigned value = Node->getValue();
diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp
index dd13763..6d735e0 100644
--- a/CodeGen/CGExpr.cpp
+++ b/CodeGen/CGExpr.cpp
@@ -244,6 +244,8 @@
 
   case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E));
   case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+  case Expr::PreDefinedExprClass:
+    return EmitPreDefinedLValue(cast<PreDefinedExpr>(E));
   case Expr::StringLiteralClass:
     return EmitStringLiteralLValue(cast<StringLiteral>(E));
     
@@ -390,6 +392,40 @@
   return LValue::MakeAddr(C);
 }
 
+LValue CodeGenFunction::EmitPreDefinedLValue(const PreDefinedExpr *E) {
+  std::string FunctionName(CurFuncDecl->getName());
+  std::string GlobalVarName;
+  
+  switch (E->getIdentType()) {
+    default:
+      assert(0 && "unknown pre-defined ident type");
+    case PreDefinedExpr::Func:
+      GlobalVarName = "__func__.";
+      break;
+    case PreDefinedExpr::Function:
+      GlobalVarName = "__FUNCTION__.";
+      break;
+    case PreDefinedExpr::PrettyFunction:
+      // FIXME:: Demangle C++ method names
+      GlobalVarName = "__PRETTY_FUNCTION__.";
+      break;
+  }
+  
+  GlobalVarName += CurFuncDecl->getName();
+  
+  // FIXME: Can cache/reuse these within the module.
+  llvm::Constant *C=llvm::ConstantArray::get(FunctionName);
+  
+  // Create a global variable for this.
+  C = new llvm::GlobalVariable(C->getType(), true, 
+                               llvm::GlobalValue::InternalLinkage,
+                               C, GlobalVarName, CurFn->getParent());
+  llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
+  llvm::Constant *Zeros[] = { Zero, Zero };
+  C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
+  return LValue::MakeAddr(C);
+}
+
 LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
   // The index must always be a pointer or integer, neither of which is an
   // aggregate.  Emit it.
@@ -457,6 +493,7 @@
     return EmitLoadOfLValue(E);
   case Expr::ArraySubscriptExprClass:
     return EmitArraySubscriptExprRV(cast<ArraySubscriptExpr>(E));
+  case Expr::PreDefinedExprClass:
   case Expr::StringLiteralClass:
     return RValue::get(EmitLValue(E).getAddress());
     
diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h
index db92ee2..d82c787 100644
--- a/CodeGen/CodeGenFunction.h
+++ b/CodeGen/CodeGenFunction.h
@@ -55,6 +55,7 @@
   class CompoundAssignOperator;
   class ArraySubscriptExpr;
   class ConditionalOperator;
+  class PreDefinedExpr;
   
   class BlockVarDecl;
   class EnumConstantDecl;
@@ -305,6 +306,7 @@
   
   LValue EmitDeclRefLValue(const DeclRefExpr *E);
   LValue EmitStringLiteralLValue(const StringLiteral *E);
+  LValue EmitPreDefinedLValue(const PreDefinedExpr *E);
   LValue EmitUnaryOpLValue(const UnaryOperator *E);
   LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E);
     
diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp
index a6c6425..467dc1d 100644
--- a/Parse/ParseExpr.cpp
+++ b/Parse/ParseExpr.cpp
@@ -507,7 +507,7 @@
   case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2]
   case tok::kw___FUNCTION__:   // primary-expression: __FUNCTION__ [GNU]
   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
-    Res = Actions.ParseSimplePrimaryExpr(Tok.getLocation(), SavedKind);
+    Res = Actions.ParsePreDefinedExpr(Tok.getLocation(), SavedKind);
     ConsumeToken();
     // These can be followed by postfix-expr pieces.
     return ParsePostfixExpressionSuffix(Res);
diff --git a/Sema/Sema.h b/Sema/Sema.h
index e76fa24..b8a03bc 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -206,7 +206,7 @@
   virtual ExprResult ParseIdentifierExpr(Scope *S, SourceLocation Loc,
                                          IdentifierInfo &II,
                                          bool HasTrailingLParen);
-  virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc,
+  virtual ExprResult ParsePreDefinedExpr(SourceLocation Loc,
                                             tok::TokenKind Kind);
   virtual ExprResult ParseNumericConstant(const Token &);
   virtual ExprResult ParseCharacterConstant(const Token &);
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 7ba795f..3bad52a 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -83,17 +83,26 @@
   abort();
 }
 
-Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
-                                              tok::TokenKind Kind) {
+Sema::ExprResult Sema::ParsePreDefinedExpr(SourceLocation Loc,
+                                           tok::TokenKind Kind) {
+  PreDefinedExpr::IdentType IT;
+  
   switch (Kind) {
   default:
     assert(0 && "Unknown simple primary expr!");
-  // TODO: MOVE this to be some other callback.
   case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2]
+    IT = PreDefinedExpr::Func;
+    break;
   case tok::kw___FUNCTION__:   // primary-expression: __FUNCTION__ [GNU]
+    IT = PreDefinedExpr::Function;
+    break;
   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
-    return 0;
+    IT = PreDefinedExpr::PrettyFunction;
+    break;
   }
+  
+  // Pre-defined identifiers are always of type char *.
+  return new PreDefinedExpr(Loc, Context.getPointerType(Context.CharTy), IT);
 }
 
 Sema::ExprResult Sema::ParseCharacterConstant(const Token &Tok) {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index fcf83b4..86762f1 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -134,6 +134,33 @@
   static bool classof(const DeclRefExpr *) { return true; }
 };
 
+// PreDefinedExpr - [C99 6.4.2.2] - A pre-defined identifier such as __func__
+class PreDefinedExpr : public Expr {
+public:
+  enum IdentType {
+    Func,
+    Function,
+    PrettyFunction
+  };
+  
+private:
+  SourceLocation Loc;
+  IdentType Type;
+public:
+  PreDefinedExpr(SourceLocation l, QualType type, IdentType IT) 
+    : Expr(PreDefinedExprClass, type), Loc(l), Type(IT) {}
+  
+  IdentType getIdentType() const { return Type; }
+  
+  virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+  virtual void visit(StmtVisitor &Visitor);
+  static bool classof(const Stmt *T) { 
+    return T->getStmtClass() == PreDefinedExprClass; 
+  }
+  static bool classof(const PreDefinedExpr *) { return true; }  
+};
+
 class IntegerLiteral : public Expr {
   llvm::APInt Value;
   SourceLocation Loc;
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index c48b6ca..6f85057 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -41,9 +41,10 @@
 STMT(16, DeclStmt        , Stmt)
 LAST_STMT(16)
 
-FIRST_EXPR(32)
+FIRST_EXPR(31)
 // Expressions.
-STMT(32, Expr                 , Stmt)
+STMT(31, Expr                 , Stmt)
+STMT(32, PreDefinedExpr       , Expr)
 STMT(33, DeclRefExpr          , Expr)
 STMT(34, IntegerLiteral       , Expr)
 STMT(35, FloatingLiteral      , Expr)
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 8d49b36..c80effe 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -275,8 +275,8 @@
     return 0;
   }
   
-  virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc,
-                                            tok::TokenKind Kind) {
+  virtual ExprResult ParsePreDefinedExpr(SourceLocation Loc,
+                                         tok::TokenKind Kind) {
     return 0;
   }
   virtual ExprResult ParseCharacterConstant(const Token &) { return 0; }