Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -1161,55 +1161,6 @@ friend class ASTStmtWriter; }; -/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. -class PredefinedExpr : public Expr { -public: - enum IdentType { - Func, - Function, - LFunction, // Same as Function, but as wide string. - FuncDName, - FuncSig, - PrettyFunction, - /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the - /// 'virtual' keyword is omitted for virtual member functions. - PrettyFunctionNoVirtual - }; - -private: - SourceLocation Loc; - IdentType Type; -public: - PredefinedExpr(SourceLocation l, QualType type, IdentType IT) - : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary, - type->isDependentType(), type->isDependentType(), - type->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(l), Type(IT) {} - - /// \brief Construct an empty predefined expression. - explicit PredefinedExpr(EmptyShell Empty) - : Expr(PredefinedExprClass, Empty) { } - - IdentType getIdentType() const { return Type; } - void setIdentType(IdentType IT) { Type = IT; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == PredefinedExprClass; - } - - // Iterators - child_range children() { return child_range(); } -}; - /// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without /// leaking memory. /// @@ -1603,6 +1554,62 @@ child_range children() { return child_range(); } }; +/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__. +class PredefinedExpr : public Expr { +public: + enum IdentType { + Func, + Function, + LFunction, // Same as Function, but as wide string. + FuncDName, + FuncSig, + PrettyFunction, + /// \brief The same as PrettyFunction, except that the + /// 'virtual' keyword is omitted for virtual member functions. + PrettyFunctionNoVirtual + }; + +private: + SourceLocation Loc; + IdentType Type; + Stmt *StringLit; +public: + PredefinedExpr(SourceLocation L, QualType T, IdentType IT, StringLiteral *SL) + : Expr(PredefinedExprClass, T, VK_LValue, OK_Ordinary, + T->isDependentType(), T->isDependentType(), + T->isInstantiationDependentType(), + /*ContainsUnexpandedParameterPack=*/false), + Loc(L), Type(IT), StringLit(SL) {} + + /// \brief Construct an empty predefined expression. + explicit PredefinedExpr(EmptyShell Empty) + : Expr(PredefinedExprClass, Empty) { } + + IdentType getIdentType() const { return Type; } + void setIdentType(IdentType IT) { Type = IT; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + const StringLiteral *getStringLiteral() const { + return cast(StringLit); + } + StringLiteral *getStringLiteral() { return cast(StringLit); } + void setStringLiteral(StringLiteral *SL) { StringLit = SL; } + + static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); + + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PredefinedExprClass; + } + + // Iterators + child_range children() { return child_range(&StringLit, &StringLit + 1); } +}; + /// ParenExpr - This represents a parethesized expression, e.g. "(1)". This /// AST node is only formed if full location information is requested. class ParenExpr : public Expr { Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -448,214 +448,6 @@ return getNameInfo().getLocEnd(); } -// FIXME: Maybe this should use DeclPrinter with a special "print predefined -// expr" policy instead. -std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { - ASTContext &Context = CurrentDecl->getASTContext(); - - if (IT == PredefinedExpr::FuncDName) { - if (const NamedDecl *ND = dyn_cast(CurrentDecl)) { - std::unique_ptr MC; - MC.reset(Context.createMangleContext()); - - if (MC->shouldMangleDeclName(ND)) { - SmallString<256> Buffer; - llvm::raw_svector_ostream Out(Buffer); - if (const CXXConstructorDecl *CD = dyn_cast(ND)) - MC->mangleCXXCtor(CD, Ctor_Base, Out); - else if (const CXXDestructorDecl *DD = dyn_cast(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(CurrentDecl)) { - if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig) - return FD->getNameAsString(); - - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - - if (const CXXMethodDecl *MD = dyn_cast(FD)) { - if (MD->isVirtual() && IT != PrettyFunctionNoVirtual) - Out << "virtual "; - if (MD->isStatic()) - Out << "static "; - } - - PrintingPolicy Policy(Context.getLangOpts()); - std::string Proto; - llvm::raw_string_ostream POut(Proto); - - const FunctionDecl *Decl = FD; - if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern()) - Decl = Pattern; - const FunctionType *AFT = Decl->getType()->getAs(); - const FunctionProtoType *FT = nullptr; - if (FD->hasWrittenPrototype()) - FT = dyn_cast(AFT); - - if (IT == FuncSig) { - switch (FT->getCallConv()) { - case CC_C: POut << "__cdecl "; break; - case CC_X86StdCall: POut << "__stdcall "; break; - case CC_X86FastCall: POut << "__fastcall "; break; - case CC_X86ThisCall: POut << "__thiscall "; break; - // Only bother printing the conventions that MSVC knows about. - default: break; - } - } - - FD->printQualifiedName(POut, Policy); - - POut << "("; - if (FT) { - for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) { - if (i) POut << ", "; - POut << Decl->getParamDecl(i)->getType().stream(Policy); - } - - if (FT->isVariadic()) { - if (FD->getNumParams()) POut << ", "; - POut << "..."; - } - } - POut << ")"; - - if (const CXXMethodDecl *MD = dyn_cast(FD)) { - const FunctionType *FT = MD->getType()->castAs(); - if (FT->isConst()) - POut << " const"; - if (FT->isVolatile()) - POut << " volatile"; - RefQualifierKind Ref = MD->getRefQualifier(); - if (Ref == RQ_LValue) - POut << " &"; - else if (Ref == RQ_RValue) - POut << " &&"; - } - - typedef SmallVector SpecsTy; - SpecsTy Specs; - const DeclContext *Ctx = FD->getDeclContext(); - while (Ctx && isa(Ctx)) { - const ClassTemplateSpecializationDecl *Spec - = dyn_cast(Ctx); - if (Spec && !Spec->isExplicitSpecialization()) - Specs.push_back(Spec); - Ctx = Ctx->getParent(); - } - - std::string TemplateParams; - llvm::raw_string_ostream TOut(TemplateParams); - for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend(); - I != E; ++I) { - const TemplateParameterList *Params - = (*I)->getSpecializedTemplate()->getTemplateParameters(); - const TemplateArgumentList &Args = (*I)->getTemplateArgs(); - assert(Params->size() == Args.size()); - for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) { - StringRef Param = Params->getParam(i)->getName(); - if (Param.empty()) continue; - TOut << Param << " = "; - Args.get(i).print(Policy, TOut); - TOut << ", "; - } - } - - FunctionTemplateSpecializationInfo *FSI - = FD->getTemplateSpecializationInfo(); - if (FSI && !FSI->isExplicitSpecialization()) { - const TemplateParameterList* Params - = FSI->getTemplate()->getTemplateParameters(); - const TemplateArgumentList* Args = FSI->TemplateArguments; - assert(Params->size() == Args->size()); - for (unsigned i = 0, e = Params->size(); i != e; ++i) { - StringRef Param = Params->getParam(i)->getName(); - if (Param.empty()) continue; - TOut << Param << " = "; - Args->get(i).print(Policy, TOut); - TOut << ", "; - } - } - - TOut.flush(); - if (!TemplateParams.empty()) { - // remove the trailing comma and space - TemplateParams.resize(TemplateParams.size() - 2); - POut << " [" << TemplateParams << "]"; - } - - POut.flush(); - - // Print "auto" for all deduced return types. This includes C++1y return - // type deduction and lambdas. For trailing return types resolve the - // decltype expression. Otherwise print the real type when this is - // not a constructor or destructor. - if ((isa(FD) && - cast(FD)->getParent()->isLambda()) || - (FT && FT->getReturnType()->getAs())) - Proto = "auto " + Proto; - else if (FT && FT->getReturnType()->getAs()) - FT->getReturnType() - ->getAs() - ->getUnderlyingType() - .getAsStringInternal(Proto, Policy); - else if (!isa(FD) && !isa(FD)) - AFT->getReturnType().getAsStringInternal(Proto, Policy); - - Out << Proto; - - Out.flush(); - return Name.str().str(); - } - if (const CapturedDecl *CD = dyn_cast(CurrentDecl)) { - for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent()) - // Skip to its enclosing function or method, but not its enclosing - // CapturedDecl. - if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) { - const Decl *D = Decl::castFromDeclContext(DC); - return ComputeName(IT, D); - } - llvm_unreachable("CapturedDecl not inside a function or method"); - } - if (const ObjCMethodDecl *MD = dyn_cast(CurrentDecl)) { - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - Out << (MD->isInstanceMethod() ? '-' : '+'); - Out << '['; - - // For incorrect code, there might not be an ObjCInterfaceDecl. Do - // a null check to avoid a crash. - if (const ObjCInterfaceDecl *ID = MD->getClassInterface()) - Out << *ID; - - if (const ObjCCategoryImplDecl *CID = - dyn_cast(MD->getDeclContext())) - Out << '(' << *CID << ')'; - - Out << ' '; - MD->getSelector().print(Out); - Out << ']'; - - Out.flush(); - return Name.str().str(); - } - if (isa(CurrentDecl) && IT == PrettyFunction) { - // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string. - return "top level"; - } - return ""; -} - void APNumericStorage::setIntValue(const ASTContext &C, const llvm::APInt &Val) { if (hasAllocation()) @@ -1017,7 +809,212 @@ } } +// FIXME: Maybe this should use DeclPrinter with a special "print predefined +// expr" policy instead. +std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { + ASTContext &Context = CurrentDecl->getASTContext(); + + if (IT == PredefinedExpr::FuncDName) { + if (const NamedDecl *ND = dyn_cast(CurrentDecl)) { + std::unique_ptr MC; + MC.reset(Context.createMangleContext()); + + if (MC->shouldMangleDeclName(ND)) { + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + if (const CXXConstructorDecl *CD = dyn_cast(ND)) + MC->mangleCXXCtor(CD, Ctor_Base, Out); + else if (const CXXDestructorDecl *DD = dyn_cast(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(CurrentDecl)) { + if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig) + return FD->getNameAsString(); + + SmallString<256> Name; + llvm::raw_svector_ostream Out(Name); + + if (const CXXMethodDecl *MD = dyn_cast(FD)) { + if (MD->isVirtual() && IT != PrettyFunctionNoVirtual) + Out << "virtual "; + if (MD->isStatic()) + Out << "static "; + } + + PrintingPolicy Policy(Context.getLangOpts()); + std::string Proto; + llvm::raw_string_ostream POut(Proto); + + const FunctionDecl *Decl = FD; + if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern()) + Decl = Pattern; + const FunctionType *AFT = Decl->getType()->getAs(); + const FunctionProtoType *FT = nullptr; + if (FD->hasWrittenPrototype()) + FT = dyn_cast(AFT); + + if (IT == FuncSig) { + switch (FT->getCallConv()) { + case CC_C: POut << "__cdecl "; break; + case CC_X86StdCall: POut << "__stdcall "; break; + case CC_X86FastCall: POut << "__fastcall "; break; + case CC_X86ThisCall: POut << "__thiscall "; break; + // Only bother printing the conventions that MSVC knows about. + default: break; + } + } + + FD->printQualifiedName(POut, Policy); + + POut << "("; + if (FT) { + for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) { + if (i) POut << ", "; + POut << Decl->getParamDecl(i)->getType().stream(Policy); + } + + if (FT->isVariadic()) { + if (FD->getNumParams()) POut << ", "; + POut << "..."; + } + } + POut << ")"; + + if (const CXXMethodDecl *MD = dyn_cast(FD)) { + const FunctionType *FT = MD->getType()->castAs(); + if (FT->isConst()) + POut << " const"; + if (FT->isVolatile()) + POut << " volatile"; + RefQualifierKind Ref = MD->getRefQualifier(); + if (Ref == RQ_LValue) + POut << " &"; + else if (Ref == RQ_RValue) + POut << " &&"; + } + + typedef SmallVector SpecsTy; + SpecsTy Specs; + const DeclContext *Ctx = FD->getDeclContext(); + while (Ctx && isa(Ctx)) { + const ClassTemplateSpecializationDecl *Spec + = dyn_cast(Ctx); + if (Spec && !Spec->isExplicitSpecialization()) + Specs.push_back(Spec); + Ctx = Ctx->getParent(); + } + + std::string TemplateParams; + llvm::raw_string_ostream TOut(TemplateParams); + for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend(); + I != E; ++I) { + const TemplateParameterList *Params + = (*I)->getSpecializedTemplate()->getTemplateParameters(); + const TemplateArgumentList &Args = (*I)->getTemplateArgs(); + assert(Params->size() == Args.size()); + for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) { + StringRef Param = Params->getParam(i)->getName(); + if (Param.empty()) continue; + TOut << Param << " = "; + Args.get(i).print(Policy, TOut); + TOut << ", "; + } + } + + FunctionTemplateSpecializationInfo *FSI + = FD->getTemplateSpecializationInfo(); + if (FSI && !FSI->isExplicitSpecialization()) { + const TemplateParameterList* Params + = FSI->getTemplate()->getTemplateParameters(); + const TemplateArgumentList* Args = FSI->TemplateArguments; + assert(Params->size() == Args->size()); + for (unsigned i = 0, e = Params->size(); i != e; ++i) { + StringRef Param = Params->getParam(i)->getName(); + if (Param.empty()) continue; + TOut << Param << " = "; + Args->get(i).print(Policy, TOut); + TOut << ", "; + } + } + + TOut.flush(); + if (!TemplateParams.empty()) { + // remove the trailing comma and space + TemplateParams.resize(TemplateParams.size() - 2); + POut << " [" << TemplateParams << "]"; + } + + POut.flush(); + + // Print "auto" for all deduced return types. This includes C++1y return + // type deduction and lambdas. For trailing return types resolve the + // decltype expression. Otherwise print the real type when this is + // not a constructor or destructor. + if (isa(FD) && + cast(FD)->getParent()->isLambda()) + Proto = "auto " + Proto; + else if (FT && FT->getReturnType()->getAs()) + FT->getReturnType() + ->getAs() + ->getUnderlyingType() + .getAsStringInternal(Proto, Policy); + else if (!isa(FD) && !isa(FD)) + AFT->getReturnType().getAsStringInternal(Proto, Policy); + + Out << Proto; + Out.flush(); + return Name.str().str(); + } + if (const CapturedDecl *CD = dyn_cast(CurrentDecl)) { + for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent()) + // Skip to its enclosing function or method, but not its enclosing + // CapturedDecl. + if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) { + const Decl *D = Decl::castFromDeclContext(DC); + return ComputeName(IT, D); + } + llvm_unreachable("CapturedDecl not inside a function or method"); + } + if (const ObjCMethodDecl *MD = dyn_cast(CurrentDecl)) { + SmallString<256> Name; + llvm::raw_svector_ostream Out(Name); + Out << (MD->isInstanceMethod() ? '-' : '+'); + Out << '['; + + // For incorrect code, there might not be an ObjCInterfaceDecl. Do + // a null check to avoid a crash. + if (const ObjCInterfaceDecl *ID = MD->getClassInterface()) + Out << *ID; + + if (const ObjCCategoryImplDecl *CID = + dyn_cast(MD->getDeclContext())) + Out << '(' << *CID << ')'; + + Out << ' '; + MD->getSelector().print(Out); + Out << ']'; + + Out.flush(); + return Name.str().str(); + } + if (isa(CurrentDecl) && IT == PrettyFunction) { + // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string. + return "top level"; + } + return ""; +} /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++". Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -2021,7 +2021,9 @@ /// Extract the value of a character from a string literal. static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, uint64_t Index) { - // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant + // FIXME: Support ObjCEncodeExpr, MakeStringConstant + if (auto *PE = dyn_cast(Lit)) + Lit = PE->getStringLiteral(); const StringLiteral *S = cast(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); @@ -2649,10 +2651,10 @@ return false; CompleteObject LitObj(&Lit, Base->getType()); return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal); - } else if (isa(Base)) { + } else if (isa(Base) || isa(Base)) { // We represent a string literal array as an lvalue pointing at the // corresponding expression, rather than building an array of chars. - // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant + // FIXME: Support ObjCEncodeExpr, MakeStringConstant APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0); CompleteObject StrObj(&Str, Base->getType()); return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal); Index: lib/AST/StmtProfile.cpp =================================================================== --- lib/AST/StmtProfile.cpp +++ lib/AST/StmtProfile.cpp @@ -469,6 +469,7 @@ void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) { VisitExpr(S); ID.AddInteger(S->getIdentType()); + VisitStringLiteral(S->getStringLiteral()); } void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) { Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -2051,86 +2051,10 @@ E->getType()); } -static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source, - SmallString<32>& Target) { - Target.resize(CharByteWidth * (Source.size() + 1)); - char *ResultPtr = &Target[0]; - const UTF8 *ErrorPtr; - bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr); - (void)success; - assert(success); - Target.resize(ResultPtr - &Target[0]); -} - LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { - switch (E->getIdentType()) { - default: - return EmitUnsupportedLValue(E, "predefined expression"); - - case PredefinedExpr::Func: - case PredefinedExpr::Function: - case PredefinedExpr::LFunction: - case PredefinedExpr::FuncDName: - case PredefinedExpr::FuncSig: - case PredefinedExpr::PrettyFunction: { - PredefinedExpr::IdentType IdentType = E->getIdentType(); - std::string GVName; - - // FIXME: We should use the string literal mangling for the Microsoft C++ - // ABI so that strings get merged. - switch (IdentType) { - default: llvm_unreachable("Invalid type"); - case PredefinedExpr::Func: GVName = "__func__."; break; - case PredefinedExpr::Function: GVName = "__FUNCTION__."; break; - case PredefinedExpr::FuncDName: GVName = "__FUNCDNAME__."; break; - case PredefinedExpr::FuncSig: GVName = "__FUNCSIG__."; break; - case PredefinedExpr::LFunction: GVName = "L__FUNCTION__."; break; - case PredefinedExpr::PrettyFunction: GVName = "__PRETTY_FUNCTION__."; break; - } - - StringRef FnName = CurFn->getName(); - if (FnName.startswith("\01")) - FnName = FnName.substr(1); - GVName += FnName; - - // If this is outside of a function use the top level decl. - const Decl *CurDecl = CurCodeDecl; - if (!CurDecl || isa(CurDecl)) - CurDecl = getContext().getTranslationUnitDecl(); - - const Type *ElemType = E->getType()->getArrayElementTypeNoTypeQual(); - std::string FunctionName; - if (isa(CurDecl)) { - // Blocks use the mangled function name. - // FIXME: ComputeName should handle blocks. - FunctionName = FnName.str(); - } else if (isa(CurDecl)) { - // For a captured statement, the function name is its enclosing - // function name not the one compiler generated. - FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl); - } else { - FunctionName = PredefinedExpr::ComputeName(IdentType, CurDecl); - assert(cast(E->getType())->getSize() - 1 == - FunctionName.size() && - "Computed __func__ length differs from type!"); - } - - llvm::Constant *C; - if (ElemType->isWideCharType()) { - SmallString<32> RawChars; - ConvertUTF8ToWideString( - getContext().getTypeSizeInChars(ElemType).getQuantity(), FunctionName, - RawChars); - StringLiteral *SL = StringLiteral::Create( - getContext(), RawChars, StringLiteral::Wide, - /*Pascal = */ false, E->getType(), E->getLocation()); - C = CGM.GetAddrOfConstantStringFromLiteral(SL); - } else { - C = CGM.GetAddrOfConstantCString(FunctionName, GVName.c_str(), 1); - } - return MakeAddrLValue(C, E->getType()); - } - } + assert(E->getStringLiteral() != nullptr && + "No string literal is associated with PredefinedExpr"); + return EmitStringLiteralLValue(E->getStringLiteral()); } /// Emit a type description suitable for use by a runtime sanitizer library. The Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -42,6 +42,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/Template.h" +#include "llvm/Support/ConvertUTF.h" using namespace clang; using namespace sema; @@ -2901,6 +2902,17 @@ } } +static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source, + SmallString<32> &Target) { + Target.resize(CharByteWidth * (Source.size() + 1)); + char *ResultPtr = &Target[0]; + const UTF8 *ErrorPtr; + bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr); + (void)success; + assert(success); + Target.resize(ResultPtr - &Target[0]); +} + ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, PredefinedExpr::IdentType IT) { // Pick the current block, lambda, captured statement or function. @@ -2920,22 +2932,36 @@ } QualType ResTy; + StringLiteral *SL = nullptr; if (cast(currentDecl)->isDependentContext()) ResTy = Context.DependentTy; else { // Pre-defined identifiers are of type char[x], where x is the length of // the string. - unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); + auto Str = PredefinedExpr::ComputeName(IT, currentDecl); + unsigned Length = Str.length(); llvm::APInt LengthI(32, Length + 1); - if (IT == PredefinedExpr::LFunction) + if (IT == PredefinedExpr::LFunction) { ResTy = Context.WideCharTy.withConst(); - else + SmallString<32> RawChars; + ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(), + Str, RawChars); + ResTy = + Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); + SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide, + /*Pascal = */ false, ResTy, Loc); + + } else { ResTy = Context.CharTy.withConst(); - ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); + ResTy = + Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); + SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii, + /*Pascal = */ false, ResTy, Loc); + } } - return new (Context) PredefinedExpr(Loc, ResTy, IT); + return new (Context) PredefinedExpr(Loc, ResTy, IT, SL); } ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -6964,7 +6964,7 @@ template ExprResult TreeTransform::TransformPredefinedExpr(PredefinedExpr *E) { - return E; + return getDerived().TransformPredefinedExpr(E); } template Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -423,6 +423,7 @@ VisitExpr(E); E->setLocation(ReadSourceLocation(Record, Idx)); E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]); + E->setStringLiteral(cast(Reader.ReadSubExpr())); } void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -333,6 +333,7 @@ VisitExpr(E); Writer.AddSourceLocation(E->getLocation(), Record); Record.push_back(E->getIdentType()); // FIXME: stable encoding + Writer.AddStmt(E->getStringLiteral()); Code = serialization::EXPR_PREDEFINED; } Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -864,7 +864,6 @@ case Stmt::ObjCProtocolExprClass: case Stmt::ObjCSelectorExprClass: case Stmt::ParenListExprClass: - case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::ConvertVectorExprClass: case Stmt::VAArgExprClass: @@ -876,6 +875,7 @@ // Cases we intentionally don't evaluate, since they don't need // to be explicitly evaluated. + case Stmt::PredefinedExprClass: case Stmt::AddrLabelExprClass: case Stmt::AttributedStmtClass: case Stmt::IntegerLiteralClass: Index: test/CodeGen/const-init.c =================================================================== --- test/CodeGen/const-init.c +++ test/CodeGen/const-init.c @@ -121,8 +121,8 @@ struct g23 {char a; short b; char c; struct g22 d;}; struct g23 g24 = {1,2,3,4}; -// CHECK: @g25.g26 = internal global i8* getelementptr inbounds ([4 x i8]* @__func__.g25, i32 0, i32 0) -// CHECK: @__func__.g25 = private unnamed_addr constant [4 x i8] c"g25\00" +// CHECK: @g25.g26 = internal global i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0) +// CHECK: @.str = private unnamed_addr constant [4 x i8] c"g25\00" int g25() { static const char *g26 = __func__; return *g26; @@ -153,7 +153,7 @@ DCC_PASSWD passwd; } DCC_SRVR_NM; // CHECK: @g29.a = internal global %struct.DCC_SRVR_NM { [2 x i8] c"@\00" }, align 1 - // CHECK: @g29.b = internal global [1 x i32] [i32 ptrtoint ([5 x i8]* @.str to i32)], align 4 + // CHECK: @g29.b = internal global [1 x i32] [i32 ptrtoint ([5 x i8]* @.str1 to i32)], align 4 // CHECK: @g29.c = internal global [1 x i32] [i32 97], align 4 static DCC_SRVR_NM a = { {"@"} }; static int b[1] = { "asdf" }; // expected-warning {{incompatible pointer to integer conversion initializing 'int' with an expression of type 'char [5]'}} Index: test/CodeGen/func-in-block.c =================================================================== --- test/CodeGen/func-in-block.c +++ test/CodeGen/func-in-block.c @@ -15,5 +15,5 @@ return 0; // not reached } -// CHECK: @__func__.__main_block_invoke = private unnamed_addr constant [20 x i8] c"__main_block_invoke\00" -// CHECK: call void @PRINTF({{.*}}@__func__.__main_block_invoke +// CHECK: @[[FUNC:.+]] = private unnamed_addr constant [5 x i8] c"main\00" +// CHECK: call void @PRINTF({{.*}}@[[FUNC]] Index: test/CodeGen/predefined-expr.c =================================================================== --- test/CodeGen/predefined-expr.c +++ test/CodeGen/predefined-expr.c @@ -1,16 +1,16 @@ // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -fms-extensions %s -emit-llvm -o - | FileCheck %s -// CHECK: @__func__.plainFunction = private unnamed_addr constant [14 x i8] c"plainFunction\00" -// CHECK: @__PRETTY_FUNCTION__.plainFunction = private unnamed_addr constant [21 x i8] c"void plainFunction()\00" -// CHECK: @__func__.externFunction = private unnamed_addr constant [15 x i8] c"externFunction\00" -// CHECK: @__PRETTY_FUNCTION__.externFunction = private unnamed_addr constant [22 x i8] c"void externFunction()\00" -// CHECK: @__func__.privateExternFunction = private unnamed_addr constant [22 x i8] c"privateExternFunction\00" -// CHECK: @__PRETTY_FUNCTION__.privateExternFunction = private unnamed_addr constant [29 x i8] c"void privateExternFunction()\00" -// CHECK: @__func__.__captured_stmt = private unnamed_addr constant [25 x i8] c"functionWithCapturedStmt\00" -// CHECK: @__PRETTY_FUNCTION__.__captured_stmt = private unnamed_addr constant [32 x i8] c"void functionWithCapturedStmt()\00" -// CHECK: @__func__.staticFunction = private unnamed_addr constant [15 x i8] c"staticFunction\00" -// CHECK: @__PRETTY_FUNCTION__.staticFunction = private unnamed_addr constant [22 x i8] c"void staticFunction()\00" +// CHECK: private unnamed_addr constant [14 x i8] c"plainFunction\00" +// CHECK: private unnamed_addr constant [21 x i8] c"void plainFunction()\00" +// CHECK: private unnamed_addr constant [15 x i8] c"externFunction\00" +// CHECK: private unnamed_addr constant [22 x i8] c"void externFunction()\00" +// CHECK: private unnamed_addr constant [22 x i8] c"privateExternFunction\00" +// CHECK: private unnamed_addr constant [29 x i8] c"void privateExternFunction()\00" +// CHECK: private unnamed_addr constant [25 x i8] c"functionWithCapturedStmt\00" +// CHECK: private unnamed_addr constant [32 x i8] c"void functionWithCapturedStmt()\00" +// CHECK: private unnamed_addr constant [15 x i8] c"staticFunction\00" +// CHECK: private unnamed_addr constant [22 x i8] c"void staticFunction()\00" int printf(const char *, ...); Index: test/CodeGenCXX/funcsig.cpp =================================================================== --- test/CodeGenCXX/funcsig.cpp +++ test/CodeGenCXX/funcsig.cpp @@ -8,7 +8,7 @@ void freeFunc(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00" +// CHECK: linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __cdecl freeFunc(int *, char)\00" struct TopLevelClass { void topLevelMethod(int *, char); @@ -16,7 +16,7 @@ void TopLevelClass::topLevelMethod(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00" +// CHECK: linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall TopLevelClass::topLevelMethod(int *, char)\00" namespace NS { struct NamespacedClass { @@ -25,5 +25,5 @@ void NamespacedClass::namespacedMethod(int *, char) { printf("__FUNCSIG__ %s\n\n", __FUNCSIG__); } -// CHECK: private unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00" +// CHECK: linkonce_odr unnamed_addr constant [{{.*}} x i8] c"void __thiscall NS::NamespacedClass::namespacedMethod(int *, char)\00" } Index: test/CodeGenCXX/predefined-expr-cxx14.cpp =================================================================== --- test/CodeGenCXX/predefined-expr-cxx14.cpp +++ test/CodeGenCXX/predefined-expr-cxx14.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -std=c++14 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +// CHECK-DAG: private unnamed_addr constant [22 x i8] c"classTemplateFunction\00" +// CHECK-DAG: private unnamed_addr constant [69 x i8] c"const auto &ClassTemplate::classTemplateFunction(T &) [T = int]\00" + +// CHECK-DAG: private unnamed_addr constant [17 x i8] c"functionTemplate\00" +// CHECK-DAG: private unnamed_addr constant [64 x i8] c"auto &ClassInTopLevelNamespace::functionTemplate(T &) [T = int]\00" + +// CHECK-DAG: private unnamed_addr constant [17 x i8] c"variadicFunction\00" +// CHECK-DAG: private unnamed_addr constant [70 x i8] c"decltype(auto) ClassInTopLevelNamespace::variadicFunction(int *, ...)\00" + +// CHECK-DAG: private unnamed_addr constant [26 x i8] c"topLevelNamespaceFunction\00" +// CHECK-DAG: private unnamed_addr constant [60 x i8] c"auto *ClassInTopLevelNamespace::topLevelNamespaceFunction()\00" + +int printf(const char * _Format, ...); + +class ClassInTopLevelNamespace { +public: + auto *topLevelNamespaceFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return static_cast(nullptr); + } + + decltype(auto) variadicFunction(int *a, ...) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return a; + } + + template + auto &functionTemplate(T &t) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return t; + } +}; + +template +class ClassTemplate { +public: + const auto &classTemplateFunction(T &t) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return t; + } +}; + +int main() { + int a; + ClassInTopLevelNamespace topLevelNamespace; + topLevelNamespace.topLevelNamespaceFunction(); + topLevelNamespace.variadicFunction(&a); + topLevelNamespace.functionTemplate(a); + + ClassTemplate t; + t.classTemplateFunction(a); + return 0; +} Index: test/CodeGenObjC/predefined-expr.m =================================================================== --- test/CodeGenObjC/predefined-expr.m +++ test/CodeGenObjC/predefined-expr.m @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 %s -emit-llvm -o - | FileCheck %s -// CHECK: @"__func__.-[Foo instanceTest1]" = private unnamed_addr constant [21 x i8] c"-[Foo instanceTest1]\00" -// CHECK: @"__func__.-[Foo instanceTest2:]" = private unnamed_addr constant [22 x i8] c"-[Foo instanceTest2:]\00" -// CHECK: @"__func__.-[Foo instanceTest3:withB:]" = private unnamed_addr constant [28 x i8] c"-[Foo instanceTest3:withB:]\00" -// CHECK: @"__func__.-[Foo instanceTest4]" = private unnamed_addr constant [21 x i8] c"-[Foo instanceTest4]\00" -// CHECK: @"__func__.+[Foo classTest1]" = private unnamed_addr constant [18 x i8] c"+[Foo classTest1]\00" -// CHECK: @"__func__.+[Foo classTest2:]" = private unnamed_addr constant [19 x i8] c"+[Foo classTest2:]\00" -// CHECK: @"__func__.+[Foo classTest3:withB:]" = private unnamed_addr constant [25 x i8] c"+[Foo classTest3:withB:]\00" -// CHECK: @"__func__.+[Foo classTest4]" = private unnamed_addr constant [18 x i8] c"+[Foo classTest4]\00" -// CHECK: @"__func__.-[Foo(Category) instanceTestWithCategory]" = private unnamed_addr constant [42 x i8] c"-[Foo(Category) instanceTestWithCategory]\00" -// CHECK: @"__func__.+[Foo(Category) classTestWithCategory]" = private unnamed_addr constant [39 x i8] c"+[Foo(Category) classTestWithCategory]\00" +// CHECK: private unnamed_addr constant [21 x i8] c"-[Foo instanceTest1]\00" +// CHECK: private unnamed_addr constant [22 x i8] c"-[Foo instanceTest2:]\00" +// CHECK: private unnamed_addr constant [28 x i8] c"-[Foo instanceTest3:withB:]\00" +// CHECK: private unnamed_addr constant [21 x i8] c"-[Foo instanceTest4]\00" +// CHECK: private unnamed_addr constant [18 x i8] c"+[Foo classTest1]\00" +// CHECK: private unnamed_addr constant [19 x i8] c"+[Foo classTest2:]\00" +// CHECK: private unnamed_addr constant [25 x i8] c"+[Foo classTest3:withB:]\00" +// CHECK: private unnamed_addr constant [18 x i8] c"+[Foo classTest4]\00" +// CHECK: private unnamed_addr constant [42 x i8] c"-[Foo(Category) instanceTestWithCategory]\00" +// CHECK: private unnamed_addr constant [39 x i8] c"+[Foo(Category) classTestWithCategory]\00" int printf(const char * _Format, ...);