forked from OSchip/llvm-project
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. llvm-svn: 159060
This commit is contained in:
parent
9137c399bd
commit
3a691a367c
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
: PredefinedExpr::ComputeName((PredefinedExpr::IdentType)IdentType,
|
||||
CurDecl));
|
||||
|
||||
llvm::Constant *C =
|
||||
CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str());
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue