From e845e272baab2adcfcc53590f18d3f152d6cfd28 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Fri, 18 May 2007 01:06:45 +0000 Subject: [PATCH] Bug #: Submitted by: Reviewed by: More tweaks to error diagnostics (adding types, using the new hooks on expr). Still more to do... llvm-svn: 39455 --- clang/AST/Sema.h | 3 +- clang/AST/SemaExpr.cpp | 46 +++++++++++-------- clang/Sema/Sema.h | 3 +- clang/Sema/SemaExpr.cpp | 46 +++++++++++-------- clang/clang.xcodeproj/project.pbxproj | 2 +- clang/include/clang/Basic/DiagnosticKinds.def | 4 +- 6 files changed, 61 insertions(+), 43 deletions(-) diff --git a/clang/AST/Sema.h b/clang/AST/Sema.h index 758fcb94cfc1..4c5a7c8d2b23 100644 --- a/clang/AST/Sema.h +++ b/clang/AST/Sema.h @@ -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 diff --git a/clang/AST/SemaExpr.cpp b/clang/AST/SemaExpr.cpp index ef8e8ba24e05..4ae4016e1513 100644 --- a/clang/AST/SemaExpr.cpp +++ b/clang/AST/SemaExpr.cpp @@ -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(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); diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 758fcb94cfc1..4c5a7c8d2b23 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -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 diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index ef8e8ba24e05..4ae4016e1513 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -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(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); diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 890d1b3bf787..6f2340dfc513 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -171,7 +171,7 @@ 1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = ""; }; 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = ""; }; 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = ""; }; - 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 = ""; }; DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = ""; }; DE06BECA0A854E4B0050E87E /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Parse/Scope.h; sourceTree = ""; }; diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 91b040d9a886..0972a0aec609 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -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,