From: Nico Weber Date: Sat, 23 Jun 2012 02:07:59 +0000 (+0000) Subject: Support L__FUNCTION__ in microsoft mode, PR11789 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28ad063b279378b19cb0704f977429df366a151e;p=clang Support L__FUNCTION__ in microsoft mode, PR11789 Heavily based on a patch from Aaron Wishnick . 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 --- 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(&*Source.begin()), + reinterpret_cast(&*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(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF16( + &sourceStart,sourceStart + Source.size(), + &targetStart,targetStart + 2*Source.size(),flags); + if (result==conversionOK) + ResultPtr = reinterpret_cast(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(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF32( + &sourceStart,sourceStart + Source.size(), + &targetStart,targetStart + 4*Source.size(),flags); + if (result==conversionOK) + ResultPtr = reinterpret_cast(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(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));