 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
80.8% |
252 / 312 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
97.4% |
304 / 312 |
| |
|
Line Coverage: |
92.5% |
282 / 305 |
| |
 |
|
 |
1 : //===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file implements semantic analysis for Objective-C expressions.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "Sema.h"
15 : #include "clang/AST/ASTContext.h"
16 : #include "clang/AST/DeclObjC.h"
17 : #include "clang/AST/ExprObjC.h"
18 : #include "llvm/ADT/SmallString.h"
19 : #include "clang/Lex/Preprocessor.h"
20 :
21 : using namespace clang;
22 :
23 : Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
24 : ExprTy **strings,
25 216: unsigned NumStrings) {
26 216: StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
27 :
28 : // Most ObjC strings are formed out of a single piece. However, we *can*
29 : // have strings formed out of multiple @ strings with multiple pptokens in
30 : // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one
31 : // StringLiteral for ObjCStringLiteral to hold onto.
32 216: StringLiteral *S = Strings[0];
33 :
34 : // If we have a multi-part string, merge it all together.
7: branch 0 taken
209: branch 1 taken
35 216: if (NumStrings != 1) {
36 : // Concatenate objc strings.
37 7: llvm::SmallString<128> StrBuf;
38 7: llvm::SmallVector<SourceLocation, 8> StrLocs;
39 :
15: branch 0 taken
7: branch 1 taken
40 22: for (unsigned i = 0; i != NumStrings; ++i) {
41 15: S = Strings[i];
42 :
43 : // ObjC strings can't be wide.
0: branch 1 not taken
15: branch 2 taken
44 15: if (S->isWide()) {
45 : Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
46 0: << S->getSourceRange();
47 0: return true;
48 : }
49 :
50 : // Get the string data.
51 15: StrBuf.append(S->getStrData(), S->getStrData()+S->getByteLength());
52 :
53 : // Get the locations of the string tokens.
54 15: StrLocs.append(S->tokloc_begin(), S->tokloc_end());
55 :
56 : // Free the temporary string.
57 15: S->Destroy(Context);
58 : }
59 :
60 : // Create the aggregate string with the appropriate content and location
61 : // information.
62 : S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false,
63 : Context.getPointerType(Context.CharTy),
7: branch 8 taken
0: branch 9 not taken
7: branch 11 taken
0: branch 12 not taken
64 7: &StrLocs[0], StrLocs.size());
65 : }
66 :
67 : // Verify that this composite string is acceptable for ObjC strings.
0: branch 1 not taken
216: branch 2 taken
68 216: if (CheckObjCString(S))
69 0: return true;
70 :
71 : // Initialize the constant string interface lazily. This assumes
72 : // the NSString interface is seen in this translation unit. Note: We
73 : // don't use NSConstantString, since the runtime team considers this
74 : // interface private (even though it appears in the header files).
75 216: QualType Ty = Context.getObjCConstantStringInterface();
145: branch 1 taken
71: branch 2 taken
76 216: if (!Ty.isNull()) {
77 145: Ty = Context.getObjCObjectPointerType(Ty);
78 : } else {
79 71: IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
80 71: NamedDecl *IF = LookupSingleName(TUScope, NSIdent, LookupOrdinaryName);
37: branch 1 taken
34: branch 2 taken
81 71: if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
82 37: Context.setObjCConstantStringInterface(StrIF);
83 37: Ty = Context.getObjCConstantStringInterface();
84 37: Ty = Context.getObjCObjectPointerType(Ty);
85 : } else {
86 : // If there is no NSString interface defined then treat constant
87 : // strings as untyped objects and let the runtime figure it out later.
88 34: Ty = Context.getObjCIdType();
89 : }
90 : }
91 :
216: branch 1 taken
0: branch 2 not taken
92 216: return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);
93 : }
94 :
95 : Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
96 : QualType EncodedType,
97 32: SourceLocation RParenLoc) {
98 32: QualType StrTy;
1: branch 2 taken
31: branch 3 taken
99 32: if (EncodedType->isDependentType())
100 1: StrTy = Context.DependentTy;
101 : else {
102 31: std::string Str;
103 31: Context.getObjCEncodingForType(EncodedType, Str);
104 :
105 : // The type of @encode is the same as the type of the corresponding string,
106 : // which is an array type.
107 31: StrTy = Context.CharTy;
108 : // A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
2: branch 1 taken
29: branch 2 taken
109 31: if (getLangOptions().CPlusPlus)
110 2: StrTy.addConst();
111 : StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
112 31: ArrayType::Normal, 0);
113 : }
114 :
32: branch 1 taken
0: branch 2 not taken
115 32: return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc);
116 : }
117 :
118 : Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
119 : SourceLocation EncodeLoc,
120 : SourceLocation LParenLoc,
121 : TypeTy *ty,
122 30: SourceLocation RParenLoc) {
123 : // FIXME: Preserve type source info ?
124 30: QualType EncodedType = GetTypeFromParser(ty);
125 :
126 30: return BuildObjCEncodeExpression(AtLoc, EncodedType, RParenLoc);
127 : }
128 :
129 : Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
130 : SourceLocation AtLoc,
131 : SourceLocation SelLoc,
132 : SourceLocation LParenLoc,
133 40: SourceLocation RParenLoc) {
134 : ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
135 40: SourceRange(LParenLoc, RParenLoc), false);
32: branch 0 taken
8: branch 1 taken
136 40: if (!Method)
137 : Method = LookupFactoryMethodInGlobalPool(Sel,
138 32: SourceRange(LParenLoc, RParenLoc));
25: branch 0 taken
15: branch 1 taken
139 40: if (!Method)
140 25: Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
141 :
142 40: QualType Ty = Context.getObjCSelType();
40: branch 1 taken
0: branch 2 not taken
143 40: return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
144 : }
145 :
146 : Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
147 : SourceLocation AtLoc,
148 : SourceLocation ProtoLoc,
149 : SourceLocation LParenLoc,
150 22: SourceLocation RParenLoc) {
151 22: ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId);
2: branch 0 taken
20: branch 1 taken
152 22: if (!PDecl) {
153 2: Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
154 2: return true;
155 : }
156 :
157 20: QualType Ty = Context.getObjCProtoType();
0: branch 1 not taken
20: branch 2 taken
158 20: if (Ty.isNull())
159 0: return true;
160 20: Ty = Context.getObjCObjectPointerType(Ty);
20: branch 1 taken
0: branch 2 not taken
161 20: return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc);
162 : }
163 :
164 : bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
165 : Selector Sel, ObjCMethodDecl *Method,
166 : bool isClassMessage,
167 : SourceLocation lbrac, SourceLocation rbrac,
168 1659: QualType &ReturnType) {
88: branch 0 taken
1571: branch 1 taken
169 1659: if (!Method) {
170 : // Apply default argument promotion as for (C99 6.5.2.2p6).
30: branch 0 taken
88: branch 1 taken
171 118: for (unsigned i = 0; i != NumArgs; i++)
172 30: DefaultArgumentPromotion(Args[i]);
173 :
174 : unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found :
24: branch 0 taken
64: branch 1 taken
175 88: diag::warn_inst_method_not_found;
176 : Diag(lbrac, DiagID)
177 88: << Sel << isClassMessage << SourceRange(lbrac, rbrac);
178 88: ReturnType = Context.getObjCIdType();
179 88: return false;
180 : }
181 :
182 1571: ReturnType = Method->getResultType();
183 :
184 1571: unsigned NumNamedArgs = Sel.getNumArgs();
0: branch 0 not taken
1571: branch 1 taken
185 1571: assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!");
186 :
187 1571: bool IsError = false;
627: branch 0 taken
1571: branch 1 taken
188 2198: for (unsigned i = 0; i < NumNamedArgs; i++) {
189 627: Expr *argExpr = Args[i];
0: branch 0 not taken
627: branch 1 taken
190 627: assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
191 :
192 627: QualType lhsType = Method->param_begin()[i]->getType();
193 627: QualType rhsType = argExpr->getType();
194 :
195 : // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
0: branch 2 not taken
627: branch 3 taken
196 627: if (lhsType->isArrayType())
197 0: lhsType = Context.getArrayDecayedType(lhsType);
0: branch 2 not taken
627: branch 3 taken
198 627: else if (lhsType->isFunctionType())
199 0: lhsType = Context.getPointerType(lhsType);
200 :
201 : AssignConvertType Result =
202 627: CheckSingleAssignmentConstraints(lhsType, argExpr);
258: branch 0 taken
369: branch 1 taken
203 627: if (Args[i] != argExpr) // The expression was converted.
204 258: Args[i] = argExpr; // Make sure we store the converted expression.
205 :
206 : IsError |=
207 : DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
208 627: argExpr, AA_Sending);
209 : }
210 :
211 : // Promote additional arguments to variadic methods.
47: branch 1 taken
1524: branch 2 taken
212 1571: if (Method->isVariadic()) {
163: branch 0 taken
47: branch 1 taken
213 210: for (unsigned i = NumNamedArgs; i < NumArgs; ++i)
214 163: IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod);
215 : } else {
216 : // Check for extra arguments to non-variadic methods.
1: branch 0 taken
1523: branch 1 taken
217 1524: if (NumArgs != NumNamedArgs) {
218 : Diag(Args[NumNamedArgs]->getLocStart(),
219 : diag::err_typecheck_call_too_many_args)
220 : << 2 /*method*/ << Method->getSourceRange()
221 : << SourceRange(Args[NumNamedArgs]->getLocStart(),
222 1: Args[NumArgs-1]->getLocEnd());
223 : }
224 : }
225 :
226 1571: return IsError;
227 : }
228 :
229 68: bool Sema::isSelfExpr(Expr *RExpr) {
55: branch 1 taken
13: branch 2 taken
230 68: if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr))
9: branch 4 taken
46: branch 5 taken
231 55: if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self"))
232 9: return true;
233 59: return false;
234 : }
235 :
236 : // Helper method for ActOnClassMethod/ActOnInstanceMethod.
237 : // Will search "local" class/category implementations for a method decl.
238 : // If failed, then we search in class's root for an instance method.
239 : // Returns 0 if no method is found.
240 : ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
241 87: ObjCInterfaceDecl *ClassDecl) {
242 87: ObjCMethodDecl *Method = 0;
243 : // lookup in class and all superclasses
166: branch 0 taken
77: branch 1 taken
156: branch 2 taken
10: branch 3 taken
244 330: while (ClassDecl && !Method) {
66: branch 1 taken
90: branch 2 taken
245 156: if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
246 66: Method = ImpDecl->getClassMethod(Sel);
247 :
248 : // Look through local category implementations associated with the class.
140: branch 0 taken
16: branch 1 taken
249 156: if (!Method)
250 140: Method = ClassDecl->getCategoryClassMethod(Sel);
251 :
252 : // Before we give up, check if the selector is an instance method.
253 : // But only in the root. This matches gcc's behaviour and what the
254 : // runtime expects.
134: branch 0 taken
22: branch 1 taken
65: branch 3 taken
69: branch 4 taken
65: branch 5 taken
91: branch 6 taken
255 156: if (!Method && !ClassDecl->getSuperClass()) {
256 65: Method = ClassDecl->lookupInstanceMethod(Sel);
257 : // Look through local category implementations associated
258 : // with the root class.
30: branch 0 taken
35: branch 1 taken
259 65: if (!Method)
260 30: Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
261 : }
262 :
263 156: ClassDecl = ClassDecl->getSuperClass();
264 : }
265 87: return Method;
266 : }
267 :
268 : ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
269 103: ObjCInterfaceDecl *ClassDecl) {
270 103: ObjCMethodDecl *Method = 0;
117: branch 0 taken
96: branch 1 taken
110: branch 2 taken
7: branch 3 taken
271 316: while (ClassDecl && !Method) {
272 : // If we have implementations in scope, check "private" methods.
20: branch 1 taken
90: branch 2 taken
273 110: if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
274 20: Method = ImpDecl->getInstanceMethod(Sel);
275 :
276 : // Look through local category implementations associated with the class.
101: branch 0 taken
9: branch 1 taken
277 110: if (!Method)
278 101: Method = ClassDecl->getCategoryInstanceMethod(Sel);
279 110: ClassDecl = ClassDecl->getSuperClass();
280 : }
281 103: return Method;
282 : }
283 :
284 : Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
285 : IdentifierInfo &receiverName,
286 : IdentifierInfo &propertyName,
287 : SourceLocation &receiverNameLoc,
288 17: SourceLocation &propertyNameLoc) {
289 :
290 17: IdentifierInfo *receiverNamePtr = &receiverName;
291 17: ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr);
292 :
293 : // Search for a declared property first.
294 :
295 17: Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
296 17: ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
297 :
298 : // If this reference is in an @implementation, check for 'private' methods.
3: branch 0 taken
14: branch 1 taken
299 17: if (!Getter)
0: branch 1 not taken
3: branch 2 taken
300 3: if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
0: branch 1 not taken
0: branch 2 not taken
301 0: if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
0: branch 1 not taken
0: branch 2 not taken
302 0: if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
303 0: Getter = ImpDecl->getClassMethod(Sel);
304 :
14: branch 0 taken
3: branch 1 taken
305 17: if (Getter) {
306 : // FIXME: refactor/share with ActOnMemberReference().
307 : // Check if we can reference this property.
0: branch 1 not taken
14: branch 2 taken
308 14: if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
309 0: return ExprError();
310 : }
311 :
312 : // Look for the matching setter, in case it is needed.
313 : Selector SetterSel =
314 : SelectorTable::constructSetterName(PP.getIdentifierTable(),
315 17: PP.getSelectorTable(), &propertyName);
316 :
317 17: ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
3: branch 0 taken
14: branch 1 taken
318 17: if (!Setter) {
319 : // If this reference is in an @implementation, also check for 'private'
320 : // methods.
0: branch 1 not taken
3: branch 2 taken
321 3: if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
0: branch 1 not taken
0: branch 2 not taken
322 0: if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
0: branch 1 not taken
0: branch 2 not taken
323 0: if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
324 0: Setter = ImpDecl->getClassMethod(SetterSel);
325 : }
326 : // Look through local category implementations associated with the class.
3: branch 0 taken
14: branch 1 taken
327 17: if (!Setter)
328 3: Setter = IFace->getCategoryClassMethod(SetterSel);
329 :
14: branch 0 taken
3: branch 1 taken
0: branch 3 not taken
14: branch 4 taken
0: branch 5 not taken
17: branch 6 taken
330 17: if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
331 0: return ExprError();
332 :
3: branch 0 taken
14: branch 1 taken
2: branch 2 taken
1: branch 3 taken
333 17: if (Getter || Setter) {
334 16: QualType PType;
335 :
14: branch 0 taken
2: branch 1 taken
336 16: if (Getter)
337 14: PType = Getter->getResultType();
338 : else {
2: branch 1 taken
2: branch 2 taken
339 6: for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
340 2: E = Setter->param_end(); PI != E; ++PI)
341 2: PType = (*PI)->getType();
342 : }
343 : return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(
344 : Getter, PType, Setter,
16: branch 1 taken
0: branch 2 not taken
345 16: propertyNameLoc, IFace, receiverNameLoc));
346 : }
347 : return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
348 1: << &propertyName << Context.getObjCInterfaceType(IFace));
349 : }
350 :
351 :
352 : // ActOnClassMessage - used for both unary and keyword messages.
353 : // ArgExprs is optional - if it is present, the number of expressions
354 : // is obtained from Sel.getNumArgs().
355 : Sema::ExprResult Sema::ActOnClassMessage(
356 : Scope *S,
357 : IdentifierInfo *receiverName, Selector Sel,
358 : SourceLocation lbrac, SourceLocation receiverLoc,
359 : SourceLocation selectorLoc, SourceLocation rbrac,
360 550: ExprTy **Args, unsigned NumArgs) {
0: branch 0 not taken
550: branch 1 taken
361 550: assert(receiverName && "missing receiver class name");
362 :
363 550: Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
364 550: ObjCInterfaceDecl* ClassDecl = 0;
365 550: bool isSuper = false;
366 :
105: branch 1 taken
445: branch 2 taken
367 550: if (receiverName->isStr("super")) {
96: branch 1 taken
9: branch 2 taken
368 105: if (getCurMethodDecl()) {
369 96: isSuper = true;
370 96: ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface();
1: branch 0 taken
95: branch 1 taken
371 96: if (!OID)
372 : return Diag(lbrac, diag::error_no_super_class_message)
373 1: << getCurMethodDecl()->getDeclName();
374 95: ClassDecl = OID->getSuperClass();
1: branch 0 taken
94: branch 1 taken
375 95: if (!ClassDecl)
376 1: return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
66: branch 2 taken
28: branch 3 taken
377 94: if (getCurMethodDecl()->isInstanceMethod()) {
378 66: QualType superTy = Context.getObjCInterfaceType(ClassDecl);
379 66: superTy = Context.getObjCObjectPointerType(superTy);
380 : ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
66: branch 2 taken
0: branch 3 not taken
381 66: superTy);
382 : // We are really in an instance method, redirect.
383 : return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
384 66: selectorLoc, rbrac, Args, NumArgs);
385 : }
386 : // We are sending a message to 'super' within a class method. Do nothing,
387 : // the receiver will pass through as 'super' (how convenient:-).
388 : } else {
389 : // 'super' has been used outside a method context. If a variable named
390 : // 'super' has been declared, redirect. If not, produce a diagnostic.
391 : NamedDecl *SuperDecl
392 9: = LookupSingleName(S, receiverName, LookupOrdinaryName);
393 9: ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
7: branch 0 taken
2: branch 1 taken
394 9: if (VD) {
395 : ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(),
7: branch 2 taken
0: branch 3 not taken
396 7: receiverLoc);
397 : // We are really in an instance method, redirect.
398 : return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
399 7: selectorLoc, rbrac, Args, NumArgs);
400 : }
1: branch 1 taken
1: branch 2 taken
401 2: else if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(SuperDecl)) {
402 : const ObjCInterfaceType *OCIT;
403 1: OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
0: branch 0 not taken
1: branch 1 taken
404 1: if (!OCIT) {
405 0: Diag(receiverLoc, diag::err_invalid_receiver_to_message);
406 0: return true;
407 : }
408 1: ClassDecl = OCIT->getDecl();
409 : }
410 : else
411 1: return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
412 : }
413 : } else
414 445: ClassDecl = getObjCInterfaceDecl(receiverName, receiverLoc);
415 :
416 : // The following code allows for the following GCC-ism:
417 : //
418 : // typedef XCElementDisplayRect XCElementGraphicsRect;
419 : //
420 : // @implementation XCRASlice
421 : // - whatever { // Note that XCElementGraphicsRect is a typedef name.
422 : // _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init];
423 : // }
424 : //
425 : // If necessary, the following lookup could move to getObjCInterfaceDecl().
2: branch 0 taken
472: branch 1 taken
426 474: if (!ClassDecl) {
427 : NamedDecl *IDecl
428 2: = LookupSingleName(TUScope, receiverName, LookupOrdinaryName);
2: branch 1 taken
0: branch 2 not taken
429 2: if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) {
430 : const ObjCInterfaceType *OCIT;
431 2: OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
1: branch 0 taken
1: branch 1 taken
432 2: if (!OCIT) {
433 1: Diag(receiverLoc, diag::err_invalid_receiver_to_message);
434 1: return true;
435 : }
436 1: ClassDecl = OCIT->getDecl();
437 : }
438 : }
0: branch 0 not taken
473: branch 1 taken
439 473: assert(ClassDecl && "missing interface declaration");
440 473: ObjCMethodDecl *Method = 0;
441 473: QualType returnType;
2: branch 1 taken
471: branch 2 taken
442 473: if (ClassDecl->isForwardDecl()) {
443 : // A forward class used in messaging is tread as a 'Class'
444 2: Diag(lbrac, diag::warn_receiver_forward_class) << ClassDecl->getDeclName();
445 2: Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
1: branch 0 taken
1: branch 1 taken
446 2: if (Method)
447 : Diag(Method->getLocation(), diag::note_method_sent_forward_class)
448 1: << Method->getDeclName();
449 : }
472: branch 0 taken
1: branch 1 taken
450 473: if (!Method)
451 472: Method = ClassDecl->lookupClassMethod(Sel);
452 :
453 : // If we have an implementation in scope, check "private" methods.
75: branch 0 taken
398: branch 1 taken
454 473: if (!Method)
455 75: Method = LookupPrivateClassMethod(Sel, ClassDecl);
456 :
449: branch 0 taken
24: branch 1 taken
0: branch 3 not taken
449: branch 4 taken
0: branch 5 not taken
473: branch 6 taken
457 473: if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
458 0: return true;
459 :
0: branch 1 not taken
473: branch 2 taken
460 473: if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
461 : lbrac, rbrac, returnType))
462 0: return true;
463 :
464 473: returnType = returnType.getNonReferenceType();
465 :
466 : // If we have the ObjCInterfaceDecl* for the class that is receiving the
467 : // message, use that to construct the ObjCMessageExpr. Otherwise pass on the
468 : // IdentifierInfo* for the class.
469 : // FIXME: need to do a better job handling 'super' usage within a class. For
470 : // now, we simply pass the "super" identifier through (which isn't consistent
471 : // with instance methods.
28: branch 0 taken
445: branch 1 taken
472 473: if (isSuper)
473 : return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method,
28: branch 1 taken
0: branch 2 not taken
474 28: lbrac, rbrac, ArgExprs, NumArgs);
475 : else
476 : return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method,
445: branch 1 taken
0: branch 2 not taken
477 445: lbrac, rbrac, ArgExprs, NumArgs);
478 : }
479 :
480 : // ActOnInstanceMessage - used for both unary and keyword messages.
481 : // ArgExprs is optional - if it is present, the number of expressions
482 : // is obtained from Sel.getNumArgs().
483 : Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
484 : SourceLocation lbrac,
485 : SourceLocation receiverLoc,
486 : SourceLocation rbrac,
487 1187: ExprTy **Args, unsigned NumArgs) {
0: branch 0 not taken
1187: branch 1 taken
488 1187: assert(receiver && "missing receiver expression");
489 :
490 1187: Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
491 1187: Expr *RExpr = static_cast<Expr *>(receiver);
492 :
493 : // If necessary, apply function/array conversion to the receiver.
494 : // C99 6.7.5.3p[7,8].
495 1187: DefaultFunctionArrayLvalueConversion(RExpr);
496 :
497 1187: QualType returnType;
498 : QualType ReceiverCType =
499 1187: Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
500 :
501 : // Handle messages to 'super'.
66: branch 1 taken
1121: branch 2 taken
502 1187: if (isa<ObjCSuperExpr>(RExpr)) {
503 66: ObjCMethodDecl *Method = 0;
66: branch 1 taken
0: branch 2 not taken
504 66: if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
505 : // If we have an interface in scope, check 'super' methods.
66: branch 1 taken
0: branch 2 not taken
506 66: if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
66: branch 1 taken
0: branch 2 not taken
507 66: if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) {
508 66: Method = SuperDecl->lookupInstanceMethod(Sel);
509 :
12: branch 0 taken
54: branch 1 taken
510 66: if (!Method)
511 : // If we have implementations in scope, check "private" methods.
512 12: Method = LookupPrivateInstanceMethod(Sel, SuperDecl);
513 : }
514 : }
515 :
57: branch 0 taken
9: branch 1 taken
0: branch 3 not taken
57: branch 4 taken
0: branch 5 not taken
66: branch 6 taken
516 66: if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
517 0: return true;
518 :
0: branch 1 not taken
66: branch 2 taken
519 66: if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
520 : lbrac, rbrac, returnType))
521 0: return true;
522 :
523 66: returnType = returnType.getNonReferenceType();
524 : return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
66: branch 1 taken
0: branch 2 not taken
525 66: rbrac, ArgExprs, NumArgs);
526 : }
527 :
528 : // Handle messages to id.
687: branch 2 taken
434: branch 3 taken
681: branch 6 taken
6: branch 7 taken
4: branch 10 taken
677: branch 11 taken
444: branch 12 taken
677: branch 13 taken
529 1121: if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
530 : Context.isObjCNSObjectType(RExpr->getType())) {
531 : ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(
532 444: Sel, SourceRange(lbrac,rbrac));
30: branch 0 taken
414: branch 1 taken
533 444: if (!Method)
534 30: Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac));
2: branch 1 taken
442: branch 2 taken
535 444: if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
536 : lbrac, rbrac, returnType))
537 2: return true;
538 442: returnType = returnType.getNonReferenceType();
539 : return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
442: branch 1 taken
0: branch 2 not taken
540 442: rbrac, ArgExprs, NumArgs);
541 : }
542 :
543 : // Handle messages to Class.
653: branch 2 taken
24: branch 3 taken
2: branch 6 taken
651: branch 7 taken
26: branch 8 taken
651: branch 9 taken
544 677: if (ReceiverCType->isObjCClassType() ||
545 : ReceiverCType->isObjCQualifiedClassType()) {
546 26: ObjCMethodDecl *Method = 0;
547 :
18: branch 1 taken
8: branch 2 taken
548 26: if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
18: branch 1 taken
0: branch 2 not taken
549 18: if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
550 : // First check the public methods in the class interface.
551 18: Method = ClassDecl->lookupClassMethod(Sel);
552 :
12: branch 0 taken
6: branch 1 taken
553 18: if (!Method)
554 12: Method = LookupPrivateClassMethod(Sel, ClassDecl);
555 :
556 : // FIXME: if we still haven't found a method, we need to look in
557 : // protocols (if we have qualifiers).
558 : }
13: branch 0 taken
5: branch 1 taken
0: branch 3 not taken
13: branch 4 taken
0: branch 5 not taken
18: branch 6 taken
559 18: if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
560 0: return true;
561 : }
13: branch 0 taken
13: branch 1 taken
562 26: if (!Method) {
563 : // If not messaging 'self', look for any factory method named 'Sel'.
10: branch 1 taken
3: branch 2 taken
564 13: if (!isSelfExpr(RExpr)) {
565 10: Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
3: branch 0 taken
7: branch 1 taken
566 10: if (!Method) {
567 : // If no class (factory) method was found, check if an _instance_
568 : // method of the same name exists in the root class only.
569 : Method = LookupInstanceMethodInGlobalPool(
570 3: Sel, SourceRange(lbrac,rbrac));
3: branch 0 taken
0: branch 1 not taken
571 3: if (Method)
2: branch 0 taken
1: branch 1 taken
572 3: if (const ObjCInterfaceDecl *ID =
573 3: dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
1: branch 1 taken
1: branch 2 taken
574 2: if (ID->getSuperClass())
575 : Diag(lbrac, diag::warn_root_inst_method_not_found)
576 1: << Sel << SourceRange(lbrac, rbrac);
577 : }
578 : }
579 : }
580 : }
0: branch 1 not taken
26: branch 2 taken
581 26: if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
582 : lbrac, rbrac, returnType))
583 0: return true;
584 26: returnType = returnType.getNonReferenceType();
585 : return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
26: branch 1 taken
0: branch 2 not taken
586 26: rbrac, ArgExprs, NumArgs);
587 : }
588 :
589 651: ObjCMethodDecl *Method = 0;
590 651: ObjCInterfaceDecl* ClassDecl = 0;
591 :
592 : // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
593 : // long as one of the protocols implements the selector (if not, warn).
23: branch 0 taken
628: branch 1 taken
594 651: if (const ObjCObjectPointerType *QIdTy =
595 651: ReceiverCType->getAsObjCQualifiedIdType()) {
596 : // Search protocols for instance methods.
23: branch 1 taken
1: branch 2 taken
597 47: for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
598 23: E = QIdTy->qual_end(); I != E; ++I) {
599 23: ObjCProtocolDecl *PDecl = *I;
23: branch 0 taken
0: branch 1 not taken
20: branch 3 taken
3: branch 4 taken
20: branch 5 taken
3: branch 6 taken
600 23: if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
601 20: break;
602 : // Since we aren't supporting "Class<foo>", look for a class method.
3: branch 0 taken
0: branch 1 not taken
2: branch 3 taken
1: branch 4 taken
2: branch 5 taken
1: branch 6 taken
603 3: if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
604 2: break;
605 : }
620: branch 0 taken
8: branch 1 taken
606 628: } else if (const ObjCObjectPointerType *OCIType =
607 628: ReceiverCType->getAsObjCInterfacePointerType()) {
608 : // We allow sending a message to a pointer to an interface (an object).
609 :
610 620: ClassDecl = OCIType->getInterfaceDecl();
611 : // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
612 : // faster than the following method (which can do *many* linear searches).
613 : // The idea is to add class info to InstanceMethodPool.
614 620: Method = ClassDecl->lookupInstanceMethod(Sel);
615 :
66: branch 0 taken
554: branch 1 taken
616 620: if (!Method) {
617 : // Search protocol qualifiers.
6: branch 1 taken
61: branch 2 taken
618 133: for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
619 66: E = OCIType->qual_end(); QI != E; ++QI) {
5: branch 1 taken
1: branch 2 taken
620 6: if ((Method = (*QI)->lookupInstanceMethod(Sel)))
621 5: break;
622 : }
623 : }
61: branch 0 taken
559: branch 1 taken
624 620: if (!Method) {
625 : // If we have implementations in scope, check "private" methods.
626 61: Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
627 :
50: branch 0 taken
11: branch 1 taken
48: branch 3 taken
2: branch 4 taken
48: branch 5 taken
13: branch 6 taken
628 61: if (!Method && !isSelfExpr(RExpr)) {
629 : // If we still haven't found a method, look in the global pool. This
630 : // behavior isn't very desirable, however we need it for GCC
631 : // compatibility. FIXME: should we deviate??
47: branch 1 taken
1: branch 2 taken
632 48: if (OCIType->qual_empty()) {
633 : Method = LookupInstanceMethodInGlobalPool(
634 47: Sel, SourceRange(lbrac,rbrac));
32: branch 0 taken
15: branch 1 taken
2: branch 4 taken
30: branch 5 taken
2: branch 6 taken
45: branch 7 taken
635 47: if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
636 : Diag(lbrac, diag::warn_maynot_respond)
637 2: << OCIType->getInterfaceDecl()->getIdentifier()->getName() << Sel;
638 : }
639 : }
640 : }
602: branch 0 taken
18: branch 1 taken
0: branch 3 not taken
602: branch 4 taken
0: branch 5 not taken
620: branch 6 taken
641 620: if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
642 0: return true;
8: branch 2 taken
0: branch 3 not taken
4: branch 6 taken
4: branch 7 taken
3: branch 10 taken
1: branch 11 taken
3: branch 14 taken
0: branch 15 not taken
7: branch 16 taken
1: branch 17 taken
643 8: } else if (!Context.getObjCIdType().isNull() &&
644 : (ReceiverCType->isPointerType() ||
645 : (ReceiverCType->isIntegerType() &&
646 : ReceiverCType->isScalarType()))) {
647 : // Implicitly convert integers and pointers to 'id' but emit a warning.
648 : Diag(lbrac, diag::warn_bad_receiver_type)
649 7: << RExpr->getType() << RExpr->getSourceRange();
4: branch 2 taken
3: branch 3 taken
650 7: if (ReceiverCType->isPointerType())
651 4: ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast);
652 : else
653 : ImpCastExprToType(RExpr, Context.getObjCIdType(),
654 3: CastExpr::CK_IntegralToPointer);
655 : } else {
656 : // Reject other random receiver types (e.g. structs).
657 : Diag(lbrac, diag::err_bad_receiver_type)
658 1: << RExpr->getType() << RExpr->getSourceRange();
659 1: return true;
660 : }
661 :
624: branch 0 taken
26: branch 1 taken
662 650: if (Method)
663 624: DiagnoseSentinelCalls(Method, receiverLoc, ArgExprs, NumArgs);
1: branch 1 taken
649: branch 2 taken
664 650: if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
665 : lbrac, rbrac, returnType))
666 1: return true;
667 649: returnType = returnType.getNonReferenceType();
668 : return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
649: branch 1 taken
0: branch 2 not taken
669 649: rbrac, ArgExprs, NumArgs);
670 : }
671 :
Generated: 2010-02-10 01:31 by zcov