aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Sema/Sema.h34
-rw-r--r--Sema/SemaDecl.cpp48
-rw-r--r--Sema/SemaExpr.cpp268
-rw-r--r--Sema/SemaStmt.cpp53
-rw-r--r--include/clang/Basic/DiagnosticKinds.def43
-rw-r--r--test/Parser/builtin_types_compatible.c2
-rw-r--r--test/Parser/implicit-casts.c4
-rw-r--r--test/Parser/typeof.c4
-rw-r--r--test/Sema/argument-checking.m4
-rw-r--r--test/Sema/array-constraint.c2
-rw-r--r--test/Sema/array-init.c6
-rw-r--r--test/Sema/builtins.c5
-rw-r--r--test/Sema/incompatible-protocol-qualified-types.m2
-rw-r--r--test/Sema/objc-comptypes-1.m14
-rw-r--r--test/Sema/objc-comptypes-3.m18
-rw-r--r--test/Sema/objc-comptypes-5.m4
-rw-r--r--test/Sema/objc-comptypes-6.m4
-rw-r--r--test/Sema/objc-comptypes-7.m34
-rw-r--r--test/Sema/protocol-id-test-3.m4
-rw-r--r--test/Sema/typedef-retain.c4
-rw-r--r--test/Sema/vector-assign.c28
21 files changed, 202 insertions, 383 deletions
diff --git a/Sema/Sema.h b/Sema/Sema.h
index 6f546514db..e790a74251 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -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).
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index 1165e526d8..07b3d71368 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -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,
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 3a3cfc18bc..7ed0bf102a 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -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;
-
+
+ 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.
@@ -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;
}
diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp
index 6b60bd0274..a983036b99 100644
--- a/Sema/SemaStmt.cpp
+++ b/Sema/SemaStmt.cpp
@@ -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);
}
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index e07245659e..891d9317e0 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -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")
diff --git a/test/Parser/builtin_types_compatible.c b/test/Parser/builtin_types_compatible.c
index b8207841a4..925c7ea50a 100644
--- a/test/Parser/builtin_types_compatible.c
+++ b/test/Parser/builtin_types_compatible.c
@@ -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);
diff --git a/test/Parser/implicit-casts.c b/test/Parser/implicit-casts.c
index a07155eea4..3d055263bc 100644
--- a/test/Parser/implicit-casts.c
+++ b/test/Parser/implicit-casts.c
@@ -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; }
diff --git a/test/Parser/typeof.c b/test/Parser/typeof.c
index 6c4e79cd16..3ea277559e 100644
--- a/test/Parser/typeof.c
+++ b/test/Parser/typeof.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 *'}}
}
diff --git a/test/Sema/argument-checking.m b/test/Sema/argument-checking.m
index 57ab14f1ff..cd84171ee7 100644
--- a/test/Sema/argument-checking.m
+++ b/test/Sema/argument-checking.m
@@ -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'}}
diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c
index f281df1aff..df79681d06 100644
--- a/test/Sema/array-constraint.c
+++ b/