зеркало из https://github.com/microsoft/clang-1.git
continue cleaning up code, and disable sending a message directly to an
interface. This fixes a bug where we used to accept: void test2(NSNumber x) { [x METH]; } which doesn't make sense and GCC rejects. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53841 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
fe1a553256
Коммит
2b1cc8be4d
|
@ -362,6 +362,10 @@ public:
|
|||
const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
|
||||
const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
|
||||
|
||||
/// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC
|
||||
/// interface, return the interface type, otherwise return null.
|
||||
const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const;
|
||||
|
||||
|
||||
/// getDesugaredType - Return the specified type with any "sugar" removed from
|
||||
/// the type. This takes off typedefs, typeof's etc. If the outer level of
|
||||
|
@ -1289,6 +1293,12 @@ inline unsigned QualType::getAddressSpace() const {
|
|||
inline const TypedefType* Type::getAsTypedefType() const {
|
||||
return dyn_cast<TypedefType>(this);
|
||||
}
|
||||
inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const {
|
||||
if (const PointerType *PT = getAsPointerType())
|
||||
return PT->getPointeeType()->getAsObjCInterfaceType();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool Type::isFunctionType() const {
|
||||
return isa<FunctionType>(CanonicalType.getUnqualifiedType());
|
||||
|
|
|
@ -226,14 +226,13 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
|||
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
|
||||
Expr *RExpr = static_cast<Expr *>(receiver);
|
||||
QualType returnType;
|
||||
ObjCMethodDecl *Method = 0;
|
||||
|
||||
QualType receiverType =
|
||||
RExpr->getType().getCanonicalType().getUnqualifiedType();
|
||||
|
||||
// Handle messages to id.
|
||||
if (receiverType == Context.getObjCIdType().getCanonicalType()) {
|
||||
Method = InstanceMethodPool[Sel].Method;
|
||||
ObjCMethodDecl *Method = InstanceMethodPool[Sel].Method;
|
||||
if (!Method)
|
||||
Method = FactoryMethodPool[Sel].Method;
|
||||
if (!Method) {
|
||||
|
@ -252,6 +251,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
|||
|
||||
// Handle messages to Class.
|
||||
if (receiverType == Context.getObjCClassType().getCanonicalType()) {
|
||||
ObjCMethodDecl *Method = 0;
|
||||
if (getCurMethodDecl()) {
|
||||
ObjCInterfaceDecl* ClassDecl = getCurMethodDecl()->getClassInterface();
|
||||
// If we have an implementation in scope, check "private" methods.
|
||||
|
@ -279,18 +279,14 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
|||
ArgExprs, NumArgs);
|
||||
}
|
||||
|
||||
// We allow sending a message to a qualified ID ("id<foo>") to an interface
|
||||
// directly ("[NSNumber foo]") and to a pointer to an interface (an object).
|
||||
if (!isa<ObjCQualifiedIdType>(receiverType) &&
|
||||
!isa<ObjCInterfaceType>(receiverType))
|
||||
if (const PointerType *PTy = receiverType->getAsPointerType())
|
||||
receiverType = PTy->getPointeeType();
|
||||
// else error, invalid receiver.
|
||||
|
||||
ObjCMethodDecl *Method = 0;
|
||||
ObjCInterfaceDecl* ClassDecl = 0;
|
||||
|
||||
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
|
||||
// long as one of the protocols implements the selector (if not, warn).
|
||||
if (ObjCQualifiedIdType *QIT =
|
||||
dyn_cast<ObjCQualifiedIdType>(receiverType)) {
|
||||
// search protocols
|
||||
// Search protocols
|
||||
for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
|
||||
ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
|
||||
if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
|
||||
|
@ -300,13 +296,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
|||
Diag(lbrac, diag::warn_method_not_found_in_protocol,
|
||||
std::string("-"), Sel.getName(),
|
||||
SourceRange(lbrac, rbrac));
|
||||
} else {
|
||||
ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType);
|
||||
if (OCIReceiver == 0) {
|
||||
Diag(lbrac, diag::error_bad_receiver_type,
|
||||
RExpr->getType().getAsString());
|
||||
return true;
|
||||
}
|
||||
} else if (const ObjCInterfaceType *OCIReceiver =
|
||||
receiverType->getAsPointerToObjCInterfaceType()) {
|
||||
// We allow sending a message to a pointer to an interface (an object).
|
||||
|
||||
ClassDecl = OCIReceiver->getDecl();
|
||||
// FIXME: consider using InstanceMethodPool, since it will be faster
|
||||
|
@ -327,6 +319,10 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
|
|||
Diag(lbrac, diag::warn_method_not_found_in_protocol,
|
||||
std::string("-"), Sel.getName(),
|
||||
SourceRange(lbrac, rbrac));
|
||||
} else {
|
||||
Diag(lbrac, diag::error_bad_receiver_type,
|
||||
RExpr->getType().getAsString());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Method) {
|
||||
|
|
|
@ -11,13 +11,16 @@ void test1() {
|
|||
}
|
||||
|
||||
void test2(NSNumber x) {
|
||||
id objects[] = {[x METH]}; // expected-error {{bad receiver type}}
|
||||
}
|
||||
|
||||
void test3(NSNumber *x) {
|
||||
id objects[] = {[x METH]};
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// rdar://5977581
|
||||
void test3() {
|
||||
void test4() {
|
||||
unsigned x[] = {[NSNumber METH2]+2};
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче