From 17ff026b730dd4c31dd72a3f7c4f971295b4cfa5 Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Sat, 27 Oct 2018 19:21:19 +0000 Subject: [PATCH] [AST] Refactor PredefinedExpr Make the following changes to PredefinedExpr: 1. Move PredefinedExpr below StringLiteral so that it can use its definition. 2. Rename IdentType to IdentKind to be more in line with clang's conventions, and propagate the change to its users. 3. Move the location and the IdentKind into the newly available space of the bit-fields of Stmt. 4. Only store the function name when needed. When parsing all of Boost, of the 1357 PredefinedExpr 919 have no function name. Differential Revision: https://reviews.llvm.org/D53605 Reviewed By: rjmccall llvm-svn: 345460 --- .../bugprone/LambdaFunctionNameCheck.cpp | 6 +- clang/include/clang/AST/Expr.h | 144 ++++++++++++--------- clang/include/clang/AST/Stmt.h | 19 +++ clang/include/clang/AST/StmtDataCollectors.td | 2 +- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/AST/ASTDumper.cpp | 2 +- clang/lib/AST/ASTImporter.cpp | 4 +- clang/lib/AST/Expr.cpp | 63 ++++++--- clang/lib/AST/StmtPrinter.cpp | 2 +- clang/lib/AST/StmtProfile.cpp | 2 +- clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/CodeGen/CGExprConstant.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 26 ++-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 +- clang/lib/Sema/TreeTransform.h | 6 +- clang/lib/Serialization/ASTReaderStmt.cpp | 15 ++- clang/lib/Serialization/ASTWriterStmt.cpp | 8 +- 17 files changed, 194 insertions(+), 113 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp index 55dbe8b..bdb769d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp @@ -73,8 +73,8 @@ void LambdaFunctionNameCheck::registerPPCallbacks(CompilerInstance &Compiler) { void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) { const auto *E = Result.Nodes.getNodeAs("E"); - if (E->getIdentType() != PredefinedExpr::Func && - E->getIdentType() != PredefinedExpr::Function) { + if (E->getIdentKind() != PredefinedExpr::Func && + E->getIdentKind() != PredefinedExpr::Function) { // We don't care about other PredefinedExprs. return; } @@ -91,7 +91,7 @@ void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) { "inside a lambda, '%0' expands to the name of the function call " "operator; consider capturing the name of the enclosing function " "explicitly") - << PredefinedExpr::getIdentTypeName(E->getIdentType()); + << PredefinedExpr::getIdentKindName(E->getIdentKind()); } } // namespace bugprone diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 8817aa4..a835c01 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -32,6 +32,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" namespace clang { class APValue; @@ -1204,64 +1205,6 @@ public: friend class ASTStmtWriter; }; -/// [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, - LFuncSig, // Same as FuncSig, but as as wide string - PrettyFunction, - /// The same as PrettyFunction, except that the - /// 'virtual' keyword is omitted for virtual member functions. - PrettyFunctionNoVirtual - }; - -private: - SourceLocation Loc; - IdentType Type; - Stmt *FnName; - -public: - PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, - StringLiteral *SL); - - /// Construct an empty predefined expression. - explicit PredefinedExpr(EmptyShell Empty) - : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {} - - IdentType getIdentType() const { return Type; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - StringLiteral *getFunctionName(); - const StringLiteral *getFunctionName() const { - return const_cast(this)->getFunctionName(); - } - - static StringRef getIdentTypeName(IdentType IT); - static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - - SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } - SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == PredefinedExprClass; - } - - // Iterators - child_range children() { return child_range(&FnName, &FnName + 1); } - const_child_range children() const { - return const_child_range(&FnName, &FnName + 1); - } - - friend class ASTStmtReader; -}; - /// Used by IntegerLiteral/FloatingLiteral to store the numeric without /// leaking memory. /// @@ -1732,6 +1675,91 @@ public: } }; +/// [C99 6.4.2.2] - A predefined identifier such as __func__. +class PredefinedExpr final + : public Expr, + private llvm::TrailingObjects { + friend class ASTStmtReader; + friend TrailingObjects; + + // PredefinedExpr is optionally followed by a single trailing + // "Stmt *" for the predefined identifier. It is present if and only if + // hasFunctionName() is true and is always a "StringLiteral *". + +public: + enum IdentKind { + Func, + Function, + LFunction, // Same as Function, but as wide string. + FuncDName, + FuncSig, + LFuncSig, // Same as FuncSig, but as as wide string + PrettyFunction, + /// The same as PrettyFunction, except that the + /// 'virtual' keyword is omitted for virtual member functions. + PrettyFunctionNoVirtual + }; + +private: + PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, + StringLiteral *SL); + + explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName); + + /// True if this PredefinedExpr has storage for a function name. + bool hasFunctionName() const { return PredefinedExprBits.HasFunctionName; } + + void setFunctionName(StringLiteral *SL) { + assert(hasFunctionName() && + "This PredefinedExpr has no storage for a function name!"); + *getTrailingObjects() = SL; + } + +public: + /// Create a PredefinedExpr. + static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, StringLiteral *SL); + + /// Create an empty PredefinedExpr. + static PredefinedExpr *CreateEmpty(const ASTContext &Ctx, + bool HasFunctionName); + + IdentKind getIdentKind() const { + return static_cast(PredefinedExprBits.Kind); + } + + SourceLocation getLocation() const { return PredefinedExprBits.Loc; } + void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; } + + StringLiteral *getFunctionName() { + return hasFunctionName() + ? static_cast(*getTrailingObjects()) + : nullptr; + } + + const StringLiteral *getFunctionName() const { + return hasFunctionName() + ? static_cast(*getTrailingObjects()) + : nullptr; + } + + static StringRef getIdentKindName(IdentKind IK); + static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl); + + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PredefinedExprClass; + } + + // Iterators + child_range children() { + return child_range(getTrailingObjects(), + getTrailingObjects() + hasFunctionName()); + } +}; + /// 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 { diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 36dd89c..bb09926 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -268,6 +268,24 @@ protected: }; enum { NumExprBits = 17 }; + class PredefinedExprBitfields { + friend class ASTStmtReader; + friend class PredefinedExpr; + + unsigned : NumExprBits; + + /// The kind of this PredefinedExpr. One of the enumeration values + /// in PredefinedExpr::IdentKind. + unsigned Kind : 4; + + /// True if this PredefinedExpr has a trailing "StringLiteral *" + /// for the predefined identifier. + unsigned HasFunctionName : 1; + + /// The location of this PredefinedExpr. + SourceLocation Loc; + }; + class CharacterLiteralBitfields { friend class CharacterLiteral; @@ -432,6 +450,7 @@ protected: // Expressions ExprBitfields ExprBits; + PredefinedExprBitfields PredefinedExprBits; CharacterLiteralBitfields CharacterLiteralBits; FloatingLiteralBitfields FloatingLiteralBits; UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits; diff --git a/clang/include/clang/AST/StmtDataCollectors.td b/clang/include/clang/AST/StmtDataCollectors.td index e1929fe3..90ca080 100644 --- a/clang/include/clang/AST/StmtDataCollectors.td +++ b/clang/include/clang/AST/StmtDataCollectors.td @@ -27,7 +27,7 @@ class ExpressionTraitExpr { } class PredefinedExpr { code Code = [{ - addData(S->getIdentType()); + addData(S->getIdentKind()); }]; } class TypeTraitExpr { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 430a851..63ea45f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4214,7 +4214,7 @@ public: TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); ExprResult BuildPredefinedExpr(SourceLocation Loc, - PredefinedExpr::IdentType IT); + PredefinedExpr::IdentKind IK); ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val); diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 03833ef..b2ba2dd 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -2198,7 +2198,7 @@ void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { VisitExpr(Node); - OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType()); + OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind()); } void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index ec345bb..6262ad3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6148,8 +6148,8 @@ ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { StringLiteral *ToFunctionName; std::tie(ToBeginLoc, ToType, ToFunctionName) = *Imp; - return new (Importer.getToContext()) PredefinedExpr( - ToBeginLoc, ToType, E->getIdentType(), ToFunctionName); + return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType, + E->getIdentKind(), ToFunctionName); } ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 9df8aaa..a3aacc7 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -458,20 +458,45 @@ SourceLocation DeclRefExpr::getEndLoc() const { return getNameInfo().getEndLoc(); } -PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, +PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, StringLiteral *SL) : Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary, FNTy->isDependentType(), FNTy->isDependentType(), FNTy->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(L), Type(IT), FnName(SL) {} + /*ContainsUnexpandedParameterPack=*/false) { + PredefinedExprBits.Kind = IK; + assert((getIdentKind() == IK) && + "IdentKind do not fit in PredefinedExprBitfields!"); + bool HasFunctionName = SL != nullptr; + PredefinedExprBits.HasFunctionName = HasFunctionName; + PredefinedExprBits.Loc = L; + if (HasFunctionName) + setFunctionName(SL); +} + +PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName) + : Expr(PredefinedExprClass, Empty) { + PredefinedExprBits.HasFunctionName = HasFunctionName; +} + +PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L, + QualType FNTy, IdentKind IK, + StringLiteral *SL) { + bool HasFunctionName = SL != nullptr; + void *Mem = Ctx.Allocate(totalSizeToAlloc(HasFunctionName), + alignof(PredefinedExpr)); + return new (Mem) PredefinedExpr(L, FNTy, IK, SL); +} -StringLiteral *PredefinedExpr::getFunctionName() { - return cast_or_null(FnName); +PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx, + bool HasFunctionName) { + void *Mem = Ctx.Allocate(totalSizeToAlloc(HasFunctionName), + alignof(PredefinedExpr)); + return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName); } -StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) { - switch (IT) { +StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) { + switch (IK) { case Func: return "__func__"; case Function: @@ -489,15 +514,15 @@ StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) { case PrettyFunctionNoVirtual: break; } - llvm_unreachable("Unknown ident type for PredefinedExpr"); + llvm_unreachable("Unknown ident kind 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) { +std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) { ASTContext &Context = CurrentDecl->getASTContext(); - if (IT == PredefinedExpr::FuncDName) { + if (IK == PredefinedExpr::FuncDName) { if (const NamedDecl *ND = dyn_cast(CurrentDecl)) { std::unique_ptr MC; MC.reset(Context.createMangleContext()); @@ -532,21 +557,21 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { llvm::raw_svector_ostream Out(Buffer); if (auto *DCBlock = dyn_cast(DC)) // For nested blocks, propagate up to the parent. - Out << ComputeName(IT, DCBlock); + Out << ComputeName(IK, DCBlock); else if (auto *DCDecl = dyn_cast(DC)) - Out << ComputeName(IT, DCDecl) << "_block_invoke"; + Out << ComputeName(IK, DCDecl) << "_block_invoke"; return Out.str(); } if (const FunctionDecl *FD = dyn_cast(CurrentDecl)) { - if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && - IT != FuncSig && IT != LFuncSig) + if (IK != PrettyFunction && IK != PrettyFunctionNoVirtual && + IK != FuncSig && IK != LFuncSig) return FD->getNameAsString(); SmallString<256> Name; llvm::raw_svector_ostream Out(Name); if (const CXXMethodDecl *MD = dyn_cast(FD)) { - if (MD->isVirtual() && IT != PrettyFunctionNoVirtual) + if (MD->isVirtual() && IK != PrettyFunctionNoVirtual) Out << "virtual "; if (MD->isStatic()) Out << "static "; @@ -564,7 +589,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (FD->hasWrittenPrototype()) FT = dyn_cast(AFT); - if (IT == FuncSig || IT == LFuncSig) { + if (IK == FuncSig || IK == LFuncSig) { switch (AFT->getCallConv()) { case CC_C: POut << "__cdecl "; break; case CC_X86StdCall: POut << "__stdcall "; break; @@ -589,7 +614,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (FT->isVariadic()) { if (FD->getNumParams()) POut << ", "; POut << "..."; - } else if ((IT == FuncSig || IT == LFuncSig || + } else if ((IK == FuncSig || IK == LFuncSig || !Context.getLangOpts().CPlusPlus) && !Decl->getNumParams()) { POut << "void"; @@ -688,7 +713,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { // CapturedDecl. if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) { const Decl *D = Decl::castFromDeclContext(DC); - return ComputeName(IT, D); + return ComputeName(IK, D); } llvm_unreachable("CapturedDecl not inside a function or method"); } @@ -713,7 +738,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { return Name.str().str(); } - if (isa(CurrentDecl) && IT == PrettyFunction) { + if (isa(CurrentDecl) && IK == PrettyFunction) { // __PRETTY_FUNCTION__ -> "top level", the others produce an empty string. return "top level"; } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 012a9d6..fa33e66 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -991,7 +991,7 @@ void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { } void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { - OS << PredefinedExpr::getIdentTypeName(Node->getIdentType()); + OS << PredefinedExpr::getIdentKindName(Node->getIdentKind()); } void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 2ad9734..ad29a05 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1010,7 +1010,7 @@ void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) { void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) { VisitExpr(S); - ID.AddInteger(S->getIdentType()); + ID.AddInteger(S->getIdentKind()); } void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a8ee16c..a2bb8b2 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2662,7 +2662,7 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { if (FnName.startswith("\01")) FnName = FnName.substr(1); StringRef NameItems[] = { - PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName}; + PredefinedExpr::getIdentKindName(E->getIdentKind()), FnName}; std::string GVName = llvm::join(NameItems, NameItems + 2, "."); if (auto *BD = dyn_cast_or_null(CurCodeDecl)) { std::string Name = SL->getString(); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index b8b6685..68b357b 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1783,7 +1783,7 @@ ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *E) { return cast(Res.getAddress()); } - auto kind = E->getIdentType(); + auto kind = E->getIdentKind(); if (kind == PredefinedExpr::PrettyFunction) { return CGM.GetAddrOfConstantCString("top level", ".tmp"); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f7efb3a..038fef1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3036,7 +3036,7 @@ static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source, } ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, - PredefinedExpr::IdentType IT) { + PredefinedExpr::IdentKind IK) { // Pick the current block, lambda, captured statement or function. Decl *currentDecl = nullptr; if (const BlockScopeInfo *BSI = getCurBlock()) @@ -3060,11 +3060,11 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, else { // Pre-defined identifiers are of type char[x], where x is the length of // the string. - auto Str = PredefinedExpr::ComputeName(IT, currentDecl); + auto Str = PredefinedExpr::ComputeName(IK, currentDecl); unsigned Length = Str.length(); llvm::APInt LengthI(32, Length + 1); - if (IT == PredefinedExpr::LFunction || IT == PredefinedExpr::LFuncSig) { + if (IK == PredefinedExpr::LFunction || IK == PredefinedExpr::LFuncSig) { ResTy = Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst()); SmallString<32> RawChars; @@ -3083,24 +3083,24 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, } } - return new (Context) PredefinedExpr(Loc, ResTy, IT, SL); + return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL); } ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { - PredefinedExpr::IdentType IT; + PredefinedExpr::IdentKind IK; switch (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___FUNCDNAME__: IT = PredefinedExpr::FuncDName; break; // [MS] - case tok::kw___FUNCSIG__: IT = PredefinedExpr::FuncSig; break; // [MS] - case tok::kw_L__FUNCTION__: IT = PredefinedExpr::LFunction; break; // [MS] - case tok::kw_L__FUNCSIG__: IT = PredefinedExpr::LFuncSig; break; // [MS] - case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; + case tok::kw___func__: IK = PredefinedExpr::Func; break; // [C99 6.4.2.2] + case tok::kw___FUNCTION__: IK = PredefinedExpr::Function; break; + case tok::kw___FUNCDNAME__: IK = PredefinedExpr::FuncDName; break; // [MS] + case tok::kw___FUNCSIG__: IK = PredefinedExpr::FuncSig; break; // [MS] + case tok::kw_L__FUNCTION__: IK = PredefinedExpr::LFunction; break; // [MS] + case tok::kw_L__FUNCSIG__: IK = PredefinedExpr::LFuncSig; break; // [MS] + case tok::kw___PRETTY_FUNCTION__: IK = PredefinedExpr::PrettyFunction; break; } - return BuildPredefinedExpr(Loc, IT); + return BuildPredefinedExpr(Loc, IK); } ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index cfedf0a..b409844 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1167,7 +1167,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { if (!E->isTypeDependent()) return E; - return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentType()); + return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind()); } ExprResult diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 73a522b..5043464 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2096,8 +2096,8 @@ public: /// 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); + PredefinedExpr::IdentKind IK) { + return getSema().BuildPredefinedExpr(Loc, IK); } /// Build a new expression that references a declaration. @@ -8921,7 +8921,7 @@ TreeTransform::TransformPredefinedExpr(PredefinedExpr *E) { return E; return getDerived().RebuildPredefinedExpr(E->getLocation(), - E->getIdentType()); + E->getIdentKind()); } template diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 535eeea..6b93c37 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -496,9 +496,12 @@ void ASTStmtReader::VisitExpr(Expr *E) { void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { VisitExpr(E); + bool HasFunctionName = Record.readInt(); + E->PredefinedExprBits.HasFunctionName = HasFunctionName; + E->PredefinedExprBits.Kind = Record.readInt(); E->setLocation(ReadSourceLocation()); - E->Type = (PredefinedExpr::IdentType)Record.readInt(); - E->FnName = cast_or_null(Record.readSubExpr()); + if (HasFunctionName) + E->setFunctionName(cast(Record.readSubExpr())); } void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { @@ -2334,12 +2337,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case STMT_CAPTURED: - S = CapturedStmt::CreateDeserialized(Context, - Record[ASTStmtReader::NumStmtFields]); + S = CapturedStmt::CreateDeserialized( + Context, Record[ASTStmtReader::NumStmtFields]); break; case EXPR_PREDEFINED: - S = new (Context) PredefinedExpr(Empty); + S = PredefinedExpr::CreateEmpty( + Context, + /*HasFunctionName*/ Record[ASTStmtReader::NumExprFields]); break; case EXPR_DECL_REF: diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index fa5c359..77c9da1 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -388,9 +388,13 @@ void ASTStmtWriter::VisitExpr(Expr *E) { void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { VisitExpr(E); + + bool HasFunctionName = E->getFunctionName() != nullptr; + Record.push_back(HasFunctionName); + Record.push_back(E->getIdentKind()); // FIXME: stable encoding Record.AddSourceLocation(E->getLocation()); - Record.push_back(E->getIdentType()); // FIXME: stable encoding - Record.AddStmt(E->getFunctionName()); + if (HasFunctionName) + Record.AddStmt(E->getFunctionName()); Code = serialization::EXPR_PREDEFINED; } -- 2.7.4