[cfe-commits] r43050 - in /cfe/trunk: Sema/Sema.h Sema/SemaExpr.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/argument-checking.m
Steve Naroff
snaroff at apple.com
Tue Oct 16 16:12:48 PDT 2007
Author: snaroff
Date: Tue Oct 16 18:12:48 2007
New Revision: 43050
URL: http://llvm.org/viewvc/llvm-project?rev=43050&view=rev
Log:
Add Sema::CheckMessageArgumentTypes()...
Added:
cfe/trunk/test/Sema/argument-checking.m
Modified:
cfe/trunk/Sema/Sema.h
cfe/trunk/Sema/SemaExpr.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=43050&r1=43049&r2=43050&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Tue Oct 16 18:12:48 2007
@@ -511,7 +511,7 @@
// 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().
@@ -631,7 +631,11 @@
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.
Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=43050&r1=43049&r2=43050&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Tue Oct 16 18:12:48 2007
@@ -1928,6 +1928,67 @@
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().
@@ -1937,6 +1998,7 @@
{
assert(receiverName && "missing receiver class name");
+ Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
ObjcInterfaceDecl* ClassDecl = getObjCInterfaceDecl(receiverName);
ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
QualType returnType;
@@ -1946,9 +2008,11 @@
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);
}
@@ -1962,6 +2026,7 @@
{
assert(receiver && "missing receiver expression");
+ Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
Expr *RExpr = static_cast<Expr *>(receiver);
QualType receiverType = RExpr->getType();
QualType returnType;
@@ -1974,6 +2039,9 @@
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
@@ -1997,8 +2065,10 @@
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);
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=43050&r1=43049&r2=43050&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue Oct 16 18:12:48 2007
@@ -763,6 +763,12 @@
"incompatible types passing '%1' to function expecting '%0'")
DIAG(ext_typecheck_passing_discards_qualifiers, WARNING,
"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,
"used type '%0' where arithmetic or pointer type is required")
DIAG(err_typecheck_expect_scalar_operand, ERROR,
Added: cfe/trunk/test/Sema/argument-checking.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/argument-checking.m?rev=43050&view=auto
==============================================================================
--- cfe/trunk/test/Sema/argument-checking.m (added)
+++ cfe/trunk/test/Sema/argument-checking.m Tue Oct 16 18:12:48 2007
@@ -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);
+
+ at interface Test
++alloc;
+-(int)charStarMeth:(char *)s;
+-structMeth:(struct S)s;
+-structMeth:(struct S)s :(struct S)s2;
+ at 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'}}
+}
More information about the cfe-commits
mailing list