More changes related to implementing ImplicitCastExpr.

- Fixed a recent regression discovered by Keith Bauer (thanks!). 
The fix involved adding (back) two arguments to UsualArithmeticConversions.
Without the reference arguments, no unary conversions were being passed back
to the caller. This had the effect of turning off the UsualUnaryConversions.
- Refactored CheckAssignmentConstraints into 3 functions. CheckAssignmentConstraints,
CheckSingleAssignmentConstraints, and CheckCompoundAssignmentConstraints. 
- Changed the argument type of DefaultFunctionArrayConversion from QualType->Expr*&.
- Removed a bunch of casts in routines I was working on (cleanup).
- Fixed the visitor for ImplicitCastExpr (oops).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39840 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Steve Naroff 2007-07-13 23:32:42 +00:00
Родитель 692233e90a
Коммит 90045e8eba
5 изменённых файлов: 107 добавлений и 59 удалений

Просмотреть файл

@ -387,7 +387,8 @@ void StmtPrinter::VisitCastExpr(CastExpr *Node) {
PrintExpr(Node->getSubExpr());
}
void StmtPrinter::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
// No need to print anything.
// No need to print anything, simply forward to the sub expression.
PrintExpr(Node->getSubExpr());
}
void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
PrintExpr(Node->getLHS());

Просмотреть файл

@ -271,16 +271,19 @@ private:
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
// functions and arrays to their respective pointers (C99 6.3.2.1)
QualType UsualUnaryConversions(Expr *&expr);
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's
// operands and then handles various conversions that are common to binary
// operators (C99 6.3.1.8). If both operands aren't arithmetic, this
// routine returns the first non-arithmetic type found. The client is
// responsible for emitting appropriate error diagnostics.
QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr);
QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
QualType &lhs, QualType &rhs);
// DefaultFunctionArrayConversion - converts functions and arrays
// to their respective pointers (C99 6.3.2.1). If the type isn't a function
// or array, this routine simply returns the input type (unmodified).
QualType DefaultFunctionArrayConversion(QualType t);
QualType DefaultFunctionArrayConversion(Expr *&expr);
enum AssignmentCheckResult {
Compatible,
@ -290,10 +293,22 @@ private:
IncompatiblePointer,
CompatiblePointerDiscardsQualifiers
};
// CheckAssignmentConstraints - conversions for assignment, argument passing,
// variable initialization, and function return values. Currently used by
// CheckAssignmentOperands, ParseCallExpr, and ParseReturnStmt. C99 6.5.16.
// CheckAssignmentConstraints - Perform type checking for assignment,
// argument passing, variable initialization, and function return values.
// This routine is only used by the following two methods. C99 6.5.16.
AssignmentCheckResult CheckAssignmentConstraints(QualType lhs, QualType rhs);
// CheckSingleAssignmentConstraints - Currently used by ParseCallExpr,
// CheckAssignmentOperands, and ParseReturnStmt. Prior to type checking,
// this routine performs the default function/array converions.
AssignmentCheckResult CheckSingleAssignmentConstraints(QualType lhs,
Expr *&rExpr);
// CheckCompoundAssignmentConstraints - Type check without performing any
// conversions. For compound assignments, the "Check...Operands" methods
// perform the necessary conversions.
AssignmentCheckResult CheckCompoundAssignmentConstraints(QualType lhs,
QualType rhs);
// Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
AssignmentCheckResult CheckPointerTypesForAssignment(QualType lhsType,
QualType rhsType);

Просмотреть файл

