aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-07-15 02:02:06 +0000
committerSteve Naroff <snaroff@apple.com>2007-07-15 02:02:06 +0000
commitfa2eaabd304172dd8afc561f6156a65f8d0e442b (patch)
tree15ce0e774aaecaf120ea8c80d3ebca1aaa3c65be
parentc3f893748348ae71a2c61fbfcd1bd4cbe12d10e7 (diff)
This is the final step/commit for implementing exlicit implicit casts. Unlike the
previous two checkins, which involved lot's of tedious refactoring, this checkin is nice and clean:-) - Hacked UsualUnaryConversions, UsualArithmeticConversions, and DefaultFunctionArrayConversion to create the AST node (using a helper function promoteExprToType). - Added a setType method to Expr. - Changed Expr::isIntegerConstantExpr to allow for the new node. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39866 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--AST/Expr.cpp3
-rw-r--r--Sema/SemaExpr.cpp63
-rw-r--r--include/clang/AST/Expr.h1
3 files changed, 45 insertions, 22 deletions
diff --git a/AST/Expr.cpp b/AST/Expr.cpp
index e22e80e76e..7638d21ed5 100644
--- a/AST/Expr.cpp
+++ b/AST/Expr.cpp
@@ -278,6 +278,9 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, SourceLocation *Loc,
default:
if (Loc) *Loc = getLocStart();
return false;
+ case ImplicitCastExprClass:
+ return cast<ImplicitCastExpr>(this)->getSubExpr()->
+ isIntegerConstantExpr(Result, Loc, isEvaluated);
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()->
isIntegerConstantExpr(Result, Loc, isEvaluated);
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 60b07a7915..cde73ce7d6 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -567,14 +567,25 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result);
}
-QualType Sema::DefaultFunctionArrayConversion(Expr *&expr) {
- QualType t = expr->getType();
+// promoteExprToType - a helper function to ensure we create exactly one
+// ImplicitCastExpr. As a convenience (to the caller), we return the type.
+static QualType promoteExprToType(Expr *&expr, QualType type) {
+ if (ImplicitCastExpr *impCast = dyn_cast<ImplicitCastExpr>(expr))
+ impCast->setType(type);
+ else
+ expr = new ImplicitCastExpr(type, expr);
+ return type;
+}
+
+/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
+QualType Sema::DefaultFunctionArrayConversion(Expr *&e) {
+ QualType t = e->getType();
assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
- if (t->isFunctionType()) // C99 6.3.2.1p4
- return Context.getPointerType(t);
+ if (t->isFunctionType())
+ return promoteExprToType(e, Context.getPointerType(t));
if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
- return Context.getPointerType(ary->getElementType()); // C99 6.3.2.1p3
+ return promoteExprToType(e, Context.getPointerType(ary->getElementType()));
return t;
}
@@ -587,10 +598,8 @@ QualType Sema::UsualUnaryConversions(Expr *&expr) {
QualType t = expr->getType();
assert(!t.isNull() && "UsualUnaryConversions - missing type");
- if (t->isPromotableIntegerType()) { // C99 6.3.1.1p2
- // expr = new ImplicitCastExpr(Context.IntTy, expr);
- return Context.IntTy;
- }
+ if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
+ return promoteExprToType(expr, Context.IntTy);
return DefaultFunctionArrayConversion(expr);
}
@@ -619,26 +628,36 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
// Handle complex types first (C99 6.3.1.8p1).
if (lhs->isComplexType() || rhs->isComplexType()) {
// if we have an integer operand, the result is the complex type.
- if (rhs->isIntegerType())
- return lhs;
- if (lhs->isIntegerType())
- return rhs;
+ if (rhs->isIntegerType()) // convert the rhs to the lhs complex type.
+ return promoteExprToType(rhsExpr, lhs);
+
+ if (lhs->isIntegerType()) // convert the lhs to the rhs complex type.
+ return promoteExprToType(lhsExpr, rhs);
- return Context.maxComplexType(lhs, rhs);
+ // Two complex types. Convert the smaller operand to the bigger result.
+ if (Context.maxComplexType(lhs, rhs) == lhs) // convert the rhs
+ return promoteExprToType(rhsExpr, lhs);
+ return promoteExprToType(lhsExpr, rhs); // convert the lhs
}
-
// Now handle "real" floating types (i.e. float, double, long double).
if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) {
// if we have an integer operand, the result is the real floating type.
- if (rhs->isIntegerType())
- return lhs;
- if (lhs->isIntegerType())
- return rhs;
+ if (rhs->isIntegerType()) // convert the rhs to the lhs floating point type.
+ return promoteExprToType(rhsExpr, lhs);
+
+ if (lhs->isIntegerType()) // convert the lhs to the rhs floating point type.
+ return promoteExprToType(lhsExpr, rhs);
- // we have two real floating types, float/complex combos were handled above.
- return Context.maxFloatingType(lhs, rhs);
+ // We have two real floating types, float/complex combos were handled above.
+ // Convert the smaller operand to the bigger result.
+ if (Context.maxFloatingType(lhs, rhs) == lhs) // convert the rhs
+ return promoteExprToType(rhsExpr, lhs);
+ return promoteExprToType(lhsExpr, rhs); // convert the lhs
}
- return Context.maxIntegerType(lhs, rhs);
+ // Finally, we have two differing integer types.
+ if (Context.maxIntegerType(lhs, rhs) == lhs) // convert the rhs
+ return promoteExprToType(rhsExpr, lhs);
+ return promoteExprToType(lhsExpr, rhs); // convert the lhs
}
// CheckPointerTypesForAssignment - This is a very tricky routine (despite
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 802f6a6d87..7e288110f5 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -34,6 +34,7 @@ protected:
~Expr() {}
public:
QualType getType() const { return TR; }
+ void setType(QualType t) { TR = t; }
/// SourceLocation tokens are not useful in isolation - they are low level
/// value objects created/interpreted by SourceManager. We assume AST