Change DefaultFunctionArrayConversions and UsualUnaryConversions to return void. The caller

needs to query the expression for the type. Since both these functions guarantee the expression 
contains a valid type, removed old/vacuous asserts (from code calling both of these routines).

llvm-svn: 39930
This commit is contained in:
Steve Naroff 2007-07-16 21:54:35 +00:00
parent 7fcaaadf1c
commit 3109001c19
4 changed files with 65 additions and 52 deletions

View File

@ -269,8 +269,12 @@ public:
tok::TokenKind Kind); tok::TokenKind Kind);
private: private:
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
// functions and arrays to their respective pointers (C99 6.3.2.1) // functions and arrays to their respective pointers (C99 6.3.2.1).
QualType UsualUnaryConversions(Expr *&expr); void UsualUnaryConversions(Expr *&expr);
// DefaultFunctionArrayConversion - converts functions and arrays
// to their respective pointers (C99 6.3.2.1).
void DefaultFunctionArrayConversion(Expr *&expr);
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's // UsualArithmeticConversions - performs the UsualUnaryConversions on it's
// operands and then handles various conversions that are common to binary // operands and then handles various conversions that are common to binary
@ -278,13 +282,7 @@ private:
// routine returns the first non-arithmetic type found. The client is // routine returns the first non-arithmetic type found. The client is
// responsible for emitting appropriate error diagnostics. // responsible for emitting appropriate error diagnostics.
QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr, QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
QualType &lhs, QualType &rhs); 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(Expr *&expr);
enum AssignmentCheckResult { enum AssignmentCheckResult {
Compatible, Compatible,
Incompatible, Incompatible,

View File

@ -286,7 +286,6 @@ ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
DefaultFunctionArrayConversion(RHSExp); DefaultFunctionArrayConversion(RHSExp);
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType(); QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
assert(!LHSTy.isNull() && !RHSTy.isNull() && "missing types");
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent // 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 // to the expression *((e1)+(e2)). This means the array "Base" may actually be
@ -374,13 +373,13 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
Expr *funcExpr = (Expr *)Fn; Expr *funcExpr = (Expr *)Fn;
assert(funcExpr && "no function call expression"); assert(funcExpr && "no function call expression");
QualType qType = UsualUnaryConversions(funcExpr); UsualUnaryConversions(funcExpr);
assert(!qType.isNull() && "no type for function call expression"); QualType funcType = funcExpr->getType();
// C99 6.5.2.2p1 - "The expression that denotes the called function shall have // C99 6.5.2.2p1 - "The expression that denotes the called function shall have
// type pointer to function". // type pointer to function".
const PointerType *PT = dyn_cast<PointerType>(qType); const PointerType *PT = dyn_cast<PointerType>(funcType);
if (PT == 0) PT = dyn_cast<PointerType>(qType.getCanonicalType()); if (PT == 0) PT = dyn_cast<PointerType>(funcType.getCanonicalType());
if (PT == 0) if (PT == 0)
return Diag(funcExpr->getLocStart(), diag::err_typecheck_call_not_function, return Diag(funcExpr->getLocStart(), diag::err_typecheck_call_not_function,
@ -482,10 +481,13 @@ ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
Expr *&cond, Expr *&lex, Expr *&rex, SourceLocation questionLoc) { Expr *&cond, Expr *&lex, Expr *&rex, SourceLocation questionLoc) {
QualType condT = UsualUnaryConversions(cond); UsualUnaryConversions(cond);
QualType lexT = UsualUnaryConversions(lex); UsualUnaryConversions(lex);
QualType rexT = UsualUnaryConversions(rex); UsualUnaryConversions(rex);
QualType condT = cond->getType();
QualType lexT = lex->getType();
QualType rexT = rex->getType();
// first, check the condition. // first, check the condition.
if (!condT->isScalarType()) { // C99 6.5.15p2 if (!condT->isScalarType()) { // C99 6.5.15p2
Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar, Diag(cond->getLocStart(), diag::err_typecheck_cond_expect_scalar,
@ -578,15 +580,14 @@ static QualType promoteExprToType(Expr *&expr, QualType type) {
} }
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
QualType Sema::DefaultFunctionArrayConversion(Expr *&e) { void Sema::DefaultFunctionArrayConversion(Expr *&e) {
QualType t = e->getType(); QualType t = e->getType();
assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type"); assert(!t.isNull() && "DefaultFunctionArrayConversion - missing type");
if (t->isFunctionType()) if (t->isFunctionType())
return promoteExprToType(e, Context.getPointerType(t)); promoteExprToType(e, Context.getPointerType(t));
if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType())) else if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
return promoteExprToType(e, Context.getPointerType(ary->getElementType())); promoteExprToType(e, Context.getPointerType(ary->getElementType()));
return t;
} }
/// UsualUnaryConversion - Performs various conversions that are common to most /// UsualUnaryConversion - Performs various conversions that are common to most
@ -594,13 +595,14 @@ QualType Sema::DefaultFunctionArrayConversion(Expr *&e) {
/// sometimes surpressed. For example, the array->pointer conversion doesn't /// sometimes surpressed. For example, the array->pointer conversion doesn't
/// apply if the array is an argument to the sizeof or address (&) operators. /// apply if the array is an argument to the sizeof or address (&) operators.
/// In these instances, this routine should *not* be called. /// In these instances, this routine should *not* be called.
QualType Sema::UsualUnaryConversions(Expr *&expr) { void Sema::UsualUnaryConversions(Expr *&expr) {
QualType t = expr->getType(); QualType t = expr->getType();
assert(!t.isNull() && "UsualUnaryConversions - missing type"); assert(!t.isNull() && "UsualUnaryConversions - missing type");
if (t->isPromotableIntegerType()) // C99 6.3.1.1p2 if (t->isPromotableIntegerType()) // C99 6.3.1.1p2
return promoteExprToType(expr, Context.IntTy); promoteExprToType(expr, Context.IntTy);
return DefaultFunctionArrayConversion(expr); else
DefaultFunctionArrayConversion(expr);
} }
/// UsualArithmeticConversions - Performs various conversions that are common to /// UsualArithmeticConversions - Performs various conversions that are common to
@ -609,8 +611,12 @@ QualType Sema::UsualUnaryConversions(Expr *&expr) {
/// responsible for emitting appropriate error diagnostics. /// responsible for emitting appropriate error diagnostics.
QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr, QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
QualType &lhs, QualType &rhs) { QualType &lhs, QualType &rhs) {
lhs = UsualUnaryConversions(lhsExpr); UsualUnaryConversions(lhsExpr);
rhs = UsualUnaryConversions(rhsExpr); UsualUnaryConversions(rhsExpr);
// FIXME: get rid of these reference parameters.
lhs = lhsExpr->getType();
rhs = rhsExpr->getType();
// If both types are identical, no conversion is needed. // If both types are identical, no conversion is needed.
if (lhs == rhs) if (lhs == rhs)
@ -757,9 +763,9 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// conversion of functions/arrays. If the conversion were done for all // conversion of functions/arrays. If the conversion were done for all
// DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary // DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary
// expressions that surpress this implicit conversion (&, sizeof). // expressions that surpress this implicit conversion (&, sizeof).
QualType rhsType = DefaultFunctionArrayConversion(rExpr); DefaultFunctionArrayConversion(rExpr);
return CheckAssignmentConstraints(lhsType, rhsType); return CheckAssignmentConstraints(lhsType, rExpr->getType());
} }
Sema::AssignmentCheckResult Sema::AssignmentCheckResult
@ -875,8 +881,10 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7
inline QualType Sema::CheckRelationalOperands( // C99 6.5.8 inline QualType Sema::CheckRelationalOperands( // C99 6.5.8
Expr *&lex, Expr *&rex, SourceLocation loc) Expr *&lex, Expr *&rex, SourceLocation loc)
{ {
QualType lType = UsualUnaryConversions(lex); UsualUnaryConversions(lex);
QualType rType = UsualUnaryConversions(rex); UsualUnaryConversions(rex);
QualType lType = lex->getType();
QualType rType = rex->getType();
if (lType->isRealType() && rType->isRealType()) if (lType->isRealType() && rType->isRealType())
return Context.IntTy; return Context.IntTy;
@ -905,8 +913,10 @@ inline QualType Sema::CheckRelationalOperands( // C99 6.5.8
inline QualType Sema::CheckEqualityOperands( // C99 6.5.9 inline QualType Sema::CheckEqualityOperands( // C99 6.5.9
Expr *&lex, Expr *&rex, SourceLocation loc) Expr *&lex, Expr *&rex, SourceLocation loc)
{ {
QualType lType = UsualUnaryConversions(lex); UsualUnaryConversions(lex);
QualType rType = UsualUnaryConversions(rex); UsualUnaryConversions(rex);
QualType lType = lex->getType();
QualType rType = rex->getType();
if (lType->isArithmeticType() && rType->isArithmeticType()) if (lType->isArithmeticType() && rType->isArithmeticType())
return Context.IntTy; return Context.IntTy;
@ -951,8 +961,10 @@ inline QualType Sema::CheckBitwiseOperands(
inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
Expr *&lex, Expr *&rex, SourceLocation loc) Expr *&lex, Expr *&rex, SourceLocation loc)
{ {
QualType lhsType = UsualUnaryConversions(lex); UsualUnaryConversions(lex);
QualType rhsType = UsualUnaryConversions(rex); UsualUnaryConversions(rex);
QualType lhsType = lex->getType();
QualType rhsType = rex->getType();
if (lhsType->isScalarType() || rhsType->isScalarType()) if (lhsType->isScalarType() || rhsType->isScalarType())
return Context.IntTy; return Context.IntTy;
@ -1048,7 +1060,8 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
inline QualType Sema::CheckCommaOperands( // C99 6.5.17 inline QualType Sema::CheckCommaOperands( // C99 6.5.17
Expr *&lex, Expr *&rex, SourceLocation loc) { Expr *&lex, Expr *&rex, SourceLocation loc) {
return UsualUnaryConversions(rex); UsualUnaryConversions(rex);
return rex->getType();
} }
/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine /// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
@ -1141,10 +1154,9 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
} }
QualType Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc) { QualType Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc) {
QualType qType = UsualUnaryConversions(op); UsualUnaryConversions(op);
QualType qType = op->getType();
assert(!qType.isNull() && "no type for * expression");
if (PointerType *PT = dyn_cast<PointerType>(qType.getCanonicalType())) { if (PointerType *PT = dyn_cast<PointerType>(qType.getCanonicalType())) {
QualType ptype = PT->getPointeeType(); QualType ptype = PT->getPointeeType();
// C99 6.5.3.2p4. "if it points to an object,...". // C99 6.5.3.2p4. "if it points to an object,...".
@ -1348,20 +1360,23 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
break; break;
case UnaryOperator::Plus: case UnaryOperator::Plus:
case UnaryOperator::Minus: case UnaryOperator::Minus:
resultType = UsualUnaryConversions(Input); UsualUnaryConversions(Input);
resultType = Input->getType();
if (!resultType->isArithmeticType()) // C99 6.5.3.3p1 if (!resultType->isArithmeticType()) // C99 6.5.3.3p1
return Diag(OpLoc, diag::err_typecheck_unary_expr, return Diag(OpLoc, diag::err_typecheck_unary_expr,
resultType.getAsString()); resultType.getAsString());
break; break;
case UnaryOperator::Not: // bitwise complement case UnaryOperator::Not: // bitwise complement
resultType = UsualUnaryConversions(Input); UsualUnaryConversions(Input);
resultType = Input->getType();
if (!resultType->isIntegerType()) // C99 6.5.3.3p1 if (!resultType->isIntegerType()) // C99 6.5.3.3p1
return Diag(OpLoc, diag::err_typecheck_unary_expr, return Diag(OpLoc, diag::err_typecheck_unary_expr,
resultType.getAsString()); resultType.getAsString());
break; break;
case UnaryOperator::LNot: // logical negation case UnaryOperator::LNot: // logical negation
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
resultType = DefaultFunctionArrayConversion(Input); DefaultFunctionArrayConversion(Input);
resultType = Input->getType();
if (!resultType->isScalarType()) // C99 6.5.3.3p1 if (!resultType->isScalarType()) // C99 6.5.3.3p1
return Diag(OpLoc, diag::err_typecheck_unary_expr, return Diag(OpLoc, diag::err_typecheck_unary_expr,
resultType.getAsString()); resultType.getAsString());

View File

@ -107,8 +107,8 @@ Sema::ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
Expr *condExpr = (Expr *)CondVal; Expr *condExpr = (Expr *)CondVal;
assert(condExpr && "ParseIfStmt(): missing expression"); assert(condExpr && "ParseIfStmt(): missing expression");
QualType condType = DefaultFunctionArrayConversion(condExpr); DefaultFunctionArrayConversion(condExpr);
assert(!condType.isNull() && "ParseIfStmt(): missing expression type"); QualType condType = condExpr->getType();
if (!condType->isScalarType()) // C99 6.8.4.1p1 if (!condType->isScalarType()) // C99 6.8.4.1p1
return Diag(IfLoc, diag::err_typecheck_statement_requires_scalar, return Diag(IfLoc, diag::err_typecheck_statement_requires_scalar,
@ -127,8 +127,8 @@ Sema::ParseWhileStmt(SourceLocation WhileLoc, ExprTy *Cond, StmtTy *Body) {
Expr *condExpr = (Expr *)Cond; Expr *condExpr = (Expr *)Cond;
assert(condExpr && "ParseWhileStmt(): missing expression"); assert(condExpr && "ParseWhileStmt(): missing expression");
QualType condType = DefaultFunctionArrayConversion(condExpr); DefaultFunctionArrayConversion(condExpr);
assert(!condType.isNull() && "ParseWhileStmt(): missing expression type"); QualType condType = condExpr->getType();
if (!condType->isScalarType()) // C99 6.8.5p2 if (!condType->isScalarType()) // C99 6.8.5p2
return Diag(WhileLoc, diag::err_typecheck_statement_requires_scalar, return Diag(WhileLoc, diag::err_typecheck_statement_requires_scalar,
@ -143,8 +143,8 @@ Sema::ParseDoStmt(SourceLocation DoLoc, StmtTy *Body,
Expr *condExpr = (Expr *)Cond; Expr *condExpr = (Expr *)Cond;
assert(condExpr && "ParseDoStmt(): missing expression"); assert(condExpr && "ParseDoStmt(): missing expression");
QualType condType = DefaultFunctionArrayConversion(condExpr); DefaultFunctionArrayConversion(condExpr);
assert(!condType.isNull() && "ParseDoStmt(): missing expression type"); QualType condType = condExpr->getType();
if (!condType->isScalarType()) // C99 6.8.5p2 if (!condType->isScalarType()) // C99 6.8.5p2
return Diag(DoLoc, diag::err_typecheck_statement_requires_scalar, return Diag(DoLoc, diag::err_typecheck_statement_requires_scalar,
@ -164,8 +164,8 @@ Sema::ParseForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
} }
if (Second) { if (Second) {
Expr *testExpr = (Expr *)Second; Expr *testExpr = (Expr *)Second;
QualType testType = DefaultFunctionArrayConversion(testExpr); DefaultFunctionArrayConversion(testExpr);
assert(!testType.isNull() && "ParseForStmt(): missing test expression type"); QualType testType = testExpr->getType();
if (!testType->isScalarType()) // C99 6.8.5p2 if (!testType->isScalarType()) // C99 6.8.5p2
return Diag(ForLoc, diag::err_typecheck_statement_requires_scalar, return Diag(ForLoc, diag::err_typecheck_statement_requires_scalar,

View File

@ -189,7 +189,7 @@
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; }; 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; }; 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; }; 84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; }; 8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; }; DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; }; DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; }; DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };