forked from OSchip/llvm-project
parent
7bcc28bf6c
commit
077c83bddb
|
|
@ -511,7 +511,7 @@ public:
|
||||||
// from the Sel.getNumArgs().
|
// from the Sel.getNumArgs().
|
||||||
TypeTy **ArgTypes, IdentifierInfo **ArgNames,
|
TypeTy **ArgTypes, IdentifierInfo **ArgNames,
|
||||||
AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind);
|
AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind);
|
||||||
|
|
||||||
// ActOnClassMessage - used for both unary and keyword messages.
|
// ActOnClassMessage - used for both unary and keyword messages.
|
||||||
// ArgExprs is optional - if it is present, the number of expressions
|
// ArgExprs is optional - if it is present, the number of expressions
|
||||||
// is obtained from Sel.getNumArgs().
|
// is obtained from Sel.getNumArgs().
|
||||||
|
|
@ -631,7 +631,11 @@ private:
|
||||||
void CheckConstantInitList(QualType DeclType, InitListExpr *IList,
|
void CheckConstantInitList(QualType DeclType, InitListExpr *IList,
|
||||||
QualType ElementType, bool isStatic,
|
QualType ElementType, bool isStatic,
|
||||||
int &nInitializers, bool &hadError);
|
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
|
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
|
||||||
/// the specified width and sign. If an overflow occurs, detect it and emit
|
/// the specified width and sign. If an overflow occurs, detect it and emit
|
||||||
/// the specified diagnostic.
|
/// the specified diagnostic.
|
||||||
|
|
|
||||||
|
|
@ -1928,6 +1928,67 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
|
||||||
return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc);
|
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.
|
// ActOnClassMessage - used for both unary and keyword messages.
|
||||||
// ArgExprs is optional - if it is present, the number of expressions
|
// ArgExprs is optional - if it is present, the number of expressions
|
||||||
// is obtained from Sel.getNumArgs().
|
// is obtained from Sel.getNumArgs().
|
||||||
|
|
@ -1937,6 +1998,7 @@ Sema::ExprResult Sema::ActOnClassMessage(
|
||||||
{
|
{
|
||||||
assert(receiverName && "missing receiver class name");
|
assert(receiverName && "missing receiver class name");
|
||||||
|
|
||||||
|
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
|
||||||
ObjcInterfaceDecl* ClassDecl = getObjCInterfaceDecl(receiverName);
|
ObjcInterfaceDecl* ClassDecl = getObjCInterfaceDecl(receiverName);
|
||||||
ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
|
ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
|
||||||
QualType returnType;
|
QualType returnType;
|
||||||
|
|
@ -1946,9 +2008,11 @@ Sema::ExprResult Sema::ActOnClassMessage(
|
||||||
returnType = GetObjcIdType();
|
returnType = GetObjcIdType();
|
||||||
} else {
|
} else {
|
||||||
returnType = Method->getResultType();
|
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,
|
return new ObjCMessageExpr(receiverName, Sel, returnType, lbrac, rbrac,
|
||||||
ArgExprs);
|
ArgExprs);
|
||||||
}
|
}
|
||||||
|
|
@ -1962,6 +2026,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
||||||
{
|
{
|
||||||
assert(receiver && "missing receiver expression");
|
assert(receiver && "missing receiver expression");
|
||||||
|
|
||||||
|
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
|
||||||
Expr *RExpr = static_cast<Expr *>(receiver);
|
Expr *RExpr = static_cast<Expr *>(receiver);
|
||||||
QualType receiverType = RExpr->getType();
|
QualType receiverType = RExpr->getType();
|
||||||
QualType returnType;
|
QualType returnType;
|
||||||
|
|
@ -1974,6 +2039,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
||||||
returnType = GetObjcIdType();
|
returnType = GetObjcIdType();
|
||||||
} else {
|
} else {
|
||||||
returnType = Method->getResultType();
|
returnType = Method->getResultType();
|
||||||
|
if (Sel.getNumArgs())
|
||||||
|
if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// FIXME (snaroff): checking in this code from Patrick. Needs to be
|
// FIXME (snaroff): checking in this code from Patrick. Needs to be
|
||||||
|
|
@ -1997,8 +2065,10 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
||||||
returnType = GetObjcIdType();
|
returnType = GetObjcIdType();
|
||||||
} else {
|
} else {
|
||||||
returnType = Method->getResultType();
|
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);
|
return new ObjCMessageExpr(RExpr, Sel, returnType, lbrac, rbrac, ArgExprs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -763,6 +763,12 @@ DIAG(ext_typecheck_passing_pointer_int, WARNING,
|
||||||
"incompatible types passing '%1' to function expecting '%0'")
|
"incompatible types passing '%1' to function expecting '%0'")
|
||||||
DIAG(ext_typecheck_passing_discards_qualifiers, WARNING,
|
DIAG(ext_typecheck_passing_discards_qualifiers, WARNING,
|
||||||
"passing '%0' to '%1' discards qualifiers")
|
"passing '%0' to '%1' discards qualifiers")
|
||||||
|
DIAG(err_typecheck_sending_incompatible, ERROR,
|
||||||
|
"incompatible types passing '%0' to method expecting '%1'")
|
||||||
|
DIAG(ext_typecheck_sending_incompatible_pointer, WARNING,
|
||||||
|
"incompatible pointer types passing '%0' to method expecting '%1'")
|
||||||
|
DIAG(ext_typecheck_sending_pointer_int, WARNING,
|
||||||
|
"incompatible types passing '%1' to method expecting '%0'")
|
||||||
DIAG(err_typecheck_cond_expect_scalar, ERROR,
|
DIAG(err_typecheck_cond_expect_scalar, ERROR,
|
||||||
"used type '%0' where arithmetic or pointer type is required")
|
"used type '%0' where arithmetic or pointer type is required")
|
||||||
DIAG(err_typecheck_expect_scalar_operand, ERROR,
|
DIAG(err_typecheck_expect_scalar_operand, ERROR,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// RUN: clang -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
typedef struct objc_object *id;
|
||||||
|
|
||||||
|
struct S { int a; };
|
||||||
|
|
||||||
|
extern int charStarFunc(char *);
|
||||||
|
extern int charFunc(char);
|
||||||
|
|
||||||
|
@interface Test
|
||||||
|
+alloc;
|
||||||
|
-(int)charStarMeth:(char *)s;
|
||||||
|
-structMeth:(struct S)s;
|
||||||
|
-structMeth:(struct S)s :(struct S)s2;
|
||||||
|
@end
|
||||||
|
|
||||||
|
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'}}
|
||||||
|
|
||||||
|
[obj charStarMeth:1]; // expected-warning {{incompatible types passing 'int' to method expecting 'char *'}}
|
||||||
|
[obj structMeth:1]; // expected-error {{incompatible types passing 'int' to method expecting 'struct S'}}
|
||||||
|
[obj structMeth:sInst :1]; // expected-error {{incompatible types passing 'int' to method expecting 'struct S'}}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue