class TemplateArgumentListInfo;
/// \brief A simple array of base specifiers.
-typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray;
+typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
/// (C++ [temp.dep.constexpr]).
bool ValueDependent : 1;
+ enum { BitsRemaining = 30 };
+
Expr(StmtClass SC, QualType T, bool TD, bool VD)
: Stmt(SC), TypeDependent(TD), ValueDependent(VD) {
setType(T);
};
private:
- CastKind Kind;
+ unsigned Kind : 5;
+ unsigned BasePathSize : BitsRemaining - 5;
Stmt *Op;
- /// BasePath - For derived-to-base and base-to-derived casts, the base array
- /// contains the inheritance path.
- CXXBaseSpecifierArray BasePath;
-
void CheckBasePath() const {
#ifndef NDEBUG
switch (getCastKind()) {
case CK_DerivedToBaseMemberPointer:
case CK_BaseToDerived:
case CK_BaseToDerivedMemberPointer:
- assert(!BasePath.empty() && "Cast kind should have a base path!");
+ assert(!path_empty() && "Cast kind should have a base path!");
break;
// These should not have an inheritance path.
case CK_MemberPointerToBoolean:
case CK_AnyPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
- assert(BasePath.empty() && "Cast kind should not have a base path!");
+ assert(path_empty() && "Cast kind should not have a base path!");
break;
}
#endif
}
+ const CXXBaseSpecifier * const *path_buffer() const {
+ return const_cast<CastExpr*>(this)->path_buffer();
+ }
+ CXXBaseSpecifier **path_buffer();
+
protected:
CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath) :
+ unsigned BasePathSize) :
Expr(SC, ty,
// Cast expressions are type-dependent if the type is
// dependent (C++ [temp.dep.expr]p3).
// Cast expressions are value-dependent if the type is
// dependent or if the subexpression is value-dependent.
ty->isDependentType() || (op && op->isValueDependent())),
- Kind(kind), Op(op), BasePath(BasePath) {
- CheckBasePath();
- }
+ Kind(kind), BasePathSize(BasePathSize), Op(op) {
+ CheckBasePath();
+ }
/// \brief Construct an empty cast.
- CastExpr(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty) { }
+ CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
+ : Expr(SC, Empty), BasePathSize(BasePathSize) { }
public:
- CastKind getCastKind() const { return Kind; }
+ CastKind getCastKind() const { return static_cast<CastKind>(Kind); }
void setCastKind(CastKind K) { Kind = K; }
const char *getCastKindName() const;
return const_cast<CastExpr *>(this)->getSubExprAsWritten();
}
- const CXXBaseSpecifierArray& getBasePath() const { return BasePath; }
- CXXBaseSpecifierArray& getBasePath() { return BasePath; }
+ typedef CXXBaseSpecifier **path_iterator;
+ typedef const CXXBaseSpecifier * const *path_const_iterator;
+ bool path_empty() const { return BasePathSize == 0; }
+ unsigned path_size() const { return BasePathSize; }
+ path_iterator path_begin() { return path_buffer(); }
+ path_iterator path_end() { return path_buffer() + path_size(); }
+ path_const_iterator path_begin() const { return path_buffer(); }
+ path_const_iterator path_end() const { return path_buffer() + path_size(); }
+
+ void setCastPath(const CXXCastPath &Path);
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
/// Category - The category this cast produces.
ResultCategory Category;
-public:
- ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, ResultCategory Cat)
- : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath), Category(Cat) { }
+ ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
+ unsigned BasePathLength, ResultCategory Cat)
+ : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength),
+ Category(Cat) { }
/// \brief Construct an empty implicit cast.
- explicit ImplicitCastExpr(EmptyShell Shell)
- : CastExpr(ImplicitCastExprClass, Shell) { }
+ explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
+ : CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
+
+public:
+ enum OnStack_t { OnStack };
+ ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
+ ResultCategory Cat)
+ : CastExpr(ImplicitCastExprClass, ty, kind, op, 0),
+ Category(Cat) { }
+
+ static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ResultCategory Cat);
+
+ static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
virtual SourceRange getSourceRange() const {
return getSubExpr()->getSourceRange();
protected:
ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
- Expr *op, CXXBaseSpecifierArray BasePath,
- TypeSourceInfo *writtenTy)
- : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {}
+ Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy)
+ : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
- ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
- : CastExpr(SC, Shell) { }
+ ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : CastExpr(SC, Shell, PathSize) { }
public:
/// getTypeInfoAsWritten - Returns the type source info for the type
class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
-public:
+
CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r)
- : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath,
+ : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
- explicit CStyleCastExpr(EmptyShell Shell)
- : ExplicitCastExpr(CStyleCastExprClass, Shell) { }
+ explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
+
+public:
+ static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K,
+ Expr *Op, const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation R);
+
+ static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
protected:
CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {}
+ : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {}
- explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell)
- : ExplicitCastExpr(SC, Shell) { }
+ explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(SC, Shell, PathSize) { }
public:
const char *getCastName() const;
/// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
-public:
CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {}
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize,
+ writtenTy, l) {}
- explicit CXXStaticCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { }
+ explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
+
+public:
+ static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L);
+ static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
/// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
-public:
CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath,
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {}
- explicit CXXDynamicCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { }
+ explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L);
+
+ static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
-public:
CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath,
+ unsigned pathSize,
TypeSourceInfo *writtenTy, SourceLocation l)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath,
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {}
- explicit CXXReinterpretCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { }
+ CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
/// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
-public:
CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
SourceLocation l)
: CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op,
- CXXBaseSpecifierArray(), writtenTy, l) {}
+ 0, writtenTy, l) {}
explicit CXXConstCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { }
+ : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
+
+public:
+ static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op,
+ TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
-public:
+
CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
- Expr *castExpr, CXXBaseSpecifierArray BasePath,
+ Expr *castExpr, unsigned pathSize,
SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
- BasePath, writtenTy),
+ pathSize, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
- explicit CXXFunctionalCastExpr(EmptyShell Shell)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { }
+ explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
+
+public:
+ static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
+ TypeSourceInfo *Written,
+ SourceLocation TyBeginLoc,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ SourceLocation RPLoc);
+ static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+
+ bool ImportCasePath(CastExpr *E, CXXCastPath &Path);
};
}
Importer.Import(E->getOperatorLoc()));
}
+bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
+ if (E->path_empty()) return false;
+
+ // TODO: import cast paths
+ return true;
+}
+
Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
return 0;
-
- // FIXME: Initialize the base path.
- assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
- CXXBaseSpecifierArray BasePath;
- return new (Importer.getToContext()) ImplicitCastExpr(T, E->getCastKind(),
- SubExpr, BasePath,
- E->getCategory());
+
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, E->getCategory());
}
Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
if (!TInfo && E->getTypeInfoAsWritten())
return 0;
- // FIXME: Initialize the base path.
- assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
- CXXBaseSpecifierArray BasePath;
- return new (Importer.getToContext()) CStyleCastExpr(T, E->getCastKind(),
- SubExpr, BasePath, TInfo,
- Importer.Import(E->getLParenLoc()),
- Importer.Import(E->getRParenLoc()));
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return CStyleCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ Importer.Import(E->getLParenLoc()),
+ Importer.Import(E->getRParenLoc()));
}
ASTImporter::ASTImporter(Diagnostic &Diags,
return SubExpr;
}
+CXXBaseSpecifier **CastExpr::path_buffer() {
+ switch (getStmtClass()) {
+#define ABSTRACT_STMT(x)
+#define CASTEXPR(Type, Base) \
+ case Stmt::Type##Class: \
+ return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
+#define STMT(Type, Base)
+#include "clang/AST/StmtNodes.inc"
+ default:
+ llvm_unreachable("non-cast expressions not possible here");
+ return 0;
+ }
+}
+
+void CastExpr::setCastPath(const CXXCastPath &Path) {
+ assert(Path.size() == path_size());
+ memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*));
+}
+
+ImplicitCastExpr *ImplicitCastExpr::Create(ASTContext &C, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ResultCategory Cat) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ ImplicitCastExpr *E =
+ new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, Cat);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
+}
+
+
+CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L, SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ CStyleCastExpr *E =
+ new (Buffer) CStyleCastExpr(T, K, Op, PathSize, WrittenTy, L, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CStyleCastExpr *CStyleCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
+}
+
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
}
}
+CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXStaticCastExpr *E =
+ new (Buffer) CXXStaticCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXDynamicCastExpr *E =
+ new (Buffer) CXXDynamicCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXReinterpretCastExpr *E =
+ new (Buffer) CXXReinterpretCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, Expr *Op,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ return new (C) CXXConstCastExpr(T, Op, WrittenTy, L);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) {
+ return new (C) CXXConstCastExpr(EmptyShell());
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::Create(ASTContext &C, QualType T,
+ TypeSourceInfo *Written, SourceLocation L,
+ CastKind K, Expr *Op, const CXXCastPath *BasePath,
+ SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXFunctionalCastExpr *E =
+ new (Buffer) CXXFunctionalCastExpr(T, Written, L, K, Op, PathSize, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
+}
+
+
CXXDefaultArgExpr *
CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
ParmVarDecl *Param, Expr *SubExpr) {
}
static void DumpBasePath(llvm::raw_ostream &OS, CastExpr *Node) {
- if (Node->getBasePath().empty())
+ if (Node->path_empty())
return;
OS << " (";
bool First = true;
- for (CXXBaseSpecifierArray::iterator I = Node->getBasePath().begin(),
- E = Node->getBasePath().end(); I != E; ++I) {
+ for (CastExpr::path_iterator
+ I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
const CXXBaseSpecifier *Base = *I;
if (!First)
OS << " -> ";
static uint64_t
ComputeNonVirtualBaseClassOffset(ASTContext &Context,
const CXXRecordDecl *DerivedClass,
- CXXBaseSpecifierArray::iterator Start,
- CXXBaseSpecifierArray::iterator End) {
+ CastExpr::path_const_iterator Start,
+ CastExpr::path_const_iterator End) {
uint64_t Offset = 0;
const CXXRecordDecl *RD = DerivedClass;
- for (CXXBaseSpecifierArray::iterator I = Start; I != End; ++I) {
+ for (CastExpr::path_const_iterator I = Start; I != End; ++I) {
const CXXBaseSpecifier *Base = *I;
assert(!Base->isVirtual() && "Should not see virtual bases here!");
llvm::Constant *
CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
- const CXXBaseSpecifierArray &BasePath) {
- assert(!BasePath.empty() && "Base path should not be empty!");
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd) {
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
uint64_t Offset =
- ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
- BasePath.begin(), BasePath.end());
+ ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
+ PathBegin, PathEnd);
if (!Offset)
return 0;
llvm::Value *
CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue) {
- assert(!BasePath.empty() && "Base path should not be empty!");
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
- CXXBaseSpecifierArray::iterator Start = BasePath.begin();
+ CastExpr::path_const_iterator Start = PathBegin;
const CXXRecordDecl *VBase = 0;
// Get the virtual base.
uint64_t NonVirtualOffset =
ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived,
- Start, BasePath.end());
+ Start, PathEnd);
// Get the base pointer type.
const llvm::Type *BasePtrTy =
- ConvertType((BasePath.end()[-1])->getType())->getPointerTo();
+ ConvertType((PathEnd[-1])->getType())->getPointerTo();
if (!NonVirtualOffset && !VBase) {
// Just cast back.
llvm::Value *
CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue) {
- assert(!BasePath.empty() && "Base path should not be empty!");
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
QualType DerivedTy =
getContext().getCanonicalType(getContext().getTagDeclType(Derived));
const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo();
llvm::Value *NonVirtualOffset =
- CGM.GetNonVirtualBaseClassOffset(Derived, BasePath);
+ CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
if (!NonVirtualOffset) {
// No offset, we can just cast back.
union {
struct {
- const CXXBaseSpecifierArray *BasePath;
+ const CastExpr *BasePath;
const CXXRecordDecl *DerivedClass;
} DerivedToBase;
} Field;
};
- SubobjectAdjustment(const CXXBaseSpecifierArray *BasePath,
+ SubobjectAdjustment(const CastExpr *BasePath,
const CXXRecordDecl *DerivedClass)
: Kind(DerivedToBaseAdjustment)
{
E = CE->getSubExpr();
CXXRecordDecl *Derived
= cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
- Adjustments.push_back(SubobjectAdjustment(&CE->getBasePath(),
- Derived));
+ Adjustments.push_back(SubobjectAdjustment(CE, Derived));
continue;
}
Object =
CGF.GetAddressOfBaseClass(Object,
Adjustment.DerivedToBase.DerivedClass,
- *Adjustment.DerivedToBase.BasePath,
+ Adjustment.DerivedToBase.BasePath->path_begin(),
+ Adjustment.DerivedToBase.BasePath->path_end(),
/*NullCheckValue=*/false);
break;
// Perform the derived-to-base conversion
llvm::Value *Base =
GetAddressOfBaseClass(This, DerivedClassDecl,
- E->getBasePath(), /*NullCheckValue=*/false);
+ E->path_begin(), E->path_end(),
+ /*NullCheckValue=*/false);
return LValue::MakeAddr(Base, MakeQualifiers(E->getType()));
}
// Perform the base-to-derived conversion
llvm::Value *Derived =
GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl,
- E->getBasePath(),/*NullCheckValue=*/false);
+ E->path_begin(), E->path_end(),
+ /*NullCheckValue=*/false);
return LValue::MakeAddr(Derived, MakeQualifiers(E->getType()));
}
std::swap(DerivedDecl, BaseDecl);
if (llvm::Constant *Adj =
- CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, E->getBasePath())) {
+ CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
+ E->path_begin(),
+ E->path_end())) {
if (E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
else
// Check if we need to update the adjustment.
if (llvm::Constant *Offset =
- CGM.GetNonVirtualBaseClassOffset(DerivedClass, E->getBasePath())) {
+ CGM.GetNonVirtualBaseClassOffset(DerivedClass,
+ E->path_begin(),
+ E->path_end())) {
llvm::Constant *Values[2];
Values[0] = CS->getOperand(0);
DestTy->getCXXRecordDeclForPointerType();
return CGF.GetAddressOfDerivedClass(Visit(E), DerivedClassDecl,
- CE->getBasePath(),
+ CE->path_begin(), CE->path_end(),
ShouldNullCheckClassCastValue(CE));
}
case CastExpr::CK_UncheckedDerivedToBase:
cast<CXXRecordDecl>(DerivedClassTy->getDecl());
return CGF.GetAddressOfBaseClass(Visit(E), DerivedClassDecl,
- CE->getBasePath(),
+ CE->path_begin(), CE->path_end(),
ShouldNullCheckClassCastValue(CE));
}
case CastExpr::CK_Dynamic: {
std::swap(DerivedDecl, BaseDecl);
if (llvm::Constant *Adj =
- CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, CE->getBasePath())){
+ CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
+ CE->path_begin(),
+ CE->path_end())) {
if (CE->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
Src = Builder.CreateNSWSub(Src, Adj, "adj");
else
// Objective-C pointer types, we can always bit cast the RHS in these cases.
if (getContext().getCanonicalType(Ivar->getType()) !=
getContext().getCanonicalType(ArgDecl->getType())) {
- ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg,
- CXXBaseSpecifierArray(),
+ ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack,
+ Ivar->getType(), CastExpr::CK_BitCast, &Arg,
ImplicitCastExpr::RValue);
BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign,
Ivar->getType(), Loc);
/// load of 'this' and returns address of the base class.
llvm::Value *GetAddressOfBaseClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue);
llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue);
llvm::Value *GetVirtualBaseClassOffset(llvm::Value *This,
/// a class. Returns null if the offset is 0.
llvm::Constant *
GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
- const CXXBaseSpecifierArray &BasePath);
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd);
/// GetStringForStringLiteral - Return the appropriate bytes for a string
/// literal, properly padded to match the literal type. If only the address of
void PCHStmtReader::VisitCastExpr(CastExpr *E) {
VisitExpr(E);
+ unsigned NumBaseSpecs = Record[Idx++];
+ assert(NumBaseSpecs == E->path_size());
E->setSubExpr(Reader.ReadSubExpr());
E->setCastKind((CastExpr::CastKind)Record[Idx++]);
- CXXBaseSpecifierArray &BasePath = E->getBasePath();
- unsigned NumBaseSpecs = Record[Idx++];
+ CastExpr::path_iterator BaseI = E->path_begin();
while (NumBaseSpecs--) {
CXXBaseSpecifier *BaseSpec = new (*Reader.getContext()) CXXBaseSpecifier;
*BaseSpec = Reader.ReadCXXBaseSpecifier(DeclsCursor, Record, Idx);
- BasePath.push_back(BaseSpec);
+ *BaseI++ = BaseSpec;
}
}
break;
case pch::EXPR_IMPLICIT_CAST:
- S = new (Context) ImplicitCastExpr(Empty);
+ S = ImplicitCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
break;
case pch::EXPR_CSTYLE_CAST:
- S = new (Context) CStyleCastExpr(Empty);
+ S = CStyleCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
break;
case pch::EXPR_COMPOUND_LITERAL:
break;
case pch::EXPR_CXX_STATIC_CAST:
- S = new (Context) CXXStaticCastExpr(Empty);
+ S = CXXStaticCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
break;
case pch::EXPR_CXX_DYNAMIC_CAST:
- S = new (Context) CXXDynamicCastExpr(Empty);
+ S = CXXDynamicCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
break;
case pch::EXPR_CXX_REINTERPRET_CAST:
- S = new (Context) CXXReinterpretCastExpr(Empty);
+ S = CXXReinterpretCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
break;
case pch::EXPR_CXX_CONST_CAST:
- S = new (Context) CXXConstCastExpr(Empty);
+ S = CXXConstCastExpr::CreateEmpty(*Context);
break;
case pch::EXPR_CXX_FUNCTIONAL_CAST:
- S = new (Context) CXXFunctionalCastExpr(Empty);
+ S = CXXFunctionalCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[PCHStmtReader::NumExprFields]);
break;
case pch::EXPR_CXX_BOOL_LITERAL:
void PCHStmtWriter::VisitCastExpr(CastExpr *E) {
VisitExpr(E);
+ Record.push_back(E->path_size());
Writer.AddStmt(E->getSubExpr());
Record.push_back(E->getCastKind()); // FIXME: stable encoding
- CXXBaseSpecifierArray &BasePath = E->getBasePath();
- Record.push_back(BasePath.size());
- for (CXXBaseSpecifierArray::iterator I = BasePath.begin(), E = BasePath.end();
- I != E; ++I)
- Writer.AddCXXBaseSpecifier(**I, Record);
+
+ for (CastExpr::path_iterator
+ PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI)
+ Writer.AddCXXBaseSpecifier(**PI, Record);
}
void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
CastExpr::CastKind Kind, Expr *E) {
TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
- return new (Ctx) CStyleCastExpr(Ty, Kind, E, CXXBaseSpecifierArray(), TInfo,
- SourceLocation(), SourceLocation());
+ return CStyleCastExpr::Create(*Ctx, Ty, Kind, E, 0, TInfo,
+ SourceLocation(), SourceLocation());
}
}
// Now, we cast the reference to a pointer to the objc_msgSend type.
QualType pToFunc = Context->getPointerType(msgSendType);
ImplicitCastExpr *ICE =
- new (Context) ImplicitCastExpr(pToFunc, CastExpr::CK_Unknown,
- DRE, CXXBaseSpecifierArray(),
- ImplicitCastExpr::RValue);
+ ImplicitCastExpr::Create(*Context, pToFunc, CastExpr::CK_Unknown,
+ DRE, 0, ImplicitCastExpr::RValue);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
CastExpr::CastKind Kind,
ImplicitCastExpr::ResultCategory Category,
- CXXBaseSpecifierArray BasePath) {
+ const CXXCastPath *BasePath) {
QualType ExprTy = Context.getCanonicalType(Expr->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
// If this is a derived-to-base cast to a through a virtual base, we
// need a vtable.
if (Kind == CastExpr::CK_DerivedToBase &&
- BasePathInvolvesVirtualBase(BasePath)) {
+ BasePathInvolvesVirtualBase(*BasePath)) {
QualType T = Expr->getType();
if (const PointerType *Pointer = T->getAs<PointerType>())
T = Pointer->getPointeeType();
}
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
- if (ImpCast->getCastKind() == Kind && BasePath.empty()) {
+ if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);
ImpCast->setCategory(Category);
return;
}
}
- Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, BasePath, Category);
+ Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, Category);
}
ImplicitCastExpr::ResultCategory Sema::CastCategory(Expr *E) {
bool CheckPointerConversion(Expr *From, QualType ToType,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray& BasePath,
+ CXXCastPath& BasePath,
bool IgnoreBaseAccess);
bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
bool InOverloadResolution,
QualType &ConvertedType);
bool CheckMemberPointerConversion(Expr *From, QualType ToType,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath,
+ CXXCastPath &BasePath,
bool IgnoreBaseAccess);
bool IsQualificationConversion(QualType FromType, QualType ToType);
OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType,
bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths);
// FIXME: I don't like this name.
- void BuildBasePathArray(const CXXBasePaths &Paths,
- CXXBaseSpecifierArray &BasePath);
+ void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
- bool BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath);
+ bool BasePathInvolvesVirtualBase(const CXXCastPath &BasePath);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
SourceLocation Loc, SourceRange Range,
- CXXBaseSpecifierArray *BasePath = 0,
+ CXXCastPath *BasePath = 0,
bool IgnoreAccess = false);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
unsigned InaccessibleBaseID,
unsigned AmbigiousBaseConvID,
SourceLocation Loc, SourceRange Range,
DeclarationName Name,
- CXXBaseSpecifierArray *BasePath);
+ CXXCastPath *BasePath);
std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
void ImpCastExprToType(Expr *&Expr, QualType Type, CastExpr::CastKind Kind,
ImplicitCastExpr::ResultCategory Category =
ImplicitCastExpr::RValue,
- CXXBaseSpecifierArray BasePath =
- CXXBaseSpecifierArray());
+ const CXXCastPath *BasePath = 0);
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
// functions and arrays to their respective pointers (C99 6.3.2.1).
/// CheckCastTypes - Check type constraints for casting between types under
/// C semantics, or forward to CXXCheckCStyleCast in C++.
bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
- CastExpr::CastKind &Kind, CXXBaseSpecifierArray &BasePath,
+ CastExpr::CastKind &Kind, CXXCastPath &BasePath,
bool FunctionalStyle = false);
// CheckVectorCast - check type constraints for vectors.
/// CXXCheckCStyleCast - Check constraints of a C-style or function-style
/// cast under C++ semantics.
bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath,
+ CastExpr::CastKind &Kind, CXXCastPath &BasePath,
bool FunctionalStyle);
/// CheckMessageArgumentTypes - Check types in an Obj-C message send.
static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CXXCastPath &BasePath);
static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CXXCastPath &BasePath);
static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType);
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CXXCastPath &BasePath);
static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CXXCastPath &BasePath);
static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
CanQualType DestType, bool CStyle,
const SourceRange &OpRange,
QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CXXCastPath &BasePath);
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr,
QualType SrcType,
QualType DestType,bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CXXCastPath &BasePath);
static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CXXCastPath &BasePath);
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, unsigned &msg);
static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
case tok::kw_const_cast:
if (!TypeDependent)
CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
- return Owned(new (Context) CXXConstCastExpr(
+ return Owned(CXXConstCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Ex, DestTInfo, OpLoc));
+ Ex, DestTInfo, OpLoc));
case tok::kw_dynamic_cast: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (!TypeDependent)
CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath);
- return Owned(new (Context)CXXDynamicCastExpr(
+ return Owned(CXXDynamicCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, BasePath, DestTInfo,
- OpLoc));
+ Kind, Ex, &BasePath, DestTInfo,
+ OpLoc));
}
case tok::kw_reinterpret_cast: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
if (!TypeDependent)
CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
- return Owned(new (Context) CXXReinterpretCastExpr(
+ return Owned(CXXReinterpretCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, CXXBaseSpecifierArray(),
+ Kind, Ex, 0,
DestTInfo, OpLoc));
}
case tok::kw_static_cast: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (!TypeDependent)
CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath);
- return Owned(new (Context) CXXStaticCastExpr(
+ return Owned(CXXStaticCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, BasePath,
- DestTInfo, OpLoc));
+ Kind, Ex, &BasePath,
+ DestTInfo, OpLoc));
}
}
CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ CXXCastPath &BasePath) {
QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
DestType = Self.Context.getCanonicalType(DestType);
void
CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ CXXCastPath &BasePath) {
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
QualType DestType, bool CStyle,
const SourceRange &OpRange, unsigned &msg,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ CXXCastPath &BasePath) {
// The order the tests is not entirely arbitrary. There is one conversion
// that can be handled in two different ways. Given:
// struct A {};
TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, const SourceRange &OpRange,
unsigned &msg, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ CXXCastPath &BasePath) {
// C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
// cast to type "reference to cv2 D", where D is a class derived from B,
// if a valid standard conversion from "pointer to D" to "pointer to B"
TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
bool CStyle, const SourceRange &OpRange,
unsigned &msg, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ CXXCastPath &BasePath) {
// C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
// type, can be converted to an rvalue of type "pointer to cv2 D", where D
// is a class derived from B, if a valid standard conversion from "pointer
TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
- CastExpr::CastKind &Kind, CXXBaseSpecifierArray &BasePath) {
+ CastExpr::CastKind &Kind, CXXCastPath &BasePath) {
// We can only work with complete types. But don't complain if it doesn't work
if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, Self.PDiag(0)) ||
Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0)))
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ CXXCastPath &BasePath) {
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
if (!DestMemPtr)
return TC_NotApplicable;
bool
Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath,
+ CXXCastPath &BasePath,
bool FunctionalStyle) {
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
TUScope, false, DRE->getLocStart()));
- // The first argument is by definition correct, we use it's type as the type
- // of the entire operation. Walk the remaining arguments promoting them to
- // the deduced value type.
+ // The first argument --- the pointer --- has a fixed type; we
+ // deduce the types of the rest of the arguments accordingly. Walk
+ // the remaining arguments, converting them to the deduced value type.
for (unsigned i = 0; i != NumFixed; ++i) {
Expr *Arg = TheCall->getArg(i+1);
// GCC does an implicit conversion to the pointer or integer ValType. This
// can fail in some cases (1i -> int**), check for this error case now.
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath))
return ExprError();
// pass in 42. The 42 gets converted to char. This is even more strange
// for things like 45.123 -> char, etc.
// FIXME: Do this check.
- ImpCastExprToType(Arg, ValType, Kind);
+ ImpCastExprToType(Arg, ValType, Kind, ImplicitCastExpr::RValue, &BasePath);
TheCall->setArg(i+1, Arg);
}
// Adjust the Expr initializer and type.
if (ECD->getInitExpr())
- ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy,
- CastExpr::CK_IntegralCast,
- ECD->getInitExpr(),
- CXXBaseSpecifierArray(),
- ImplicitCastExpr::RValue));
+ ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
+ CastExpr::CK_IntegralCast,
+ ECD->getInitExpr(),
+ /*base paths*/ 0,
+ ImplicitCastExpr::RValue));
if (getLangOptions().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
}
void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
- CXXBaseSpecifierArray &BasePathArray) {
+ CXXCastPath &BasePathArray) {
assert(BasePathArray.empty() && "Base path array must be empty!");
assert(Paths.isRecordingPaths() && "Must record paths!");
// Now add all bases.
for (unsigned I = Start, E = Path.size(); I != E; ++I)
- BasePathArray.push_back(Path[I].Base);
+ BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
}
/// \brief Determine whether the given base path includes a virtual
/// base class.
-bool Sema::BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath) {
- for (CXXBaseSpecifierArray::iterator B = BasePath.begin(),
- BEnd = BasePath.end();
+bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) {
+ for (CXXCastPath::const_iterator B = BasePath.begin(),
+ BEnd = BasePath.end();
B != BEnd; ++B)
if ((*B)->isVirtual())
return true;
unsigned AmbigiousBaseConvID,
SourceLocation Loc, SourceRange Range,
DeclarationName Name,
- CXXBaseSpecifierArray *BasePath) {
+ CXXCastPath *BasePath) {
// First, determine whether the path from Derived to Base is
// ambiguous. This is slightly more expensive than checking whether
// the Derived to Base conversion exists, because here we need to
bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
SourceLocation Loc, SourceRange Range,
- CXXBaseSpecifierArray *BasePath,
+ CXXCastPath *BasePath,
bool IgnoreAccess) {
return CheckDerivedToBaseConversion(Derived, Base,
IgnoreAccess ? 0
QualType ArgTy =
SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
ParamType.getQualifiers());
+
+ CXXCastPath BasePath;
+ BasePath.push_back(BaseSpec);
SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
CastExpr::CK_UncheckedDerivedToBase,
- ImplicitCastExpr::LValue,
- CXXBaseSpecifierArray(BaseSpec));
+ ImplicitCastExpr::LValue, &BasePath);
InitializationKind InitKind
= InitializationKind::CreateDirect(Constructor->getLocation(),
continue;
}
+ CXXCastPath BasePath;
+ BasePath.push_back(Base);
+
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
Expr *From = OtherRef->Retain();
ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
CastExpr::CK_UncheckedDerivedToBase,
- ImplicitCastExpr::LValue, CXXBaseSpecifierArray(Base));
+ ImplicitCastExpr::LValue, &BasePath);
// Dereference "this".
OwningExprResult To = CreateBuiltinUnaryOp(Loc, UnaryOperator::Deref,
Context.getCVRQualifiedType(BaseType,
CopyAssignOperator->getTypeQualifiers()),
CastExpr::CK_UncheckedDerivedToBase,
- ImplicitCastExpr::LValue, CXXBaseSpecifierArray(Base));
+ ImplicitCastExpr::LValue, &BasePath);
To = Owned(ToE);
// Build the copy.
// type of the object type, in which case we just ignore it.
// Otherwise build the appropriate casts.
if (IsDerivedFrom(FromRecordType, QRecordType)) {
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
FromLoc, FromRange, &BasePath))
return true;
if (PointerConversions)
QType = Context.getPointerType(QType);
ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase,
- Category, BasePath);
+ Category, &BasePath);
FromType = QType;
FromRecordType = QRecordType;
// conversion is non-trivial.
if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
assert(IsDerivedFrom(FromRecordType, URecordType));
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
FromLoc, FromRange, &BasePath))
return true;
if (PointerConversions)
UType = Context.getPointerType(UType);
ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase,
- Category, BasePath);
+ Category, &BasePath);
FromType = UType;
FromRecordType = URecordType;
}
IgnoreAccess = true;
}
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
FromLoc, FromRange, &BasePath,
IgnoreAccess))
return true;
ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase,
- Category, BasePath);
+ Category, &BasePath);
return false;
}
/// CheckCastTypes - Check type constraints for casting between types.
bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
CastExpr::CastKind& Kind,
- CXXBaseSpecifierArray &BasePath,
+ CXXCastPath &BasePath,
bool FunctionalStyle) {
if (getLangOptions().CPlusPlus)
return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, BasePath,
Expr *castExpr = static_cast<Expr*>(Op.get());
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
Kind, BasePath))
return ExprError();
Op.release();
- return Owned(new (Context) CStyleCastExpr(
+ return Owned(CStyleCastExpr::Create(Context,
Ty->getType().getNonLValueExprType(Context),
- Kind, castExpr, BasePath, Ty,
- LParenLoc, RParenLoc));
+ Kind, castExpr, &BasePath, Ty,
+ LParenLoc, RParenLoc));
}
/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence
//
if (NumExprs == 1) {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, BasePath,
/*FunctionalStyle=*/true))
return ExprError();
exprs.release();
- return Owned(new (Context) CXXFunctionalCastExpr(
+ return Owned(CXXFunctionalCastExpr::Create(Context,
Ty.getNonLValueExprType(Context),
- TInfo, TyBeginLoc, Kind,
- Exprs[0], BasePath,
- RParenLoc));
+ TInfo, TyBeginLoc, Kind,
+ Exprs[0], &BasePath,
+ RParenLoc));
}
if (Ty->isRecordType()) {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckPointerConversion(From, ToType, Kind, BasePath, IgnoreBaseAccess))
return true;
- ImpCastExprToType(From, ToType, Kind, ImplicitCastExpr::RValue, BasePath);
+ ImpCastExprToType(From, ToType, Kind, ImplicitCastExpr::RValue, &BasePath);
break;
}
case ICK_Pointer_Member: {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckMemberPointerConversion(From, ToType, Kind, BasePath,
IgnoreBaseAccess))
return true;
if (CheckExceptionSpecCompatibility(From, ToType))
return true;
- ImpCastExprToType(From, ToType, Kind, ImplicitCastExpr::RValue, BasePath);
+ ImpCastExprToType(From, ToType, Kind, ImplicitCastExpr::RValue, &BasePath);
break;
}
case ICK_Boolean_Conversion: {
}
case ICK_Derived_To_Base: {
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(From->getType(),
ToType.getNonReferenceType(),
From->getLocStart(),
return true;
ImpCastExprToType(From, ToType.getNonReferenceType(),
- CastExpr::CK_DerivedToBase, CastCategory(From), BasePath);
+ CastExpr::CK_DerivedToBase, CastCategory(From),
+ &BasePath);
break;
}
ImplicitCastExpr::ResultCategory Category =
isIndirect ? ImplicitCastExpr::RValue : CastCategory(lex);
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
BuildBasePathArray(Paths, BasePath);
ImpCastExprToType(lex, UseType, CastExpr::CK_DerivedToBase, Category,
- BasePath);
+ &BasePath);
}
if (isa<CXXScalarValueInitExpr>(rex->IgnoreParens())) {
// We have a derived-to-base cast that produces either an rvalue or an
// lvalue. Perform that cast.
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
// Casts to inaccessible base classes are allowed with C-style casts.
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
(Step->Kind == SK_CastDerivedToBaseXValue ?
ImplicitCastExpr::XValue :
ImplicitCastExpr::RValue);
- CurInit = S.Owned(new (S.Context) ImplicitCastExpr(Step->Type,
- CastExpr::CK_DerivedToBase,
- (Expr*)CurInit.release(),
- BasePath, Category));
+ CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+ Step->Type,
+ CastExpr::CK_DerivedToBase,
+ (Expr*)CurInit.release(),
+ &BasePath, Category));
break;
}
CurInitExpr = CurInit.takeAs<Expr>();
// FIXME: xvalues
- CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(),
- CastKind,
- CurInitExpr,
- CXXBaseSpecifierArray(),
+ CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+ CurInitExpr->getType(),
+ CastKind, CurInitExpr, 0,
IsLvalue ? ImplicitCastExpr::LValue : ImplicitCastExpr::RValue));
if (RequiresCopy)
/// error, or returns false otherwise.
bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray& BasePath,
+ CXXCastPath& BasePath,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
/// otherwise.
bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath,
+ CXXCastPath &BasePath,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
// well-formed.
DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
From->getLocStart());
- ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()),
+ ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
+ Context.getPointerType(Conversion->getType()),
CastExpr::CK_FunctionToPointerDecay,
- &ConversionRef, CXXBaseSpecifierArray(),
- ImplicitCastExpr::RValue);
+ &ConversionRef, ImplicitCastExpr::RValue);
// Note that it is safe to allocate CallExpr on the stack here because
// there are 0 arguments (i.e., nothing is allocated using ASTContext's
assert(Context.hasSameType(ICE->getSubExpr()->getType(),
SubExpr->getType()) &&
"Implicit cast type cannot be determined from overload");
+ assert(ICE->path_empty() && "fixing up hierarchy conversion?");
if (SubExpr == ICE->getSubExpr())
return ICE->Retain();
- return new (Context) ImplicitCastExpr(ICE->getType(),
- ICE->getCastKind(),
- SubExpr, CXXBaseSpecifierArray(),
- ICE->getCategory());
+ return ImplicitCastExpr::Create(Context, ICE->getType(),
+ ICE->getCastKind(),
+ SubExpr, 0,
+ ICE->getCategory());
}
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {