File: | tools/clang/lib/Sema/SemaExprObjC.cpp |
Warning: | line 1714, column 14 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 "clang/Sema/SemaInternal.h" | |||||
15 | #include "clang/AST/ASTContext.h" | |||||
16 | #include "clang/AST/DeclObjC.h" | |||||
17 | #include "clang/AST/ExprObjC.h" | |||||
18 | #include "clang/AST/StmtVisitor.h" | |||||
19 | #include "clang/AST/TypeLoc.h" | |||||
20 | #include "clang/Analysis/DomainSpecific/CocoaConventions.h" | |||||
21 | #include "clang/Edit/Commit.h" | |||||
22 | #include "clang/Edit/Rewriters.h" | |||||
23 | #include "clang/Lex/Preprocessor.h" | |||||
24 | #include "clang/Sema/Initialization.h" | |||||
25 | #include "clang/Sema/Lookup.h" | |||||
26 | #include "clang/Sema/Scope.h" | |||||
27 | #include "clang/Sema/ScopeInfo.h" | |||||
28 | #include "llvm/ADT/SmallString.h" | |||||
29 | ||||||
30 | using namespace clang; | |||||
31 | using namespace sema; | |||||
32 | using llvm::makeArrayRef; | |||||
33 | ||||||
34 | ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, | |||||
35 | ArrayRef<Expr *> Strings) { | |||||
36 | // Most ObjC strings are formed out of a single piece. However, we *can* | |||||
37 | // have strings formed out of multiple @ strings with multiple pptokens in | |||||
38 | // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one | |||||
39 | // StringLiteral for ObjCStringLiteral to hold onto. | |||||
40 | StringLiteral *S = cast<StringLiteral>(Strings[0]); | |||||
41 | ||||||
42 | // If we have a multi-part string, merge it all together. | |||||
43 | if (Strings.size() != 1) { | |||||
44 | // Concatenate objc strings. | |||||
45 | SmallString<128> StrBuf; | |||||
46 | SmallVector<SourceLocation, 8> StrLocs; | |||||
47 | ||||||
48 | for (Expr *E : Strings) { | |||||
49 | S = cast<StringLiteral>(E); | |||||
50 | ||||||
51 | // ObjC strings can't be wide or UTF. | |||||
52 | if (!S->isAscii()) { | |||||
53 | Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant) | |||||
54 | << S->getSourceRange(); | |||||
55 | return true; | |||||
56 | } | |||||
57 | ||||||
58 | // Append the string. | |||||
59 | StrBuf += S->getString(); | |||||
60 | ||||||
61 | // Get the locations of the string tokens. | |||||
62 | StrLocs.append(S->tokloc_begin(), S->tokloc_end()); | |||||
63 | } | |||||
64 | ||||||
65 | // Create the aggregate string with the appropriate content and location | |||||
66 | // information. | |||||
67 | const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType()); | |||||
68 | assert(CAT && "String literal not of constant array type!")(static_cast <bool> (CAT && "String literal not of constant array type!" ) ? void (0) : __assert_fail ("CAT && \"String literal not of constant array type!\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 68, __extension__ __PRETTY_FUNCTION__)); | |||||
69 | QualType StrTy = Context.getConstantArrayType( | |||||
70 | CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1), | |||||
71 | CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers()); | |||||
72 | S = StringLiteral::Create(Context, StrBuf, StringLiteral::Ascii, | |||||
73 | /*Pascal=*/false, StrTy, &StrLocs[0], | |||||
74 | StrLocs.size()); | |||||
75 | } | |||||
76 | ||||||
77 | return BuildObjCStringLiteral(AtLocs[0], S); | |||||
78 | } | |||||
79 | ||||||
80 | ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){ | |||||
81 | // Verify that this composite string is acceptable for ObjC strings. | |||||
82 | if (CheckObjCString(S)) | |||||
83 | return true; | |||||
84 | ||||||
85 | // Initialize the constant string interface lazily. This assumes | |||||
86 | // the NSString interface is seen in this translation unit. Note: We | |||||
87 | // don't use NSConstantString, since the runtime team considers this | |||||
88 | // interface private (even though it appears in the header files). | |||||
89 | QualType Ty = Context.getObjCConstantStringInterface(); | |||||
90 | if (!Ty.isNull()) { | |||||
91 | Ty = Context.getObjCObjectPointerType(Ty); | |||||
92 | } else if (getLangOpts().NoConstantCFStrings) { | |||||
93 | IdentifierInfo *NSIdent=nullptr; | |||||
94 | std::string StringClass(getLangOpts().ObjCConstantStringClass); | |||||
95 | ||||||
96 | if (StringClass.empty()) | |||||
97 | NSIdent = &Context.Idents.get("NSConstantString"); | |||||
98 | else | |||||
99 | NSIdent = &Context.Idents.get(StringClass); | |||||
100 | ||||||
101 | NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, | |||||
102 | LookupOrdinaryName); | |||||
103 | if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { | |||||
104 | Context.setObjCConstantStringInterface(StrIF); | |||||
105 | Ty = Context.getObjCConstantStringInterface(); | |||||
106 | Ty = Context.getObjCObjectPointerType(Ty); | |||||
107 | } else { | |||||
108 | // If there is no NSConstantString interface defined then treat this | |||||
109 | // as error and recover from it. | |||||
110 | Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent | |||||
111 | << S->getSourceRange(); | |||||
112 | Ty = Context.getObjCIdType(); | |||||
113 | } | |||||
114 | } else { | |||||
115 | IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString); | |||||
116 | NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc, | |||||
117 | LookupOrdinaryName); | |||||
118 | if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { | |||||
119 | Context.setObjCConstantStringInterface(StrIF); | |||||
120 | Ty = Context.getObjCConstantStringInterface(); | |||||
121 | Ty = Context.getObjCObjectPointerType(Ty); | |||||
122 | } else { | |||||
123 | // If there is no NSString interface defined, implicitly declare | |||||
124 | // a @class NSString; and use that instead. This is to make sure | |||||
125 | // type of an NSString literal is represented correctly, instead of | |||||
126 | // being an 'id' type. | |||||
127 | Ty = Context.getObjCNSStringType(); | |||||
128 | if (Ty.isNull()) { | |||||
129 | ObjCInterfaceDecl *NSStringIDecl = | |||||
130 | ObjCInterfaceDecl::Create (Context, | |||||
131 | Context.getTranslationUnitDecl(), | |||||
132 | SourceLocation(), NSIdent, | |||||
133 | nullptr, nullptr, SourceLocation()); | |||||
134 | Ty = Context.getObjCInterfaceType(NSStringIDecl); | |||||
135 | Context.setObjCNSStringType(Ty); | |||||
136 | } | |||||
137 | Ty = Context.getObjCObjectPointerType(Ty); | |||||
138 | } | |||||
139 | } | |||||
140 | ||||||
141 | return new (Context) ObjCStringLiteral(S, Ty, AtLoc); | |||||
142 | } | |||||
143 | ||||||
144 | /// \brief Emits an error if the given method does not exist, or if the return | |||||
145 | /// type is not an Objective-C object. | |||||
146 | static bool validateBoxingMethod(Sema &S, SourceLocation Loc, | |||||
147 | const ObjCInterfaceDecl *Class, | |||||
148 | Selector Sel, const ObjCMethodDecl *Method) { | |||||
149 | if (!Method) { | |||||
150 | // FIXME: Is there a better way to avoid quotes than using getName()? | |||||
151 | S.Diag(Loc, diag::err_undeclared_boxing_method) << Sel << Class->getName(); | |||||
152 | return false; | |||||
153 | } | |||||
154 | ||||||
155 | // Make sure the return type is reasonable. | |||||
156 | QualType ReturnType = Method->getReturnType(); | |||||
157 | if (!ReturnType->isObjCObjectPointerType()) { | |||||
158 | S.Diag(Loc, diag::err_objc_literal_method_sig) | |||||
159 | << Sel; | |||||
160 | S.Diag(Method->getLocation(), diag::note_objc_literal_method_return) | |||||
161 | << ReturnType; | |||||
162 | return false; | |||||
163 | } | |||||
164 | ||||||
165 | return true; | |||||
166 | } | |||||
167 | ||||||
168 | /// \brief Maps ObjCLiteralKind to NSClassIdKindKind | |||||
169 | static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind( | |||||
170 | Sema::ObjCLiteralKind LiteralKind) { | |||||
171 | switch (LiteralKind) { | |||||
172 | case Sema::LK_Array: | |||||
173 | return NSAPI::ClassId_NSArray; | |||||
174 | case Sema::LK_Dictionary: | |||||
175 | return NSAPI::ClassId_NSDictionary; | |||||
176 | case Sema::LK_Numeric: | |||||
177 | return NSAPI::ClassId_NSNumber; | |||||
178 | case Sema::LK_String: | |||||
179 | return NSAPI::ClassId_NSString; | |||||
180 | case Sema::LK_Boxed: | |||||
181 | return NSAPI::ClassId_NSValue; | |||||
182 | ||||||
183 | // there is no corresponding matching | |||||
184 | // between LK_None/LK_Block and NSClassIdKindKind | |||||
185 | case Sema::LK_Block: | |||||
186 | case Sema::LK_None: | |||||
187 | break; | |||||
188 | } | |||||
189 | llvm_unreachable("LiteralKind can't be converted into a ClassKind")::llvm::llvm_unreachable_internal("LiteralKind can't be converted into a ClassKind" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 189); | |||||
190 | } | |||||
191 | ||||||
192 | /// \brief Validates ObjCInterfaceDecl availability. | |||||
193 | /// ObjCInterfaceDecl, used to create ObjC literals, should be defined | |||||
194 | /// if clang not in a debugger mode. | |||||
195 | static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl, | |||||
196 | SourceLocation Loc, | |||||
197 | Sema::ObjCLiteralKind LiteralKind) { | |||||
198 | if (!Decl) { | |||||
199 | NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind); | |||||
200 | IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind); | |||||
201 | S.Diag(Loc, diag::err_undeclared_objc_literal_class) | |||||
202 | << II->getName() << LiteralKind; | |||||
203 | return false; | |||||
204 | } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) { | |||||
205 | S.Diag(Loc, diag::err_undeclared_objc_literal_class) | |||||
206 | << Decl->getName() << LiteralKind; | |||||
207 | S.Diag(Decl->getLocation(), diag::note_forward_class); | |||||
208 | return false; | |||||
209 | } | |||||
210 | ||||||
211 | return true; | |||||
212 | } | |||||
213 | ||||||
214 | /// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind. | |||||
215 | /// Used to create ObjC literals, such as NSDictionary (@{}), | |||||
216 | /// NSArray (@[]) and Boxed Expressions (@()) | |||||
217 | static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S, | |||||
218 | SourceLocation Loc, | |||||
219 | Sema::ObjCLiteralKind LiteralKind) { | |||||
220 | NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind); | |||||
221 | IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind); | |||||
222 | NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc, | |||||
223 | Sema::LookupOrdinaryName); | |||||
224 | ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF); | |||||
225 | if (!ID && S.getLangOpts().DebuggerObjCLiteral) { | |||||
226 | ASTContext &Context = S.Context; | |||||
227 | TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); | |||||
228 | ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II, | |||||
229 | nullptr, nullptr, SourceLocation()); | |||||
230 | } | |||||
231 | ||||||
232 | if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) { | |||||
233 | ID = nullptr; | |||||
234 | } | |||||
235 | ||||||
236 | return ID; | |||||
237 | } | |||||
238 | ||||||
239 | /// \brief Retrieve the NSNumber factory method that should be used to create | |||||
240 | /// an Objective-C literal for the given type. | |||||
241 | static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, | |||||
242 | QualType NumberType, | |||||
243 | bool isLiteral = false, | |||||
244 | SourceRange R = SourceRange()) { | |||||
245 | Optional<NSAPI::NSNumberLiteralMethodKind> Kind = | |||||
246 | S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType); | |||||
247 | ||||||
248 | if (!Kind) { | |||||
249 | if (isLiteral) { | |||||
250 | S.Diag(Loc, diag::err_invalid_nsnumber_type) | |||||
251 | << NumberType << R; | |||||
252 | } | |||||
253 | return nullptr; | |||||
254 | } | |||||
255 | ||||||
256 | // If we already looked up this method, we're done. | |||||
257 | if (S.NSNumberLiteralMethods[*Kind]) | |||||
258 | return S.NSNumberLiteralMethods[*Kind]; | |||||
259 | ||||||
260 | Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind, | |||||
261 | /*Instance=*/false); | |||||
262 | ||||||
263 | ASTContext &CX = S.Context; | |||||
264 | ||||||
265 | // Look up the NSNumber class, if we haven't done so already. It's cached | |||||
266 | // in the Sema instance. | |||||
267 | if (!S.NSNumberDecl) { | |||||
268 | S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc, | |||||
269 | Sema::LK_Numeric); | |||||
270 | if (!S.NSNumberDecl) { | |||||
271 | return nullptr; | |||||
272 | } | |||||
273 | } | |||||
274 | ||||||
275 | if (S.NSNumberPointer.isNull()) { | |||||
276 | // generate the pointer to NSNumber type. | |||||
277 | QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl); | |||||
278 | S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject); | |||||
279 | } | |||||
280 | ||||||
281 | // Look for the appropriate method within NSNumber. | |||||
282 | ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel); | |||||
283 | if (!Method && S.getLangOpts().DebuggerObjCLiteral) { | |||||
284 | // create a stub definition this NSNumber factory method. | |||||
285 | TypeSourceInfo *ReturnTInfo = nullptr; | |||||
286 | Method = | |||||
287 | ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel, | |||||
288 | S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl, | |||||
289 | /*isInstance=*/false, /*isVariadic=*/false, | |||||
290 | /*isPropertyAccessor=*/false, | |||||
291 | /*isImplicitlyDeclared=*/true, | |||||
292 | /*isDefined=*/false, ObjCMethodDecl::Required, | |||||
293 | /*HasRelatedResultType=*/false); | |||||
294 | ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method, | |||||
295 | SourceLocation(), SourceLocation(), | |||||
296 | &CX.Idents.get("value"), | |||||
297 | NumberType, /*TInfo=*/nullptr, | |||||
298 | SC_None, nullptr); | |||||
299 | Method->setMethodParams(S.Context, value, None); | |||||
300 | } | |||||
301 | ||||||
302 | if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method)) | |||||
303 | return nullptr; | |||||
304 | ||||||
305 | // Note: if the parameter type is out-of-line, we'll catch it later in the | |||||
306 | // implicit conversion. | |||||
307 | ||||||
308 | S.NSNumberLiteralMethods[*Kind] = Method; | |||||
309 | return Method; | |||||
310 | } | |||||
311 | ||||||
312 | /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the | |||||
313 | /// numeric literal expression. Type of the expression will be "NSNumber *". | |||||
314 | ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) { | |||||
315 | // Determine the type of the literal. | |||||
316 | QualType NumberType = Number->getType(); | |||||
317 | if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) { | |||||
318 | // In C, character literals have type 'int'. That's not the type we want | |||||
319 | // to use to determine the Objective-c literal kind. | |||||
320 | switch (Char->getKind()) { | |||||
321 | case CharacterLiteral::Ascii: | |||||
322 | case CharacterLiteral::UTF8: | |||||
323 | NumberType = Context.CharTy; | |||||
324 | break; | |||||
325 | ||||||
326 | case CharacterLiteral::Wide: | |||||
327 | NumberType = Context.getWideCharType(); | |||||
328 | break; | |||||
329 | ||||||
330 | case CharacterLiteral::UTF16: | |||||
331 | NumberType = Context.Char16Ty; | |||||
332 | break; | |||||
333 | ||||||
334 | case CharacterLiteral::UTF32: | |||||
335 | NumberType = Context.Char32Ty; | |||||
336 | break; | |||||
337 | } | |||||
338 | } | |||||
339 | ||||||
340 | // Look for the appropriate method within NSNumber. | |||||
341 | // Construct the literal. | |||||
342 | SourceRange NR(Number->getSourceRange()); | |||||
343 | ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType, | |||||
344 | true, NR); | |||||
345 | if (!Method) | |||||
346 | return ExprError(); | |||||
347 | ||||||
348 | // Convert the number to the type that the parameter expects. | |||||
349 | ParmVarDecl *ParamDecl = Method->parameters()[0]; | |||||
350 | InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, | |||||
351 | ParamDecl); | |||||
352 | ExprResult ConvertedNumber = PerformCopyInitialization(Entity, | |||||
353 | SourceLocation(), | |||||
354 | Number); | |||||
355 | if (ConvertedNumber.isInvalid()) | |||||
356 | return ExprError(); | |||||
357 | Number = ConvertedNumber.get(); | |||||
358 | ||||||
359 | // Use the effective source range of the literal, including the leading '@'. | |||||
360 | return MaybeBindToTemporary( | |||||
361 | new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method, | |||||
362 | SourceRange(AtLoc, NR.getEnd()))); | |||||
363 | } | |||||
364 | ||||||
365 | ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc, | |||||
366 | SourceLocation ValueLoc, | |||||
367 | bool Value) { | |||||
368 | ExprResult Inner; | |||||
369 | if (getLangOpts().CPlusPlus) { | |||||
370 | Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false); | |||||
371 | } else { | |||||
372 | // C doesn't actually have a way to represent literal values of type | |||||
373 | // _Bool. So, we'll use 0/1 and implicit cast to _Bool. | |||||
374 | Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0); | |||||
375 | Inner = ImpCastExprToType(Inner.get(), Context.BoolTy, | |||||
376 | CK_IntegralToBoolean); | |||||
377 | } | |||||
378 | ||||||
379 | return BuildObjCNumericLiteral(AtLoc, Inner.get()); | |||||
380 | } | |||||
381 | ||||||
382 | /// \brief Check that the given expression is a valid element of an Objective-C | |||||
383 | /// collection literal. | |||||
384 | static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, | |||||
385 | QualType T, | |||||
386 | bool ArrayLiteral = false) { | |||||
387 | // If the expression is type-dependent, there's nothing for us to do. | |||||
388 | if (Element->isTypeDependent()) | |||||
389 | return Element; | |||||
390 | ||||||
391 | ExprResult Result = S.CheckPlaceholderExpr(Element); | |||||
392 | if (Result.isInvalid()) | |||||
393 | return ExprError(); | |||||
394 | Element = Result.get(); | |||||
395 | ||||||
396 | // In C++, check for an implicit conversion to an Objective-C object pointer | |||||
397 | // type. | |||||
398 | if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) { | |||||
399 | InitializedEntity Entity | |||||
400 | = InitializedEntity::InitializeParameter(S.Context, T, | |||||
401 | /*Consumed=*/false); | |||||
402 | InitializationKind Kind | |||||
403 | = InitializationKind::CreateCopy(Element->getLocStart(), | |||||
404 | SourceLocation()); | |||||
405 | InitializationSequence Seq(S, Entity, Kind, Element); | |||||
406 | if (!Seq.Failed()) | |||||
407 | return Seq.Perform(S, Entity, Kind, Element); | |||||
408 | } | |||||
409 | ||||||
410 | Expr *OrigElement = Element; | |||||
411 | ||||||
412 | // Perform lvalue-to-rvalue conversion. | |||||
413 | Result = S.DefaultLvalueConversion(Element); | |||||
414 | if (Result.isInvalid()) | |||||
415 | return ExprError(); | |||||
416 | Element = Result.get(); | |||||
417 | ||||||
418 | // Make sure that we have an Objective-C pointer type or block. | |||||
419 | if (!Element->getType()->isObjCObjectPointerType() && | |||||
420 | !Element->getType()->isBlockPointerType()) { | |||||
421 | bool Recovered = false; | |||||
422 | ||||||
423 | // If this is potentially an Objective-C numeric literal, add the '@'. | |||||
424 | if (isa<IntegerLiteral>(OrigElement) || | |||||
425 | isa<CharacterLiteral>(OrigElement) || | |||||
426 | isa<FloatingLiteral>(OrigElement) || | |||||
427 | isa<ObjCBoolLiteralExpr>(OrigElement) || | |||||
428 | isa<CXXBoolLiteralExpr>(OrigElement)) { | |||||
429 | if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) { | |||||
430 | int Which = isa<CharacterLiteral>(OrigElement) ? 1 | |||||
431 | : (isa<CXXBoolLiteralExpr>(OrigElement) || | |||||
432 | isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2 | |||||
433 | : 3; | |||||
434 | ||||||
435 | S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) | |||||
436 | << Which << OrigElement->getSourceRange() | |||||
437 | << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); | |||||
438 | ||||||
439 | Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(), | |||||
440 | OrigElement); | |||||
441 | if (Result.isInvalid()) | |||||
442 | return ExprError(); | |||||
443 | ||||||
444 | Element = Result.get(); | |||||
445 | Recovered = true; | |||||
446 | } | |||||
447 | } | |||||
448 | // If this is potentially an Objective-C string literal, add the '@'. | |||||
449 | else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) { | |||||
450 | if (String->isAscii()) { | |||||
451 | S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection) | |||||
452 | << 0 << OrigElement->getSourceRange() | |||||
453 | << FixItHint::CreateInsertion(OrigElement->getLocStart(), "@"); | |||||
454 | ||||||
455 | Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String); | |||||
456 | if (Result.isInvalid()) | |||||
457 | return ExprError(); | |||||
458 | ||||||
459 | Element = Result.get(); | |||||
460 | Recovered = true; | |||||
461 | } | |||||
462 | } | |||||
463 | ||||||
464 | if (!Recovered) { | |||||
465 | S.Diag(Element->getLocStart(), diag::err_invalid_collection_element) | |||||
466 | << Element->getType(); | |||||
467 | return ExprError(); | |||||
468 | } | |||||
469 | } | |||||
470 | if (ArrayLiteral) | |||||
471 | if (ObjCStringLiteral *getString = | |||||
472 | dyn_cast<ObjCStringLiteral>(OrigElement)) { | |||||
473 | if (StringLiteral *SL = getString->getString()) { | |||||
474 | unsigned numConcat = SL->getNumConcatenated(); | |||||
475 | if (numConcat > 1) { | |||||
476 | // Only warn if the concatenated string doesn't come from a macro. | |||||
477 | bool hasMacro = false; | |||||
478 | for (unsigned i = 0; i < numConcat ; ++i) | |||||
479 | if (SL->getStrTokenLoc(i).isMacroID()) { | |||||
480 | hasMacro = true; | |||||
481 | break; | |||||
482 | } | |||||
483 | if (!hasMacro) | |||||
484 | S.Diag(Element->getLocStart(), | |||||
485 | diag::warn_concatenated_nsarray_literal) | |||||
486 | << Element->getType(); | |||||
487 | } | |||||
488 | } | |||||
489 | } | |||||
490 | ||||||
491 | // Make sure that the element has the type that the container factory | |||||
492 | // function expects. | |||||
493 | return S.PerformCopyInitialization( | |||||
494 | InitializedEntity::InitializeParameter(S.Context, T, | |||||
495 | /*Consumed=*/false), | |||||
496 | Element->getLocStart(), Element); | |||||
497 | } | |||||
498 | ||||||
499 | ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { | |||||
500 | if (ValueExpr->isTypeDependent()) { | |||||
501 | ObjCBoxedExpr *BoxedExpr = | |||||
502 | new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr, SR); | |||||
503 | return BoxedExpr; | |||||
504 | } | |||||
505 | ObjCMethodDecl *BoxingMethod = nullptr; | |||||
506 | QualType BoxedType; | |||||
507 | // Convert the expression to an RValue, so we can check for pointer types... | |||||
508 | ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr); | |||||
509 | if (RValue.isInvalid()) { | |||||
510 | return ExprError(); | |||||
511 | } | |||||
512 | SourceLocation Loc = SR.getBegin(); | |||||
513 | ValueExpr = RValue.get(); | |||||
514 | QualType ValueType(ValueExpr->getType()); | |||||
515 | if (const PointerType *PT = ValueType->getAs<PointerType>()) { | |||||
516 | QualType PointeeType = PT->getPointeeType(); | |||||
517 | if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) { | |||||
518 | ||||||
519 | if (!NSStringDecl) { | |||||
520 | NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, | |||||
521 | Sema::LK_String); | |||||
522 | if (!NSStringDecl) { | |||||
523 | return ExprError(); | |||||
524 | } | |||||
525 | QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl); | |||||
526 | NSStringPointer = Context.getObjCObjectPointerType(NSStringObject); | |||||
527 | } | |||||
528 | ||||||
529 | if (!StringWithUTF8StringMethod) { | |||||
530 | IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String"); | |||||
531 | Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II); | |||||
532 | ||||||
533 | // Look for the appropriate method within NSString. | |||||
534 | BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String); | |||||
535 | if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) { | |||||
536 | // Debugger needs to work even if NSString hasn't been defined. | |||||
537 | TypeSourceInfo *ReturnTInfo = nullptr; | |||||
538 | ObjCMethodDecl *M = ObjCMethodDecl::Create( | |||||
539 | Context, SourceLocation(), SourceLocation(), stringWithUTF8String, | |||||
540 | NSStringPointer, ReturnTInfo, NSStringDecl, | |||||
541 | /*isInstance=*/false, /*isVariadic=*/false, | |||||
542 | /*isPropertyAccessor=*/false, | |||||
543 | /*isImplicitlyDeclared=*/true, | |||||
544 | /*isDefined=*/false, ObjCMethodDecl::Required, | |||||
545 | /*HasRelatedResultType=*/false); | |||||
546 | QualType ConstCharType = Context.CharTy.withConst(); | |||||
547 | ParmVarDecl *value = | |||||
548 | ParmVarDecl::Create(Context, M, | |||||
549 | SourceLocation(), SourceLocation(), | |||||
550 | &Context.Idents.get("value"), | |||||
551 | Context.getPointerType(ConstCharType), | |||||
552 | /*TInfo=*/nullptr, | |||||
553 | SC_None, nullptr); | |||||
554 | M->setMethodParams(Context, value, None); | |||||
555 | BoxingMethod = M; | |||||
556 | } | |||||
557 | ||||||
558 | if (!validateBoxingMethod(*this, Loc, NSStringDecl, | |||||
559 | stringWithUTF8String, BoxingMethod)) | |||||
560 | return ExprError(); | |||||
561 | ||||||
562 | StringWithUTF8StringMethod = BoxingMethod; | |||||
563 | } | |||||
564 | ||||||
565 | BoxingMethod = StringWithUTF8StringMethod; | |||||
566 | BoxedType = NSStringPointer; | |||||
567 | // Transfer the nullability from method's return type. | |||||
568 | Optional<NullabilityKind> Nullability = | |||||
569 | BoxingMethod->getReturnType()->getNullability(Context); | |||||
570 | if (Nullability) | |||||
571 | BoxedType = Context.getAttributedType( | |||||
572 | AttributedType::getNullabilityAttrKind(*Nullability), BoxedType, | |||||
573 | BoxedType); | |||||
574 | } | |||||
575 | } else if (ValueType->isBuiltinType()) { | |||||
576 | // The other types we support are numeric, char and BOOL/bool. We could also | |||||
577 | // provide limited support for structure types, such as NSRange, NSRect, and | |||||
578 | // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h> | |||||
579 | // for more details. | |||||
580 | ||||||
581 | // Check for a top-level character literal. | |||||
582 | if (const CharacterLiteral *Char = | |||||
583 | dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) { | |||||
584 | // In C, character literals have type 'int'. That's not the type we want | |||||
585 | // to use to determine the Objective-c literal kind. | |||||
586 | switch (Char->getKind()) { | |||||
587 | case CharacterLiteral::Ascii: | |||||
588 | case CharacterLiteral::UTF8: | |||||
589 | ValueType = Context.CharTy; | |||||
590 | break; | |||||
591 | ||||||
592 | case CharacterLiteral::Wide: | |||||
593 | ValueType = Context.getWideCharType(); | |||||
594 | break; | |||||
595 | ||||||
596 | case CharacterLiteral::UTF16: | |||||
597 | ValueType = Context.Char16Ty; | |||||
598 | break; | |||||
599 | ||||||
600 | case CharacterLiteral::UTF32: | |||||
601 | ValueType = Context.Char32Ty; | |||||
602 | break; | |||||
603 | } | |||||
604 | } | |||||
605 | // FIXME: Do I need to do anything special with BoolTy expressions? | |||||
606 | ||||||
607 | // Look for the appropriate method within NSNumber. | |||||
608 | BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType); | |||||
609 | BoxedType = NSNumberPointer; | |||||
610 | } else if (const EnumType *ET = ValueType->getAs<EnumType>()) { | |||||
611 | if (!ET->getDecl()->isComplete()) { | |||||
612 | Diag(Loc, diag::err_objc_incomplete_boxed_expression_type) | |||||
613 | << ValueType << ValueExpr->getSourceRange(); | |||||
614 | return ExprError(); | |||||
615 | } | |||||
616 | ||||||
617 | BoxingMethod = getNSNumberFactoryMethod(*this, Loc, | |||||
618 | ET->getDecl()->getIntegerType()); | |||||
619 | BoxedType = NSNumberPointer; | |||||
620 | } else if (ValueType->isObjCBoxableRecordType()) { | |||||
621 | // Support for structure types, that marked as objc_boxable | |||||
622 | // struct __attribute__((objc_boxable)) s { ... }; | |||||
623 | ||||||
624 | // Look up the NSValue class, if we haven't done so already. It's cached | |||||
625 | // in the Sema instance. | |||||
626 | if (!NSValueDecl) { | |||||
627 | NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, | |||||
628 | Sema::LK_Boxed); | |||||
629 | if (!NSValueDecl) { | |||||
630 | return ExprError(); | |||||
631 | } | |||||
632 | ||||||
633 | // generate the pointer to NSValue type. | |||||
634 | QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl); | |||||
635 | NSValuePointer = Context.getObjCObjectPointerType(NSValueObject); | |||||
636 | } | |||||
637 | ||||||
638 | if (!ValueWithBytesObjCTypeMethod) { | |||||
639 | IdentifierInfo *II[] = { | |||||
640 | &Context.Idents.get("valueWithBytes"), | |||||
641 | &Context.Idents.get("objCType") | |||||
642 | }; | |||||
643 | Selector ValueWithBytesObjCType = Context.Selectors.getSelector(2, II); | |||||
644 | ||||||
645 | // Look for the appropriate method within NSValue. | |||||
646 | BoxingMethod = NSValueDecl->lookupClassMethod(ValueWithBytesObjCType); | |||||
647 | if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) { | |||||
648 | // Debugger needs to work even if NSValue hasn't been defined. | |||||
649 | TypeSourceInfo *ReturnTInfo = nullptr; | |||||
650 | ObjCMethodDecl *M = ObjCMethodDecl::Create( | |||||
651 | Context, | |||||
652 | SourceLocation(), | |||||
653 | SourceLocation(), | |||||
654 | ValueWithBytesObjCType, | |||||
655 | NSValuePointer, | |||||
656 | ReturnTInfo, | |||||
657 | NSValueDecl, | |||||
658 | /*isInstance=*/false, | |||||
659 | /*isVariadic=*/false, | |||||
660 | /*isPropertyAccessor=*/false, | |||||
661 | /*isImplicitlyDeclared=*/true, | |||||
662 | /*isDefined=*/false, | |||||
663 | ObjCMethodDecl::Required, | |||||
664 | /*HasRelatedResultType=*/false); | |||||
665 | ||||||
666 | SmallVector<ParmVarDecl *, 2> Params; | |||||
667 | ||||||
668 | ParmVarDecl *bytes = | |||||
669 | ParmVarDecl::Create(Context, M, | |||||
670 | SourceLocation(), SourceLocation(), | |||||
671 | &Context.Idents.get("bytes"), | |||||
672 | Context.VoidPtrTy.withConst(), | |||||
673 | /*TInfo=*/nullptr, | |||||
674 | SC_None, nullptr); | |||||
675 | Params.push_back(bytes); | |||||
676 | ||||||
677 | QualType ConstCharType = Context.CharTy.withConst(); | |||||
678 | ParmVarDecl *type = | |||||
679 | ParmVarDecl::Create(Context, M, | |||||
680 | SourceLocation(), SourceLocation(), | |||||
681 | &Context.Idents.get("type"), | |||||
682 | Context.getPointerType(ConstCharType), | |||||
683 | /*TInfo=*/nullptr, | |||||
684 | SC_None, nullptr); | |||||
685 | Params.push_back(type); | |||||
686 | ||||||
687 | M->setMethodParams(Context, Params, None); | |||||
688 | BoxingMethod = M; | |||||
689 | } | |||||
690 | ||||||
691 | if (!validateBoxingMethod(*this, Loc, NSValueDecl, | |||||
692 | ValueWithBytesObjCType, BoxingMethod)) | |||||
693 | return ExprError(); | |||||
694 | ||||||
695 | ValueWithBytesObjCTypeMethod = BoxingMethod; | |||||
696 | } | |||||
697 | ||||||
698 | if (!ValueType.isTriviallyCopyableType(Context)) { | |||||
699 | Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type) | |||||
700 | << ValueType << ValueExpr->getSourceRange(); | |||||
701 | return ExprError(); | |||||
702 | } | |||||
703 | ||||||
704 | BoxingMethod = ValueWithBytesObjCTypeMethod; | |||||
705 | BoxedType = NSValuePointer; | |||||
706 | } | |||||
707 | ||||||
708 | if (!BoxingMethod) { | |||||
709 | Diag(Loc, diag::err_objc_illegal_boxed_expression_type) | |||||
710 | << ValueType << ValueExpr->getSourceRange(); | |||||
711 | return ExprError(); | |||||
712 | } | |||||
713 | ||||||
714 | DiagnoseUseOfDecl(BoxingMethod, Loc); | |||||
715 | ||||||
716 | ExprResult ConvertedValueExpr; | |||||
717 | if (ValueType->isObjCBoxableRecordType()) { | |||||
718 | InitializedEntity IE = InitializedEntity::InitializeTemporary(ValueType); | |||||
719 | ConvertedValueExpr = PerformCopyInitialization(IE, ValueExpr->getExprLoc(), | |||||
720 | ValueExpr); | |||||
721 | } else { | |||||
722 | // Convert the expression to the type that the parameter requires. | |||||
723 | ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0]; | |||||
724 | InitializedEntity IE = InitializedEntity::InitializeParameter(Context, | |||||
725 | ParamDecl); | |||||
726 | ConvertedValueExpr = PerformCopyInitialization(IE, SourceLocation(), | |||||
727 | ValueExpr); | |||||
728 | } | |||||
729 | ||||||
730 | if (ConvertedValueExpr.isInvalid()) | |||||
731 | return ExprError(); | |||||
732 | ValueExpr = ConvertedValueExpr.get(); | |||||
733 | ||||||
734 | ObjCBoxedExpr *BoxedExpr = | |||||
735 | new (Context) ObjCBoxedExpr(ValueExpr, BoxedType, | |||||
736 | BoxingMethod, SR); | |||||
737 | return MaybeBindToTemporary(BoxedExpr); | |||||
738 | } | |||||
739 | ||||||
740 | /// Build an ObjC subscript pseudo-object expression, given that | |||||
741 | /// that's supported by the runtime. | |||||
742 | ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, | |||||
743 | Expr *IndexExpr, | |||||
744 | ObjCMethodDecl *getterMethod, | |||||
745 | ObjCMethodDecl *setterMethod) { | |||||
746 | assert(!LangOpts.isSubscriptPointerArithmetic())(static_cast <bool> (!LangOpts.isSubscriptPointerArithmetic ()) ? void (0) : __assert_fail ("!LangOpts.isSubscriptPointerArithmetic()" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 746, __extension__ __PRETTY_FUNCTION__)); | |||||
747 | ||||||
748 | // We can't get dependent types here; our callers should have | |||||
749 | // filtered them out. | |||||
750 | assert((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&(static_cast <bool> ((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) && "base or index cannot have dependent type here" ) ? void (0) : __assert_fail ("(!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) && \"base or index cannot have dependent type here\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 751, __extension__ __PRETTY_FUNCTION__)) | |||||
751 | "base or index cannot have dependent type here")(static_cast <bool> ((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) && "base or index cannot have dependent type here" ) ? void (0) : __assert_fail ("(!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) && \"base or index cannot have dependent type here\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 751, __extension__ __PRETTY_FUNCTION__)); | |||||
752 | ||||||
753 | // Filter out placeholders in the index. In theory, overloads could | |||||
754 | // be preserved here, although that might not actually work correctly. | |||||
755 | ExprResult Result = CheckPlaceholderExpr(IndexExpr); | |||||
756 | if (Result.isInvalid()) | |||||
757 | return ExprError(); | |||||
758 | IndexExpr = Result.get(); | |||||
759 | ||||||
760 | // Perform lvalue-to-rvalue conversion on the base. | |||||
761 | Result = DefaultLvalueConversion(BaseExpr); | |||||
762 | if (Result.isInvalid()) | |||||
763 | return ExprError(); | |||||
764 | BaseExpr = Result.get(); | |||||
765 | ||||||
766 | // Build the pseudo-object expression. | |||||
767 | return new (Context) ObjCSubscriptRefExpr( | |||||
768 | BaseExpr, IndexExpr, Context.PseudoObjectTy, VK_LValue, OK_ObjCSubscript, | |||||
769 | getterMethod, setterMethod, RB); | |||||
770 | } | |||||
771 | ||||||
772 | ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { | |||||
773 | SourceLocation Loc = SR.getBegin(); | |||||
774 | ||||||
775 | if (!NSArrayDecl) { | |||||
776 | NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, | |||||
777 | Sema::LK_Array); | |||||
778 | if (!NSArrayDecl) { | |||||
779 | return ExprError(); | |||||
780 | } | |||||
781 | } | |||||
782 | ||||||
783 | // Find the arrayWithObjects:count: method, if we haven't done so already. | |||||
784 | QualType IdT = Context.getObjCIdType(); | |||||
785 | if (!ArrayWithObjectsMethod) { | |||||
786 | Selector | |||||
787 | Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount); | |||||
788 | ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel); | |||||
789 | if (!Method && getLangOpts().DebuggerObjCLiteral) { | |||||
790 | TypeSourceInfo *ReturnTInfo = nullptr; | |||||
791 | Method = ObjCMethodDecl::Create( | |||||
792 | Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo, | |||||
793 | Context.getTranslationUnitDecl(), false /*Instance*/, | |||||
794 | false /*isVariadic*/, | |||||
795 | /*isPropertyAccessor=*/false, | |||||
796 | /*isImplicitlyDeclared=*/true, /*isDefined=*/false, | |||||
797 | ObjCMethodDecl::Required, false); | |||||
798 | SmallVector<ParmVarDecl *, 2> Params; | |||||
799 | ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, | |||||
800 | SourceLocation(), | |||||
801 | SourceLocation(), | |||||
802 | &Context.Idents.get("objects"), | |||||
803 | Context.getPointerType(IdT), | |||||
804 | /*TInfo=*/nullptr, | |||||
805 | SC_None, nullptr); | |||||
806 | Params.push_back(objects); | |||||
807 | ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, | |||||
808 | SourceLocation(), | |||||
809 | SourceLocation(), | |||||
810 | &Context.Idents.get("cnt"), | |||||
811 | Context.UnsignedLongTy, | |||||
812 | /*TInfo=*/nullptr, SC_None, | |||||
813 | nullptr); | |||||
814 | Params.push_back(cnt); | |||||
815 | Method->setMethodParams(Context, Params, None); | |||||
816 | } | |||||
817 | ||||||
818 | if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method)) | |||||
819 | return ExprError(); | |||||
820 | ||||||
821 | // Dig out the type that all elements should be converted to. | |||||
822 | QualType T = Method->parameters()[0]->getType(); | |||||
823 | const PointerType *PtrT = T->getAs<PointerType>(); | |||||
824 | if (!PtrT || | |||||
825 | !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) { | |||||
826 | Diag(SR.getBegin(), diag::err_objc_literal_method_sig) | |||||
827 | << Sel; | |||||
828 | Diag(Method->parameters()[0]->getLocation(), | |||||
829 | diag::note_objc_literal_method_param) | |||||
830 | << 0 << T | |||||
831 | << Context.getPointerType(IdT.withConst()); | |||||
832 | return ExprError(); | |||||
833 | } | |||||
834 | ||||||
835 | // Check that the 'count' parameter is integral. | |||||
836 | if (!Method->parameters()[1]->getType()->isIntegerType()) { | |||||
837 | Diag(SR.getBegin(), diag::err_objc_literal_method_sig) | |||||
838 | << Sel; | |||||
839 | Diag(Method->parameters()[1]->getLocation(), | |||||
840 | diag::note_objc_literal_method_param) | |||||
841 | << 1 | |||||
842 | << Method->parameters()[1]->getType() | |||||
843 | << "integral"; | |||||
844 | return ExprError(); | |||||
845 | } | |||||
846 | ||||||
847 | // We've found a good +arrayWithObjects:count: method. Save it! | |||||
848 | ArrayWithObjectsMethod = Method; | |||||
849 | } | |||||
850 | ||||||
851 | QualType ObjectsType = ArrayWithObjectsMethod->parameters()[0]->getType(); | |||||
852 | QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType(); | |||||
853 | ||||||
854 | // Check that each of the elements provided is valid in a collection literal, | |||||
855 | // performing conversions as necessary. | |||||
856 | Expr **ElementsBuffer = Elements.data(); | |||||
857 | for (unsigned I = 0, N = Elements.size(); I != N; ++I) { | |||||
858 | ExprResult Converted = CheckObjCCollectionLiteralElement(*this, | |||||
859 | ElementsBuffer[I], | |||||
860 | RequiredType, true); | |||||
861 | if (Converted.isInvalid()) | |||||
862 | return ExprError(); | |||||
863 | ||||||
864 | ElementsBuffer[I] = Converted.get(); | |||||
865 | } | |||||
866 | ||||||
867 | QualType Ty | |||||
868 | = Context.getObjCObjectPointerType( | |||||
869 | Context.getObjCInterfaceType(NSArrayDecl)); | |||||
870 | ||||||
871 | return MaybeBindToTemporary( | |||||
872 | ObjCArrayLiteral::Create(Context, Elements, Ty, | |||||
873 | ArrayWithObjectsMethod, SR)); | |||||
874 | } | |||||
875 | ||||||
876 | ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, | |||||
877 | MutableArrayRef<ObjCDictionaryElement> Elements) { | |||||
878 | SourceLocation Loc = SR.getBegin(); | |||||
879 | ||||||
880 | if (!NSDictionaryDecl) { | |||||
881 | NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc, | |||||
882 | Sema::LK_Dictionary); | |||||
883 | if (!NSDictionaryDecl) { | |||||
884 | return ExprError(); | |||||
885 | } | |||||
886 | } | |||||
887 | ||||||
888 | // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done | |||||
889 | // so already. | |||||
890 | QualType IdT = Context.getObjCIdType(); | |||||
891 | if (!DictionaryWithObjectsMethod) { | |||||
892 | Selector Sel = NSAPIObj->getNSDictionarySelector( | |||||
893 | NSAPI::NSDict_dictionaryWithObjectsForKeysCount); | |||||
894 | ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel); | |||||
895 | if (!Method && getLangOpts().DebuggerObjCLiteral) { | |||||
896 | Method = ObjCMethodDecl::Create(Context, | |||||
897 | SourceLocation(), SourceLocation(), Sel, | |||||
898 | IdT, | |||||
899 | nullptr /*TypeSourceInfo */, | |||||
900 | Context.getTranslationUnitDecl(), | |||||
901 | false /*Instance*/, false/*isVariadic*/, | |||||
902 | /*isPropertyAccessor=*/false, | |||||
903 | /*isImplicitlyDeclared=*/true, /*isDefined=*/false, | |||||
904 | ObjCMethodDecl::Required, | |||||
905 | false); | |||||
906 | SmallVector<ParmVarDecl *, 3> Params; | |||||
907 | ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, | |||||
908 | SourceLocation(), | |||||
909 | SourceLocation(), | |||||
910 | &Context.Idents.get("objects"), | |||||
911 | Context.getPointerType(IdT), | |||||
912 | /*TInfo=*/nullptr, SC_None, | |||||
913 | nullptr); | |||||
914 | Params.push_back(objects); | |||||
915 | ParmVarDecl *keys = ParmVarDecl::Create(Context, Method, | |||||
916 | SourceLocation(), | |||||
917 | SourceLocation(), | |||||
918 | &Context.Idents.get("keys"), | |||||
919 | Context.getPointerType(IdT), | |||||
920 | /*TInfo=*/nullptr, SC_None, | |||||
921 | nullptr); | |||||
922 | Params.push_back(keys); | |||||
923 | ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, | |||||
924 | SourceLocation(), | |||||
925 | SourceLocation(), | |||||
926 | &Context.Idents.get("cnt"), | |||||
927 | Context.UnsignedLongTy, | |||||
928 | /*TInfo=*/nullptr, SC_None, | |||||
929 | nullptr); | |||||
930 | Params.push_back(cnt); | |||||
931 | Method->setMethodParams(Context, Params, None); | |||||
932 | } | |||||
933 | ||||||
934 | if (!validateBoxingMethod(*this, SR.getBegin(), NSDictionaryDecl, Sel, | |||||
935 | Method)) | |||||
936 | return ExprError(); | |||||
937 | ||||||
938 | // Dig out the type that all values should be converted to. | |||||
939 | QualType ValueT = Method->parameters()[0]->getType(); | |||||
940 | const PointerType *PtrValue = ValueT->getAs<PointerType>(); | |||||
941 | if (!PtrValue || | |||||
942 | !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) { | |||||
943 | Diag(SR.getBegin(), diag::err_objc_literal_method_sig) | |||||
944 | << Sel; | |||||
945 | Diag(Method->parameters()[0]->getLocation(), | |||||
946 | diag::note_objc_literal_method_param) | |||||
947 | << 0 << ValueT | |||||
948 | << Context.getPointerType(IdT.withConst()); | |||||
949 | return ExprError(); | |||||
950 | } | |||||
951 | ||||||
952 | // Dig out the type that all keys should be converted to. | |||||
953 | QualType KeyT = Method->parameters()[1]->getType(); | |||||
954 | const PointerType *PtrKey = KeyT->getAs<PointerType>(); | |||||
955 | if (!PtrKey || | |||||
956 | !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), | |||||
957 | IdT)) { | |||||
958 | bool err = true; | |||||
959 | if (PtrKey) { | |||||
960 | if (QIDNSCopying.isNull()) { | |||||
961 | // key argument of selector is id<NSCopying>? | |||||
962 | if (ObjCProtocolDecl *NSCopyingPDecl = | |||||
963 | LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) { | |||||
964 | ObjCProtocolDecl *PQ[] = {NSCopyingPDecl}; | |||||
965 | QIDNSCopying = | |||||
966 | Context.getObjCObjectType(Context.ObjCBuiltinIdTy, { }, | |||||
967 | llvm::makeArrayRef( | |||||
968 | (ObjCProtocolDecl**) PQ, | |||||
969 | 1), | |||||
970 | false); | |||||
971 | QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying); | |||||
972 | } | |||||
973 | } | |||||
974 | if (!QIDNSCopying.isNull()) | |||||
975 | err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(), | |||||
976 | QIDNSCopying); | |||||
977 | } | |||||
978 | ||||||
979 | if (err) { | |||||
980 | Diag(SR.getBegin(), diag::err_objc_literal_method_sig) | |||||
981 | << Sel; | |||||
982 | Diag(Method->parameters()[1]->getLocation(), | |||||
983 | diag::note_objc_literal_method_param) | |||||
984 | << 1 << KeyT | |||||
985 | << Context.getPointerType(IdT.withConst()); | |||||
986 | return ExprError(); | |||||
987 | } | |||||
988 | } | |||||
989 | ||||||
990 | // Check that the 'count' parameter is integral. | |||||
991 | QualType CountType = Method->parameters()[2]->getType(); | |||||
992 | if (!CountType->isIntegerType()) { | |||||
993 | Diag(SR.getBegin(), diag::err_objc_literal_method_sig) | |||||
994 | << Sel; | |||||
995 | Diag(Method->parameters()[2]->getLocation(), | |||||
996 | diag::note_objc_literal_method_param) | |||||
997 | << 2 << CountType | |||||
998 | << "integral"; | |||||
999 | return ExprError(); | |||||
1000 | } | |||||
1001 | ||||||
1002 | // We've found a good +dictionaryWithObjects:keys:count: method; save it! | |||||
1003 | DictionaryWithObjectsMethod = Method; | |||||
1004 | } | |||||
1005 | ||||||
1006 | QualType ValuesT = DictionaryWithObjectsMethod->parameters()[0]->getType(); | |||||
1007 | QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType(); | |||||
1008 | QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType(); | |||||
1009 | QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType(); | |||||
1010 | ||||||
1011 | // Check that each of the keys and values provided is valid in a collection | |||||
1012 | // literal, performing conversions as necessary. | |||||
1013 | bool HasPackExpansions = false; | |||||
1014 | for (ObjCDictionaryElement &Element : Elements) { | |||||
1015 | // Check the key. | |||||
1016 | ExprResult Key = CheckObjCCollectionLiteralElement(*this, Element.Key, | |||||
1017 | KeyT); | |||||
1018 | if (Key.isInvalid()) | |||||
1019 | return ExprError(); | |||||
1020 | ||||||
1021 | // Check the value. | |||||
1022 | ExprResult Value | |||||
1023 | = CheckObjCCollectionLiteralElement(*this, Element.Value, ValueT); | |||||
1024 | if (Value.isInvalid()) | |||||
1025 | return ExprError(); | |||||
1026 | ||||||
1027 | Element.Key = Key.get(); | |||||
1028 | Element.Value = Value.get(); | |||||
1029 | ||||||
1030 | if (Element.EllipsisLoc.isInvalid()) | |||||
1031 | continue; | |||||
1032 | ||||||
1033 | if (!Element.Key->containsUnexpandedParameterPack() && | |||||
1034 | !Element.Value->containsUnexpandedParameterPack()) { | |||||
1035 | Diag(Element.EllipsisLoc, | |||||
1036 | diag::err_pack_expansion_without_parameter_packs) | |||||
1037 | << SourceRange(Element.Key->getLocStart(), | |||||
1038 | Element.Value->getLocEnd()); | |||||
1039 | return ExprError(); | |||||
1040 | } | |||||
1041 | ||||||
1042 | HasPackExpansions = true; | |||||
1043 | } | |||||
1044 | ||||||
1045 | QualType Ty | |||||
1046 | = Context.getObjCObjectPointerType( | |||||
1047 | Context.getObjCInterfaceType(NSDictionaryDecl)); | |||||
1048 | return MaybeBindToTemporary(ObjCDictionaryLiteral::Create( | |||||
1049 | Context, Elements, HasPackExpansions, Ty, | |||||
1050 | DictionaryWithObjectsMethod, SR)); | |||||
1051 | } | |||||
1052 | ||||||
1053 | ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, | |||||
1054 | TypeSourceInfo *EncodedTypeInfo, | |||||
1055 | SourceLocation RParenLoc) { | |||||
1056 | QualType EncodedType = EncodedTypeInfo->getType(); | |||||
1057 | QualType StrTy; | |||||
1058 | if (EncodedType->isDependentType()) | |||||
1059 | StrTy = Context.DependentTy; | |||||
1060 | else { | |||||
1061 | if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled. | |||||
1062 | !EncodedType->isVoidType()) // void is handled too. | |||||
1063 | if (RequireCompleteType(AtLoc, EncodedType, | |||||
1064 | diag::err_incomplete_type_objc_at_encode, | |||||
1065 | EncodedTypeInfo->getTypeLoc())) | |||||
1066 | return ExprError(); | |||||
1067 | ||||||
1068 | std::string Str; | |||||
1069 | QualType NotEncodedT; | |||||
1070 | Context.getObjCEncodingForType(EncodedType, Str, nullptr, &NotEncodedT); | |||||
1071 | if (!NotEncodedT.isNull()) | |||||
1072 | Diag(AtLoc, diag::warn_incomplete_encoded_type) | |||||
1073 | << EncodedType << NotEncodedT; | |||||
1074 | ||||||
1075 | // The type of @encode is the same as the type of the corresponding string, | |||||
1076 | // which is an array type. | |||||
1077 | StrTy = Context.CharTy; | |||||
1078 | // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). | |||||
1079 | if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) | |||||
1080 | StrTy.addConst(); | |||||
1081 | StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1), | |||||
1082 | ArrayType::Normal, 0); | |||||
1083 | } | |||||
1084 | ||||||
1085 | return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc); | |||||
1086 | } | |||||
1087 | ||||||
1088 | ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, | |||||
1089 | SourceLocation EncodeLoc, | |||||
1090 | SourceLocation LParenLoc, | |||||
1091 | ParsedType ty, | |||||
1092 | SourceLocation RParenLoc) { | |||||
1093 | // FIXME: Preserve type source info ? | |||||
1094 | TypeSourceInfo *TInfo; | |||||
1095 | QualType EncodedType = GetTypeFromParser(ty, &TInfo); | |||||
1096 | if (!TInfo) | |||||
1097 | TInfo = Context.getTrivialTypeSourceInfo(EncodedType, | |||||
1098 | getLocForEndOfToken(LParenLoc)); | |||||
1099 | ||||||
1100 | return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); | |||||
1101 | } | |||||
1102 | ||||||
1103 | static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S, | |||||
1104 | SourceLocation AtLoc, | |||||
1105 | SourceLocation LParenLoc, | |||||
1106 | SourceLocation RParenLoc, | |||||
1107 | ObjCMethodDecl *Method, | |||||
1108 | ObjCMethodList &MethList) { | |||||
1109 | ObjCMethodList *M = &MethList; | |||||
1110 | bool Warned = false; | |||||
1111 | for (M = M->getNext(); M; M=M->getNext()) { | |||||
1112 | ObjCMethodDecl *MatchingMethodDecl = M->getMethod(); | |||||
1113 | if (MatchingMethodDecl == Method || | |||||
1114 | isa<ObjCImplDecl>(MatchingMethodDecl->getDeclContext()) || | |||||
1115 | MatchingMethodDecl->getSelector() != Method->getSelector()) | |||||
1116 | continue; | |||||
1117 | if (!S.MatchTwoMethodDeclarations(Method, | |||||
1118 | MatchingMethodDecl, Sema::MMS_loose)) { | |||||
1119 | if (!Warned) { | |||||
1120 | Warned = true; | |||||
1121 | S.Diag(AtLoc, diag::warn_multiple_selectors) | |||||
1122 | << Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(") | |||||
1123 | << FixItHint::CreateInsertion(RParenLoc, ")"); | |||||
1124 | S.Diag(Method->getLocation(), diag::note_method_declared_at) | |||||
1125 | << Method->getDeclName(); | |||||
1126 | } | |||||
1127 | S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at) | |||||
1128 | << MatchingMethodDecl->getDeclName(); | |||||
1129 | } | |||||
1130 | } | |||||
1131 | return Warned; | |||||
1132 | } | |||||
1133 | ||||||
1134 | static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc, | |||||
1135 | ObjCMethodDecl *Method, | |||||
1136 | SourceLocation LParenLoc, | |||||
1137 | SourceLocation RParenLoc, | |||||
1138 | bool WarnMultipleSelectors) { | |||||
1139 | if (!WarnMultipleSelectors || | |||||
1140 | S.Diags.isIgnored(diag::warn_multiple_selectors, SourceLocation())) | |||||
1141 | return; | |||||
1142 | bool Warned = false; | |||||
1143 | for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(), | |||||
1144 | e = S.MethodPool.end(); b != e; b++) { | |||||
1145 | // first, instance methods | |||||
1146 | ObjCMethodList &InstMethList = b->second.first; | |||||
1147 | if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc, | |||||
1148 | Method, InstMethList)) | |||||
1149 | Warned = true; | |||||
1150 | ||||||
1151 | // second, class methods | |||||
1152 | ObjCMethodList &ClsMethList = b->second.second; | |||||
1153 | if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc, | |||||
1154 | Method, ClsMethList) || Warned) | |||||
1155 | return; | |||||
1156 | } | |||||
1157 | } | |||||
1158 | ||||||
1159 | ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, | |||||
1160 | SourceLocation AtLoc, | |||||
1161 | SourceLocation SelLoc, | |||||
1162 | SourceLocation LParenLoc, | |||||
1163 | SourceLocation RParenLoc, | |||||
1164 | bool WarnMultipleSelectors) { | |||||
1165 | ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, | |||||
1166 | SourceRange(LParenLoc, RParenLoc)); | |||||
1167 | if (!Method) | |||||
1168 | Method = LookupFactoryMethodInGlobalPool(Sel, | |||||
1169 | SourceRange(LParenLoc, RParenLoc)); | |||||
1170 | if (!Method) { | |||||
1171 | if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) { | |||||
1172 | Selector MatchedSel = OM->getSelector(); | |||||
1173 | SourceRange SelectorRange(LParenLoc.getLocWithOffset(1), | |||||
1174 | RParenLoc.getLocWithOffset(-1)); | |||||
1175 | Diag(SelLoc, diag::warn_undeclared_selector_with_typo) | |||||
1176 | << Sel << MatchedSel | |||||
1177 | << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString()); | |||||
1178 | ||||||
1179 | } else | |||||
1180 | Diag(SelLoc, diag::warn_undeclared_selector) << Sel; | |||||
1181 | } else | |||||
1182 | DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc, | |||||
1183 | WarnMultipleSelectors); | |||||
1184 | ||||||
1185 | if (Method && | |||||
1186 | Method->getImplementationControl() != ObjCMethodDecl::Optional && | |||||
1187 | !getSourceManager().isInSystemHeader(Method->getLocation())) | |||||
1188 | ReferencedSelectors.insert(std::make_pair(Sel, AtLoc)); | |||||
1189 | ||||||
1190 | // In ARC, forbid the user from using @selector for | |||||
1191 | // retain/release/autorelease/dealloc/retainCount. | |||||
1192 | if (getLangOpts().ObjCAutoRefCount) { | |||||
1193 | switch (Sel.getMethodFamily()) { | |||||
1194 | case OMF_retain: | |||||
1195 | case OMF_release: | |||||
1196 | case OMF_autorelease: | |||||
1197 | case OMF_retainCount: | |||||
1198 | case OMF_dealloc: | |||||
1199 | Diag(AtLoc, diag::err_arc_illegal_selector) << | |||||
1200 | Sel << SourceRange(LParenLoc, RParenLoc); | |||||
1201 | break; | |||||
1202 | ||||||
1203 | case OMF_None: | |||||
1204 | case OMF_alloc: | |||||
1205 | case OMF_copy: | |||||
1206 | case OMF_finalize: | |||||
1207 | case OMF_init: | |||||
1208 | case OMF_mutableCopy: | |||||
1209 | case OMF_new: | |||||
1210 | case OMF_self: | |||||
1211 | case OMF_initialize: | |||||
1212 | case OMF_performSelector: | |||||
1213 | break; | |||||
1214 | } | |||||
1215 | } | |||||
1216 | QualType Ty = Context.getObjCSelType(); | |||||
1217 | return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); | |||||
1218 | } | |||||
1219 | ||||||
1220 | ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, | |||||
1221 | SourceLocation AtLoc, | |||||
1222 | SourceLocation ProtoLoc, | |||||
1223 | SourceLocation LParenLoc, | |||||
1224 | SourceLocation ProtoIdLoc, | |||||
1225 | SourceLocation RParenLoc) { | |||||
1226 | ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc); | |||||
1227 | if (!PDecl) { | |||||
1228 | Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; | |||||
1229 | return true; | |||||
1230 | } | |||||
1231 | if (PDecl->hasDefinition()) | |||||
1232 | PDecl = PDecl->getDefinition(); | |||||
1233 | ||||||
1234 | QualType Ty = Context.getObjCProtoType(); | |||||
1235 | if (Ty.isNull()) | |||||
1236 | return true; | |||||
1237 | Ty = Context.getObjCObjectPointerType(Ty); | |||||
1238 | return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc); | |||||
1239 | } | |||||
1240 | ||||||
1241 | /// Try to capture an implicit reference to 'self'. | |||||
1242 | ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) { | |||||
1243 | DeclContext *DC = getFunctionLevelDeclContext(); | |||||
1244 | ||||||
1245 | // If we're not in an ObjC method, error out. Note that, unlike the | |||||
1246 | // C++ case, we don't require an instance method --- class methods | |||||
1247 | // still have a 'self', and we really do still need to capture it! | |||||
1248 | ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC); | |||||
1249 | if (!method) | |||||
1250 | return nullptr; | |||||
1251 | ||||||
1252 | tryCaptureVariable(method->getSelfDecl(), Loc); | |||||
1253 | ||||||
1254 | return method; | |||||
1255 | } | |||||
1256 | ||||||
1257 | static QualType stripObjCInstanceType(ASTContext &Context, QualType T) { | |||||
1258 | QualType origType = T; | |||||
1259 | if (auto nullability = AttributedType::stripOuterNullability(T)) { | |||||
1260 | if (T == Context.getObjCInstanceType()) { | |||||
1261 | return Context.getAttributedType( | |||||
1262 | AttributedType::getNullabilityAttrKind(*nullability), | |||||
1263 | Context.getObjCIdType(), | |||||
1264 | Context.getObjCIdType()); | |||||
1265 | } | |||||
1266 | ||||||
1267 | return origType; | |||||
1268 | } | |||||
1269 | ||||||
1270 | if (T == Context.getObjCInstanceType()) | |||||
1271 | return Context.getObjCIdType(); | |||||
1272 | ||||||
1273 | return origType; | |||||
1274 | } | |||||
1275 | ||||||
1276 | /// Determine the result type of a message send based on the receiver type, | |||||
1277 | /// method, and the kind of message send. | |||||
1278 | /// | |||||
1279 | /// This is the "base" result type, which will still need to be adjusted | |||||
1280 | /// to account for nullability. | |||||
1281 | static QualType getBaseMessageSendResultType(Sema &S, | |||||
1282 | QualType ReceiverType, | |||||
1283 | ObjCMethodDecl *Method, | |||||
1284 | bool isClassMessage, | |||||
1285 | bool isSuperMessage) { | |||||
1286 | assert(Method && "Must have a method")(static_cast <bool> (Method && "Must have a method" ) ? void (0) : __assert_fail ("Method && \"Must have a method\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 1286, __extension__ __PRETTY_FUNCTION__)); | |||||
1287 | if (!Method->hasRelatedResultType()) | |||||
1288 | return Method->getSendResultType(ReceiverType); | |||||
1289 | ||||||
1290 | ASTContext &Context = S.Context; | |||||
1291 | ||||||
1292 | // Local function that transfers the nullability of the method's | |||||
1293 | // result type to the returned result. | |||||
1294 | auto transferNullability = [&](QualType type) -> QualType { | |||||
1295 | // If the method's result type has nullability, extract it. | |||||
1296 | if (auto nullability = Method->getSendResultType(ReceiverType) | |||||
1297 | ->getNullability(Context)){ | |||||
1298 | // Strip off any outer nullability sugar from the provided type. | |||||
1299 | (void)AttributedType::stripOuterNullability(type); | |||||
1300 | ||||||
1301 | // Form a new attributed type using the method result type's nullability. | |||||
1302 | return Context.getAttributedType( | |||||
1303 | AttributedType::getNullabilityAttrKind(*nullability), | |||||
1304 | type, | |||||
1305 | type); | |||||
1306 | } | |||||
1307 | ||||||
1308 | return type; | |||||
1309 | }; | |||||
1310 | ||||||
1311 | // If a method has a related return type: | |||||
1312 | // - if the method found is an instance method, but the message send | |||||
1313 | // was a class message send, T is the declared return type of the method | |||||
1314 | // found | |||||
1315 | if (Method->isInstanceMethod() && isClassMessage) | |||||
1316 | return stripObjCInstanceType(Context, | |||||
1317 | Method->getSendResultType(ReceiverType)); | |||||
1318 | ||||||
1319 | // - if the receiver is super, T is a pointer to the class of the | |||||
1320 | // enclosing method definition | |||||
1321 | if (isSuperMessage) { | |||||
1322 | if (ObjCMethodDecl *CurMethod = S.getCurMethodDecl()) | |||||
1323 | if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) { | |||||
1324 | return transferNullability( | |||||
1325 | Context.getObjCObjectPointerType( | |||||
1326 | Context.getObjCInterfaceType(Class))); | |||||
1327 | } | |||||
1328 | } | |||||
1329 | ||||||
1330 | // - if the receiver is the name of a class U, T is a pointer to U | |||||
1331 | if (ReceiverType->getAsObjCInterfaceType()) | |||||
1332 | return transferNullability(Context.getObjCObjectPointerType(ReceiverType)); | |||||
1333 | // - if the receiver is of type Class or qualified Class type, | |||||
1334 | // T is the declared return type of the method. | |||||
1335 | if (ReceiverType->isObjCClassType() || | |||||
1336 | ReceiverType->isObjCQualifiedClassType()) | |||||
1337 | return stripObjCInstanceType(Context, | |||||
1338 | Method->getSendResultType(ReceiverType)); | |||||
1339 | ||||||
1340 | // - if the receiver is id, qualified id, Class, or qualified Class, T | |||||
1341 | // is the receiver type, otherwise | |||||
1342 | // - T is the type of the receiver expression. | |||||
1343 | return transferNullability(ReceiverType); | |||||
1344 | } | |||||
1345 | ||||||
1346 | QualType Sema::getMessageSendResultType(QualType ReceiverType, | |||||
1347 | ObjCMethodDecl *Method, | |||||
1348 | bool isClassMessage, | |||||
1349 | bool isSuperMessage) { | |||||
1350 | // Produce the result type. | |||||
1351 | QualType resultType = getBaseMessageSendResultType(*this, ReceiverType, | |||||
1352 | Method, | |||||
1353 | isClassMessage, | |||||
1354 | isSuperMessage); | |||||
1355 | ||||||
1356 | // If this is a class message, ignore the nullability of the receiver. | |||||
1357 | if (isClassMessage) | |||||
1358 | return resultType; | |||||
1359 | ||||||
1360 | // Map the nullability of the result into a table index. | |||||
1361 | unsigned receiverNullabilityIdx = 0; | |||||
1362 | if (auto nullability = ReceiverType->getNullability(Context)) | |||||
1363 | receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability); | |||||
1364 | ||||||
1365 | unsigned resultNullabilityIdx = 0; | |||||
1366 | if (auto nullability = resultType->getNullability(Context)) | |||||
1367 | resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability); | |||||
1368 | ||||||
1369 | // The table of nullability mappings, indexed by the receiver's nullability | |||||
1370 | // and then the result type's nullability. | |||||
1371 | static const uint8_t None = 0; | |||||
1372 | static const uint8_t NonNull = 1; | |||||
1373 | static const uint8_t Nullable = 2; | |||||
1374 | static const uint8_t Unspecified = 3; | |||||
1375 | static const uint8_t nullabilityMap[4][4] = { | |||||
1376 | // None NonNull Nullable Unspecified | |||||
1377 | /* None */ { None, None, Nullable, None }, | |||||
1378 | /* NonNull */ { None, NonNull, Nullable, Unspecified }, | |||||
1379 | /* Nullable */ { Nullable, Nullable, Nullable, Nullable }, | |||||
1380 | /* Unspecified */ { None, Unspecified, Nullable, Unspecified } | |||||
1381 | }; | |||||
1382 | ||||||
1383 | unsigned newResultNullabilityIdx | |||||
1384 | = nullabilityMap[receiverNullabilityIdx][resultNullabilityIdx]; | |||||
1385 | if (newResultNullabilityIdx == resultNullabilityIdx) | |||||
1386 | return resultType; | |||||
1387 | ||||||
1388 | // Strip off the existing nullability. This removes as little type sugar as | |||||
1389 | // possible. | |||||
1390 | do { | |||||
1391 | if (auto attributed = dyn_cast<AttributedType>(resultType.getTypePtr())) { | |||||
1392 | resultType = attributed->getModifiedType(); | |||||
1393 | } else { | |||||
1394 | resultType = resultType.getDesugaredType(Context); | |||||
1395 | } | |||||
1396 | } while (resultType->getNullability(Context)); | |||||
1397 | ||||||
1398 | // Add nullability back if needed. | |||||
1399 | if (newResultNullabilityIdx > 0) { | |||||
1400 | auto newNullability | |||||
1401 | = static_cast<NullabilityKind>(newResultNullabilityIdx-1); | |||||
1402 | return Context.getAttributedType( | |||||
1403 | AttributedType::getNullabilityAttrKind(newNullability), | |||||
1404 | resultType, resultType); | |||||
1405 | } | |||||
1406 | ||||||
1407 | return resultType; | |||||
1408 | } | |||||
1409 | ||||||
1410 | /// Look for an ObjC method whose result type exactly matches the given type. | |||||
1411 | static const ObjCMethodDecl * | |||||
1412 | findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD, | |||||
1413 | QualType instancetype) { | |||||
1414 | if (MD->getReturnType() == instancetype) | |||||
1415 | return MD; | |||||
1416 | ||||||
1417 | // For these purposes, a method in an @implementation overrides a | |||||
1418 | // declaration in the @interface. | |||||
1419 | if (const ObjCImplDecl *impl = | |||||
1420 | dyn_cast<ObjCImplDecl>(MD->getDeclContext())) { | |||||
1421 | const ObjCContainerDecl *iface; | |||||
1422 | if (const ObjCCategoryImplDecl *catImpl = | |||||
1423 | dyn_cast<ObjCCategoryImplDecl>(impl)) { | |||||
1424 | iface = catImpl->getCategoryDecl(); | |||||
1425 | } else { | |||||
1426 | iface = impl->getClassInterface(); | |||||
1427 | } | |||||
1428 | ||||||
1429 | const ObjCMethodDecl *ifaceMD = | |||||
1430 | iface->getMethod(MD->getSelector(), MD->isInstanceMethod()); | |||||
1431 | if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype); | |||||
1432 | } | |||||
1433 | ||||||
1434 | SmallVector<const ObjCMethodDecl *, 4> overrides; | |||||
1435 | MD->getOverriddenMethods(overrides); | |||||
1436 | for (unsigned i = 0, e = overrides.size(); i != e; ++i) { | |||||
1437 | if (const ObjCMethodDecl *result = | |||||
1438 | findExplicitInstancetypeDeclarer(overrides[i], instancetype)) | |||||
1439 | return result; | |||||
1440 | } | |||||
1441 | ||||||
1442 | return nullptr; | |||||
1443 | } | |||||
1444 | ||||||
1445 | void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { | |||||
1446 | // Only complain if we're in an ObjC method and the required return | |||||
1447 | // type doesn't match the method's declared return type. | |||||
1448 | ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext); | |||||
1449 | if (!MD || !MD->hasRelatedResultType() || | |||||
1450 | Context.hasSameUnqualifiedType(destType, MD->getReturnType())) | |||||
1451 | return; | |||||
1452 | ||||||
1453 | // Look for a method overridden by this method which explicitly uses | |||||
1454 | // 'instancetype'. | |||||
1455 | if (const ObjCMethodDecl *overridden = | |||||
1456 | findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) { | |||||
1457 | SourceRange range = overridden->getReturnTypeSourceRange(); | |||||
1458 | SourceLocation loc = range.getBegin(); | |||||
1459 | if (loc.isInvalid()) | |||||
1460 | loc = overridden->getLocation(); | |||||
1461 | Diag(loc, diag::note_related_result_type_explicit) | |||||
1462 | << /*current method*/ 1 << range; | |||||
1463 | return; | |||||
1464 | } | |||||
1465 | ||||||
1466 | // Otherwise, if we have an interesting method family, note that. | |||||
1467 | // This should always trigger if the above didn't. | |||||
1468 | if (ObjCMethodFamily family = MD->getMethodFamily()) | |||||
1469 | Diag(MD->getLocation(), diag::note_related_result_type_family) | |||||
1470 | << /*current method*/ 1 | |||||
1471 | << family; | |||||
1472 | } | |||||
1473 | ||||||
1474 | void Sema::EmitRelatedResultTypeNote(const Expr *E) { | |||||
1475 | E = E->IgnoreParenImpCasts(); | |||||
1476 | const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E); | |||||
1477 | if (!MsgSend) | |||||
1478 | return; | |||||
1479 | ||||||
1480 | const ObjCMethodDecl *Method = MsgSend->getMethodDecl(); | |||||
1481 | if (!Method) | |||||
1482 | return; | |||||
1483 | ||||||
1484 | if (!Method->hasRelatedResultType()) | |||||
1485 | return; | |||||
1486 | ||||||
1487 | if (Context.hasSameUnqualifiedType( | |||||
1488 | Method->getReturnType().getNonReferenceType(), MsgSend->getType())) | |||||
1489 | return; | |||||
1490 | ||||||
1491 | if (!Context.hasSameUnqualifiedType(Method->getReturnType(), | |||||
1492 | Context.getObjCInstanceType())) | |||||
1493 | return; | |||||
1494 | ||||||
1495 | Diag(Method->getLocation(), diag::note_related_result_type_inferred) | |||||
1496 | << Method->isInstanceMethod() << Method->getSelector() | |||||
1497 | << MsgSend->getType(); | |||||
1498 | } | |||||
1499 | ||||||
1500 | bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, | |||||
1501 | MultiExprArg Args, | |||||
1502 | Selector Sel, | |||||
1503 | ArrayRef<SourceLocation> SelectorLocs, | |||||
1504 | ObjCMethodDecl *Method, | |||||
1505 | bool isClassMessage, bool isSuperMessage, | |||||
1506 | SourceLocation lbrac, SourceLocation rbrac, | |||||
1507 | SourceRange RecRange, | |||||
1508 | QualType &ReturnType, ExprValueKind &VK) { | |||||
1509 | SourceLocation SelLoc; | |||||
1510 | if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) | |||||
1511 | SelLoc = SelectorLocs.front(); | |||||
1512 | else | |||||
1513 | SelLoc = lbrac; | |||||
1514 | ||||||
1515 | if (!Method) { | |||||
1516 | // Apply default argument promotion as for (C99 6.5.2.2p6). | |||||
1517 | for (unsigned i = 0, e = Args.size(); i != e; i++) { | |||||
1518 | if (Args[i]->isTypeDependent()) | |||||
1519 | continue; | |||||
1520 | ||||||
1521 | ExprResult result; | |||||
1522 | if (getLangOpts().DebuggerSupport) { | |||||
1523 | QualType paramTy; // ignored | |||||
1524 | result = checkUnknownAnyArg(SelLoc, Args[i], paramTy); | |||||
1525 | } else { | |||||
1526 | result = DefaultArgumentPromotion(Args[i]); | |||||
1527 | } | |||||
1528 | if (result.isInvalid()) | |||||
1529 | return true; | |||||
1530 | Args[i] = result.get(); | |||||
1531 | } | |||||
1532 | ||||||
1533 | unsigned DiagID; | |||||
1534 | if (getLangOpts().ObjCAutoRefCount) | |||||
1535 | DiagID = diag::err_arc_method_not_found; | |||||
1536 | else | |||||
1537 | DiagID = isClassMessage ? diag::warn_class_method_not_found | |||||
1538 | : diag::warn_inst_method_not_found; | |||||
1539 | if (!getLangOpts().DebuggerSupport) { | |||||
1540 | const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType); | |||||
1541 | if (OMD && !OMD->isInvalidDecl()) { | |||||
1542 | if (getLangOpts().ObjCAutoRefCount) | |||||
1543 | DiagID = diag::err_method_not_found_with_typo; | |||||
1544 | else | |||||
1545 | DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo | |||||
1546 | : diag::warn_instance_method_not_found_with_typo; | |||||
1547 | Selector MatchedSel = OMD->getSelector(); | |||||
1548 | SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back()); | |||||
1549 | if (MatchedSel.isUnarySelector()) | |||||
1550 | Diag(SelLoc, DiagID) | |||||
1551 | << Sel<< isClassMessage << MatchedSel | |||||
1552 | << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString()); | |||||
1553 | else | |||||
1554 | Diag(SelLoc, DiagID) << Sel<< isClassMessage << MatchedSel; | |||||
1555 | } | |||||
1556 | else | |||||
1557 | Diag(SelLoc, DiagID) | |||||
1558 | << Sel << isClassMessage << SourceRange(SelectorLocs.front(), | |||||
1559 | SelectorLocs.back()); | |||||
1560 | // Find the class to which we are sending this message. | |||||
1561 | if (ReceiverType->isObjCObjectPointerType()) { | |||||
1562 | if (ObjCInterfaceDecl *ThisClass = | |||||
1563 | ReceiverType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()) { | |||||
1564 | Diag(ThisClass->getLocation(), diag::note_receiver_class_declared); | |||||
1565 | if (!RecRange.isInvalid()) | |||||
1566 | if (ThisClass->lookupClassMethod(Sel)) | |||||
1567 | Diag(RecRange.getBegin(),diag::note_receiver_expr_here) | |||||
1568 | << FixItHint::CreateReplacement(RecRange, | |||||
1569 | ThisClass->getNameAsString()); | |||||
1570 | } | |||||
1571 | } | |||||
1572 | } | |||||
1573 | ||||||
1574 | // In debuggers, we want to use __unknown_anytype for these | |||||
1575 | // results so that clients can cast them. | |||||
1576 | if (getLangOpts().DebuggerSupport) { | |||||
1577 | ReturnType = Context.UnknownAnyTy; | |||||
1578 | } else { | |||||
1579 | ReturnType = Context.getObjCIdType(); | |||||
1580 | } | |||||
1581 | VK = VK_RValue; | |||||
1582 | return false; | |||||
1583 | } | |||||
1584 | ||||||
1585 | ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage, | |||||
1586 | isSuperMessage); | |||||
1587 | VK = Expr::getValueKindForType(Method->getReturnType()); | |||||
1588 | ||||||
1589 | unsigned NumNamedArgs = Sel.getNumArgs(); | |||||
1590 | // Method might have more arguments than selector indicates. This is due | |||||
1591 | // to addition of c-style arguments in method. | |||||
1592 | if (Method->param_size() > Sel.getNumArgs()) | |||||
1593 | NumNamedArgs = Method->param_size(); | |||||
1594 | // FIXME. This need be cleaned up. | |||||
1595 | if (Args.size() < NumNamedArgs) { | |||||
1596 | Diag(SelLoc, diag::err_typecheck_call_too_few_args) | |||||
1597 | << 2 << NumNamedArgs << static_cast<unsigned>(Args.size()); | |||||
1598 | return false; | |||||
1599 | } | |||||
1600 | ||||||
1601 | // Compute the set of type arguments to be substituted into each parameter | |||||
1602 | // type. | |||||
1603 | Optional<ArrayRef<QualType>> typeArgs | |||||
1604 | = ReceiverType->getObjCSubstitutions(Method->getDeclContext()); | |||||
1605 | bool IsError = false; | |||||
1606 | for (unsigned i = 0; i < NumNamedArgs; i++) { | |||||
1607 | // We can't do any type-checking on a type-dependent argument. | |||||
1608 | if (Args[i]->isTypeDependent()) | |||||
1609 | continue; | |||||
1610 | ||||||
1611 | Expr *argExpr = Args[i]; | |||||
1612 | ||||||
1613 | ParmVarDecl *param = Method->parameters()[i]; | |||||
1614 | assert(argExpr && "CheckMessageArgumentTypes(): missing expression")(static_cast <bool> (argExpr && "CheckMessageArgumentTypes(): missing expression" ) ? void (0) : __assert_fail ("argExpr && \"CheckMessageArgumentTypes(): missing expression\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 1614, __extension__ __PRETTY_FUNCTION__)); | |||||
1615 | ||||||
1616 | // Strip the unbridged-cast placeholder expression off unless it's | |||||
1617 | // a consumed argument. | |||||
1618 | if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) && | |||||
1619 | !param->hasAttr<CFConsumedAttr>()) | |||||
1620 | argExpr = stripARCUnbridgedCast(argExpr); | |||||
1621 | ||||||
1622 | // If the parameter is __unknown_anytype, infer its type | |||||
1623 | // from the argument. | |||||
1624 | if (param->getType() == Context.UnknownAnyTy) { | |||||
1625 | QualType paramType; | |||||
1626 | ExprResult argE = checkUnknownAnyArg(SelLoc, argExpr, paramType); | |||||
1627 | if (argE.isInvalid()) { | |||||
1628 | IsError = true; | |||||
1629 | } else { | |||||
1630 | Args[i] = argE.get(); | |||||
1631 | ||||||
1632 | // Update the parameter type in-place. | |||||
1633 | param->setType(paramType); | |||||
1634 | } | |||||
1635 | continue; | |||||
1636 | } | |||||
1637 | ||||||
1638 | QualType origParamType = param->getType(); | |||||
1639 | QualType paramType = param->getType(); | |||||
1640 | if (typeArgs) | |||||
1641 | paramType = paramType.substObjCTypeArgs( | |||||
1642 | Context, | |||||
1643 | *typeArgs, | |||||
1644 | ObjCSubstitutionContext::Parameter); | |||||
1645 | ||||||
1646 | if (RequireCompleteType(argExpr->getSourceRange().getBegin(), | |||||
1647 | paramType, | |||||
1648 | diag::err_call_incomplete_argument, argExpr)) | |||||
1649 | return true; | |||||
1650 | ||||||
1651 | InitializedEntity Entity | |||||
1652 | = InitializedEntity::InitializeParameter(Context, param, paramType); | |||||
1653 | ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), argExpr); | |||||
1654 | if (ArgE.isInvalid()) | |||||
1655 | IsError = true; | |||||
1656 | else { | |||||
1657 | Args[i] = ArgE.getAs<Expr>(); | |||||
1658 | ||||||
1659 | // If we are type-erasing a block to a block-compatible | |||||
1660 | // Objective-C pointer type, we may need to extend the lifetime | |||||
1661 | // of the block object. | |||||
1662 | if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() && | |||||
1663 | Args[i]->getType()->isBlockPointerType() && | |||||
1664 | origParamType->isObjCObjectPointerType()) { | |||||
1665 | ExprResult arg = Args[i]; | |||||
1666 | maybeExtendBlockObject(arg); | |||||
1667 | Args[i] = arg.get(); | |||||
1668 | } | |||||
1669 | } | |||||
1670 | } | |||||
1671 | ||||||
1672 | // Promote additional arguments to variadic methods. | |||||
1673 | if (Method->isVariadic()) { | |||||
1674 | for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) { | |||||
1675 | if (Args[i]->isTypeDependent()) | |||||
1676 | continue; | |||||
1677 | ||||||
1678 | ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, | |||||
1679 | nullptr); | |||||
1680 | IsError |= Arg.isInvalid(); | |||||
1681 | Args[i] = Arg.get(); | |||||
1682 | } | |||||
1683 | } else { | |||||
1684 | // Check for extra arguments to non-variadic methods. | |||||
1685 | if (Args.size() != NumNamedArgs) { | |||||
1686 | Diag(Args[NumNamedArgs]->getLocStart(), | |||||
1687 | diag::err_typecheck_call_too_many_args) | |||||
1688 | << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size()) | |||||
1689 | << Method->getSourceRange() | |||||
1690 | << SourceRange(Args[NumNamedArgs]->getLocStart(), | |||||
1691 | Args.back()->getLocEnd()); | |||||
1692 | } | |||||
1693 | } | |||||
1694 | ||||||
1695 | DiagnoseSentinelCalls(Method, SelLoc, Args); | |||||
1696 | ||||||
1697 | // Do additional checkings on method. | |||||
1698 | IsError |= CheckObjCMethodCall( | |||||
1699 | Method, SelLoc, makeArrayRef(Args.data(), Args.size())); | |||||
1700 | ||||||
1701 | return IsError; | |||||
1702 | } | |||||
1703 | ||||||
1704 | bool Sema::isSelfExpr(Expr *RExpr) { | |||||
1705 | // 'self' is objc 'self' in an objc method only. | |||||
1706 | ObjCMethodDecl *Method = | |||||
1707 | dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor()); | |||||
1708 | return isSelfExpr(RExpr, Method); | |||||
1709 | } | |||||
1710 | ||||||
1711 | bool Sema::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) { | |||||
1712 | if (!method) return false; | |||||
1713 | ||||||
1714 | receiver = receiver->IgnoreParenLValueCasts(); | |||||
| ||||||
1715 | if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver)) | |||||
1716 | if (DRE->getDecl() == method->getSelfDecl()) | |||||
1717 | return true; | |||||
1718 | return false; | |||||
1719 | } | |||||
1720 | ||||||
1721 | /// LookupMethodInType - Look up a method in an ObjCObjectType. | |||||
1722 | ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type, | |||||
1723 | bool isInstance) { | |||||
1724 | const ObjCObjectType *objType = type->castAs<ObjCObjectType>(); | |||||
1725 | if (ObjCInterfaceDecl *iface = objType->getInterface()) { | |||||
1726 | // Look it up in the main interface (and categories, etc.) | |||||
1727 | if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance)) | |||||
1728 | return method; | |||||
1729 | ||||||
1730 | // Okay, look for "private" methods declared in any | |||||
1731 | // @implementations we've seen. | |||||
1732 | if (ObjCMethodDecl *method = iface->lookupPrivateMethod(sel, isInstance)) | |||||
1733 | return method; | |||||
1734 | } | |||||
1735 | ||||||
1736 | // Check qualifiers. | |||||
1737 | for (const auto *I : objType->quals()) | |||||
1738 | if (ObjCMethodDecl *method = I->lookupMethod(sel, isInstance)) | |||||
1739 | return method; | |||||
1740 | ||||||
1741 | return nullptr; | |||||
1742 | } | |||||
1743 | ||||||
1744 | /// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier | |||||
1745 | /// list of a qualified objective pointer type. | |||||
1746 | ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, | |||||
1747 | const ObjCObjectPointerType *OPT, | |||||
1748 | bool Instance) | |||||
1749 | { | |||||
1750 | ObjCMethodDecl *MD = nullptr; | |||||
1751 | for (const auto *PROTO : OPT->quals()) { | |||||
1752 | if ((MD = PROTO->lookupMethod(Sel, Instance))) { | |||||
1753 | return MD; | |||||
1754 | } | |||||
1755 | } | |||||
1756 | return nullptr; | |||||
1757 | } | |||||
1758 | ||||||
1759 | /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an | |||||
1760 | /// objective C interface. This is a property reference expression. | |||||
1761 | ExprResult Sema:: | |||||
1762 | HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, | |||||
1763 | Expr *BaseExpr, SourceLocation OpLoc, | |||||
1764 | DeclarationName MemberName, | |||||
1765 | SourceLocation MemberLoc, | |||||
1766 | SourceLocation SuperLoc, QualType SuperType, | |||||
1767 | bool Super) { | |||||
1768 | const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); | |||||
1769 | ObjCInterfaceDecl *IFace = IFaceT->getDecl(); | |||||
1770 | ||||||
1771 | if (!MemberName.isIdentifier()) { | |||||
1772 | Diag(MemberLoc, diag::err_invalid_property_name) | |||||
1773 | << MemberName << QualType(OPT, 0); | |||||
1774 | return ExprError(); | |||||
1775 | } | |||||
1776 | ||||||
1777 | IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); | |||||
1778 | ||||||
1779 | SourceRange BaseRange = Super? SourceRange(SuperLoc) | |||||
1780 | : BaseExpr->getSourceRange(); | |||||
1781 | if (RequireCompleteType(MemberLoc, OPT->getPointeeType(), | |||||
1782 | diag::err_property_not_found_forward_class, | |||||
1783 | MemberName, BaseRange)) | |||||
1784 | return ExprError(); | |||||
1785 | ||||||
1786 | if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration( | |||||
1787 | Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { | |||||
1788 | // Check whether we can reference this property. | |||||
1789 | if (DiagnoseUseOfDecl(PD, MemberLoc)) | |||||
1790 | return ExprError(); | |||||
1791 | if (Super) | |||||
1792 | return new (Context) | |||||
1793 | ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, | |||||
1794 | OK_ObjCProperty, MemberLoc, SuperLoc, SuperType); | |||||
1795 | else | |||||
1796 | return new (Context) | |||||
1797 | ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, | |||||
1798 | OK_ObjCProperty, MemberLoc, BaseExpr); | |||||
1799 | } | |||||
1800 | // Check protocols on qualified interfaces. | |||||
1801 | for (const auto *I : OPT->quals()) | |||||
1802 | if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration( | |||||
1803 | Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { | |||||
1804 | // Check whether we can reference this property. | |||||
1805 | if (DiagnoseUseOfDecl(PD, MemberLoc)) | |||||
1806 | return ExprError(); | |||||
1807 | ||||||
1808 | if (Super) | |||||
1809 | return new (Context) ObjCPropertyRefExpr( | |||||
1810 | PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, | |||||
1811 | SuperLoc, SuperType); | |||||
1812 | else | |||||
1813 | return new (Context) | |||||
1814 | ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, | |||||
1815 | OK_ObjCProperty, MemberLoc, BaseExpr); | |||||
1816 | } | |||||
1817 | // If that failed, look for an "implicit" property by seeing if the nullary | |||||
1818 | // selector is implemented. | |||||
1819 | ||||||
1820 | // FIXME: The logic for looking up nullary and unary selectors should be | |||||
1821 | // shared with the code in ActOnInstanceMessage. | |||||
1822 | ||||||
1823 | Selector Sel = PP.getSelectorTable().getNullarySelector(Member); | |||||
1824 | ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); | |||||
1825 | ||||||
1826 | // May be found in property's qualified list. | |||||
1827 | if (!Getter) | |||||
1828 | Getter = LookupMethodInQualifiedType(Sel, OPT, true); | |||||
1829 | ||||||
1830 | // If this reference is in an @implementation, check for 'private' methods. | |||||
1831 | if (!Getter) | |||||
1832 | Getter = IFace->lookupPrivateMethod(Sel); | |||||
1833 | ||||||
1834 | if (Getter) { | |||||
1835 | // Check if we can reference this property. | |||||
1836 | if (DiagnoseUseOfDecl(Getter, MemberLoc)) | |||||
1837 | return ExprError(); | |||||
1838 | } | |||||
1839 | // If we found a getter then this may be a valid dot-reference, we | |||||
1840 | // will look for the matching setter, in case it is needed. | |||||
1841 | Selector SetterSel = | |||||
1842 | SelectorTable::constructSetterSelector(PP.getIdentifierTable(), | |||||
1843 | PP.getSelectorTable(), Member); | |||||
1844 | ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); | |||||
1845 | ||||||
1846 | // May be found in property's qualified list. | |||||
1847 | if (!Setter) | |||||
1848 | Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); | |||||
1849 | ||||||
1850 | if (!Setter) { | |||||
1851 | // If this reference is in an @implementation, also check for 'private' | |||||
1852 | // methods. | |||||
1853 | Setter = IFace->lookupPrivateMethod(SetterSel); | |||||
1854 | } | |||||
1855 | ||||||
1856 | if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) | |||||
1857 | return ExprError(); | |||||
1858 | ||||||
1859 | // Special warning if member name used in a property-dot for a setter accessor | |||||
1860 | // does not use a property with same name; e.g. obj.X = ... for a property with | |||||
1861 | // name 'x'. | |||||
1862 | if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor() && | |||||
1863 | !IFace->FindPropertyDeclaration( | |||||
1864 | Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { | |||||
1865 | if (const ObjCPropertyDecl *PDecl = Setter->findPropertyDecl()) { | |||||
1866 | // Do not warn if user is using property-dot syntax to make call to | |||||
1867 | // user named setter. | |||||
1868 | if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter)) | |||||
1869 | Diag(MemberLoc, | |||||
1870 | diag::warn_property_access_suggest) | |||||
1871 | << MemberName << QualType(OPT, 0) << PDecl->getName() | |||||
1872 | << FixItHint::CreateReplacement(MemberLoc, PDecl->getName()); | |||||
1873 | } | |||||
1874 | } | |||||
1875 | ||||||
1876 | if (Getter || Setter) { | |||||
1877 | if (Super) | |||||
1878 | return new (Context) | |||||
1879 | ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue, | |||||
1880 | OK_ObjCProperty, MemberLoc, SuperLoc, SuperType); | |||||
1881 | else | |||||
1882 | return new (Context) | |||||
1883 | ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue, | |||||
1884 | OK_ObjCProperty, MemberLoc, BaseExpr); | |||||
1885 | ||||||
1886 | } | |||||
1887 | ||||||
1888 | // Attempt to correct for typos in property names. | |||||
1889 | if (TypoCorrection Corrected = | |||||
1890 | CorrectTypo(DeclarationNameInfo(MemberName, MemberLoc), | |||||
1891 | LookupOrdinaryName, nullptr, nullptr, | |||||
1892 | llvm::make_unique<DeclFilterCCC<ObjCPropertyDecl>>(), | |||||
1893 | CTK_ErrorRecovery, IFace, false, OPT)) { | |||||
1894 | DeclarationName TypoResult = Corrected.getCorrection(); | |||||
1895 | if (TypoResult.isIdentifier() && | |||||
1896 | TypoResult.getAsIdentifierInfo() == Member) { | |||||
1897 | // There is no need to try the correction if it is the same. | |||||
1898 | NamedDecl *ChosenDecl = | |||||
1899 | Corrected.isKeyword() ? nullptr : Corrected.getFoundDecl(); | |||||
1900 | if (ChosenDecl && isa<ObjCPropertyDecl>(ChosenDecl)) | |||||
1901 | if (cast<ObjCPropertyDecl>(ChosenDecl)->isClassProperty()) { | |||||
1902 | // This is a class property, we should not use the instance to | |||||
1903 | // access it. | |||||
1904 | Diag(MemberLoc, diag::err_class_property_found) << MemberName | |||||
1905 | << OPT->getInterfaceDecl()->getName() | |||||
1906 | << FixItHint::CreateReplacement(BaseExpr->getSourceRange(), | |||||
1907 | OPT->getInterfaceDecl()->getName()); | |||||
1908 | return ExprError(); | |||||
1909 | } | |||||
1910 | } else { | |||||
1911 | diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest) | |||||
1912 | << MemberName << QualType(OPT, 0)); | |||||
1913 | return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, | |||||
1914 | TypoResult, MemberLoc, | |||||
1915 | SuperLoc, SuperType, Super); | |||||
1916 | } | |||||
1917 | } | |||||
1918 | ObjCInterfaceDecl *ClassDeclared; | |||||
1919 | if (ObjCIvarDecl *Ivar = | |||||
1920 | IFace->lookupInstanceVariable(Member, ClassDeclared)) { | |||||
1921 | QualType T = Ivar->getType(); | |||||
1922 | if (const ObjCObjectPointerType * OBJPT = | |||||
1923 | T->getAsObjCInterfacePointerType()) { | |||||
1924 | if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(), | |||||
1925 | diag::err_property_not_as_forward_class, | |||||
1926 | MemberName, BaseExpr)) | |||||
1927 | return ExprError(); | |||||
1928 | } | |||||
1929 | Diag(MemberLoc, | |||||
1930 | diag::err_ivar_access_using_property_syntax_suggest) | |||||
1931 | << MemberName << QualType(OPT, 0) << Ivar->getDeclName() | |||||
1932 | << FixItHint::CreateReplacement(OpLoc, "->"); | |||||
1933 | return ExprError(); | |||||
1934 | } | |||||
1935 | ||||||
1936 | Diag(MemberLoc, diag::err_property_not_found) | |||||
1937 | << MemberName << QualType(OPT, 0); | |||||
1938 | if (Setter) | |||||
1939 | Diag(Setter->getLocation(), diag::note_getter_unavailable) | |||||
1940 | << MemberName << BaseExpr->getSourceRange(); | |||||
1941 | return ExprError(); | |||||
1942 | } | |||||
1943 | ||||||
1944 | ExprResult Sema:: | |||||
1945 | ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, | |||||
1946 | IdentifierInfo &propertyName, | |||||
1947 | SourceLocation receiverNameLoc, | |||||
1948 | SourceLocation propertyNameLoc) { | |||||
1949 | ||||||
1950 | IdentifierInfo *receiverNamePtr = &receiverName; | |||||
1951 | ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr, | |||||
1952 | receiverNameLoc); | |||||
1953 | ||||||
1954 | QualType SuperType; | |||||
1955 | if (!IFace) { | |||||
1956 | // If the "receiver" is 'super' in a method, handle it as an expression-like | |||||
1957 | // property reference. | |||||
1958 | if (receiverNamePtr->isStr("super")) { | |||||
1959 | if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { | |||||
1960 | if (auto classDecl = CurMethod->getClassInterface()) { | |||||
1961 | SuperType = QualType(classDecl->getSuperClassType(), 0); | |||||
1962 | if (CurMethod->isInstanceMethod()) { | |||||
1963 | if (SuperType.isNull()) { | |||||
1964 | // The current class does not have a superclass. | |||||
1965 | Diag(receiverNameLoc, diag::err_root_class_cannot_use_super) | |||||
1966 | << CurMethod->getClassInterface()->getIdentifier(); | |||||
1967 | return ExprError(); | |||||
1968 | } | |||||
1969 | QualType T = Context.getObjCObjectPointerType(SuperType); | |||||
1970 | ||||||
1971 | return HandleExprPropertyRefExpr(T->castAs<ObjCObjectPointerType>(), | |||||
1972 | /*BaseExpr*/nullptr, | |||||
1973 | SourceLocation()/*OpLoc*/, | |||||
1974 | &propertyName, | |||||
1975 | propertyNameLoc, | |||||
1976 | receiverNameLoc, T, true); | |||||
1977 | } | |||||
1978 | ||||||
1979 | // Otherwise, if this is a class method, try dispatching to our | |||||
1980 | // superclass. | |||||
1981 | IFace = CurMethod->getClassInterface()->getSuperClass(); | |||||
1982 | } | |||||
1983 | } | |||||
1984 | } | |||||
1985 | ||||||
1986 | if (!IFace) { | |||||
1987 | Diag(receiverNameLoc, diag::err_expected_either) << tok::identifier | |||||
1988 | << tok::l_paren; | |||||
1989 | return ExprError(); | |||||
1990 | } | |||||
1991 | } | |||||
1992 | ||||||
1993 | Selector GetterSel; | |||||
1994 | Selector SetterSel; | |||||
1995 | if (auto PD = IFace->FindPropertyDeclaration( | |||||
1996 | &propertyName, ObjCPropertyQueryKind::OBJC_PR_query_class)) { | |||||
1997 | GetterSel = PD->getGetterName(); | |||||
1998 | SetterSel = PD->getSetterName(); | |||||
1999 | } else { | |||||
2000 | GetterSel = PP.getSelectorTable().getNullarySelector(&propertyName); | |||||
2001 | SetterSel = SelectorTable::constructSetterSelector( | |||||
2002 | PP.getIdentifierTable(), PP.getSelectorTable(), &propertyName); | |||||
2003 | } | |||||
2004 | ||||||
2005 | // Search for a declared property first. | |||||
2006 | ObjCMethodDecl *Getter = IFace->lookupClassMethod(GetterSel); | |||||
2007 | ||||||
2008 | // If this reference is in an @implementation, check for 'private' methods. | |||||
2009 | if (!Getter) | |||||
2010 | Getter = IFace->lookupPrivateClassMethod(GetterSel); | |||||
2011 | ||||||
2012 | if (Getter) { | |||||
2013 | // FIXME: refactor/share with ActOnMemberReference(). | |||||
2014 | // Check if we can reference this property. | |||||
2015 | if (DiagnoseUseOfDecl(Getter, propertyNameLoc)) | |||||
2016 | return ExprError(); | |||||
2017 | } | |||||
2018 | ||||||
2019 | // Look for the matching setter, in case it is needed. | |||||
2020 | ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); | |||||
2021 | if (!Setter) { | |||||
2022 | // If this reference is in an @implementation, also check for 'private' | |||||
2023 | // methods. | |||||
2024 | Setter = IFace->lookupPrivateClassMethod(SetterSel); | |||||
2025 | } | |||||
2026 | // Look through local category implementations associated with the class. | |||||
2027 | if (!Setter) | |||||
2028 | Setter = IFace->getCategoryClassMethod(SetterSel); | |||||
2029 | ||||||
2030 | if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc)) | |||||
2031 | return ExprError(); | |||||
2032 | ||||||
2033 | if (Getter || Setter) { | |||||
2034 | if (!SuperType.isNull()) | |||||
2035 | return new (Context) | |||||
2036 | ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue, | |||||
2037 | OK_ObjCProperty, propertyNameLoc, receiverNameLoc, | |||||
2038 | SuperType); | |||||
2039 | ||||||
2040 | return new (Context) ObjCPropertyRefExpr( | |||||
2041 | Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, | |||||
2042 | propertyNameLoc, receiverNameLoc, IFace); | |||||
2043 | } | |||||
2044 | return ExprError(Diag(propertyNameLoc, diag::err_property_not_found) | |||||
2045 | << &propertyName << Context.getObjCInterfaceType(IFace)); | |||||
2046 | } | |||||
2047 | ||||||
2048 | namespace { | |||||
2049 | ||||||
2050 | class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { | |||||
2051 | public: | |||||
2052 | ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) { | |||||
2053 | // Determine whether "super" is acceptable in the current context. | |||||
2054 | if (Method && Method->getClassInterface()) | |||||
2055 | WantObjCSuper = Method->getClassInterface()->getSuperClass(); | |||||
2056 | } | |||||
2057 | ||||||
2058 | bool ValidateCandidate(const TypoCorrection &candidate) override { | |||||
2059 | return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() || | |||||
2060 | candidate.isKeyword("super"); | |||||
2061 | } | |||||
2062 | }; | |||||
2063 | ||||||
2064 | } // end anonymous namespace | |||||
2065 | ||||||
2066 | Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, | |||||
2067 | IdentifierInfo *Name, | |||||
2068 | SourceLocation NameLoc, | |||||
2069 | bool IsSuper, | |||||
2070 | bool HasTrailingDot, | |||||
2071 | ParsedType &ReceiverType) { | |||||
2072 | ReceiverType = nullptr; | |||||
2073 | ||||||
2074 | // If the identifier is "super" and there is no trailing dot, we're | |||||
2075 | // messaging super. If the identifier is "super" and there is a | |||||
2076 | // trailing dot, it's an instance message. | |||||
2077 | if (IsSuper && S->isInObjcMethodScope()) | |||||
2078 | return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage; | |||||
2079 | ||||||
2080 | LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); | |||||
2081 | LookupName(Result, S); | |||||
2082 | ||||||
2083 | switch (Result.getResultKind()) { | |||||
2084 | case LookupResult::NotFound: | |||||
2085 | // Normal name lookup didn't find anything. If we're in an | |||||
2086 | // Objective-C method, look for ivars. If we find one, we're done! | |||||
2087 | // FIXME: This is a hack. Ivar lookup should be part of normal | |||||
2088 | // lookup. | |||||
2089 | if (ObjCMethodDecl *Method = getCurMethodDecl()) { | |||||
2090 | if (!Method->getClassInterface()) { | |||||
2091 | // Fall back: let the parser try to parse it as an instance message. | |||||
2092 | return ObjCInstanceMessage; | |||||
2093 | } | |||||
2094 | ||||||
2095 | ObjCInterfaceDecl *ClassDeclared; | |||||
2096 | if (Method->getClassInterface()->lookupInstanceVariable(Name, | |||||
2097 | ClassDeclared)) | |||||
2098 | return ObjCInstanceMessage; | |||||
2099 | } | |||||
2100 | ||||||
2101 | // Break out; we'll perform typo correction below. | |||||
2102 | break; | |||||
2103 | ||||||
2104 | case LookupResult::NotFoundInCurrentInstantiation: | |||||
2105 | case LookupResult::FoundOverloaded: | |||||
2106 | case LookupResult::FoundUnresolvedValue: | |||||
2107 | case LookupResult::Ambiguous: | |||||
2108 | Result.suppressDiagnostics(); | |||||
2109 | return ObjCInstanceMessage; | |||||
2110 | ||||||
2111 | case LookupResult::Found: { | |||||
2112 | // If the identifier is a class or not, and there is a trailing dot, | |||||
2113 | // it's an instance message. | |||||
2114 | if (HasTrailingDot) | |||||
2115 | return ObjCInstanceMessage; | |||||
2116 | // We found something. If it's a type, then we have a class | |||||
2117 | // message. Otherwise, it's an instance message. | |||||
2118 | NamedDecl *ND = Result.getFoundDecl(); | |||||
2119 | QualType T; | |||||
2120 | if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) | |||||
2121 | T = Context.getObjCInterfaceType(Class); | |||||
2122 | else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) { | |||||
2123 | T = Context.getTypeDeclType(Type); | |||||
2124 | DiagnoseUseOfDecl(Type, NameLoc); | |||||
2125 | } | |||||
2126 | else | |||||
2127 | return ObjCInstanceMessage; | |||||
2128 | ||||||
2129 | // We have a class message, and T is the type we're | |||||
2130 | // messaging. Build source-location information for it. | |||||
2131 | TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); | |||||
2132 | ReceiverType = CreateParsedType(T, TSInfo); | |||||
2133 | return ObjCClassMessage; | |||||
2134 | } | |||||
2135 | } | |||||
2136 | ||||||
2137 | if (TypoCorrection Corrected = CorrectTypo( | |||||
2138 | Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, | |||||
2139 | llvm::make_unique<ObjCInterfaceOrSuperCCC>(getCurMethodDecl()), | |||||
2140 | CTK_ErrorRecovery, nullptr, false, nullptr, false)) { | |||||
2141 | if (Corrected.isKeyword()) { | |||||
2142 | // If we've found the keyword "super" (the only keyword that would be | |||||
2143 | // returned by CorrectTypo), this is a send to super. | |||||
2144 | diagnoseTypo(Corrected, | |||||
2145 | PDiag(diag::err_unknown_receiver_suggest) << Name); | |||||
2146 | return ObjCSuperMessage; | |||||
2147 | } else if (ObjCInterfaceDecl *Class = | |||||
2148 | Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { | |||||
2149 | // If we found a declaration, correct when it refers to an Objective-C | |||||
2150 | // class. | |||||
2151 | diagnoseTypo(Corrected, | |||||
2152 | PDiag(diag::err_unknown_receiver_suggest) << Name); | |||||
2153 | QualType T = Context.getObjCInterfaceType(Class); | |||||
2154 | TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); | |||||
2155 | ReceiverType = CreateParsedType(T, TSInfo); | |||||
2156 | return ObjCClassMessage; | |||||
2157 | } | |||||
2158 | } | |||||
2159 | ||||||
2160 | // Fall back: let the parser try to parse it as an instance message. | |||||
2161 | return ObjCInstanceMessage; | |||||
2162 | } | |||||
2163 | ||||||
2164 | ExprResult Sema::ActOnSuperMessage(Scope *S, | |||||
2165 | SourceLocation SuperLoc, | |||||
2166 | Selector Sel, | |||||
2167 | SourceLocation LBracLoc, | |||||
2168 | ArrayRef<SourceLocation> SelectorLocs, | |||||
2169 | SourceLocation RBracLoc, | |||||
2170 | MultiExprArg Args) { | |||||
2171 | // Determine whether we are inside a method or not. | |||||
2172 | ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc); | |||||
2173 | if (!Method) { | |||||
2174 | Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); | |||||
2175 | return ExprError(); | |||||
2176 | } | |||||
2177 | ||||||
2178 | ObjCInterfaceDecl *Class = Method->getClassInterface(); | |||||
2179 | if (!Class) { | |||||
2180 | Diag(SuperLoc, diag::err_no_super_class_message) | |||||
2181 | << Method->getDeclName(); | |||||
2182 | return ExprError(); | |||||
2183 | } | |||||
2184 | ||||||
2185 | QualType SuperTy(Class->getSuperClassType(), 0); | |||||
2186 | if (SuperTy.isNull()) { | |||||
2187 | // The current class does not have a superclass. | |||||
2188 | Diag(SuperLoc, diag::err_root_class_cannot_use_super) | |||||
2189 | << Class->getIdentifier(); | |||||
2190 | return ExprError(); | |||||
2191 | } | |||||
2192 | ||||||
2193 | // We are in a method whose class has a superclass, so 'super' | |||||
2194 | // is acting as a keyword. | |||||
2195 | if (Method->getSelector() == Sel) | |||||
2196 | getCurFunction()->ObjCShouldCallSuper = false; | |||||
2197 | ||||||
2198 | if (Method->isInstanceMethod()) { | |||||
2199 | // Since we are in an instance method, this is an instance | |||||
2200 | // message to the superclass instance. | |||||
2201 | SuperTy = Context.getObjCObjectPointerType(SuperTy); | |||||
2202 | return BuildInstanceMessage(nullptr, SuperTy, SuperLoc, | |||||
2203 | Sel, /*Method=*/nullptr, | |||||
2204 | LBracLoc, SelectorLocs, RBracLoc, Args); | |||||
2205 | } | |||||
2206 | ||||||
2207 | // Since we are in a class method, this is a class message to | |||||
2208 | // the superclass. | |||||
2209 | return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr, | |||||
2210 | SuperTy, | |||||
2211 | SuperLoc, Sel, /*Method=*/nullptr, | |||||
2212 | LBracLoc, SelectorLocs, RBracLoc, Args); | |||||
2213 | } | |||||
2214 | ||||||
2215 | ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType, | |||||
2216 | bool isSuperReceiver, | |||||
2217 | SourceLocation Loc, | |||||
2218 | Selector Sel, | |||||
2219 | ObjCMethodDecl *Method, | |||||
2220 | MultiExprArg Args) { | |||||
2221 | TypeSourceInfo *receiverTypeInfo = nullptr; | |||||
2222 | if (!ReceiverType.isNull()) | |||||
2223 | receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType); | |||||
2224 | ||||||
2225 | return BuildClassMessage(receiverTypeInfo, ReceiverType, | |||||
2226 | /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(), | |||||
2227 | Sel, Method, Loc, Loc, Loc, Args, | |||||
2228 | /*isImplicit=*/true); | |||||
2229 | } | |||||
2230 | ||||||
2231 | static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg, | |||||
2232 | unsigned DiagID, | |||||
2233 | bool (*refactor)(const ObjCMessageExpr *, | |||||
2234 | const NSAPI &, edit::Commit &)) { | |||||
2235 | SourceLocation MsgLoc = Msg->getExprLoc(); | |||||
2236 | if (S.Diags.isIgnored(DiagID, MsgLoc)) | |||||
2237 | return; | |||||
2238 | ||||||
2239 | SourceManager &SM = S.SourceMgr; | |||||
2240 | edit::Commit ECommit(SM, S.LangOpts); | |||||
2241 | if (refactor(Msg,*S.NSAPIObj, ECommit)) { | |||||
2242 | DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID) | |||||
2243 | << Msg->getSelector() << Msg->getSourceRange(); | |||||
2244 | // FIXME: Don't emit diagnostic at all if fixits are non-commitable. | |||||
2245 | if (!ECommit.isCommitable()) | |||||
2246 | return; | |||||
2247 | for (edit::Commit::edit_iterator | |||||
2248 | I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) { | |||||
2249 | const edit::Commit::Edit &Edit = *I; | |||||
2250 | switch (Edit.Kind) { | |||||
2251 | case edit::Commit::Act_Insert: | |||||
2252 | Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc, | |||||
2253 | Edit.Text, | |||||
2254 | Edit.BeforePrev)); | |||||
2255 | break; | |||||
2256 | case edit::Commit::Act_InsertFromRange: | |||||
2257 | Builder.AddFixItHint( | |||||
2258 | FixItHint::CreateInsertionFromRange(Edit.OrigLoc, | |||||
2259 | Edit.getInsertFromRange(SM), | |||||
2260 | Edit.BeforePrev)); | |||||
2261 | break; | |||||
2262 | case edit::Commit::Act_Remove: | |||||
2263 | Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM))); | |||||
2264 | break; | |||||
2265 | } | |||||
2266 | } | |||||
2267 | } | |||||
2268 | } | |||||
2269 | ||||||
2270 | static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) { | |||||
2271 | applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use, | |||||
2272 | edit::rewriteObjCRedundantCallWithLiteral); | |||||
2273 | } | |||||
2274 | ||||||
2275 | static void checkFoundationAPI(Sema &S, SourceLocation Loc, | |||||
2276 | const ObjCMethodDecl *Method, | |||||
2277 | ArrayRef<Expr *> Args, QualType ReceiverType, | |||||
2278 | bool IsClassObjectCall) { | |||||
2279 | // Check if this is a performSelector method that uses a selector that returns | |||||
2280 | // a record or a vector type. | |||||
2281 | if (Method->getSelector().getMethodFamily() != OMF_performSelector || | |||||
2282 | Args.empty()) | |||||
2283 | return; | |||||
2284 | const auto *SE = dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens()); | |||||
2285 | if (!SE) | |||||
2286 | return; | |||||
2287 | ObjCMethodDecl *ImpliedMethod; | |||||
2288 | if (!IsClassObjectCall) { | |||||
2289 | const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>(); | |||||
2290 | if (!OPT || !OPT->getInterfaceDecl()) | |||||
2291 | return; | |||||
2292 | ImpliedMethod = | |||||
2293 | OPT->getInterfaceDecl()->lookupInstanceMethod(SE->getSelector()); | |||||
2294 | if (!ImpliedMethod) | |||||
2295 | ImpliedMethod = | |||||
2296 | OPT->getInterfaceDecl()->lookupPrivateMethod(SE->getSelector()); | |||||
2297 | } else { | |||||
2298 | const auto *IT = ReceiverType->getAs<ObjCInterfaceType>(); | |||||
2299 | if (!IT) | |||||
2300 | return; | |||||
2301 | ImpliedMethod = IT->getDecl()->lookupClassMethod(SE->getSelector()); | |||||
2302 | if (!ImpliedMethod) | |||||
2303 | ImpliedMethod = | |||||
2304 | IT->getDecl()->lookupPrivateClassMethod(SE->getSelector()); | |||||
2305 | } | |||||
2306 | if (!ImpliedMethod) | |||||
2307 | return; | |||||
2308 | QualType Ret = ImpliedMethod->getReturnType(); | |||||
2309 | if (Ret->isRecordType() || Ret->isVectorType() || Ret->isExtVectorType()) { | |||||
2310 | QualType Ret = ImpliedMethod->getReturnType(); | |||||
2311 | S.Diag(Loc, diag::warn_objc_unsafe_perform_selector) | |||||
2312 | << Method->getSelector() | |||||
2313 | << (!Ret->isRecordType() | |||||
2314 | ? /*Vector*/ 2 | |||||
2315 | : Ret->isUnionType() ? /*Union*/ 1 : /*Struct*/ 0); | |||||
2316 | S.Diag(ImpliedMethod->getLocStart(), | |||||
2317 | diag::note_objc_unsafe_perform_selector_method_declared_here) | |||||
2318 | << ImpliedMethod->getSelector() << Ret; | |||||
2319 | } | |||||
2320 | } | |||||
2321 | ||||||
2322 | /// \brief Diagnose use of %s directive in an NSString which is being passed | |||||
2323 | /// as formatting string to formatting method. | |||||
2324 | static void | |||||
2325 | DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S, | |||||
2326 | ObjCMethodDecl *Method, | |||||
2327 | Selector Sel, | |||||
2328 | Expr **Args, unsigned NumArgs) { | |||||
2329 | unsigned Idx = 0; | |||||
2330 | bool Format = false; | |||||
2331 | ObjCStringFormatFamily SFFamily = Sel.getStringFormatFamily(); | |||||
2332 | if (SFFamily == ObjCStringFormatFamily::SFF_NSString) { | |||||
2333 | Idx = 0; | |||||
2334 | Format = true; | |||||
2335 | } | |||||
2336 | else if (Method) { | |||||
2337 | for (const auto *I : Method->specific_attrs<FormatAttr>()) { | |||||
2338 | if (S.GetFormatNSStringIdx(I, Idx)) { | |||||
2339 | Format = true; | |||||
2340 | break; | |||||
2341 | } | |||||
2342 | } | |||||
2343 | } | |||||
2344 | if (!Format || NumArgs <= Idx) | |||||
2345 | return; | |||||
2346 | ||||||
2347 | Expr *FormatExpr = Args[Idx]; | |||||
2348 | if (ObjCStringLiteral *OSL = | |||||
2349 | dyn_cast<ObjCStringLiteral>(FormatExpr->IgnoreParenImpCasts())) { | |||||
2350 | StringLiteral *FormatString = OSL->getString(); | |||||
2351 | if (S.FormatStringHasSArg(FormatString)) { | |||||
2352 | S.Diag(FormatExpr->getExprLoc(), diag::warn_objc_cdirective_format_string) | |||||
2353 | << "%s" << 0 << 0; | |||||
2354 | if (Method) | |||||
2355 | S.Diag(Method->getLocation(), diag::note_method_declared_at) | |||||
2356 | << Method->getDeclName(); | |||||
2357 | } | |||||
2358 | } | |||||
2359 | } | |||||
2360 | ||||||
2361 | /// \brief Build an Objective-C class message expression. | |||||
2362 | /// | |||||
2363 | /// This routine takes care of both normal class messages and | |||||
2364 | /// class messages to the superclass. | |||||
2365 | /// | |||||
2366 | /// \param ReceiverTypeInfo Type source information that describes the | |||||
2367 | /// receiver of this message. This may be NULL, in which case we are | |||||
2368 | /// sending to the superclass and \p SuperLoc must be a valid source | |||||
2369 | /// location. | |||||
2370 | ||||||
2371 | /// \param ReceiverType The type of the object receiving the | |||||
2372 | /// message. When \p ReceiverTypeInfo is non-NULL, this is the same | |||||
2373 | /// type as that refers to. For a superclass send, this is the type of | |||||
2374 | /// the superclass. | |||||
2375 | /// | |||||
2376 | /// \param SuperLoc The location of the "super" keyword in a | |||||
2377 | /// superclass message. | |||||
2378 | /// | |||||
2379 | /// \param Sel The selector to which the message is being sent. | |||||
2380 | /// | |||||
2381 | /// \param Method The method that this class message is invoking, if | |||||
2382 | /// already known. | |||||
2383 | /// | |||||
2384 | /// \param LBracLoc The location of the opening square bracket ']'. | |||||
2385 | /// | |||||
2386 | /// \param RBracLoc The location of the closing square bracket ']'. | |||||
2387 | /// | |||||
2388 | /// \param ArgsIn The message arguments. | |||||
2389 | ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, | |||||
2390 | QualType ReceiverType, | |||||
2391 | SourceLocation SuperLoc, | |||||
2392 | Selector Sel, | |||||
2393 | ObjCMethodDecl *Method, | |||||
2394 | SourceLocation LBracLoc, | |||||
2395 | ArrayRef<SourceLocation> SelectorLocs, | |||||
2396 | SourceLocation RBracLoc, | |||||
2397 | MultiExprArg ArgsIn, | |||||
2398 | bool isImplicit) { | |||||
2399 | SourceLocation Loc = SuperLoc.isValid()? SuperLoc | |||||
2400 | : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); | |||||
2401 | if (LBracLoc.isInvalid()) { | |||||
2402 | Diag(Loc, diag::err_missing_open_square_message_send) | |||||
2403 | << FixItHint::CreateInsertion(Loc, "["); | |||||
2404 | LBracLoc = Loc; | |||||
2405 | } | |||||
2406 | SourceLocation SelLoc; | |||||
2407 | if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) | |||||
2408 | SelLoc = SelectorLocs.front(); | |||||
2409 | else | |||||
2410 | SelLoc = Loc; | |||||
2411 | ||||||
2412 | if (ReceiverType->isDependentType()) { | |||||
2413 | // If the receiver type is dependent, we can't type-check anything | |||||
2414 | // at this point. Build a dependent expression. | |||||
2415 | unsigned NumArgs = ArgsIn.size(); | |||||
2416 | Expr **Args = ArgsIn.data(); | |||||
2417 | assert(SuperLoc.isInvalid() && "Message to super with dependent type")(static_cast <bool> (SuperLoc.isInvalid() && "Message to super with dependent type" ) ? void (0) : __assert_fail ("SuperLoc.isInvalid() && \"Message to super with dependent type\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 2417, __extension__ __PRETTY_FUNCTION__)); | |||||
2418 | return ObjCMessageExpr::Create( | |||||
2419 | Context, ReceiverType, VK_RValue, LBracLoc, ReceiverTypeInfo, Sel, | |||||
2420 | SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), RBracLoc, | |||||
2421 | isImplicit); | |||||
2422 | } | |||||
2423 | ||||||
2424 | // Find the class to which we are sending this message. | |||||
2425 | ObjCInterfaceDecl *Class = nullptr; | |||||
2426 | const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>(); | |||||
2427 | if (!ClassType || !(Class = ClassType->getInterface())) { | |||||
2428 | Diag(Loc, diag::err_invalid_receiver_class_message) | |||||
2429 | << ReceiverType; | |||||
2430 | return ExprError(); | |||||
2431 | } | |||||
2432 | assert(Class && "We don't know which class we're messaging?")(static_cast <bool> (Class && "We don't know which class we're messaging?" ) ? void (0) : __assert_fail ("Class && \"We don't know which class we're messaging?\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 2432, __extension__ __PRETTY_FUNCTION__)); | |||||
2433 | // objc++ diagnoses during typename annotation. | |||||
2434 | if (!getLangOpts().CPlusPlus) | |||||
2435 | (void)DiagnoseUseOfDecl(Class, SelLoc); | |||||
2436 | // Find the method we are messaging. | |||||
2437 | if (!Method) { | |||||
2438 | SourceRange TypeRange | |||||
2439 | = SuperLoc.isValid()? SourceRange(SuperLoc) | |||||
2440 | : ReceiverTypeInfo->getTypeLoc().getSourceRange(); | |||||
2441 | if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class), | |||||
2442 | (getLangOpts().ObjCAutoRefCount | |||||
2443 | ? diag::err_arc_receiver_forward_class | |||||
2444 | : diag::warn_receiver_forward_class), | |||||
2445 | TypeRange)) { | |||||
2446 | // A forward class used in messaging is treated as a 'Class' | |||||
2447 | Method = LookupFactoryMethodInGlobalPool(Sel, | |||||
2448 | SourceRange(LBracLoc, RBracLoc)); | |||||
2449 | if (Method && !getLangOpts().ObjCAutoRefCount) | |||||
2450 | Diag(Method->getLocation(), diag::note_method_sent_forward_class) | |||||
2451 | << Method->getDeclName(); | |||||
2452 | } | |||||
2453 | if (!Method) | |||||
2454 | Method = Class->lookupClassMethod(Sel); | |||||
2455 | ||||||
2456 | // If we have an implementation in scope, check "private" methods. | |||||
2457 | if (!Method) | |||||
2458 | Method = Class->lookupPrivateClassMethod(Sel); | |||||
2459 | ||||||
2460 | if (Method && DiagnoseUseOfDecl(Method, SelLoc)) | |||||
2461 | return ExprError(); | |||||
2462 | } | |||||
2463 | ||||||
2464 | // Check the argument types and determine the result type. | |||||
2465 | QualType ReturnType; | |||||
2466 | ExprValueKind VK = VK_RValue; | |||||
2467 | ||||||
2468 | unsigned NumArgs = ArgsIn.size(); | |||||
2469 | Expr **Args = ArgsIn.data(); | |||||
2470 | if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), | |||||
2471 | Sel, SelectorLocs, | |||||
2472 | Method, true, | |||||
2473 | SuperLoc.isValid(), LBracLoc, RBracLoc, | |||||
2474 | SourceRange(), | |||||
2475 | ReturnType, VK)) | |||||
2476 | return ExprError(); | |||||
2477 | ||||||
2478 | if (Method && !Method->getReturnType()->isVoidType() && | |||||
2479 | RequireCompleteType(LBracLoc, Method->getReturnType(), | |||||
2480 | diag::err_illegal_message_expr_incomplete_type)) | |||||
2481 | return ExprError(); | |||||
2482 | ||||||
2483 | // Warn about explicit call of +initialize on its own class. But not on 'super'. | |||||
2484 | if (Method && Method->getMethodFamily() == OMF_initialize) { | |||||
2485 | if (!SuperLoc.isValid()) { | |||||
2486 | const ObjCInterfaceDecl *ID = | |||||
2487 | dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()); | |||||
2488 | if (ID == Class) { | |||||
2489 | Diag(Loc, diag::warn_direct_initialize_call); | |||||
2490 | Diag(Method->getLocation(), diag::note_method_declared_at) | |||||
2491 | << Method->getDeclName(); | |||||
2492 | } | |||||
2493 | } | |||||
2494 | else if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { | |||||
2495 | // [super initialize] is allowed only within an +initialize implementation | |||||
2496 | if (CurMeth->getMethodFamily() != OMF_initialize) { | |||||
2497 | Diag(Loc, diag::warn_direct_super_initialize_call); | |||||
2498 | Diag(Method->getLocation(), diag::note_method_declared_at) | |||||
2499 | << Method->getDeclName(); | |||||
2500 | Diag(CurMeth->getLocation(), diag::note_method_declared_at) | |||||
2501 | << CurMeth->getDeclName(); | |||||
2502 | } | |||||
2503 | } | |||||
2504 | } | |||||
2505 | ||||||
2506 | DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs); | |||||
2507 | ||||||
2508 | // Construct the appropriate ObjCMessageExpr. | |||||
2509 | ObjCMessageExpr *Result; | |||||
2510 | if (SuperLoc.isValid()) | |||||
2511 | Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, | |||||
2512 | SuperLoc, /*IsInstanceSuper=*/false, | |||||
2513 | ReceiverType, Sel, SelectorLocs, | |||||
2514 | Method, makeArrayRef(Args, NumArgs), | |||||
2515 | RBracLoc, isImplicit); | |||||
2516 | else { | |||||
2517 | Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, | |||||
2518 | ReceiverTypeInfo, Sel, SelectorLocs, | |||||
2519 | Method, makeArrayRef(Args, NumArgs), | |||||
2520 | RBracLoc, isImplicit); | |||||
2521 | if (!isImplicit) | |||||
2522 | checkCocoaAPI(*this, Result); | |||||
2523 | } | |||||
2524 | if (Method) | |||||
2525 | checkFoundationAPI(*this, SelLoc, Method, makeArrayRef(Args, NumArgs), | |||||
2526 | ReceiverType, /*IsClassObjectCall=*/true); | |||||
2527 | return MaybeBindToTemporary(Result); | |||||
2528 | } | |||||
2529 | ||||||
2530 | // ActOnClassMessage - used for both unary and keyword messages. | |||||
2531 | // ArgExprs is optional - if it is present, the number of expressions | |||||
2532 | // is obtained from Sel.getNumArgs(). | |||||
2533 | ExprResult Sema::ActOnClassMessage(Scope *S, | |||||
2534 | ParsedType Receiver, | |||||
2535 | Selector Sel, | |||||
2536 | SourceLocation LBracLoc, | |||||
2537 | ArrayRef<SourceLocation> SelectorLocs, | |||||
2538 | SourceLocation RBracLoc, | |||||
2539 | MultiExprArg Args) { | |||||
2540 | TypeSourceInfo *ReceiverTypeInfo; | |||||
2541 | QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo); | |||||
2542 | if (ReceiverType.isNull()) | |||||
2543 | return ExprError(); | |||||
2544 | ||||||
2545 | if (!ReceiverTypeInfo) | |||||
2546 | ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc); | |||||
2547 | ||||||
2548 | return BuildClassMessage(ReceiverTypeInfo, ReceiverType, | |||||
2549 | /*SuperLoc=*/SourceLocation(), Sel, | |||||
2550 | /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc, | |||||
2551 | Args); | |||||
2552 | } | |||||
2553 | ||||||
2554 | ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, | |||||
2555 | QualType ReceiverType, | |||||
2556 | SourceLocation Loc, | |||||
2557 | Selector Sel, | |||||
2558 | ObjCMethodDecl *Method, | |||||
2559 | MultiExprArg Args) { | |||||
2560 | return BuildInstanceMessage(Receiver, ReceiverType, | |||||
2561 | /*SuperLoc=*/!Receiver ? Loc : SourceLocation(), | |||||
2562 | Sel, Method, Loc, Loc, Loc, Args, | |||||
2563 | /*isImplicit=*/true); | |||||
2564 | } | |||||
2565 | ||||||
2566 | static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) { | |||||
2567 | if (!S.NSAPIObj) | |||||
2568 | return false; | |||||
2569 | const auto *Protocol = dyn_cast<ObjCProtocolDecl>(M->getDeclContext()); | |||||
2570 | if (!Protocol) | |||||
2571 | return false; | |||||
2572 | const IdentifierInfo *II = S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject); | |||||
2573 | if (const auto *RootClass = dyn_cast_or_null<ObjCInterfaceDecl>( | |||||
2574 | S.LookupSingleName(S.TUScope, II, Protocol->getLocStart(), | |||||
2575 | Sema::LookupOrdinaryName))) { | |||||
2576 | for (const ObjCProtocolDecl *P : RootClass->all_referenced_protocols()) { | |||||
2577 | if (P->getCanonicalDecl() == Protocol->getCanonicalDecl()) | |||||
2578 | return true; | |||||
2579 | } | |||||
2580 | } | |||||
2581 | return false; | |||||
2582 | } | |||||
2583 | ||||||
2584 | /// \brief Build an Objective-C instance message expression. | |||||
2585 | /// | |||||
2586 | /// This routine takes care of both normal instance messages and | |||||
2587 | /// instance messages to the superclass instance. | |||||
2588 | /// | |||||
2589 | /// \param Receiver The expression that computes the object that will | |||||
2590 | /// receive this message. This may be empty, in which case we are | |||||
2591 | /// sending to the superclass instance and \p SuperLoc must be a valid | |||||
2592 | /// source location. | |||||
2593 | /// | |||||
2594 | /// \param ReceiverType The (static) type of the object receiving the | |||||
2595 | /// message. When a \p Receiver expression is provided, this is the | |||||
2596 | /// same type as that expression. For a superclass instance send, this | |||||
2597 | /// is a pointer to the type of the superclass. | |||||
2598 | /// | |||||
2599 | /// \param SuperLoc The location of the "super" keyword in a | |||||
2600 | /// superclass instance message. | |||||
2601 | /// | |||||
2602 | /// \param Sel The selector to which the message is being sent. | |||||
2603 | /// | |||||
2604 | /// \param Method The method that this instance message is invoking, if | |||||
2605 | /// already known. | |||||
2606 | /// | |||||
2607 | /// \param LBracLoc The location of the opening square bracket ']'. | |||||
2608 | /// | |||||
2609 | /// \param RBracLoc The location of the closing square bracket ']'. | |||||
2610 | /// | |||||
2611 | /// \param ArgsIn The message arguments. | |||||
2612 | ExprResult Sema::BuildInstanceMessage(Expr *Receiver, | |||||
2613 | QualType ReceiverType, | |||||
2614 | SourceLocation SuperLoc, | |||||
2615 | Selector Sel, | |||||
2616 | ObjCMethodDecl *Method, | |||||
2617 | SourceLocation LBracLoc, | |||||
2618 | ArrayRef<SourceLocation> SelectorLocs, | |||||
2619 | SourceLocation RBracLoc, | |||||
2620 | MultiExprArg ArgsIn, | |||||
2621 | bool isImplicit) { | |||||
2622 | assert((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the "(static_cast <bool> ((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the " "SuperLoc must be valid so we can " "use it instead.") ? void (0) : __assert_fail ("(Receiver || SuperLoc.isValid()) && \"If the Receiver is null, the \" \"SuperLoc must be valid so we can \" \"use it instead.\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 2624, __extension__ __PRETTY_FUNCTION__)) | |||||
| ||||||
2623 | "SuperLoc must be valid so we can "(static_cast <bool> ((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the " "SuperLoc must be valid so we can " "use it instead.") ? void (0) : __assert_fail ("(Receiver || SuperLoc.isValid()) && \"If the Receiver is null, the \" \"SuperLoc must be valid so we can \" \"use it instead.\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 2624, __extension__ __PRETTY_FUNCTION__)) | |||||
2624 | "use it instead.")(static_cast <bool> ((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the " "SuperLoc must be valid so we can " "use it instead.") ? void (0) : __assert_fail ("(Receiver || SuperLoc.isValid()) && \"If the Receiver is null, the \" \"SuperLoc must be valid so we can \" \"use it instead.\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 2624, __extension__ __PRETTY_FUNCTION__)); | |||||
2625 | ||||||
2626 | // The location of the receiver. | |||||
2627 | SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); | |||||
2628 | SourceRange RecRange = | |||||
2629 | SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange(); | |||||
2630 | SourceLocation SelLoc; | |||||
2631 | if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) | |||||
2632 | SelLoc = SelectorLocs.front(); | |||||
2633 | else | |||||
2634 | SelLoc = Loc; | |||||
2635 | ||||||
2636 | if (LBracLoc.isInvalid()) { | |||||
2637 | Diag(Loc, diag::err_missing_open_square_message_send) | |||||
2638 | << FixItHint::CreateInsertion(Loc, "["); | |||||
2639 | LBracLoc = Loc; | |||||
2640 | } | |||||
2641 | ||||||
2642 | // If we have a receiver expression, perform appropriate promotions | |||||
2643 | // and determine receiver type. | |||||
2644 | if (Receiver) { | |||||
2645 | if (Receiver->hasPlaceholderType()) { | |||||
2646 | ExprResult Result; | |||||
2647 | if (Receiver->getType() == Context.UnknownAnyTy) | |||||
2648 | Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType()); | |||||
2649 | else | |||||
2650 | Result = CheckPlaceholderExpr(Receiver); | |||||
2651 | if (Result.isInvalid()) return ExprError(); | |||||
2652 | Receiver = Result.get(); | |||||
2653 | } | |||||
2654 | ||||||
2655 | if (Receiver->isTypeDependent()) { | |||||
2656 | // If the receiver is type-dependent, we can't type-check anything | |||||
2657 | // at this point. Build a dependent expression. | |||||
2658 | unsigned NumArgs = ArgsIn.size(); | |||||
2659 | Expr **Args = ArgsIn.data(); | |||||
2660 | assert(SuperLoc.isInvalid() && "Message to super with dependent type")(static_cast <bool> (SuperLoc.isInvalid() && "Message to super with dependent type" ) ? void (0) : __assert_fail ("SuperLoc.isInvalid() && \"Message to super with dependent type\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 2660, __extension__ __PRETTY_FUNCTION__)); | |||||
2661 | return ObjCMessageExpr::Create( | |||||
2662 | Context, Context.DependentTy, VK_RValue, LBracLoc, Receiver, Sel, | |||||
2663 | SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), | |||||
2664 | RBracLoc, isImplicit); | |||||
2665 | } | |||||
2666 | ||||||
2667 | // If necessary, apply function/array conversion to the receiver. | |||||
2668 | // C99 6.7.5.3p[7,8]. | |||||
2669 | ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); | |||||
2670 | if (Result.isInvalid()) | |||||
2671 | return ExprError(); | |||||
2672 | Receiver = Result.get(); | |||||
2673 | ReceiverType = Receiver->getType(); | |||||
2674 | ||||||
2675 | // If the receiver is an ObjC pointer, a block pointer, or an | |||||
2676 | // __attribute__((NSObject)) pointer, we don't need to do any | |||||
2677 | // special conversion in order to look up a receiver. | |||||
2678 | if (ReceiverType->isObjCRetainableType()) { | |||||
2679 | // do nothing | |||||
2680 | } else if (!getLangOpts().ObjCAutoRefCount && | |||||
2681 | !Context.getObjCIdType().isNull() && | |||||
2682 | (ReceiverType->isPointerType() || | |||||
2683 | ReceiverType->isIntegerType())) { | |||||
2684 | // Implicitly convert integers and pointers to 'id' but emit a warning. | |||||
2685 | // But not in ARC. | |||||
2686 | Diag(Loc, diag::warn_bad_receiver_type) | |||||
2687 | << ReceiverType | |||||
2688 | << Receiver->getSourceRange(); | |||||
2689 | if (ReceiverType->isPointerType()) { | |||||
2690 | Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), | |||||
2691 | CK_CPointerToObjCPointerCast).get(); | |||||
2692 | } else { | |||||
2693 | // TODO: specialized warning on null receivers? | |||||
2694 | bool IsNull = Receiver->isNullPointerConstant(Context, | |||||
2695 | Expr::NPC_ValueDependentIsNull); | |||||
2696 | CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer; | |||||
2697 | Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), | |||||
2698 | Kind).get(); | |||||
2699 | } | |||||
2700 | ReceiverType = Receiver->getType(); | |||||
2701 | } else if (getLangOpts().CPlusPlus) { | |||||
2702 | // The receiver must be a complete type. | |||||
2703 | if (RequireCompleteType(Loc, Receiver->getType(), | |||||
2704 | diag::err_incomplete_receiver_type)) | |||||
2705 | return ExprError(); | |||||
2706 | ||||||
2707 | ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver); | |||||
2708 | if (result.isUsable()) { | |||||
2709 | Receiver = result.get(); | |||||
2710 | ReceiverType = Receiver->getType(); | |||||
2711 | } | |||||
2712 | } | |||||
2713 | } | |||||
2714 | ||||||
2715 | if (ReceiverType->isObjCIdType() && !isImplicit) | |||||
2716 | Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id); | |||||
2717 | ||||||
2718 | // There's a somewhat weird interaction here where we assume that we | |||||
2719 | // won't actually have a method unless we also don't need to do some | |||||
2720 | // of the more detailed type-checking on the receiver. | |||||
2721 | ||||||
2722 | if (!Method) { | |||||
2723 | // Handle messages to id and __kindof types (where we use the | |||||
2724 | // global method pool). | |||||
2725 | const ObjCObjectType *typeBound = nullptr; | |||||
2726 | bool receiverIsIdLike = ReceiverType->isObjCIdOrObjectKindOfType(Context, | |||||
2727 | typeBound); | |||||
2728 | if (receiverIsIdLike || ReceiverType->isBlockPointerType() || | |||||
2729 | (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) { | |||||
2730 | SmallVector<ObjCMethodDecl*, 4> Methods; | |||||
2731 | // If we have a type bound, further filter the methods. | |||||
2732 | CollectMultipleMethodsInGlobalPool(Sel, Methods, true/*InstanceFirst*/, | |||||
2733 | true/*CheckTheOther*/, typeBound); | |||||
2734 | if (!Methods.empty()) { | |||||
2735 | // We choose the first method as the initial candidate, then try to | |||||
2736 | // select a better one. | |||||
2737 | Method = Methods[0]; | |||||
2738 | ||||||
2739 | if (ObjCMethodDecl *BestMethod = | |||||
2740 | SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(), Methods)) | |||||
2741 | Method = BestMethod; | |||||
2742 | ||||||
2743 | if (!AreMultipleMethodsInGlobalPool(Sel, Method, | |||||
2744 | SourceRange(LBracLoc, RBracLoc), | |||||
2745 | receiverIsIdLike, Methods)) | |||||
2746 | DiagnoseUseOfDecl(Method, SelLoc); | |||||
2747 | } | |||||
2748 | } else if (ReceiverType->isObjCClassOrClassKindOfType() || | |||||
2749 | ReceiverType->isObjCQualifiedClassType()) { | |||||
2750 | // Handle messages to Class. | |||||
2751 | // We allow sending a message to a qualified Class ("Class<foo>"), which | |||||
2752 | // is ok as long as one of the protocols implements the selector (if not, | |||||
2753 | // warn). | |||||
2754 | if (!ReceiverType->isObjCClassOrClassKindOfType()) { | |||||
2755 | const ObjCObjectPointerType *QClassTy | |||||
2756 | = ReceiverType->getAsObjCQualifiedClassType(); | |||||
2757 | // Search protocols for class methods. | |||||
2758 | Method = LookupMethodInQualifiedType(Sel, QClassTy, false); | |||||
2759 | if (!Method) { | |||||
2760 | Method = LookupMethodInQualifiedType(Sel, QClassTy, true); | |||||
2761 | // warn if instance method found for a Class message. | |||||
2762 | if (Method && !isMethodDeclaredInRootProtocol(*this, Method)) { | |||||
2763 | Diag(SelLoc, diag::warn_instance_method_on_class_found) | |||||
2764 | << Method->getSelector() << Sel; | |||||
2765 | Diag(Method->getLocation(), diag::note_method_declared_at) | |||||
2766 | << Method->getDeclName(); | |||||
2767 | } | |||||
2768 | } | |||||
2769 | } else { | |||||
2770 | if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { | |||||
2771 | if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { | |||||
2772 | // First check the public methods in the class interface. | |||||
2773 | Method = ClassDecl->lookupClassMethod(Sel); | |||||
2774 | ||||||
2775 | if (!Method) | |||||
2776 | Method = ClassDecl->lookupPrivateClassMethod(Sel); | |||||
2777 | } | |||||
2778 | if (Method && DiagnoseUseOfDecl(Method, SelLoc)) | |||||
2779 | return ExprError(); | |||||
2780 | } | |||||
2781 | if (!Method) { | |||||
2782 | // If not messaging 'self', look for any factory method named 'Sel'. | |||||
2783 | if (!Receiver || !isSelfExpr(Receiver)) { | |||||
2784 | // If no class (factory) method was found, check if an _instance_ | |||||
2785 | // method of the same name exists in the root class only. | |||||
2786 | SmallVector<ObjCMethodDecl*, 4> Methods; | |||||
2787 | CollectMultipleMethodsInGlobalPool(Sel, Methods, | |||||
2788 | false/*InstanceFirst*/, | |||||
2789 | true/*CheckTheOther*/); | |||||
2790 | if (!Methods.empty()) { | |||||
2791 | // We choose the first method as the initial candidate, then try | |||||
2792 | // to select a better one. | |||||
2793 | Method = Methods[0]; | |||||
2794 | ||||||
2795 | // If we find an instance method, emit waring. | |||||
2796 | if (Method->isInstanceMethod()) { | |||||
2797 | if (const ObjCInterfaceDecl *ID = | |||||
2798 | dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) { | |||||
2799 | if (ID->getSuperClass()) | |||||
2800 | Diag(SelLoc, diag::warn_root_inst_method_not_found) | |||||
2801 | << Sel << SourceRange(LBracLoc, RBracLoc); | |||||
2802 | } | |||||
2803 | } | |||||
2804 | ||||||
2805 | if (ObjCMethodDecl *BestMethod = | |||||
2806 | SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(), | |||||
2807 | Methods)) | |||||
2808 | Method = BestMethod; | |||||
2809 | } | |||||
2810 | } | |||||
2811 | } | |||||
2812 | } | |||||
2813 | } else { | |||||
2814 | ObjCInterfaceDecl *ClassDecl = nullptr; | |||||
2815 | ||||||
2816 | // We allow sending a message to a qualified ID ("id<foo>"), which is ok as | |||||
2817 | // long as one of the protocols implements the selector (if not, warn). | |||||
2818 | // And as long as message is not deprecated/unavailable (warn if it is). | |||||
2819 | if (const ObjCObjectPointerType *QIdTy | |||||
2820 | = ReceiverType->getAsObjCQualifiedIdType()) { | |||||
2821 | // Search protocols for instance methods. | |||||
2822 | Method = LookupMethodInQualifiedType(Sel, QIdTy, true); | |||||
2823 | if (!Method) | |||||
2824 | Method = LookupMethodInQualifiedType(Sel, QIdTy, false); | |||||
2825 | if (Method && DiagnoseUseOfDecl(Method, SelLoc)) | |||||
2826 | return ExprError(); | |||||
2827 | } else if (const ObjCObjectPointerType *OCIType | |||||
2828 | = ReceiverType->getAsObjCInterfacePointerType()) { | |||||
2829 | // We allow sending a message to a pointer to an interface (an object). | |||||
2830 | ClassDecl = OCIType->getInterfaceDecl(); | |||||
2831 | ||||||
2832 | // Try to complete the type. Under ARC, this is a hard error from which | |||||
2833 | // we don't try to recover. | |||||
2834 | // FIXME: In the non-ARC case, this will still be a hard error if the | |||||
2835 | // definition is found in a module that's not visible. | |||||
2836 | const ObjCInterfaceDecl *forwardClass = nullptr; | |||||
2837 | if (RequireCompleteType(Loc, OCIType->getPointeeType(), | |||||
2838 | getLangOpts().ObjCAutoRefCount | |||||
2839 | ? diag::err_arc_receiver_forward_instance | |||||
2840 | : diag::warn_receiver_forward_instance, | |||||
2841 | Receiver? Receiver->getSourceRange() | |||||
2842 | : SourceRange(SuperLoc))) { | |||||
2843 | if (getLangOpts().ObjCAutoRefCount) | |||||
2844 | return ExprError(); | |||||
2845 | ||||||
2846 | forwardClass = OCIType->getInterfaceDecl(); | |||||
2847 | Diag(Receiver ? Receiver->getLocStart() | |||||
2848 | : SuperLoc, diag::note_receiver_is_id); | |||||
2849 | Method = nullptr; | |||||
2850 | } else { | |||||
2851 | Method = ClassDecl->lookupInstanceMethod(Sel); | |||||
2852 | } | |||||
2853 | ||||||
2854 | if (!Method) | |||||
2855 | // Search protocol qualifiers. | |||||
2856 | Method = LookupMethodInQualifiedType(Sel, OCIType, true); | |||||
2857 | ||||||
2858 | if (!Method) { | |||||
2859 | // If we have implementations in scope, check "private" methods. | |||||
2860 | Method = ClassDecl->lookupPrivateMethod(Sel); | |||||
2861 | ||||||
2862 | if (!Method && getLangOpts().ObjCAutoRefCount) { | |||||
2863 | Diag(SelLoc, diag::err_arc_may_not_respond) | |||||
2864 | << OCIType->getPointeeType() << Sel << RecRange | |||||
2865 | << SourceRange(SelectorLocs.front(), SelectorLocs.back()); | |||||
2866 | return ExprError(); | |||||
2867 | } | |||||
2868 | ||||||
2869 | if (!Method && (!Receiver || !isSelfExpr(Receiver))) { | |||||
2870 | // If we still haven't found a method, look in the global pool. This | |||||
2871 | // behavior isn't very desirable, however we need it for GCC | |||||
2872 | // compatibility. FIXME: should we deviate?? | |||||
2873 | if (OCIType->qual_empty()) { | |||||
2874 | SmallVector<ObjCMethodDecl*, 4> Methods; | |||||
2875 | CollectMultipleMethodsInGlobalPool(Sel, Methods, | |||||
2876 | true/*InstanceFirst*/, | |||||
2877 | false/*CheckTheOther*/); | |||||
2878 | if (!Methods.empty()) { | |||||
2879 | // We choose the first method as the initial candidate, then try | |||||
2880 | // to select a better one. | |||||
2881 | Method = Methods[0]; | |||||
2882 | ||||||
2883 | if (ObjCMethodDecl *BestMethod = | |||||
2884 | SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod(), | |||||
2885 | Methods)) | |||||
2886 | Method = BestMethod; | |||||
2887 | ||||||
2888 | AreMultipleMethodsInGlobalPool(Sel, Method, | |||||
2889 | SourceRange(LBracLoc, RBracLoc), | |||||
2890 | true/*receiverIdOrClass*/, | |||||
2891 | Methods); | |||||
2892 | } | |||||
2893 | if (Method && !forwardClass) | |||||
2894 | Diag(SelLoc, diag::warn_maynot_respond) | |||||
2895 | << OCIType->getInterfaceDecl()->getIdentifier() | |||||
2896 | << Sel << RecRange; | |||||
2897 | } | |||||
2898 | } | |||||
2899 | } | |||||
2900 | if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass)) | |||||
2901 | return ExprError(); | |||||
2902 | } else { | |||||
2903 | // Reject other random receiver types (e.g. structs). | |||||
2904 | Diag(Loc, diag::err_bad_receiver_type) | |||||
2905 | << ReceiverType << Receiver->getSourceRange(); | |||||
2906 | return ExprError(); | |||||
2907 | } | |||||
2908 | } | |||||
2909 | } | |||||
2910 | ||||||
2911 | FunctionScopeInfo *DIFunctionScopeInfo = | |||||
2912 | (Method && Method->getMethodFamily() == OMF_init) | |||||
2913 | ? getEnclosingFunction() : nullptr; | |||||
2914 | ||||||
2915 | if (DIFunctionScopeInfo && | |||||
2916 | DIFunctionScopeInfo->ObjCIsDesignatedInit && | |||||
2917 | (SuperLoc.isValid() || isSelfExpr(Receiver))) { | |||||
2918 | bool isDesignatedInitChain = false; | |||||
2919 | if (SuperLoc.isValid()) { | |||||
2920 | if (const ObjCObjectPointerType * | |||||
2921 | OCIType = ReceiverType->getAsObjCInterfacePointerType()) { | |||||
2922 | if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) { | |||||
2923 | // Either we know this is a designated initializer or we | |||||
2924 | // conservatively assume it because we don't know for sure. | |||||
2925 | if (!ID->declaresOrInheritsDesignatedInitializers() || | |||||
2926 | ID->isDesignatedInitializer(Sel)) { | |||||
2927 | isDesignatedInitChain = true; | |||||
2928 | DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false; | |||||
2929 | } | |||||
2930 | } | |||||
2931 | } | |||||
2932 | } | |||||
2933 | if (!isDesignatedInitChain) { | |||||
2934 | const ObjCMethodDecl *InitMethod = nullptr; | |||||
2935 | bool isDesignated = | |||||
2936 | getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod); | |||||
2937 | assert(isDesignated && InitMethod)(static_cast <bool> (isDesignated && InitMethod ) ? void (0) : __assert_fail ("isDesignated && InitMethod" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 2937, __extension__ __PRETTY_FUNCTION__)); | |||||
2938 | (void)isDesignated; | |||||
2939 | Diag(SelLoc, SuperLoc.isValid() ? | |||||
2940 | diag::warn_objc_designated_init_non_designated_init_call : | |||||
2941 | diag::warn_objc_designated_init_non_super_designated_init_call); | |||||
2942 | Diag(InitMethod->getLocation(), | |||||
2943 | diag::note_objc_designated_init_marked_here); | |||||
2944 | } | |||||
2945 | } | |||||
2946 | ||||||
2947 | if (DIFunctionScopeInfo && | |||||
2948 | DIFunctionScopeInfo->ObjCIsSecondaryInit && | |||||
2949 | (SuperLoc.isValid() || isSelfExpr(Receiver))) { | |||||
2950 | if (SuperLoc.isValid()) { | |||||
2951 | Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call); | |||||
2952 | } else { | |||||
2953 | DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false; | |||||
2954 | } | |||||
2955 | } | |||||
2956 | ||||||
2957 | // Check the message arguments. | |||||
2958 | unsigned NumArgs = ArgsIn.size(); | |||||
2959 | Expr **Args = ArgsIn.data(); | |||||
2960 | QualType ReturnType; | |||||
2961 | ExprValueKind VK = VK_RValue; | |||||
2962 | bool ClassMessage = (ReceiverType->isObjCClassType() || | |||||
2963 | ReceiverType->isObjCQualifiedClassType()); | |||||
2964 | if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), | |||||
2965 | Sel, SelectorLocs, Method, | |||||
2966 | ClassMessage, SuperLoc.isValid(), | |||||
2967 | LBracLoc, RBracLoc, RecRange, ReturnType, VK)) | |||||
2968 | return ExprError(); | |||||
2969 | ||||||
2970 | if (Method && !Method->getReturnType()->isVoidType() && | |||||
2971 | RequireCompleteType(LBracLoc, Method->getReturnType(), | |||||
2972 | diag::err_illegal_message_expr_incomplete_type)) | |||||
2973 | return ExprError(); | |||||
2974 | ||||||
2975 | // In ARC, forbid the user from sending messages to | |||||
2976 | // retain/release/autorelease/dealloc/retainCount explicitly. | |||||
2977 | if (getLangOpts().ObjCAutoRefCount) { | |||||
2978 | ObjCMethodFamily family = | |||||
2979 | (Method ? Method->getMethodFamily() : Sel.getMethodFamily()); | |||||
2980 | switch (family) { | |||||
2981 | case OMF_init: | |||||
2982 | if (Method) | |||||
2983 | checkInitMethod(Method, ReceiverType); | |||||
2984 | break; | |||||
2985 | ||||||
2986 | case OMF_None: | |||||
2987 | case OMF_alloc: | |||||
2988 | case OMF_copy: | |||||
2989 | case OMF_finalize: | |||||
2990 | case OMF_mutableCopy: | |||||
2991 | case OMF_new: | |||||
2992 | case OMF_self: | |||||
2993 | case OMF_initialize: | |||||
2994 | break; | |||||
2995 | ||||||
2996 | case OMF_dealloc: | |||||
2997 | case OMF_retain: | |||||
2998 | case OMF_release: | |||||
2999 | case OMF_autorelease: | |||||
3000 | case OMF_retainCount: | |||||
3001 | Diag(SelLoc, diag::err_arc_illegal_explicit_message) | |||||
3002 | << Sel << RecRange; | |||||
3003 | break; | |||||
3004 | ||||||
3005 | case OMF_performSelector: | |||||
3006 | if (Method && NumArgs >= 1) { | |||||
3007 | if (const auto *SelExp = | |||||
3008 | dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens())) { | |||||
3009 | Selector ArgSel = SelExp->getSelector(); | |||||
3010 | ObjCMethodDecl *SelMethod = | |||||
3011 | LookupInstanceMethodInGlobalPool(ArgSel, | |||||
3012 | SelExp->getSourceRange()); | |||||
3013 | if (!SelMethod) | |||||
3014 | SelMethod = | |||||
3015 | LookupFactoryMethodInGlobalPool(ArgSel, | |||||
3016 | SelExp->getSourceRange()); | |||||
3017 | if (SelMethod) { | |||||
3018 | ObjCMethodFamily SelFamily = SelMethod->getMethodFamily(); | |||||
3019 | switch (SelFamily) { | |||||
3020 | case OMF_alloc: | |||||
3021 | case OMF_copy: | |||||
3022 | case OMF_mutableCopy: | |||||
3023 | case OMF_new: | |||||
3024 | case OMF_init: | |||||
3025 | // Issue error, unless ns_returns_not_retained. | |||||
3026 | if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) { | |||||
3027 | // selector names a +1 method | |||||
3028 | Diag(SelLoc, | |||||
3029 | diag::err_arc_perform_selector_retains); | |||||
3030 | Diag(SelMethod->getLocation(), diag::note_method_declared_at) | |||||
3031 | << SelMethod->getDeclName(); | |||||
3032 | } | |||||
3033 | break; | |||||
3034 | default: | |||||
3035 | // +0 call. OK. unless ns_returns_retained. | |||||
3036 | if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) { | |||||
3037 | // selector names a +1 method | |||||
3038 | Diag(SelLoc, | |||||
3039 | diag::err_arc_perform_selector_retains); | |||||
3040 | Diag(SelMethod->getLocation(), diag::note_method_declared_at) | |||||
3041 | << SelMethod->getDeclName(); | |||||
3042 | } | |||||
3043 | break; | |||||
3044 | } | |||||
3045 | } | |||||
3046 | } else { | |||||
3047 | // error (may leak). | |||||
3048 | Diag(SelLoc, diag::warn_arc_perform_selector_leaks); | |||||
3049 | Diag(Args[0]->getExprLoc(), diag::note_used_here); | |||||
3050 | } | |||||
3051 | } | |||||
3052 | break; | |||||
3053 | } | |||||
3054 | } | |||||
3055 | ||||||
3056 | DiagnoseCStringFormatDirectiveInObjCAPI(*this, Method, Sel, Args, NumArgs); | |||||
3057 | ||||||
3058 | // Construct the appropriate ObjCMessageExpr instance. | |||||
3059 | ObjCMessageExpr *Result; | |||||
3060 | if (SuperLoc.isValid()) | |||||
3061 | Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, | |||||
3062 | SuperLoc, /*IsInstanceSuper=*/true, | |||||
3063 | ReceiverType, Sel, SelectorLocs, Method, | |||||
3064 | makeArrayRef(Args, NumArgs), RBracLoc, | |||||
3065 | isImplicit); | |||||
3066 | else { | |||||
3067 | Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, | |||||
3068 | Receiver, Sel, SelectorLocs, Method, | |||||
3069 | makeArrayRef(Args, NumArgs), RBracLoc, | |||||
3070 | isImplicit); | |||||
3071 | if (!isImplicit) | |||||
3072 | checkCocoaAPI(*this, Result); | |||||
3073 | } | |||||
3074 | if (Method) { | |||||
3075 | bool IsClassObjectCall = ClassMessage; | |||||
3076 | // 'self' message receivers in class methods should be treated as message | |||||
3077 | // sends to the class object in order for the semantic checks to be | |||||
3078 | // performed correctly. Messages to 'super' already count as class messages, | |||||
3079 | // so they don't need to be handled here. | |||||
3080 | if (Receiver && isSelfExpr(Receiver)) { | |||||
3081 | if (const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>()) { | |||||
3082 | if (OPT->getObjectType()->isObjCClass()) { | |||||
3083 | if (const auto *CurMeth = getCurMethodDecl()) { | |||||
3084 | IsClassObjectCall = true; | |||||
3085 | ReceiverType = | |||||
3086 | Context.getObjCInterfaceType(CurMeth->getClassInterface()); | |||||
3087 | } | |||||
3088 | } | |||||
3089 | } | |||||
3090 | } | |||||
3091 | checkFoundationAPI(*this, SelLoc, Method, makeArrayRef(Args, NumArgs), | |||||
3092 | ReceiverType, IsClassObjectCall); | |||||
3093 | } | |||||
3094 | ||||||
3095 | if (getLangOpts().ObjCAutoRefCount) { | |||||
3096 | // In ARC, annotate delegate init calls. | |||||
3097 | if (Result->getMethodFamily() == OMF_init && | |||||
3098 | (SuperLoc.isValid() || isSelfExpr(Receiver))) { | |||||
3099 | // Only consider init calls *directly* in init implementations, | |||||
3100 | // not within blocks. | |||||
3101 | ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(CurContext); | |||||
3102 | if (method && method->getMethodFamily() == OMF_init) { | |||||
3103 | // The implicit assignment to self means we also don't want to | |||||
3104 | // consume the result. | |||||
3105 | Result->setDelegateInitCall(true); | |||||
3106 | return Result; | |||||
3107 | } | |||||
3108 | } | |||||
3109 | ||||||
3110 | // In ARC, check for message sends which are likely to introduce | |||||
3111 | // retain cycles. | |||||
3112 | checkRetainCycles(Result); | |||||
3113 | } | |||||
3114 | ||||||
3115 | if (getLangOpts().ObjCWeak) { | |||||
3116 | if (!isImplicit && Method) { | |||||
3117 | if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) { | |||||
3118 | bool IsWeak = | |||||
3119 | Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak; | |||||
3120 | if (!IsWeak && Sel.isUnarySelector()) | |||||
3121 | IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak; | |||||
3122 | if (IsWeak && | |||||
3123 | !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, LBracLoc)) | |||||
3124 | getCurFunction()->recordUseOfWeak(Result, Prop); | |||||
3125 | } | |||||
3126 | } | |||||
3127 | } | |||||
3128 | ||||||
3129 | CheckObjCCircularContainer(Result); | |||||
3130 | ||||||
3131 | return MaybeBindToTemporary(Result); | |||||
3132 | } | |||||
3133 | ||||||
3134 | static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) { | |||||
3135 | if (ObjCSelectorExpr *OSE = | |||||
3136 | dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) { | |||||
3137 | Selector Sel = OSE->getSelector(); | |||||
3138 | SourceLocation Loc = OSE->getAtLoc(); | |||||
3139 | auto Pos = S.ReferencedSelectors.find(Sel); | |||||
3140 | if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc) | |||||
3141 | S.ReferencedSelectors.erase(Pos); | |||||
3142 | } | |||||
3143 | } | |||||
3144 | ||||||
3145 | // ActOnInstanceMessage - used for both unary and keyword messages. | |||||
3146 | // ArgExprs is optional - if it is present, the number of expressions | |||||
3147 | // is obtained from Sel.getNumArgs(). | |||||
3148 | ExprResult Sema::ActOnInstanceMessage(Scope *S, | |||||
3149 | Expr *Receiver, | |||||
3150 | Selector Sel, | |||||
3151 | SourceLocation LBracLoc, | |||||
3152 | ArrayRef<SourceLocation> SelectorLocs, | |||||
3153 | SourceLocation RBracLoc, | |||||
3154 | MultiExprArg Args) { | |||||
3155 | if (!Receiver) | |||||
3156 | return ExprError(); | |||||
3157 | ||||||
3158 | // A ParenListExpr can show up while doing error recovery with invalid code. | |||||
3159 | if (isa<ParenListExpr>(Receiver)) { | |||||
3160 | ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver); | |||||
3161 | if (Result.isInvalid()) return ExprError(); | |||||
3162 | Receiver = Result.get(); | |||||
3163 | } | |||||
3164 | ||||||
3165 | if (RespondsToSelectorSel.isNull()) { | |||||
3166 | IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector"); | |||||
3167 | RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId); | |||||
3168 | } | |||||
3169 | if (Sel == RespondsToSelectorSel) | |||||
3170 | RemoveSelectorFromWarningCache(*this, Args[0]); | |||||
3171 | ||||||
3172 | return BuildInstanceMessage(Receiver, Receiver->getType(), | |||||
3173 | /*SuperLoc=*/SourceLocation(), Sel, | |||||
3174 | /*Method=*/nullptr, LBracLoc, SelectorLocs, | |||||
3175 | RBracLoc, Args); | |||||
3176 | } | |||||
3177 | ||||||
3178 | enum ARCConversionTypeClass { | |||||
3179 | /// int, void, struct A | |||||
3180 | ACTC_none, | |||||
3181 | ||||||
3182 | /// id, void (^)() | |||||
3183 | ACTC_retainable, | |||||
3184 | ||||||
3185 | /// id*, id***, void (^*)(), | |||||
3186 | ACTC_indirectRetainable, | |||||
3187 | ||||||
3188 | /// void* might be a normal C type, or it might a CF type. | |||||
3189 | ACTC_voidPtr, | |||||
3190 | ||||||
3191 | /// struct A* | |||||
3192 | ACTC_coreFoundation | |||||
3193 | }; | |||||
3194 | ||||||
3195 | static bool isAnyRetainable(ARCConversionTypeClass ACTC) { | |||||
3196 | return (ACTC == ACTC_retainable || | |||||
3197 | ACTC == ACTC_coreFoundation || | |||||
3198 | ACTC == ACTC_voidPtr); | |||||
3199 | } | |||||
3200 | ||||||
3201 | static bool isAnyCLike(ARCConversionTypeClass ACTC) { | |||||
3202 | return ACTC == ACTC_none || | |||||
3203 | ACTC == ACTC_voidPtr || | |||||
3204 | ACTC == ACTC_coreFoundation; | |||||
3205 | } | |||||
3206 | ||||||
3207 | static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) { | |||||
3208 | bool isIndirect = false; | |||||
3209 | ||||||
3210 | // Ignore an outermost reference type. | |||||
3211 | if (const ReferenceType *ref = type->getAs<ReferenceType>()) { | |||||
3212 | type = ref->getPointeeType(); | |||||
3213 | isIndirect = true; | |||||
3214 | } | |||||
3215 | ||||||
3216 | // Drill through pointers and arrays recursively. | |||||
3217 | while (true) { | |||||
3218 | if (const PointerType *ptr = type->getAs<PointerType>()) { | |||||
3219 | type = ptr->getPointeeType(); | |||||
3220 | ||||||
3221 | // The first level of pointer may be the innermost pointer on a CF type. | |||||
3222 | if (!isIndirect) { | |||||
3223 | if (type->isVoidType()) return ACTC_voidPtr; | |||||
3224 | if (type->isRecordType()) return ACTC_coreFoundation; | |||||
3225 | } | |||||
3226 | } else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) { | |||||
3227 | type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0); | |||||
3228 | } else { | |||||
3229 | break; | |||||
3230 | } | |||||
3231 | isIndirect = true; | |||||
3232 | } | |||||
3233 | ||||||
3234 | if (isIndirect) { | |||||
3235 | if (type->isObjCARCBridgableType()) | |||||
3236 | return ACTC_indirectRetainable; | |||||
3237 | return ACTC_none; | |||||
3238 | } | |||||
3239 | ||||||
3240 | if (type->isObjCARCBridgableType()) | |||||
3241 | return ACTC_retainable; | |||||
3242 | ||||||
3243 | return ACTC_none; | |||||
3244 | } | |||||
3245 | ||||||
3246 | namespace { | |||||
3247 | /// A result from the cast checker. | |||||
3248 | enum ACCResult { | |||||
3249 | /// Cannot be casted. | |||||
3250 | ACC_invalid, | |||||
3251 | ||||||
3252 | /// Can be safely retained or not retained. | |||||
3253 | ACC_bottom, | |||||
3254 | ||||||
3255 | /// Can be casted at +0. | |||||
3256 | ACC_plusZero, | |||||
3257 | ||||||
3258 | /// Can be casted at +1. | |||||
3259 | ACC_plusOne | |||||
3260 | }; | |||||
3261 | ACCResult merge(ACCResult left, ACCResult right) { | |||||
3262 | if (left == right) return left; | |||||
3263 | if (left == ACC_bottom) return right; | |||||
3264 | if (right == ACC_bottom) return left; | |||||
3265 | return ACC_invalid; | |||||
3266 | } | |||||
3267 | ||||||
3268 | /// A checker which white-lists certain expressions whose conversion | |||||
3269 | /// to or from retainable type would otherwise be forbidden in ARC. | |||||
3270 | class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> { | |||||
3271 | typedef StmtVisitor<ARCCastChecker, ACCResult> super; | |||||
3272 | ||||||
3273 | ASTContext &Context; | |||||
3274 | ARCConversionTypeClass SourceClass; | |||||
3275 | ARCConversionTypeClass TargetClass; | |||||
3276 | bool Diagnose; | |||||
3277 | ||||||
3278 | static bool isCFType(QualType type) { | |||||
3279 | // Someday this can use ns_bridged. For now, it has to do this. | |||||
3280 | return type->isCARCBridgableType(); | |||||
3281 | } | |||||
3282 | ||||||
3283 | public: | |||||
3284 | ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source, | |||||
3285 | ARCConversionTypeClass target, bool diagnose) | |||||
3286 | : Context(Context), SourceClass(source), TargetClass(target), | |||||
3287 | Diagnose(diagnose) {} | |||||
3288 | ||||||
3289 | using super::Visit; | |||||
3290 | ACCResult Visit(Expr *e) { | |||||
3291 | return super::Visit(e->IgnoreParens()); | |||||
3292 | } | |||||
3293 | ||||||
3294 | ACCResult VisitStmt(Stmt *s) { | |||||
3295 | return ACC_invalid; | |||||
3296 | } | |||||
3297 | ||||||
3298 | /// Null pointer constants can be casted however you please. | |||||
3299 | ACCResult VisitExpr(Expr *e) { | |||||
3300 | if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) | |||||
3301 | return ACC_bottom; | |||||
3302 | return ACC_invalid; | |||||
3303 | } | |||||
3304 | ||||||
3305 | /// Objective-C string literals can be safely casted. | |||||
3306 | ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) { | |||||
3307 | // If we're casting to any retainable type, go ahead. Global | |||||
3308 | // strings are immune to retains, so this is bottom. | |||||
3309 | if (isAnyRetainable(TargetClass)) return ACC_bottom; | |||||
3310 | ||||||
3311 | return ACC_invalid; | |||||
3312 | } | |||||
3313 | ||||||
3314 | /// Look through certain implicit and explicit casts. | |||||
3315 | ACCResult VisitCastExpr(CastExpr *e) { | |||||
3316 | switch (e->getCastKind()) { | |||||
3317 | case CK_NullToPointer: | |||||
3318 | return ACC_bottom; | |||||
3319 | ||||||
3320 | case CK_NoOp: | |||||
3321 | case CK_LValueToRValue: | |||||
3322 | case CK_BitCast: | |||||
3323 | case CK_CPointerToObjCPointerCast: | |||||
3324 | case CK_BlockPointerToObjCPointerCast: | |||||
3325 | case CK_AnyPointerToBlockPointerCast: | |||||
3326 | return Visit(e->getSubExpr()); | |||||
3327 | ||||||
3328 | default: | |||||
3329 | return ACC_invalid; | |||||
3330 | } | |||||
3331 | } | |||||
3332 | ||||||
3333 | /// Look through unary extension. | |||||
3334 | ACCResult VisitUnaryExtension(UnaryOperator *e) { | |||||
3335 | return Visit(e->getSubExpr()); | |||||
3336 | } | |||||
3337 | ||||||
3338 | /// Ignore the LHS of a comma operator. | |||||
3339 | ACCResult VisitBinComma(BinaryOperator *e) { | |||||
3340 | return Visit(e->getRHS()); | |||||
3341 | } | |||||
3342 | ||||||
3343 | /// Conditional operators are okay if both sides are okay. | |||||
3344 | ACCResult VisitConditionalOperator(ConditionalOperator *e) { | |||||
3345 | ACCResult left = Visit(e->getTrueExpr()); | |||||
3346 | if (left == ACC_invalid) return ACC_invalid; | |||||
3347 | return merge(left, Visit(e->getFalseExpr())); | |||||
3348 | } | |||||
3349 | ||||||
3350 | /// Look through pseudo-objects. | |||||
3351 | ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) { | |||||
3352 | // If we're getting here, we should always have a result. | |||||
3353 | return Visit(e->getResultExpr()); | |||||
3354 | } | |||||
3355 | ||||||
3356 | /// Statement expressions are okay if their result expression is okay. | |||||
3357 | ACCResult VisitStmtExpr(StmtExpr *e) { | |||||
3358 | return Visit(e->getSubStmt()->body_back()); | |||||
3359 | } | |||||
3360 | ||||||
3361 | /// Some declaration references are okay. | |||||
3362 | ACCResult VisitDeclRefExpr(DeclRefExpr *e) { | |||||
3363 | VarDecl *var = dyn_cast<VarDecl>(e->getDecl()); | |||||
3364 | // References to global constants are okay. | |||||
3365 | if (isAnyRetainable(TargetClass) && | |||||
3366 | isAnyRetainable(SourceClass) && | |||||
3367 | var && | |||||
3368 | !var->hasDefinition(Context) && | |||||
3369 | var->getType().isConstQualified()) { | |||||
3370 | ||||||
3371 | // In system headers, they can also be assumed to be immune to retains. | |||||
3372 | // These are things like 'kCFStringTransformToLatin'. | |||||
3373 | if (Context.getSourceManager().isInSystemHeader(var->getLocation())) | |||||
3374 | return ACC_bottom; | |||||
3375 | ||||||
3376 | return ACC_plusZero; | |||||
3377 | } | |||||
3378 | ||||||
3379 | // Nothing else. | |||||
3380 | return ACC_invalid; | |||||
3381 | } | |||||
3382 | ||||||
3383 | /// Some calls are okay. | |||||
3384 | ACCResult VisitCallExpr(CallExpr *e) { | |||||
3385 | if (FunctionDecl *fn = e->getDirectCallee()) | |||||
3386 | if (ACCResult result = checkCallToFunction(fn)) | |||||
3387 | return result; | |||||
3388 | ||||||
3389 | return super::VisitCallExpr(e); | |||||
3390 | } | |||||
3391 | ||||||
3392 | ACCResult checkCallToFunction(FunctionDecl *fn) { | |||||
3393 | // Require a CF*Ref return type. | |||||
3394 | if (!isCFType(fn->getReturnType())) | |||||
3395 | return ACC_invalid; | |||||
3396 | ||||||
3397 | if (!isAnyRetainable(TargetClass)) | |||||
3398 | return ACC_invalid; | |||||
3399 | ||||||
3400 | // Honor an explicit 'not retained' attribute. | |||||
3401 | if (fn->hasAttr<CFReturnsNotRetainedAttr>()) | |||||
3402 | return ACC_plusZero; | |||||
3403 | ||||||
3404 | // Honor an explicit 'retained' attribute, except that for | |||||
3405 | // now we're not going to permit implicit handling of +1 results, | |||||
3406 | // because it's a bit frightening. | |||||
3407 | if (fn->hasAttr<CFReturnsRetainedAttr>()) | |||||
3408 | return Diagnose ? ACC_plusOne | |||||
3409 | : ACC_invalid; // ACC_plusOne if we start accepting this | |||||
3410 | ||||||
3411 | // Recognize this specific builtin function, which is used by CFSTR. | |||||
3412 | unsigned builtinID = fn->getBuiltinID(); | |||||
3413 | if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString) | |||||
3414 | return ACC_bottom; | |||||
3415 | ||||||
3416 | // Otherwise, don't do anything implicit with an unaudited function. | |||||
3417 | if (!fn->hasAttr<CFAuditedTransferAttr>()) | |||||
3418 | return ACC_invalid; | |||||
3419 | ||||||
3420 | // Otherwise, it's +0 unless it follows the create convention. | |||||
3421 | if (ento::coreFoundation::followsCreateRule(fn)) | |||||
3422 | return Diagnose ? ACC_plusOne | |||||
3423 | : ACC_invalid; // ACC_plusOne if we start accepting this | |||||
3424 | ||||||
3425 | return ACC_plusZero; | |||||
3426 | } | |||||
3427 | ||||||
3428 | ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) { | |||||
3429 | return checkCallToMethod(e->getMethodDecl()); | |||||
3430 | } | |||||
3431 | ||||||
3432 | ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) { | |||||
3433 | ObjCMethodDecl *method; | |||||
3434 | if (e->isExplicitProperty()) | |||||
3435 | method = e->getExplicitProperty()->getGetterMethodDecl(); | |||||
3436 | else | |||||
3437 | method = e->getImplicitPropertyGetter(); | |||||
3438 | return checkCallToMethod(method); | |||||
3439 | } | |||||
3440 | ||||||
3441 | ACCResult checkCallToMethod(ObjCMethodDecl *method) { | |||||
3442 | if (!method) return ACC_invalid; | |||||
3443 | ||||||
3444 | // Check for message sends to functions returning CF types. We | |||||
3445 | // just obey the Cocoa conventions with these, even though the | |||||
3446 | // return type is CF. | |||||
3447 | if (!isAnyRetainable(TargetClass) || !isCFType(method->getReturnType())) | |||||
3448 | return ACC_invalid; | |||||
3449 | ||||||
3450 | // If the method is explicitly marked not-retained, it's +0. | |||||
3451 | if (method->hasAttr<CFReturnsNotRetainedAttr>()) | |||||
3452 | return ACC_plusZero; | |||||
3453 | ||||||
3454 | // If the method is explicitly marked as returning retained, or its | |||||
3455 | // selector follows a +1 Cocoa convention, treat it as +1. | |||||
3456 | if (method->hasAttr<CFReturnsRetainedAttr>()) | |||||
3457 | return ACC_plusOne; | |||||
3458 | ||||||
3459 | switch (method->getSelector().getMethodFamily()) { | |||||
3460 | case OMF_alloc: | |||||
3461 | case OMF_copy: | |||||
3462 | case OMF_mutableCopy: | |||||
3463 | case OMF_new: | |||||
3464 | return ACC_plusOne; | |||||
3465 | ||||||
3466 | default: | |||||
3467 | // Otherwise, treat it as +0. | |||||
3468 | return ACC_plusZero; | |||||
3469 | } | |||||
3470 | } | |||||
3471 | }; | |||||
3472 | } // end anonymous namespace | |||||
3473 | ||||||
3474 | bool Sema::isKnownName(StringRef name) { | |||||
3475 | if (name.empty()) | |||||
3476 | return false; | |||||
3477 | LookupResult R(*this, &Context.Idents.get(name), SourceLocation(), | |||||
3478 | Sema::LookupOrdinaryName); | |||||
3479 | return LookupName(R, TUScope, false); | |||||
3480 | } | |||||
3481 | ||||||
3482 | static void addFixitForObjCARCConversion(Sema &S, | |||||
3483 | DiagnosticBuilder &DiagB, | |||||
3484 | Sema::CheckedConversionKind CCK, | |||||
3485 | SourceLocation afterLParen, | |||||
3486 | QualType castType, | |||||
3487 | Expr *castExpr, | |||||
3488 | Expr *realCast, | |||||
3489 | const char *bridgeKeyword, | |||||
3490 | const char *CFBridgeName) { | |||||
3491 | // We handle C-style and implicit casts here. | |||||
3492 | switch (CCK) { | |||||
3493 | case Sema::CCK_ImplicitConversion: | |||||
3494 | case Sema::CCK_CStyleCast: | |||||
3495 | case Sema::CCK_OtherCast: | |||||
3496 | break; | |||||
3497 | case Sema::CCK_FunctionalCast: | |||||
3498 | return; | |||||
3499 | } | |||||
3500 | ||||||
3501 | if (CFBridgeName) { | |||||
3502 | if (CCK == Sema::CCK_OtherCast) { | |||||
3503 | if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) { | |||||
3504 | SourceRange range(NCE->getOperatorLoc(), | |||||
3505 | NCE->getAngleBrackets().getEnd()); | |||||
3506 | SmallString<32> BridgeCall; | |||||
3507 | ||||||
3508 | SourceManager &SM = S.getSourceManager(); | |||||
3509 | char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1)); | |||||
3510 | if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts())) | |||||
3511 | BridgeCall += ' '; | |||||
3512 | ||||||
3513 | BridgeCall += CFBridgeName; | |||||
3514 | DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall)); | |||||
3515 | } | |||||
3516 | return; | |||||
3517 | } | |||||
3518 | Expr *castedE = castExpr; | |||||
3519 | if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE)) | |||||
3520 | castedE = CCE->getSubExpr(); | |||||
3521 | castedE = castedE->IgnoreImpCasts(); | |||||
3522 | SourceRange range = castedE->getSourceRange(); | |||||
3523 | ||||||
3524 | SmallString<32> BridgeCall; | |||||
3525 | ||||||
3526 | SourceManager &SM = S.getSourceManager(); | |||||
3527 | char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1)); | |||||
3528 | if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts())) | |||||
3529 | BridgeCall += ' '; | |||||
3530 | ||||||
3531 | BridgeCall += CFBridgeName; | |||||
3532 | ||||||
3533 | if (isa<ParenExpr>(castedE)) { | |||||
3534 | DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), | |||||
3535 | BridgeCall)); | |||||
3536 | } else { | |||||
3537 | BridgeCall += '('; | |||||
3538 | DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), | |||||
3539 | BridgeCall)); | |||||
3540 | DiagB.AddFixItHint(FixItHint::CreateInsertion( | |||||
3541 | S.getLocForEndOfToken(range.getEnd()), | |||||
3542 | ")")); | |||||
3543 | } | |||||
3544 | return; | |||||
3545 | } | |||||
3546 | ||||||
3547 | if (CCK == Sema::CCK_CStyleCast) { | |||||
3548 | DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword)); | |||||
3549 | } else if (CCK == Sema::CCK_OtherCast) { | |||||
3550 | if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) { | |||||
3551 | std::string castCode = "("; | |||||
3552 | castCode += bridgeKeyword; | |||||
3553 | castCode += castType.getAsString(); | |||||
3554 | castCode += ")"; | |||||
3555 | SourceRange Range(NCE->getOperatorLoc(), | |||||
3556 | NCE->getAngleBrackets().getEnd()); | |||||
3557 | DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode)); | |||||
3558 | } | |||||
3559 | } else { | |||||
3560 | std::string castCode = "("; | |||||
3561 | castCode += bridgeKeyword; | |||||
3562 | castCode += castType.getAsString(); | |||||
3563 | castCode += ")"; | |||||
3564 | Expr *castedE = castExpr->IgnoreImpCasts(); | |||||
3565 | SourceRange range = castedE->getSourceRange(); | |||||
3566 | if (isa<ParenExpr>(castedE)) { | |||||
3567 | DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), | |||||
3568 | castCode)); | |||||
3569 | } else { | |||||
3570 | castCode += "("; | |||||
3571 | DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(), | |||||
3572 | castCode)); | |||||
3573 | DiagB.AddFixItHint(FixItHint::CreateInsertion( | |||||
3574 | S.getLocForEndOfToken(range.getEnd()), | |||||
3575 | ")")); | |||||
3576 | } | |||||
3577 | } | |||||
3578 | } | |||||
3579 | ||||||
3580 | template <typename T> | |||||
3581 | static inline T *getObjCBridgeAttr(const TypedefType *TD) { | |||||
3582 | TypedefNameDecl *TDNDecl = TD->getDecl(); | |||||
3583 | QualType QT = TDNDecl->getUnderlyingType(); | |||||
3584 | if (QT->isPointerType()) { | |||||
3585 | QT = QT->getPointeeType(); | |||||
3586 | if (const RecordType *RT = QT->getAs<RecordType>()) | |||||
3587 | if (RecordDecl *RD = RT->getDecl()->getMostRecentDecl()) | |||||
3588 | return RD->getAttr<T>(); | |||||
3589 | } | |||||
3590 | return nullptr; | |||||
3591 | } | |||||
3592 | ||||||
3593 | static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T, | |||||
3594 | TypedefNameDecl *&TDNDecl) { | |||||
3595 | while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { | |||||
3596 | TDNDecl = TD->getDecl(); | |||||
3597 | if (ObjCBridgeRelatedAttr *ObjCBAttr = | |||||
3598 | getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD)) | |||||
3599 | return ObjCBAttr; | |||||
3600 | T = TDNDecl->getUnderlyingType(); | |||||
3601 | } | |||||
3602 | return nullptr; | |||||
3603 | } | |||||
3604 | ||||||
3605 | static void | |||||
3606 | diagnoseObjCARCConversion(Sema &S, SourceRange castRange, | |||||
3607 | QualType castType, ARCConversionTypeClass castACTC, | |||||
3608 | Expr *castExpr, Expr *realCast, | |||||
3609 | ARCConversionTypeClass exprACTC, | |||||
3610 | Sema::CheckedConversionKind CCK) { | |||||
3611 | SourceLocation loc = | |||||
3612 | (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); | |||||
3613 | ||||||
3614 | if (S.makeUnavailableInSystemHeader(loc, | |||||
3615 | UnavailableAttr::IR_ARCForbiddenConversion)) | |||||
3616 | return; | |||||
3617 | ||||||
3618 | QualType castExprType = castExpr->getType(); | |||||
3619 | // Defer emitting a diagnostic for bridge-related casts; that will be | |||||
3620 | // handled by CheckObjCBridgeRelatedConversions. | |||||
3621 | TypedefNameDecl *TDNDecl = nullptr; | |||||
3622 | if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable && | |||||
3623 | ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) || | |||||
3624 | (exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable && | |||||
3625 | ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl))) | |||||
3626 | return; | |||||
3627 | ||||||
3628 | unsigned srcKind = 0; | |||||
3629 | switch (exprACTC) { | |||||
3630 | case ACTC_none: | |||||
3631 | case ACTC_coreFoundation: | |||||
3632 | case ACTC_voidPtr: | |||||
3633 | srcKind = (castExprType->isPointerType() ? 1 : 0); | |||||
3634 | break; | |||||
3635 | case ACTC_retainable: | |||||
3636 | srcKind = (castExprType->isBlockPointerType() ? 2 : 3); | |||||
3637 | break; | |||||
3638 | case ACTC_indirectRetainable: | |||||
3639 | srcKind = 4; | |||||
3640 | break; | |||||
3641 | } | |||||
3642 | ||||||
3643 | // Check whether this could be fixed with a bridge cast. | |||||
3644 | SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin()); | |||||
3645 | SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc; | |||||
3646 | ||||||
3647 | // Bridge from an ARC type to a CF type. | |||||
3648 | if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) { | |||||
3649 | ||||||
3650 | S.Diag(loc, diag::err_arc_cast_requires_bridge) | |||||
3651 | << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit | |||||
3652 | << 2 // of C pointer type | |||||
3653 | << castExprType | |||||
3654 | << unsigned(castType->isBlockPointerType()) // to ObjC|block type | |||||
3655 | << castType | |||||
3656 | << castRange | |||||
3657 | << castExpr->getSourceRange(); | |||||
3658 | bool br = S.isKnownName("CFBridgingRelease"); | |||||
3659 | ACCResult CreateRule = | |||||
3660 | ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr); | |||||
3661 | assert(CreateRule != ACC_bottom && "This cast should already be accepted.")(static_cast <bool> (CreateRule != ACC_bottom && "This cast should already be accepted.") ? void (0) : __assert_fail ("CreateRule != ACC_bottom && \"This cast should already be accepted.\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 3661, __extension__ __PRETTY_FUNCTION__)); | |||||
3662 | if (CreateRule != ACC_plusOne) | |||||
3663 | { | |||||
3664 | DiagnosticBuilder DiagB = | |||||
3665 | (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) | |||||
3666 | : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); | |||||
3667 | ||||||
3668 | addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, | |||||
3669 | castType, castExpr, realCast, "__bridge ", | |||||
3670 | nullptr); | |||||
3671 | } | |||||
3672 | if (CreateRule != ACC_plusZero) | |||||
3673 | { | |||||
3674 | DiagnosticBuilder DiagB = | |||||
3675 | (CCK == Sema::CCK_OtherCast && !br) ? | |||||
3676 | S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType : | |||||
3677 | S.Diag(br ? castExpr->getExprLoc() : noteLoc, | |||||
3678 | diag::note_arc_bridge_transfer) | |||||
3679 | << castExprType << br; | |||||
3680 | ||||||
3681 | addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, | |||||
3682 | castType, castExpr, realCast, "__bridge_transfer ", | |||||
3683 | br ? "CFBridgingRelease" : nullptr); | |||||
3684 | } | |||||
3685 | ||||||
3686 | return; | |||||
3687 | } | |||||
3688 | ||||||
3689 | // Bridge from a CF type to an ARC type. | |||||
3690 | if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) { | |||||
3691 | bool br = S.isKnownName("CFBridgingRetain"); | |||||
3692 | S.Diag(loc, diag::err_arc_cast_requires_bridge) | |||||
3693 | << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit | |||||
3694 | << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type | |||||
3695 | << castExprType | |||||
3696 | << 2 // to C pointer type | |||||
3697 | << castType | |||||
3698 | << castRange | |||||
3699 | << castExpr->getSourceRange(); | |||||
3700 | ACCResult CreateRule = | |||||
3701 | ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr); | |||||
3702 | assert(CreateRule != ACC_bottom && "This cast should already be accepted.")(static_cast <bool> (CreateRule != ACC_bottom && "This cast should already be accepted.") ? void (0) : __assert_fail ("CreateRule != ACC_bottom && \"This cast should already be accepted.\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 3702, __extension__ __PRETTY_FUNCTION__)); | |||||
3703 | if (CreateRule != ACC_plusOne) | |||||
3704 | { | |||||
3705 | DiagnosticBuilder DiagB = | |||||
3706 | (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) | |||||
3707 | : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); | |||||
3708 | addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, | |||||
3709 | castType, castExpr, realCast, "__bridge ", | |||||
3710 | nullptr); | |||||
3711 | } | |||||
3712 | if (CreateRule != ACC_plusZero) | |||||
3713 | { | |||||
3714 | DiagnosticBuilder DiagB = | |||||
3715 | (CCK == Sema::CCK_OtherCast && !br) ? | |||||
3716 | S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType : | |||||
3717 | S.Diag(br ? castExpr->getExprLoc() : noteLoc, | |||||
3718 | diag::note_arc_bridge_retained) | |||||
3719 | << castType << br; | |||||
3720 | ||||||
3721 | addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, | |||||
3722 | castType, castExpr, realCast, "__bridge_retained ", | |||||
3723 | br ? "CFBridgingRetain" : nullptr); | |||||
3724 | } | |||||
3725 | ||||||
3726 | return; | |||||
3727 | } | |||||
3728 | ||||||
3729 | S.Diag(loc, diag::err_arc_mismatched_cast) | |||||
3730 | << (CCK != Sema::CCK_ImplicitConversion) | |||||
3731 | << srcKind << castExprType << castType | |||||
3732 | << castRange << castExpr->getSourceRange(); | |||||
3733 | } | |||||
3734 | ||||||
3735 | template <typename TB> | |||||
3736 | static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr, | |||||
3737 | bool &HadTheAttribute, bool warn) { | |||||
3738 | QualType T = castExpr->getType(); | |||||
3739 | HadTheAttribute = false; | |||||
3740 | while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { | |||||
3741 | TypedefNameDecl *TDNDecl = TD->getDecl(); | |||||
3742 | if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) { | |||||
3743 | if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) { | |||||
3744 | HadTheAttribute = true; | |||||
3745 | if (Parm->isStr("id")) | |||||
3746 | return true; | |||||
3747 | ||||||
3748 | NamedDecl *Target = nullptr; | |||||
3749 | // Check for an existing type with this name. | |||||
3750 | LookupResult R(S, DeclarationName(Parm), SourceLocation(), | |||||
3751 | Sema::LookupOrdinaryName); | |||||
3752 | if (S.LookupName(R, S.TUScope)) { | |||||
3753 | Target = R.getFoundDecl(); | |||||
3754 | if (Target && isa<ObjCInterfaceDecl>(Target)) { | |||||
3755 | ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target); | |||||
3756 | if (const ObjCObjectPointerType *InterfacePointerType = | |||||
3757 | castType->getAsObjCInterfacePointerType()) { | |||||
3758 | ObjCInterfaceDecl *CastClass | |||||
3759 | = InterfacePointerType->getObjectType()->getInterface(); | |||||
3760 | if ((CastClass == ExprClass) || | |||||
3761 | (CastClass && CastClass->isSuperClassOf(ExprClass))) | |||||
3762 | return true; | |||||
3763 | if (warn) | |||||
3764 | S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) | |||||
3765 | << T << Target->getName() << castType->getPointeeType(); | |||||
3766 | return false; | |||||
3767 | } else if (castType->isObjCIdType() || | |||||
3768 | (S.Context.ObjCObjectAdoptsQTypeProtocols( | |||||
3769 | castType, ExprClass))) | |||||
3770 | // ok to cast to 'id'. | |||||
3771 | // casting to id<p-list> is ok if bridge type adopts all of | |||||
3772 | // p-list protocols. | |||||
3773 | return true; | |||||
3774 | else { | |||||
3775 | if (warn) { | |||||
3776 | S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) | |||||
3777 | << T << Target->getName() << castType; | |||||
3778 | S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
3779 | S.Diag(Target->getLocStart(), diag::note_declared_at); | |||||
3780 | } | |||||
3781 | return false; | |||||
3782 | } | |||||
3783 | } | |||||
3784 | } else if (!castType->isObjCIdType()) { | |||||
3785 | S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface) | |||||
3786 | << castExpr->getType() << Parm; | |||||
3787 | S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
3788 | if (Target) | |||||
3789 | S.Diag(Target->getLocStart(), diag::note_declared_at); | |||||
3790 | } | |||||
3791 | return true; | |||||
3792 | } | |||||
3793 | return false; | |||||
3794 | } | |||||
3795 | T = TDNDecl->getUnderlyingType(); | |||||
3796 | } | |||||
3797 | return true; | |||||
3798 | } | |||||
3799 | ||||||
3800 | template <typename TB> | |||||
3801 | static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr, | |||||
3802 | bool &HadTheAttribute, bool warn) { | |||||
3803 | QualType T = castType; | |||||
3804 | HadTheAttribute = false; | |||||
3805 | while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) { | |||||
3806 | TypedefNameDecl *TDNDecl = TD->getDecl(); | |||||
3807 | if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) { | |||||
3808 | if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) { | |||||
3809 | HadTheAttribute = true; | |||||
3810 | if (Parm->isStr("id")) | |||||
3811 | return true; | |||||
3812 | ||||||
3813 | NamedDecl *Target = nullptr; | |||||
3814 | // Check for an existing type with this name. | |||||
3815 | LookupResult R(S, DeclarationName(Parm), SourceLocation(), | |||||
3816 | Sema::LookupOrdinaryName); | |||||
3817 | if (S.LookupName(R, S.TUScope)) { | |||||
3818 | Target = R.getFoundDecl(); | |||||
3819 | if (Target && isa<ObjCInterfaceDecl>(Target)) { | |||||
3820 | ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target); | |||||
3821 | if (const ObjCObjectPointerType *InterfacePointerType = | |||||
3822 | castExpr->getType()->getAsObjCInterfacePointerType()) { | |||||
3823 | ObjCInterfaceDecl *ExprClass | |||||
3824 | = InterfacePointerType->getObjectType()->getInterface(); | |||||
3825 | if ((CastClass == ExprClass) || | |||||
3826 | (ExprClass && CastClass->isSuperClassOf(ExprClass))) | |||||
3827 | return true; | |||||
3828 | if (warn) { | |||||
3829 | S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) | |||||
3830 | << castExpr->getType()->getPointeeType() << T; | |||||
3831 | S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
3832 | } | |||||
3833 | return false; | |||||
3834 | } else if (castExpr->getType()->isObjCIdType() || | |||||
3835 | (S.Context.QIdProtocolsAdoptObjCObjectProtocols( | |||||
3836 | castExpr->getType(), CastClass))) | |||||
3837 | // ok to cast an 'id' expression to a CFtype. | |||||
3838 | // ok to cast an 'id<plist>' expression to CFtype provided plist | |||||
3839 | // adopts all of CFtype's ObjetiveC's class plist. | |||||
3840 | return true; | |||||
3841 | else { | |||||
3842 | if (warn) { | |||||
3843 | S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf) | |||||
3844 | << castExpr->getType() << castType; | |||||
3845 | S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
3846 | S.Diag(Target->getLocStart(), diag::note_declared_at); | |||||
3847 | } | |||||
3848 | return false; | |||||
3849 | } | |||||
3850 | } | |||||
3851 | } | |||||
3852 | S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject) | |||||
3853 | << castExpr->getType() << castType; | |||||
3854 | S.Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
3855 | if (Target) | |||||
3856 | S.Diag(Target->getLocStart(), diag::note_declared_at); | |||||
3857 | return true; | |||||
3858 | } | |||||
3859 | return false; | |||||
3860 | } | |||||
3861 | T = TDNDecl->getUnderlyingType(); | |||||
3862 | } | |||||
3863 | return true; | |||||
3864 | } | |||||
3865 | ||||||
3866 | void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) { | |||||
3867 | if (!getLangOpts().ObjC1) | |||||
3868 | return; | |||||
3869 | // warn in presence of __bridge casting to or from a toll free bridge cast. | |||||
3870 | ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType()); | |||||
3871 | ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType); | |||||
3872 | if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) { | |||||
3873 | bool HasObjCBridgeAttr; | |||||
3874 | bool ObjCBridgeAttrWillNotWarn = | |||||
3875 | CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, | |||||
3876 | false); | |||||
3877 | if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr) | |||||
3878 | return; | |||||
3879 | bool HasObjCBridgeMutableAttr; | |||||
3880 | bool ObjCBridgeMutableAttrWillNotWarn = | |||||
3881 | CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, | |||||
3882 | HasObjCBridgeMutableAttr, false); | |||||
3883 | if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr) | |||||
3884 | return; | |||||
3885 | ||||||
3886 | if (HasObjCBridgeAttr) | |||||
3887 | CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, | |||||
3888 | true); | |||||
3889 | else if (HasObjCBridgeMutableAttr) | |||||
3890 | CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, | |||||
3891 | HasObjCBridgeMutableAttr, true); | |||||
3892 | } | |||||
3893 | else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) { | |||||
3894 | bool HasObjCBridgeAttr; | |||||
3895 | bool ObjCBridgeAttrWillNotWarn = | |||||
3896 | CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, | |||||
3897 | false); | |||||
3898 | if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr) | |||||
3899 | return; | |||||
3900 | bool HasObjCBridgeMutableAttr; | |||||
3901 | bool ObjCBridgeMutableAttrWillNotWarn = | |||||
3902 | CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, | |||||
3903 | HasObjCBridgeMutableAttr, false); | |||||
3904 | if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr) | |||||
3905 | return; | |||||
3906 | ||||||
3907 | if (HasObjCBridgeAttr) | |||||
3908 | CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr, HasObjCBridgeAttr, | |||||
3909 | true); | |||||
3910 | else if (HasObjCBridgeMutableAttr) | |||||
3911 | CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr, | |||||
3912 | HasObjCBridgeMutableAttr, true); | |||||
3913 | } | |||||
3914 | } | |||||
3915 | ||||||
3916 | void Sema::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) { | |||||
3917 | QualType SrcType = castExpr->getType(); | |||||
3918 | if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(castExpr)) { | |||||
3919 | if (PRE->isExplicitProperty()) { | |||||
3920 | if (ObjCPropertyDecl *PDecl = PRE->getExplicitProperty()) | |||||
3921 | SrcType = PDecl->getType(); | |||||
3922 | } | |||||
3923 | else if (PRE->isImplicitProperty()) { | |||||
3924 | if (ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) | |||||
3925 | SrcType = Getter->getReturnType(); | |||||
3926 | } | |||||
3927 | } | |||||
3928 | ||||||
3929 | ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(SrcType); | |||||
3930 | ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(castType); | |||||
3931 | if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation) | |||||
3932 | return; | |||||
3933 | CheckObjCBridgeRelatedConversions(castExpr->getLocStart(), | |||||
3934 | castType, SrcType, castExpr); | |||||
3935 | } | |||||
3936 | ||||||
3937 | bool Sema::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, | |||||
3938 | CastKind &Kind) { | |||||
3939 | if (!getLangOpts().ObjC1) | |||||
3940 | return false; | |||||
3941 | ARCConversionTypeClass exprACTC = | |||||
3942 | classifyTypeForARCConversion(castExpr->getType()); | |||||
3943 | ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType); | |||||
3944 | if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) || | |||||
3945 | (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) { | |||||
3946 | CheckTollFreeBridgeCast(castType, castExpr); | |||||
3947 | Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast | |||||
3948 | : CK_CPointerToObjCPointerCast; | |||||
3949 | return true; | |||||
3950 | } | |||||
3951 | return false; | |||||
3952 | } | |||||
3953 | ||||||
3954 | bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, | |||||
3955 | QualType DestType, QualType SrcType, | |||||
3956 | ObjCInterfaceDecl *&RelatedClass, | |||||
3957 | ObjCMethodDecl *&ClassMethod, | |||||
3958 | ObjCMethodDecl *&InstanceMethod, | |||||
3959 | TypedefNameDecl *&TDNDecl, | |||||
3960 | bool CfToNs, bool Diagnose) { | |||||
3961 | QualType T = CfToNs ? SrcType : DestType; | |||||
3962 | ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl); | |||||
3963 | if (!ObjCBAttr) | |||||
3964 | return false; | |||||
3965 | ||||||
3966 | IdentifierInfo *RCId = ObjCBAttr->getRelatedClass(); | |||||
3967 | IdentifierInfo *CMId = ObjCBAttr->getClassMethod(); | |||||
3968 | IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod(); | |||||
3969 | if (!RCId) | |||||
3970 | return false; | |||||
3971 | NamedDecl *Target = nullptr; | |||||
3972 | // Check for an existing type with this name. | |||||
3973 | LookupResult R(*this, DeclarationName(RCId), SourceLocation(), | |||||
3974 | Sema::LookupOrdinaryName); | |||||
3975 | if (!LookupName(R, TUScope)) { | |||||
3976 | if (Diagnose) { | |||||
3977 | Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId | |||||
3978 | << SrcType << DestType; | |||||
3979 | Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
3980 | } | |||||
3981 | return false; | |||||
3982 | } | |||||
3983 | Target = R.getFoundDecl(); | |||||
3984 | if (Target && isa<ObjCInterfaceDecl>(Target)) | |||||
3985 | RelatedClass = cast<ObjCInterfaceDecl>(Target); | |||||
3986 | else { | |||||
3987 | if (Diagnose) { | |||||
3988 | Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId | |||||
3989 | << SrcType << DestType; | |||||
3990 | Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
3991 | if (Target) | |||||
3992 | Diag(Target->getLocStart(), diag::note_declared_at); | |||||
3993 | } | |||||
3994 | return false; | |||||
3995 | } | |||||
3996 | ||||||
3997 | // Check for an existing class method with the given selector name. | |||||
3998 | if (CfToNs && CMId) { | |||||
3999 | Selector Sel = Context.Selectors.getUnarySelector(CMId); | |||||
4000 | ClassMethod = RelatedClass->lookupMethod(Sel, false); | |||||
4001 | if (!ClassMethod) { | |||||
4002 | if (Diagnose) { | |||||
4003 | Diag(Loc, diag::err_objc_bridged_related_known_method) | |||||
4004 | << SrcType << DestType << Sel << false; | |||||
4005 | Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
4006 | } | |||||
4007 | return false; | |||||
4008 | } | |||||
4009 | } | |||||
4010 | ||||||
4011 | // Check for an existing instance method with the given selector name. | |||||
4012 | if (!CfToNs && IMId) { | |||||
4013 | Selector Sel = Context.Selectors.getNullarySelector(IMId); | |||||
4014 | InstanceMethod = RelatedClass->lookupMethod(Sel, true); | |||||
4015 | if (!InstanceMethod) { | |||||
4016 | if (Diagnose) { | |||||
4017 | Diag(Loc, diag::err_objc_bridged_related_known_method) | |||||
4018 | << SrcType << DestType << Sel << true; | |||||
4019 | Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
4020 | } | |||||
4021 | return false; | |||||
4022 | } | |||||
4023 | } | |||||
4024 | return true; | |||||
4025 | } | |||||
4026 | ||||||
4027 | bool | |||||
4028 | Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, | |||||
4029 | QualType DestType, QualType SrcType, | |||||
4030 | Expr *&SrcExpr, bool Diagnose) { | |||||
4031 | ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType); | |||||
4032 | ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType); | |||||
4033 | bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable); | |||||
4034 | bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation); | |||||
4035 | if (!CfToNs && !NsToCf) | |||||
4036 | return false; | |||||
4037 | ||||||
4038 | ObjCInterfaceDecl *RelatedClass; | |||||
4039 | ObjCMethodDecl *ClassMethod = nullptr; | |||||
4040 | ObjCMethodDecl *InstanceMethod = nullptr; | |||||
4041 | TypedefNameDecl *TDNDecl = nullptr; | |||||
4042 | if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass, | |||||
4043 | ClassMethod, InstanceMethod, TDNDecl, | |||||
4044 | CfToNs, Diagnose)) | |||||
4045 | return false; | |||||
4046 | ||||||
4047 | if (CfToNs) { | |||||
4048 | // Implicit conversion from CF to ObjC object is needed. | |||||
4049 | if (ClassMethod) { | |||||
4050 | if (Diagnose) { | |||||
4051 | std::string ExpressionString = "["; | |||||
4052 | ExpressionString += RelatedClass->getNameAsString(); | |||||
4053 | ExpressionString += " "; | |||||
4054 | ExpressionString += ClassMethod->getSelector().getAsString(); | |||||
4055 | SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd()); | |||||
4056 | // Provide a fixit: [RelatedClass ClassMethod SrcExpr] | |||||
4057 | Diag(Loc, diag::err_objc_bridged_related_known_method) | |||||
4058 | << SrcType << DestType << ClassMethod->getSelector() << false | |||||
4059 | << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString) | |||||
4060 | << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); | |||||
4061 | Diag(RelatedClass->getLocStart(), diag::note_declared_at); | |||||
4062 | Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
4063 | ||||||
4064 | QualType receiverType = Context.getObjCInterfaceType(RelatedClass); | |||||
4065 | // Argument. | |||||
4066 | Expr *args[] = { SrcExpr }; | |||||
4067 | ExprResult msg = BuildClassMessageImplicit(receiverType, false, | |||||
4068 | ClassMethod->getLocation(), | |||||
4069 | ClassMethod->getSelector(), ClassMethod, | |||||
4070 | MultiExprArg(args, 1)); | |||||
4071 | SrcExpr = msg.get(); | |||||
4072 | } | |||||
4073 | return true; | |||||
4074 | } | |||||
4075 | } | |||||
4076 | else { | |||||
4077 | // Implicit conversion from ObjC type to CF object is needed. | |||||
4078 | if (InstanceMethod) { | |||||
4079 | if (Diagnose) { | |||||
4080 | std::string ExpressionString; | |||||
4081 | SourceLocation SrcExprEndLoc = | |||||
4082 | getLocForEndOfToken(SrcExpr->getLocEnd()); | |||||
4083 | if (InstanceMethod->isPropertyAccessor()) | |||||
4084 | if (const ObjCPropertyDecl *PDecl = | |||||
4085 | InstanceMethod->findPropertyDecl()) { | |||||
4086 | // fixit: ObjectExpr.propertyname when it is aproperty accessor. | |||||
4087 | ExpressionString = "."; | |||||
4088 | ExpressionString += PDecl->getNameAsString(); | |||||
4089 | Diag(Loc, diag::err_objc_bridged_related_known_method) | |||||
4090 | << SrcType << DestType << InstanceMethod->getSelector() << true | |||||
4091 | << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); | |||||
4092 | } | |||||
4093 | if (ExpressionString.empty()) { | |||||
4094 | // Provide a fixit: [ObjectExpr InstanceMethod] | |||||
4095 | ExpressionString = " "; | |||||
4096 | ExpressionString += InstanceMethod->getSelector().getAsString(); | |||||
4097 | ExpressionString += "]"; | |||||
4098 | ||||||
4099 | Diag(Loc, diag::err_objc_bridged_related_known_method) | |||||
4100 | << SrcType << DestType << InstanceMethod->getSelector() << true | |||||
4101 | << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[") | |||||
4102 | << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); | |||||
4103 | } | |||||
4104 | Diag(RelatedClass->getLocStart(), diag::note_declared_at); | |||||
4105 | Diag(TDNDecl->getLocStart(), diag::note_declared_at); | |||||
4106 | ||||||
4107 | ExprResult msg = | |||||
4108 | BuildInstanceMessageImplicit(SrcExpr, SrcType, | |||||
4109 | InstanceMethod->getLocation(), | |||||
4110 | InstanceMethod->getSelector(), | |||||
4111 | InstanceMethod, None); | |||||
4112 | SrcExpr = msg.get(); | |||||
4113 | } | |||||
4114 | return true; | |||||
4115 | } | |||||
4116 | } | |||||
4117 | return false; | |||||
4118 | } | |||||
4119 | ||||||
4120 | Sema::ARCConversionResult | |||||
4121 | Sema::CheckObjCConversion(SourceRange castRange, QualType castType, | |||||
4122 | Expr *&castExpr, CheckedConversionKind CCK, | |||||
4123 | bool Diagnose, bool DiagnoseCFAudited, | |||||
4124 | BinaryOperatorKind Opc) { | |||||
4125 | QualType castExprType = castExpr->getType(); | |||||
4126 | ||||||
4127 | // For the purposes of the classification, we assume reference types | |||||
4128 | // will bind to temporaries. | |||||
4129 | QualType effCastType = castType; | |||||
4130 | if (const ReferenceType *ref = castType->getAs<ReferenceType>()) | |||||
4131 | effCastType = ref->getPointeeType(); | |||||
4132 | ||||||
4133 | ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType); | |||||
4134 | ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType); | |||||
4135 | if (exprACTC == castACTC) { | |||||
4136 | // Check for viability and report error if casting an rvalue to a | |||||
4137 | // life-time qualifier. | |||||
4138 | if (castACTC == ACTC_retainable && | |||||
4139 | (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) && | |||||
4140 | castType != castExprType) { | |||||
4141 | const Type *DT = castType.getTypePtr(); | |||||
4142 | QualType QDT = castType; | |||||
4143 | // We desugar some types but not others. We ignore those | |||||
4144 | // that cannot happen in a cast; i.e. auto, and those which | |||||
4145 | // should not be de-sugared; i.e typedef. | |||||
4146 | if (const ParenType *PT = dyn_cast<ParenType>(DT)) | |||||
4147 | QDT = PT->desugar(); | |||||
4148 | else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT)) | |||||
4149 | QDT = TP->desugar(); | |||||
4150 | else if (const AttributedType *AT = dyn_cast<AttributedType>(DT)) | |||||
4151 | QDT = AT->desugar(); | |||||
4152 | if (QDT != castType && | |||||
4153 | QDT.getObjCLifetime() != Qualifiers::OCL_None) { | |||||
4154 | if (Diagnose) { | |||||
4155 | SourceLocation loc = (castRange.isValid() ? castRange.getBegin() | |||||
4156 | : castExpr->getExprLoc()); | |||||
4157 | Diag(loc, diag::err_arc_nolifetime_behavior); | |||||
4158 | } | |||||
4159 | return ACR_error; | |||||
4160 | } | |||||
4161 | } | |||||
4162 | return ACR_okay; | |||||
4163 | } | |||||
4164 | ||||||
4165 | // The life-time qualifier cast check above is all we need for ObjCWeak. | |||||
4166 | // ObjCAutoRefCount has more restrictions on what is legal. | |||||
4167 | if (!getLangOpts().ObjCAutoRefCount) | |||||
4168 | return ACR_okay; | |||||
4169 | ||||||
4170 | if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; | |||||
4171 | ||||||
4172 | // Allow all of these types to be cast to integer types (but not | |||||
4173 | // vice-versa). | |||||
4174 | if (castACTC == ACTC_none && castType->isIntegralType(Context)) | |||||
4175 | return ACR_okay; | |||||
4176 | ||||||
4177 | // Allow casts between pointers to lifetime types (e.g., __strong id*) | |||||
4178 | // and pointers to void (e.g., cv void *). Casting from void* to lifetime* | |||||
4179 | // must be explicit. | |||||
4180 | if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr) | |||||
4181 | return ACR_okay; | |||||
4182 | if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr && | |||||
4183 | CCK != CCK_ImplicitConversion) | |||||
4184 | return ACR_okay; | |||||
4185 | ||||||
4186 | switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) { | |||||
4187 | // For invalid casts, fall through. | |||||
4188 | case ACC_invalid: | |||||
4189 | break; | |||||
4190 | ||||||
4191 | // Do nothing for both bottom and +0. | |||||
4192 | case ACC_bottom: | |||||
4193 | case ACC_plusZero: | |||||
4194 | return ACR_okay; | |||||
4195 | ||||||
4196 | // If the result is +1, consume it here. | |||||
4197 | case ACC_plusOne: | |||||
4198 | castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), | |||||
4199 | CK_ARCConsumeObject, castExpr, | |||||
4200 | nullptr, VK_RValue); | |||||
4201 | Cleanup.setExprNeedsCleanups(true); | |||||
4202 | return ACR_okay; | |||||
4203 | } | |||||
4204 | ||||||
4205 | // If this is a non-implicit cast from id or block type to a | |||||
4206 | // CoreFoundation type, delay complaining in case the cast is used | |||||
4207 | // in an acceptable context. | |||||
4208 | if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) && | |||||
4209 | CCK != CCK_ImplicitConversion) | |||||
4210 | return ACR_unbridged; | |||||
4211 | ||||||
4212 | // Issue a diagnostic about a missing @-sign when implicit casting a cstring | |||||
4213 | // to 'NSString *', instead of falling through to report a "bridge cast" | |||||
4214 | // diagnostic. | |||||
4215 | if (castACTC == ACTC_retainable && exprACTC == ACTC_none && | |||||
4216 | ConversionToObjCStringLiteralCheck(castType, castExpr, Diagnose)) | |||||
4217 | return ACR_error; | |||||
4218 | ||||||
4219 | // Do not issue "bridge cast" diagnostic when implicit casting | |||||
4220 | // a retainable object to a CF type parameter belonging to an audited | |||||
4221 | // CF API function. Let caller issue a normal type mismatched diagnostic | |||||
4222 | // instead. | |||||
4223 | if ((!DiagnoseCFAudited || exprACTC != ACTC_retainable || | |||||
4224 | castACTC != ACTC_coreFoundation) && | |||||
4225 | !(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable && | |||||
4226 | (Opc == BO_NE || Opc == BO_EQ))) { | |||||
4227 | if (Diagnose) | |||||
4228 | diagnoseObjCARCConversion(*this, castRange, castType, castACTC, castExpr, | |||||
4229 | castExpr, exprACTC, CCK); | |||||
4230 | return ACR_error; | |||||
4231 | } | |||||
4232 | return ACR_okay; | |||||
4233 | } | |||||
4234 | ||||||
4235 | /// Given that we saw an expression with the ARCUnbridgedCastTy | |||||
4236 | /// placeholder type, complain bitterly. | |||||
4237 | void Sema::diagnoseARCUnbridgedCast(Expr *e) { | |||||
4238 | // We expect the spurious ImplicitCastExpr to already have been stripped. | |||||
4239 | assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast))(static_cast <bool> (!e->hasPlaceholderType(BuiltinType ::ARCUnbridgedCast)) ? void (0) : __assert_fail ("!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 4239, __extension__ __PRETTY_FUNCTION__)); | |||||
4240 | CastExpr *realCast = cast<CastExpr>(e->IgnoreParens()); | |||||
4241 | ||||||
4242 | SourceRange castRange; | |||||
4243 | QualType castType; | |||||
4244 | CheckedConversionKind CCK; | |||||
4245 | ||||||
4246 | if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) { | |||||
4247 | castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc()); | |||||
4248 | castType = cast->getTypeAsWritten(); | |||||
4249 | CCK = CCK_CStyleCast; | |||||
4250 | } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) { | |||||
4251 | castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(); | |||||
4252 | castType = cast->getTypeAsWritten(); | |||||
4253 | CCK = CCK_OtherCast; | |||||
4254 | } else { | |||||
4255 | llvm_unreachable("Unexpected ImplicitCastExpr")::llvm::llvm_unreachable_internal("Unexpected ImplicitCastExpr" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 4255); | |||||
4256 | } | |||||
4257 | ||||||
4258 | ARCConversionTypeClass castACTC = | |||||
4259 | classifyTypeForARCConversion(castType.getNonReferenceType()); | |||||
4260 | ||||||
4261 | Expr *castExpr = realCast->getSubExpr(); | |||||
4262 | assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable)(static_cast <bool> (classifyTypeForARCConversion(castExpr ->getType()) == ACTC_retainable) ? void (0) : __assert_fail ("classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 4262, __extension__ __PRETTY_FUNCTION__)); | |||||
4263 | ||||||
4264 | diagnoseObjCARCConversion(*this, castRange, castType, castACTC, | |||||
4265 | castExpr, realCast, ACTC_retainable, CCK); | |||||
4266 | } | |||||
4267 | ||||||
4268 | /// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast | |||||
4269 | /// type, remove the placeholder cast. | |||||
4270 | Expr *Sema::stripARCUnbridgedCast(Expr *e) { | |||||
4271 | assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast))(static_cast <bool> (e->hasPlaceholderType(BuiltinType ::ARCUnbridgedCast)) ? void (0) : __assert_fail ("e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast)" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 4271, __extension__ __PRETTY_FUNCTION__)); | |||||
4272 | ||||||
4273 | if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) { | |||||
4274 | Expr *sub = stripARCUnbridgedCast(pe->getSubExpr()); | |||||
4275 | return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub); | |||||
4276 | } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) { | |||||
4277 | assert(uo->getOpcode() == UO_Extension)(static_cast <bool> (uo->getOpcode() == UO_Extension ) ? void (0) : __assert_fail ("uo->getOpcode() == UO_Extension" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 4277, __extension__ __PRETTY_FUNCTION__)); | |||||
4278 | Expr *sub = stripARCUnbridgedCast(uo->getSubExpr()); | |||||
4279 | return new (Context) | |||||
4280 | UnaryOperator(sub, UO_Extension, sub->getType(), sub->getValueKind(), | |||||
4281 | sub->getObjectKind(), uo->getOperatorLoc(), false); | |||||
4282 | } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { | |||||
4283 | assert(!gse->isResultDependent())(static_cast <bool> (!gse->isResultDependent()) ? void (0) : __assert_fail ("!gse->isResultDependent()", "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 4283, __extension__ __PRETTY_FUNCTION__)); | |||||
4284 | ||||||
4285 | unsigned n = gse->getNumAssocs(); | |||||
4286 | SmallVector<Expr*, 4> subExprs(n); | |||||
4287 | SmallVector<TypeSourceInfo*, 4> subTypes(n); | |||||
4288 | for (unsigned i = 0; i != n; ++i) { | |||||
4289 | subTypes[i] = gse->getAssocTypeSourceInfo(i); | |||||
4290 | Expr *sub = gse->getAssocExpr(i); | |||||
4291 | if (i == gse->getResultIndex()) | |||||
4292 | sub = stripARCUnbridgedCast(sub); | |||||
4293 | subExprs[i] = sub; | |||||
4294 | } | |||||
4295 | ||||||
4296 | return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(), | |||||
4297 | gse->getControllingExpr(), | |||||
4298 | subTypes, subExprs, | |||||
4299 | gse->getDefaultLoc(), | |||||
4300 | gse->getRParenLoc(), | |||||
4301 | gse->containsUnexpandedParameterPack(), | |||||
4302 | gse->getResultIndex()); | |||||
4303 | } else { | |||||
4304 | assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!")(static_cast <bool> (isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!") ? void (0) : __assert_fail ("isa<ImplicitCastExpr>(e) && \"bad form of unbridged cast!\"" , "/build/llvm-toolchain-snapshot-7~svn324650/tools/clang/lib/Sema/SemaExprObjC.cpp" , 4304, __extension__ __PRETTY_FUNCTION__)); | |||||
4305 | return cast<ImplicitCastExpr>(e)->getSubExpr(); | |||||
4306 | } | |||||
4307 | } | |||||
4308 | ||||||
4309 | bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType, | |||||
4310 | QualType exprType) { | |||||
4311 | QualType canCastType = | |||||
4312 | Context.getCanonicalType(castType).getUnqualifiedType(); | |||||
4313 | QualType canExprType = | |||||
4314 | Context.getCanonicalType(exprType).getUnqualifiedType(); | |||||
4315 | if (isa<ObjCObjectPointerType>(canCastType) && | |||||
4316 | castType.getObjCLifetime() == Qualifiers::OCL_Weak && | |||||
4317 | canExprType->isObjCObjectPointerType()) { | |||||
4318 | if (const ObjCObjectPointerType *ObjT = | |||||
4319 | canExprType->getAs<ObjCObjectPointerType>()) | |||||
4320 | if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl()) | |||||
4321 | return !ObjI->isArcWeakrefUnavailable(); | |||||
4322 | } | |||||
4323 | return true; | |||||
4324 | } | |||||
4325 | ||||||
4326 | /// Look for an ObjCReclaimReturnedObject cast and destroy it. | |||||
4327 | static Expr *maybeUndoReclaimObject(Expr *e) { | |||||
4328 | Expr *curExpr = e, *prevExpr = nullptr; | |||||
4329 | ||||||
4330 | // Walk down the expression until we hit an implicit cast of kind | |||||
4331 | // ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast. | |||||
4332 | while (true) { | |||||
4333 | if (auto *pe = dyn_cast<ParenExpr>(curExpr)) { | |||||
4334 | prevExpr = curExpr; | |||||
4335 | curExpr = pe->getSubExpr(); | |||||
4336 | continue; | |||||
4337 | } | |||||
4338 | ||||||
4339 | if (auto *ce = dyn_cast<CastExpr>(curExpr)) { | |||||
4340 | if (auto *ice = dyn_cast<ImplicitCastExpr>(ce)) | |||||
4341 | if (ice->getCastKind() == CK_ARCReclaimReturnedObject) { | |||||
4342 | if (!prevExpr) | |||||
4343 | return ice->getSubExpr(); | |||||
4344 | if (auto *pe = dyn_cast<ParenExpr>(prevExpr)) | |||||
4345 | pe->setSubExpr(ice->getSubExpr()); | |||||
4346 | else | |||||
4347 | cast<CastExpr>(prevExpr)->setSubExpr(ice->getSubExpr()); | |||||
4348 | return e; | |||||
4349 | } | |||||
4350 | ||||||
4351 | prevExpr = curExpr; | |||||
4352 | curExpr = ce->getSubExpr(); | |||||
4353 | continue; | |||||
4354 | } | |||||
4355 | ||||||
4356 | // Break out of the loop if curExpr is neither a Paren nor a Cast. | |||||
4357 | break; | |||||
4358 | } | |||||
4359 | ||||||
4360 | return e; | |||||
4361 | } | |||||
4362 | ||||||
4363 | ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, | |||||
4364 | ObjCBridgeCastKind Kind, | |||||
4365 | SourceLocation BridgeKeywordLoc, | |||||
4366 | TypeSourceInfo *TSInfo, | |||||
4367 | Expr *SubExpr) { | |||||
4368 | ExprResult SubResult = UsualUnaryConversions(SubExpr); | |||||
4369 | if (SubResult.isInvalid()) return ExprError(); | |||||
4370 | SubExpr = SubResult.get(); | |||||
4371 | ||||||
4372 | QualType T = TSInfo->getType(); | |||||
4373 | QualType FromType = SubExpr->getType(); | |||||
4374 | ||||||
4375 | CastKind CK; | |||||
4376 | ||||||
4377 | bool MustConsume = false; | |||||
4378 | if (T->isDependentType() || SubExpr->isTypeDependent()) { | |||||
4379 | // Okay: we'll build a dependent expression type. | |||||
4380 | CK = CK_Dependent; | |||||
4381 | } else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) { | |||||
4382 | // Casting CF -> id | |||||
4383 | CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast | |||||
4384 | : CK_CPointerToObjCPointerCast); | |||||
4385 | switch (Kind) { | |||||
4386 | case OBC_Bridge: | |||||
4387 | break; | |||||
4388 | ||||||
4389 | case OBC_BridgeRetained: { | |||||
4390 | bool br = isKnownName("CFBridgingRelease"); | |||||
4391 | Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) | |||||
4392 | << 2 | |||||
4393 | << FromType | |||||
4394 | << (T->isBlockPointerType()? 1 : 0) | |||||
4395 | << T | |||||
4396 | << SubExpr->getSourceRange() | |||||
4397 | << Kind; | |||||
4398 | Diag(BridgeKeywordLoc, diag::note_arc_bridge) | |||||
4399 | << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge"); | |||||
4400 | Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer) | |||||
4401 | << FromType << br | |||||
4402 | << FixItHint::CreateReplacement(BridgeKeywordLoc, | |||||
4403 | br ? "CFBridgingRelease " | |||||
4404 | : "__bridge_transfer "); | |||||
4405 | ||||||
4406 | Kind = OBC_Bridge; | |||||
4407 | break; | |||||
4408 | } | |||||
4409 | ||||||
4410 | case OBC_BridgeTransfer: | |||||
4411 | // We must consume the Objective-C object produced by the cast. | |||||
4412 | MustConsume = true; | |||||
4413 | break; | |||||
4414 | } | |||||
4415 | } else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) { | |||||
4416 | // Okay: id -> CF | |||||
4417 | CK = CK_BitCast; | |||||
4418 | switch (Kind) { | |||||
4419 | case OBC_Bridge: | |||||
4420 | // Reclaiming a value that's going to be __bridge-casted to CF | |||||
4421 | // is very dangerous, so we don't do it. | |||||
4422 | SubExpr = maybeUndoReclaimObject(SubExpr); | |||||
4423 | break; | |||||
4424 | ||||||
4425 | case OBC_BridgeRetained: | |||||
4426 | // Produce the object before casting it. | |||||
4427 | SubExpr = ImplicitCastExpr::Create(Context, FromType, | |||||
4428 | CK_ARCProduceObject, | |||||
4429 | SubExpr, nullptr, VK_RValue); | |||||
4430 | break; | |||||
4431 | ||||||
4432 | case OBC_BridgeTransfer: { | |||||
4433 | bool br = isKnownName("CFBridgingRetain"); | |||||
4434 | Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind) | |||||
4435 | << (FromType->isBlockPointerType()? 1 : 0) | |||||
4436 | << FromType | |||||
4437 | << 2 | |||||
4438 | << T | |||||
4439 | << SubExpr->getSourceRange() | |||||
4440 | << Kind; | |||||
4441 | ||||||
4442 | Diag(BridgeKeywordLoc, diag::note_arc_bridge) | |||||
4443 | << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge "); | |||||
4444 | Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained) | |||||
4445 | << T << br | |||||
4446 | << FixItHint::CreateReplacement(BridgeKeywordLoc, | |||||
4447 | br ? "CFBridgingRetain " : "__bridge_retained"); | |||||
4448 | ||||||
4449 | Kind = OBC_Bridge; | |||||
4450 | break; | |||||
4451 | } | |||||
4452 | } | |||||
4453 | } else { | |||||
4454 | Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible) | |||||
4455 | << FromType << T << Kind | |||||
4456 | << SubExpr->getSourceRange() | |||||
4457 | << TSInfo->getTypeLoc().getSourceRange(); | |||||
4458 | return ExprError(); | |||||
4459 | } | |||||
4460 | ||||||
4461 | Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK, | |||||
4462 | BridgeKeywordLoc, | |||||
4463 | TSInfo, SubExpr); | |||||
4464 | ||||||
4465 | if (MustConsume) { | |||||
4466 | Cleanup.setExprNeedsCleanups(true); | |||||
4467 | Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, | |||||
4468 | nullptr, VK_RValue); | |||||
4469 | } | |||||
4470 | ||||||
4471 | return Result; | |||||
4472 | } | |||||
4473 | ||||||
4474 | ExprResult Sema::ActOnObjCBridgedCast(Scope *S, | |||||
4475 | SourceLocation LParenLoc, | |||||
4476 | ObjCBridgeCastKind Kind, | |||||
4477 | SourceLocation BridgeKeywordLoc, | |||||
4478 | ParsedType Type, | |||||
4479 | SourceLocation RParenLoc, | |||||
4480 | Expr *SubExpr) { | |||||
4481 | TypeSourceInfo *TSInfo = nullptr; | |||||
4482 | QualType T = GetTypeFromParser(Type, &TSInfo); | |||||
4483 | if (Kind == OBC_Bridge) | |||||
4484 | CheckTollFreeBridgeCast(T, SubExpr); | |||||
4485 | if (!TSInfo) | |||||
4486 | TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc); | |||||
4487 | return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo, | |||||
4488 | SubExpr); | |||||
4489 | } |