forked from OSchip/llvm-project
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:
parent
d98c63ebb9
commit
9bad62c72a
|
@ -613,34 +613,42 @@ private:
|
|||
// responsible for emitting appropriate error diagnostics.
|
||||
QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr,
|
||||
bool isCompAssign = false);
|
||||
enum AssignmentCheckResult {
|
||||
enum AssignConvertType {
|
||||
Compatible,
|
||||
Incompatible,
|
||||
PointerFromInt,
|
||||
IntFromPointer,
|
||||
PointerInt,
|
||||
FunctionVoidPointer,
|
||||
IncompatiblePointer,
|
||||
CompatiblePointerDiscardsQualifiers
|
||||
};
|
||||
// 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.
|
||||
AssignmentCheckResult CheckAssignmentConstraints(QualType lhs, QualType rhs);
|
||||
|
||||
/// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
|
||||
/// assignment conversion type specified by ConvTy. This returns true if the
|
||||
/// 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,
|
||||
// CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
|
||||
// this routine performs the default function/array converions.
|
||||
AssignmentCheckResult CheckSingleAssignmentConstraints(QualType lhs,
|
||||
Expr *&rExpr);
|
||||
AssignConvertType CheckSingleAssignmentConstraints(QualType lhs,
|
||||
Expr *&rExpr);
|
||||
// CheckCompoundAssignmentConstraints - Type check without performing any
|
||||
// conversions. For compound assignments, the "Check...Operands" methods
|
||||
// perform the necessary conversions.
|
||||
AssignmentCheckResult CheckCompoundAssignmentConstraints(QualType lhs,
|
||||
QualType rhs);
|
||||
AssignConvertType CheckCompoundAssignmentConstraints(QualType lhs,
|
||||
QualType rhs);
|
||||
|
||||
// Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
|
||||
AssignmentCheckResult CheckPointerTypesForAssignment(QualType lhsType,
|
||||
QualType rhsType);
|
||||
AssignConvertType CheckPointerTypesForAssignment(QualType lhsType,
|
||||
QualType rhsType);
|
||||
|
||||
/// the following "Check" methods will return a valid/converted QualType
|
||||
/// or a null QualType (indicating an error diagnostic was issued).
|
||||
|
|
|
@ -364,53 +364,13 @@ bool Sema::CheckSingleInitializer(Expr *&Init, bool isStatic,
|
|||
return true;
|
||||
}
|
||||
|
||||
AssignmentCheckResult result;
|
||||
// Get the type before calling CheckSingleAssignmentConstraints(), since
|
||||
// it can promote the expression.
|
||||
QualType rhsType = Init->getType();
|
||||
QualType InitType = Init->getType();
|
||||
|
||||
result = CheckSingleAssignmentConstraints(DeclType, Init);
|
||||
|
||||
// decode the result (notice that extensions still return a type).
|
||||
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;
|
||||
AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
|
||||
return DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
|
||||
InitType, Init, "initializing");
|
||||
}
|
||||
|
||||
bool Sema::CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot,
|
||||
|
|
|
@ -615,55 +615,17 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc,
|
|||
// Continue to check argument types (even if we have too few/many args).
|
||||
for (unsigned i = 0; i != NumArgsToCheck; i++) {
|
||||
Expr *Arg = Args[i];
|
||||
QualType LHSType = Proto->getArgType(i);
|
||||
QualType RHSType = 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);
|
||||
QualType ProtoArgType = Proto->getArgType(i);
|
||||
QualType ArgType = Arg->getType();
|
||||
|
||||
// Compute implicit casts from the operand to the formal argument type.
|
||||
AssignmentCheckResult Result =
|
||||
CheckSingleAssignmentConstraints(LHSType, Arg);
|
||||
AssignConvertType ConvTy =
|
||||
CheckSingleAssignmentConstraints(ProtoArgType, Arg);
|
||||
TheCall->setArg(i, Arg);
|
||||
|
||||
// Decode the result (notice that AST's are still created for extensions).
|
||||
SourceLocation Loc = Arg->getLocStart();
|
||||
switch (Result) {
|
||||
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 (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), ProtoArgType,
|
||||
ArgType, Arg, "passing"))
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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.
|
||||
// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
|
||||
// FIXME: add a couple examples in this comment.
|
||||
Sema::AssignmentCheckResult
|
||||
Sema::AssignConvertType
|
||||
Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
|
||||
QualType lhptee, rhptee;
|
||||
|
||||
|
@ -1068,21 +1030,21 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
|
|||
lhptee = lhptee.getCanonicalType();
|
||||
rhptee = rhptee.getCanonicalType();
|
||||
|
||||
AssignmentCheckResult r = Compatible;
|
||||
AssignConvertType ConvTy = Compatible;
|
||||
|
||||
// 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
|
||||
// qualifiers of the type *pointed to* by the right;
|
||||
if ((lhptee.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
|
||||
// incomplete type and the other is a pointer to a qualified or unqualified
|
||||
// version of void...
|
||||
if (lhptee->isVoidType()) {
|
||||
if (rhptee->isObjectType() || rhptee->isIncompleteType())
|
||||
return r;
|
||||
return ConvTy;
|
||||
|
||||
// As an extension, we allow cast to/from void* to function pointer.
|
||||
if (rhptee->isFunctionType())
|
||||
|
@ -1091,7 +1053,7 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
|
|||
|
||||
if (rhptee->isVoidType()) {
|
||||
if (lhptee->isObjectType() || lhptee->isIncompleteType())
|
||||
return r;
|
||||
return ConvTy;
|
||||
|
||||
// As an extension, we allow cast to/from void* to function pointer.
|
||||
if (lhptee->isFunctionType())
|
||||
|
@ -1103,7 +1065,7 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
|
|||
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
|
||||
rhptee.getUnqualifiedType()))
|
||||
return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
|
||||
return r;
|
||||
return ConvTy;
|
||||
}
|
||||
|
||||
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
|
||||
|
@ -1123,7 +1085,7 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
|
|||
/// C99 spec dictates.
|
||||
/// Note: the warning above turn into errors when -pedantic-errors is enabled.
|
||||
///
|
||||
Sema::AssignmentCheckResult
|
||||
Sema::AssignConvertType
|
||||
Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
||||
|
||||
|
||||
|
@ -1169,14 +1131,14 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
|||
return Compatible;
|
||||
} else if (lhsType->isPointerType()) {
|
||||
if (rhsType->isIntegerType())
|
||||
return PointerFromInt;
|
||||
return PointerInt;
|
||||
|
||||
if (rhsType->isPointerType())
|
||||
return CheckPointerTypesForAssignment(lhsType, rhsType);
|
||||
} else if (rhsType->isPointerType()) {
|
||||
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
|
||||
if ((lhsType->isIntegerType()) && (lhsType != Context.BoolTy))
|
||||
return IntFromPointer;
|
||||
return PointerInt;
|
||||
|
||||
if (lhsType->isPointerType())
|
||||
return CheckPointerTypesForAssignment(lhsType, rhsType);
|
||||
|
@ -1187,7 +1149,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
|||
return Incompatible;
|
||||
}
|
||||
|
||||
Sema::AssignmentCheckResult
|
||||
Sema::AssignConvertType
|
||||
Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
|
||||
// C99 6.5.16.1p1: the left operand is a pointer and the right is
|
||||
// a null pointer constant.
|
||||
|
@ -1206,9 +1168,8 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
|
|||
if (!lhsType->isReferenceType())
|
||||
DefaultFunctionArrayConversion(rExpr);
|
||||
|
||||
Sema::AssignmentCheckResult result;
|
||||
|
||||
result = CheckAssignmentConstraints(lhsType, rExpr->getType());
|
||||
Sema::AssignConvertType result =
|
||||
CheckAssignmentConstraints(lhsType, rExpr->getType());
|
||||
|
||||
// C99 6.5.16.1p2: The value of the right operand is converted to the
|
||||
// type of the assignment expression.
|
||||
|
@ -1217,7 +1178,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Sema::AssignmentCheckResult
|
||||
Sema::AssignConvertType
|
||||
Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
|
||||
return CheckAssignmentConstraints(lhsType, rhsType);
|
||||
}
|
||||
|
@ -1501,81 +1462,47 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
|
|||
{
|
||||
QualType lhsType = lex->getType();
|
||||
QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType;
|
||||
bool hadError = false;
|
||||
Expr::isModifiableLvalueResult mlval = lex->isModifiableLvalue();
|
||||
|
||||
switch (mlval) { // C99 6.5.16p2
|
||||
case Expr::MLV_Valid:
|
||||
break;
|
||||
case Expr::MLV_ConstQualified:
|
||||
Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange());
|
||||
hadError = true;
|
||||
break;
|
||||
case Expr::MLV_ArrayType:
|
||||
Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue,
|
||||
lhsType.getAsString(), lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_NotObjectType:
|
||||
Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue,
|
||||
lhsType.getAsString(), lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_InvalidExpression:
|
||||
Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue,
|
||||
lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_IncompleteType:
|
||||
case Expr::MLV_IncompleteVoidType:
|
||||
Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
|
||||
lhsType.getAsString(), lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_DuplicateVectorComponents:
|
||||
Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue,
|
||||
lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_Valid:
|
||||
break;
|
||||
case Expr::MLV_ConstQualified:
|
||||
Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_ArrayType:
|
||||
Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue,
|
||||
lhsType.getAsString(), lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_NotObjectType:
|
||||
Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue,
|
||||
lhsType.getAsString(), lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_InvalidExpression:
|
||||
Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue,
|
||||
lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_IncompleteType:
|
||||
case Expr::MLV_IncompleteVoidType:
|
||||
Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
|
||||
lhsType.getAsString(), lex->getSourceRange());
|
||||
return QualType();
|
||||
case Expr::MLV_DuplicateVectorComponents:
|
||||
Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue,
|
||||
lex->getSourceRange());
|
||||
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).
|
||||
switch (result) {
|
||||
case Compatible:
|
||||
break;
|
||||
case Incompatible:
|
||||
Diag(loc, diag::err_typecheck_assign_incompatible,
|
||||
lhsType.getAsString(), rhsType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
hadError = true;
|
||||
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;
|
||||
}
|
||||
AssignConvertType ConvTy;
|
||||
if (compoundType.isNull())
|
||||
ConvTy = CheckSingleAssignmentConstraints(lhsType, rex);
|
||||
else
|
||||
ConvTy = CheckCompoundAssignmentConstraints(lhsType, rhsType);
|
||||
|
||||
if (DiagnoseAssignmentResult(ConvTy, loc, lhsType, rhsType,
|
||||
rex, "assigning"))
|
||||
return QualType();
|
||||
|
||||
// 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
|
||||
// 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).
|
||||
// C++ 5.17p1: the type of the assignment expression is that of its left
|
||||
// oprdu.
|
||||
return hadError ? QualType() : lhsType.getUnqualifiedType();
|
||||
return lhsType.getUnqualifiedType();
|
||||
}
|
||||
|
||||
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,
|
||||
ExprTy *expr, TypeTy *type,
|
||||
SourceLocation RPLoc)
|
||||
{
|
||||
SourceLocation RPLoc) {
|
||||
Expr *E = static_cast<Expr*>(expr);
|
||||
QualType T = QualType::getFromOpaquePtr(type);
|
||||
|
||||
InitBuiltinVaListType();
|
||||
|
||||
Sema::AssignmentCheckResult result;
|
||||
|
||||
result = CheckAssignmentConstraints(Context.getBuiltinVaListType(),
|
||||
E->getType());
|
||||
if (result != Compatible)
|
||||
if (CheckAssignmentConstraints(Context.getBuiltinVaListType(), E->getType())
|
||||
!= Compatible)
|
||||
return Diag(E->getLocStart(),
|
||||
diag::err_first_argument_to_va_arg_not_of_type_va_list,
|
||||
E->getType().getAsString(),
|
||||
|
@ -2206,6 +2129,39 @@ Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
|
|||
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,
|
||||
ObjcMethodDecl *Method) {
|
||||
bool anyIncompatibleArgs = false;
|
||||
|
@ -2223,44 +2179,14 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
|
|||
else if (lhsType->isFunctionType())
|
||||
lhsType = Context.getPointerType(lhsType);
|
||||
|
||||
AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
|
||||
argExpr);
|
||||
AssignConvertType Result = CheckSingleAssignmentConstraints(lhsType,
|
||||
argExpr);
|
||||
if (Args[i] != argExpr) // The expression was converted.
|
||||
Args[i] = argExpr; // Make sure we store the converted expression.
|
||||
SourceLocation l = argExpr->getLocStart();
|
||||
|
||||
// Decode the result (notice that AST's are still created for extensions).
|
||||
const char *Kind = "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;
|
||||
}
|
||||
|
||||
anyIncompatibleArgs |=
|
||||
DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
|
||||
argExpr, "sending");
|
||||
}
|
||||
return anyIncompatibleArgs;
|
||||
}
|
||||
|
|
|
@ -616,10 +616,10 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
|
|||
Action::StmtResult
|
||||
Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
|
||||
Expr *RetValExp = static_cast<Expr *>(rex);
|
||||
QualType lhsType = CurFunctionDecl ? CurFunctionDecl->getResultType() :
|
||||
CurMethodDecl->getResultType();
|
||||
QualType FnRetType = CurFunctionDecl ? CurFunctionDecl->getResultType() :
|
||||
CurMethodDecl->getResultType();
|
||||
|
||||
if (lhsType->isVoidType()) {
|
||||
if (FnRetType->isVoidType()) {
|
||||
if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns)
|
||||
Diag(ReturnLoc, diag::ext_return_has_expr,
|
||||
(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
|
||||
QualType rhsType = RetValExp->getType();
|
||||
QualType RetValType = RetValExp->getType();
|
||||
|
||||
// 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
|
||||
// function return.
|
||||
AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
|
||||
RetValExp);
|
||||
|
||||
// decode the result (notice that extensions still return a type).
|
||||
switch (result) {
|
||||
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;
|
||||
}
|
||||
AssignConvertType ConvTy = CheckSingleAssignmentConstraints(FnRetType,
|
||||
RetValExp);
|
||||
if (DiagnoseAssignmentResult(ConvTy, ReturnLoc, FnRetType,
|
||||
RetValType, RetValExp, "returning"))
|
||||
return true;
|
||||
|
||||
if (RetValExp) CheckReturnStackAddr(RetValExp, lhsType, ReturnLoc);
|
||||
if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
|
||||
|
||||
return new ReturnStmt(ReturnLoc, (Expr*)RetValExp);
|
||||
}
|
||||
|
|
|
@ -764,6 +764,7 @@ DIAG(ext_typecheck_comparison_of_distinct_pointers, WARNING,
|
|||
DIAG(err_typecheck_assign_const, ERROR,
|
||||
"read-only variable is not assignable")
|
||||
|
||||
// assignment related diagnostics (also for argument passing, returning, etc).
|
||||
DIAG(err_typecheck_convert_incompatible, ERROR,
|
||||
"incompatible type %2 '%1', expected '%0'")
|
||||
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,
|
||||
"%2 '%1' converts between void* and function pointer, expected '%0'")
|
||||
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,
|
||||
"%d '%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")
|
||||
|
||||
"%2 '%1' discards qualifiers, expected '%0'")
|
||||
|
||||
DIAG(err_typecheck_array_not_modifiable_lvalue, ERROR,
|
||||
"array type '%0' is not assignable")
|
||||
|
|
|
@ -35,7 +35,7 @@ static void test()
|
|||
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(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);
|
||||
y = __builtin_choose_expr(4+3-7, b, x);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
// RUN: clang -fsyntax-only -verify -pedantic %s
|
||||
_Complex double X;
|
||||
void test1(int c) {
|
||||
X = 5;
|
||||
|
@ -14,7 +14,7 @@ void test2() {
|
|||
}
|
||||
int test3() {
|
||||
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; }
|
||||
int y; void test5(char c) { y += c; }
|
||||
|
|
|
@ -16,8 +16,4 @@ static void test() {
|
|||
const typeof (*pi) aConstInt;
|
||||
int xx;
|
||||
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 *'}}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ void test() {
|
|||
id obj = [Test alloc];
|
||||
struct S sInst;
|
||||
|
||||
charStarFunc(1); // expected-warning {{incompatible types passing 'int' to function expecting 'char *'}}
|
||||
charFunc("abc"); // expected-warning {{incompatible types passing 'char *' to function expecting 'char'}}
|
||||
charStarFunc(1); // expected-warning {{incompatible pointer/int conversion passing 'int', expected '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 structMeth:1]; // expected-error {{incompatible type sending 'int'}}
|
||||
|
|
|
@ -45,7 +45,7 @@ typedef int TA[I]; // expected-error {{variable length array declared outside of
|
|||
void strFunc(char *);
|
||||
const char staticAry[] = "test";
|
||||
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 *'}}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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}}
|
||||
|
||||
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() {
|
||||
int x = 1;
|
||||
|
@ -44,11 +44,11 @@ void func() {
|
|||
int a,b,c;
|
||||
} 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}}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang %s -fsyntax-only -verify
|
||||
// RUN: clang %s -fsyntax-only -verify -pedantic
|
||||
|
||||
int test1(float a, int b) {
|
||||
return __builtin_isless(a, b);
|
||||
|
@ -26,8 +26,7 @@ int test6(float a, long double b) {
|
|||
void cfstring() {
|
||||
CFSTR("\242"); // expected-warning {{ CFString literal contains non-ASCII character }}
|
||||
CFSTR("\0"); // expected-warning {{ CFString literal contains NUL character }}
|
||||
CFSTR(242); // expected-error {{ CFString literal is not a string constant }} \
|
||||
expected-warning {{incompatible types}}
|
||||
CFSTR(242); // expected-error {{ CFString literal is not a string constant }} expected-warning {{incompatible pointer/int conversion}}
|
||||
CFSTR("foo", "bar"); // expected-error {{ error: too many arguments to function }}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ INTF <MyProto1> * Func1(INTF <MyProto1, MyProto2> *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> *}}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
// RUN: clang -fsyntax-only -verify -pedantic %s
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
|
@ -33,25 +33,25 @@ int main()
|
|||
/* Assigning to a 'MyClass *' variable should always generate a
|
||||
warning, unless done from an 'id'. */
|
||||
obj_c = obj; /* Ok */
|
||||
obj_c = obj_cp; // // expected-warning {{incompatible pointer types assigning 'MyOtherClass *' to 'MyClass *'}}
|
||||
obj_c = obj_C; // expected-warning {{incompatible pointer types assigning 'Class' 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', expected 'MyClass *'}}
|
||||
|
||||
/* Assigning to an 'id<MyProtocol>' variable should generate a
|
||||
warning if done from a 'MyClass *' (which doesn't implement
|
||||
MyProtocol), but not from an 'id' or from a 'MyOtherClass *'
|
||||
(which implements MyProtocol). */
|
||||
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_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
|
||||
a warning, unless done from an 'id' or an 'id<MyProtocol>' (since
|
||||
MyOtherClass implements MyProtocol). */
|
||||
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_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. */
|
||||
if (obj == obj_p) foo() ; /* Ok */ /*Bogus warning here in 2.95.4*/
|
||||
|
|
|
@ -24,21 +24,21 @@ int main()
|
|||
id<MyProtocolAB> obj_ab = 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_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_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_b; // expected-error {{incompatible types assigning 'id<MyProtocolB>' to 'id<MyProtocolAB>'}}
|
||||
obj_ab = obj_ac; // expected-error {{incompatible types assigning 'id<MyProtocolAC>' to 'id<MyProtocolAB>'}}
|
||||
obj_ab = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAB>'}}
|
||||
obj_ab = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected '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_b; // expected-error {{incompatible types assigning 'id<MyProtocolB>' to 'id<MyProtocolAC>'}}
|
||||
obj_ac = obj_ab; // expected-error {{incompatible types assigning 'id<MyProtocolAB>' to 'id<MyProtocolAC>'}}
|
||||
obj_ac = obj_a; // expected-error {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAC>'}}
|
||||
obj_ac = obj_b; // expected-error {{incompatible type assigning 'id<MyProtocolB>', expected '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_b == obj_a) foo (); // expected-error {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}}
|
||||
|
|
|
@ -23,8 +23,8 @@ int main()
|
|||
MyClass *obj_c_cat_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_super_p = obj_id_p; // expected-error {{incompatible types assigning 'id<MyProtocol>' to 'MyOtherClass *'}}
|
||||
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 type assigning 'id<MyProtocol>', expected 'MyOtherClass *'}}
|
||||
obj_id_p = obj_c_cat_p; /* Ok */
|
||||
obj_id_p = obj_c_super_p; /* Ok */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
// RUN: clang -fsyntax-only -verify -pedantic %s
|
||||
|
||||
#include <objc/Object.h>
|
||||
|
||||
|
@ -9,7 +9,7 @@ extern Object* foo(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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
// RUN: clang -fsyntax-only -verify -pedantic %s
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
|
@ -23,27 +23,27 @@ int main()
|
|||
|
||||
/* These should all generate warnings. */
|
||||
|
||||
obj = i; // expected-warning {{incompatible types assigning 'int' to 'id'}}
|
||||
obj = j; // expected-warning {{incompatible pointer 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 *', expected 'id'}}
|
||||
|
||||
obj_p = i; // expected-error {{incompatible types assigning 'int' to 'id<MyProtocol>' }}
|
||||
obj_p = j; // 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 type assigning 'int *', expected 'id<MyProtocol>'}}
|
||||
|
||||
obj_c = i; // expected-warning {{incompatible types assigning 'int' to 'MyClass *'}}
|
||||
obj_c = j; // expected-warning {{incompatible pointer 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 *', expected 'MyClass *'}}
|
||||
|
||||
obj_C = i; // expected-warning {{incompatible types assigning 'int' to 'Class'}}
|
||||
obj_C = j; // expected-warning {{incompatible pointer 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 *', expected 'Class'}}
|
||||
|
||||
i = obj; // expected-warning {{incompatible types assigning 'id' to 'int'}}
|
||||
i = obj_p; // expected-error {{incompatible types assigning 'id<MyProtocol>' to 'int'}}
|
||||
i = obj_c; // expected-warning {{incompatible types assigning 'MyClass *' to 'int'}}
|
||||
i = obj_C; // expected-warning {{incompatible types assigning 'Class' to 'int'}}
|
||||
i = obj; // expected-warning {{incompatible pointer/int conversion assigning 'id', expected 'int'}}
|
||||
i = obj_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'int'}}
|
||||
i = obj_c; // expected-warning {{incompatible pointer/int conversion assigning 'MyClass *', expected '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_p; // expected-error {{incompatible types assigning 'id<MyProtocol>' to 'int *'}}
|
||||
j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *' to 'int *'}}
|
||||
j = obj_C; // expected-warning {{incompatible pointer types assigning 'Class' to 'int *'}}
|
||||
j = obj; // expected-warning {{incompatible pointer types assigning 'id', expected 'int *'}}
|
||||
j = obj_p; // expected-error {{incompatible type assigning 'id<MyProtocol>', expected 'int *'}}
|
||||
j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected '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 (i == obj) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'id')}}
|
||||
|
|
|
@ -29,7 +29,7 @@ id<MyProto1> Func(INTF <MyProto1, MyProto2> *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>'}}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ INTF<MyProto1> * Hunc1(id <MyProto1, MyProto2>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> *'}}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ typedef int int4 __attribute__((vector_size(16)));
|
|||
typedef int4* int4p;
|
||||
|
||||
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) {
|
||||
result[i] = a; // expected-error {{assigning 'float4' to 'int4'}}
|
||||
result[i] = a; // expected-error {{assigning 'float4', expected 'int4'}}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,27 +13,27 @@ void f() {
|
|||
v4ss v5;
|
||||
|
||||
v1 = v2;
|
||||
v1 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v2s'}}
|
||||
v1 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v2s'}}
|
||||
v1 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2s'}}
|
||||
v1 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v2s'}}
|
||||
v1 = v5;
|
||||
|
||||
v2 = v1;
|
||||
v2 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v2u'}}
|
||||
v2 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v2u'}}
|
||||
v2 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2u'}}
|
||||
v2 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v2u'}}
|
||||
v2 = v5;
|
||||
|
||||
v3 = v1; // expected-error {{incompatible types assigning 'v2s' to 'v1s'}}
|
||||
v3 = v2; // expected-error {{incompatible types assigning 'v2u' to 'v1s'}}
|
||||
v3 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v1s'}}
|
||||
v3 = v5; // expected-error {{incompatible types assigning 'v4ss' to 'v1s'}}
|
||||
v3 = v1; // expected-error {{incompatible type assigning 'v2s', expected 'v1s'}}
|
||||
v3 = v2; // expected-error {{incompatible type assigning 'v2u', expected 'v1s'}}
|
||||
v3 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v1s'}}
|
||||
v3 = v5; // expected-error {{incompatible type assigning 'v4ss', expected 'v1s'}}
|
||||
|
||||
v4 = v1; // expected-error {{incompatible types assigning 'v2s' to 'v2f'}}
|
||||
v4 = v2; // expected-error {{incompatible types assigning 'v2u' to 'v2f'}}
|
||||
v4 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v2f'}}
|
||||
v4 = v5; // expected-error {{incompatible types assigning 'v4ss' to 'v2f'}}
|
||||
v4 = v1; // expected-error {{incompatible type assigning 'v2s', expected 'v2f'}}
|
||||
v4 = v2; // expected-error {{incompatible type assigning 'v2u', expected 'v2f'}}
|
||||
v4 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2f'}}
|
||||
v4 = v5; // expected-error {{incompatible type assigning 'v4ss', expected 'v2f'}}
|
||||
|
||||
v5 = v1;
|
||||
v5 = v2;
|
||||
v5 = v3; // expected-error {{incompatible types assigning 'v1s' to 'v4ss'}}
|
||||
v5 = v4; // expected-error {{incompatible types assigning 'v2f' to 'v4ss'}}
|
||||
v5 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v4ss'}}
|
||||
v5 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v4ss'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue