[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
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 @@
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) {}
-
-StringLiteral *PredefinedExpr::getFunctionName() {
- return cast_or_null<StringLiteral>(FnName);
+ /*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);
}
-StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
- switch (IT) {
+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<Stmt *>(HasFunctionName),
+ alignof(PredefinedExpr));
+ return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
+}
+
+PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx,
+ bool HasFunctionName) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
+ alignof(PredefinedExpr));
+ return new (Mem) PredefinedExpr(EmptyShell(), HasFunctionName);
+}
+
+StringRef PredefinedExpr::getIdentKindName(PredefinedExpr::IdentKind IK) {
+ switch (IK) {
case Func:
return "__func__";
case Function:
@@ -489,15 +514,15 @@
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<NamedDecl>(CurrentDecl)) {
std::unique_ptr<MangleContext> MC;
MC.reset(Context.createMangleContext());
@@ -532,21 +557,21 @@
llvm::raw_svector_ostream Out(Buffer);
if (auto *DCBlock = dyn_cast<BlockDecl>(DC))
// For nested blocks, propagate up to the parent.
- Out << ComputeName(IT, DCBlock);
+ Out << ComputeName(IK, DCBlock);
else if (auto *DCDecl = dyn_cast<Decl>(DC))
- Out << ComputeName(IT, DCDecl) << "_block_invoke";
+ Out << ComputeName(IK, DCDecl) << "_block_invoke";
return Out.str();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(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<CXXMethodDecl>(FD)) {
- if (MD->isVirtual() && IT != PrettyFunctionNoVirtual)
+ if (MD->isVirtual() && IK != PrettyFunctionNoVirtual)
Out << "virtual ";
if (MD->isStatic())
Out << "static ";
@@ -564,7 +589,7 @@
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(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 @@
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 @@
// 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 @@
return Name.str().str();
}
- if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
+ if (isa<TranslationUnitDecl>(CurrentDecl) && IK == PrettyFunction) {
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
return "top level";
}