aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2012-06-23 02:07:59 +0000
committerNico Weber <nicolasweber@gmx.de>2012-06-23 02:07:59 +0000
commit28ad063b279378b19cb0704f977429df366a151e (patch)
tree4c797a94b4a042caaad08b236cca4b314c92be6e
parent3f835687b8f7ad3060fe4c462727b212ed714b30 (diff)
Support L__FUNCTION__ in microsoft mode, PR11789
Heavily based on a patch from Aaron Wishnick <aaron.s.wishnick@gmail.com>. I'll clean up the duplicated function in CodeGen as a follow-up, later today or tomorrow. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159060 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Expr.h1
-rw-r--r--include/clang/Basic/TokenKinds.def3
-rw-r--r--lib/AST/StmtDumper.cpp1
-rw-r--r--lib/AST/StmtPrinter.cpp3
-rw-r--r--lib/CodeGen/CGExpr.cpp101
-rw-r--r--lib/Parse/ParseExpr.cpp1
-rw-r--r--lib/Parse/ParseTentative.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp6
8 files changed, 110 insertions, 7 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 8c3712dfc8..cdf9a58e8c 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1047,6 +1047,7 @@ public:
enum IdentType {
Func,
Function,
+ LFunction, // Same as Function, but as wide string.
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 7c800df7fb..bbab3c7f36 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -342,6 +342,9 @@ KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
// GNU Extensions (outside impl-reserved namespace)
KEYWORD(typeof , KEYGNU)
+// MS Extensions
+KEYWORD(L__FUNCTION__ , KEYMS)
+
// GNU and MS Type Traits
KEYWORD(__has_nothrow_assign , KEYCXX)
KEYWORD(__has_nothrow_copy , KEYCXX)
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index a57cce8371..ce330e06b7 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -424,6 +424,7 @@ void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) {
default: llvm_unreachable("unknown case");
case PredefinedExpr::Func: OS << " __func__"; break;
case PredefinedExpr::Function: OS << " __FUNCTION__"; break;
+ case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break;
case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break;
}
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index cb757cdde1..9c7259745c 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -643,6 +643,9 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
case PredefinedExpr::Function:
OS << "__FUNCTION__";
break;
+ case PredefinedExpr::LFunction:
+ OS << "L__FUNCTION__";
+ break;
case PredefinedExpr::PrettyFunction:
OS << "__PRETTY_FUNCTION__";
break;
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 0f794487b9..c8563d6044 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -21,6 +21,7 @@
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/ConvertUTF.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
#include "llvm/LLVMContext.h"
@@ -1701,6 +1702,73 @@ LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
E->getType());
}
+static llvm::Constant*
+GetAddrOfConstantWideString(StringRef Str,
+ const char *GlobalName,
+ ASTContext &Context,
+ QualType Ty, SourceLocation Loc,
+ CodeGenModule &CGM) {
+
+ StringLiteral *SL = StringLiteral::Create(Context,
+ Str,
+ StringLiteral::Wide,
+ /*Pascal = */false,
+ Ty, Loc);
+ llvm::Constant *C = CGM.GetConstantArrayFromStringLiteral(SL);
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), C->getType(),
+ !CGM.getLangOpts().WritableStrings,
+ llvm::GlobalValue::PrivateLinkage,
+ C, GlobalName);
+ const unsigned WideAlignment =
+ Context.getTypeAlignInChars(Ty).getQuantity();
+ GV->setAlignment(WideAlignment);
+ return GV;
+}
+
+// FIXME: Mostly copied from StringLiteralParser::CopyStringFragment
+static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
+ SmallString<32>& Target) {
+ Target.resize(CharByteWidth * (Source.size() + 1));
+ char* ResultPtr = &Target[0];
+
+ assert(CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4);
+ ConversionResult result = conversionOK;
+ // Copy the character span over.
+ if (CharByteWidth == 1) {
+ if (!isLegalUTF8String(reinterpret_cast<const UTF8*>(&*Source.begin()),
+ reinterpret_cast<const UTF8*>(&*Source.end())))
+ result = sourceIllegal;
+ memcpy(ResultPtr, Source.data(), Source.size());
+ ResultPtr += Source.size();
+ } else if (CharByteWidth == 2) {
+ UTF8 const *sourceStart = (UTF8 const *)Source.data();
+ // FIXME: Make the type of the result buffer correct instead of
+ // using reinterpret_cast.
+ UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr);
+ ConversionFlags flags = strictConversion;
+ result = ConvertUTF8toUTF16(
+ &sourceStart,sourceStart + Source.size(),
+ &targetStart,targetStart + 2*Source.size(),flags);
+ if (result==conversionOK)
+ ResultPtr = reinterpret_cast<char*>(targetStart);
+ } else if (CharByteWidth == 4) {
+ UTF8 const *sourceStart = (UTF8 const *)Source.data();
+ // FIXME: Make the type of the result buffer correct instead of
+ // using reinterpret_cast.
+ UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr);
+ ConversionFlags flags = strictConversion;
+ result = ConvertUTF8toUTF32(
+ &sourceStart,sourceStart + Source.size(),
+ &targetStart,targetStart + 4*Source.size(),flags);
+ if (result==conversionOK)
+ ResultPtr = reinterpret_cast<char*>(targetStart);
+ }
+ assert((result != targetExhausted)
+ && "ConvertUTF8toUTFXX exhausted target buffer");
+ assert(result == conversionOK);
+ Target.resize(ResultPtr - &Target[0]);
+}
LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
switch (E->getIdentType()) {
@@ -1709,11 +1777,12 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
case PredefinedExpr::Func:
case PredefinedExpr::Function:
+ case PredefinedExpr::LFunction:
case PredefinedExpr::PrettyFunction: {
- unsigned Type = E->getIdentType();
+ unsigned IdentType = E->getIdentType();
std::string GlobalVarName;
- switch (Type) {
+ switch (IdentType) {
default: llvm_unreachable("Invalid type");
case PredefinedExpr::Func:
GlobalVarName = "__func__.";
@@ -1721,6 +1790,9 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
case PredefinedExpr::Function:
GlobalVarName = "__FUNCTION__.";
break;
+ case PredefinedExpr::LFunction:
+ GlobalVarName = "L__FUNCTION__.";
+ break;
case PredefinedExpr::PrettyFunction:
GlobalVarName = "__PRETTY_FUNCTION__.";
break;
@@ -1738,10 +1810,27 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
std::string FunctionName =
(isa<BlockDecl>(CurDecl)
? FnName.str()
- : PredefinedExpr::ComputeName((PredefinedExpr::IdentType)Type, CurDecl));
-
- llvm::Constant *C =
- CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str());
+ : PredefinedExpr::ComputeName((PredefinedExpr::IdentType)IdentType,
+ CurDecl));
+
+ const Type* ElemType = E->getType()->getArrayElementTypeNoTypeQual();
+ llvm::Constant *C;
+ if (ElemType->isWideCharType()) {
+ SmallString<32> RawChars;
+ ConvertUTF8ToWideString(
+ getContext().getTypeSizeInChars(ElemType).getQuantity(),
+ FunctionName, RawChars);
+ C = GetAddrOfConstantWideString(RawChars,
+ GlobalVarName.c_str(),
+ getContext(),
+ E->getType(),
+ E->getLocation(),
+ CGM);
+ } else {
+ C = CGM.GetAddrOfConstantCString(FunctionName,
+ GlobalVarName.c_str(),
+ 1);
+ }
return MakeAddrLValue(C, E->getType());
}
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index d1c5989475..840402530b 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -854,6 +854,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_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);
ConsumeToken();
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index c2e539ca61..8a5e7266d3 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -744,6 +744,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___imag:
case tok::kw___real:
case tok::kw___FUNCTION__:
+ case tok::kw_L__FUNCTION__:
case tok::kw___PRETTY_FUNCTION__:
case tok::kw___has_nothrow_assign:
case tok::kw___has_nothrow_copy:
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 286d6d73a3..d652a253fe 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2463,6 +2463,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_L__FUNCTION__: IT = PredefinedExpr::LFunction; break;
case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break;
}
@@ -2484,7 +2485,10 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
- ResTy = Context.CharTy.withConst();
+ if (Kind == tok::kw_L__FUNCTION__)
+ ResTy = Context.WCharTy.withConst();
+ else
+ ResTy = Context.CharTy.withConst();
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
}
return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));