Submitted by:
Reviewed by:
More tweaks to error diagnostics (adding types, using the new hooks on expr).
Still more to do...

llvm-svn: 39455
This commit is contained in:
Steve Naroff 2007-05-18 01:06:45 +00:00
parent 72cada0ad9
commit e845e272ba
6 changed files with 61 additions and 43 deletions

View File

@ -279,8 +279,7 @@ private:
Expr *cond, Expr *lhs, Expr *rhs, SourceLocation questionLoc);
/// type checking unary operators (subroutines of ParseUnaryOp).
QualType CheckIncrementDecrementOperand( // C99 6.5.3.1
Expr *op, SourceLocation loc);
QualType CheckIncrementDecrementOperand(Expr *op); // C99 6.5.3.1
QualType CheckAddressOfOperand( // C99 6.5.3.2
Expr *op, SourceLocation loc);
QualType CheckIndirectionOperand( // C99 6.5.3.2

View File

@ -220,7 +220,7 @@ Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc,
case tok::plusplus: Opc = UnaryOperator::PostInc; break;
case tok::minusminus: Opc = UnaryOperator::PostDec; break;
}
QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
QualType result = CheckIncrementDecrementOperand((Expr *)Input);
if (result.isNull())
return true;
return new UnaryOperator((Expr *)Input, Opc, result, OpLoc);
@ -641,7 +641,8 @@ inline QualType Sema::CheckMultiplyDivideOperands(
if (resType->isArithmeticType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -652,7 +653,8 @@ inline QualType Sema::CheckRemainderOperands(
if (resType->isIntegerType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -669,7 +671,8 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
(lhsType->isIntegerType() && rhsType->isPointerType()))
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lhsType.getAsString(), rhsType.getAsString());
return QualType();
}
@ -685,7 +688,8 @@ inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
(lhsType->isPointerType() && rhsType->isPointerType()))
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lhsType.getAsString(), rhsType.getAsString());
return QualType();
}
@ -696,7 +700,8 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7
if (resType->isIntegerType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -715,7 +720,8 @@ inline QualType Sema::CheckRelationalOperands( // C99 6.5.8
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
return Context.IntTy;
}
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lType.getAsString(), rType.getAsString());
return QualType();
}
@ -733,7 +739,8 @@ inline QualType Sema::CheckEqualityOperands( // C99 6.5.9
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
return Context.IntTy;
}
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lType.getAsString(), rType.getAsString());
return QualType();
}
@ -744,7 +751,8 @@ inline QualType Sema::CheckBitwiseOperands(
if (resType->isIntegerType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -756,7 +764,8 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
if (lhsType->isScalarType() || rhsType->isScalarType())
return Context.IntTy;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -770,10 +779,10 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
// this check is done first to give a more precise diagnostic.
// isModifiableLvalue() will also check for "const".
if (lhsType.isConstQualified()) {
Diag(loc, diag::err_typecheck_assign_const);
Diag(lex->getLocStart(), diag::err_typecheck_assign_const);
hadError = true;
} else if (!lex->isModifiableLvalue()) { // C99 6.5.16p2
Diag(loc, diag::err_typecheck_assign_non_lvalue);
Diag(lex->getLocStart(), diag::err_typecheck_assign_non_lvalue);
return QualType(); // no need to continue checking...
}
if (lhsType == rhsType) // common case, fast path...
@ -787,7 +796,8 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
case Compatible:
break;
case Incompatible:
Diag(loc, diag::err_typecheck_assign_incompatible);
Diag(loc, diag::err_typecheck_assign_incompatible,
lhsType.getAsString(), rhsType.getAsString());
hadError = true;
break;
case PointerFromInt:
@ -814,27 +824,27 @@ inline QualType Sema::CheckCommaOperands( // C99 6.5.17
return UsualUnaryConversion(rex->getType());
}
QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
QualType Sema::CheckIncrementDecrementOperand(Expr *op) {
QualType resType = UsualArithmeticConversions(op->getType(), Context.IntTy);
assert(!resType.isNull() && "no type for increment/decrement expression");
// C99 6.5.2.4p1
if (const PointerType *pt = dyn_cast<PointerType>(resType)) {
if (!pt->getPointeeType()->isObjectType()) { // C99 6.5.2.4p2, 6.5.6p2
Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type,
Diag(op->getLocStart(), diag::err_typecheck_arithmetic_incomplete_type,
resType.getAsString());
return QualType();
}
} else if (!resType->isRealType()) {
// FIXME: Allow Complex as a GCC extension.
Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement,
Diag(op->getLocStart(), diag::err_typecheck_illegal_increment_decrement,
resType.getAsString());
return QualType();
}
// At this point, we know we have a real or pointer type. Now make sure
// the operand is a modifiable lvalue.
if (!op->isModifiableLvalue()) {
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_incr_decr);
Diag(op->getLocStart(), diag::err_typecheck_invalid_lvalue_incr_decr);
return QualType();
}
return resType;
@ -1080,7 +1090,7 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
assert(0 && "Unimplemented unary expr!");
case UnaryOperator::PreInc:
case UnaryOperator::PreDec:
resultType = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
resultType = CheckIncrementDecrementOperand((Expr *)Input);
break;
case UnaryOperator::AddrOf:
resultType = CheckAddressOfOperand((Expr *)Input, OpLoc);

View File

@ -279,8 +279,7 @@ private:
Expr *cond, Expr *lhs, Expr *rhs, SourceLocation questionLoc);
/// type checking unary operators (subroutines of ParseUnaryOp).
QualType CheckIncrementDecrementOperand( // C99 6.5.3.1
Expr *op, SourceLocation loc);
QualType CheckIncrementDecrementOperand(Expr *op); // C99 6.5.3.1
QualType CheckAddressOfOperand( // C99 6.5.3.2
Expr *op, SourceLocation loc);
QualType CheckIndirectionOperand( // C99 6.5.3.2

View File

@ -220,7 +220,7 @@ Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc,
case tok::plusplus: Opc = UnaryOperator::PostInc; break;
case tok::minusminus: Opc = UnaryOperator::PostDec; break;
}
QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
QualType result = CheckIncrementDecrementOperand((Expr *)Input);
if (result.isNull())
return true;
return new UnaryOperator((Expr *)Input, Opc, result, OpLoc);
@ -641,7 +641,8 @@ inline QualType Sema::CheckMultiplyDivideOperands(
if (resType->isArithmeticType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -652,7 +653,8 @@ inline QualType Sema::CheckRemainderOperands(
if (resType->isIntegerType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -669,7 +671,8 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
(lhsType->isIntegerType() && rhsType->isPointerType()))
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lhsType.getAsString(), rhsType.getAsString());
return QualType();
}
@ -685,7 +688,8 @@ inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
(lhsType->isPointerType() && rhsType->isPointerType()))
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lhsType.getAsString(), rhsType.getAsString());
return QualType();
}
@ -696,7 +700,8 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7
if (resType->isIntegerType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -715,7 +720,8 @@ inline QualType Sema::CheckRelationalOperands( // C99 6.5.8
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
return Context.IntTy;
}
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lType.getAsString(), rType.getAsString());
return QualType();
}
@ -733,7 +739,8 @@ inline QualType Sema::CheckEqualityOperands( // C99 6.5.9
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
return Context.IntTy;
}
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lType.getAsString(), rType.getAsString());
return QualType();
}
@ -744,7 +751,8 @@ inline QualType Sema::CheckBitwiseOperands(
if (resType->isIntegerType())
return resType;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -756,7 +764,8 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
if (lhsType->isScalarType() || rhsType->isScalarType())
return Context.IntTy;
Diag(loc, diag::err_typecheck_invalid_operands);
Diag(loc, diag::err_typecheck_invalid_operands,
lex->getType().getAsString(), rex->getType().getAsString());
return QualType();
}
@ -770,10 +779,10 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
// this check is done first to give a more precise diagnostic.
// isModifiableLvalue() will also check for "const".
if (lhsType.isConstQualified()) {
Diag(loc, diag::err_typecheck_assign_const);
Diag(lex->getLocStart(), diag::err_typecheck_assign_const);
hadError = true;
} else if (!lex->isModifiableLvalue()) { // C99 6.5.16p2
Diag(loc, diag::err_typecheck_assign_non_lvalue);
Diag(lex->getLocStart(), diag::err_typecheck_assign_non_lvalue);
return QualType(); // no need to continue checking...
}
if (lhsType == rhsType) // common case, fast path...
@ -787,7 +796,8 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
case Compatible:
break;
case Incompatible:
Diag(loc, diag::err_typecheck_assign_incompatible);
Diag(loc, diag::err_typecheck_assign_incompatible,
lhsType.getAsString(), rhsType.getAsString());
hadError = true;
break;
case PointerFromInt:
@ -814,27 +824,27 @@ inline QualType Sema::CheckCommaOperands( // C99 6.5.17
return UsualUnaryConversion(rex->getType());
}
QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
QualType Sema::CheckIncrementDecrementOperand(Expr *op) {
QualType resType = UsualArithmeticConversions(op->getType(), Context.IntTy);
assert(!resType.isNull() && "no type for increment/decrement expression");
// C99 6.5.2.4p1
if (const PointerType *pt = dyn_cast<PointerType>(resType)) {
if (!pt->getPointeeType()->isObjectType()) { // C99 6.5.2.4p2, 6.5.6p2
Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type,
Diag(op->getLocStart(), diag::err_typecheck_arithmetic_incomplete_type,
resType.getAsString());
return QualType();
}
} else if (!resType->isRealType()) {
// FIXME: Allow Complex as a GCC extension.
Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement,
Diag(op->getLocStart(), diag::err_typecheck_illegal_increment_decrement,
resType.getAsString());
return QualType();
}
// At this point, we know we have a real or pointer type. Now make sure
// the operand is a modifiable lvalue.
if (!op->isModifiableLvalue()) {
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_incr_decr);
Diag(op->getLocStart(), diag::err_typecheck_invalid_lvalue_incr_decr);
return QualType();
}
return resType;
@ -1080,7 +1090,7 @@ Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
assert(0 && "Unimplemented unary expr!");
case UnaryOperator::PreInc:
case UnaryOperator::PreDec:
resultType = CheckIncrementDecrementOperand((Expr *)Input, OpLoc);
resultType = CheckIncrementDecrementOperand((Expr *)Input);
break;
case UnaryOperator::AddrOf:
resultType = CheckAddressOfOperand((Expr *)Input, OpLoc);

View File

@ -171,7 +171,7 @@
1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = "<group>"; };
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
DE06BECA0A854E4B0050E87E /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Parse/Scope.h; sourceTree = "<group>"; };

View File

@ -546,13 +546,13 @@ DIAG(err_typecheck_invalid_lvalue_addrof, ERROR,
DIAG(err_typecheck_unary_expr, ERROR,
"invalid argument type to unary expression '%0'")
DIAG(err_typecheck_invalid_operands, ERROR,
"invalid operands to binary expression")
"invalid operands to binary expression ('%0' and '%1')")
DIAG(ext_typecheck_comparison_of_pointer_integer, EXTENSION,
"comparison between pointer and integer")
DIAG(err_typecheck_assign_const, ERROR,
"assignment of read-only variable")
DIAG(err_typecheck_assign_incompatible, ERROR,
"incompatible types in assignment")
"incompatible types in assignment ('%0' and '%1')")
DIAG(ext_typecheck_assign_int_from_pointer, EXTENSION,
"assignment makes integer from pointer without a cast")
DIAG(ext_typecheck_assign_pointer_from_int, EXTENSION,