riccibruno created this revision.
riccibruno added a reviewer: rjmccall.
riccibruno added a project: clang.
Herald added a subscriber: cfe-commits.
riccibruno added a dependency: D53604: [AST] Widen the bit-fields of Stmt to 8
bytes.
This patch does 3 things:
1. Move PredefinedExpr below StringLiteral so that it can use its definition.
2. Move the location and the IdentType into the newly available space of the
bit-fields of Stmt.
3. Only store the function name when needed.
Repository:
rC Clang
https://reviews.llvm.org/D53605
Files:
include/clang/AST/Expr.h
include/clang/AST/Stmt.h
lib/AST/ASTImporter.cpp
lib/AST/Expr.cpp
lib/Sema/SemaExpr.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -388,9 +388,13 @@
void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
- Record.AddSourceLocation(E->getLocation());
+
+ bool HasFunctionName = !!E->getFunctionName();
+ Record.push_back(HasFunctionName);
Record.push_back(E->getIdentType()); // FIXME: stable encoding
- Record.AddStmt(E->getFunctionName());
+ Record.AddSourceLocation(E->getLocation());
+ if (HasFunctionName)
+ Record.AddStmt(E->getFunctionName());
Code = serialization::EXPR_PREDEFINED;
}
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -496,9 +496,12 @@
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
+ bool HasFunctionName = Record.readInt();
+ E->PredefinedExprBits.HasFnName = HasFunctionName;
+ E->PredefinedExprBits.Type = Record.readInt();
E->setLocation(ReadSourceLocation());
- E->Type = (PredefinedExpr::IdentType)Record.readInt();
- E->FnName = cast_or_null<StringLiteral>(Record.readSubExpr());
+ if (HasFunctionName)
+ E->setFunctionName(cast<StringLiteral>(Record.readSubExpr()));
}
void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
@@ -2334,12 +2337,14 @@
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:
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -3083,7 +3083,7 @@
}
}
- return new (Context) PredefinedExpr(Loc, ResTy, IT, SL);
+ return PredefinedExpr::Create(Context, Loc, ResTy, IT, SL);
}
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -463,11 +463,36 @@
: 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.Type = IT;
+ assert((getIdentType() == IT) &&
+ "IdentType do not fit in PredefinedExprBitfields!");
+ bool HasFunctionName = !!SL;
+ PredefinedExprBits.HasFnName = HasFunctionName;
+ PredefinedExprBits.Loc = L;
+ if (HasFunctionName)
+ setFunctionName(SL);
+}
+
+PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName)
+ : Expr(PredefinedExprClass, Empty) {
+ PredefinedExprBits.HasFnName = HasFunctionName;
+}
+
+PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
+ QualType FNTy, IdentType IT,
+ StringLiteral *SL) {
+ bool HasFunctionName = !!SL;
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
+ alignof(PredefinedExpr));
+ return new (Mem) PredefinedExpr(L, FNTy, IT, 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::getIdentTypeName(PredefinedExpr::IdentType IT) {
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -6148,8 +6148,8 @@
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->getIdentType(), ToFunctionName);
}
ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h
+++ include/clang/AST/Stmt.h
@@ -268,6 +268,24 @@
};
enum { NumExprBits = 17 };
+ class PredefinedExprBitfields {
+ friend class ASTStmtReader;
+ friend class PredefinedExpr;
+
+ unsigned : NumExprBits;
+
+ /// The type of this PredefinedExpr. One of the enumeration values
+ /// in PredefinedExpr::IdentType.
+ unsigned Type : 4;
+
+ /// True if this PredefinedExpr has a trailing "StringLiteral *"
+ /// for the predefined identifier.
+ unsigned HasFnName : 1;
+
+ /// The location of this PredefinedExpr.
+ SourceLocation Loc;
+ };
+
class CharacterLiteralBitfields {
friend class CharacterLiteral;
@@ -432,6 +450,7 @@
// Expressions
ExprBitfields ExprBits;
+ PredefinedExprBitfields PredefinedExprBits;
CharacterLiteralBitfields CharacterLiteralBits;
FloatingLiteralBitfields FloatingLiteralBits;
UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits;
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ 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 @@
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<PredefinedExpr *>(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,90 @@
}
};
+/// [C99 6.4.2.2] - A predefined identifier such as __func__.
+class PredefinedExpr final
+ : public Expr,
+ private llvm::TrailingObjects<PredefinedExpr, Stmt *> {
+ 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 in fact a "StringLiteral *".
+
+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:
+ PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
+ StringLiteral *SL);
+
+ explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);
+
+ bool hasFunctionName() const { return PredefinedExprBits.HasFnName; }
+
+ void setFunctionName(StringLiteral *SL) {
+ assert(hasFunctionName() &&
+ "This PredefinedExpr has no storage for a function name!");
+ *getTrailingObjects<Stmt *>() = SL;
+ }
+
+public:
+ /// Create a PredefinedExpr.
+ static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
+ QualType FNTy, IdentType IT, StringLiteral *SL);
+
+ /// Create an empty PredefinedExpr.
+ static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
+ bool HasFunctionName);
+
+ IdentType getIdentType() const {
+ return static_cast<IdentType>(PredefinedExprBits.Type);
+ }
+
+ SourceLocation getLocation() const { return PredefinedExprBits.Loc; }
+ void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; }
+
+ StringLiteral *getFunctionName() {
+ return hasFunctionName()
+ ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
+ : nullptr;
+ }
+
+ const StringLiteral *getFunctionName() const {
+ return hasFunctionName()
+ ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>())
+ : nullptr;
+ }
+
+ static StringRef getIdentTypeName(IdentType IT);
+ static std::string ComputeName(IdentType IT, 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<Stmt *>(),
+ getTrailingObjects<Stmt *>() + 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 {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits