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
This commit is contained in:
parent
72cada0ad9
commit
e845e272ba
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>"; };
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue