// 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).
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,
// 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 "...".
// 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;
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())
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())
if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(),
rhptee.getUnqualifiedType()))
return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
- return r;
+ return ConvTy;
}
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
/// 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) {
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);
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.
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.
return result;
}
-Sema::AssignmentCheckResult
+Sema::AssignConvertType
Sema::CheckCompoundAssignmentConstraints(QualType lhsType, QualType rhsType) {
return CheckAssignmentConstraints(lhsType, rhsType);
}
{
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;
-
+
+ AssignConvertType ConvTy;
if (compoundType.isNull())
- result = CheckSingleAssignmentConstraints(lhsType, rex);
+ ConvTy = CheckSingleAssignmentConstraints(lhsType, rex);
else
- result = CheckCompoundAssignmentConstraints(lhsType, rhsType);
+ ConvTy = 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;
- }
+ 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.
// 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
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(),
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;
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;
}
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() :
}
}
// 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);
}
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,
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")
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);
-// RUN: clang -fsyntax-only -verify %s
+// RUN: clang -fsyntax-only -verify -pedantic %s
_Complex double X;
void test1(int c) {
X = 5;
}
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; }
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 *'}}
}
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'}}
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 *'}}
}
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;
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() {
-// RUN: clang %s -fsyntax-only -verify
+// RUN: clang %s -fsyntax-only -verify -pedantic
int test1(float a, int b) {
return __builtin_isless(a, 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 }}
}
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> *}}
}
-// RUN: clang -fsyntax-only -verify %s
+// RUN: clang -fsyntax-only -verify -pedantic %s
#include <objc/objc.h>
/* 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*/
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>')}}
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 */
-// RUN: clang -fsyntax-only -verify %s
+// RUN: clang -fsyntax-only -verify -pedantic %s
#include <objc/Object.h>
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;
}
-// RUN: clang -fsyntax-only -verify %s
+// RUN: clang -fsyntax-only -verify -pedantic %s
#include <objc/objc.h>
/* 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')}}
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>'}}
}
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> *'}}
}
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'}}
}
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'}}
}