Merge all the 'assignment' diagnostic code into one routine, decloning

it from several places.  This merges the diagnostics, making them more
uniform and fewer in number. This also simplifies and cleans up the code.

Some highlights:
1. This removes a bunch of very-similar diagnostics.
2. This renames AssignmentCheckResult -> AssignConvertType
3. This merges PointerFromInt + IntFromPointer which were always treated the same.
4. This updates a bunch of test cases that have minor changes to the produced diagnostics.

llvm-svn: 45589
This commit is contained in:
Chris Lattner 2008-01-04 18:04:52 +00:00
parent d98c63ebb9
commit 9bad62c72a
21 changed files with 204 additions and 385 deletions

View File

@ -613,34 +613,42 @@ private:
// responsible for emitting appropriate error diagnostics. // responsible for emitting appropriate error diagnostics.
QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr, QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
bool isCompAssign = false); bool isCompAssign = false);
enum AssignmentCheckResult { enum AssignConvertType {
Compatible, Compatible,
Incompatible, Incompatible,
PointerFromInt, PointerInt,
IntFromPointer,
FunctionVoidPointer, FunctionVoidPointer,
IncompatiblePointer, IncompatiblePointer,
CompatiblePointerDiscardsQualifiers CompatiblePointerDiscardsQualifiers
}; };
// CheckAssignmentConstraints - Perform type checking for assignment,
// argument passing, variable initialization, and function return values. /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
// This routine is only used by the following two methods. C99 6.5.16. /// assignment conversion type specified by ConvTy. This returns true if the
AssignmentCheckResult CheckAssignmentConstraints(QualType lhs, QualType rhs); /// conversion was invalid or false if the conversion was accepted.
bool DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
Expr *SrcExpr, const char *Flavor);
/// 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.
AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs);
// CheckSingleAssignmentConstraints - Currently used by ActOnCallExpr, // CheckSingleAssignmentConstraints - Currently used by ActOnCallExpr,
// CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking, // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
// this routine performs the default function/array converions. // this routine performs the default function/array converions.
AssignmentCheckResult CheckSingleAssignmentConstraints(QualType lhs, AssignConvertType CheckSingleAssignmentConstraints(QualType lhs,
Expr *&rExpr); Expr *&rExpr);
// CheckCompoundAssignmentConstraints - Type check without performing any // CheckCompoundAssignmentConstraints - Type check without performing any
// conversions. For compound assignments, the "Check...Operands" methods // conversions. For compound assignments, the "Check...Operands" methods
// perform the necessary conversions. // perform the necessary conversions.
AssignmentCheckResult CheckCompoundAssignmentConstraints(QualType lhs, AssignConvertType CheckCompoundAssignmentConstraints(QualType lhs,
QualType rhs); QualType rhs);
// Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1) // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
AssignmentCheckResult CheckPointerTypesForAssignment(QualType lhsType, AssignConvertType CheckPointerTypesForAssignment(QualType lhsType,
QualType rhsType); QualType rhsType);
/// the following "Check" methods will return a valid/converted QualType /// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued). /// or a null QualType (indicating an error diagnostic was issued).

View File

@ -364,53 +364,13 @@ bool Sema::CheckSingleInitializer(Expr *&Init, bool isStatic,
return true; return true;
} }
AssignmentCheckResult result;
// Get the type before calling CheckSingleAssignmentConstraints(), since // Get the type before calling CheckSingleAssignmentConstraints(), since
// it can promote the expression. // it can promote the expression.
QualType rhsType = Init->getType(); QualType InitType = Init->getType();
result = CheckSingleAssignmentConstraints(DeclType, Init); AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
return DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
// decode the result (notice that extensions still return a type). InitType, Init, "initializing");
switch (result) {
case Compatible:
break;
case Incompatible:
// FIXME: tighten up this check which should allow:
// char s[] = "abc", which is identical to char s[] = { 'a', 'b', 'c' };
if (rhsType == Context.getPointerType(Context.CharTy))
break;
Diag(Init->getLocStart(), diag::err_typecheck_assign_incompatible,
DeclType.getAsString(), rhsType.getAsString(),
Init->getSourceRange());
return true;
case PointerFromInt:
Diag(Init->getLocStart(), diag::ext_typecheck_assign_pointer_int,
DeclType.getAsString(), rhsType.getAsString(),
Init->getSourceRange());
break;
case IntFromPointer:
Diag(Init->getLocStart(), diag::ext_typecheck_assign_pointer_int,
DeclType.getAsString(), rhsType.getAsString(),
Init->getSourceRange());
break;
case FunctionVoidPointer:
Diag(Init->getLocStart(), diag::ext_typecheck_assign_pointer_void_func,
DeclType.getAsString(), rhsType.getAsString(),
Init->getSourceRange());
break;
case IncompatiblePointer:
Diag(Init->getLocStart(), diag::ext_typecheck_assign_incompatible_pointer,
DeclType.getAsString(), rhsType.getAsString(),
Init->getSourceRange());
break;
case CompatiblePointerDiscardsQualifiers:
Diag(Init->getLocStart(), diag::ext_typecheck_assign_discards_qualifiers,
DeclType.getAsString(), rhsType.getAsString(),
Init->getSourceRange());
break;
}
return false;
} }
bool Sema::CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot, bool Sema::CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot,

View File

@ -615,55 +615,17 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
// Continue to check argument types (even if we have too few/many args). // Continue to check argument types (even if we have too few/many args).
for (unsigned i = 0; i != NumArgsToCheck; i++) { for (unsigned i = 0; i != NumArgsToCheck; i++) {
Expr *Arg = Args[i]; Expr *Arg = Args[i];
QualType LHSType = Proto->getArgType(i); QualType ProtoArgType = Proto->getArgType(i);
QualType RHSType = Arg->getType(); QualType ArgType = Arg->getType();
// If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
if (const ArrayType *AT = LHSType->getAsArrayType())
LHSType = Context.getPointerType(AT->getElementType());
else if (LHSType->isFunctionType())
LHSType = Context.getPointerType(LHSType);
// Compute implicit casts from the operand to the formal argument type. // Compute implicit casts from the operand to the formal argument type.
AssignmentCheckResult Result = AssignConvertType ConvTy =
CheckSingleAssignmentConstraints(LHSType, Arg); CheckSingleAssignmentConstraints(ProtoArgType, Arg);
TheCall->setArg(i, Arg); TheCall->setArg(i, Arg);
// Decode the result (notice that AST's are still created for extensions). if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), ProtoArgType,
SourceLocation Loc = Arg->getLocStart(); ArgType, Arg, "passing"))
switch (Result) { return true;
case Compatible:
break;
case PointerFromInt:
Diag(Loc, diag::ext_typecheck_passing_pointer_int,
LHSType.getAsString(), RHSType.getAsString(),
Fn->getSourceRange(), Arg->getSourceRange());
break;
case IntFromPointer:
Diag(Loc, diag::ext_typecheck_passing_pointer_int,
LHSType.getAsString(), RHSType.getAsString(),
Fn->getSourceRange(), Arg->getSourceRange());
break;
case FunctionVoidPointer:
Diag(Loc, diag::ext_typecheck_passing_pointer_void_func,
LHSType.getAsString(), RHSType.getAsString(),
Fn->getSourceRange(), Arg->getSourceRange());
break;
case IncompatiblePointer:
Diag(Loc, diag::ext_typecheck_passing_incompatible_pointer,
RHSType.getAsString(), LHSType.getAsString(),
Fn->getSourceRange(), Arg->getSourceRange());
break;
case CompatiblePointerDiscardsQualifiers:
Diag(Loc, diag::ext_typecheck_passing_discards_qualifiers,
RHSType.getAsString(), LHSType.getAsString(),
Fn->getSourceRange(), Arg->getSourceRange());
break;
case Incompatible:
return Diag(Loc, diag::err_typecheck_passing_incompatible,
RHSType.getAsString(), LHSType.getAsString(),
Fn->getSourceRange(), Arg->getSourceRange());
}
} }
// If this is a variadic call, handle args passed through "...". // If this is a variadic call, handle args passed through "...".
@ -1056,7 +1018,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
// routine is it effectively iqnores the qualifiers on the top level pointee. // routine is it effectively iqnores the qualifiers on the top level pointee.
// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3]. // This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
// FIXME: add a couple examples in this comment. // FIXME: add a couple examples in this comment.
Sema::AssignmentCheckResult Sema::AssignConvertType
Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
QualType lhptee, rhptee; QualType lhptee, rhptee;
@ -1068,21 +1030,21 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
lhptee = lhptee.getCanonicalType(); lhptee = lhptee.getCanonicalType();
rhptee = rhptee.getCanonicalType(); rhptee = rhptee.getCanonicalType();
AssignmentCheckResult r = Compatible; AssignConvertType ConvTy = Compatible;
// C99 6.5.16.1p1: This following citation is common to constraints // C99 6.5.16.1p1: This following citation is common to constraints
// 3 & 4 (below). ...and the type *pointed to* by the left has all the // 3 & 4 (below). ...and the type *pointed to* by the left has all the
// qualifiers of the type *pointed to* by the right; // qualifiers of the type *pointed to* by the right;
if ((lhptee.getQualifiers() & rhptee.getQualifiers()) != if ((lhptee.getQualifiers() & rhptee.getQualifiers()) !=
rhptee.getQualifiers()) rhptee.getQualifiers())
r = CompatiblePointerDiscardsQualifiers; ConvTy = CompatiblePointerDiscardsQualifiers;
// C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
// incomplete type and the other is a pointer to a qualified or unqualified // incomplete type and the other is a pointer to a qualified or unqualified
// version of void... // version of void...
if (lhptee->isVoidType()) { if (lhptee->isVoidType()) {
if (rhptee->isObjectType() || rhptee->isIncompleteType()) if (rhptee->isObjectType() || rhptee->isIncompleteType())
return r; return ConvTy;
// As an extension, we allow cast to/from void* to function pointer. // As an extension, we allow cast to/from void* to function pointer.
if (rhptee->isFunctionType()) if (rhptee->isFunctionType())
@ -1091,7 +1053,7 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
if (rhptee->isVoidType()) { if (rhptee->isVoidType()) {
if (lhptee->isObjectType() || lhptee->isIncompleteType()) if (lhptee->isObjectType() || lhptee->isIncompleteType())
return r; return ConvTy;
// As an extension, we allow cast to/from void* to function pointer. // As an extension, we allow cast to/from void* to function pointer.
if (lhptee->isFunctionType()) if (lhptee->isFunctionType())
@ -1103,7 +1065,7 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
rhptee.getUnqualifiedType())) rhptee.getUnqualifiedType()))
return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
return r; return ConvTy;
} }
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently /// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
@ -1123,7 +1085,7 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
/// C99 spec dictates. /// C99 spec dictates.
/// Note: the warning above turn into errors when -pedantic-errors is enabled. /// Note: the warning above turn into errors when -pedantic-errors is enabled.
/// ///
Sema::AssignmentCheckResult Sema::AssignConvertType
Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
@ -1169,14 +1131,14 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return Compatible; return Compatible;
} else if (lhsType->isPointerType()) { } else if (lhsType->isPointerType()) {
if (rhsType->isIntegerType()) if (rhsType->isIntegerType())
return PointerFromInt; return PointerInt;
if (rhsType->isPointerType()) if (rhsType->isPointerType())
return CheckPointerTypesForAssignment(lhsType, rhsType); return CheckPointerTypesForAssignment(lhsType, rhsType);
} else if (rhsType->isPointerType()) { } else if (rhsType->isPointerType()) {
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer. // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
if ((lhsType->isIntegerType()) && (lhsType != Context.BoolTy)) if ((lhsType->isIntegerType()) && (lhsType != Context.BoolTy))
return IntFromPointer; return PointerInt;
if (lhsType->isPointerType()) if (lhsType->isPointerType())
return CheckPointerTypesForAssignment(lhsType, rhsType); return CheckPointerTypesForAssignment(lhsType, rhsType);
@ -1187,7 +1149,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return Incompatible; return Incompatible;
} }
Sema::AssignmentCheckResult Sema::AssignConvertType
Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// C99 6.5.16.1p1: the left operand is a pointer and the right is // C99 6.5.16.1p1: the left operand is a pointer and the right is
// a null pointer constant. // a null pointer constant.
@ -1206,9 +1168,8 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
if (!lhsType->isReferenceType()) if (!lhsType->isReferenceType())
DefaultFunctionArrayConversion(rExpr); DefaultFunctionArrayConversion(rExpr);
Sema::AssignmentCheckResult result; Sema::AssignConvertType result =
CheckAssignmentConstraints(lhsType, rExpr->getType());
result = CheckAssignmentConstraints(lhsType, rExpr->getType());
// C99 6.5.16.1p2: The value of the right operand is converted to the // C99 6.5.16.1p2: The value of the right operand is converted to the
// type of the assignment expression. // type of the assignment expression.
@ -1217,7 +1178,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
return result; return result;
} }
Sema::AssignmentCheckResult Sema::AssignConvertType
Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) { Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
return CheckAssignmentConstraints(lhsType, rhsType); return CheckAssignmentConstraints(lhsType, rhsType);
} }
@ -1501,81 +1462,47 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
{ {
QualType lhsType = lex->getType(); QualType lhsType = lex->getType();
QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType; QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType;
bool hadError = false;
Expr::isModifiableLvalueResult mlval = lex->isModifiableLvalue(); Expr::isModifiableLvalueResult mlval = lex->isModifiableLvalue();
switch (mlval) { // C99 6.5.16p2 switch (mlval) { // C99 6.5.16p2
case Expr::MLV_Valid: case Expr::MLV_Valid:
break; break;
case Expr::MLV_ConstQualified: case Expr::MLV_ConstQualified:
Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange()); Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange());
hadError = true; return QualType();
break; case Expr::MLV_ArrayType:
case Expr::MLV_ArrayType: Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue,
Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue, lhsType.getAsString(), lex->getSourceRange());
lhsType.getAsString(), lex->getSourceRange()); return QualType();
return QualType(); case Expr::MLV_NotObjectType:
case Expr::MLV_NotObjectType: Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue,
Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue, lhsType.getAsString(), lex->getSourceRange());
lhsType.getAsString(), lex->getSourceRange()); return QualType();
return QualType(); case Expr::MLV_InvalidExpression:
case Expr::MLV_InvalidExpression: Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue,
Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue, lex->getSourceRange());
lex->getSourceRange()); return QualType();
return QualType(); case Expr::MLV_IncompleteType:
case Expr::MLV_IncompleteType: case Expr::MLV_IncompleteVoidType:
case Expr::MLV_IncompleteVoidType: Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue, lhsType.getAsString(), lex->getSourceRange());
lhsType.getAsString(), lex->getSourceRange()); return QualType();
return QualType(); case Expr::MLV_DuplicateVectorComponents:
case Expr::MLV_DuplicateVectorComponents: Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue,
Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue, lex->getSourceRange());
lex->getSourceRange()); return QualType();
return QualType();
} }
AssignmentCheckResult result;
if (compoundType.isNull())
result = CheckSingleAssignmentConstraints(lhsType, rex);
else
result = CheckCompoundAssignmentConstraints(lhsType, rhsType);
// decode the result (notice that extensions still return a type). AssignConvertType ConvTy;
switch (result) { if (compoundType.isNull())
case Compatible: ConvTy = CheckSingleAssignmentConstraints(lhsType, rex);
break; else
case Incompatible: ConvTy = CheckCompoundAssignmentConstraints(lhsType, rhsType);
Diag(loc, diag::err_typecheck_assign_incompatible,
lhsType.getAsString(), rhsType.getAsString(), if (DiagnoseAssignmentResult(ConvTy, loc, lhsType, rhsType,
lex->getSourceRange(), rex->getSourceRange()); rex, "assigning"))
hadError = true; return QualType();
break;
case PointerFromInt:
Diag(loc, diag::ext_typecheck_assign_pointer_int,
lhsType.getAsString(), rhsType.getAsString(),
lex->getSourceRange(), rex->getSourceRange());
break;
case IntFromPointer:
Diag(loc, diag::ext_typecheck_assign_pointer_int,
lhsType.getAsString(), rhsType.getAsString(),
lex->getSourceRange(), rex->getSourceRange());
break;
case FunctionVoidPointer:
Diag(loc, diag::ext_typecheck_assign_pointer_void_func,
lhsType.getAsString(), rhsType.getAsString(),
lex->getSourceRange(), rex->getSourceRange());
break;
case IncompatiblePointer:
Diag(loc, diag::ext_typecheck_assign_incompatible_pointer,
lhsType.getAsString(), rhsType.getAsString(),
lex->getSourceRange(), rex->getSourceRange());
break;
case CompatiblePointerDiscardsQualifiers:
Diag(loc, diag::ext_typecheck_assign_discards_qualifiers,
lhsType.getAsString(), rhsType.getAsString(),
lex->getSourceRange(), rex->getSourceRange());
break;
}
// C99 6.5.16p3: The type of an assignment expression is the type of the // C99 6.5.16p3: The type of an assignment expression is the type of the
// left operand unless the left operand has qualified type, in which case // left operand unless the left operand has qualified type, in which case
// it is the unqualified version of the type of the left operand. // it is the unqualified version of the type of the left operand.
@ -1583,7 +1510,7 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
// is converted to the type of the assignment expression (above). // is converted to the type of the assignment expression (above).
// C++ 5.17p1: the type of the assignment expression is that of its left // C++ 5.17p1: the type of the assignment expression is that of its left
// oprdu. // oprdu.
return hadError ? QualType() : lhsType.getUnqualifiedType(); return lhsType.getUnqualifiedType();
} }
inline QualType Sema::CheckCommaOperands( // C99 6.5.17 inline QualType Sema::CheckCommaOperands( // C99 6.5.17
@ -2097,18 +2024,14 @@ Sema::ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
ExprTy *expr, TypeTy *type, ExprTy *expr, TypeTy *type,
SourceLocation RPLoc) SourceLocation RPLoc) {
{
Expr *E = static_cast<Expr*>(expr); Expr *E = static_cast<Expr*>(expr);
QualType T = QualType::getFromOpaquePtr(type); QualType T = QualType::getFromOpaquePtr(type);
InitBuiltinVaListType(); InitBuiltinVaListType();
Sema::AssignmentCheckResult result; if (CheckAssignmentConstraints(Context.getBuiltinVaListType(), E->getType())
!= Compatible)
result = CheckAssignmentConstraints(Context.getBuiltinVaListType(),
E->getType());
if (result != Compatible)
return Diag(E->getLocStart(), return Diag(E->getLocStart(),
diag::err_first_argument_to_va_arg_not_of_type_va_list, diag::err_first_argument_to_va_arg_not_of_type_va_list,
E->getType().getAsString(), E->getType().getAsString(),
@ -2206,6 +2129,39 @@ Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc); return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc);
} }
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
Expr *SrcExpr, const char *Flavor) {
// Decode the result (notice that AST's are still created for extensions).
bool isInvalid = false;
unsigned DiagKind;
switch (ConvTy) {
default: assert(0 && "Unknown conversion type");
case Compatible: return false;
case PointerInt:
DiagKind = diag::ext_typecheck_convert_pointer_int;
break;
case IncompatiblePointer:
DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
break;
case FunctionVoidPointer:
DiagKind = diag::ext_typecheck_convert_pointer_void_func;
break;
case CompatiblePointerDiscardsQualifiers:
DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
break;
case Incompatible:
DiagKind = diag::err_typecheck_convert_incompatible;
isInvalid = true;
break;
}
Diag(Loc, DiagKind, DstType.getAsString(), SrcType.getAsString(), Flavor,
SrcExpr->getSourceRange());
return isInvalid;
}
bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
ObjcMethodDecl *Method) { ObjcMethodDecl *Method) {
bool anyIncompatibleArgs = false; bool anyIncompatibleArgs = false;
@ -2223,44 +2179,14 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
else if (lhsType->isFunctionType()) else if (lhsType->isFunctionType())
lhsType = Context.getPointerType(lhsType); lhsType = Context.getPointerType(lhsType);
AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType, AssignConvertType Result = CheckSingleAssignmentConstraints(lhsType,
argExpr); argExpr);
if (Args[i] != argExpr) // The expression was converted. if (Args[i] != argExpr) // The expression was converted.
Args[i] = argExpr; // Make sure we store the converted expression. Args[i] = argExpr; // Make sure we store the converted expression.
SourceLocation l = argExpr->getLocStart();
anyIncompatibleArgs |=
// Decode the result (notice that AST's are still created for extensions). DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
const char *Kind = "sending"; argExpr, "sending");
switch (result) {
case Compatible:
break;
case PointerFromInt:
case IntFromPointer:
Diag(l, diag::ext_typecheck_convert_pointer_int,
lhsType.getAsString(), rhsType.getAsString(), Kind,
argExpr->getSourceRange());
break;
case IncompatiblePointer:
Diag(l, diag::ext_typecheck_convert_incompatible_pointer,
lhsType.getAsString(), rhsType.getAsString(), Kind,
argExpr->getSourceRange());
break;
case FunctionVoidPointer:
Diag(l, diag::ext_typecheck_convert_pointer_void_func,
lhsType.getAsString(), rhsType.getAsString(), Kind,
argExpr->getSourceRange());
break;
case CompatiblePointerDiscardsQualifiers:
Diag(l, diag::ext_typecheck_convert_discards_qualifiers,
lhsType.getAsString(), rhsType.getAsString(), Kind,
argExpr->getSourceRange());
break;
case Incompatible:
Diag(l, diag::err_typecheck_convert_incompatible,
lhsType.getAsString(), rhsType.getAsString(), Kind,
argExpr->getSourceRange());
anyIncompatibleArgs = true;
}
} }
return anyIncompatibleArgs; return anyIncompatibleArgs;
} }

View File

@ -616,10 +616,10 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
Action::StmtResult Action::StmtResult
Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) { Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
Expr *RetValExp = static_cast<Expr *>(rex); Expr *RetValExp = static_cast<Expr *>(rex);
QualType lhsType = CurFunctionDecl ? CurFunctionDecl->getResultType() : QualType FnRetType = CurFunctionDecl ? CurFunctionDecl->getResultType() :
CurMethodDecl->getResultType(); CurMethodDecl->getResultType();
if (lhsType->isVoidType()) { if (FnRetType->isVoidType()) {
if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns) if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns)
Diag(ReturnLoc, diag::ext_return_has_expr, Diag(ReturnLoc, diag::ext_return_has_expr,
(CurFunctionDecl ? CurFunctionDecl->getIdentifier()->getName() : (CurFunctionDecl ? CurFunctionDecl->getIdentifier()->getName() :
@ -639,51 +639,18 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
} }
} }
// we have a non-void function with an expression, continue checking // we have a non-void function with an expression, continue checking
QualType rhsType = RetValExp->getType(); QualType RetValType = RetValExp->getType();
// C99 6.8.6.4p3(136): The return statement is not an assignment. The // 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 // overlap restriction of subclause 6.5.16.1 does not apply to the case of
// function return. // function return.
AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType, AssignConvertType ConvTy = CheckSingleAssignmentConstraints(FnRetType,
RetValExp); RetValExp);
if (DiagnoseAssignmentResult(ConvTy, ReturnLoc, FnRetType,
// decode the result (notice that extensions still return a type). RetValType, RetValExp, "returning"))
switch (result) { return true;
case Compatible:
break;
case Incompatible:
Diag(ReturnLoc, diag::err_typecheck_return_incompatible,
lhsType.getAsString(), rhsType.getAsString(),
RetValExp->getSourceRange());
break;
case PointerFromInt:
Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
lhsType.getAsString(), rhsType.getAsString(),
RetValExp->getSourceRange());
break;
case IntFromPointer:
Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
lhsType.getAsString(), rhsType.getAsString(),
RetValExp->getSourceRange());
break;
case FunctionVoidPointer:
Diag(ReturnLoc, diag::ext_typecheck_return_pointer_void_func,
lhsType.getAsString(), rhsType.getAsString(),
RetValExp->getSourceRange());
break;
case IncompatiblePointer:
Diag(ReturnLoc, diag::ext_typecheck_return_incompatible_pointer,
lhsType.getAsString(), rhsType.getAsString(),
RetValExp->getSourceRange());
break;
case CompatiblePointerDiscardsQualifiers:
Diag(ReturnLoc, diag::ext_typecheck_return_discards_qualifiers,
lhsType.getAsString(), rhsType.getAsString(),
RetValExp->getSourceRange());
break;
}
if (RetValExp) CheckReturnStackAddr(RetValExp, lhsType, ReturnLoc); if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
return new ReturnStmt(ReturnLoc, (Expr*)RetValExp); return new ReturnStmt(ReturnLoc, (Expr*)RetValExp);
} }