@ -278,14 +278,16 @@ Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc,
Action::ExprResult Sema::
ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
ExprTy *Idx, SourceLocation RLoc) {
QualType t1 = ((Expr *)Base)->getType();
QualType t2 = ((Expr *)Idx)->getType();
Expr *lex = (Expr *)Base;
Expr *rex = (Expr *)Idx;
QualType t1 = lex->getType();
QualType t2 = rex->getType();
assert(!t1.isNull() && "no type for array base expression");
assert(!t2.isNull() && "no type for array index expression");
QualType canonT1 = DefaultFunctionArrayConversion(t1).getCanonicalType();
QualType canonT2 = DefaultFunctionArrayConversion(t2).getCanonicalType();
QualType canonT1 = DefaultFunctionArrayConversion(lex).getCanonicalType();
QualType canonT2 = DefaultFunctionArrayConversion(rex).getCanonicalType();
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
@ -297,17 +299,16 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
if (isa<PointerType>(canonT1) || isa<VectorType>(canonT1)) {
baseType = canonT1;
indexType = canonT2;
baseExpr = static_cast<Expr *>(Base);
indexExpr = static_cast<Expr *>(Idx);
baseExpr = lex;
indexExpr = rex;
} else if (isa<PointerType>(canonT2)) { // uncommon
baseType = canonT2;
indexType = canonT1;
baseExpr = static_cast<Expr *>(Idx);
indexExpr = static_cast<Expr *>(Base);
baseExpr = rex;
indexExpr = lex;
} else {
return Diag(static_cast<Expr *>(Base)->getLocStart(),
diag::err_typecheck_subscript_value,
static_cast<Expr *>(Base)->getSourceRange());
return Diag(lex->getLocStart(), diag::err_typecheck_subscript_value,
rex->getSourceRange());
}
// C99 6.5.2.1p1
if (!indexType->isIntegerType()) {
@ -427,8 +428,8 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
if (lhsType == rhsType) // common case, fast path...
continue;
AssignmentCheckResult result = CheckAssignmentConstraints(lhsType,
rhsType);
AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
argExpr);
SourceLocation l = argExpr->getLocStart();
// decode the result (notice that AST's are still created for extensions).
@ -495,7 +496,7 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
}
// now check the two expressions.
if (lexT->isArithmeticType() && rexT->isArithmeticType()) // C99 6.5.15p3,5
return UsualArithmeticConversions(lex, rex);
return UsualArithmeticConversions(lex, rex, lexT, rexT);
if ((lexT->isStructureType() && rexT->isStructureType()) || // C99 6.5.15p3
(lexT->isUnionType() && rexT->isUnionType())) {
@ -565,7 +566,10 @@ Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result);
}
QualType Sema::DefaultFunctionArrayConversion(QualType t) {
QualType Sema::DefaultFunctionArrayConversion(Expr *&expr) {
QualType t = expr->getType();
assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
if (t->isFunctionType()) // C99 6.3.2.1p4
return Context.getPointerType(t);
if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
@ -582,18 +586,21 @@ QualType Sema::UsualUnaryConversions(Expr *&expr) {
QualType t = expr->getType();
assert(!t.isNull() && "UsualUnaryConversions - missing type");
if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
if (t->isPromotableIntegerType()) { // C99 6.3.1.1p2
// expr = new ImplicitCastExpr(Context.IntTy, expr);
return Context.IntTy;
return DefaultFunctionArrayConversion(t);
}
return DefaultFunctionArrayConversion(expr);
}
/// UsualArithmeticConversions - Performs various conversions that are common to
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
/// routine returns the first non-arithmetic type found. The client is
/// responsible for emitting appropriate error diagnostics.
QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr) {
QualType lhs = UsualUnaryConversions(lhsExpr);
QualType rhs = UsualUnaryConversions(rhsExpr);
QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
QualType &lhs, QualType &rhs) {
lhs = UsualUnaryConversions(lhsExpr);
rhs = UsualUnaryConversions(rhsExpr);
// If both types are identical, no conversion is needed.
if (lhs == rhs)
@ -695,12 +702,6 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
///
Sema::AssignmentCheckResult
Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
// This check seems unnatural, however it is necessary to insure the proper
// conversion of functions/arrays. If the conversion were done for all
// DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary
// expressions that surpress this implicit conversion (&, sizeof).
rhsType = DefaultFunctionArrayConversion(rhsType);
if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) {
if (lhsType->isVectorType() || rhsType->isVectorType()) {
if (lhsType.getCanonicalType() != rhsType.getCanonicalType())
@ -730,6 +731,22 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return Incompatible;
}
Sema::AssignmentCheckResult
Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// This check seems unnatural, however it is necessary to insure the proper
// conversion of functions/arrays. If the conversion were done for all
// DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary
// expressions that surpress this implicit conversion (&, sizeof).
QualType rhsType = DefaultFunctionArrayConversion(rExpr);
return CheckAssignmentConstraints(lhsType, rhsType);
}
Sema::AssignmentCheckResult
Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
return CheckAssignmentConstraints(lhsType, rhsType);
}
inline void Sema::InvalidOperands(SourceLocation loc, Expr *&lex, Expr *&rex) {
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString(),
@ -753,10 +770,12 @@ inline QualType Sema::CheckVectorOperands(SourceLocation loc, Expr *&lex,
inline QualType Sema::CheckMultiplyDivideOperands(
Expr *&lex, Expr *&rex, SourceLocation loc)
{
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
QualType lhsType = lex->getType(), rhsType = rex->getType();
if (lhsType->isVectorType() || rhsType->isVectorType())
return CheckVectorOperands(loc, lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
if (resType->isArithmeticType())
return resType;
@ -767,7 +786,9 @@ inline QualType Sema::CheckMultiplyDivideOperands(
inline QualType Sema::CheckRemainderOperands(
Expr *&lex, Expr *&rex, SourceLocation loc)
{
QualType resType = UsualArithmeticConversions(lex, rex);
QualType lhsType = lex->getType(), rhsType = rex->getType();
QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
if (resType->isIntegerType())
return resType;
@ -783,7 +804,7 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
if (lhsType->isVectorType() || rhsType->isVectorType())
return CheckVectorOperands(loc, lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
// handle the common case first (both operands are arithmetic).
if (resType->isArithmeticType())
@ -803,7 +824,8 @@ inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
if (lhsType->isVectorType() || rhsType->isVectorType())
return CheckVectorOperands(loc, lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
// handle the common case first (both operands are arithmetic).
if (resType->isArithmeticType())
@ -822,7 +844,7 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7
// FIXME: Shifts don't perform usual arithmetic conversions. This is wrong
// for int << longlong -> the result type should be int, not long long.
QualType lhsType = lex->getType(), rhsType = rex->getType();
QualType resType = UsualArithmeticConversions(lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
if (resType->isIntegerType())
return resType;
@ -897,7 +919,8 @@ inline QualType Sema::CheckBitwiseOperands(
if (lhsType->isVectorType() || rhsType->isVectorType())
return CheckVectorOperands(loc, lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex);
QualType resType = UsualArithmeticConversions(lex, rex, lhsType, rhsType);
if (resType->isIntegerType())
return resType;
@ -953,7 +976,12 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
if (lhsType == rhsType) // common case, fast path...
return lhsType;
AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
AssignmentCheckResult result;
if (compoundType.isNull())
result = CheckSingleAssignmentConstraints(lhsType, rex);
else
result = CheckCompoundAssignmentConstraints(lhsType, rhsType);
// decode the result (notice that extensions still return a type).
switch (result) {
@ -1313,7 +1341,7 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
break;
case UnaryOperator::LNot: // logical negation
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
resultType = DefaultFunctionArrayConversion(Input->getType());
resultType = DefaultFunctionArrayConversion(Input);
if (!resultType->isScalarType()) // C99 6.5.3.3p1
return Diag(OpLoc, diag::err_typecheck_unary_expr,
resultType.getAsString());

Просмотреть файл

@ -107,7 +107,7 @@ Sema::ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
Expr *condExpr = (Expr *)CondVal;
assert(condExpr && "ParseIfStmt(): missing expression");
QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
QualType condType = DefaultFunctionArrayConversion(condExpr);
assert(!condType.isNull() && "ParseIfStmt(): missing expression type");
if (!condType->isScalarType()) // C99 6.8.4.1p1
@ -127,7 +127,7 @@ Sema::ParseWhileStmt(SourceLocation WhileLoc, ExprTy *Cond, StmtTy *Body) {
Expr *condExpr = (Expr *)Cond;
assert(condExpr && "ParseWhileStmt(): missing expression");
QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
QualType condType = DefaultFunctionArrayConversion(condExpr);
assert(!condType.isNull() && "ParseWhileStmt(): missing expression type");
if (!condType->isScalarType()) // C99 6.8.5p2
@ -143,7 +143,7 @@ Sema::ParseDoStmt(SourceLocation DoLoc, StmtTy *Body,
Expr *condExpr = (Expr *)Cond;
assert(condExpr && "ParseDoStmt(): missing expression");
QualType condType = DefaultFunctionArrayConversion(condExpr->getType());
QualType condType = DefaultFunctionArrayConversion(condExpr);
assert(!condType.isNull() && "ParseDoStmt(): missing expression type");
if (!condType->isScalarType()) // C99 6.8.5p2
@ -164,7 +164,7 @@ Sema::ParseForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
}
if (Second) {
Expr *testExpr = (Expr *)Second;
QualType testType = DefaultFunctionArrayConversion(testExpr->getType());
QualType testType = DefaultFunctionArrayConversion(testExpr);
assert(!testType.isNull() && "ParseForStmt(): missing test expression type");
if (!testType->isScalarType()) // C99 6.8.5p2
@ -224,15 +224,16 @@ Sema::ParseBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
Action::StmtResult
Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *RetValExp) {
Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
Expr *RetValExp = static_cast<Expr *>(rex);
QualType lhsType = CurFunctionDecl->getResultType();
if (lhsType->isVoidType()) {
if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns)
Diag(ReturnLoc, diag::ext_return_has_expr,
CurFunctionDecl->getIdentifier()->getName(),
((Expr *)RetValExp)->getSourceRange());
return new ReturnStmt((Expr*)RetValExp);
RetValExp->getSourceRange());
return new ReturnStmt(RetValExp);
} else {
if (!RetValExp) {
const char *funcName = CurFunctionDecl->getIdentifier()->getName();
@ -244,15 +245,16 @@ Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *RetValExp) {
}
}
// we have a non-void function with an expression, continue checking
QualType rhsType = ((Expr *)RetValExp)->getType();
QualType rhsType = RetValExp->getType();
if (lhsType == rhsType) // common case, fast path...
return new ReturnStmt((Expr*)RetValExp);
return new ReturnStmt(RetValExp);
// C99 6.8.6.4p3(136): The return statement is not an assignment. The
// overlap restriction of subclause 6.5.16.1 does not apply to the case of
// function return.
AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
RetValExp);
bool hadError = false;
// decode the result (notice that extensions still return a type).
@ -262,31 +264,31 @@ Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *RetValExp) {
case Incompatible:
Diag(ReturnLoc, diag::err_typecheck_return_incompatible,
lhsType.getAsString(), rhsType.getAsString(),
((Expr *)RetValExp)->getSourceRange());
RetValExp->getSourceRange());
hadError = true;
break;
case PointerFromInt:
// check for null pointer constant (C99 6.3.2.3p3)
if (!((Expr *)RetValExp)->isNullPointerConstant()) {
if (!RetValExp->isNullPointerConstant()) {
Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
lhsType.getAsString(), rhsType.getAsString(),
((Expr *)RetValExp)->getSourceRange());
RetValExp->getSourceRange());
}
break;
case IntFromPointer:
Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
lhsType.getAsString(), rhsType.getAsString(),
((Expr *)RetValExp)->getSourceRange());
RetValExp->getSourceRange());
break;
case IncompatiblePointer:
Diag(ReturnLoc, diag::ext_typecheck_return_incompatible_pointer,
lhsType.getAsString(), rhsType.getAsString(),
((Expr *)RetValExp)->getSourceRange());
RetValExp->getSourceRange());
break;
case CompatiblePointerDiscardsQualifiers:
Diag(ReturnLoc, diag::ext_typecheck_return_discards_qualifiers,
lhsType.getAsString(), rhsType.getAsString(),
((Expr *)RetValExp)->getSourceRange());
RetValExp->getSourceRange());
break;
}
return new ReturnStmt((Expr*)RetValExp);

Просмотреть файл

@ -439,6 +439,8 @@ public:
Expr *getSubExpr() { return Op; }
const Expr *getSubExpr() const { return Op; }
virtual SourceRange getSourceRange() const { return SourceRange(); }
virtual void visit(StmtVisitor &Visitor);
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;