From fa2eaabd304172dd8afc561f6156a65f8d0e442b Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Sun, 15 Jul 2007 02:02:06 +0000 Subject: [PATCH] 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 --- AST/Expr.cpp | 3 ++ Sema/SemaExpr.cpp | 63 ++++++++++++++++++++++++++-------------- include/clang/AST/Expr.h | 1 + 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(this)->getSubExpr()-> + isIntegerConstantExpr(Result, Loc, isEvaluated); case ParenExprClass: return cast(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(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(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); - return Context.maxComplexType(lhs, rhs); + if (lhs->isIntegerType()) // convert the lhs to the rhs complex type. + return promoteExprToType(lhsExpr, 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); - // we have two real floating types, float/complex combos were handled above. - return Context.maxFloatingType(lhs, rhs); + 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. + // 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