View File

@ -764,6 +764,7 @@ DIAG(ext_typecheck_comparison_of_distinct_pointers, WARNING,
DIAG(err_typecheck_assign_const, ERROR, DIAG(err_typecheck_assign_const, ERROR,
"read-only variable is not assignable") "read-only variable is not assignable")
// assignment related diagnostics (also for argument passing, returning, etc).
DIAG(err_typecheck_convert_incompatible, ERROR, DIAG(err_typecheck_convert_incompatible, ERROR,
"incompatible type %2 '%1', expected '%0'") "incompatible type %2 '%1', expected '%0'")
DIAG(ext_typecheck_convert_pointer_int, EXTENSION, DIAG(ext_typecheck_convert_pointer_int, EXTENSION,
@ -771,47 +772,9 @@ DIAG(ext_typecheck_convert_pointer_int, EXTENSION,
DIAG(ext_typecheck_convert_pointer_void_func, EXTENSION, DIAG(ext_typecheck_convert_pointer_void_func, EXTENSION,
"%2 '%1' converts between void* and function pointer, expected '%0'") "%2 '%1' converts between void* and function pointer, expected '%0'")
DIAG(ext_typecheck_convert_incompatible_pointer, EXTENSION, DIAG(ext_typecheck_convert_incompatible_pointer, EXTENSION,
"incompatible pointer types %d '%1', expected '%0'") "incompatible pointer types %2 '%1', expected '%0'")
DIAG(ext_typecheck_convert_discards_qualifiers, EXTENSION, DIAG(ext_typecheck_convert_discards_qualifiers, EXTENSION,
"%d '%1' discards qualifiers, expected '%0'") "%2 '%1' discards qualifiers, expected '%0'")
DIAG(err_typecheck_return_incompatible, ERROR,
"incompatible type returning '%1', expected '%0'")
DIAG(ext_typecheck_return_pointer_int, EXTENSION,
"incompatible type returning '%1', expected '%0'")
DIAG(ext_typecheck_return_pointer_void_func, EXTENSION,
"returning '%1' to from function expecting '%0' converts between void*"
" and function pointer")
DIAG(ext_typecheck_return_incompatible_pointer, EXTENSION,
"incompatible pointer types returning '%1', expected '%0'")
DIAG(ext_typecheck_return_discards_qualifiers, EXTENSION,
"returning '%1' from function expecting '%0' discards qualifiers")
DIAG(err_typecheck_assign_incompatible, ERROR,
"incompatible types assigning '%1' to '%0'")
DIAG(ext_typecheck_assign_pointer_int, WARNING,
"incompatible types assigning '%1' to '%0'")
DIAG(ext_typecheck_assign_incompatible_pointer, WARNING,
"incompatible pointer types assigning '%1' to '%0'")
DIAG(ext_typecheck_assign_discards_qualifiers, WARNING,
"assigning '%1' to '%0' discards qualifiers")
DIAG(ext_typecheck_assign_pointer_void_func, EXTENSION,
"assigning '%1' to '%0' converts between void* and function pointer")
DIAG(err_typecheck_passing_incompatible, ERROR,
"incompatible types passing '%0' to function expecting '%1'")
DIAG(ext_typecheck_passing_incompatible_pointer, WARNING,
"incompatible pointer types passing '%0' to function expecting '%1'")
DIAG(ext_typecheck_passing_pointer_int, WARNING,
"incompatible types passing '%1' to function expecting '%0'")
DIAG(ext_typecheck_passing_pointer_void_func, EXTENSION,
"passing '%1' to function expecting '%0' converts between void*"
" and function pointer")
DIAG(ext_typecheck_passing_discards_qualifiers, WARNING,
"passing '%0' to '%1' discards qualifiers")
DIAG(err_typecheck_array_not_modifiable_lvalue, ERROR, DIAG(err_typecheck_array_not_modifiable_lvalue, ERROR,
"array type '%0' is not assignable") "array type '%0' is not assignable")

View File

@ -35,7 +35,7 @@ static void test()
struct xx { int a; } x, y; struct xx { int a; } x, y;
c = __builtin_choose_expr(a+3-7, b, x); // expected-error{{'__builtin_choose_expr' requires a constant expression}} c = __builtin_choose_expr(a+3-7, b, x); // expected-error{{'__builtin_choose_expr' requires a constant expression}}
c = __builtin_choose_expr(0, b, x); // expected-error{{incompatible types assigning 'struct xx' to 'int'}} c = __builtin_choose_expr(0, b, x); // expected-error{{incompatible type assigning 'struct xx', expected 'int'}}
c = __builtin_choose_expr(5+3-7, b, x); c = __builtin_choose_expr(5+3-7, b, x);
y = __builtin_choose_expr(4+3-7, b, x); y = __builtin_choose_expr(4+3-7, b, x);

View File

@ -1,4 +1,4 @@
// RUN: clang -fsyntax-only -verify %s // RUN: clang -fsyntax-only -verify -pedantic %s
_Complex double X; _Complex double X;
void test1(int c) { void test1(int c) {
X = 5; X = 5;
@ -14,7 +14,7 @@ void test2() {
} }
int test3() { int test3() {
int a[2]; int a[2];
a[0] = test3; // expected-warning{{incompatible types assigning 'int (void)' to 'int'}} a[0] = test3; // expected-warning{{incompatible pointer/int conversion assigning 'int (void)', expected 'int'}}
} }
short x; void test4(char c) { x += c; } short x; void test4(char c) { x += c; }
int y; void test5(char c) { y += c; } int y; void test5(char c) { y += c; }

View File

@ -16,8 +16,4 @@ static void test() {
const typeof (*pi) aConstInt; const typeof (*pi) aConstInt;
int xx; int xx;
int *i; int *i;
i = aci; // expected-warning{{incompatible types assigning 'typeof(int const)' to 'int *'}}
i = anInt; // expected-warning{{incompatible types assigning 'typeof(TInt)' to 'int *'}}
i = aConstInt; // expected-warning{{incompatible types assigning 'typeof(*pi) const' to 'int *'}}
i = xx; // expected-warning{{incompatible types assigning 'int' to 'int *'}}
} }

View File

@ -16,8 +16,8 @@ void test() {
id obj = [Test alloc]; id obj = [Test alloc];
struct S sInst; struct S sInst;
charStarFunc(1); // expected-warning {{incompatible types passing 'int' to function expecting 'char *'}} charStarFunc(1); // expected-warning {{incompatible pointer/int conversion passing 'int', expected 'char *'}}
charFunc("abc"); // expected-warning {{incompatible types passing 'char *' to function expecting 'char'}} charFunc("abc"); // expected-warning {{incompatible pointer/int conversion passing 'char *', expected 'char'}}
[obj charStarMeth:1]; // expected-warning {{incompatible pointer/int conversion sending 'int'}} [obj charStarMeth:1]; // expected-warning {{incompatible pointer/int conversion sending 'int'}}
[obj structMeth:1]; // expected-error {{incompatible type sending 'int'}} [obj structMeth:1]; // expected-error {{incompatible type sending 'int'}}

View File

@ -45,7 +45,7 @@ typedef int TA[I]; // expected-error {{variable length array declared outside of
void strFunc(char *); void strFunc(char *);
const char staticAry[] = "test"; const char staticAry[] = "test";
int checkStaticAry() { int checkStaticAry() {
strFunc(staticAry); // expected-warning{{passing 'char const [5]' to 'char *' discards qualifiers}} strFunc(staticAry); // expected-warning{{passing 'char const [5]' discards qualifiers, expected 'char *'}}
} }

View File

@ -9,7 +9,7 @@ int ary2[] = { x, y, z }; // expected-error{{initializer element is not constant
extern int fileScopeExtern[3] = { 1, 3, 5 }; // expected-warning{{'extern' variable has an initializer}} extern int fileScopeExtern[3] = { 1, 3, 5 }; // expected-warning{{'extern' variable has an initializer}}
static int ary3[] = { 1, "abc", 3, 4 }; // expected-warning{{incompatible types assigning 'char *' to 'int'}} static int ary3[] = { 1, "abc", 3, 4 }; // expected-warning{{incompatible pointer/int conversion initializing 'char *', expected 'int'}}
void func() { void func() {
int x = 1; int x = 1;
@ -44,11 +44,11 @@ void func() {
int a,b,c; int a,b,c;
} z = { 1 }; } z = { 1 };
struct threeElements *p = 7; // expected-warning{{incompatible types assigning 'int' to 'struct threeElements *'}} struct threeElements *p = 7; // expected-warning{{incompatible pointer/int conversion initializing 'int', expected 'struct threeElements *'}}
extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{'extern' variable cannot have an initializer}} extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{'extern' variable cannot have an initializer}}
static int x2[3] = { 1.0, "abc" , 5.8 }; // expected-warning{{incompatible types assigning 'char *' to 'int'}} static int x2[3] = { 1.0, "abc" , 5.8 }; // expected-warning{{incompatible pointer/int conversion initializing 'char *', expected 'int'}}
} }
void test() { void test() {

View File

@ -1,4 +1,4 @@
// RUN: clang %s -fsyntax-only -verify // RUN: clang %s -fsyntax-only -verify -pedantic
int test1(float a, int b) { int test1(float a, int b) {
return __builtin_isless(a, b); return __builtin_isless(a, b);
@ -26,8 +26,7 @@ int test6(float a, long double b) {
void cfstring() { void cfstring() {
CFSTR("\242"); // expected-warning {{ CFString literal contains non-ASCII character }} CFSTR("\242"); // expected-warning {{ CFString literal contains non-ASCII character }}
CFSTR("\0"); // expected-warning {{ CFString literal contains NUL character }} CFSTR("\0"); // expected-warning {{ CFString literal contains NUL character }}
CFSTR(242); // expected-error {{ CFString literal is not a string constant }} \ CFSTR(242); // expected-error {{ CFString literal is not a string constant }} expected-warning {{incompatible pointer/int conversion}}
expected-warning {{incompatible types}}
CFSTR("foo", "bar"); // expected-error {{ error: too many arguments to function }} CFSTR("foo", "bar"); // expected-error {{ error: too many arguments to function }}
} }

View File

@ -21,7 +21,7 @@ INTF <MyProto1> * Func1(INTF <MyProto1, MyProto2> *p2)
INTF <MyProto1, MyProto2> * Func2(INTF <MyProto1> *p2) INTF <MyProto1, MyProto2> * Func2(INTF <MyProto1> *p2)
{ {
Func(p2); // expected-warning {{incompatible pointer types passing 'INTF<MyProto1> *' to function expecting 'INTF<MyProto1,MyProto2> *}} Func(p2); // expected-warning {{incompatible pointer types passing 'INTF<MyProto1> *', expected 'INTF<MyProto1,MyProto2> *}}
return p2; // expected-warning {{incompatible pointer types returning 'INTF<MyProto1> *', expected 'INTF<MyProto1,MyProto2> *}} return p2; // expected-warning {{incompatible pointer types returning 'INTF<MyProto1> *', expected 'INTF<MyProto1,MyProto2> *}}
} }

View File

@ -1,4 +1,4 @@
// RUN: clang -fsyntax-only -verify %s // RUN: clang -fsyntax-only -verify -pedantic %s
#include <objc/objc.h> #include <objc/objc.h>
@ -33,25 +33,25 @@ int main()
/* Assigning to a 'MyClass *' variable should always generate a /* Assigning to a 'MyClass *' variable should always generate a
warning, unless done from an 'id'. */ warning, unless done from an 'id'. */
obj_c = obj; /* Ok */ obj_c = obj; /* Ok */
obj_c = obj_cp; // // expected-warning {{incompatible pointer types assigning 'MyOtherClass *' to 'MyClass *'}} obj_c = obj_cp; // // expected-warning {{incompatible pointer types assigning 'MyOtherClass *', expected 'MyClass *'}}
obj_c = obj_C; // expected-warning {{incompatible pointer types assigning 'Class' to 'MyClass *'}} obj_c = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'MyClass *'}}
/* Assigning to an 'id<MyProtocol>' variable should generate a /* Assigning to an 'id<MyProtocol>' variable should generate a
warning if done from a 'MyClass *' (which doesn't implement warning if done from a 'MyClass *' (which doesn't implement
MyProtocol), but not from an 'id' or from a 'MyOtherClass *' MyProtocol), but not from an 'id' or from a 'MyOtherClass *'
(which implements MyProtocol). */ (which implements MyProtocol). */
obj_p = obj; /* Ok */ obj_p = obj; /* Ok */
obj_p = obj_c; // expected-error {{incompatible types assigning 'MyClass *' to 'id<MyProtocol>'}} obj_p = obj_c; // expected-error {{incompatible type assigning 'MyClass *', expected 'id<MyProtocol>'}}
obj_p = obj_cp; /* Ok */ obj_p = obj_cp; /* Ok */
obj_p = obj_C; // expected-error {{incompatible types assigning 'Class' to 'id<MyProtocol>'}} obj_p = obj_C; // expected-error {{incompatible type assigning 'Class', expected 'id<MyProtocol>'}}
/* Assigning to a 'MyOtherClass *' variable should always generate /* Assigning to a 'MyOtherClass *' variable should always generate
a warning, unless done from an 'id' or an 'id<MyProtocol>' (since a warning, unless done from an 'id' or an 'id<MyProtocol>' (since
MyOtherClass implements MyProtocol). */ MyOtherClass implements MyProtocol). */
obj_cp = obj; /* Ok */ obj_cp = obj; /* Ok */
obj_cp = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *' to 'MyOtherClass *'}} obj_cp = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'MyOtherClass *'}}
obj_cp = obj_p; /* Ok */ obj_cp = obj_p; /* Ok */
obj_cp = obj_C; // expected-warning {{incompatible pointer types assigning 'Class' to 'MyOtherClass *'}} obj_cp = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'MyOtherClass *'}}
/* Any comparison involving an 'id' must be without warnings. */ /* Any comparison involving an 'id' must be without warnings. */
if (obj == obj_p) foo() ; /* Ok */ /*Bogus warning here in 2.95.4*/ if (obj == obj_p) foo() ; /* Ok */ /*Bogus warning here in 2.95.4*/

View File

@ -24,21 +24,21 @@ int main()
id<MyProtocolAB> obj_ab = nil; id<MyProtocolAB> obj_ab = nil;
id<MyProtocolAC> obj_ac = nil; id<MyProtocolAC> obj_ac = nil;
obj_a = obj_b; // expected-error {{incompatible types assigning 'id<MyProtocolB>' to 'id<MyProtocolA>'}} obj_a = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolA>'}}
obj_a = obj_ab; /* Ok */ obj_a = obj_ab; /* Ok */
obj_a = obj_ac; /* Ok */ obj_a = obj_ac; /* Ok */
obj_b = obj_a; // expected-error {{incompatible types assigning 'id<MyProtocolA>' to 'id<MyProtocolB>'}} obj_b = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolB>'}}
obj_b = obj_ab; /* Ok */ obj_b = obj_ab; /* Ok */
obj_b = obj_ac; // expected-error {{incompatible types assigning 'id<MyProtocolAC>' to 'id<MyProtocolB>'}} obj_b = obj_ac; // expected-error {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolB>'}}
obj_ab = obj_a; // expected-error {{incompatible types assigning 'id<MyProtocolA>' to 'id<MyProtocolAB>'}} obj_ab = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAB>'}}
obj_ab = obj_b; // expected-error {{incompatible types assigning 'id<MyProtocolB>' to 'id<MyProtocolAB>'}} obj_ab = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAB>'}}
obj_ab = obj_ac; // expected-error {{incompatible types assigning 'id<MyProtocolAC>' to 'id<MyProtocolAB>'}} obj_ab = obj_ac; // expected-error {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolAB>'}}
obj_ac = obj_a; // expected-error {{incompatible types assigning 'id<MyProtocolA>' to 'id<MyProtocolAC>'}} obj_ac = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAC>'}}
obj_ac = obj_b; // expected-error {{incompatible types assigning 'id<MyProtocolB>' to 'id<MyProtocolAC>'}} obj_ac = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAC>'}}
obj_ac = obj_ab; // expected-error {{incompatible types assigning 'id<MyProtocolAB>' to 'id<MyProtocolAC>'}} obj_ac = obj_ab; // expected-error {{incompatible type assigning 'id<MyProtocolAB>', expected 'id<MyProtocolAC>'}}
if (obj_a == obj_b) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolA>' and 'id<MyProtocolB>')}} if (obj_a == obj_b) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolA>' and 'id<MyProtocolB>')}}
if (obj_b == obj_a) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}} if (obj_b == obj_a) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}}

