SourceLocation(), II);
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
- CastExpr *castExpr = new ExplicitCastExpr(castT, IV->getBase(),
- SourceLocation());
+ CastExpr *castExpr = new ExplicitCCastExpr(castT, IV->getBase(), castT,
+ SourceLocation());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new ParenExpr(IV->getBase()->getLocStart(),
IV->getBase()->getLocEnd(),
SourceLocation(), II);
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
- CastExpr *castExpr = new ExplicitCastExpr(castT, IV->getBase(),
- SourceLocation());
+ CastExpr *castExpr = new ExplicitCCastExpr(castT, IV->getBase(), castT,
+ SourceLocation());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new ParenExpr(IV->getBase()->getLocStart(),
IV->getBase()->getLocEnd(), castExpr);
}
}
- if (ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(S))
+ if (ExplicitCCastExpr *CE = dyn_cast<ExplicitCCastExpr>(S))
RewriteObjCQualifiedInterfaceTypes(CE);
if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
buf += " _rethrow = objc_exception_extract(&_stack);\n";
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
buf += " objc_sync_exit(";
- Expr *syncExpr = new ExplicitCastExpr(Context->getObjCIdType(),
- S->getSynchExpr(), SourceLocation());
+ Expr *syncExpr = new ExplicitCCastExpr(Context->getObjCIdType(),
+ S->getSynchExpr(),
+ Context->getObjCIdType(),
+ SourceLocation());
std::string syncExprBufS;
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
syncExpr->printPretty(syncExprBuf);
Context->getPointerType(DRE->getType()),
SourceLocation());
// cast to NSConstantString *
- CastExpr *cast = new ExplicitCastExpr(Exp->getType(), Unop, SourceLocation());
+ CastExpr *cast = new ExplicitCCastExpr(Exp->getType(), Unop,
+ Exp->getType(), SourceLocation());
ReplaceStmt(Exp, cast);
delete Exp;
return cast;
&ClsExprs[0],
ClsExprs.size());
// To turn off a warning, type-cast to 'id'
- InitExprs.push_back(
- new ExplicitCastExpr(Context->getObjCIdType(),
- Cls, SourceLocation())); // set 'super class', using objc_getClass().
+ InitExprs.push_back( // set 'super class', using objc_getClass().
+ new ExplicitCCastExpr(Context->getObjCIdType(),
+ Cls, Context->getObjCIdType(),
+ SourceLocation()));
// struct objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
llvm::SmallVector<Expr*, 4> InitExprs;
InitExprs.push_back(
- new ExplicitCastExpr(Context->getObjCIdType(),
+ new ExplicitCCastExpr(Context->getObjCIdType(),
new DeclRefExpr(CurMethodDef->getSelfDecl(),
Context->getObjCIdType(),
- SourceLocation()),
+ SourceLocation()),
+ Context->getObjCIdType(),
SourceLocation())); // set the 'receiver'.
llvm::SmallVector<Expr*, 8> ClsExprs;
ClsExprs.size());
// To turn off a warning, type-cast to 'id'
InitExprs.push_back(
- new ExplicitCastExpr(Context->getObjCIdType(),
- Cls, SourceLocation())); // set 'super class', using objc_getClass().
+ // set 'super class', using objc_getClass().
+ new ExplicitCCastExpr(Context->getObjCIdType(),
+ Cls, Context->getObjCIdType(), SourceLocation()));
// struct objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
} else {
// Remove all type-casts because it may contain objc-style types; e.g.
// Foo<Proto> *.
- while (ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(recExpr))
+ while (ExplicitCCastExpr *CE = dyn_cast<ExplicitCCastExpr>(recExpr))
recExpr = CE->getSubExpr();
- recExpr = new ExplicitCastExpr(Context->getObjCIdType(), recExpr,
- SourceLocation());
+ recExpr = new ExplicitCCastExpr(Context->getObjCIdType(), recExpr,
+ Context->getObjCIdType(),
+ SourceLocation());
MsgExprs.push_back(recExpr);
}
}
// Make all implicit casts explicit...ICE comes in handy:-)
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
// Reuse the ICE type, it is exactly what the doctor ordered.
- userExpr = new ExplicitCastExpr(ICE->getType()->isObjCQualifiedIdType()
+ QualType type = ICE->getType()->isObjCQualifiedIdType()
? Context->getObjCIdType()
- : ICE->getType(), userExpr, SourceLocation());
+ : ICE->getType();
+ userExpr = new ExplicitCCastExpr(type, userExpr, type, SourceLocation());
}
// Make id<P...> cast into an 'id' cast.
- else if (ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(userExpr)) {
+ else if (ExplicitCCastExpr *CE = dyn_cast<ExplicitCCastExpr>(userExpr)) {
if (CE->getType()->isObjCQualifiedIdType()) {
- while ((CE = dyn_cast<ExplicitCastExpr>(userExpr)))
+ while ((CE = dyn_cast<ExplicitCCastExpr>(userExpr)))
userExpr = CE->getSubExpr();
- userExpr = new ExplicitCastExpr(Context->getObjCIdType(),
- userExpr, SourceLocation());
+ userExpr = new ExplicitCCastExpr(Context->getObjCIdType(),
+ userExpr, Context->getObjCIdType(),
+ SourceLocation());
}
}
MsgExprs.push_back(userExpr);
// If we don't do this cast, we get the following bizarre warning/note:
// xx.m:13: warning: function called through a non-compatible type
// xx.m:13: note: if this code is reached, the program will abort
- cast = new ExplicitCastExpr(Context->getPointerType(Context->VoidTy), DRE,
- SourceLocation());
+ cast = new ExplicitCCastExpr(Context->getPointerType(Context->VoidTy), DRE,
+ Context->getPointerType(Context->VoidTy),
+ SourceLocation());
// Now do the "normal" pointer to function cast.
QualType castType = Context->getFunctionType(returnType,
// If we don't have a method decl, force a variadic cast.
Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0);
castType = Context->getPointerType(castType);
- cast = new ExplicitCastExpr(castType, cast, SourceLocation());
+ cast = new ExplicitCCastExpr(castType, cast, castType, SourceLocation());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
DeclRefExpr *STDRE = new DeclRefExpr(MsgSendStretFlavor, msgSendType,
SourceLocation());
// Need to cast objc_msgSend_stret to "void *" (see above comment).
- cast = new ExplicitCastExpr(Context->getPointerType(Context->VoidTy), STDRE,
- SourceLocation());
+ cast = new ExplicitCCastExpr(Context->getPointerType(Context->VoidTy), STDRE,
+ Context->getPointerType(Context->VoidTy),
+ SourceLocation());
// Now do the "normal" pointer to function cast.
castType = Context->getFunctionType(returnType,
&ArgTypes[0], ArgTypes.size(),
Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0);
castType = Context->getPointerType(castType);
- cast = new ExplicitCastExpr(castType, cast, SourceLocation());
+ cast = new ExplicitCCastExpr(castType, cast, castType, SourceLocation());
// Don't forget the parens to enforce the proper binding.
PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
static CompoundLiteralExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
-/// CastExpr - Base class for Cast Operators (explicit, implicit, etc.).
-/// Classes that derive from CastExpr are:
-///
-/// ImplicitCastExpr
-/// ExplicitCastExpr
-///
+/// CastExpr - Base class for type casts, including both implicit
+/// casts (ImplicitCastExpr) and explicit casts that have some
+/// representation in the source code (ExplicitCastExpr's derived
+/// classes).
class CastExpr : public Expr {
Stmt *Op;
protected:
switch (T->getStmtClass()) {
case ImplicitCastExprClass:
case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
+ case CXXNamedCastExprClass:
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
case CXXFunctionalCastExprClass:
return true;
default:
virtual child_iterator child_end();
};
-/// ImplicitCastExpr - Allows us to explicitly represent implicit type
-/// conversions. For example: converting T[]->T*, void f()->void (*f)(),
-/// float->double, short->int, etc.
+/// ImplicitCastExpr - Allows us to explicitly represent implicit type
+/// conversions, which have no direct representation in the original
+/// source code. For example: converting T[]->T*, void f()->void
+/// (*f)(), float->double, short->int, etc.
///
class ImplicitCastExpr : public CastExpr {
public:
static ImplicitCastExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
-/// ExplicitCastExpr - [C99 6.5.4] Cast Operators.
+/// ExplicitCastExpr - An explicit cast written in the source
+/// code.
+///
+/// This class is effectively an abstract class, because it provides
+/// the basic representation of an explicitly-written cast without
+/// specifying which kind of cast (C cast, functional cast, static
+/// cast, etc.) was written; specific derived classes represent the
+/// particular style of cast and its location information.
///
+/// Unlike implicit casts, explicit cast nodes have two different
+/// types: the type that was written into the source code, and the
+/// actual type of the expression as determined by semantic
+/// analysis. These types may differ slightly. For example, in C++ one
+/// can cast to a reference type, which indicates that the resulting
+/// expression will be an lvalue. The reference type, however, will
+/// not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
+ /// TypeAsWritten - The type that this expression is casting to, as
+ /// written in the source code.
+ QualType TypeAsWritten;
+
+protected:
+ ExplicitCastExpr(StmtClass SC, QualType exprTy, Expr *op, QualType writtenTy) :
+ CastExpr(SC, exprTy, op), TypeAsWritten(writtenTy) {}
+
+public:
+ /// getTypeAsWritten - Returns the type that this expression is
+ /// casting to, as written in the source code.
+ QualType getTypeAsWritten() const { return TypeAsWritten; }
+
+ static bool classof(const Stmt *T) {
+ switch (T->getStmtClass()) {
+ case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
+ case CXXFunctionalCastExprClass:
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const ExplicitCastExpr *) { return true; }
+};
+
+/// ExplicitCCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
+/// cast in C++ (C++ [expr.cast]), which uses the syntax
+/// (Type)expr. For example: @c (int)f.
+class ExplicitCCastExpr : public ExplicitCastExpr {
SourceLocation Loc; // the location of the left paren
public:
- ExplicitCastExpr(QualType ty, Expr *op, SourceLocation l) :
- CastExpr(ExplicitCastExprClass, ty, op), Loc(l) {}
+ ExplicitCCastExpr(QualType exprTy, Expr *op, QualType writtenTy,
+ SourceLocation l) :
+ ExplicitCastExpr(ExplicitCCastExprClass, exprTy, op, writtenTy), Loc(l) {}
SourceLocation getLParenLoc() const { return Loc; }
return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
}
static bool classof(const Stmt *T) {
- return T->getStmtClass() == ExplicitCastExprClass;
+ return T->getStmtClass() == ExplicitCCastExprClass;
}
- static bool classof(const ExplicitCastExpr *) { return true; }
+ static bool classof(const ExplicitCCastExpr *) { return true; }
virtual void EmitImpl(llvm::Serializer& S) const;
- static ExplicitCastExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+ static ExplicitCCastExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
class BinaryOperator : public Expr {
// C++ Expressions.
//===--------------------------------------------------------------------===//
-/// CXXCastExpr - [C++ 5.2.7, 5.2.9, 5.2.10, 5.2.11] C++ Cast Operators.
-///
-class CXXCastExpr : public Expr {
-public:
- enum Opcode {
- DynamicCast,
- StaticCast,
- ReinterpretCast,
- ConstCast
- };
+/// CXXNamedCastExpr - Abstract class common to all of the C++ "named"
+/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
+/// const_cast.
+///
+/// This abstract class is inherited by all of the classes
+/// representing "named" casts, e.g., CXXStaticCastExpr,
+/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr.
+class CXXNamedCastExpr : public ExplicitCastExpr {
private:
- QualType Ty;
- Opcode Opc;
- Stmt *Op;
SourceLocation Loc; // the location of the casting op
+
+protected:
+ CXXNamedCastExpr(StmtClass SC, QualType ty, Expr *op, QualType writtenTy,
+ SourceLocation l)
+ : ExplicitCastExpr(SC, ty, op, writtenTy), Loc(l) {}
+
public:
- CXXCastExpr(Opcode op, QualType ty, Expr *expr, SourceLocation l)
- : Expr(CXXCastExprClass, ty), Ty(ty), Opc(op), Op(expr), Loc(l) {}
-
- QualType getDestType() const { return Ty; }
- Expr *getSubExpr() const { return cast<Expr>(Op); }
-
- Opcode getOpcode() const { return Opc; }
-
- /// getOpcodeStr - Turn an Opcode enum value into the string it represents,
- /// e.g. "reinterpret_cast".
- static const char *getOpcodeStr(Opcode Op) {
- // FIXME: move out of line.
- switch (Op) {
- default: assert(0 && "Not a C++ cast expression");
- case CXXCastExpr::ConstCast: return "const_cast";
- case CXXCastExpr::DynamicCast: return "dynamic_cast";
- case CXXCastExpr::ReinterpretCast: return "reinterpret_cast";
- case CXXCastExpr::StaticCast: return "static_cast";
- }
- }
-
+ const char *getCastName() const;
+
virtual SourceRange getSourceRange() const {
return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
}
static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXCastExprClass;
+ switch (T->getStmtClass()) {
+ case CXXNamedCastExprClass:
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
+ return true;
+ default:
+ return false;
+ }
}
- static bool classof(const CXXCastExpr *) { return true; }
+ static bool classof(const CXXNamedCastExpr *) { return true; }
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
+ virtual void EmitImpl(llvm::Serializer& S) const;
+ static CXXNamedCastExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C,
+ StmtClass SC);
+};
+
+/// CXXStaticCastExpr - A C++ @c static_cast expression (C++ [expr.static.cast]).
+///
+/// This expression node represents a C++ static cast, e.g.,
+/// @c static_cast<int>(1.0).
+class CXXStaticCastExpr : public CXXNamedCastExpr {
+public:
+ CXXStaticCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXStaticCastExprClass;
+ }
+ static bool classof(const CXXStaticCastExpr *) { return true; }
+};
+
+/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression
+/// (C++ [expr.dynamic.cast]), which may perform a run-time check to
+/// determine how to perform the type cast.
+///
+/// This expression node represents a dynamic cast, e.g.,
+/// @c dynamic_cast<Derived*>(BasePtr).
+class CXXDynamicCastExpr : public CXXNamedCastExpr {
+public:
+ CXXDynamicCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDynamicCastExprClass;
+ }
+ static bool classof(const CXXDynamicCastExpr *) { return true; }
+};
+
+/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++
+/// [expr.reinterpret.cast]), which provides a differently-typed view
+/// of a value but performs no actual work at run time.
+///
+/// This expression node represents a reinterpret cast, e.g.,
+/// @c reinterpret_cast<int>(VoidPtr).
+class CXXReinterpretCastExpr : public CXXNamedCastExpr {
+public:
+ CXXReinterpretCastExpr(QualType ty, Expr *op, QualType writtenTy,
+ SourceLocation l)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXReinterpretCastExprClass;
+ }
+ static bool classof(const CXXReinterpretCastExpr *) { return true; }
+};
+
+/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]),
+/// which can remove type qualifiers but does not change the underlying value.
+///
+/// This expression node represents a const cast, e.g.,
+/// @c const_cast<char*>(PtrToConstChar).
+class CXXConstCastExpr : public CXXNamedCastExpr {
+public:
+ CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy,
+ SourceLocation l)
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConstCastExprClass;
+ }
+ static bool classof(const CXXConstCastExpr *) { return true; }
};
/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal.
ASTContext& C);
};
-/// CXXFunctionalCastExpr - [C++ 5.2.3p1] Explicit type conversion
-/// (functional notation).
-/// Example: "x = int(0.5);"
-///
-class CXXFunctionalCastExpr : public CastExpr {
+/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion
+/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c
+/// x = int(0.5);
+class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
- CXXFunctionalCastExpr(QualType ty, SourceLocation tyBeginLoc, Expr *castExpr,
+ CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
+ SourceLocation tyBeginLoc, Expr *castExpr,
SourceLocation rParenLoc) :
- CastExpr(CXXFunctionalCastExprClass, ty, castExpr),
+ ExplicitCastExpr(CXXFunctionalCastExprClass, ty, castExpr, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
STMT(48, ConditionalOperator , Expr)
STMT(49, ImplicitCastExpr , CastExpr)
STMT(50, ExplicitCastExpr , CastExpr)
-STMT(51, CompoundLiteralExpr , Expr)
-STMT(52, ExtVectorElementExpr , Expr)
-STMT(53, InitListExpr , Expr)
-STMT(54, VAArgExpr , Expr)
+STMT(51, ExplicitCCastExpr , ExplicitCastExpr)
+STMT(52, CompoundLiteralExpr , Expr)
+STMT(53, ExtVectorElementExpr , Expr)
+STMT(54, InitListExpr , Expr)
+STMT(55, VAArgExpr , Expr)
// GNU Extensions.
-STMT(55, AddrLabelExpr , Expr)
-STMT(56, StmtExpr , Expr)
-STMT(57, TypesCompatibleExpr , Expr)
-STMT(58, ChooseExpr , Expr)
+STMT(56, AddrLabelExpr , Expr)
+STMT(57, StmtExpr , Expr)
+STMT(58, TypesCompatibleExpr , Expr)
+STMT(59, ChooseExpr , Expr)
// C++ Expressions.
-STMT(60, CXXCastExpr , Expr)
-STMT(61, CXXBoolLiteralExpr , Expr)
-STMT(62, CXXThrowExpr , Expr)
-STMT(63, CXXDefaultArgExpr , Expr)
-STMT(64, CXXFunctionalCastExpr, CastExpr)
-STMT(65, CXXZeroInitValueExpr , Expr)
-STMT(66, CXXConditionDeclExpr , DeclRefExpr)
+STMT(60, CXXNamedCastExpr , ExplicitCastExpr)
+STMT(61, CXXStaticCastExpr , CXXNamedCastExpr)
+STMT(62, CXXDynamicCastExpr , CXXNamedCastExpr)
+STMT(63, CXXReinterpretCastExpr , CXXNamedCastExpr)
+STMT(64, CXXConstCastExpr , CXXNamedCastExpr)
+STMT(65, CXXBoolLiteralExpr , Expr)
+STMT(66, CXXThrowExpr , Expr)
+STMT(67, CXXDefaultArgExpr , Expr)
+STMT(68, CXXFunctionalCastExpr , Expr)
+STMT(69, CXXZeroInitValueExpr , Expr)
+STMT(70, CXXConditionDeclExpr , DeclRefExpr)
// Obj-C Expressions.
-STMT(70, ObjCStringLiteral , Expr)
-STMT(71, ObjCEncodeExpr , Expr)
-STMT(72, ObjCMessageExpr , Expr)
-STMT(73, ObjCSelectorExpr , Expr)
-STMT(74, ObjCProtocolExpr , Expr)
-STMT(75, ObjCIvarRefExpr , Expr)
-STMT(76, ObjCPropertyRefExpr , Expr)
+STMT(80, ObjCStringLiteral , Expr)
+STMT(81, ObjCEncodeExpr , Expr)
+STMT(82, ObjCMessageExpr , Expr)
+STMT(83, ObjCSelectorExpr , Expr)
+STMT(84, ObjCProtocolExpr , Expr)
+STMT(85, ObjCIvarRefExpr , Expr)
+STMT(86, ObjCPropertyRefExpr , Expr)
// Clang Extensions.
-STMT(77, OverloadExpr , Expr)
-STMT(78, ShuffleVectorExpr , Expr)
-STMT(79, BlockExpr , Expr)
-STMT(80, BlockDeclRefExpr , Expr)
+STMT(90, OverloadExpr , Expr)
+STMT(91, ShuffleVectorExpr , Expr)
+STMT(92, BlockExpr , Expr)
+STMT(93, BlockDeclRefExpr , Expr)
-LAST_EXPR(80)
+LAST_EXPR(93)
#undef STMT
#undef FIRST_STMT
//===------------------------- C++ Expressions --------------------------===//
- /// ActOnCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
- virtual ExprResult ActOnCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc, TypeTy *Ty,
- SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc, ExprTy *Op,
- SourceLocation RParenLoc) {
+ /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ virtual ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc, TypeTy *Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc, ExprTy *Op,
+ SourceLocation RParenLoc) {
return 0;
}
return E->hasLocalSideEffect();
return false;
}
- case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
case CXXFunctionalCastExprClass:
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.
return true;
}
case ImplicitCastExprClass:
- case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
case CXXFunctionalCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(this)->getSubExpr();
SourceLocation CastLoc = getLocStart();
break;
}
case ImplicitCastExprClass:
- case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
case CXXFunctionalCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(this)->getSubExpr();
SourceLocation CastLoc = getLocStart();
//===----------------------------------------------------------------------===//
-// CXXCastExpr
-Stmt::child_iterator CXXCastExpr::child_begin() { return &Op; }
-Stmt::child_iterator CXXCastExpr::child_end() { return &Op+1; }
-
// CXXBoolLiteralExpr
Stmt::child_iterator CXXBoolLiteralExpr::child_begin() {
return child_iterator();
Stmt::child_iterator CXXConditionDeclExpr::child_end() {
return child_iterator();
}
+
+//===----------------------------------------------------------------------===//
+// Named casts
+//===----------------------------------------------------------------------===//
+
+/// getCastName - Get the name of the C++ cast being used, e.g.,
+/// "static_cast", "dynamic_cast", "reinterpret_cast", or
+/// "const_cast". The returned pointer must not be freed.
+const char *CXXNamedCastExpr::getCastName() const {
+ switch (getStmtClass()) {
+ case CXXStaticCastExprClass: return "static_cast";
+ case CXXDynamicCastExprClass: return "dynamic_cast";
+ case CXXReinterpretCastExprClass: return "reinterpret_cast";
+ case CXXConstCastExprClass: return "const_cast";
+ default: return "<invalid cast>";
+ }
+}
void VisitTypesCompatibleExpr(TypesCompatibleExpr *Node);
// C++
- void VisitCXXCastExpr(CXXCastExpr *Node);
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
+ void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
// ObjC
void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
// C++ Expressions
//===----------------------------------------------------------------------===//
-void StmtDumper::VisitCXXCastExpr(CXXCastExpr *Node) {
+void StmtDumper::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
DumpExpr(Node);
- fprintf(F, " %s", CXXCastExpr::getOpcodeStr(Node->getOpcode()));
+ fprintf(F, " %s<%s>", Node->getCastName(),
+ Node->getTypeAsWritten().getAsString().c_str());
}
void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
fprintf(F, " %s", Node->getValue() ? "true" : "false");
}
+void StmtDumper::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
+ DumpExpr(Node);
+ fprintf(F, " functional cast to %s",
+ Node->getTypeAsWritten().getAsString().c_str());
+}
+
//===----------------------------------------------------------------------===//
// Obj-C Expressions
//===----------------------------------------------------------------------===//
void StmtPrinter::VisitCastExpr(CastExpr *) {
assert(0 && "CastExpr is an abstract class");
}
-void StmtPrinter::VisitExplicitCastExpr(ExplicitCastExpr *Node) {
+void StmtPrinter::VisitExplicitCastExpr(ExplicitCastExpr *) {
+ assert(0 && "ExplicitCastExpr is an abstract class");
+}
+void StmtPrinter::VisitExplicitCCastExpr(ExplicitCCastExpr *Node) {
OS << "(" << Node->getType().getAsString() << ")";
PrintExpr(Node->getSubExpr());
}
// C++
-void StmtPrinter::VisitCXXCastExpr(CXXCastExpr *Node) {
- OS << CXXCastExpr::getOpcodeStr(Node->getOpcode()) << '<';
- OS << Node->getDestType().getAsString() << ">(";
+void StmtPrinter::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
+ OS << Node->getCastName() << '<';
+ OS << Node->getTypeAsWritten().getAsString() << ">(";
PrintExpr(Node->getSubExpr());
OS << ")";
}
+void StmtPrinter::VisitCXXStaticCastExpr(CXXStaticCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
+void StmtPrinter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
+void StmtPrinter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
+void StmtPrinter::VisitCXXConstCastExpr(CXXConstCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
OS << (Node->getValue() ? "true" : "false");
}
case ImplicitCastExprClass:
return ImplicitCastExpr::CreateImpl(D, C);
- case ExplicitCastExprClass:
- return ExplicitCastExpr::CreateImpl(D, C);
+ case ExplicitCCastExprClass:
+ return ExplicitCCastExpr::CreateImpl(D, C);
case IndirectGotoStmtClass:
return IndirectGotoStmt::CreateImpl(D, C);
case CXXFunctionalCastExprClass:
return CXXFunctionalCastExpr::CreateImpl(D, C);
+ case CXXStaticCastExprClass:
+ return CXXStaticCastExpr::CreateImpl(D, C, SC);
+
+ case CXXDynamicCastExprClass:
+ return CXXDynamicCastExpr::CreateImpl(D, C, SC);
+
+ case CXXReinterpretCastExprClass:
+ return CXXReinterpretCastExpr::CreateImpl(D, C, SC);
+
+ case CXXConstCastExprClass:
+ return CXXConstCastExpr::CreateImpl(D, C, SC);
+
case CXXZeroInitValueExprClass:
return CXXZeroInitValueExpr::CreateImpl(D, C);
}
return stmt;
}
-void ExplicitCastExpr::EmitImpl(Serializer& S) const {
+void ExplicitCCastExpr::EmitImpl(Serializer& S) const {
S.Emit(getType());
+ S.Emit(getTypeAsWritten());
S.Emit(Loc);
S.EmitOwnedPtr(getSubExpr());
}
-ExplicitCastExpr* ExplicitCastExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+ExplicitCCastExpr* ExplicitCCastExpr::CreateImpl(Deserializer& D, ASTContext& C) {
QualType t = QualType::ReadVal(D);
+ QualType writtenTy = QualType::ReadVal(D);
SourceLocation Loc = SourceLocation::ReadVal(D);
Expr* Op = D.ReadOwnedPtr<Expr>(C);
- return new ExplicitCastExpr(t,Op,Loc);
+ return new ExplicitCCastExpr(t,Op,writtenTy,Loc);
}
-
void CharacterLiteral::EmitImpl(Serializer& S) const {
S.Emit(Value);
void CXXFunctionalCastExpr::EmitImpl(Serializer& S) const {
S.Emit(getType());
+ S.Emit(getTypeAsWritten());
S.Emit(TyBeginLoc);
S.Emit(RParenLoc);
S.EmitOwnedPtr(getSubExpr());
CXXFunctionalCastExpr *
CXXFunctionalCastExpr::CreateImpl(Deserializer& D, ASTContext& C) {
QualType Ty = QualType::ReadVal(D);
+ QualType WrittenTy = QualType::ReadVal(D);
SourceLocation TyBeginLoc = SourceLocation::ReadVal(D);
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
Expr* SubExpr = D.ReadOwnedPtr<Expr>(C);
- return new CXXFunctionalCastExpr(Ty, TyBeginLoc, SubExpr, RParenLoc);
+ return new CXXFunctionalCastExpr(Ty, WrittenTy, TyBeginLoc, SubExpr, RParenLoc);
+}
+
+void CXXNamedCastExpr::EmitImpl(Serializer& S) const {
+ S.Emit(getType());
+ S.Emit(getTypeAsWritten());
+ S.Emit(Loc);
+ S.EmitOwnedPtr(getSubExpr());
+}
+
+CXXNamedCastExpr *
+CXXNamedCastExpr::CreateImpl(Deserializer& D, ASTContext& C, StmtClass SC) {
+ QualType Ty = QualType::ReadVal(D);
+ QualType WrittenTy = QualType::ReadVal(D);
+ SourceLocation Loc = SourceLocation::ReadVal(D);
+ Expr* SubExpr = D.ReadOwnedPtr<Expr>(C);
+ switch (SC) {
+ case CXXStaticCastExprClass:
+ return new CXXStaticCastExpr(Ty, SubExpr, WrittenTy, Loc);
+ case CXXDynamicCastExprClass:
+ return new CXXDynamicCastExpr(Ty, SubExpr, WrittenTy, Loc);
+ case CXXReinterpretCastExprClass:
+ return new CXXReinterpretCastExpr(Ty, SubExpr, WrittenTy, Loc);
+ case CXXConstCastExprClass:
+ return new CXXConstCastExpr(Ty, SubExpr, WrittenTy, Loc);
+ default:
+ assert(false && "Unknown cast type!");
+ return 0;
+ }
}
void CXXZeroInitValueExpr::EmitImpl(Serializer& S) const {
// subexpression that has a value.
case Stmt::ImplicitCastExprClass:
- case Stmt::ExplicitCastExprClass: {
+ case Stmt::ExplicitCCastExprClass: {
CastExpr* C = cast<CastExpr>(E);
QualType CT = C->getType();
QualType ST = C->getSubExpr()->getType();
break;
case Stmt::ImplicitCastExprClass:
- case Stmt::ExplicitCastExprClass: {
+ case Stmt::ExplicitCCastExprClass: {
CastExpr* C = cast<CastExpr>(S);
VisitCast(C, C->getSubExpr(), Pred, Dst);
break;
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
+ if (const ExplicitCastExpr *ExCast = dyn_cast_or_null<ExplicitCastExpr>(CastE))
+ T = ExCast->getTypeAsWritten();
+
if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType())
VisitLValue(Ex, Pred, S1);
else
ExprResult Result = ParseSimpleParenExpression(RParenLoc);
if (!Result.isInvalid)
- Result = Actions.ActOnCXXCasts(OpLoc, Kind,
- LAngleBracketLoc, CastTy, RAngleBracketLoc,
- LParenLoc, Result.Val, RParenLoc);
+ Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
+ LAngleBracketLoc, CastTy, RAngleBracketLoc,
+ LParenLoc, Result.Val, RParenLoc);
return Result;
}
SourceLocation *CommaLocs,
SourceLocation RParenLoc);
- /// ActOnCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
- virtual ExprResult ActOnCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc, TypeTy *Ty,
- SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc, ExprTy *E,
- SourceLocation RParenLoc);
+ /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ virtual ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc, TypeTy *Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc, ExprTy *E,
+ SourceLocation RParenLoc);
// Helpers for ActOnCXXCasts
bool CastsAwayConstness(QualType SrcType, QualType DestType);
}
// Perform checking for stack values returned by reference.
else if (lhsType->isReferenceType()) {
- // Check for an implicit cast to a reference.
- if (ImplicitCastExpr *I = dyn_cast<ImplicitCastExpr>(RetValExp))
- if (DeclRefExpr *DR = EvalVal(I->getSubExpr()))
- Diag(DR->getLocStart(), diag::warn_ret_stack_ref,
- DR->getDecl()->getIdentifier()->getName(),
- RetValExp->getSourceRange());
+ // Check for a reference to the stack
+ if (DeclRefExpr *DR = EvalVal(RetValExp))
+ Diag(DR->getLocStart(), diag::warn_ret_stack_ref,
+ DR->getDecl()->getIdentifier()->getName(),
+ RetValExp->getSourceRange());
}
}
// For casts, we need to handle conversions from arrays to
// pointer values, and pointer-to-pointer conversions.
- case Stmt::ExplicitCastExprClass:
- case Stmt::ImplicitCastExprClass: {
-
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::ExplicitCCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass: {
Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
QualType T = SubExpr->getType();
// C++ casts. For dynamic casts, static casts, and const casts, we
// are always converting from a pointer-to-pointer, so we just blow
- // through the cast. In the case the dynamic cast doesn't fail
- // (and return NULL), we take the conservative route and report cases
+ // through the cast. In the case the dynamic cast doesn't fail (and
+ // return NULL), we take the conservative route and report cases
// where we return the address of a stack variable. For Reinterpre
- case Stmt::CXXCastExprClass: {
- CXXCastExpr *C = cast<CXXCastExpr>(E);
-
- if (C->getOpcode() == CXXCastExpr::ReinterpretCast) {
- Expr *S = C->getSubExpr();
+ // FIXME: The comment about is wrong; we're not always converting
+ // from pointer to pointer. I'm guessing that this code should also
+ // handle references to objects.
+ case Stmt::CXXStaticCastExprClass:
+ case Stmt::CXXDynamicCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass: {
+ Expr *S = cast<CXXNamedCastExpr>(E)->getSubExpr();
if (S->getType()->isPointerType() || S->getType()->isBlockPointerType())
return EvalAddr(S);
else
return NULL;
- }
- else
- return EvalAddr(C->getSubExpr());
}
// Everything else: we simply don't reason about them.
CheckArithmeticConstantExpression(IExp);
}
case Expr::ImplicitCastExprClass:
- case Expr::ExplicitCastExprClass: {
+ case Expr::ExplicitCCastExprClass: {
const Expr* SubExpr = cast<CastExpr>(Init)->getSubExpr();
if (Init->getStmtClass() == Expr::ImplicitCastExprClass) {
// Check for implicit promotion
// if we don't, we'll figure it out later
return 0;
}
- case Expr::ExplicitCastExprClass: {
+ case Expr::ExplicitCCastExprClass: {
const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
// Check for pointer->pointer cast
return true;
}
case Expr::ImplicitCastExprClass:
- case Expr::ExplicitCastExprClass: {
+ case Expr::ExplicitCCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(Init)->getSubExpr();
if (SubExpr->getType()->isArithmeticType())
return CheckArithmeticConstantExpression(SubExpr);
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), castType, castExpr))
return true;
- return new ExplicitCastExpr(castType, castExpr, LParenLoc);
+ return new ExplicitCCastExpr(castType, castExpr, castType, LParenLoc);
}
/// Note that lex is not null here, even if this is the gnu "x ?: y" extension.
#include "llvm/Support/Debug.h"
using namespace clang;
-/// ActOnCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
+/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
Action::ExprResult
-Sema::ActOnCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc, TypeTy *Ty,
- SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc, ExprTy *E,
- SourceLocation RParenLoc) {
- CXXCastExpr::Opcode Op;
+Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc, TypeTy *Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc, ExprTy *E,
+ SourceLocation RParenLoc) {
Expr *Ex = (Expr*)E;
QualType DestType = QualType::getFromOpaquePtr(Ty);
switch (Kind) {
default: assert(0 && "Unknown C++ cast!");
+
case tok::kw_const_cast:
- Op = CXXCastExpr::ConstCast;
CheckConstCast(OpLoc, Ex, DestType);
- break;
+ return new CXXConstCastExpr(DestType.getNonReferenceType(), Ex,
+ DestType, OpLoc);
+
case tok::kw_dynamic_cast:
- Op = CXXCastExpr::DynamicCast;
- break;
+ return new CXXDynamicCastExpr(DestType.getNonReferenceType(), Ex,
+ DestType, OpLoc);
+
case tok::kw_reinterpret_cast:
- Op = CXXCastExpr::ReinterpretCast;
CheckReinterpretCast(OpLoc, Ex, DestType);
- break;
+ return new CXXReinterpretCastExpr(DestType.getNonReferenceType(), Ex,
+ DestType, OpLoc);
+
case tok::kw_static_cast:
- Op = CXXCastExpr::StaticCast;
- break;
+ return new CXXStaticCastExpr(DestType.getNonReferenceType(), Ex,
+ DestType, OpLoc);
}
- return new CXXCastExpr(Op, DestType, Ex, OpLoc);
+ return true;
}
/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid.
if (NumExprs == 1) {
if (CheckCastTypes(TypeRange, Ty, Exprs[0]))
return true;
- return new CXXFunctionalCastExpr(Ty, TyBeginLoc, Exprs[0], RParenLoc);
+ return new CXXFunctionalCastExpr(Ty.getNonReferenceType(), Ty, TyBeginLoc,
+ Exprs[0], RParenLoc);
}
// C++ 5.2.3p1:
// RUN: clang -fsyntax-only -verify %s
-
int* ret_local() {
int x = 1;
return &x; // expected-warning {{address of stack memory}}