diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTDumper.cpp | 10 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 53 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 23 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 91 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 15 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 1 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 |
12 files changed, 122 insertions, 127 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index d134e646eb9..25ed2cda26a 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -1714,15 +1714,7 @@ void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { VisitExpr(Node); - switch (Node->getIdentType()) { - 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; - case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break; - } + OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType()); } void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 0970d59c9c5..8410bad88d9 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -448,6 +448,38 @@ SourceLocation DeclRefExpr::getLocEnd() const { return getNameInfo().getLocEnd(); } +PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, + StringLiteral *SL) + : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary, + FNTy->isDependentType(), FNTy->isDependentType(), + FNTy->isInstantiationDependentType(), + /*ContainsUnexpandedParameterPack=*/false), + Loc(L), Type(IT), FnName(SL) {} + +StringLiteral *PredefinedExpr::getFunctionName() { + return cast<StringLiteral>(FnName); +} + +StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) { + switch (IT) { + case Func: + return "__func__"; + case Function: + return "__FUNCTION__"; + case FuncDName: + return "__FUNCDNAME__"; + case LFunction: + return "L__FUNCTION__"; + case PrettyFunction: + return "__PRETTY_FUNCTION__"; + case FuncSig: + return "__FUNCSIG__"; + case PrettyFunctionNoVirtual: + break; + } + llvm_unreachable("Unknown ident type for PredefinedExpr"); +} + // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { @@ -477,6 +509,22 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } return ""; } + if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) { + std::unique_ptr<MangleContext> MC; + MC.reset(Context.createMangleContext()); + SmallString<256> Buffer; + llvm::raw_svector_ostream Out(Buffer); + auto DC = CurrentDecl->getDeclContext(); + if (DC->isFileContext()) + MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out); + else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) + MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); + else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) + MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); + else + MC->mangleBlock(DC, BD, Out); + return Out.str(); + } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) { if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig) return FD->getNameAsString(); @@ -600,9 +648,8 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { // 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<CXXMethodDecl>(FD) && - cast<CXXMethodDecl>(FD)->getParent()->isLambda()) || - (FT && FT->getReturnType()->getAs<AutoType>())) + if (isa<CXXMethodDecl>(FD) && + cast<CXXMethodDecl>(FD)->getParent()->isLambda()) Proto = "auto " + Proto; else if (FT && FT->getReturnType()->getAs<DecltypeType>()) FT->getReturnType() diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 74bc31db34f..f7eef828063 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2021,7 +2021,9 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived, /// 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<PredefinedExpr>(Lit)) + Lit = PE->getFunctionName(); const StringLiteral *S = cast<StringLiteral>(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); @@ -2715,10 +2717,10 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, return false; CompleteObject LitObj(&Lit, Base->getType()); return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal); - } else if (isa<StringLiteral>(Base)) { + } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(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); diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 301d6a7bb68..c84875c09fb 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1004,28 +1004,7 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { } void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { - switch (Node->getIdentType()) { - 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::FuncSig: - OS << "__FUNCSIG__"; - break; - case PredefinedExpr::LFunction: - OS << "L__FUNCTION__"; - break; - case PredefinedExpr::PrettyFunction: - OS << "__PRETTY_FUNCTION__"; - break; - } + OS << PredefinedExpr::getIdentTypeName(Node->getIdentType()); } void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 518d81bd361..19f6e949990 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -24,6 +24,7 @@ #include "clang/AST/Attr.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" @@ -2069,86 +2070,18 @@ LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) { 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<VarDecl>(CurDecl)) - CurDecl = getContext().getTranslationUnitDecl(); - - const Type *ElemType = E->getType()->getArrayElementTypeNoTypeQual(); - std::string FunctionName; - if (isa<BlockDecl>(CurDecl)) { - // Blocks use the mangled function name. - // FIXME: ComputeName should handle blocks. - FunctionName = FnName.str(); - } else if (isa<CapturedDecl>(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<ConstantArrayType>(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()); - } - } + auto SL = E->getFunctionName(); + assert(SL != nullptr && "No StringLiteral name in PredefinedExpr"); + StringRef FnName = CurFn->getName(); + if (FnName.startswith("\01")) + FnName = FnName.substr(1); + StringRef NameItems[] = { + PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName}; + std::string GVName = llvm::join(NameItems, NameItems + 2, "."); + + auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName); + return MakeAddrLValue(C, E->getType()); } /// Emit a type description suitable for use by a runtime sanitizer library. The diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index a7a65b88c91..5d314f525cd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2729,7 +2729,8 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, /// GetAddrOfConstantStringFromLiteral - Return a pointer to a /// constant array for the given string literal. llvm::GlobalVariable * -CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) { +CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, + StringRef Name) { auto Alignment = getContext().getAlignOfGlobalVarInChars(S->getType()).getQuantity(); @@ -2761,7 +2762,7 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) { GlobalVariableName = MangledNameBuffer; } else { LT = llvm::GlobalValue::PrivateLinkage; - GlobalVariableName = ".str"; + GlobalVariableName = Name; } auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 955f665f86c..665a7a589f8 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -785,7 +785,8 @@ public: /// Return a pointer to a constant array for the given string literal. llvm::GlobalVariable * - GetAddrOfConstantStringFromLiteral(const StringLiteral *S); + GetAddrOfConstantStringFromLiteral(const StringLiteral *S, + StringRef Name = ".str"); /// Return a pointer to a constant array for the given ObjCEncodeExpr node. llvm::GlobalVariable * diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0c7cb2e6df1..40909534629 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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; @@ -2905,6 +2906,17 @@ ExprResult Sema::BuildDeclarationNameExpr( } } +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. @@ -2924,22 +2936,35 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, } QualType ResTy; + StringLiteral *SL = nullptr; if (cast<DeclContext>(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, + /*IndexTypeQuals*/ 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, + /*IndexTypeQuals*/ 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) { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 08a134a30be..df4ab10e748 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1677,6 +1677,15 @@ public: return getSema().ActOnSEHFinallyBlock(Loc, Block); } + /// \brief Build a new predefined expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildPredefinedExpr(SourceLocation Loc, + PredefinedExpr::IdentType IT) { + return getSema().BuildPredefinedExpr(Loc, IT); + } + /// \brief Build a new expression that references a declaration. /// /// By default, performs semantic analysis to build the new expression. @@ -7016,7 +7025,11 @@ OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) { template<typename Derived> ExprResult TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) { - return E; + if (!E->isTypeDependent()) + return E; + + return getDerived().RebuildPredefinedExpr(E->getLocation(), + E->getIdentType()); } template<typename Derived> diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 811427e359f..61e509b254f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -422,7 +422,8 @@ void ASTStmtReader::VisitExpr(Expr *E) { void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { VisitExpr(E); E->setLocation(ReadSourceLocation(Record, Idx)); - E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]); + E->Type = (PredefinedExpr::IdentType)Record[Idx++]; + E->FnName = cast<StringLiteral>(Reader.ReadSubExpr()); } void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index d91e2be361b..ff42c8301d9 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -333,6 +333,7 @@ void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { VisitExpr(E); Writer.AddSourceLocation(E->getLocation(), Record); Record.push_back(E->getIdentType()); // FIXME: stable encoding + Writer.AddStmt(E->getFunctionName()); Code = serialization::EXPR_PREDEFINED; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 807d5216e88..c844147e35c 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -868,7 +868,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::ObjCProtocolExprClass: case Stmt::ObjCSelectorExprClass: case Stmt::ParenListExprClass: - case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::ConvertVectorExprClass: case Stmt::VAArgExprClass: @@ -880,6 +879,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, // 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: |