View File

@ -23,8 +23,8 @@ int main()
MyClass *obj_c_cat_p = nil; MyClass *obj_c_cat_p = nil;
MyOtherClass *obj_c_super_p = nil; MyOtherClass *obj_c_super_p = nil;
obj_c_cat_p = obj_id_p; // expected-error {{incompatible types assigning 'id<MyProtocol>' to 'MyClass *'}} obj_c_cat_p = obj_id_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'MyClass *'}}
obj_c_super_p = obj_id_p; // expected-error {{incompatible types assigning 'id<MyProtocol>' to 'MyOtherClass *'}} obj_c_super_p = obj_id_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'MyOtherClass *'}}
obj_id_p = obj_c_cat_p; /* Ok */ obj_id_p = obj_c_cat_p; /* Ok */
obj_id_p = obj_c_super_p; /* Ok */ obj_id_p = obj_c_super_p; /* Ok */

View File

@ -1,4 +1,4 @@
// RUN: clang -fsyntax-only -verify %s // RUN: clang -fsyntax-only -verify -pedantic %s
#include <objc/Object.h> #include <objc/Object.h>
@ -9,7 +9,7 @@ extern Object* foo(void);
static Derived *test(void) static Derived *test(void)
{ {
Derived *m = foo(); // expected-warning {{incompatible pointer types assigning 'Object *' to 'Derived *'}} Derived *m = foo(); // expected-warning {{incompatible pointer types initializing 'Object *', expected 'Derived *'}}
return m; return m;
} }

