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