aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2013-11-06 23:31:56 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2013-11-06 23:31:56 +0000
commitbafa74f360cb3ec82fa8c688845330f491d167fd (patch)
tree04e5868504115359abe3a3fc4a9c80d82d250921
parent00b0f7e1174b7f552ffec0fe0e088584a5d1d092 (diff)
downloadclang-bafa74f360cb3ec82fa8c688845330f491d167fd.tar.gz
[-fms-extensions] Add support for __FUNCDNAME__
Summary: Similar to __FUNCTION__, MSVC exposes the name of the enclosing mangled function name via __FUNCDNAME__. This implementation is very naive and unoptimized, it is expected that __FUNCDNAME__ would be used rarely in practice. Reviewers: rnk, rsmith, thakis CC: cfe-commits, silvas Differential Revision: http://llvm-reviews.chandlerc.com/D2109 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194181 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Expr.h1
-rw-r--r--include/clang/Basic/TokenKinds.def1
-rw-r--r--lib/AST/ASTDumper.cpp1
-rw-r--r--lib/AST/Expr.cpp25
-rw-r--r--lib/AST/StmtPrinter.cpp3
-rw-r--r--lib/CodeGen/CGExpr.cpp4
-rw-r--r--lib/Parse/ParseExpr.cpp3
-rw-r--r--lib/Parse/ParseTentative.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp1
9 files changed, 40 insertions, 0 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index eee304aea6..f2648b9a4a 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1150,6 +1150,7 @@ public:
Func,
Function,
LFunction, // Same as Function, but as wide string.
+ FuncDName,
PrettyFunction,
/// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index f0a042d31a..c17449c4bd 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -349,6 +349,7 @@ KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
KEYWORD(typeof , KEYGNU)
// MS Extensions
+KEYWORD(__FUNCDNAME__ , KEYMS)
KEYWORD(L__FUNCTION__ , KEYMS)
KEYWORD(__is_interface_class , KEYMS)
KEYWORD(__is_sealed , KEYMS)
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 68d3c0ca78..2f402559f4 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -1661,6 +1661,7 @@ void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
default: llvm_unreachable("unknown case");
case PredefinedExpr::Func: OS << " __func__"; break;
case PredefinedExpr::Function: OS << " __FUNCTION__"; break;
+ case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break;
case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break;
case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 38f5e2f488..e467883288 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
@@ -478,6 +479,30 @@ SourceLocation DeclRefExpr::getLocEnd() const {
std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
ASTContext &Context = CurrentDecl->getASTContext();
+ if (IT == PredefinedExpr::FuncDName) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) {
+ OwningPtr<MangleContext> MC;
+ MC.reset(Context.createMangleContext());
+
+ if (MC->shouldMangleDeclName(ND)) {
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND))
+ MC->mangleCXXCtor(CD, Ctor_Base, Out);
+ else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND))
+ MC->mangleCXXDtor(DD, Dtor_Base, Out);
+ else
+ MC->mangleName(ND, Out);
+
+ Out.flush();
+ if (!Buffer.empty() && Buffer.front() == '\01')
+ return Buffer.substr(1);
+ return Buffer.str();
+ } else
+ return ND->getIdentifier()->getName();
+ }
+ return "";
+ }
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual)
return FD->getNameAsString();
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 29e8e9f97f..0ecb5b52c2 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -738,6 +738,9 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
case PredefinedExpr::Function:
OS << "__FUNCTION__";
break;
+ case PredefinedExpr::FuncDName:
+ OS << "__FUNCDNAME__";
+ break;
case PredefinedExpr::LFunction:
OS << "L__FUNCTION__";
break;
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 4a427d540f..96d6a019c2 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1944,6 +1944,7 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
case PredefinedExpr::Func:
case PredefinedExpr::Function:
case PredefinedExpr::LFunction:
+ case PredefinedExpr::FuncDName:
case PredefinedExpr::PrettyFunction: {
PredefinedExpr::IdentType IdentType = E->getIdentType();
std::string GlobalVarName;
@@ -1956,6 +1957,9 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
case PredefinedExpr::Function:
GlobalVarName = "__FUNCTION__.";
break;
+ case PredefinedExpr::FuncDName:
+ GlobalVarName = "__FUNCDNAME__.";
+ break;
case PredefinedExpr::LFunction:
GlobalVarName = "L__FUNCTION__.";
break;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index e9cb827bd9..65b9b82cda 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -491,6 +491,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// [C11] generic-selection
/// '__func__' [C99 6.4.2.2]
/// [GNU] '__FUNCTION__'
+/// [MS] '__FUNCDNAME__'
+/// [MS] 'L__FUNCTION__'
/// [GNU] '__PRETTY_FUNCTION__'
/// [GNU] '(' compound-statement ')'
/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
@@ -870,6 +872,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
break;
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
+ case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]
case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 2dc16d3b0b..b35d632d0a 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -940,6 +940,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___imag:
case tok::kw___real:
case tok::kw___FUNCTION__:
+ case tok::kw___FUNCDNAME__:
case tok::kw_L__FUNCTION__:
case tok::kw___PRETTY_FUNCTION__:
case tok::kw___has_nothrow_assign:
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index edae0147d5..80ebfe7162 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2855,6 +2855,7 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
default: llvm_unreachable("Unknown simple primary expr!");
case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2]
case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break;
+ case tok::kw___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS]
case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
}