]> granicus.if.org Git - clang/commitdiff
Implement code generation for __func__, __FUNCTION__ and __PRETTY_FUNCTION__
authorAnders Carlsson <andersca@mac.com>
Sat, 21 Jul 2007 05:21:51 +0000 (05:21 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 21 Jul 2007 05:21:51 +0000 (05:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40162 91177308-0d34-0410-b5e6-96231b3b80d8

AST/StmtPrinter.cpp
CodeGen/CGExpr.cpp
CodeGen/CodeGenFunction.h
Parse/ParseExpr.cpp
Sema/Sema.h
Sema/SemaExpr.cpp
include/clang/AST/Expr.h
include/clang/AST/StmtNodes.def
include/clang/Parse/Action.h

index a3fff0243056a5b4c4fbb09b88b86ff2c5dba638..05d794c4c7d294ed92f24d4c96e1365cd27f35e2 100644 (file)
@@ -291,6 +291,22 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
   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();
index dd137634711606e6c3cbca5d6fce7445734d5160..6d735e0b5e138db91d3bbdde398a706321499fd0 100644 (file)
@@ -244,6 +244,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
 
   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 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
   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 @@ RValue CodeGenFunction::EmitExpr(const Expr *E) {
     return EmitLoadOfLValue(E);
   case Expr::ArraySubscriptExprClass:
     return EmitArraySubscriptExprRV(cast<ArraySubscriptExpr>(E));
+  case Expr::PreDefinedExprClass:
   case Expr::StringLiteralClass:
     return RValue::get(EmitLValue(E).getAddress());
     
index db92ee29b9acc6a42e9a9afb2e963a74eb3cac5c..d82c787eaea8c23372c76fdba9c888671fee5e16 100644 (file)
@@ -55,6 +55,7 @@ namespace clang {
   class CompoundAssignOperator;
   class ArraySubscriptExpr;
   class ConditionalOperator;
+  class PreDefinedExpr;
   
   class BlockVarDecl;
   class EnumConstantDecl;
@@ -305,6 +306,7 @@ public:
   
   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);
     
index a6c6425d2ef9927c541ec2f565f7f875e8b08ecf..467dc1dcf31ba72ffc0644234d7dafe61ae6b26d 100644 (file)
@@ -507,7 +507,7 @@ Parser::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___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);
index e76fa24ce80a87a1442ab6fc792af5f0a1bc636f..b8a03bc096fbdf24d8cdbe066949f0a31f895490 100644 (file)
@@ -206,7 +206,7 @@ public:
   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 &);
index 7ba795f47e4ce6018c9c07f45782fa51ebfa579d..3bad52a4751cd84e0a9c67a12ee27166a151793b 100644 (file)
@@ -83,17 +83,26 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
   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) {
index fcf83b4ca3d661a5f69d81a8a1fbfeb454a48739..86762f1af40dd0f38f2c3b9e34968acfeb02e67e 100644 (file)
@@ -134,6 +134,33 @@ public:
   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;
index c48b6ca5c4795413fcae4455470fe679cd8c6aa6..6f85057686c68d5f91466b2f2f51f5e87ef883d7 100644 (file)
@@ -41,9 +41,10 @@ STMT(15, ReturnStmt      , Stmt)
 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)
index 8d49b36ac95d23a7a4c4e1c54b0c85ebb7746b88..c80effe156cd7e2f75da97aa30ef9bb2f032faa2 100644 (file)
@@ -275,8 +275,8 @@ public:
     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; }