From: Anders Carlsson Date: Sat, 21 Jul 2007 05:21:51 +0000 (+0000) Subject: Implement code generation for __func__, __FUNCTION__ and __PRETTY_FUNCTION__ X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=227426661be33ff3e21f2b6b9f97971da2da044f;p=clang 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 a3fff02430..05d794c4c7 100644 --- a/AST/StmtPrinter.cpp +++ b/AST/StmtPrinter.cpp @@ -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(); diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index dd13763471..6d735e0b5e 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -244,6 +244,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast(E)); case Expr::ParenExprClass:return EmitLValue(cast(E)->getSubExpr()); + case Expr::PreDefinedExprClass: + return EmitPreDefinedLValue(cast(E)); case Expr::StringLiteralClass: return EmitStringLiteralLValue(cast(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(E)); + case Expr::PreDefinedExprClass: case Expr::StringLiteralClass: return RValue::get(EmitLValue(E).getAddress()); diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h index db92ee29b9..d82c787eae 100644 --- a/CodeGen/CodeGenFunction.h +++ b/CodeGen/CodeGenFunction.h @@ -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); diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp index a6c6425d2e..467dc1dcf3 100644 --- a/Parse/ParseExpr.cpp +++ b/Parse/ParseExpr.cpp @@ -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); diff --git a/Sema/Sema.h b/Sema/Sema.h index e76fa24ce8..b8a03bc096 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -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 &); diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 7ba795f47e..3bad52a475 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -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) { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index fcf83b4ca3..86762f1af4 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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; diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index c48b6ca5c4..6f85057686 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -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) diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 8d49b36ac9..c80effe156 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -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; }