aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Driver/RewriteObjC.cpp71
-rw-r--r--include/clang/AST/Expr.h84
-rw-r--r--include/clang/AST/ExprCXX.h150
-rw-r--r--include/clang/AST/StmtNodes.def59
-rw-r--r--include/clang/Parse/Action.h12
-rw-r--r--lib/AST/Expr.cpp6
-rw-r--r--lib/AST/ExprCXX.cpp21
-rw-r--r--lib/AST/StmtDumper.cpp14
-rw-r--r--lib/AST/StmtPrinter.cpp27
-rw-r--r--lib/AST/StmtSerialization.cpp57
-rw-r--r--lib/Analysis/Environment.cpp2
-rw-r--r--lib/Analysis/GRExprEngine.cpp5
-rw-r--r--lib/Parse/ParseExprCXX.cpp6
-rw-r--r--lib/Sema/Sema.h12
-rw-r--r--lib/Sema/SemaChecking.cpp37
-rw-r--r--lib/Sema/SemaDecl.cpp6
-rw-r--r--lib/Sema/SemaExpr.cpp2
-rw-r--r--lib/Sema/SemaExprCXX.cpp38
-rw-r--r--test/SemaCXX/return-stack-addr.cpp1
19 files changed, 413 insertions, 197 deletions
diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp
index 37d416ac97..00604726fa 100644
--- a/Driver/RewriteObjC.cpp
+++ b/Driver/RewriteObjC.cpp
@@ -1057,8 +1057,8 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
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(),
@@ -1099,8 +1099,8 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
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);
@@ -1238,7 +1238,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
}
}
- if (ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(S))
+ if (ExplicitCCastExpr *CE = dyn_cast<ExplicitCCastExpr>(S))
RewriteObjCQualifiedInterfaceTypes(CE);
if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
@@ -1559,8 +1559,10 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *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);
@@ -2186,7 +2188,8 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
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;
@@ -2321,9 +2324,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
&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;
@@ -2372,10 +2376,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
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;
@@ -2389,8 +2394,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
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;
@@ -2417,10 +2423,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
} 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);
}
}
@@ -2441,17 +2448,19 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// 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);
@@ -2494,8 +2503,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// 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,
@@ -2503,7 +2513,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// 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);
@@ -2522,14 +2532,15 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
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);
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 28edccee53..70a768171e 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -771,12 +771,10 @@ public:
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:
@@ -791,6 +789,12 @@ public:
switch (T->getStmtClass()) {
case ImplicitCastExprClass:
case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
+ case CXXNamedCastExprClass:
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
case CXXFunctionalCastExprClass:
return true;
default:
@@ -804,9 +808,10 @@ public:
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:
@@ -826,13 +831,62 @@ 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; }
@@ -840,12 +894,12 @@ public:
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 {
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 915c9e000f..ef5f95d09c 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -23,54 +23,112 @@ namespace clang {
// 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.
@@ -170,17 +228,17 @@ public:
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; }
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index ed8861ba99..a79639eac0 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -77,42 +77,47 @@ STMT(47, CompoundAssignOperator, BinaryOperator)
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
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 63f5be704a..8c414e49ae 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -593,12 +593,12 @@ public:
//===------------------------- 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;
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 61ea005793..1380264e0e 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -304,7 +304,7 @@ bool Expr::hasLocalSideEffect() const {
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.
@@ -628,7 +628,7 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
return true;
}
case ImplicitCastExprClass:
- case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
case CXXFunctionalCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(this)->getSubExpr();
SourceLocation CastLoc = getLocStart();
@@ -946,7 +946,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
break;
}
case ImplicitCastExprClass:
- case ExplicitCastExprClass:
+ case ExplicitCCastExprClass:
case CXXFunctionalCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(this)->getSubExpr();
SourceLocation CastLoc = getLocStart();
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 0c374ff5cc..82626d864a 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -25,10 +25,6 @@ void CXXConditionDeclExpr::Destroy(ASTContext& C) {
//===----------------------------------------------------------------------===//
-// 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();
@@ -67,3 +63,20 @@ Stmt::child_iterator CXXConditionDeclExpr::child_begin() {
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>";
+ }
+}
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 666cad6260..349b6fb6e3 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -128,8 +128,9 @@ namespace {
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);
@@ -406,9 +407,10 @@ void StmtDumper::VisitTypesCompatibleExpr(TypesCompatibleExpr *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) {
@@ -416,6 +418,12 @@ 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
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index ba67a97deb..fb6fba399e 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -707,7 +707,10 @@ void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
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());
}
@@ -809,13 +812,29 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
// 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");
}
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index decd9a76c9..bf7cbc5e7b 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -106,8 +106,8 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {
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);
@@ -201,6 +201,18 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& 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);
}
@@ -364,19 +376,20 @@ CaseStmt* CaseStmt::CreateImpl(Deserializer& D, ASTContext& 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);
@@ -1270,6 +1283,7 @@ CXXDefaultArgExpr *CXXDefaultArgExpr::CreateImpl(Deserializer& D, ASTContext& C)
void CXXFunctionalCastExpr::EmitImpl(Serializer& S) const {
S.Emit(getType());
+ S.Emit(getTypeAsWritten());
S.Emit(TyBeginLoc);
S.Emit(RParenLoc);
S.EmitOwnedPtr(getSubExpr());
@@ -1278,10 +1292,39 @@ void CXXFunctionalCastExpr::EmitImpl(Serializer& S) const {
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 {
diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp
index f220ee7a12..a5f158c5d6 100644
--- a/lib/Analysis/Environment.cpp
+++ b/lib/Analysis/Environment.cpp
@@ -47,7 +47,7 @@ SVal Environment::GetSVal(Expr* E, BasicValueFactory& BasicVals) 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();
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 2a74311cd9..282a08c21a 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -345,7 +345,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
break;
case Stmt::ImplicitCastExprClass:
- case Stmt::ExplicitCastExprClass: {
+ case Stmt::ExplicitCCastExprClass: {
CastExpr* C = cast<CastExpr>(S);
VisitCast(C, C->getSubExpr(), Pred, Dst);
break;
@@ -1445,6 +1445,9 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
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
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 8b4db30950..2b9ab55032 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -61,9 +61,9 @@ Parser::ExprResult Parser::ParseCXXCasts() {
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;
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index a2872a2c1a..f84b5c5e71 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -695,12 +695,12 @@ public:
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);
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 27f3abe68a..3365992ff6 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -736,12 +736,11 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
}
// 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());
}
}
@@ -826,9 +825,9 @@ static DeclRefExpr* EvalAddr(Expr *E) {
// 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();
@@ -844,21 +843,21 @@ static DeclRefExpr* EvalAddr(Expr *E) {
// 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.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 624c576103..7b88ec2c16 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1060,7 +1060,7 @@ bool Sema::CheckAddressConstantExpression(const Expr* Init) {
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
@@ -1190,7 +1190,7 @@ static const Expr* FindExpressionBaseAddress(const Expr* E) {
// 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
@@ -1310,7 +1310,7 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
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);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index d1be2a4a27..a73f0dde0a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1333,7 +1333,7 @@ ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
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.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index fa81f118c7..34eff25b4c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -21,36 +21,39 @@
#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.
@@ -437,7 +440,8 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
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:
diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp
index da68c8d77a..9eadac7edd 100644
--- a/test/SemaCXX/return-stack-addr.cpp
+++ b/test/SemaCXX/return-stack-addr.cpp
@@ -1,6 +1,5 @@
// RUN: clang -fsyntax-only -verify %s
-
int* ret_local() {
int x = 1;
return &x; // expected-warning {{address of stack memory}}