// from the Sel.getNumArgs().
TypeTy **ArgTypes, IdentifierInfo **ArgNames,
AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind);
-
+
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
void CheckConstantInitList(QualType DeclType, InitListExpr *IList,
QualType ElementType, bool isStatic,
int &nInitializers, bool &hadError);
-
+
+ // returns true if there were any incompatible arguments.
+ bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
+ ObjcMethodDecl *Method);
+
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
/// the specified width and sign. If an overflow occurs, detect it and emit
/// the specified diagnostic.
return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
}
+
+bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
+ ObjcMethodDecl *Method) {
+ bool anyIncompatibleArgs = false;
+
+ for (unsigned i = 0; i < NumArgs; i++) {
+ Expr *argExpr = Args[i];
+ assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
+
+ QualType lhsType = Method->getParamDecl(i)->getType();
+ QualType rhsType = argExpr->getType();
+
+ // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
+ if (const ArrayType *ary = lhsType->getAsArrayType())
+ lhsType = Context.getPointerType(ary->getElementType());
+ else if (lhsType->isFunctionType())
+ lhsType = Context.getPointerType(lhsType);
+
+ AssignmentCheckResult 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).
+ switch (result) {
+ case Compatible:
+ break;
+ case PointerFromInt:
+ // check for null pointer constant (C99 6.3.2.3p3)
+ if (!argExpr->isNullPointerConstant(Context)) {
+ Diag(l, diag::ext_typecheck_sending_pointer_int,
+ lhsType.getAsString(), rhsType.getAsString(),
+ argExpr->getSourceRange());
+ }
+ break;
+ case IntFromPointer:
+ Diag(l, diag::ext_typecheck_sending_pointer_int,
+ lhsType.getAsString(), rhsType.getAsString(),
+ argExpr->getSourceRange());
+ break;
+ case IncompatiblePointer:
+ Diag(l, diag::ext_typecheck_sending_incompatible_pointer,
+ rhsType.getAsString(), lhsType.getAsString(),
+ argExpr->getSourceRange());
+ break;
+ case CompatiblePointerDiscardsQualifiers:
+ Diag(l, diag::ext_typecheck_passing_discards_qualifiers,
+ rhsType.getAsString(), lhsType.getAsString(),
+ argExpr->getSourceRange());
+ break;
+ case Incompatible:
+ Diag(l, diag::err_typecheck_sending_incompatible,
+ rhsType.getAsString(), lhsType.getAsString(),
+ argExpr->getSourceRange());
+ anyIncompatibleArgs = true;
+ }
+ }
+ return anyIncompatibleArgs;
+}
+
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
{
assert(receiverName && "missing receiver class name");
+ Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
ObjcInterfaceDecl* ClassDecl = getObjCInterfaceDecl(receiverName);
ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
QualType returnType;
returnType = GetObjcIdType();
} else {
returnType = Method->getResultType();
+ if (Sel.getNumArgs()) {
+ if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
+ return true;
+ }
}
- // Expr *RExpr = global reference to the class symbol...
- Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
return new ObjCMessageExpr(receiverName, Sel, returnType, lbrac, rbrac,
ArgExprs);
}
{
assert(receiver && "missing receiver expression");
+ Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
Expr *RExpr = static_cast<Expr *>(receiver);
QualType receiverType = RExpr->getType();
QualType returnType;
returnType = GetObjcIdType();
} else {
returnType = Method->getResultType();
+ if (Sel.getNumArgs())
+ if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
+ return true;
}
} else {
// FIXME (snaroff): checking in this code from Patrick. Needs to be
returnType = GetObjcIdType();
} else {
returnType = Method->getResultType();
+ if (Sel.getNumArgs())
+ if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
+ return true;
}
}
- Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
return new ObjCMessageExpr(RExpr, Sel, returnType, lbrac, rbrac, ArgExprs);
}