View File

@ -1,4 +1,4 @@
// RUN: clang -fsyntax-only -verify %s // RUN: clang -fsyntax-only -verify -pedantic %s
#include <objc/objc.h> #include <objc/objc.h>
@ -23,27 +23,27 @@ int main()
/* These should all generate warnings. */ /* These should all generate warnings. */
obj = i; // expected-warning {{incompatible types assigning 'int' to 'id'}} obj = i; // expected-warning {{incompatible pointer/int conversion assigning 'int', expected 'id'}}
obj = j; // expected-warning {{incompatible pointer types assigning 'int *' to 'id'}} obj = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'id'}}
obj_p = i; // expected-error {{incompatible types assigning 'int' to 'id<MyProtocol>' }} obj_p = i; // expected-error {{incompatible type assigning 'int', expected 'id<MyProtocol>' }}
obj_p = j; // expected-error {{incompatible types assigning 'int *' to 'id<MyProtocol>'}} obj_p = j; // expected-error {{incompatible type assigning 'int *', expected 'id<MyProtocol>'}}
obj_c = i; // expected-warning {{incompatible types assigning 'int' to 'MyClass *'}} obj_c = i; // expected-warning {{incompatible pointer/int conversion assigning 'int', expected 'MyClass *'}}
obj_c = j; // expected-warning {{incompatible pointer types assigning 'int *' to 'MyClass *'}} obj_c = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'MyClass *'}}
obj_C = i; // expected-warning {{incompatible types assigning 'int' to 'Class'}} obj_C = i; // expected-warning {{incompatible pointer/int conversion assigning 'int', expected 'Class'}}
obj_C = j; // expected-warning {{incompatible pointer types assigning 'int *' to 'Class'}} obj_C = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'Class'}}
i = obj; // expected-warning {{incompatible types assigning 'id' to 'int'}} i = obj; // expected-warning {{incompatible pointer/int conversion assigning 'id', expected 'int'}}
i = obj_p; // expected-error {{incompatible types assigning 'id<MyProtocol>' to 'int'}} i = obj_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'int'}}
i = obj_c; // expected-warning {{incompatible types assigning 'MyClass *' to 'int'}} i = obj_c; // expected-warning {{incompatible pointer/int conversion assigning 'MyClass *', expected 'int'}}
i = obj_C; // expected-warning {{incompatible types assigning 'Class' to 'int'}} i = obj_C; // expected-warning {{incompatible pointer/int conversion assigning 'Class', expected 'int'}}
j = obj; // expected-warning {{incompatible pointer types assigning 'id' to 'int *'}} j = obj; // expected-warning {{incompatible pointer types assigning 'id', expected 'int *'}}
j = obj_p; // expected-error {{incompatible types assigning 'id<MyProtocol>' to 'int *'}} j = obj_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'int *'}}
j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *' to 'int *'}} j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'int *'}}
j = obj_C; // expected-warning {{incompatible pointer types assigning 'Class' to 'int *'}} j = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'int *'}}
if (obj == i) foo() ; // expected-warning {{comparison between pointer and integer ('id' and 'int')}} if (obj == i) foo() ; // expected-warning {{comparison between pointer and integer ('id' and 'int')}}
if (i == obj) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'id')}} if (i == obj) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'id')}}

View File

@ -29,7 +29,7 @@ id<MyProto1> Func(INTF <MyProto1, MyProto2> *p2)
id<MyProto1, MyProto2> Gunc2(id <MyProto1>p2) id<MyProto1, MyProto2> Gunc2(id <MyProto1>p2)
{ {
Func(p2); // expected-error {{incompatible types passing 'id<MyProto1>' to function expecting 'INTF<MyProto1,MyProto2> *'}} Func(p2); // expected-error {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
return p2; // expected-error {{incompatible type returning 'id<MyProto1>', expected 'id<MyProto1,MyProto2>'}} return p2; // expected-error {{incompatible type returning 'id<MyProto1>', expected 'id<MyProto1,MyProto2>'}}
} }
@ -61,7 +61,7 @@ INTF<MyProto1> * Hunc1(id <MyProto1, MyProto2>p2)
INTF<MyProto1, MyProto2> * Hunc2(id <MyProto1>p2) INTF<MyProto1, MyProto2> * Hunc2(id <MyProto1>p2)
{ {
Func(p2); // expected-error {{incompatible types passing 'id<MyProto1>' to function expecting 'INTF<MyProto1,MyProto2> *'}} Func(p2); // expected-error {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
return p2; // expected-error {{incompatible type returning 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}} return p2; // expected-error {{incompatible type returning 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}}
} }

View File

@ -5,10 +5,10 @@ typedef int int4 __attribute__((vector_size(16)));
typedef int4* int4p; typedef int4* int4p;
void test1(float4 a, int4 *result, int i) { void test1(float4 a, int4 *result, int i) {
result[i] = a; // expected-error {{assigning 'float4' to 'int4'}} result[i] = a; // expected-error {{assigning 'float4', expected 'int4'}}
} }
void test2(float4 a, int4p result, int i) { void test2(float4 a, int4p result, int i) {
result[i] = a; // expected-error {{assigning 'float4' to 'int4'}} result[i] = a; // expected-error {{assigning 'float4', expected 'int4'}}
} }

View File

@ -13,27 +13,27 @@ void f() {
v4ss v5; v4ss v5;
v1 = v2; v1 = v2;
v1 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v2s'}} v1 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2s'}}
v1 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v2s'}} v1 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v2s'}}
v1 = v5; v1 = v5;
v2 = v1; v2 = v1;
v2 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v2u'}} v2 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2u'}}
v2 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v2u'}} v2 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v2u'}}
v2 = v5; v2 = v5;
v3 = v1; // expected-error {{incompatible types assigning 'v2s' to 'v1s'}} v3 = v1; // expected-error {{incompatible type assigning 'v2s', expected 'v1s'}}
v3 = v2; // expected-error {{incompatible types assigning 'v2u' to 'v1s'}} v3 = v2; // expected-error {{incompatible type assigning 'v2u', expected 'v1s'}}
v3 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v1s'}} v3 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v1s'}}
v3 = v5; // expected-error {{incompatible types assigning 'v4ss' to 'v1s'}} v3 = v5; // expected-error {{incompatible type assigning 'v4ss', expected 'v1s'}}
v4 = v1; // expected-error {{incompatible types assigning 'v2s' to 'v2f'}} v4 = v1; // expected-error {{incompatible type assigning 'v2s', expected 'v2f'}}
v4 = v2; // expected-error {{incompatible types assigning 'v2u' to 'v2f'}} v4 = v2; // expected-error {{incompatible type assigning 'v2u', expected 'v2f'}}
v4 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v2f'}} v4 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2f'}}
v4 = v5; // expected-error {{incompatible types assigning 'v4ss' to 'v2f'}} v4 = v5; // expected-error {{incompatible type assigning 'v4ss', expected 'v2f'}}
v5 = v1; v5 = v1;
v5 = v2; v5 = v2;
v5 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v4ss'}} v5 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v4ss'}}
v5 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v4ss'}} v5 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v4ss'}}
} }