// 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,
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);
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
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()) {
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).
}
// 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())) {
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()))
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)
///
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())
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(),
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;
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;
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())
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())
// 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;
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;
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) {
case Compatible:
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());
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
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
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
}
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
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();
}
}
// 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).
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);