[cfe-commits] r102081 - in /cfe/trunk/lib/Sema: Sema.h SemaExprObjC.cpp TreeTransform.h
Douglas Gregor
dgregor at apple.com
Thu Apr 22 10:01:48 PDT 2010
Author: dgregor
Date: Thu Apr 22 12:01:48 2010
New Revision: 102081
URL: http://llvm.org/viewvc/llvm-project?rev=102081&view=rev
Log:
When a dependent Objective-C++ message send was able to resolve the
method being called at template definition time, retain that method
and pass it through to type-checking. We will not perform any lookup
for the method during template instantiation.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/lib/Sema/TreeTransform.h
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=102081&r1=102080&r2=102081&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Apr 22 12:01:48 2010
@@ -3886,6 +3886,7 @@
QualType ReceiverType,
SourceLocation SuperLoc,
Selector Sel,
+ ObjCMethodDecl *Method,
SourceLocation LBracLoc,
SourceLocation RBracLoc,
MultiExprArg Args);
@@ -3902,6 +3903,7 @@
QualType ReceiverType,
SourceLocation SuperLoc,
Selector Sel,
+ ObjCMethodDecl *Method,
SourceLocation LBracLoc,
SourceLocation RBracLoc,
MultiExprArg Args);
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=102081&r1=102080&r2=102081&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Thu Apr 22 12:01:48 2010
@@ -643,14 +643,16 @@
QualType SuperTy = Context.getObjCInterfaceType(Super);
SuperTy = Context.getObjCObjectPointerType(SuperTy);
return BuildInstanceMessage(ExprArg(*this), SuperTy, SuperLoc,
- Sel, LBracLoc, RBracLoc, move(Args));
+ Sel, /*Method=*/0, LBracLoc, RBracLoc,
+ move(Args));
}
// Since we are in a class method, this is a class message to
// the superclass.
return BuildClassMessage(/*ReceiverTypeInfo=*/0,
Context.getObjCInterfaceType(Super),
- SuperLoc, Sel, LBracLoc, RBracLoc, move(Args));
+ SuperLoc, Sel, /*Method=*/0, LBracLoc, RBracLoc,
+ move(Args));
}
/// \brief Build an Objective-C class message expression.
@@ -673,6 +675,9 @@
///
/// \param Sel The selector to which the message is being sent.
///
+/// \param Method The method that this class message is invoking, if
+/// already known.
+///
/// \param LBracLoc The location of the opening square bracket ']'.
///
/// \param RBrac The location of the closing square bracket ']'.
@@ -682,6 +687,7 @@
QualType ReceiverType,
SourceLocation SuperLoc,
Selector Sel,
+ ObjCMethodDecl *Method,
SourceLocation LBracLoc,
SourceLocation RBracLoc,
MultiExprArg ArgsIn) {
@@ -712,25 +718,26 @@
assert(Class && "We don't know which class we're messaging?");
// Find the method we are messaging.
- ObjCMethodDecl *Method = 0;
- if (Class->isForwardDecl()) {
- // A forward class used in messaging is treated as a 'Class'
- Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
- Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
- if (Method)
- Diag(Method->getLocation(), diag::note_method_sent_forward_class)
- << Method->getDeclName();
- }
- if (!Method)
- Method = Class->lookupClassMethod(Sel);
+ if (!Method) {
+ if (Class->isForwardDecl()) {
+ // A forward class used in messaging is treated as a 'Class'
+ Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
+ if (Method)
+ Diag(Method->getLocation(), diag::note_method_sent_forward_class)
+ << Method->getDeclName();
+ }
+ if (!Method)
+ Method = Class->lookupClassMethod(Sel);
- // If we have an implementation in scope, check "private" methods.
- if (!Method)
- Method = LookupPrivateClassMethod(Sel, Class);
+ // If we have an implementation in scope, check "private" methods.
+ if (!Method)
+ Method = LookupPrivateClassMethod(Sel, Class);
- if (Method && DiagnoseUseOfDecl(Method, Loc))
- return ExprError();
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
+ }
// Check the argument types and determine the result type.
QualType ReturnType;
@@ -775,7 +782,7 @@
ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
- /*SuperLoc=*/SourceLocation(), Sel,
+ /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
LBracLoc, RBracLoc, move(Args));
}
@@ -799,6 +806,9 @@
///
/// \param Sel The selector to which the message is being sent.
///
+/// \param Method The method that this instance message is invoking, if
+/// already known.
+///
/// \param LBracLoc The location of the opening square bracket ']'.
///
/// \param RBrac The location of the closing square bracket ']'.
@@ -808,6 +818,7 @@
QualType ReceiverType,
SourceLocation SuperLoc,
Selector Sel,
+ ObjCMethodDecl *Method,
SourceLocation LBracLoc,
SourceLocation RBracLoc,
MultiExprArg ArgsIn) {
@@ -836,125 +847,126 @@
// The location of the receiver.
SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
- ObjCMethodDecl *Method = 0;
- // Handle messages to id.
- if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() ||
- (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
- Method = LookupInstanceMethodInGlobalPool(Sel,
+ if (!Method) {
+ // Handle messages to id.
+ if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() ||
+ (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
+ Method = LookupInstanceMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
- if (!Method)
- Method = LookupFactoryMethodInGlobalPool(Sel,
+ if (!Method)
+ Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
- } else if (ReceiverType->isObjCClassType() ||
- ReceiverType->isObjCQualifiedClassType()) {
- // Handle messages to Class.
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
- // First check the public methods in the class interface.
- Method = ClassDecl->lookupClassMethod(Sel);
+ } else if (ReceiverType->isObjCClassType() ||
+ ReceiverType->isObjCQualifiedClassType()) {
+ // Handle messages to Class.
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+ // First check the public methods in the class interface.
+ Method = ClassDecl->lookupClassMethod(Sel);
- if (!Method)
- Method = LookupPrivateClassMethod(Sel, ClassDecl);
+ if (!Method)
+ Method = LookupPrivateClassMethod(Sel, ClassDecl);
- // FIXME: if we still haven't found a method, we need to look in
- // protocols (if we have qualifiers).
- }
- if (Method && DiagnoseUseOfDecl(Method, Loc))
- return ExprError();
- }
- if (!Method) {
- // If not messaging 'self', look for any factory method named 'Sel'.
- if (!Receiver || !isSelfExpr(Receiver)) {
- Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
- if (!Method) {
- // If no class (factory) method was found, check if an _instance_
- // method of the same name exists in the root class only.
- Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
- if (Method)
- if (const ObjCInterfaceDecl *ID =
- dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
- if (ID->getSuperClass())
- Diag(Loc, diag::warn_root_inst_method_not_found)
- << Sel << SourceRange(LBracLoc, RBracLoc);
- }
+ // FIXME: if we still haven't found a method, we need to look in
+ // protocols (if we have qualifiers).
}
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
}
- }
- } else {
- 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 (const ObjCObjectPointerType *QIdTy
- = ReceiverType->getAsObjCQualifiedIdType()) {
- // Search protocols for instance methods.
- for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
- E = QIdTy->qual_end(); I != E; ++I) {
- ObjCProtocolDecl *PDecl = *I;
- if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
- break;
- // Since we aren't supporting "Class<foo>", look for a class method.
- if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
- break;
+ if (!Method) {
+ // If not messaging 'self', look for any factory method named 'Sel'.
+ if (!Receiver || !isSelfExpr(Receiver)) {
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
+ if (!Method) {
+ // If no class (factory) method was found, check if an _instance_
+ // method of the same name exists in the root class only.
+ Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
+ if (Method)
+ if (const ObjCInterfaceDecl *ID =
+ dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
+ if (ID->getSuperClass())
+ Diag(Loc, diag::warn_root_inst_method_not_found)
+ << Sel << SourceRange(LBracLoc, RBracLoc);
+ }
+ }
+ }
}
- } else if (const ObjCObjectPointerType *OCIType
- = ReceiverType->getAsObjCInterfacePointerType()) {
- // We allow sending a message to a pointer to an interface (an object).
- ClassDecl = OCIType->getInterfaceDecl();
- // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
- // faster than the following method (which can do *many* linear searches).
- // The idea is to add class info to InstanceMethodPool.
- Method = ClassDecl->lookupInstanceMethod(Sel);
+ } else {
+ ObjCInterfaceDecl* ClassDecl = 0;
- if (!Method) {
- // Search protocol qualifiers.
- for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
- E = OCIType->qual_end(); QI != E; ++QI) {
- if ((Method = (*QI)->lookupInstanceMethod(Sel)))
+ // 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 (const ObjCObjectPointerType *QIdTy
+ = ReceiverType->getAsObjCQualifiedIdType()) {
+ // Search protocols for instance methods.
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+ E = QIdTy->qual_end(); I != E; ++I) {
+ ObjCProtocolDecl *PDecl = *I;
+ if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
+ break;
+ // Since we aren't supporting "Class<foo>", look for a class method.
+ if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
break;
}
- }
- if (!Method) {
- // If we have implementations in scope, check "private" methods.
- Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+ } else if (const ObjCObjectPointerType *OCIType
+ = ReceiverType->getAsObjCInterfacePointerType()) {
+ // We allow sending a message to a pointer to an interface (an object).
+ ClassDecl = OCIType->getInterfaceDecl();
+ // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
+ // faster than the following method (which can do *many* linear searches).
+ // The idea is to add class info to InstanceMethodPool.
+ Method = ClassDecl->lookupInstanceMethod(Sel);
- if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
- // If we still haven't found a method, look in the global pool. This
- // behavior isn't very desirable, however we need it for GCC
- // compatibility. FIXME: should we deviate??
- if (OCIType->qual_empty()) {
- Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
- if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
- Diag(Loc, diag::warn_maynot_respond)
- << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+ if (!Method) {
+ // Search protocol qualifiers.
+ for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
+ E = OCIType->qual_end(); QI != E; ++QI) {
+ if ((Method = (*QI)->lookupInstanceMethod(Sel)))
+ break;
}
}
- }
- if (Method && DiagnoseUseOfDecl(Method, Loc))
+ if (!Method) {
+ // If we have implementations in scope, check "private" methods.
+ Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+
+ if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
+ // If we still haven't found a method, look in the global pool. This
+ // behavior isn't very desirable, however we need it for GCC
+ // compatibility. FIXME: should we deviate??
+ if (OCIType->qual_empty()) {
+ Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LBracLoc, RBracLoc));
+ if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
+ Diag(Loc, diag::warn_maynot_respond)
+ << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+ }
+ }
+ }
+ if (Method && DiagnoseUseOfDecl(Method, Loc))
+ return ExprError();
+ } else if (!Context.getObjCIdType().isNull() &&
+ (ReceiverType->isPointerType() ||
+ (ReceiverType->isIntegerType() &&
+ ReceiverType->isScalarType()))) {
+ // Implicitly convert integers and pointers to 'id' but emit a warning.
+ Diag(Loc, diag::warn_bad_receiver_type)
+ << ReceiverType
+ << Receiver->getSourceRange();
+ if (ReceiverType->isPointerType())
+ ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ CastExpr::CK_BitCast);
+ else
+ ImpCastExprToType(Receiver, Context.getObjCIdType(),
+ CastExpr::CK_IntegralToPointer);
+ ReceiverType = Receiver->getType();
+ } else {
+ // Reject other random receiver types (e.g. structs).
+ Diag(Loc, diag::err_bad_receiver_type)
+ << ReceiverType << Receiver->getSourceRange();
return ExprError();
- } else if (!Context.getObjCIdType().isNull() &&
- (ReceiverType->isPointerType() ||
- (ReceiverType->isIntegerType() &&
- ReceiverType->isScalarType()))) {
- // Implicitly convert integers and pointers to 'id' but emit a warning.
- Diag(Loc, diag::warn_bad_receiver_type)
- << ReceiverType
- << Receiver->getSourceRange();
- if (ReceiverType->isPointerType())
- ImpCastExprToType(Receiver, Context.getObjCIdType(),
- CastExpr::CK_BitCast);
- else
- ImpCastExprToType(Receiver, Context.getObjCIdType(),
- CastExpr::CK_IntegralToPointer);
- ReceiverType = Receiver->getType();
- } else {
- // Reject other random receiver types (e.g. structs).
- Diag(Loc, diag::err_bad_receiver_type)
- << ReceiverType << Receiver->getSourceRange();
- return ExprError();
+ }
}
}
@@ -992,7 +1004,7 @@
return ExprError();
return BuildInstanceMessage(move(ReceiverE), Receiver->getType(),
- /*SuperLoc=*/SourceLocation(),
- Sel, LBracLoc, RBracLoc, move(Args));
+ /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
+ LBracLoc, RBracLoc, move(Args));
}
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=102081&r1=102080&r2=102081&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Apr 22 12:01:48 2010
@@ -1698,13 +1698,10 @@
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
- // FIXME: Drops Method
return SemaRef.BuildClassMessage(ReceiverTypeInfo,
ReceiverTypeInfo->getType(),
/*SuperLoc=*/SourceLocation(),
- Sel,
- LBracLoc,
- RBracLoc,
+ Sel, Method, LBracLoc, RBracLoc,
move(Args));
}
@@ -1715,14 +1712,11 @@
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
- // FIXME: Drops Method
QualType ReceiverType = static_cast<Expr *>(Receiver.get())->getType();
return SemaRef.BuildInstanceMessage(move(Receiver),
ReceiverType,
/*SuperLoc=*/SourceLocation(),
- Sel,
- LBracLoc,
- RBracLoc,
+ Sel, Method, LBracLoc, RBracLoc,
move(Args));
}
More information about the cfe-commits
mailing list