forked from OSchip/llvm-project
Patch to add semantics check for ObjC2's foreacn statement.
llvm-svn: 45561
This commit is contained in:
parent
816dea2fc5
commit
775d5d02af
|
|
@ -26,6 +26,20 @@ bool Sema::isBuiltinObjcType(TypedefDecl *TD) {
|
|||
strcmp(typeName, "SEL") == 0 || strcmp(typeName, "Protocol") == 0;
|
||||
}
|
||||
|
||||
bool Sema::isObjcObjectPointerType(QualType type) const {
|
||||
if (!type->isPointerType() && !type->isObjcQualifiedIdType())
|
||||
return false;
|
||||
if (type == Context.getObjcIdType() || type == Context.getObjcClassType() ||
|
||||
type->isObjcQualifiedIdType())
|
||||
return true;
|
||||
|
||||
while (type->isPointerType()) {
|
||||
PointerType *pointerType = static_cast<PointerType*>(type.getTypePtr());
|
||||
type = pointerType->getPointeeType();
|
||||
}
|
||||
return (type->isObjcInterfaceType() || type->isObjcQualifiedIdType());
|
||||
}
|
||||
|
||||
void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
|
||||
TUScope = S;
|
||||
if (PP.getLangOptions().ObjC1) {
|
||||
|
|
|
|||
|
|
@ -285,6 +285,10 @@ private:
|
|||
/// isBuiltinObjcType - Returns true of the type is "id", "SEL", "Class"
|
||||
/// or "Protocol".
|
||||
bool isBuiltinObjcType(TypedefDecl *TD);
|
||||
|
||||
/// isObjcObjectPointerType - Returns tru if type is an objective-c pointer
|
||||
/// to an object type; such as "id", "Class", Intf*, id<P>, etc.
|
||||
bool isObjcObjectPointerType(QualType type) const;
|
||||
|
||||
/// AddInstanceMethodToGlobalPool - All instance methods in a translation
|
||||
/// unit are added to a global pool. This allows us to efficiently associate
|
||||
|
|
|
|||
|
|
@ -2350,8 +2350,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
|||
return true;
|
||||
}
|
||||
} else {
|
||||
bool receiverIsQualId =
|
||||
dyn_cast<ObjcQualifiedIdType>(RExpr->getType()) != 0;
|
||||
bool receiverIsQualId = dyn_cast<ObjcQualifiedIdType>(receiverType) != 0;
|
||||
// FIXME (snaroff): checking in this code from Patrick. Needs to be
|
||||
// revisited. how do we get the ClassDecl from the receiver expression?
|
||||
if (!receiverIsQualId)
|
||||
|
|
|
|||
|
|
@ -538,8 +538,9 @@ Sema::ActOnObjcForCollectionStmt(SourceLocation ForColLoc,
|
|||
Stmt *First = static_cast<Stmt*>(first);
|
||||
Expr *Second = static_cast<Expr*>(second);
|
||||
Stmt *Body = static_cast<Stmt*>(body);
|
||||
|
||||
QualType FirstType;
|
||||
if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
|
||||
FirstType = dyn_cast<ValueDecl>(DS->getDecl())->getType();
|
||||
// C99 6.8.5p3: The declaration part of a 'for' statement shall only declare
|
||||
// identifiers for objects having storage class 'auto' or 'register'.
|
||||
for (ScopedDecl *D = DS->getDecl(); D; D = D->getNextDeclarator()) {
|
||||
|
|
@ -547,19 +548,21 @@ Sema::ActOnObjcForCollectionStmt(SourceLocation ForColLoc,
|
|||
if (BVD && !BVD->hasLocalStorage())
|
||||
BVD = 0;
|
||||
if (BVD == 0)
|
||||
Diag(dyn_cast<ScopedDecl>(D)->getLocation(),
|
||||
diag::err_non_variable_decl_in_for);
|
||||
// FIXME: mark decl erroneous!
|
||||
return Diag(dyn_cast<ScopedDecl>(D)->getLocation(),
|
||||
diag::err_non_variable_decl_in_for);
|
||||
}
|
||||
}
|
||||
else
|
||||
FirstType = static_cast<Expr*>(first)->getType();
|
||||
if (!isObjcObjectPointerType(FirstType))
|
||||
Diag(ForColLoc, diag::err_selector_element_type,
|
||||
FirstType.getAsString(), First->getSourceRange());
|
||||
if (Second) {
|
||||
DefaultFunctionArrayConversion(Second);
|
||||
QualType SecondType = Second->getType();
|
||||
#if 0
|
||||
if (!SecondType->isScalarType()) // C99 6.8.5p2
|
||||
return Diag(ForColLoc, diag::err_typecheck_statement_requires_scalar,
|
||||
SecondType.getAsString(), Second->getSourceRange());
|
||||
#endif
|
||||
if (!isObjcObjectPointerType(SecondType))
|
||||
Diag(ForColLoc, diag::err_collection_expr_type,
|
||||
SecondType.getAsString(), Second->getSourceRange());
|
||||
}
|
||||
return new ObjcForCollectionStmt(First, Second, Body, ForColLoc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -472,6 +472,10 @@ DIAG(warn_method_not_found, WARNING,
|
|||
"method '%0%1' not found (return type defaults to 'id')")
|
||||
DIAG(warn_method_not_found_in_protocol, WARNING,
|
||||
"method '%0%1' not found in protocol (return type defaults to 'id')")
|
||||
DIAG(err_collection_expr_type, ERROR,
|
||||
"collection expression is not of valid object type (its type is '%0')")
|
||||
DIAG(err_selector_element_type, ERROR,
|
||||
"selector element is not of valid object type (its type is '%0')")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Semantic Analysis
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
// RUN: clang -fsyntax-only %s
|
||||
|
||||
typedef struct objc_class *Class;
|
||||
typedef struct objc_object {
|
||||
Class isa;
|
||||
} *id;
|
||||
|
||||
|
||||
@protocol P @end
|
||||
|
||||
@interface MyList
|
||||
@end
|
||||
|
||||
@implementation MyList
|
||||
- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface MyList (BasicTest)
|
||||
- (void)compilerTestAgainst;
|
||||
@end
|
||||
|
||||
@implementation MyList (BasicTest)
|
||||
- (void)compilerTestAgainst {
|
||||
int i;
|
||||
for (id elem in self)
|
||||
++i;
|
||||
for (MyList *elem in self)
|
||||
++i;
|
||||
for (id<P> se in self)
|
||||
++i;
|
||||
|
||||
MyList<P> *p;
|
||||
for (p in self)
|
||||
++i;
|
||||
|
||||
for (p in p)
|
||||
++i;
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
typedef struct objc_class *Class;
|
||||
typedef struct objc_object {
|
||||
Class isa;
|
||||
} *id;
|
||||
|
||||
|
||||
@interface MyList
|
||||
@end
|
||||
|
||||
@implementation MyList
|
||||
- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface MyList (BasicTest)
|
||||
- (void)compilerTestAgainst;
|
||||
@end
|
||||
|
||||
@implementation MyList (BasicTest)
|
||||
- (void)compilerTestAgainst {
|
||||
|
||||
int i=0;
|
||||
for (int * elem in elem) // expected-error {{selector element is not of valid object type (its type is 'int *')}} \
|
||||
expected-error {{collection expression is not of valid object type (its type is 'int *')}}
|
||||
++i;
|
||||
for (i in elem) // expected-error {{use of undeclared identifier 'elem'}} \
|
||||
expected-error {{selector element is not of valid object type (its type is 'int')}}
|
||||
++i;
|
||||
for (id se in i) // expected-error {{collection expression is not of valid object type (its type is 'int')}}
|
||||
++i;
|
||||
}
|
||||
@end
|
||||
|
||||
Loading…
Reference in New Issue