1//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for Objective-C expressions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/Availability.h"
15#include "clang/AST/DeclObjC.h"
16#include "clang/AST/ExprObjC.h"
17#include "clang/AST/StmtVisitor.h"
18#include "clang/AST/TypeLoc.h"
19#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
20#include "clang/Basic/Builtins.h"
21#include "clang/Basic/TargetInfo.h"
22#include "clang/Edit/Commit.h"
23#include "clang/Edit/Rewriters.h"
24#include "clang/Lex/Preprocessor.h"
25#include "clang/Sema/Initialization.h"
26#include "clang/Sema/Lookup.h"
27#include "clang/Sema/Scope.h"
28#include "clang/Sema/ScopeInfo.h"
29#include "clang/Sema/SemaObjC.h"
30#include "llvm/Support/ConvertUTF.h"
31#include <optional>
32
33using namespace clang;
34using namespace sema;
35using llvm::APFloat;
36using llvm::ArrayRef;
37
38ExprResult SemaObjC::ParseObjCStringLiteral(SourceLocation *AtLocs,
39 ArrayRef<Expr *> Strings) {
40 ASTContext &Context = getASTContext();
41 // Most ObjC strings are formed out of a single piece. However, we *can*
42 // have strings formed out of multiple @ strings with multiple pptokens in
43 // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one
44 // StringLiteral for ObjCStringLiteral to hold onto.
45 StringLiteral *S = cast<StringLiteral>(Val: Strings[0]);
46
47 // If we have a multi-part string, merge it all together.
48 if (Strings.size() != 1) {
49 // Concatenate objc strings.
50 SmallString<128> StrBuf;
51 SmallVector<SourceLocation, 8> StrLocs;
52
53 for (Expr *E : Strings) {
54 S = cast<StringLiteral>(Val: E);
55
56 // ObjC strings can't be wide or UTF.
57 if (!S->isOrdinary()) {
58 Diag(Loc: S->getBeginLoc(), DiagID: diag::err_cfstring_literal_not_string_constant)
59 << S->getSourceRange();
60 return true;
61 }
62
63 // Append the string.
64 StrBuf += S->getString();
65
66 // Get the locations of the string tokens.
67 StrLocs.append(in_start: S->tokloc_begin(), in_end: S->tokloc_end());
68 }
69
70 // Create the aggregate string with the appropriate content and location
71 // information.
72 const ConstantArrayType *CAT = Context.getAsConstantArrayType(T: S->getType());
73 assert(CAT && "String literal not of constant array type!");
74 QualType StrTy = Context.getConstantArrayType(
75 EltTy: CAT->getElementType(), ArySize: llvm::APInt(32, StrBuf.size() + 1), SizeExpr: nullptr,
76 ASM: CAT->getSizeModifier(), IndexTypeQuals: CAT->getIndexTypeCVRQualifiers());
77 S = StringLiteral::Create(Ctx: Context, Str: StrBuf, Kind: StringLiteralKind::Ordinary,
78 /*Pascal=*/false, Ty: StrTy, Locs: StrLocs);
79 }
80
81 return BuildObjCStringLiteral(AtLoc: AtLocs[0], S);
82}
83
84ExprResult SemaObjC::BuildObjCStringLiteral(SourceLocation AtLoc,
85 StringLiteral *S) {
86 ASTContext &Context = getASTContext();
87 // Verify that this composite string is acceptable for ObjC strings.
88 if (CheckObjCString(Arg: S))
89 return true;
90
91 // Initialize the constant string interface lazily. This assumes
92 // the NSString interface is seen in this translation unit. Note: We
93 // don't use NSConstantString, since the runtime team considers this
94 // interface private (even though it appears in the header files).
95 QualType Ty = Context.getObjCConstantStringInterface();
96 if (!Ty.isNull()) {
97 Ty = Context.getObjCObjectPointerType(OIT: Ty);
98 } else if (getLangOpts().NoConstantCFStrings) {
99 IdentifierInfo *NSIdent=nullptr;
100 std::string StringClass(getLangOpts().ObjCConstantStringClass);
101
102 if (StringClass.empty())
103 NSIdent = &Context.Idents.get(Name: "NSConstantString");
104 else
105 NSIdent = &Context.Idents.get(Name: StringClass);
106
107 NamedDecl *IF = SemaRef.LookupSingleName(S: SemaRef.TUScope, Name: NSIdent, Loc: AtLoc,
108 NameKind: Sema::LookupOrdinaryName);
109 if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(Val: IF)) {
110 Context.setObjCConstantStringInterface(StrIF);
111 Ty = Context.getObjCConstantStringInterface();
112 Ty = Context.getObjCObjectPointerType(OIT: Ty);
113 } else {
114 // If there is no NSConstantString interface defined then treat this
115 // as error and recover from it.
116 Diag(Loc: S->getBeginLoc(), DiagID: diag::err_no_nsconstant_string_class)
117 << NSIdent << S->getSourceRange();
118 Ty = Context.getObjCIdType();
119 }
120 } else {
121 IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(K: NSAPI::ClassId_NSString);
122 NamedDecl *IF = SemaRef.LookupSingleName(S: SemaRef.TUScope, Name: NSIdent, Loc: AtLoc,
123 NameKind: Sema::LookupOrdinaryName);
124 if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(Val: IF)) {
125 Context.setObjCConstantStringInterface(StrIF);
126 Ty = Context.getObjCConstantStringInterface();
127 Ty = Context.getObjCObjectPointerType(OIT: Ty);
128 } else {
129 // If there is no NSString interface defined, implicitly declare
130 // a @class NSString; and use that instead. This is to make sure
131 // type of an NSString literal is represented correctly, instead of
132 // being an 'id' type.
133 Ty = Context.getObjCNSStringType();
134 if (Ty.isNull()) {
135 ObjCInterfaceDecl *NSStringIDecl =
136 ObjCInterfaceDecl::Create (C: Context,
137 DC: Context.getTranslationUnitDecl(),
138 atLoc: SourceLocation(), Id: NSIdent,
139 typeParamList: nullptr, PrevDecl: nullptr, ClassLoc: SourceLocation());
140 Ty = Context.getObjCInterfaceType(Decl: NSStringIDecl);
141 Context.setObjCNSStringType(Ty);
142 }
143 Ty = Context.getObjCObjectPointerType(OIT: Ty);
144 }
145 }
146
147 return new (Context) ObjCStringLiteral(S, Ty, AtLoc);
148}
149
150/// Emits an error if the given method does not exist, or if the return
151/// type is not an Objective-C object.
152static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
153 const ObjCInterfaceDecl *Class,
154 Selector Sel, const ObjCMethodDecl *Method) {
155 if (!Method) {
156 // FIXME: Is there a better way to avoid quotes than using getName()?
157 S.Diag(Loc, DiagID: diag::err_undeclared_boxing_method) << Sel << Class->getName();
158 return false;
159 }
160
161 // Make sure the return type is reasonable.
162 QualType ReturnType = Method->getReturnType();
163 if (!ReturnType->isObjCObjectPointerType()) {
164 S.Diag(Loc, DiagID: diag::err_objc_literal_method_sig)
165 << Sel;
166 S.Diag(Loc: Method->getLocation(), DiagID: diag::note_objc_literal_method_return)
167 << ReturnType;
168 return false;
169 }
170
171 return true;
172}
173
174/// Maps ObjCLiteralKind to NSClassIdKindKind
175static NSAPI::NSClassIdKindKind
176ClassKindFromLiteralKind(SemaObjC::ObjCLiteralKind LiteralKind) {
177 switch (LiteralKind) {
178 case SemaObjC::LK_Array:
179 return NSAPI::ClassId_NSArray;
180 case SemaObjC::LK_Dictionary:
181 return NSAPI::ClassId_NSDictionary;
182 case SemaObjC::LK_Numeric:
183 return NSAPI::ClassId_NSNumber;
184 case SemaObjC::LK_String:
185 return NSAPI::ClassId_NSString;
186 case SemaObjC::LK_Boxed:
187 return NSAPI::ClassId_NSValue;
188
189 // there is no corresponding matching
190 // between LK_None/LK_Block and NSClassIdKindKind
191 case SemaObjC::LK_Block:
192 case SemaObjC::LK_None:
193 break;
194 }
195 llvm_unreachable("LiteralKind can't be converted into a ClassKind");
196}
197
198/// Validates ObjCInterfaceDecl availability.
199/// ObjCInterfaceDecl, used to create ObjC literals, should be defined
200/// if clang not in a debugger mode.
201static bool
202ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
203 SourceLocation Loc,
204 SemaObjC::ObjCLiteralKind LiteralKind) {
205 if (!Decl) {
206 NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind);
207 IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(K: Kind);
208 S.Diag(Loc, DiagID: diag::err_undeclared_objc_literal_class)
209 << II->getName() << LiteralKind;
210 return false;
211 } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) {
212 S.Diag(Loc, DiagID: diag::err_undeclared_objc_literal_class)
213 << Decl->getName() << LiteralKind;
214 S.Diag(Loc: Decl->getLocation(), DiagID: diag::note_forward_class);
215 return false;
216 }
217
218 return true;
219}
220
221/// Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
222/// Used to create ObjC literals, such as NSDictionary (@{}),
223/// NSArray (@[]) and Boxed Expressions (@())
224static ObjCInterfaceDecl *
225LookupObjCInterfaceDeclForLiteral(Sema &S, SourceLocation Loc,
226 SemaObjC::ObjCLiteralKind LiteralKind) {
227 NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind);
228 IdentifierInfo *II = S.ObjC().NSAPIObj->getNSClassId(K: ClassKind);
229 NamedDecl *IF = S.LookupSingleName(S: S.TUScope, Name: II, Loc,
230 NameKind: Sema::LookupOrdinaryName);
231 ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(Val: IF);
232 if (!ID && S.getLangOpts().DebuggerObjCLiteral) {
233 ASTContext &Context = S.Context;
234 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
235 ID = ObjCInterfaceDecl::Create (C: Context, DC: TU, atLoc: SourceLocation(), Id: II,
236 typeParamList: nullptr, PrevDecl: nullptr, ClassLoc: SourceLocation());
237 }
238
239 if (!ValidateObjCLiteralInterfaceDecl(S, Decl: ID, Loc, LiteralKind)) {
240 ID = nullptr;
241 }
242
243 return ID;
244}
245
246/// Retrieve the NSNumber factory method that should be used to create
247/// an Objective-C literal for the given type.
248static ObjCMethodDecl *getNSNumberFactoryMethod(SemaObjC &S, SourceLocation Loc,
249 QualType NumberType,
250 bool isLiteral = false,
251 SourceRange R = SourceRange()) {
252 std::optional<NSAPI::NSNumberLiteralMethodKind> Kind =
253 S.NSAPIObj->getNSNumberFactoryMethodKind(T: NumberType);
254
255 if (!Kind) {
256 if (isLiteral) {
257 S.Diag(Loc, DiagID: diag::err_invalid_nsnumber_type)
258 << NumberType << R;
259 }
260 return nullptr;
261 }
262
263 // If we already looked up this method, we're done.
264 if (S.NSNumberLiteralMethods[*Kind])
265 return S.NSNumberLiteralMethods[*Kind];
266
267 Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(MK: *Kind,
268 /*Instance=*/false);
269
270 ASTContext &CX = S.SemaRef.Context;
271
272 // Look up the NSNumber class, if we haven't done so already. It's cached
273 // in the Sema instance.
274 if (!S.NSNumberDecl) {
275 S.NSNumberDecl =
276 LookupObjCInterfaceDeclForLiteral(S&: S.SemaRef, Loc, LiteralKind: SemaObjC::LK_Numeric);
277 if (!S.NSNumberDecl) {
278 return nullptr;
279 }
280 }
281
282 if (S.NSNumberPointer.isNull()) {
283 // generate the pointer to NSNumber type.
284 QualType NSNumberObject = CX.getObjCInterfaceType(Decl: S.NSNumberDecl);
285 S.NSNumberPointer = CX.getObjCObjectPointerType(OIT: NSNumberObject);
286 }
287
288 // Look for the appropriate method within NSNumber.
289 ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);
290 if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
291 // create a stub definition this NSNumber factory method.
292 TypeSourceInfo *ReturnTInfo = nullptr;
293 Method = ObjCMethodDecl::Create(
294 C&: CX, beginLoc: SourceLocation(), endLoc: SourceLocation(), SelInfo: Sel, T: S.NSNumberPointer,
295 ReturnTInfo, contextDecl: S.NSNumberDecl,
296 /*isInstance=*/false, /*isVariadic=*/false,
297 /*isPropertyAccessor=*/false,
298 /*isSynthesizedAccessorStub=*/false,
299 /*isImplicitlyDeclared=*/true,
300 /*isDefined=*/false, impControl: ObjCImplementationControl::Required,
301 /*HasRelatedResultType=*/false);
302 ParmVarDecl *value =
303 ParmVarDecl::Create(C&: S.SemaRef.Context, DC: Method, StartLoc: SourceLocation(),
304 IdLoc: SourceLocation(), Id: &CX.Idents.get(Name: "value"),
305 T: NumberType, /*TInfo=*/nullptr, S: SC_None, DefArg: nullptr);
306 Method->setMethodParams(C&: S.SemaRef.Context, Params: value, SelLocs: {});
307 }
308
309 if (!validateBoxingMethod(S&: S.SemaRef, Loc, Class: S.NSNumberDecl, Sel, Method))
310 return nullptr;
311
312 // Note: if the parameter type is out-of-line, we'll catch it later in the
313 // implicit conversion.
314
315 S.NSNumberLiteralMethods[*Kind] = Method;
316 return Method;
317}
318
319static bool CheckObjCNumberExpressionIsConstant(Sema &S, Expr *Number) {
320 const LangOptions &LangOpts = S.getLangOpts();
321
322 if (!LangOpts.ObjCConstantLiterals)
323 return false;
324
325 const QualType Ty = Number->IgnoreParens()->getType();
326 ASTContext &Context = S.Context;
327
328 if (Number->isValueDependent())
329 return false;
330
331 if (!Number->isEvaluatable(Ctx: Context))
332 return false;
333
334 // Note `@YES` `@NO` need to be handled explicitly
335 // to meet existing plist encoding / decoding expectations
336 // we can't convert anything that is "bool like" so ensure
337 // we're referring to a `BOOL` typedef or a real `_Bool`
338 // preferring explicit types over the typedefs.
339 //
340 // Also we can emit the constant singleton if supported by the target always.
341 assert(LangOpts.ObjCRuntime.hasConstantCFBooleans() &&
342 "The current ABI doesn't support the constant CFBooleanTrue "
343 "singleton!");
344 const bool IsBoolType =
345 (Ty->isBooleanType() || NSAPI(Context).isObjCBOOLType(T: Ty));
346 if (IsBoolType)
347 return true;
348
349 // If for debug or other reasons an explict opt-out is passed bail.
350 // This doesn't effect `BOOL` singletons similar to collection singletons.
351 if (!LangOpts.ConstantNSNumberLiterals)
352 return false;
353
354 // Note: Other parts of Sema prevent the boxing of types that aren't supported
355 // by `NSNumber`
356 Expr::EvalResult IntResult{};
357 if (Number->EvaluateAsInt(Result&: IntResult, Ctx: Context))
358 return true;
359
360 // Eval the number as an llvm::APFloat and ensure it fits
361 // what NSNumber expects.
362 APFloat FloatValue(0.0);
363 if (Number->EvaluateAsFloat(Result&: FloatValue, Ctx: Context)) {
364 // This asserts that the sema checks for `ObjCBoxedExpr` haven't changed to
365 // allow larger values than NSNumber supports
366 if (&FloatValue.getSemantics() == &APFloat::IEEEsingle())
367 return true;
368 if (&FloatValue.getSemantics() == &APFloat::IEEEdouble())
369 return true;
370
371 llvm_unreachable(
372 "NSNumber only supports `float` or `double` floating-point types.");
373 }
374
375 return false;
376}
377
378/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
379/// numeric literal expression. Type of the expression will be "NSNumber *".
380ExprResult SemaObjC::BuildObjCNumericLiteral(SourceLocation AtLoc,
381 Expr *Number) {
382 ASTContext &Context = getASTContext();
383 // Determine the type of the literal.
384 QualType NumberType = Number->getType();
385 if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Val: Number)) {
386 // In C, character literals have type 'int'. That's not the type we want
387 // to use to determine the Objective-c literal kind.
388 switch (Char->getKind()) {
389 case CharacterLiteralKind::Ascii:
390 case CharacterLiteralKind::UTF8:
391 NumberType = Context.CharTy;
392 break;
393
394 case CharacterLiteralKind::Wide:
395 NumberType = Context.getWideCharType();
396 break;
397
398 case CharacterLiteralKind::UTF16:
399 NumberType = Context.Char16Ty;
400 break;
401
402 case CharacterLiteralKind::UTF32:
403 NumberType = Context.Char32Ty;
404 break;
405 }
406 }
407
408 // Look for the appropriate method within NSNumber.
409 // Construct the literal.
410 SourceRange NR(Number->getSourceRange());
411 ObjCMethodDecl *Method = getNSNumberFactoryMethod(S&: *this, Loc: AtLoc, NumberType,
412 isLiteral: true, R: NR);
413 if (!Method)
414 return ExprError();
415
416 // Convert the number to the type that the parameter expects.
417 ParmVarDecl *ParamDecl = Method->parameters()[0];
418 InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
419 Parm: ParamDecl);
420 ExprResult ConvertedNumber =
421 SemaRef.PerformCopyInitialization(Entity, EqualLoc: SourceLocation(), Init: Number);
422 if (ConvertedNumber.isInvalid())
423 return ExprError();
424 Number = ConvertedNumber.get();
425
426 const bool IsConstInitLiteral =
427 CheckObjCNumberExpressionIsConstant(S&: SemaRef, Number);
428
429 auto *NumberLiteral = new (Context)
430 ObjCBoxedExpr(Number, NSNumberPointer, Method, IsConstInitLiteral,
431 SourceRange(AtLoc, NR.getEnd()));
432
433 // Use the effective source range of the literal, including the leading '@'.
434 return SemaRef.MaybeBindToTemporary(E: NumberLiteral);
435}
436
437/// Check that the given expression is a valid element of an Objective-C
438/// collection literal.
439static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
440 QualType T,
441 bool ArrayLiteral = false) {
442 // If the expression is type-dependent, there's nothing for us to do.
443 if (Element->isTypeDependent())
444 return Element;
445
446 ExprResult Result = S.CheckPlaceholderExpr(E: Element);
447 if (Result.isInvalid())
448 return ExprError();
449 Element = Result.get();
450
451 // In C++, check for an implicit conversion to an Objective-C object pointer
452 // type.
453 if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) {
454 InitializedEntity Entity
455 = InitializedEntity::InitializeParameter(Context&: S.Context, Type: T,
456 /*Consumed=*/false);
457 InitializationKind Kind = InitializationKind::CreateCopy(
458 InitLoc: Element->getBeginLoc(), EqualLoc: SourceLocation());
459 InitializationSequence Seq(S, Entity, Kind, Element);
460 if (!Seq.Failed())
461 return Seq.Perform(S, Entity, Kind, Args: Element);
462 }
463
464 Expr *OrigElement = Element;
465
466 // Perform lvalue-to-rvalue conversion.
467 Result = S.DefaultLvalueConversion(E: Element);
468 if (Result.isInvalid())
469 return ExprError();
470 Element = Result.get();
471
472 // Make sure that we have an Objective-C pointer type or block.
473 if (!Element->getType()->isObjCObjectPointerType() &&
474 !Element->getType()->isBlockPointerType()) {
475 bool Recovered = false;
476
477 // If this is potentially an Objective-C numeric literal, add the '@'.
478 if (isa<IntegerLiteral>(Val: OrigElement) ||
479 isa<CharacterLiteral>(Val: OrigElement) ||
480 isa<FloatingLiteral>(Val: OrigElement) ||
481 isa<ObjCBoolLiteralExpr>(Val: OrigElement) ||
482 isa<CXXBoolLiteralExpr>(Val: OrigElement)) {
483 if (S.ObjC().NSAPIObj->getNSNumberFactoryMethodKind(
484 T: OrigElement->getType())) {
485 int Which = isa<CharacterLiteral>(Val: OrigElement) ? 1
486 : (isa<CXXBoolLiteralExpr>(Val: OrigElement) ||
487 isa<ObjCBoolLiteralExpr>(Val: OrigElement)) ? 2
488 : 3;
489
490 S.Diag(Loc: OrigElement->getBeginLoc(), DiagID: diag::err_box_literal_collection)
491 << Which << OrigElement->getSourceRange()
492 << FixItHint::CreateInsertion(InsertionLoc: OrigElement->getBeginLoc(), Code: "@");
493
494 Result = S.ObjC().BuildObjCNumericLiteral(AtLoc: OrigElement->getBeginLoc(),
495 Number: OrigElement);
496 if (Result.isInvalid())
497 return ExprError();
498
499 Element = Result.get();
500 Recovered = true;
501 }
502 }
503 // If this is potentially an Objective-C string literal, add the '@'.
504 else if (StringLiteral *String = dyn_cast<StringLiteral>(Val: OrigElement)) {
505 if (String->isOrdinary()) {
506 S.Diag(Loc: OrigElement->getBeginLoc(), DiagID: diag::err_box_literal_collection)
507 << 0 << OrigElement->getSourceRange()
508 << FixItHint::CreateInsertion(InsertionLoc: OrigElement->getBeginLoc(), Code: "@");
509
510 Result =
511 S.ObjC().BuildObjCStringLiteral(AtLoc: OrigElement->getBeginLoc(), S: String);
512 if (Result.isInvalid())
513 return ExprError();
514
515 Element = Result.get();
516 Recovered = true;
517 }
518 }
519
520 if (!Recovered) {
521 S.Diag(Loc: Element->getBeginLoc(), DiagID: diag::err_invalid_collection_element)
522 << Element->getType();
523 return ExprError();
524 }
525 }
526 if (ArrayLiteral)
527 if (ObjCStringLiteral *getString =
528 dyn_cast<ObjCStringLiteral>(Val: OrigElement)) {
529 if (StringLiteral *SL = getString->getString()) {
530 unsigned numConcat = SL->getNumConcatenated();
531 if (numConcat > 1) {
532 // Only warn if the concatenated string doesn't come from a macro.
533 bool hasMacro = false;
534 for (unsigned i = 0; i < numConcat ; ++i)
535 if (SL->getStrTokenLoc(TokNum: i).isMacroID()) {
536 hasMacro = true;
537 break;
538 }
539 if (!hasMacro)
540 S.Diag(Loc: Element->getBeginLoc(),
541 DiagID: diag::warn_concatenated_nsarray_literal)
542 << Element->getType();
543 }
544 }
545 }
546
547 // Make sure that the element has the type that the container factory
548 // function expects.
549 return S.PerformCopyInitialization(
550 Entity: InitializedEntity::InitializeParameter(Context&: S.Context, Type: T,
551 /*Consumed=*/false),
552 EqualLoc: Element->getBeginLoc(), Init: Element);
553}
554
555ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
556 ASTContext &Context = getASTContext();
557 if (ValueExpr->isTypeDependent()) {
558 ObjCBoxedExpr *BoxedExpr = new (Context)
559 ObjCBoxedExpr(ValueExpr, Context.DependentTy, nullptr,
560 /*ExpressibleAsConstantInitializer=*/true, SR);
561 return BoxedExpr;
562 }
563 ObjCMethodDecl *BoxingMethod = nullptr;
564 QualType BoxedType;
565 // Convert the expression to an RValue, so we can check for pointer types...
566 ExprResult RValue = SemaRef.DefaultFunctionArrayLvalueConversion(E: ValueExpr);
567 if (RValue.isInvalid()) {
568 return ExprError();
569 }
570
571 // Check if the runtime supports constant init literals
572 const bool IsConstInitLiteral =
573 CheckObjCNumberExpressionIsConstant(S&: SemaRef, Number: ValueExpr);
574 SourceLocation Loc = SR.getBegin();
575 ValueExpr = RValue.get();
576 QualType ValueType(ValueExpr->getType());
577 if (const PointerType *PT = ValueType->getAs<PointerType>()) {
578 QualType PointeeType = PT->getPointeeType();
579 if (Context.hasSameUnqualifiedType(T1: PointeeType, T2: Context.CharTy)) {
580
581 if (!NSStringDecl) {
582 NSStringDecl =
583 LookupObjCInterfaceDeclForLiteral(S&: SemaRef, Loc, LiteralKind: LK_String);
584 if (!NSStringDecl) {
585 return ExprError();
586 }
587 QualType NSStringObject = Context.getObjCInterfaceType(Decl: NSStringDecl);
588 NSStringPointer = Context.getObjCObjectPointerType(OIT: NSStringObject);
589 }
590
591 // The boxed expression can be emitted as a compile time constant if it is
592 // a string literal whose character encoding is compatible with UTF-8.
593 if (auto *CE = dyn_cast<ImplicitCastExpr>(Val: ValueExpr))
594 if (CE->getCastKind() == CK_ArrayToPointerDecay)
595 if (auto *SL =
596 dyn_cast<StringLiteral>(Val: CE->getSubExpr()->IgnoreParens())) {
597 assert((SL->isOrdinary() || SL->isUTF8()) &&
598 "unexpected character encoding");
599 StringRef Str = SL->getString();
600 const llvm::UTF8 *StrBegin = Str.bytes_begin();
601 const llvm::UTF8 *StrEnd = Str.bytes_end();
602 // Check that this is a valid UTF-8 string.
603 if (llvm::isLegalUTF8String(source: &StrBegin, sourceEnd: StrEnd)) {
604 BoxedType = Context.getAttributedType(nullability: NullabilityKind::NonNull,
605 modifiedType: NSStringPointer, equivalentType: NSStringPointer);
606 return new (Context)
607 ObjCBoxedExpr(CE, BoxedType, nullptr, true, SR);
608 }
609
610 Diag(Loc: SL->getBeginLoc(), DiagID: diag::warn_objc_boxing_invalid_utf8_string)
611 << NSStringPointer << SL->getSourceRange();
612 }
613
614 if (!StringWithUTF8StringMethod) {
615 IdentifierInfo *II = &Context.Idents.get(Name: "stringWithUTF8String");
616 Selector stringWithUTF8String = Context.Selectors.getUnarySelector(ID: II);
617
618 // Look for the appropriate method within NSString.
619 BoxingMethod = NSStringDecl->lookupClassMethod(Sel: stringWithUTF8String);
620 if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
621 // Debugger needs to work even if NSString hasn't been defined.
622 TypeSourceInfo *ReturnTInfo = nullptr;
623 ObjCMethodDecl *M = ObjCMethodDecl::Create(
624 C&: Context, beginLoc: SourceLocation(), endLoc: SourceLocation(), SelInfo: stringWithUTF8String,
625 T: NSStringPointer, ReturnTInfo, contextDecl: NSStringDecl,
626 /*isInstance=*/false, /*isVariadic=*/false,
627 /*isPropertyAccessor=*/false,
628 /*isSynthesizedAccessorStub=*/false,
629 /*isImplicitlyDeclared=*/true,
630 /*isDefined=*/false, impControl: ObjCImplementationControl::Required,
631 /*HasRelatedResultType=*/false);
632 QualType ConstCharType = Context.CharTy.withConst();
633 ParmVarDecl *value =
634 ParmVarDecl::Create(C&: Context, DC: M,
635 StartLoc: SourceLocation(), IdLoc: SourceLocation(),
636 Id: &Context.Idents.get(Name: "value"),
637 T: Context.getPointerType(T: ConstCharType),
638 /*TInfo=*/nullptr,
639 S: SC_None, DefArg: nullptr);
640 M->setMethodParams(C&: Context, Params: value, SelLocs: {});
641 BoxingMethod = M;
642 }
643
644 if (!validateBoxingMethod(S&: SemaRef, Loc, Class: NSStringDecl,
645 Sel: stringWithUTF8String, Method: BoxingMethod))
646 return ExprError();
647
648 StringWithUTF8StringMethod = BoxingMethod;
649 }
650
651 BoxingMethod = StringWithUTF8StringMethod;
652 BoxedType = NSStringPointer;
653 // Transfer the nullability from method's return type.
654 NullabilityKindOrNone Nullability =
655 BoxingMethod->getReturnType()->getNullability();
656 if (Nullability)
657 BoxedType =
658 Context.getAttributedType(nullability: *Nullability, modifiedType: BoxedType, equivalentType: BoxedType);
659 }
660 } else if (ValueType->isBuiltinType()) {
661 // The other types we support are numeric, char and BOOL/bool. We could also
662 // provide limited support for structure types, such as NSRange, NSRect, and
663 // NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>
664 // for more details.
665
666 // Check for a top-level character literal.
667 if (const CharacterLiteral *Char =
668 dyn_cast<CharacterLiteral>(Val: ValueExpr->IgnoreParens())) {
669 // In C, character literals have type 'int'. That's not the type we want
670 // to use to determine the Objective-c literal kind.
671 switch (Char->getKind()) {
672 case CharacterLiteralKind::Ascii:
673 case CharacterLiteralKind::UTF8:
674 ValueType = Context.CharTy;
675 break;
676
677 case CharacterLiteralKind::Wide:
678 ValueType = Context.getWideCharType();
679 break;
680
681 case CharacterLiteralKind::UTF16:
682 ValueType = Context.Char16Ty;
683 break;
684
685 case CharacterLiteralKind::UTF32:
686 ValueType = Context.Char32Ty;
687 break;
688 }
689 }
690 // Look for the appropriate method within NSNumber.
691 BoxingMethod = getNSNumberFactoryMethod(S&: *this, Loc, NumberType: ValueType);
692 BoxedType = NSNumberPointer;
693 } else if (const auto *ED = ValueType->getAsEnumDecl()) {
694 if (!ED->isComplete()) {
695 Diag(Loc, DiagID: diag::err_objc_incomplete_boxed_expression_type)
696 << ValueType << ValueExpr->getSourceRange();
697 return ExprError();
698 }
699
700 BoxingMethod = getNSNumberFactoryMethod(S&: *this, Loc, NumberType: ED->getIntegerType());
701 BoxedType = NSNumberPointer;
702 } else if (ValueType->isObjCBoxableRecordType()) {
703 // Support for structure types, that marked as objc_boxable
704 // struct __attribute__((objc_boxable)) s { ... };
705
706 // Look up the NSValue class, if we haven't done so already. It's cached
707 // in the Sema instance.
708 if (!NSValueDecl) {
709 NSValueDecl = LookupObjCInterfaceDeclForLiteral(S&: SemaRef, Loc, LiteralKind: LK_Boxed);
710 if (!NSValueDecl) {
711 return ExprError();
712 }
713
714 // generate the pointer to NSValue type.
715 QualType NSValueObject = Context.getObjCInterfaceType(Decl: NSValueDecl);
716 NSValuePointer = Context.getObjCObjectPointerType(OIT: NSValueObject);
717 }
718
719 if (!ValueWithBytesObjCTypeMethod) {
720 const IdentifierInfo *II[] = {&Context.Idents.get(Name: "valueWithBytes"),
721 &Context.Idents.get(Name: "objCType")};
722 Selector ValueWithBytesObjCType = Context.Selectors.getSelector(NumArgs: 2, IIV: II);
723
724 // Look for the appropriate method within NSValue.
725 BoxingMethod = NSValueDecl->lookupClassMethod(Sel: ValueWithBytesObjCType);
726 if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
727 // Debugger needs to work even if NSValue hasn't been defined.
728 TypeSourceInfo *ReturnTInfo = nullptr;
729 ObjCMethodDecl *M = ObjCMethodDecl::Create(
730 C&: Context, beginLoc: SourceLocation(), endLoc: SourceLocation(), SelInfo: ValueWithBytesObjCType,
731 T: NSValuePointer, ReturnTInfo, contextDecl: NSValueDecl,
732 /*isInstance=*/false,
733 /*isVariadic=*/false,
734 /*isPropertyAccessor=*/false,
735 /*isSynthesizedAccessorStub=*/false,
736 /*isImplicitlyDeclared=*/true,
737 /*isDefined=*/false, impControl: ObjCImplementationControl::Required,
738 /*HasRelatedResultType=*/false);
739
740 SmallVector<ParmVarDecl *, 2> Params;
741
742 ParmVarDecl *bytes =
743 ParmVarDecl::Create(C&: Context, DC: M,
744 StartLoc: SourceLocation(), IdLoc: SourceLocation(),
745 Id: &Context.Idents.get(Name: "bytes"),
746 T: Context.VoidPtrTy.withConst(),
747 /*TInfo=*/nullptr,
748 S: SC_None, DefArg: nullptr);
749 Params.push_back(Elt: bytes);
750
751 QualType ConstCharType = Context.CharTy.withConst();
752 ParmVarDecl *type =
753 ParmVarDecl::Create(C&: Context, DC: M,
754 StartLoc: SourceLocation(), IdLoc: SourceLocation(),
755 Id: &Context.Idents.get(Name: "type"),
756 T: Context.getPointerType(T: ConstCharType),
757 /*TInfo=*/nullptr,
758 S: SC_None, DefArg: nullptr);
759 Params.push_back(Elt: type);
760
761 M->setMethodParams(C&: Context, Params, SelLocs: {});
762 BoxingMethod = M;
763 }
764
765 if (!validateBoxingMethod(S&: SemaRef, Loc, Class: NSValueDecl,
766 Sel: ValueWithBytesObjCType, Method: BoxingMethod))
767 return ExprError();
768
769 ValueWithBytesObjCTypeMethod = BoxingMethod;
770 }
771
772 if (!ValueType.isTriviallyCopyableType(Context)) {
773 Diag(Loc, DiagID: diag::err_objc_non_trivially_copyable_boxed_expression_type)
774 << ValueType << ValueExpr->getSourceRange();
775 return ExprError();
776 }
777
778 BoxingMethod = ValueWithBytesObjCTypeMethod;
779 BoxedType = NSValuePointer;
780 }
781
782 if (!BoxingMethod) {
783 Diag(Loc, DiagID: diag::err_objc_illegal_boxed_expression_type)
784 << ValueType << ValueExpr->getSourceRange();
785 return ExprError();
786 }
787
788 SemaRef.DiagnoseUseOfDecl(D: BoxingMethod, Locs: Loc);
789
790 ExprResult ConvertedValueExpr;
791 if (ValueType->isObjCBoxableRecordType()) {
792 InitializedEntity IE = InitializedEntity::InitializeTemporary(Type: ValueType);
793 ConvertedValueExpr = SemaRef.PerformCopyInitialization(
794 Entity: IE, EqualLoc: ValueExpr->getExprLoc(), Init: ValueExpr);
795 if (ConvertedValueExpr.isInvalid())
796 return ExprError();
797
798 ValueExpr = ConvertedValueExpr.get();
799 } else if (BoxingMethod->parameters().size() > 0) {
800 // Convert the expression to the type that the parameter requires.
801 ParmVarDecl *ParamDecl = BoxingMethod->parameters()[0];
802 InitializedEntity IE = InitializedEntity::InitializeParameter(Context,
803 Parm: ParamDecl);
804 ConvertedValueExpr =
805 SemaRef.PerformCopyInitialization(Entity: IE, EqualLoc: SourceLocation(), Init: ValueExpr);
806 if (ConvertedValueExpr.isInvalid())
807 return ExprError();
808
809 ValueExpr = ConvertedValueExpr.get();
810 }
811
812 ObjCBoxedExpr *BoxedExpr = new (Context)
813 ObjCBoxedExpr(ValueExpr, BoxedType, BoxingMethod, IsConstInitLiteral, SR);
814
815 return SemaRef.MaybeBindToTemporary(E: BoxedExpr);
816}
817
818/// Build an ObjC subscript pseudo-object expression, given that
819/// that's supported by the runtime.
820ExprResult SemaObjC::BuildObjCSubscriptExpression(
821 SourceLocation RB, Expr *BaseExpr, Expr *IndexExpr,
822 ObjCMethodDecl *getterMethod, ObjCMethodDecl *setterMethod) {
823 assert(!getLangOpts().isSubscriptPointerArithmetic());
824 ASTContext &Context = getASTContext();
825
826 // We can't get dependent types here; our callers should have
827 // filtered them out.
828 assert((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&
829 "base or index cannot have dependent type here");
830
831 // Filter out placeholders in the index. In theory, overloads could
832 // be preserved here, although that might not actually work correctly.
833 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: IndexExpr);
834 if (Result.isInvalid())
835 return ExprError();
836 IndexExpr = Result.get();
837
838 // Perform lvalue-to-rvalue conversion on the base.
839 Result = SemaRef.DefaultLvalueConversion(E: BaseExpr);
840 if (Result.isInvalid())
841 return ExprError();
842 BaseExpr = Result.get();
843
844 // Build the pseudo-object expression.
845 return new (Context) ObjCSubscriptRefExpr(
846 BaseExpr, IndexExpr, Context.PseudoObjectTy, VK_LValue, OK_ObjCSubscript,
847 getterMethod, setterMethod, RB);
848}
849
850ExprResult SemaObjC::BuildObjCArrayLiteral(SourceRange SR,
851 MultiExprArg Elements) {
852 ASTContext &Context = getASTContext();
853 SourceLocation Loc = SR.getBegin();
854
855 if (!NSArrayDecl) {
856 NSArrayDecl =
857 LookupObjCInterfaceDeclForLiteral(S&: SemaRef, Loc, LiteralKind: SemaObjC::LK_Array);
858 if (!NSArrayDecl) {
859 return ExprError();
860 }
861 }
862
863 // Find the arrayWithObjects:count: method, if we haven't done so already.
864 QualType IdT = Context.getObjCIdType();
865 if (!ArrayWithObjectsMethod) {
866 Selector
867 Sel = NSAPIObj->getNSArraySelector(MK: NSAPI::NSArr_arrayWithObjectsCount);
868 ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);
869 if (!Method && getLangOpts().DebuggerObjCLiteral) {
870 TypeSourceInfo *ReturnTInfo = nullptr;
871 Method = ObjCMethodDecl::Create(
872 C&: Context, beginLoc: SourceLocation(), endLoc: SourceLocation(), SelInfo: Sel, T: IdT, ReturnTInfo,
873 contextDecl: Context.getTranslationUnitDecl(), isInstance: false /*Instance*/,
874 isVariadic: false /*isVariadic*/,
875 /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,
876 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
877 impControl: ObjCImplementationControl::Required, HasRelatedResultType: false);
878 SmallVector<ParmVarDecl *, 2> Params;
879 ParmVarDecl *objects = ParmVarDecl::Create(C&: Context, DC: Method,
880 StartLoc: SourceLocation(),
881 IdLoc: SourceLocation(),
882 Id: &Context.Idents.get(Name: "objects"),
883 T: Context.getPointerType(T: IdT),
884 /*TInfo=*/nullptr,
885 S: SC_None, DefArg: nullptr);
886 Params.push_back(Elt: objects);
887 ParmVarDecl *cnt = ParmVarDecl::Create(C&: Context, DC: Method,
888 StartLoc: SourceLocation(),
889 IdLoc: SourceLocation(),
890 Id: &Context.Idents.get(Name: "cnt"),
891 T: Context.UnsignedLongTy,
892 /*TInfo=*/nullptr, S: SC_None,
893 DefArg: nullptr);
894 Params.push_back(Elt: cnt);
895 Method->setMethodParams(C&: Context, Params, SelLocs: {});
896 }
897
898 if (!validateBoxingMethod(S&: SemaRef, Loc, Class: NSArrayDecl, Sel, Method))
899 return ExprError();
900
901 // Dig out the type that all elements should be converted to.
902 QualType T = Method->parameters()[0]->getType();
903 const PointerType *PtrT = T->getAs<PointerType>();
904 if (!PtrT ||
905 !Context.hasSameUnqualifiedType(T1: PtrT->getPointeeType(), T2: IdT)) {
906 Diag(Loc: SR.getBegin(), DiagID: diag::err_objc_literal_method_sig)
907 << Sel;
908 Diag(Loc: Method->parameters()[0]->getLocation(),
909 DiagID: diag::note_objc_literal_method_param)
910 << 0 << T
911 << Context.getPointerType(T: IdT.withConst());
912 return ExprError();
913 }
914
915 // Check that the 'count' parameter is integral.
916 if (!Method->parameters()[1]->getType()->isIntegerType()) {
917 Diag(Loc: SR.getBegin(), DiagID: diag::err_objc_literal_method_sig)
918 << Sel;
919 Diag(Loc: Method->parameters()[1]->getLocation(),
920 DiagID: diag::note_objc_literal_method_param)
921 << 1
922 << Method->parameters()[1]->getType()
923 << "integral";
924 return ExprError();
925 }
926
927 // We've found a good +arrayWithObjects:count: method. Save it!
928 ArrayWithObjectsMethod = Method;
929 }
930
931 QualType ObjectsType = ArrayWithObjectsMethod->parameters()[0]->getType();
932 QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType();
933
934 const LangOptions &LangOpts = getLangOpts();
935
936 bool ExpressibleAsConstantInitLiteral = LangOpts.ConstantNSArrayLiterals;
937
938 // ExpressibleAsConstantInitLiteral isn't meaningful for dependent literals.
939 if (ExpressibleAsConstantInitLiteral &&
940 llvm::any_of(Range&: Elements,
941 P: [](Expr *Elem) { return Elem->isValueDependent(); }))
942 ExpressibleAsConstantInitLiteral = false;
943
944 // We can stil emit a constant empty array
945 if (LangOpts.ObjCConstantLiterals && Elements.size() == 0) {
946 assert(LangOpts.ObjCRuntime.hasConstantEmptyCollections() &&
947 "The current ABI doesn't support an empty constant NSArray "
948 "singleton!");
949 ExpressibleAsConstantInitLiteral = true;
950 }
951
952 // Check that each of the elements provided is valid in a collection literal,
953 // performing conversions as necessary.
954 Expr **ElementsBuffer = Elements.data();
955 for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
956 ExprResult Converted = CheckObjCCollectionLiteralElement(
957 S&: SemaRef, Element: ElementsBuffer[I], T: RequiredType, ArrayLiteral: true);
958 if (Converted.isInvalid())
959 return ExprError();
960
961 ElementsBuffer[I] = Converted.get();
962
963 // Only allow actual literals and not references to other constant literals
964 // to be in constant collections since they *could* be modified / reassigned
965 if (ExpressibleAsConstantInitLiteral &&
966 (!isa<ObjCObjectLiteral>(Val: ElementsBuffer[I]->IgnoreImpCasts()) ||
967 !ElementsBuffer[I]->isConstantInitializer(Ctx&: Context)))
968 ExpressibleAsConstantInitLiteral = false;
969 }
970
971 QualType Ty
972 = Context.getObjCObjectPointerType(
973 OIT: Context.getObjCInterfaceType(Decl: NSArrayDecl));
974
975 auto *ArrayLiteral =
976 ObjCArrayLiteral::Create(C: Context, Elements, T: Ty, Method: ArrayWithObjectsMethod,
977 ExpressibleAsConstantInitializer: ExpressibleAsConstantInitLiteral, SR);
978
979 return SemaRef.MaybeBindToTemporary(E: ArrayLiteral);
980}
981
982/// Check for duplicate keys in an ObjC dictionary literal. For instance:
983/// NSDictionary *nd = @{ @"foo" : @"bar", @"foo" : @"baz" };
984static void
985CheckObjCDictionaryLiteralDuplicateKeys(Sema &S,
986 ObjCDictionaryLiteral *Literal) {
987 if (Literal->isValueDependent() || Literal->isTypeDependent())
988 return;
989
990 // NSNumber has quite relaxed equality semantics (for instance, @YES is
991 // considered equal to @1.0). For now, ignore floating points and just do a
992 // bit-width and sign agnostic integer compare.
993 struct APSIntCompare {
994 bool operator()(const llvm::APSInt &LHS, const llvm::APSInt &RHS) const {
995 return llvm::APSInt::compareValues(I1: LHS, I2: RHS) < 0;
996 }
997 };
998
999 llvm::DenseMap<StringRef, SourceLocation> StringKeys;
1000 std::map<llvm::APSInt, SourceLocation, APSIntCompare> IntegralKeys;
1001
1002 auto checkOneKey = [&](auto &Map, const auto &Key, SourceLocation Loc) {
1003 auto Pair = Map.insert({Key, Loc});
1004 if (!Pair.second) {
1005 S.Diag(Loc, DiagID: diag::warn_nsdictionary_duplicate_key);
1006 S.Diag(Pair.first->second, diag::note_nsdictionary_duplicate_key_here);
1007 }
1008 };
1009
1010 for (unsigned Idx = 0, End = Literal->getNumElements(); Idx != End; ++Idx) {
1011 Expr *Key = Literal->getKeyValueElement(Index: Idx).Key->IgnoreParenImpCasts();
1012
1013 if (auto *StrLit = dyn_cast<ObjCStringLiteral>(Val: Key)) {
1014 StringRef Bytes = StrLit->getString()->getBytes();
1015 SourceLocation Loc = StrLit->getExprLoc();
1016 checkOneKey(StringKeys, Bytes, Loc);
1017 }
1018
1019 if (auto *BE = dyn_cast<ObjCBoxedExpr>(Val: Key)) {
1020 Expr *Boxed = BE->getSubExpr();
1021 SourceLocation Loc = BE->getExprLoc();
1022
1023 // Check for @("foo").
1024 if (auto *Str = dyn_cast<StringLiteral>(Val: Boxed->IgnoreParenImpCasts())) {
1025 checkOneKey(StringKeys, Str->getBytes(), Loc);
1026 continue;
1027 }
1028
1029 Expr::EvalResult Result;
1030 if (Boxed->EvaluateAsInt(Result, Ctx: S.getASTContext(),
1031 AllowSideEffects: Expr::SE_AllowSideEffects)) {
1032 checkOneKey(IntegralKeys, Result.Val.getInt(), Loc);
1033 }
1034 }
1035 }
1036}
1037
1038/// Warn about string keys of a constant dictionary literal that are not
1039/// well-formed UTF-8. When a dictionary is emitted as a static constant, its
1040/// keys are stored and looked up as UTF-16, and the CFString emitter truncates
1041/// each key at the first ill-formed byte. A truncated key generally cannot be
1042/// found at runtime as written, so flag it -- mirroring the diagnostic emitted
1043/// for ill-formed UTF-8 when boxing a string
1044/// (warn_objc_boxing_invalid_utf8_string).
1045static void CheckObjCDictionaryLiteralUTF8Keys(Sema &S,
1046 ObjCDictionaryLiteral *Literal) {
1047 // Only constant dictionaries store/truncate keys as UTF-16; ordinary runtime
1048 // dictionaries keep the original NSString unchanged.
1049 if (!Literal->isExpressibleAsConstantInitializer())
1050 return;
1051 if (Literal->isValueDependent() || Literal->isTypeDependent())
1052 return;
1053 // With -fno-constant-cfstrings the keys are emitted as
1054 // OBJC_CLASS_$_NSConstantString, which preserves the original bytes (no
1055 // truncation) and compares them as-is at lookup time, so an ill-formed key
1056 // is still found and there is nothing to warn about.
1057 if (S.getLangOpts().NoConstantCFStrings)
1058 return;
1059
1060 for (unsigned Idx = 0, End = Literal->getNumElements(); Idx != End; ++Idx) {
1061 Expr *Key = Literal->getKeyValueElement(Index: Idx).Key->IgnoreParenImpCasts();
1062 auto *StrLit = dyn_cast<ObjCStringLiteral>(Val: Key);
1063 if (!StrLit)
1064 continue;
1065 StringRef Bytes = StrLit->getString()->getBytes();
1066 const llvm::UTF8 *Begin = Bytes.bytes_begin();
1067 const llvm::UTF8 *End2 = Bytes.bytes_end();
1068 if (!llvm::isLegalUTF8String(source: &Begin, sourceEnd: End2))
1069 S.Diag(Loc: StrLit->getExprLoc(),
1070 DiagID: diag::warn_objc_dictionary_ill_formed_utf8_key)
1071 << StrLit->getSourceRange();
1072 }
1073}
1074
1075ExprResult SemaObjC::BuildObjCDictionaryLiteral(
1076 SourceRange SR, MutableArrayRef<ObjCDictionaryElement> Elements) {
1077 ASTContext &Context = getASTContext();
1078 SourceLocation Loc = SR.getBegin();
1079
1080 if (!NSDictionaryDecl) {
1081 NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(
1082 S&: SemaRef, Loc, LiteralKind: SemaObjC::LK_Dictionary);
1083 if (!NSDictionaryDecl) {
1084 return ExprError();
1085 }
1086 }
1087
1088 // Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
1089 // so already.
1090 QualType IdT = Context.getObjCIdType();
1091 if (!DictionaryWithObjectsMethod) {
1092 Selector Sel = NSAPIObj->getNSDictionarySelector(
1093 MK: NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
1094 ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);
1095 if (!Method && getLangOpts().DebuggerObjCLiteral) {
1096 Method = ObjCMethodDecl::Create(
1097 C&: Context, beginLoc: SourceLocation(), endLoc: SourceLocation(), SelInfo: Sel, T: IdT,
1098 ReturnTInfo: nullptr /*TypeSourceInfo */, contextDecl: Context.getTranslationUnitDecl(),
1099 isInstance: false /*Instance*/, isVariadic: false /*isVariadic*/,
1100 /*isPropertyAccessor=*/false,
1101 /*isSynthesizedAccessorStub=*/false,
1102 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1103 impControl: ObjCImplementationControl::Required, HasRelatedResultType: false);
1104 SmallVector<ParmVarDecl *, 3> Params;
1105 ParmVarDecl *objects = ParmVarDecl::Create(C&: Context, DC: Method,
1106 StartLoc: SourceLocation(),
1107 IdLoc: SourceLocation(),
1108 Id: &Context.Idents.get(Name: "objects"),
1109 T: Context.getPointerType(T: IdT),
1110 /*TInfo=*/nullptr, S: SC_None,
1111 DefArg: nullptr);
1112 Params.push_back(Elt: objects);
1113 ParmVarDecl *keys = ParmVarDecl::Create(C&: Context, DC: Method,
1114 StartLoc: SourceLocation(),
1115 IdLoc: SourceLocation(),
1116 Id: &Context.Idents.get(Name: "keys"),
1117 T: Context.getPointerType(T: IdT),
1118 /*TInfo=*/nullptr, S: SC_None,
1119 DefArg: nullptr);
1120 Params.push_back(Elt: keys);
1121 ParmVarDecl *cnt = ParmVarDecl::Create(C&: Context, DC: Method,
1122 StartLoc: SourceLocation(),
1123 IdLoc: SourceLocation(),
1124 Id: &Context.Idents.get(Name: "cnt"),
1125 T: Context.UnsignedLongTy,
1126 /*TInfo=*/nullptr, S: SC_None,
1127 DefArg: nullptr);
1128 Params.push_back(Elt: cnt);
1129 Method->setMethodParams(C&: Context, Params, SelLocs: {});
1130 }
1131
1132 if (!validateBoxingMethod(S&: SemaRef, Loc: SR.getBegin(), Class: NSDictionaryDecl, Sel,
1133 Method))
1134 return ExprError();
1135
1136 // Dig out the type that all values should be converted to.
1137 QualType ValueT = Method->parameters()[0]->getType();
1138 const PointerType *PtrValue = ValueT->getAs<PointerType>();
1139 if (!PtrValue ||
1140 !Context.hasSameUnqualifiedType(T1: PtrValue->getPointeeType(), T2: IdT)) {
1141 Diag(Loc: SR.getBegin(), DiagID: diag::err_objc_literal_method_sig)
1142 << Sel;
1143 Diag(Loc: Method->parameters()[0]->getLocation(),
1144 DiagID: diag::note_objc_literal_method_param)
1145 << 0 << ValueT
1146 << Context.getPointerType(T: IdT.withConst());
1147 return ExprError();
1148 }
1149
1150 // Dig out the type that all keys should be converted to.
1151 QualType KeyT = Method->parameters()[1]->getType();
1152 const PointerType *PtrKey = KeyT->getAs<PointerType>();
1153 if (!PtrKey ||
1154 !Context.hasSameUnqualifiedType(T1: PtrKey->getPointeeType(),
1155 T2: IdT)) {
1156 bool err = true;
1157 if (PtrKey) {
1158 if (QIDNSCopying.isNull()) {
1159 // key argument of selector is id<NSCopying>?
1160 if (ObjCProtocolDecl *NSCopyingPDecl =
1161 LookupProtocol(II: &Context.Idents.get(Name: "NSCopying"), IdLoc: SR.getBegin())) {
1162 ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
1163 QIDNSCopying = Context.getObjCObjectType(
1164 Base: Context.ObjCBuiltinIdTy, typeArgs: {},
1165 protocols: llvm::ArrayRef((ObjCProtocolDecl **)PQ, 1), isKindOf: false);
1166 QIDNSCopying = Context.getObjCObjectPointerType(OIT: QIDNSCopying);
1167 }
1168 }
1169 if (!QIDNSCopying.isNull())
1170 err = !Context.hasSameUnqualifiedType(T1: PtrKey->getPointeeType(),
1171 T2: QIDNSCopying);
1172 }
1173
1174 if (err) {
1175 Diag(Loc: SR.getBegin(), DiagID: diag::err_objc_literal_method_sig)
1176 << Sel;
1177 Diag(Loc: Method->parameters()[1]->getLocation(),
1178 DiagID: diag::note_objc_literal_method_param)
1179 << 1 << KeyT
1180 << Context.getPointerType(T: IdT.withConst());
1181 return ExprError();
1182 }
1183 }
1184
1185 // Check that the 'count' parameter is integral.
1186 QualType CountType = Method->parameters()[2]->getType();
1187 if (!CountType->isIntegerType()) {
1188 Diag(Loc: SR.getBegin(), DiagID: diag::err_objc_literal_method_sig)
1189 << Sel;
1190 Diag(Loc: Method->parameters()[2]->getLocation(),
1191 DiagID: diag::note_objc_literal_method_param)
1192 << 2 << CountType
1193 << "integral";
1194 return ExprError();
1195 }
1196
1197 // We've found a good +dictionaryWithObjects:keys:count: method; save it!
1198 DictionaryWithObjectsMethod = Method;
1199 }
1200
1201 QualType ValuesT = DictionaryWithObjectsMethod->parameters()[0]->getType();
1202 QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType();
1203 QualType KeysT = DictionaryWithObjectsMethod->parameters()[1]->getType();
1204 QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();
1205
1206 // Check that each of the keys and values provided is valid in a collection
1207 // literal, performing conversions as necessary.
1208 bool HasPackExpansions = false;
1209
1210 const LangOptions &LangOpts = getLangOpts();
1211
1212 bool ExpressibleAsConstantInitLiteral = LangOpts.ConstantNSDictionaryLiterals;
1213
1214 // ExpressibleAsConstantInitLiteral isn't meaningful for dependent dictionary
1215 // literals.
1216 for (ObjCDictionaryElement &Elem : Elements) {
1217 if (!ExpressibleAsConstantInitLiteral)
1218 break;
1219 if (Elem.Key->isValueDependent() || Elem.Value->isValueDependent())
1220 ExpressibleAsConstantInitLiteral = false;
1221 }
1222
1223 // We can stil emit a constant empty dictionary.
1224 if (LangOpts.ObjCConstantLiterals && Elements.size() == 0) {
1225 assert(LangOpts.ObjCRuntime.hasConstantEmptyCollections() &&
1226 "The current ABI doesn't support an empty constant NSDictionary "
1227 "singleton!");
1228 ExpressibleAsConstantInitLiteral = true;
1229 }
1230
1231 for (ObjCDictionaryElement &Element : Elements) {
1232 // Check the key.
1233 ExprResult Key =
1234 CheckObjCCollectionLiteralElement(S&: SemaRef, Element: Element.Key, T: KeyT);
1235 if (Key.isInvalid())
1236 return ExprError();
1237
1238 // Check the value.
1239 ExprResult Value =
1240 CheckObjCCollectionLiteralElement(S&: SemaRef, Element: Element.Value, T: ValueT);
1241 if (Value.isInvalid())
1242 return ExprError();
1243
1244 Element.Key = Key.get();
1245 Element.Value = Value.get();
1246
1247 if (ExpressibleAsConstantInitLiteral &&
1248 !Element.Key->isConstantInitializer(Ctx&: Context))
1249 ExpressibleAsConstantInitLiteral = false;
1250
1251 // Only support string keys like plists
1252 if (ExpressibleAsConstantInitLiteral &&
1253 !isa<ObjCStringLiteral>(Val: Element.Key->IgnoreImpCasts()))
1254 ExpressibleAsConstantInitLiteral = false;
1255
1256 // Only allow actual literals and not references to other constant literals
1257 // to be in constant collections since they *could* be modified / reassigned
1258 if (ExpressibleAsConstantInitLiteral &&
1259 (!isa<ObjCObjectLiteral>(Val: Element.Value->IgnoreImpCasts()) ||
1260 !Element.Value->isConstantInitializer(Ctx&: Context)))
1261 ExpressibleAsConstantInitLiteral = false;
1262
1263 if (Element.EllipsisLoc.isInvalid())
1264 continue;
1265
1266 if (!Element.Key->containsUnexpandedParameterPack() &&
1267 !Element.Value->containsUnexpandedParameterPack()) {
1268 Diag(Loc: Element.EllipsisLoc,
1269 DiagID: diag::err_pack_expansion_without_parameter_packs)
1270 << SourceRange(Element.Key->getBeginLoc(),
1271 Element.Value->getEndLoc());
1272 return ExprError();
1273 }
1274
1275 HasPackExpansions = true;
1276 }
1277
1278 QualType Ty = Context.getObjCObjectPointerType(
1279 OIT: Context.getObjCInterfaceType(Decl: NSDictionaryDecl));
1280
1281 auto *DictionaryLiteral = ObjCDictionaryLiteral::Create(
1282 C: Context, VK: Elements, HasPackExpansions, T: Ty, Method: DictionaryWithObjectsMethod,
1283 ExpressibleAsConstantInitializer: ExpressibleAsConstantInitLiteral, SR);
1284
1285 CheckObjCDictionaryLiteralDuplicateKeys(S&: SemaRef, Literal: DictionaryLiteral);
1286 CheckObjCDictionaryLiteralUTF8Keys(S&: SemaRef, Literal: DictionaryLiteral);
1287
1288 return SemaRef.MaybeBindToTemporary(E: DictionaryLiteral);
1289}
1290
1291ExprResult SemaObjC::BuildObjCEncodeExpression(SourceLocation AtLoc,
1292 TypeSourceInfo *EncodedTypeInfo,
1293 SourceLocation RParenLoc) {
1294 ASTContext &Context = getASTContext();
1295 QualType EncodedType = EncodedTypeInfo->getType();
1296 QualType StrTy;
1297 if (EncodedType->isDependentType())
1298 StrTy = Context.DependentTy;
1299 else {
1300 if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled.
1301 !EncodedType->isVoidType()) // void is handled too.
1302 if (SemaRef.RequireCompleteType(Loc: AtLoc, T: EncodedType,
1303 DiagID: diag::err_incomplete_type_objc_at_encode,
1304 Args: EncodedTypeInfo->getTypeLoc()))
1305 return ExprError();
1306
1307 std::string Str;
1308 QualType NotEncodedT;
1309 Context.getObjCEncodingForType(T: EncodedType, S&: Str, Field: nullptr, NotEncodedT: &NotEncodedT);
1310 if (!NotEncodedT.isNull())
1311 Diag(Loc: AtLoc, DiagID: diag::warn_incomplete_encoded_type)
1312 << EncodedType << NotEncodedT;
1313
1314 // The type of @encode is the same as the type of the corresponding string,
1315 // which is an array type.
1316 StrTy = Context.getStringLiteralArrayType(EltTy: Context.CharTy, Length: Str.size());
1317 }
1318
1319 return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
1320}
1321
1322ExprResult SemaObjC::ParseObjCEncodeExpression(SourceLocation AtLoc,
1323 SourceLocation EncodeLoc,
1324 SourceLocation LParenLoc,
1325 ParsedType ty,
1326 SourceLocation RParenLoc) {
1327 ASTContext &Context = getASTContext();
1328 // FIXME: Preserve type source info ?
1329 TypeSourceInfo *TInfo;
1330 QualType EncodedType = SemaRef.GetTypeFromParser(Ty: ty, TInfo: &TInfo);
1331 if (!TInfo)
1332 TInfo = Context.getTrivialTypeSourceInfo(
1333 T: EncodedType, Loc: SemaRef.getLocForEndOfToken(Loc: LParenLoc));
1334
1335 return BuildObjCEncodeExpression(AtLoc, EncodedTypeInfo: TInfo, RParenLoc);
1336}
1337
1338static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
1339 SourceLocation AtLoc,
1340 SourceLocation LParenLoc,
1341 SourceLocation RParenLoc,
1342 ObjCMethodDecl *Method,
1343 ObjCMethodList &MethList) {
1344 ObjCMethodList *M = &MethList;
1345 bool Warned = false;
1346 for (M = M->getNext(); M; M=M->getNext()) {
1347 ObjCMethodDecl *MatchingMethodDecl = M->getMethod();
1348 if (MatchingMethodDecl == Method ||
1349 isa<ObjCImplDecl>(Val: MatchingMethodDecl->getDeclContext()) ||
1350 MatchingMethodDecl->getSelector() != Method->getSelector())
1351 continue;
1352 if (!S.ObjC().MatchTwoMethodDeclarations(Method, PrevMethod: MatchingMethodDecl,
1353 strategy: SemaObjC::MMS_loose)) {
1354 if (!Warned) {
1355 Warned = true;
1356 S.Diag(Loc: AtLoc, DiagID: diag::warn_multiple_selectors)
1357 << Method->getSelector() << FixItHint::CreateInsertion(InsertionLoc: LParenLoc, Code: "(")
1358 << FixItHint::CreateInsertion(InsertionLoc: RParenLoc, Code: ")");
1359 S.Diag(Loc: Method->getLocation(), DiagID: diag::note_method_declared_at)
1360 << Method->getDeclName();
1361 }
1362 S.Diag(Loc: MatchingMethodDecl->getLocation(), DiagID: diag::note_method_declared_at)
1363 << MatchingMethodDecl->getDeclName();
1364 }
1365 }
1366 return Warned;
1367}
1368
1369static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
1370 ObjCMethodDecl *Method,
1371 SourceLocation LParenLoc,
1372 SourceLocation RParenLoc,
1373 bool WarnMultipleSelectors) {
1374 if (!WarnMultipleSelectors ||
1375 S.Diags.isIgnored(DiagID: diag::warn_multiple_selectors, Loc: SourceLocation()))
1376 return;
1377 bool Warned = false;
1378 for (SemaObjC::GlobalMethodPool::iterator b = S.ObjC().MethodPool.begin(),
1379 e = S.ObjC().MethodPool.end();
1380 b != e; b++) {
1381 // first, instance methods
1382 ObjCMethodList &InstMethList = b->second.first;
1383 if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
1384 Method, MethList&: InstMethList))
1385 Warned = true;
1386
1387 // second, class methods
1388 ObjCMethodList &ClsMethList = b->second.second;
1389 if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, LParenLoc, RParenLoc,
1390 Method, MethList&: ClsMethList) || Warned)
1391 return;
1392 }
1393}
1394
1395static ObjCMethodDecl *LookupDirectMethodInMethodList(Sema &S, Selector Sel,
1396 ObjCMethodList &MethList,
1397 bool &onlyDirect,
1398 bool &anyDirect) {
1399 (void)Sel;
1400 ObjCMethodList *M = &MethList;
1401 ObjCMethodDecl *DirectMethod = nullptr;
1402 for (; M; M = M->getNext()) {
1403 ObjCMethodDecl *Method = M->getMethod();
1404 if (!Method)
1405 continue;
1406 assert(Method->getSelector() == Sel && "Method with wrong selector in method list");
1407 if (Method->isDirectMethod()) {
1408 anyDirect = true;
1409 DirectMethod = Method;
1410 } else
1411 onlyDirect = false;
1412 }
1413
1414 return DirectMethod;
1415}
1416
1417// Search the global pool for (potentially) direct methods matching the given
1418// selector. If a non-direct method is found, set \param onlyDirect to false. If
1419// a direct method is found, set \param anyDirect to true. Returns a direct
1420// method, if any.
1421static ObjCMethodDecl *LookupDirectMethodInGlobalPool(Sema &S, Selector Sel,
1422 bool &onlyDirect,
1423 bool &anyDirect) {
1424 auto Iter = S.ObjC().MethodPool.find(Val: Sel);
1425 if (Iter == S.ObjC().MethodPool.end())
1426 return nullptr;
1427
1428 ObjCMethodDecl *DirectInstance = LookupDirectMethodInMethodList(
1429 S, Sel, MethList&: Iter->second.first, onlyDirect, anyDirect);
1430 ObjCMethodDecl *DirectClass = LookupDirectMethodInMethodList(
1431 S, Sel, MethList&: Iter->second.second, onlyDirect, anyDirect);
1432
1433 return DirectInstance ? DirectInstance : DirectClass;
1434}
1435
1436static ObjCMethodDecl *findMethodInCurrentClass(Sema &S, Selector Sel) {
1437 auto *CurMD = S.getCurMethodDecl();
1438 if (!CurMD)
1439 return nullptr;
1440 ObjCInterfaceDecl *IFace = CurMD->getClassInterface();
1441
1442 // The language enforce that only one direct method is present in a given
1443 // class, so we just need to find one method in the current class to know
1444 // whether Sel is potentially direct in this context.
1445 if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/true))
1446 return MD;
1447 if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*Instance=*/true))
1448 return MD;
1449 if (ObjCMethodDecl *MD = IFace->lookupMethod(Sel, /*isInstance=*/false))
1450 return MD;
1451 if (ObjCMethodDecl *MD = IFace->lookupPrivateMethod(Sel, /*Instance=*/false))
1452 return MD;
1453
1454 return nullptr;
1455}
1456
1457ExprResult SemaObjC::ParseObjCSelectorExpression(
1458 Selector Sel, SourceLocation AtLoc, SourceLocation SelKWLoc,
1459 SourceLocation SelNameLoc, SourceLocation LParenLoc,
1460 SourceLocation RParenLoc, bool WarnMultipleSelectors) {
1461 ASTContext &Context = getASTContext();
1462 ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
1463 R: SourceRange(LParenLoc, RParenLoc));
1464 if (!Method)
1465 Method = LookupFactoryMethodInGlobalPool(Sel,
1466 R: SourceRange(LParenLoc, RParenLoc));
1467 if (!Method) {
1468 if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) {
1469 Selector MatchedSel = OM->getSelector();
1470 SourceRange SelectorRange(LParenLoc.getLocWithOffset(Offset: 1),
1471 RParenLoc.getLocWithOffset(Offset: -1));
1472 Diag(Loc: SelKWLoc, DiagID: diag::warn_undeclared_selector_with_typo)
1473 << Sel << MatchedSel
1474 << FixItHint::CreateReplacement(RemoveRange: SelectorRange,
1475 Code: MatchedSel.getAsString());
1476
1477 } else
1478 Diag(Loc: SelKWLoc, DiagID: diag::warn_undeclared_selector) << Sel;
1479 } else {
1480 DiagnoseMismatchedSelectors(S&: SemaRef, AtLoc, Method, LParenLoc, RParenLoc,
1481 WarnMultipleSelectors);
1482
1483 bool onlyDirect = true;
1484 bool anyDirect = false;
1485 ObjCMethodDecl *GlobalDirectMethod =
1486 LookupDirectMethodInGlobalPool(S&: SemaRef, Sel, onlyDirect, anyDirect);
1487
1488 if (onlyDirect) {
1489 Diag(Loc: AtLoc, DiagID: diag::err_direct_selector_expression)
1490 << Method->getSelector();
1491 Diag(Loc: Method->getLocation(), DiagID: diag::note_direct_method_declared_at)
1492 << Method->getDeclName();
1493 } else if (anyDirect) {
1494 // If we saw any direct methods, see if we see a direct member of the
1495 // current class. If so, the @selector will likely be used to refer to
1496 // this direct method.
1497 ObjCMethodDecl *LikelyTargetMethod =
1498 findMethodInCurrentClass(S&: SemaRef, Sel);
1499 if (LikelyTargetMethod && LikelyTargetMethod->isDirectMethod()) {
1500 Diag(Loc: AtLoc, DiagID: diag::warn_potentially_direct_selector_expression) << Sel;
1501 Diag(Loc: LikelyTargetMethod->getLocation(),
1502 DiagID: diag::note_direct_method_declared_at)
1503 << LikelyTargetMethod->getDeclName();
1504 } else if (!LikelyTargetMethod) {
1505 // Otherwise, emit the "strict" variant of this diagnostic, unless
1506 // LikelyTargetMethod is non-direct.
1507 Diag(Loc: AtLoc, DiagID: diag::warn_strict_potentially_direct_selector_expression)
1508 << Sel;
1509 Diag(Loc: GlobalDirectMethod->getLocation(),
1510 DiagID: diag::note_direct_method_declared_at)
1511 << GlobalDirectMethod->getDeclName();
1512 }
1513 }
1514 }
1515
1516 if (Method &&
1517 Method->getImplementationControl() !=
1518 ObjCImplementationControl::Optional &&
1519 !SemaRef.getSourceManager().isInSystemHeader(Loc: Method->getLocation()))
1520 ReferencedSelectors.insert(KV: std::make_pair(x&: Sel, y&: AtLoc));
1521
1522 // In ARC, forbid the user from using @selector for
1523 // retain/release/autorelease/dealloc/retainCount.
1524 if (getLangOpts().ObjCAutoRefCount) {
1525 switch (Sel.getMethodFamily()) {
1526 case OMF_retain:
1527 case OMF_release:
1528 case OMF_autorelease:
1529 case OMF_retainCount:
1530 case OMF_dealloc:
1531 Diag(Loc: AtLoc, DiagID: diag::err_arc_illegal_selector) <<
1532 Sel << SourceRange(LParenLoc, RParenLoc);
1533 break;
1534
1535 case OMF_None:
1536 case OMF_alloc:
1537 case OMF_copy:
1538 case OMF_finalize:
1539 case OMF_init:
1540 case OMF_mutableCopy:
1541 case OMF_new:
1542 case OMF_self:
1543 case OMF_initialize:
1544 case OMF_performSelector:
1545 break;
1546 }
1547 }
1548 QualType Ty = Context.getObjCSelType();
1549 return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, SelNameLoc, RParenLoc);
1550}
1551
1552ExprResult SemaObjC::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
1553 SourceLocation AtLoc,
1554 SourceLocation ProtoLoc,
1555 SourceLocation LParenLoc,
1556 SourceLocation ProtoIdLoc,
1557 SourceLocation RParenLoc) {
1558 ASTContext &Context = getASTContext();
1559 ObjCProtocolDecl* PDecl = LookupProtocol(II: ProtocolId, IdLoc: ProtoIdLoc);
1560 if (!PDecl) {
1561 Diag(Loc: ProtoLoc, DiagID: diag::err_undeclared_protocol) << ProtocolId;
1562 return true;
1563 }
1564 if (PDecl->isNonRuntimeProtocol())
1565 Diag(Loc: ProtoLoc, DiagID: diag::err_objc_non_runtime_protocol_in_protocol_expr)
1566 << PDecl;
1567 if (!PDecl->hasDefinition()) {
1568 Diag(Loc: ProtoLoc, DiagID: diag::err_atprotocol_protocol) << PDecl;
1569 Diag(Loc: PDecl->getLocation(), DiagID: diag::note_entity_declared_at) << PDecl;
1570 } else {
1571 PDecl = PDecl->getDefinition();
1572 }
1573
1574 QualType Ty = Context.getObjCProtoType();
1575 if (Ty.isNull())
1576 return true;
1577 Ty = Context.getObjCObjectPointerType(OIT: Ty);
1578 return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc);
1579}
1580
1581/// Try to capture an implicit reference to 'self'.
1582ObjCMethodDecl *SemaObjC::tryCaptureObjCSelf(SourceLocation Loc) {
1583 DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
1584
1585 // If we're not in an ObjC method, error out. Note that, unlike the
1586 // C++ case, we don't require an instance method --- class methods
1587 // still have a 'self', and we really do still need to capture it!
1588 ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(Val: DC);
1589 if (!method)
1590 return nullptr;
1591
1592 SemaRef.tryCaptureVariable(Var: method->getSelfDecl(), Loc);
1593
1594 return method;
1595}
1596
1597static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {
1598 QualType origType = T;
1599 if (auto nullability = AttributedType::stripOuterNullability(T)) {
1600 if (T == Context.getObjCInstanceType()) {
1601 return Context.getAttributedType(nullability: *nullability, modifiedType: Context.getObjCIdType(),
1602 equivalentType: Context.getObjCIdType());
1603 }
1604
1605 return origType;
1606 }
1607
1608 if (T == Context.getObjCInstanceType())
1609 return Context.getObjCIdType();
1610
1611 return origType;
1612}
1613
1614/// Determine the result type of a message send based on the receiver type,
1615/// method, and the kind of message send.
1616///
1617/// This is the "base" result type, which will still need to be adjusted
1618/// to account for nullability.
1619static QualType getBaseMessageSendResultType(Sema &S,
1620 QualType ReceiverType,
1621 ObjCMethodDecl *Method,
1622 bool isClassMessage,
1623 bool isSuperMessage) {
1624 assert(Method && "Must have a method");
1625 if (!Method->hasRelatedResultType())
1626 return Method->getSendResultType(receiverType: ReceiverType);
1627
1628 ASTContext &Context = S.Context;
1629
1630 // Local function that transfers the nullability of the method's
1631 // result type to the returned result.
1632 auto transferNullability = [&](QualType type) -> QualType {
1633 // If the method's result type has nullability, extract it.
1634 if (auto nullability =
1635 Method->getSendResultType(receiverType: ReceiverType)->getNullability()) {
1636 // Strip off any outer nullability sugar from the provided type.
1637 (void)AttributedType::stripOuterNullability(T&: type);
1638
1639 // Form a new attributed type using the method result type's nullability.
1640 return Context.getAttributedType(nullability: *nullability, modifiedType: type, equivalentType: type);
1641 }
1642
1643 return type;
1644 };
1645
1646 // If a method has a related return type:
1647 // - if the method found is an instance method, but the message send
1648 // was a class message send, T is the declared return type of the method
1649 // found
1650 if (Method->isInstanceMethod() && isClassMessage)
1651 return stripObjCInstanceType(Context,
1652 T: Method->getSendResultType(receiverType: ReceiverType));
1653
1654 // - if the receiver is super, T is a pointer to the class of the
1655 // enclosing method definition
1656 if (isSuperMessage) {
1657 if (ObjCMethodDecl *CurMethod = S.getCurMethodDecl())
1658 if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) {
1659 return transferNullability(
1660 Context.getObjCObjectPointerType(
1661 OIT: Context.getObjCInterfaceType(Decl: Class)));
1662 }
1663 }
1664
1665 // - if the receiver is the name of a class U, T is a pointer to U
1666 if (ReceiverType->getAsObjCInterfaceType())
1667 return transferNullability(Context.getObjCObjectPointerType(OIT: ReceiverType));
1668 // - if the receiver is of type Class or qualified Class type,
1669 // T is the declared return type of the method.
1670 if (ReceiverType->isObjCClassType() ||
1671 ReceiverType->isObjCQualifiedClassType())
1672 return stripObjCInstanceType(Context,
1673 T: Method->getSendResultType(receiverType: ReceiverType));
1674
1675 // - if the receiver is id, qualified id, Class, or qualified Class, T
1676 // is the receiver type, otherwise
1677 // - T is the type of the receiver expression.
1678 return transferNullability(ReceiverType);
1679}
1680
1681QualType SemaObjC::getMessageSendResultType(const Expr *Receiver,
1682 QualType ReceiverType,
1683 ObjCMethodDecl *Method,
1684 bool isClassMessage,
1685 bool isSuperMessage) {
1686 ASTContext &Context = getASTContext();
1687 // Produce the result type.
1688 QualType resultType = getBaseMessageSendResultType(
1689 S&: SemaRef, ReceiverType, Method, isClassMessage, isSuperMessage);
1690
1691 // If this is a class message, ignore the nullability of the receiver.
1692 if (isClassMessage) {
1693 // In a class method, class messages to 'self' that return instancetype can
1694 // be typed as the current class. We can safely do this in ARC because self
1695 // can't be reassigned, and we do it unsafely outside of ARC because in
1696 // practice people never reassign self in class methods and there's some
1697 // virtue in not being aggressively pedantic.
1698 if (Receiver && Receiver->isObjCSelfExpr()) {
1699 assert(ReceiverType->isObjCClassType() && "expected a Class self");
1700 QualType T = Method->getSendResultType(receiverType: ReceiverType);
1701 AttributedType::stripOuterNullability(T);
1702 if (T == Context.getObjCInstanceType()) {
1703 const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(
1704 Val: cast<ImplicitParamDecl>(
1705 Val: cast<DeclRefExpr>(Val: Receiver->IgnoreParenImpCasts())->getDecl())
1706 ->getDeclContext());
1707 assert(MD->isClassMethod() && "expected a class method");
1708 QualType NewResultType = Context.getObjCObjectPointerType(
1709 OIT: Context.getObjCInterfaceType(Decl: MD->getClassInterface()));
1710 if (auto Nullability = resultType->getNullability())
1711 NewResultType = Context.getAttributedType(nullability: *Nullability, modifiedType: NewResultType,
1712 equivalentType: NewResultType);
1713 return NewResultType;
1714 }
1715 }
1716 return resultType;
1717 }
1718
1719 // There is nothing left to do if the result type cannot have a nullability
1720 // specifier.
1721 if (!resultType->canHaveNullability())
1722 return resultType;
1723
1724 // Map the nullability of the result into a table index.
1725 unsigned receiverNullabilityIdx = 0;
1726 if (NullabilityKindOrNone nullability = ReceiverType->getNullability()) {
1727 if (*nullability == NullabilityKind::NullableResult)
1728 nullability = NullabilityKind::Nullable;
1729 receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
1730 }
1731
1732 unsigned resultNullabilityIdx = 0;
1733 if (NullabilityKindOrNone nullability = resultType->getNullability()) {
1734 if (*nullability == NullabilityKind::NullableResult)
1735 nullability = NullabilityKind::Nullable;
1736 resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
1737 }
1738
1739 // The table of nullability mappings, indexed by the receiver's nullability
1740 // and then the result type's nullability.
1741 static const uint8_t None = 0;
1742 static const uint8_t NonNull = 1;
1743 static const uint8_t Nullable = 2;
1744 static const uint8_t Unspecified = 3;
1745 static const uint8_t nullabilityMap[4][4] = {
1746 // None NonNull Nullable Unspecified
1747 /* None */ { None, None, Nullable, None },
1748 /* NonNull */ { None, NonNull, Nullable, Unspecified },
1749 /* Nullable */ { Nullable, Nullable, Nullable, Nullable },
1750 /* Unspecified */ { None, Unspecified, Nullable, Unspecified }
1751 };
1752
1753 unsigned newResultNullabilityIdx
1754 = nullabilityMap[receiverNullabilityIdx][resultNullabilityIdx];
1755 if (newResultNullabilityIdx == resultNullabilityIdx)
1756 return resultType;
1757
1758 // Strip off the existing nullability. This removes as little type sugar as
1759 // possible.
1760 do {
1761 if (auto attributed = dyn_cast<AttributedType>(Val: resultType.getTypePtr())) {
1762 resultType = attributed->getModifiedType();
1763 } else {
1764 resultType = resultType.getDesugaredType(Context);
1765 }
1766 } while (resultType->getNullability());
1767
1768 // Add nullability back if needed.
1769 if (newResultNullabilityIdx > 0) {
1770 auto newNullability
1771 = static_cast<NullabilityKind>(newResultNullabilityIdx-1);
1772 return Context.getAttributedType(nullability: newNullability, modifiedType: resultType, equivalentType: resultType);
1773 }
1774
1775 return resultType;
1776}
1777
1778/// Look for an ObjC method whose result type exactly matches the given type.
1779static const ObjCMethodDecl *
1780findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
1781 QualType instancetype) {
1782 if (MD->getReturnType() == instancetype)
1783 return MD;
1784
1785 // For these purposes, a method in an @implementation overrides a
1786 // declaration in the @interface.
1787 if (const ObjCImplDecl *impl =
1788 dyn_cast<ObjCImplDecl>(Val: MD->getDeclContext())) {
1789 const ObjCContainerDecl *iface;
1790 if (const ObjCCategoryImplDecl *catImpl =
1791 dyn_cast<ObjCCategoryImplDecl>(Val: impl)) {
1792 iface = catImpl->getCategoryDecl();
1793 } else {
1794 iface = impl->getClassInterface();
1795 }
1796
1797 const ObjCMethodDecl *ifaceMD =
1798 iface->getMethod(Sel: MD->getSelector(), isInstance: MD->isInstanceMethod());
1799 if (ifaceMD) return findExplicitInstancetypeDeclarer(MD: ifaceMD, instancetype);
1800 }
1801
1802 SmallVector<const ObjCMethodDecl *, 4> overrides;
1803 MD->getOverriddenMethods(Overridden&: overrides);
1804 for (unsigned i = 0, e = overrides.size(); i != e; ++i) {
1805 if (const ObjCMethodDecl *result =
1806 findExplicitInstancetypeDeclarer(MD: overrides[i], instancetype))
1807 return result;
1808 }
1809
1810 return nullptr;
1811}
1812
1813void SemaObjC::EmitRelatedResultTypeNoteForReturn(QualType destType) {
1814 ASTContext &Context = getASTContext();
1815 // Only complain if we're in an ObjC method and the required return
1816 // type doesn't match the method's declared return type.
1817 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Val: SemaRef.CurContext);
1818 if (!MD || !MD->hasRelatedResultType() ||
1819 Context.hasSameUnqualifiedType(T1: destType, T2: MD->getReturnType()))
1820 return;
1821
1822 // Look for a method overridden by this method which explicitly uses
1823 // 'instancetype'.
1824 if (const ObjCMethodDecl *overridden =
1825 findExplicitInstancetypeDeclarer(MD, instancetype: Context.getObjCInstanceType())) {
1826 SourceRange range = overridden->getReturnTypeSourceRange();
1827 SourceLocation loc = range.getBegin();
1828 if (loc.isInvalid())
1829 loc = overridden->getLocation();
1830 Diag(Loc: loc, DiagID: diag::note_related_result_type_explicit)
1831 << /*current method*/ 1 << range;
1832 return;
1833 }
1834
1835 // Otherwise, if we have an interesting method family, note that.
1836 // This should always trigger if the above didn't.
1837 if (ObjCMethodFamily family = MD->getMethodFamily())
1838 Diag(Loc: MD->getLocation(), DiagID: diag::note_related_result_type_family)
1839 << /*current method*/ 1
1840 << family;
1841}
1842
1843void SemaObjC::EmitRelatedResultTypeNote(const Expr *E) {
1844 ASTContext &Context = getASTContext();
1845 E = E->IgnoreParenImpCasts();
1846 const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(Val: E);
1847 if (!MsgSend)
1848 return;
1849
1850 const ObjCMethodDecl *Method = MsgSend->getMethodDecl();
1851 if (!Method)
1852 return;
1853
1854 if (!Method->hasRelatedResultType())
1855 return;
1856
1857 if (Context.hasSameUnqualifiedType(
1858 T1: Method->getReturnType().getNonReferenceType(), T2: MsgSend->getType()))
1859 return;
1860
1861 if (!Context.hasSameUnqualifiedType(T1: Method->getReturnType(),
1862 T2: Context.getObjCInstanceType()))
1863 return;
1864
1865 Diag(Loc: Method->getLocation(), DiagID: diag::note_related_result_type_inferred)
1866 << Method->isInstanceMethod() << Method->getSelector()
1867 << MsgSend->getType();
1868}
1869
1870bool SemaObjC::CheckMessageArgumentTypes(
1871 const Expr *Receiver, QualType ReceiverType, MultiExprArg Args,
1872 Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method,
1873 bool isClassMessage, bool isSuperMessage, SourceLocation lbrac,
1874 SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType,
1875 ExprValueKind &VK) {
1876 ASTContext &Context = getASTContext();
1877 SourceLocation SelLoc;
1878 if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
1879 SelLoc = SelectorLocs.front();
1880 else
1881 SelLoc = lbrac;
1882
1883 if (!Method) {
1884 // Apply default argument promotion as for (C99 6.5.2.2p6).
1885 for (unsigned i = 0, e = Args.size(); i != e; i++) {
1886 if (Args[i]->isTypeDependent())
1887 continue;
1888
1889 ExprResult result;
1890 if (getLangOpts().DebuggerSupport) {
1891 QualType paramTy; // ignored
1892 result = SemaRef.checkUnknownAnyArg(callLoc: SelLoc, result: Args[i], paramType&: paramTy);
1893 } else {
1894 result = SemaRef.DefaultArgumentPromotion(E: Args[i]);
1895 }
1896 if (result.isInvalid())
1897 return true;
1898 Args[i] = result.get();
1899 }
1900
1901 unsigned DiagID;
1902 if (getLangOpts().ObjCAutoRefCount)
1903 DiagID = diag::err_arc_method_not_found;
1904 else
1905 DiagID = isClassMessage ? diag::warn_class_method_not_found
1906 : diag::warn_inst_method_not_found;
1907 if (!getLangOpts().DebuggerSupport) {
1908 const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ObjectType: ReceiverType);
1909 if (OMD && !OMD->isInvalidDecl()) {
1910 if (getLangOpts().ObjCAutoRefCount)
1911 DiagID = diag::err_method_not_found_with_typo;
1912 else
1913 DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo
1914 : diag::warn_instance_method_not_found_with_typo;
1915 Selector MatchedSel = OMD->getSelector();
1916 SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());
1917 if (MatchedSel.isUnarySelector())
1918 Diag(Loc: SelLoc, DiagID)
1919 << Sel<< isClassMessage << MatchedSel
1920 << FixItHint::CreateReplacement(RemoveRange: SelectorRange, Code: MatchedSel.getAsString());
1921 else
1922 Diag(Loc: SelLoc, DiagID) << Sel<< isClassMessage << MatchedSel;
1923 }
1924 else
1925 Diag(Loc: SelLoc, DiagID)
1926 << Sel << isClassMessage << SourceRange(SelectorLocs.front(),
1927 SelectorLocs.back());
1928 // Find the class to which we are sending this message.
1929 if (auto *ObjPT = ReceiverType->getAs<ObjCObjectPointerType>()) {
1930 if (ObjCInterfaceDecl *ThisClass = ObjPT->getInterfaceDecl()) {
1931 Diag(Loc: ThisClass->getLocation(), DiagID: diag::note_receiver_class_declared);
1932 if (!RecRange.isInvalid())
1933 if (ThisClass->lookupClassMethod(Sel))
1934 Diag(Loc: RecRange.getBegin(), DiagID: diag::note_receiver_expr_here)
1935 << FixItHint::CreateReplacement(RemoveRange: RecRange,
1936 Code: ThisClass->getNameAsString());
1937 }
1938 }
1939 }
1940
1941 // In debuggers, we want to use __unknown_anytype for these
1942 // results so that clients can cast them.
1943 if (getLangOpts().DebuggerSupport) {
1944 ReturnType = Context.UnknownAnyTy;
1945 } else {
1946 ReturnType = Context.getObjCIdType();
1947 }
1948 VK = VK_PRValue;
1949 return false;
1950 }
1951
1952 ReturnType = getMessageSendResultType(Receiver, ReceiverType, Method,
1953 isClassMessage, isSuperMessage);
1954 VK = Expr::getValueKindForType(T: Method->getReturnType());
1955
1956 unsigned NumNamedArgs = Sel.getNumArgs();
1957 // Method might have more arguments than selector indicates. This is due
1958 // to addition of c-style arguments in method.
1959 if (Method->param_size() > Sel.getNumArgs())
1960 NumNamedArgs = Method->param_size();
1961 // FIXME. This need be cleaned up.
1962 if (Args.size() < NumNamedArgs) {
1963 Diag(Loc: SelLoc, DiagID: diag::err_typecheck_call_too_few_args)
1964 << 2 << NumNamedArgs << static_cast<unsigned>(Args.size())
1965 << /*is non object*/ 0;
1966 return false;
1967 }
1968
1969 // Compute the set of type arguments to be substituted into each parameter
1970 // type.
1971 std::optional<ArrayRef<QualType>> typeArgs =
1972 ReceiverType->getObjCSubstitutions(dc: Method->getDeclContext());
1973 bool IsError = false;
1974 for (unsigned i = 0; i < NumNamedArgs; i++) {
1975 // We can't do any type-checking on a type-dependent argument.
1976 if (Args[i]->isTypeDependent())
1977 continue;
1978
1979 Expr *argExpr = Args[i];
1980
1981 ParmVarDecl *param = Method->parameters()[i];
1982 assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
1983
1984 if (param->hasAttr<NoEscapeAttr>() &&
1985 param->getType()->isBlockPointerType())
1986 if (auto *BE = dyn_cast<BlockExpr>(
1987 Val: argExpr->IgnoreParenNoopCasts(Ctx: Context)))
1988 BE->getBlockDecl()->setDoesNotEscape();
1989
1990 // Strip the unbridged-cast placeholder expression off unless it's
1991 // a consumed argument.
1992 if (argExpr->hasPlaceholderType(K: BuiltinType::ARCUnbridgedCast) &&
1993 !param->hasAttr<CFConsumedAttr>())
1994 argExpr = stripARCUnbridgedCast(e: argExpr);
1995
1996 // If the parameter is __unknown_anytype, infer its type
1997 // from the argument.
1998 if (param->getType() == Context.UnknownAnyTy) {
1999 QualType paramType;
2000 ExprResult argE = SemaRef.checkUnknownAnyArg(callLoc: SelLoc, result: argExpr, paramType);
2001 if (argE.isInvalid()) {
2002 IsError = true;
2003 } else {
2004 Args[i] = argE.get();
2005
2006 // Update the parameter type in-place.
2007 param->setType(paramType);
2008 }
2009 continue;
2010 }
2011
2012 QualType origParamType = param->getType();
2013 QualType paramType = param->getType();
2014 if (typeArgs)
2015 paramType = paramType.substObjCTypeArgs(
2016 ctx&: Context,
2017 typeArgs: *typeArgs,
2018 context: ObjCSubstitutionContext::Parameter);
2019
2020 if (SemaRef.RequireCompleteType(
2021 Loc: argExpr->getSourceRange().getBegin(), T: paramType,
2022 DiagID: diag::err_call_incomplete_argument, Args: argExpr))
2023 return true;
2024
2025 InitializedEntity Entity
2026 = InitializedEntity::InitializeParameter(Context, Parm: param, Type: paramType);
2027 ExprResult ArgE =
2028 SemaRef.PerformCopyInitialization(Entity, EqualLoc: SourceLocation(), Init: argExpr);
2029 if (ArgE.isInvalid())
2030 IsError = true;
2031 else {
2032 Args[i] = ArgE.getAs<Expr>();
2033
2034 // If we are type-erasing a block to a block-compatible
2035 // Objective-C pointer type, we may need to extend the lifetime
2036 // of the block object.
2037 if (typeArgs && Args[i]->isPRValue() && paramType->isBlockPointerType() &&
2038 Args[i]->getType()->isBlockPointerType() &&
2039 origParamType->isObjCObjectPointerType()) {
2040 ExprResult arg = Args[i];
2041 SemaRef.maybeExtendBlockObject(E&: arg);
2042 Args[i] = arg.get();
2043 }
2044 }
2045 }
2046
2047 // Promote additional arguments to variadic methods.
2048 if (Method->isVariadic()) {
2049 for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {
2050 if (Args[i]->isTypeDependent())
2051 continue;
2052
2053 ExprResult Arg = SemaRef.DefaultVariadicArgumentPromotion(
2054 E: Args[i], CT: VariadicCallType::Method, FDecl: nullptr);
2055 IsError |= Arg.isInvalid();
2056 Args[i] = Arg.get();
2057 }
2058 } else {
2059 // Check for extra arguments to non-variadic methods.
2060 if (Args.size() != NumNamedArgs) {
2061 Diag(Loc: Args[NumNamedArgs]->getBeginLoc(),
2062 DiagID: diag::err_typecheck_call_too_many_args)
2063 << 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())
2064 << Method->getSourceRange() << /*is non object*/ 0
2065 << SourceRange(Args[NumNamedArgs]->getBeginLoc(),
2066 Args.back()->getEndLoc());
2067 }
2068 }
2069
2070 SemaRef.DiagnoseSentinelCalls(D: Method, Loc: SelLoc, Args);
2071
2072 // Do additional checkings on method.
2073 IsError |=
2074 CheckObjCMethodCall(Method, loc: SelLoc, Args: ArrayRef(Args.data(), Args.size()));
2075
2076 return IsError;
2077}
2078
2079bool SemaObjC::isSelfExpr(Expr *RExpr) {
2080 // 'self' is objc 'self' in an objc method only.
2081 ObjCMethodDecl *Method = dyn_cast_or_null<ObjCMethodDecl>(
2082 Val: SemaRef.CurContext->getNonClosureAncestor());
2083 return isSelfExpr(RExpr, Method);
2084}
2085
2086bool SemaObjC::isSelfExpr(Expr *receiver, const ObjCMethodDecl *method) {
2087 if (!method) return false;
2088
2089 receiver = receiver->IgnoreParenLValueCasts();
2090 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: receiver))
2091 if (DRE->getDecl() == method->getSelfDecl())
2092 return true;
2093 return false;
2094}
2095
2096/// LookupMethodInType - Look up a method in an ObjCObjectType.
2097ObjCMethodDecl *SemaObjC::LookupMethodInObjectType(Selector sel, QualType type,
2098 bool isInstance) {
2099 const ObjCObjectType *objType = type->castAs<ObjCObjectType>();
2100 if (ObjCInterfaceDecl *iface = objType->getInterface()) {
2101 // Look it up in the main interface (and categories, etc.)
2102 if (ObjCMethodDecl *method = iface->lookupMethod(Sel: sel, isInstance))
2103 return method;
2104
2105 // Okay, look for "private" methods declared in any
2106 // @implementations we've seen.
2107 if (ObjCMethodDecl *method = iface->lookupPrivateMethod(Sel: sel, Instance: isInstance))
2108 return method;
2109 }
2110
2111 // Check qualifiers.
2112 for (const auto *I : objType->quals())
2113 if (ObjCMethodDecl *method = I->lookupMethod(Sel: sel, isInstance))
2114 return method;
2115
2116 return nullptr;
2117}
2118
2119/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
2120/// list of a qualified objective pointer type.
2121ObjCMethodDecl *SemaObjC::LookupMethodInQualifiedType(
2122 Selector Sel, const ObjCObjectPointerType *OPT, bool Instance) {
2123 ObjCMethodDecl *MD = nullptr;
2124 for (const auto *PROTO : OPT->quals()) {
2125 if ((MD = PROTO->lookupMethod(Sel, isInstance: Instance))) {
2126 return MD;
2127 }
2128 }
2129 return nullptr;
2130}
2131
2132/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
2133/// objective C interface. This is a property reference expression.
2134ExprResult SemaObjC::HandleExprPropertyRefExpr(
2135 const ObjCObjectPointerType *OPT, Expr *BaseExpr, SourceLocation OpLoc,
2136 DeclarationName MemberName, SourceLocation MemberLoc,
2137 SourceLocation SuperLoc, QualType SuperType, bool Super) {
2138 ASTContext &Context = getASTContext();
2139 const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
2140 assert(IFaceT && "Expected an Interface");
2141 ObjCInterfaceDecl *IFace = IFaceT->getDecl();
2142
2143 if (!MemberName.isIdentifier()) {
2144 Diag(Loc: MemberLoc, DiagID: diag::err_invalid_property_name)
2145 << MemberName << QualType(OPT, 0);
2146 return ExprError();
2147 }
2148
2149 IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
2150
2151 SourceRange BaseRange = Super? SourceRange(SuperLoc)
2152 : BaseExpr->getSourceRange();
2153 if (SemaRef.RequireCompleteType(Loc: MemberLoc, T: OPT->getPointeeType(),
2154 DiagID: diag::err_property_not_found_forward_class,
2155 Args: MemberName, Args: BaseRange))
2156 return ExprError();
2157
2158 if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(
2159 PropertyId: Member, QueryKind: ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
2160 // Check whether we can reference this property.
2161 if (SemaRef.DiagnoseUseOfDecl(D: PD, Locs: MemberLoc))
2162 return ExprError();
2163 if (Super)
2164 return new (Context)
2165 ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
2166 OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);
2167 else
2168 return new (Context)
2169 ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
2170 OK_ObjCProperty, MemberLoc, BaseExpr);
2171 }
2172 // Check protocols on qualified interfaces.
2173 for (const auto *I : OPT->quals())
2174 if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(
2175 PropertyId: Member, QueryKind: ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
2176 // Check whether we can reference this property.
2177 if (SemaRef.DiagnoseUseOfDecl(D: PD, Locs: MemberLoc))
2178 return ExprError();
2179
2180 if (Super)
2181 return new (Context) ObjCPropertyRefExpr(
2182 PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc,
2183 SuperLoc, SuperType);
2184 else
2185 return new (Context)
2186 ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue,
2187 OK_ObjCProperty, MemberLoc, BaseExpr);
2188 }
2189 // If that failed, look for an "implicit" property by seeing if the nullary
2190 // selector is implemented.
2191
2192 // FIXME: The logic for looking up nullary and unary selectors should be
2193 // shared with the code in ActOnInstanceMessage.
2194
2195 Selector Sel = SemaRef.PP.getSelectorTable().getNullarySelector(ID: Member);
2196 ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
2197
2198 // May be found in property's qualified list.
2199 if (!Getter)
2200 Getter = LookupMethodInQualifiedType(Sel, OPT, Instance: true);
2201
2202 // If this reference is in an @implementation, check for 'private' methods.
2203 if (!Getter)
2204 Getter = IFace->lookupPrivateMethod(Sel);
2205
2206 if (Getter) {
2207 // Check if we can reference this property.
2208 if (SemaRef.DiagnoseUseOfDecl(D: Getter, Locs: MemberLoc))
2209 return ExprError();
2210 }
2211 // If we found a getter then this may be a valid dot-reference, we
2212 // will look for the matching setter, in case it is needed.
2213 Selector SetterSel = SelectorTable::constructSetterSelector(
2214 Idents&: SemaRef.PP.getIdentifierTable(), SelTable&: SemaRef.PP.getSelectorTable(), Name: Member);
2215 ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(Sel: SetterSel);
2216
2217 // May be found in property's qualified list.
2218 if (!Setter)
2219 Setter = LookupMethodInQualifiedType(Sel: SetterSel, OPT, Instance: true);
2220
2221 if (!Setter) {
2222 // If this reference is in an @implementation, also check for 'private'
2223 // methods.
2224 Setter = IFace->lookupPrivateMethod(Sel: SetterSel);
2225 }
2226
2227 if (Setter && SemaRef.DiagnoseUseOfDecl(D: Setter, Locs: MemberLoc))
2228 return ExprError();
2229
2230 // Special warning if member name used in a property-dot for a setter accessor
2231 // does not use a property with same name; e.g. obj.X = ... for a property with
2232 // name 'x'.
2233 if (Setter && Setter->isImplicit() && Setter->isPropertyAccessor() &&
2234 !IFace->FindPropertyDeclaration(
2235 PropertyId: Member, QueryKind: ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
2236 if (const ObjCPropertyDecl *PDecl = Setter->findPropertyDecl()) {
2237 // Do not warn if user is using property-dot syntax to make call to
2238 // user named setter.
2239 if (!(PDecl->getPropertyAttributes() &
2240 ObjCPropertyAttribute::kind_setter))
2241 Diag(Loc: MemberLoc,
2242 DiagID: diag::warn_property_access_suggest)
2243 << MemberName << QualType(OPT, 0) << PDecl->getName()
2244 << FixItHint::CreateReplacement(RemoveRange: MemberLoc, Code: PDecl->getName());
2245 }
2246 }
2247
2248 if (Getter || Setter) {
2249 if (Super)
2250 return new (Context)
2251 ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
2252 OK_ObjCProperty, MemberLoc, SuperLoc, SuperType);
2253 else
2254 return new (Context)
2255 ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
2256 OK_ObjCProperty, MemberLoc, BaseExpr);
2257
2258 }
2259
2260 // Attempt to correct for typos in property names.
2261 DeclFilterCCC<ObjCPropertyDecl> CCC{};
2262 if (TypoCorrection Corrected = SemaRef.CorrectTypo(
2263 Typo: DeclarationNameInfo(MemberName, MemberLoc), LookupKind: Sema::LookupOrdinaryName,
2264 S: nullptr, SS: nullptr, CCC, Mode: CorrectTypoKind::ErrorRecovery, MemberContext: IFace, EnteringContext: false,
2265 OPT)) {
2266 DeclarationName TypoResult = Corrected.getCorrection();
2267 if (TypoResult.isIdentifier() &&
2268 TypoResult.getAsIdentifierInfo() == Member) {
2269 // There is no need to try the correction if it is the same.
2270 NamedDecl *ChosenDecl =
2271 Corrected.isKeyword() ? nullptr : Corrected.getFoundDecl();
2272 if (ChosenDecl && isa<ObjCPropertyDecl>(Val: ChosenDecl))
2273 if (cast<ObjCPropertyDecl>(Val: ChosenDecl)->isClassProperty()) {
2274 // This is a class property, we should not use the instance to
2275 // access it.
2276 Diag(Loc: MemberLoc, DiagID: diag::err_class_property_found) << MemberName
2277 << OPT->getInterfaceDecl()->getName()
2278 << FixItHint::CreateReplacement(RemoveRange: BaseExpr->getSourceRange(),
2279 Code: OPT->getInterfaceDecl()->getName());
2280 return ExprError();
2281 }
2282 } else {
2283 SemaRef.diagnoseTypo(Correction: Corrected,
2284 TypoDiag: PDiag(DiagID: diag::err_property_not_found_suggest)
2285 << MemberName << QualType(OPT, 0));
2286 return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,
2287 MemberName: TypoResult, MemberLoc,
2288 SuperLoc, SuperType, Super);
2289 }
2290 }
2291 ObjCInterfaceDecl *ClassDeclared;
2292 if (ObjCIvarDecl *Ivar =
2293 IFace->lookupInstanceVariable(IVarName: Member, ClassDeclared)) {
2294 QualType T = Ivar->getType();
2295 if (const ObjCObjectPointerType * OBJPT =
2296 T->getAsObjCInterfacePointerType()) {
2297 if (SemaRef.RequireCompleteType(Loc: MemberLoc, T: OBJPT->getPointeeType(),
2298 DiagID: diag::err_property_not_as_forward_class,
2299 Args: MemberName, Args: BaseExpr))
2300 return ExprError();
2301 }
2302 Diag(Loc: MemberLoc,
2303 DiagID: diag::err_ivar_access_using_property_syntax_suggest)
2304 << MemberName << QualType(OPT, 0) << Ivar->getDeclName()
2305 << FixItHint::CreateReplacement(RemoveRange: OpLoc, Code: "->");
2306 return ExprError();
2307 }
2308
2309 Diag(Loc: MemberLoc, DiagID: diag::err_property_not_found)
2310 << MemberName << QualType(OPT, 0);
2311 if (Setter)
2312 Diag(Loc: Setter->getLocation(), DiagID: diag::note_getter_unavailable)
2313 << MemberName << BaseExpr->getSourceRange();
2314 return ExprError();
2315}
2316
2317ExprResult SemaObjC::ActOnClassPropertyRefExpr(
2318 const IdentifierInfo &receiverName, const IdentifierInfo &propertyName,
2319 SourceLocation receiverNameLoc, SourceLocation propertyNameLoc) {
2320 ASTContext &Context = getASTContext();
2321 const IdentifierInfo *receiverNamePtr = &receiverName;
2322 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(Id&: receiverNamePtr,
2323 IdLoc: receiverNameLoc);
2324
2325 QualType SuperType;
2326 if (!IFace) {
2327 // If the "receiver" is 'super' in a method, handle it as an expression-like
2328 // property reference.
2329 if (receiverNamePtr->isStr(Str: "super")) {
2330 if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(Loc: receiverNameLoc)) {
2331 if (auto classDecl = CurMethod->getClassInterface()) {
2332 SuperType = QualType(classDecl->getSuperClassType(), 0);
2333 if (CurMethod->isInstanceMethod()) {
2334 if (SuperType.isNull()) {
2335 // The current class does not have a superclass.
2336 Diag(Loc: receiverNameLoc, DiagID: diag::err_root_class_cannot_use_super)
2337 << CurMethod->getClassInterface()->getIdentifier();
2338 return ExprError();
2339 }
2340 QualType T = Context.getObjCObjectPointerType(OIT: SuperType);
2341
2342 return HandleExprPropertyRefExpr(OPT: T->castAs<ObjCObjectPointerType>(),
2343 /*BaseExpr*/nullptr,
2344 OpLoc: SourceLocation()/*OpLoc*/,
2345 MemberName: &propertyName,
2346 MemberLoc: propertyNameLoc,
2347 SuperLoc: receiverNameLoc, SuperType: T, Super: true);
2348 }
2349
2350 // Otherwise, if this is a class method, try dispatching to our
2351 // superclass.
2352 IFace = CurMethod->getClassInterface()->getSuperClass();
2353 }
2354 }
2355 }
2356
2357 if (!IFace) {
2358 Diag(Loc: receiverNameLoc, DiagID: diag::err_expected_either) << tok::identifier
2359 << tok::l_paren;
2360 return ExprError();
2361 }
2362 }
2363
2364 Selector GetterSel;
2365 Selector SetterSel;
2366 if (auto PD = IFace->FindPropertyDeclaration(
2367 PropertyId: &propertyName, QueryKind: ObjCPropertyQueryKind::OBJC_PR_query_class)) {
2368 GetterSel = PD->getGetterName();
2369 SetterSel = PD->getSetterName();
2370 } else {
2371 GetterSel = SemaRef.PP.getSelectorTable().getNullarySelector(ID: &propertyName);
2372 SetterSel = SelectorTable::constructSetterSelector(
2373 Idents&: SemaRef.PP.getIdentifierTable(), SelTable&: SemaRef.PP.getSelectorTable(),
2374 Name: &propertyName);
2375 }
2376
2377 // Search for a declared property first.
2378 ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel: GetterSel);
2379
2380 // If this reference is in an @implementation, check for 'private' methods.
2381 if (!Getter)
2382 Getter = IFace->lookupPrivateClassMethod(Sel: GetterSel);
2383
2384 if (Getter) {
2385 // FIXME: refactor/share with ActOnMemberReference().
2386 // Check if we can reference this property.
2387 if (SemaRef.DiagnoseUseOfDecl(D: Getter, Locs: propertyNameLoc))
2388 return ExprError();
2389 }
2390
2391 // Look for the matching setter, in case it is needed.
2392 ObjCMethodDecl *Setter = IFace->lookupClassMethod(Sel: SetterSel);
2393 if (!Setter) {
2394 // If this reference is in an @implementation, also check for 'private'
2395 // methods.
2396 Setter = IFace->lookupPrivateClassMethod(Sel: SetterSel);
2397 }
2398 // Look through local category implementations associated with the class.
2399 if (!Setter)
2400 Setter = IFace->getCategoryClassMethod(Sel: SetterSel);
2401
2402 if (Setter && SemaRef.DiagnoseUseOfDecl(D: Setter, Locs: propertyNameLoc))
2403 return ExprError();
2404
2405 if (Getter || Setter) {
2406 if (!SuperType.isNull())
2407 return new (Context)
2408 ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue,
2409 OK_ObjCProperty, propertyNameLoc, receiverNameLoc,
2410 SuperType);
2411
2412 return new (Context) ObjCPropertyRefExpr(
2413 Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty,
2414 propertyNameLoc, receiverNameLoc, IFace);
2415 }
2416 return ExprError(Diag(Loc: propertyNameLoc, DiagID: diag::err_property_not_found)
2417 << &propertyName << Context.getObjCInterfaceType(Decl: IFace));
2418}
2419
2420namespace {
2421
2422class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback {
2423 public:
2424 ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
2425 // Determine whether "super" is acceptable in the current context.
2426 if (Method && Method->getClassInterface())
2427 WantObjCSuper = Method->getClassInterface()->getSuperClass();
2428 }
2429
2430 bool ValidateCandidate(const TypoCorrection &candidate) override {
2431 return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
2432 candidate.isKeyword(Str: "super");
2433 }
2434
2435 std::unique_ptr<CorrectionCandidateCallback> clone() override {
2436 return std::make_unique<ObjCInterfaceOrSuperCCC>(args&: *this);
2437 }
2438};
2439
2440} // end anonymous namespace
2441
2442SemaObjC::ObjCMessageKind
2443SemaObjC::getObjCMessageKind(Scope *S, IdentifierInfo *Name,
2444 SourceLocation NameLoc, bool IsSuper,
2445 bool HasTrailingDot, ParsedType &ReceiverType) {
2446 ASTContext &Context = getASTContext();
2447 ReceiverType = nullptr;
2448
2449 // If the identifier is "super" and there is no trailing dot, we're
2450 // messaging super. If the identifier is "super" and there is a
2451 // trailing dot, it's an instance message.
2452 if (IsSuper && S->isInObjcMethodScope())
2453 return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;
2454
2455 LookupResult Result(SemaRef, Name, NameLoc, Sema::LookupOrdinaryName);
2456 SemaRef.LookupName(R&: Result, S);
2457
2458 switch (Result.getResultKind()) {
2459 case LookupResultKind::NotFound:
2460 // Normal name lookup didn't find anything. If we're in an
2461 // Objective-C method, look for ivars. If we find one, we're done!
2462 // FIXME: This is a hack. Ivar lookup should be part of normal
2463 // lookup.
2464 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2465 if (!Method->getClassInterface()) {
2466 // Fall back: let the parser try to parse it as an instance message.
2467 return ObjCInstanceMessage;
2468 }
2469
2470 ObjCInterfaceDecl *ClassDeclared;
2471 if (Method->getClassInterface()->lookupInstanceVariable(IVarName: Name,
2472 ClassDeclared))
2473 return ObjCInstanceMessage;
2474 }
2475
2476 // Break out; we'll perform typo correction below.
2477 break;
2478
2479 case LookupResultKind::NotFoundInCurrentInstantiation:
2480 case LookupResultKind::FoundOverloaded:
2481 case LookupResultKind::FoundUnresolvedValue:
2482 case LookupResultKind::Ambiguous:
2483 Result.suppressDiagnostics();
2484 return ObjCInstanceMessage;
2485
2486 case LookupResultKind::Found: {
2487 // If the identifier is a class or not, and there is a trailing dot,
2488 // it's an instance message.
2489 if (HasTrailingDot)
2490 return ObjCInstanceMessage;
2491 // We found something. If it's a type, then we have a class
2492 // message. Otherwise, it's an instance message.
2493 NamedDecl *ND = Result.getFoundDecl();
2494 QualType T;
2495 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(Val: ND))
2496 T = Context.getObjCInterfaceType(Decl: Class);
2497 else if (TypeDecl *Type = dyn_cast<TypeDecl>(Val: ND)) {
2498 SemaRef.DiagnoseUseOfDecl(D: Type, Locs: NameLoc);
2499 T = Context.getTypeDeclType(Keyword: ElaboratedTypeKeyword::None,
2500 /*Qualifier=*/std::nullopt, Decl: Type);
2501 } else
2502 return ObjCInstanceMessage;
2503
2504 // We have a class message, and T is the type we're
2505 // messaging. Build source-location information for it.
2506 TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, Loc: NameLoc);
2507 ReceiverType = SemaRef.CreateParsedType(T, TInfo: TSInfo);
2508 return ObjCClassMessage;
2509 }
2510 }
2511
2512 ObjCInterfaceOrSuperCCC CCC(SemaRef.getCurMethodDecl());
2513 if (TypoCorrection Corrected = SemaRef.CorrectTypo(
2514 Typo: Result.getLookupNameInfo(), LookupKind: Result.getLookupKind(), S, SS: nullptr, CCC,
2515 Mode: CorrectTypoKind::ErrorRecovery, MemberContext: nullptr, EnteringContext: false, OPT: nullptr, RecordFailure: false)) {
2516 if (Corrected.isKeyword()) {
2517 // If we've found the keyword "super" (the only keyword that would be
2518 // returned by CorrectTypo), this is a send to super.
2519 SemaRef.diagnoseTypo(Correction: Corrected, TypoDiag: PDiag(DiagID: diag::err_unknown_receiver_suggest)
2520 << Name);
2521 return ObjCSuperMessage;
2522 } else if (ObjCInterfaceDecl *Class =
2523 Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
2524 // If we found a declaration, correct when it refers to an Objective-C
2525 // class.
2526 SemaRef.diagnoseTypo(Correction: Corrected, TypoDiag: PDiag(DiagID: diag::err_unknown_receiver_suggest)
2527 << Name);
2528 QualType T = Context.getObjCInterfaceType(Decl: Class);
2529 TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, Loc: NameLoc);
2530 ReceiverType = SemaRef.CreateParsedType(T, TInfo: TSInfo);
2531 return ObjCClassMessage;
2532 }
2533 }
2534
2535 // Fall back: let the parser try to parse it as an instance message.
2536 return ObjCInstanceMessage;
2537}
2538
2539ExprResult SemaObjC::ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
2540 Selector Sel, SourceLocation LBracLoc,
2541 ArrayRef<SourceLocation> SelectorLocs,
2542 SourceLocation RBracLoc,
2543 MultiExprArg Args) {
2544 ASTContext &Context = getASTContext();
2545 // Determine whether we are inside a method or not.
2546 ObjCMethodDecl *Method = tryCaptureObjCSelf(Loc: SuperLoc);
2547 if (!Method) {
2548 Diag(Loc: SuperLoc, DiagID: diag::err_invalid_receiver_to_message_super);
2549 return ExprError();
2550 }
2551
2552 ObjCInterfaceDecl *Class = Method->getClassInterface();
2553 if (!Class) {
2554 Diag(Loc: SuperLoc, DiagID: diag::err_no_super_class_message)
2555 << Method->getDeclName();
2556 return ExprError();
2557 }
2558
2559 QualType SuperTy(Class->getSuperClassType(), 0);
2560 if (SuperTy.isNull()) {
2561 // The current class does not have a superclass.
2562 Diag(Loc: SuperLoc, DiagID: diag::err_root_class_cannot_use_super)
2563 << Class->getIdentifier();
2564 return ExprError();
2565 }
2566
2567 // We are in a method whose class has a superclass, so 'super'
2568 // is acting as a keyword.
2569 if (Method->getSelector() == Sel)
2570 SemaRef.getCurFunction()->ObjCShouldCallSuper = false;
2571
2572 if (Method->isInstanceMethod()) {
2573 // Since we are in an instance method, this is an instance
2574 // message to the superclass instance.
2575 SuperTy = Context.getObjCObjectPointerType(OIT: SuperTy);
2576 return BuildInstanceMessage(Receiver: nullptr, ReceiverType: SuperTy, SuperLoc,
2577 Sel, /*Method=*/nullptr,
2578 LBracLoc, SelectorLocs, RBracLoc, Args);
2579 }
2580
2581 // Since we are in a class method, this is a class message to
2582 // the superclass.
2583 return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr,
2584 ReceiverType: SuperTy,
2585 SuperLoc, Sel, /*Method=*/nullptr,
2586 LBracLoc, SelectorLocs, RBracLoc, Args);
2587}
2588
2589ExprResult SemaObjC::BuildClassMessageImplicit(QualType ReceiverType,
2590 bool isSuperReceiver,
2591 SourceLocation Loc, Selector Sel,
2592 ObjCMethodDecl *Method,
2593 MultiExprArg Args) {
2594 ASTContext &Context = getASTContext();
2595 TypeSourceInfo *receiverTypeInfo = nullptr;
2596 if (!ReceiverType.isNull())
2597 receiverTypeInfo = Context.getTrivialTypeSourceInfo(T: ReceiverType);
2598
2599 assert(((isSuperReceiver && Loc.isValid()) || receiverTypeInfo) &&
2600 "Either the super receiver location needs to be valid or the receiver "
2601 "needs valid type source information");
2602 return BuildClassMessage(ReceiverTypeInfo: receiverTypeInfo, ReceiverType,
2603 /*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(),
2604 Sel, Method, LBracLoc: Loc, SelectorLocs: Loc, RBracLoc: Loc, Args,
2605 /*isImplicit=*/true);
2606}
2607
2608static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,
2609 unsigned DiagID,
2610 bool (*refactor)(const ObjCMessageExpr *,
2611 const NSAPI &, edit::Commit &)) {
2612 SourceLocation MsgLoc = Msg->getExprLoc();
2613 if (S.Diags.isIgnored(DiagID, Loc: MsgLoc))
2614 return;
2615
2616 SourceManager &SM = S.SourceMgr;
2617 edit::Commit ECommit(SM, S.LangOpts);
2618 if (refactor(Msg, *S.ObjC().NSAPIObj, ECommit)) {
2619 auto Builder = S.Diag(Loc: MsgLoc, DiagID)
2620 << Msg->getSelector() << Msg->getSourceRange();
2621 // FIXME: Don't emit diagnostic at all if fixits are non-commitable.
2622 if (!ECommit.isCommitable())
2623 return;
2624 for (edit::Commit::edit_iterator
2625 I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) {
2626 const edit::Commit::Edit &Edit = *I;
2627 switch (Edit.Kind) {
2628 case edit::Commit::Act_Insert:
2629 Builder.AddFixItHint(Hint: FixItHint::CreateInsertion(InsertionLoc: Edit.OrigLoc,
2630 Code: Edit.Text,
2631 BeforePreviousInsertions: Edit.BeforePrev));
2632 break;
2633 case edit::Commit::Act_InsertFromRange:
2634 Builder.AddFixItHint(
2635 Hint: FixItHint::CreateInsertionFromRange(InsertionLoc: Edit.OrigLoc,
2636 FromRange: Edit.getInsertFromRange(SM),
2637 BeforePreviousInsertions: Edit.BeforePrev));
2638 break;
2639 case edit::Commit::Act_Remove:
2640 Builder.AddFixItHint(Hint: FixItHint::CreateRemoval(RemoveRange: Edit.getFileRange(SM)));
2641 break;
2642 }
2643 }
2644 }
2645}
2646
2647static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {
2648 applyCocoaAPICheck(S, Msg, DiagID: diag::warn_objc_redundant_literal_use,
2649 refactor: edit::rewriteObjCRedundantCallWithLiteral);
2650}
2651
2652static void checkFoundationAPI(Sema &S, SourceLocation Loc,
2653 const ObjCMethodDecl *Method,
2654 ArrayRef<Expr *> Args, QualType ReceiverType,
2655 bool IsClassObjectCall) {
2656 // Check if this is a performSelector method that uses a selector that returns
2657 // a record or a vector type.
2658 if (Method->getSelector().getMethodFamily() != OMF_performSelector ||
2659 Args.empty())
2660 return;
2661 const auto *SE = dyn_cast<ObjCSelectorExpr>(Val: Args[0]->IgnoreParens());
2662 if (!SE)
2663 return;
2664 ObjCMethodDecl *ImpliedMethod;
2665 if (!IsClassObjectCall) {
2666 const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>();
2667 if (!OPT || !OPT->getInterfaceDecl())
2668 return;
2669 ImpliedMethod =
2670 OPT->getInterfaceDecl()->lookupInstanceMethod(Sel: SE->getSelector());
2671 if (!ImpliedMethod)
2672 ImpliedMethod =
2673 OPT->getInterfaceDecl()->lookupPrivateMethod(Sel: SE->getSelector());
2674 } else {
2675 const auto *IT = ReceiverType->getAs<ObjCInterfaceType>();
2676 if (!IT)
2677 return;
2678 ImpliedMethod = IT->getDecl()->lookupClassMethod(Sel: SE->getSelector());
2679 if (!ImpliedMethod)
2680 ImpliedMethod =
2681 IT->getDecl()->lookupPrivateClassMethod(Sel: SE->getSelector());
2682 }
2683 if (!ImpliedMethod)
2684 return;
2685 QualType Ret = ImpliedMethod->getReturnType();
2686 if (Ret->isRecordType() || Ret->isVectorType() || Ret->isExtVectorType()) {
2687 S.Diag(Loc, DiagID: diag::warn_objc_unsafe_perform_selector)
2688 << Method->getSelector()
2689 << (!Ret->isRecordType()
2690 ? /*Vector*/ 2
2691 : Ret->isUnionType() ? /*Union*/ 1 : /*Struct*/ 0);
2692 S.Diag(Loc: ImpliedMethod->getBeginLoc(),
2693 DiagID: diag::note_objc_unsafe_perform_selector_method_declared_here)
2694 << ImpliedMethod->getSelector() << Ret;
2695 }
2696}
2697
2698/// Diagnose use of %s directive in an NSString which is being passed
2699/// as formatting string to formatting method.
2700static void
2701DiagnoseCStringFormatDirectiveInObjCAPI(Sema &S,
2702 ObjCMethodDecl *Method,
2703 Selector Sel,
2704 Expr **Args, unsigned NumArgs) {
2705 unsigned Idx = 0;
2706 bool Format = false;
2707 ObjCStringFormatFamily SFFamily = Sel.getStringFormatFamily();
2708 if (SFFamily == ObjCStringFormatFamily::SFF_NSString) {
2709 Idx = 0;
2710 Format = true;
2711 }
2712 else if (Method) {
2713 for (const auto *I : Method->specific_attrs<FormatAttr>()) {
2714 if (S.ObjC().GetFormatNSStringIdx(Format: I, Idx)) {
2715 Format = true;
2716 break;
2717 }
2718 }
2719 }
2720 if (!Format || NumArgs <= Idx)
2721 return;
2722
2723 Expr *FormatExpr = Args[Idx];
2724 if (ObjCStringLiteral *OSL =
2725 dyn_cast<ObjCStringLiteral>(Val: FormatExpr->IgnoreParenImpCasts())) {
2726 StringLiteral *FormatString = OSL->getString();
2727 if (S.FormatStringHasSArg(FExpr: FormatString)) {
2728 S.Diag(Loc: FormatExpr->getExprLoc(), DiagID: diag::warn_objc_cdirective_format_string)
2729 << "%s" << 0 << 0;
2730 if (Method)
2731 S.Diag(Loc: Method->getLocation(), DiagID: diag::note_method_declared_at)
2732 << Method->getDeclName();
2733 }
2734 }
2735}
2736
2737/// Build an Objective-C class message expression.
2738///
2739/// This routine takes care of both normal class messages and
2740/// class messages to the superclass.
2741///
2742/// \param ReceiverTypeInfo Type source information that describes the
2743/// receiver of this message. This may be NULL, in which case we are
2744/// sending to the superclass and \p SuperLoc must be a valid source
2745/// location.
2746
2747/// \param ReceiverType The type of the object receiving the
2748/// message. When \p ReceiverTypeInfo is non-NULL, this is the same
2749/// type as that refers to. For a superclass send, this is the type of
2750/// the superclass.
2751///
2752/// \param SuperLoc The location of the "super" keyword in a
2753/// superclass message.
2754///
2755/// \param Sel The selector to which the message is being sent.
2756///
2757/// \param Method The method that this class message is invoking, if
2758/// already known.
2759///
2760/// \param LBracLoc The location of the opening square bracket ']'.
2761///
2762/// \param RBracLoc The location of the closing square bracket ']'.
2763///
2764/// \param ArgsIn The message arguments.
2765ExprResult SemaObjC::BuildClassMessage(
2766 TypeSourceInfo *ReceiverTypeInfo, QualType ReceiverType,
2767 SourceLocation SuperLoc, Selector Sel, ObjCMethodDecl *Method,
2768 SourceLocation LBracLoc, ArrayRef<SourceLocation> SelectorLocs,
2769 SourceLocation RBracLoc, MultiExprArg ArgsIn, bool isImplicit) {
2770 ASTContext &Context = getASTContext();
2771 SourceLocation Loc = SuperLoc.isValid()? SuperLoc
2772 : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
2773 if (LBracLoc.isInvalid()) {
2774 Diag(Loc, DiagID: diag::err_missing_open_square_message_send)
2775 << FixItHint::CreateInsertion(InsertionLoc: Loc, Code: "[");
2776 LBracLoc = Loc;
2777 }
2778 ArrayRef<SourceLocation> SelectorSlotLocs;
2779 if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
2780 SelectorSlotLocs = SelectorLocs;
2781 else
2782 SelectorSlotLocs = Loc;
2783 SourceLocation SelLoc = SelectorSlotLocs.front();
2784
2785 if (ReceiverType->isDependentType()) {
2786 // If the receiver type is dependent, we can't type-check anything
2787 // at this point. Build a dependent expression.
2788 unsigned NumArgs = ArgsIn.size();
2789 Expr **Args = ArgsIn.data();
2790 assert(SuperLoc.isInvalid() && "Message to super with dependent type");
2791 return ObjCMessageExpr::Create(Context, T: ReceiverType, VK: VK_PRValue, LBracLoc,
2792 Receiver: ReceiverTypeInfo, Sel, SelLocs: SelectorLocs,
2793 /*Method=*/nullptr, Args: ArrayRef(Args, NumArgs),
2794 RBracLoc, isImplicit);
2795 }
2796
2797 // Find the class to which we are sending this message.
2798 ObjCInterfaceDecl *Class = nullptr;
2799 const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
2800 if (!ClassType || !(Class = ClassType->getInterface())) {
2801 Diag(Loc, DiagID: diag::err_invalid_receiver_class_message)
2802 << ReceiverType;
2803 return ExprError();
2804 }
2805 assert(Class && "We don't know which class we're messaging?");
2806 // objc++ diagnoses during typename annotation.
2807 if (!getLangOpts().CPlusPlus)
2808 (void)SemaRef.DiagnoseUseOfDecl(D: Class, Locs: SelectorSlotLocs);
2809 // Find the method we are messaging.
2810 if (!Method) {
2811 SourceRange TypeRange
2812 = SuperLoc.isValid()? SourceRange(SuperLoc)
2813 : ReceiverTypeInfo->getTypeLoc().getSourceRange();
2814 if (SemaRef.RequireCompleteType(Loc, T: Context.getObjCInterfaceType(Decl: Class),
2815 DiagID: (getLangOpts().ObjCAutoRefCount
2816 ? diag::err_arc_receiver_forward_class
2817 : diag::warn_receiver_forward_class),
2818 Args: TypeRange)) {
2819 // A forward class used in messaging is treated as a 'Class'
2820 Method = LookupFactoryMethodInGlobalPool(Sel,
2821 R: SourceRange(LBracLoc, RBracLoc));
2822 if (Method && !getLangOpts().ObjCAutoRefCount)
2823 Diag(Loc: Method->getLocation(), DiagID: diag::note_method_sent_forward_class)
2824 << Method->getDeclName();
2825 }
2826 if (!Method)
2827 Method = Class->lookupClassMethod(Sel);
2828
2829 // If we have an implementation in scope, check "private" methods.
2830 if (!Method)
2831 Method = Class->lookupPrivateClassMethod(Sel);
2832
2833 if (Method && SemaRef.DiagnoseUseOfDecl(D: Method, Locs: SelectorSlotLocs, UnknownObjCClass: nullptr,
2834 ObjCPropertyAccess: false, AvoidPartialAvailabilityChecks: false, ClassReceiver: Class))
2835 return ExprError();
2836 }
2837
2838 // Check the argument types and determine the result type.
2839 QualType ReturnType;
2840 ExprValueKind VK = VK_PRValue;
2841
2842 unsigned NumArgs = ArgsIn.size();
2843 Expr **Args = ArgsIn.data();
2844 if (CheckMessageArgumentTypes(/*Receiver=*/nullptr, ReceiverType,
2845 Args: MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
2846 Method, isClassMessage: true, isSuperMessage: SuperLoc.isValid(), lbrac: LBracLoc,
2847 rbrac: RBracLoc, RecRange: SourceRange(), ReturnType, VK))
2848 return ExprError();
2849
2850 if (Method && !Method->getReturnType()->isVoidType() &&
2851 SemaRef.RequireCompleteType(
2852 Loc: LBracLoc, T: Method->getReturnType(),
2853 DiagID: diag::err_illegal_message_expr_incomplete_type))
2854 return ExprError();
2855
2856 if (Method && Method->isDirectMethod() && SuperLoc.isValid()) {
2857 Diag(Loc: SuperLoc, DiagID: diag::err_messaging_super_with_direct_method)
2858 << FixItHint::CreateReplacement(
2859 RemoveRange: SuperLoc, Code: getLangOpts().ObjCAutoRefCount
2860 ? "self"
2861 : Method->getClassInterface()->getName());
2862 Diag(Loc: Method->getLocation(), DiagID: diag::note_direct_method_declared_at)
2863 << Method->getDeclName();
2864 }
2865
2866 // Warn about explicit call of +initialize on its own class. But not on 'super'.
2867 if (Method && Method->getMethodFamily() == OMF_initialize) {
2868 if (!SuperLoc.isValid()) {
2869 const ObjCInterfaceDecl *ID =
2870 dyn_cast<ObjCInterfaceDecl>(Val: Method->getDeclContext());
2871 if (ID == Class) {
2872 Diag(Loc, DiagID: diag::warn_direct_initialize_call);
2873 Diag(Loc: Method->getLocation(), DiagID: diag::note_method_declared_at)
2874 << Method->getDeclName();
2875 }
2876 } else if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) {
2877 // [super initialize] is allowed only within an +initialize implementation
2878 if (CurMeth->getMethodFamily() != OMF_initialize) {
2879 Diag(Loc, DiagID: diag::warn_direct_super_initialize_call);
2880 Diag(Loc: Method->getLocation(), DiagID: diag::note_method_declared_at)
2881 << Method->getDeclName();
2882 Diag(Loc: CurMeth->getLocation(), DiagID: diag::note_method_declared_at)
2883 << CurMeth->getDeclName();
2884 }
2885 }
2886 }
2887
2888 DiagnoseCStringFormatDirectiveInObjCAPI(S&: SemaRef, Method, Sel, Args, NumArgs);
2889
2890 // Construct the appropriate ObjCMessageExpr.
2891 ObjCMessageExpr *Result;
2892 if (SuperLoc.isValid())
2893 Result = ObjCMessageExpr::Create(
2894 Context, T: ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/false,
2895 SuperType: ReceiverType, Sel, SelLocs: SelectorLocs, Method, Args: ArrayRef(Args, NumArgs),
2896 RBracLoc, isImplicit);
2897 else {
2898 Result = ObjCMessageExpr::Create(
2899 Context, T: ReturnType, VK, LBracLoc, Receiver: ReceiverTypeInfo, Sel, SelLocs: SelectorLocs,
2900 Method, Args: ArrayRef(Args, NumArgs), RBracLoc, isImplicit);
2901 if (!isImplicit)
2902 checkCocoaAPI(S&: SemaRef, Msg: Result);
2903 }
2904 if (Method)
2905 checkFoundationAPI(S&: SemaRef, Loc: SelLoc, Method, Args: ArrayRef(Args, NumArgs),
2906 ReceiverType, /*IsClassObjectCall=*/true);
2907 return SemaRef.MaybeBindToTemporary(E: Result);
2908}
2909
2910// ActOnClassMessage - used for both unary and keyword messages.
2911// ArgExprs is optional - if it is present, the number of expressions
2912// is obtained from Sel.getNumArgs().
2913ExprResult SemaObjC::ActOnClassMessage(Scope *S, ParsedType Receiver,
2914 Selector Sel, SourceLocation LBracLoc,
2915 ArrayRef<SourceLocation> SelectorLocs,
2916 SourceLocation RBracLoc,
2917 MultiExprArg Args) {
2918 ASTContext &Context = getASTContext();
2919 TypeSourceInfo *ReceiverTypeInfo;
2920 QualType ReceiverType =
2921 SemaRef.GetTypeFromParser(Ty: Receiver, TInfo: &ReceiverTypeInfo);
2922 if (ReceiverType.isNull())
2923 return ExprError();
2924
2925 if (!ReceiverTypeInfo)
2926 ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(T: ReceiverType, Loc: LBracLoc);
2927
2928 return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
2929 /*SuperLoc=*/SourceLocation(), Sel,
2930 /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc,
2931 ArgsIn: Args);
2932}
2933
2934ExprResult SemaObjC::BuildInstanceMessageImplicit(
2935 Expr *Receiver, QualType ReceiverType, SourceLocation Loc, Selector Sel,
2936 ObjCMethodDecl *Method, MultiExprArg Args) {
2937 return BuildInstanceMessage(Receiver, ReceiverType,
2938 /*SuperLoc=*/!Receiver ? Loc : SourceLocation(),
2939 Sel, Method, LBracLoc: Loc, SelectorLocs: Loc, RBracLoc: Loc, Args,
2940 /*isImplicit=*/true);
2941}
2942
2943static bool isMethodDeclaredInRootProtocol(Sema &S, const ObjCMethodDecl *M) {
2944 if (!S.ObjC().NSAPIObj)
2945 return false;
2946 const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Val: M->getDeclContext());
2947 if (!Protocol)
2948 return false;
2949 const IdentifierInfo *II =
2950 S.ObjC().NSAPIObj->getNSClassId(K: NSAPI::ClassId_NSObject);
2951 if (const auto *RootClass = dyn_cast_or_null<ObjCInterfaceDecl>(
2952 Val: S.LookupSingleName(S: S.TUScope, Name: II, Loc: Protocol->getBeginLoc(),
2953 NameKind: Sema::LookupOrdinaryName))) {
2954 for (const ObjCProtocolDecl *P : RootClass->all_referenced_protocols()) {
2955 if (P->getCanonicalDecl() == Protocol->getCanonicalDecl())
2956 return true;
2957 }
2958 }
2959 return false;
2960}
2961
2962/// Build an Objective-C instance message expression.
2963///
2964/// This routine takes care of both normal instance messages and
2965/// instance messages to the superclass instance.
2966///
2967/// \param Receiver The expression that computes the object that will
2968/// receive this message. This may be empty, in which case we are
2969/// sending to the superclass instance and \p SuperLoc must be a valid
2970/// source location.
2971///
2972/// \param ReceiverType The (static) type of the object receiving the
2973/// message. When a \p Receiver expression is provided, this is the
2974/// same type as that expression. For a superclass instance send, this
2975/// is a pointer to the type of the superclass.
2976///
2977/// \param SuperLoc The location of the "super" keyword in a
2978/// superclass instance message.
2979///
2980/// \param Sel The selector to which the message is being sent.
2981///
2982/// \param Method The method that this instance message is invoking, if
2983/// already known.
2984///
2985/// \param LBracLoc The location of the opening square bracket ']'.
2986///
2987/// \param RBracLoc The location of the closing square bracket ']'.
2988///
2989/// \param ArgsIn The message arguments.
2990ExprResult SemaObjC::BuildInstanceMessage(
2991 Expr *Receiver, QualType ReceiverType, SourceLocation SuperLoc,
2992 Selector Sel, ObjCMethodDecl *Method, SourceLocation LBracLoc,
2993 ArrayRef<SourceLocation> SelectorLocs, SourceLocation RBracLoc,
2994 MultiExprArg ArgsIn, bool isImplicit) {
2995 assert((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the "
2996 "SuperLoc must be valid so we can "
2997 "use it instead.");
2998 ASTContext &Context = getASTContext();
2999
3000 // The location of the receiver.
3001 SourceLocation Loc = SuperLoc.isValid() ? SuperLoc : Receiver->getBeginLoc();
3002 SourceRange RecRange =
3003 SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
3004 ArrayRef<SourceLocation> SelectorSlotLocs;
3005 if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
3006 SelectorSlotLocs = SelectorLocs;
3007 else
3008 SelectorSlotLocs = Loc;
3009 SourceLocation SelLoc = SelectorSlotLocs.front();
3010
3011 if (LBracLoc.isInvalid()) {
3012 Diag(Loc, DiagID: diag::err_missing_open_square_message_send)
3013 << FixItHint::CreateInsertion(InsertionLoc: Loc, Code: "[");
3014 LBracLoc = Loc;
3015 }
3016
3017 // If we have a receiver expression, perform appropriate promotions
3018 // and determine receiver type.
3019 if (Receiver) {
3020 if (Receiver->hasPlaceholderType()) {
3021 ExprResult Result;
3022 if (Receiver->getType() == Context.UnknownAnyTy)
3023 Result =
3024 SemaRef.forceUnknownAnyToType(E: Receiver, ToType: Context.getObjCIdType());
3025 else
3026 Result = SemaRef.CheckPlaceholderExpr(E: Receiver);
3027 if (Result.isInvalid()) return ExprError();
3028 Receiver = Result.get();
3029 }
3030
3031 if (Receiver->isTypeDependent()) {
3032 // If the receiver is type-dependent, we can't type-check anything
3033 // at this point. Build a dependent expression.
3034 unsigned NumArgs = ArgsIn.size();
3035 Expr **Args = ArgsIn.data();
3036 assert(SuperLoc.isInvalid() && "Message to super with dependent type");
3037 return ObjCMessageExpr::Create(
3038 Context, T: Context.DependentTy, VK: VK_PRValue, LBracLoc, Receiver, Sel,
3039 SeLocs: SelectorLocs, /*Method=*/nullptr, Args: ArrayRef(Args, NumArgs), RBracLoc,
3040 isImplicit);
3041 }
3042
3043 // If necessary, apply function/array conversion to the receiver.
3044 // C99 6.7.5.3p[7,8].
3045 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Receiver);
3046 if (Result.isInvalid())
3047 return ExprError();
3048 Receiver = Result.get();
3049 ReceiverType = Receiver->getType();
3050
3051 // If the receiver is an ObjC pointer, a block pointer, or an
3052 // __attribute__((NSObject)) pointer, we don't need to do any
3053 // special conversion in order to look up a receiver.
3054 if (ReceiverType->isObjCRetainableType()) {
3055 // do nothing
3056 } else if (!getLangOpts().ObjCAutoRefCount &&
3057 !Context.getObjCIdType().isNull() &&
3058 (ReceiverType->isPointerType() ||
3059 ReceiverType->isIntegerType())) {
3060 // Implicitly convert integers and pointers to 'id' but emit a warning.
3061 // But not in ARC.
3062 Diag(Loc, DiagID: diag::warn_bad_receiver_type) << ReceiverType << RecRange;
3063 if (ReceiverType->isPointerType()) {
3064 Receiver = SemaRef
3065 .ImpCastExprToType(E: Receiver, Type: Context.getObjCIdType(),
3066 CK: CK_CPointerToObjCPointerCast)
3067 .get();
3068 } else {
3069 // TODO: specialized warning on null receivers?
3070 bool IsNull = Receiver->isNullPointerConstant(Ctx&: Context,
3071 NPC: Expr::NPC_ValueDependentIsNull);
3072 CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
3073 Receiver =
3074 SemaRef.ImpCastExprToType(E: Receiver, Type: Context.getObjCIdType(), CK: Kind)
3075 .get();
3076 }
3077 ReceiverType = Receiver->getType();
3078 } else if (getLangOpts().CPlusPlus) {
3079 // The receiver must be a complete type.
3080 if (SemaRef.RequireCompleteType(Loc, T: Receiver->getType(),
3081 DiagID: diag::err_incomplete_receiver_type))
3082 return ExprError();
3083
3084 ExprResult result =
3085 SemaRef.PerformContextuallyConvertToObjCPointer(From: Receiver);
3086 if (result.isUsable()) {
3087 Receiver = result.get();
3088 ReceiverType = Receiver->getType();
3089 }
3090 }
3091 }
3092
3093 // There's a somewhat weird interaction here where we assume that we
3094 // won't actually have a method unless we also don't need to do some
3095 // of the more detailed type-checking on the receiver.
3096
3097 if (!Method) {
3098 // Handle messages to id and __kindof types (where we use the
3099 // global method pool).
3100 const ObjCObjectType *typeBound = nullptr;
3101 bool receiverIsIdLike = ReceiverType->isObjCIdOrObjectKindOfType(ctx: Context,
3102 bound&: typeBound);
3103 if (receiverIsIdLike || ReceiverType->isBlockPointerType() ||
3104 (Receiver && Context.isObjCNSObjectType(Ty: Receiver->getType()))) {
3105 SmallVector<ObjCMethodDecl*, 4> Methods;
3106 // If we have a type bound, further filter the methods.
3107 CollectMultipleMethodsInGlobalPool(Sel, Methods, InstanceFirst: true/*InstanceFirst*/,
3108 CheckTheOther: true/*CheckTheOther*/, TypeBound: typeBound);
3109 if (!Methods.empty()) {
3110 // We choose the first method as the initial candidate, then try to
3111 // select a better one.
3112 Method = Methods[0];
3113
3114 if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(
3115 Sel, Args: ArgsIn, IsInstance: Method->isInstanceMethod(), Methods))
3116 Method = BestMethod;
3117
3118 if (!AreMultipleMethodsInGlobalPool(Sel, BestMethod: Method,
3119 R: SourceRange(LBracLoc, RBracLoc),
3120 receiverIdOrClass: receiverIsIdLike, Methods))
3121 SemaRef.DiagnoseUseOfDecl(D: Method, Locs: SelectorSlotLocs);
3122 }
3123 } else if (ReceiverType->isObjCClassOrClassKindOfType() ||
3124 ReceiverType->isObjCQualifiedClassType()) {
3125 // Handle messages to Class.
3126 // We allow sending a message to a qualified Class ("Class<foo>"), which
3127 // is ok as long as one of the protocols implements the selector (if not,
3128 // warn).
3129 if (!ReceiverType->isObjCClassOrClassKindOfType()) {
3130 const ObjCObjectPointerType *QClassTy
3131 = ReceiverType->getAsObjCQualifiedClassType();
3132 // Search protocols for class methods.
3133 Method = LookupMethodInQualifiedType(Sel, OPT: QClassTy, Instance: false);
3134 if (!Method) {
3135 Method = LookupMethodInQualifiedType(Sel, OPT: QClassTy, Instance: true);
3136 // warn if instance method found for a Class message.
3137 if (Method && !isMethodDeclaredInRootProtocol(S&: SemaRef, M: Method)) {
3138 Diag(Loc: SelLoc, DiagID: diag::warn_instance_method_on_class_found)
3139 << Method->getSelector() << Sel;
3140 Diag(Loc: Method->getLocation(), DiagID: diag::note_method_declared_at)
3141 << Method->getDeclName();
3142 }
3143 }
3144 } else {
3145 if (ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl()) {
3146 if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
3147 // As a guess, try looking for the method in the current interface.
3148 // This very well may not produce the "right" method.
3149
3150 // First check the public methods in the class interface.
3151 Method = ClassDecl->lookupClassMethod(Sel);
3152
3153 if (!Method)
3154 Method = ClassDecl->lookupPrivateClassMethod(Sel);
3155
3156 if (Method && SemaRef.DiagnoseUseOfDecl(D: Method, Locs: SelectorSlotLocs))
3157 return ExprError();
3158 }
3159 }
3160 if (!Method) {
3161 // If not messaging 'self', look for any factory method named 'Sel'.
3162 if (!Receiver || !isSelfExpr(RExpr: Receiver)) {
3163 // If no class (factory) method was found, check if an _instance_
3164 // method of the same name exists in the root class only.
3165 SmallVector<ObjCMethodDecl*, 4> Methods;
3166 CollectMultipleMethodsInGlobalPool(Sel, Methods,
3167 InstanceFirst: false/*InstanceFirst*/,
3168 CheckTheOther: true/*CheckTheOther*/);
3169 if (!Methods.empty()) {
3170 // We choose the first method as the initial candidate, then try
3171 // to select a better one.
3172 Method = Methods[0];
3173
3174 // If we find an instance method, emit warning.
3175 if (Method->isInstanceMethod()) {
3176 if (const ObjCInterfaceDecl *ID =
3177 dyn_cast<ObjCInterfaceDecl>(Val: Method->getDeclContext())) {
3178 if (ID->getSuperClass())
3179 Diag(Loc: SelLoc, DiagID: diag::warn_root_inst_method_not_found)
3180 << Sel << SourceRange(LBracLoc, RBracLoc);
3181 }
3182 }
3183
3184 if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(
3185 Sel, Args: ArgsIn, IsInstance: Method->isInstanceMethod(), Methods))
3186 Method = BestMethod;
3187 }
3188 }
3189 }
3190 }
3191 } else {
3192 ObjCInterfaceDecl *ClassDecl = nullptr;
3193
3194 // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
3195 // long as one of the protocols implements the selector (if not, warn).
3196 // And as long as message is not deprecated/unavailable (warn if it is).
3197 if (const ObjCObjectPointerType *QIdTy
3198 = ReceiverType->getAsObjCQualifiedIdType()) {
3199 // Search protocols for instance methods.
3200 Method = LookupMethodInQualifiedType(Sel, OPT: QIdTy, Instance: true);
3201 if (!Method)
3202 Method = LookupMethodInQualifiedType(Sel, OPT: QIdTy, Instance: false);
3203 if (Method && SemaRef.DiagnoseUseOfDecl(D: Method, Locs: SelectorSlotLocs))
3204 return ExprError();
3205 } else if (const ObjCObjectPointerType *OCIType
3206 = ReceiverType->getAsObjCInterfacePointerType()) {
3207 // We allow sending a message to a pointer to an interface (an object).
3208 ClassDecl = OCIType->getInterfaceDecl();
3209
3210 // Try to complete the type. Under ARC, this is a hard error from which
3211 // we don't try to recover.
3212 // FIXME: In the non-ARC case, this will still be a hard error if the
3213 // definition is found in a module that's not visible.
3214 const ObjCInterfaceDecl *forwardClass = nullptr;
3215 if (SemaRef.RequireCompleteType(
3216 Loc, T: OCIType->getPointeeType(),
3217 DiagID: getLangOpts().ObjCAutoRefCount
3218 ? diag::err_arc_receiver_forward_instance
3219 : diag::warn_receiver_forward_instance,
3220 Args: RecRange)) {
3221 if (getLangOpts().ObjCAutoRefCount)
3222 return ExprError();
3223
3224 forwardClass = OCIType->getInterfaceDecl();
3225 Diag(Loc: Receiver ? Receiver->getBeginLoc() : SuperLoc,
3226 DiagID: diag::note_receiver_is_id);
3227 Method = nullptr;
3228 } else {
3229 Method = ClassDecl->lookupInstanceMethod(Sel);
3230 }
3231
3232 if (!Method)
3233 // Search protocol qualifiers.
3234 Method = LookupMethodInQualifiedType(Sel, OPT: OCIType, Instance: true);
3235
3236 if (!Method) {
3237 // If we have implementations in scope, check "private" methods.
3238 Method = ClassDecl->lookupPrivateMethod(Sel);
3239
3240 if (!Method && getLangOpts().ObjCAutoRefCount) {
3241 Diag(Loc: SelLoc, DiagID: diag::err_arc_may_not_respond)
3242 << OCIType->getPointeeType() << Sel << RecRange
3243 << SourceRange(SelectorLocs.front(), SelectorLocs.back());
3244 return ExprError();
3245 }
3246
3247 if (!Method && (!Receiver || !isSelfExpr(RExpr: Receiver))) {
3248 // If we still haven't found a method, look in the global pool. This
3249 // behavior isn't very desirable, however we need it for GCC
3250 // compatibility. FIXME: should we deviate??
3251 if (OCIType->qual_empty()) {
3252 SmallVector<ObjCMethodDecl*, 4> Methods;
3253 CollectMultipleMethodsInGlobalPool(Sel, Methods,
3254 InstanceFirst: true/*InstanceFirst*/,
3255 CheckTheOther: false/*CheckTheOther*/);
3256 if (!Methods.empty()) {
3257 // We choose the first method as the initial candidate, then try
3258 // to select a better one.
3259 Method = Methods[0];
3260
3261 if (ObjCMethodDecl *BestMethod = SemaRef.SelectBestMethod(
3262 Sel, Args: ArgsIn, IsInstance: Method->isInstanceMethod(), Methods))
3263 Method = BestMethod;
3264
3265 AreMultipleMethodsInGlobalPool(Sel, BestMethod: Method,
3266 R: SourceRange(LBracLoc, RBracLoc),
3267 receiverIdOrClass: true/*receiverIdOrClass*/,
3268 Methods);
3269 }
3270 if (Method && !forwardClass)
3271 Diag(Loc: SelLoc, DiagID: diag::warn_maynot_respond)
3272 << OCIType->getInterfaceDecl()->getIdentifier()
3273 << Sel << RecRange;
3274 }
3275 }
3276 }
3277 if (Method &&
3278 SemaRef.DiagnoseUseOfDecl(D: Method, Locs: SelectorSlotLocs, UnknownObjCClass: forwardClass))
3279 return ExprError();
3280 } else {
3281 // Reject other random receiver types (e.g. structs).
3282 Diag(Loc, DiagID: diag::err_bad_receiver_type) << ReceiverType << RecRange;
3283 return ExprError();
3284 }
3285 }
3286 }
3287
3288 FunctionScopeInfo *DIFunctionScopeInfo =
3289 (Method && Method->getMethodFamily() == OMF_init)
3290 ? SemaRef.getEnclosingFunction()
3291 : nullptr;
3292
3293 if (Method && Method->isDirectMethod()) {
3294 if (ReceiverType->isObjCIdType() && !isImplicit) {
3295 Diag(Loc: Receiver->getExprLoc(),
3296 DiagID: diag::err_messaging_unqualified_id_with_direct_method);
3297 Diag(Loc: Method->getLocation(), DiagID: diag::note_direct_method_declared_at)
3298 << Method->getDeclName();
3299 }
3300
3301 // Under ARC, self can't be assigned, and doing a direct call to `self`
3302 // when it's a Class is hence safe. For other cases, we can't trust `self`
3303 // is what we think it is, so we reject it.
3304 if (ReceiverType->isObjCClassType() && !isImplicit &&
3305 !(Receiver->isObjCSelfExpr() && getLangOpts().ObjCAutoRefCount)) {
3306 {
3307 auto Builder = Diag(Loc: Receiver->getExprLoc(),
3308 DiagID: diag::err_messaging_class_with_direct_method);
3309 if (Receiver->isObjCSelfExpr()) {
3310 Builder.AddFixItHint(Hint: FixItHint::CreateReplacement(
3311 RemoveRange: RecRange, Code: Method->getClassInterface()->getName()));
3312 }
3313 }
3314 Diag(Loc: Method->getLocation(), DiagID: diag::note_direct_method_declared_at)
3315 << Method->getDeclName();
3316 }
3317
3318 if (SuperLoc.isValid()) {
3319 {
3320 auto Builder =
3321 Diag(Loc: SuperLoc, DiagID: diag::err_messaging_super_with_direct_method);
3322 if (ReceiverType->isObjCClassType()) {
3323 Builder.AddFixItHint(Hint: FixItHint::CreateReplacement(
3324 RemoveRange: SuperLoc, Code: Method->getClassInterface()->getName()));
3325 } else {
3326 Builder.AddFixItHint(Hint: FixItHint::CreateReplacement(RemoveRange: SuperLoc, Code: "self"));
3327 }
3328 }
3329 Diag(Loc: Method->getLocation(), DiagID: diag::note_direct_method_declared_at)
3330 << Method->getDeclName();
3331 }
3332 } else if (ReceiverType->isObjCIdType() && !isImplicit) {
3333 Diag(Loc: Receiver->getExprLoc(), DiagID: diag::warn_messaging_unqualified_id);
3334 }
3335
3336 if (DIFunctionScopeInfo &&
3337 DIFunctionScopeInfo->ObjCIsDesignatedInit &&
3338 (SuperLoc.isValid() || isSelfExpr(RExpr: Receiver))) {
3339 bool isDesignatedInitChain = false;
3340 if (SuperLoc.isValid()) {
3341 if (const ObjCObjectPointerType *
3342 OCIType = ReceiverType->getAsObjCInterfacePointerType()) {
3343 if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {
3344 // Either we know this is a designated initializer or we
3345 // conservatively assume it because we don't know for sure.
3346 if (!ID->declaresOrInheritsDesignatedInitializers() ||
3347 ID->isDesignatedInitializer(Sel)) {
3348 isDesignatedInitChain = true;
3349 DIFunctionScopeInfo->ObjCWarnForNoDesignatedInitChain = false;
3350 }
3351 }
3352 }
3353 }
3354 if (!isDesignatedInitChain) {
3355 const ObjCMethodDecl *InitMethod = nullptr;
3356 auto *CurMD = SemaRef.getCurMethodDecl();
3357 assert(CurMD && "Current method declaration should not be null");
3358 bool isDesignated =
3359 CurMD->isDesignatedInitializerForTheInterface(InitMethod: &InitMethod);
3360 assert(isDesignated && InitMethod);
3361 (void)isDesignated;
3362 Diag(Loc: SelLoc, DiagID: SuperLoc.isValid() ?
3363 diag::warn_objc_designated_init_non_designated_init_call :
3364 diag::warn_objc_designated_init_non_super_designated_init_call);
3365 Diag(Loc: InitMethod->getLocation(),
3366 DiagID: diag::note_objc_designated_init_marked_here);
3367 }
3368 }
3369
3370 if (DIFunctionScopeInfo &&
3371 DIFunctionScopeInfo->ObjCIsSecondaryInit &&
3372 (SuperLoc.isValid() || isSelfExpr(RExpr: Receiver))) {
3373 if (SuperLoc.isValid()) {
3374 Diag(Loc: SelLoc, DiagID: diag::warn_objc_secondary_init_super_init_call);
3375 } else {
3376 DIFunctionScopeInfo->ObjCWarnForNoInitDelegation = false;
3377 }
3378 }
3379
3380 // Check the message arguments.
3381 unsigned NumArgs = ArgsIn.size();
3382 Expr **Args = ArgsIn.data();
3383 QualType ReturnType;
3384 ExprValueKind VK = VK_PRValue;
3385 bool ClassMessage = (ReceiverType->isObjCClassType() ||
3386 ReceiverType->isObjCQualifiedClassType());
3387 if (CheckMessageArgumentTypes(Receiver, ReceiverType,
3388 Args: MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
3389 Method, isClassMessage: ClassMessage, isSuperMessage: SuperLoc.isValid(),
3390 lbrac: LBracLoc, rbrac: RBracLoc, RecRange, ReturnType, VK))
3391 return ExprError();
3392
3393 if (Method && !Method->getReturnType()->isVoidType() &&
3394 SemaRef.RequireCompleteType(
3395 Loc: LBracLoc, T: Method->getReturnType(),
3396 DiagID: diag::err_illegal_message_expr_incomplete_type))
3397 return ExprError();
3398
3399 // In ARC, forbid the user from sending messages to
3400 // retain/release/autorelease/dealloc/retainCount explicitly.
3401 if (getLangOpts().ObjCAutoRefCount) {
3402 ObjCMethodFamily family =
3403 (Method ? Method->getMethodFamily() : Sel.getMethodFamily());
3404 switch (family) {
3405 case OMF_init:
3406 if (Method)
3407 checkInitMethod(method: Method, receiverTypeIfCall: ReceiverType);
3408 break;
3409
3410 case OMF_None:
3411 case OMF_alloc:
3412 case OMF_copy:
3413 case OMF_finalize:
3414 case OMF_mutableCopy:
3415 case OMF_new:
3416 case OMF_self:
3417 case OMF_initialize:
3418 break;
3419
3420 case OMF_dealloc:
3421 case OMF_retain:
3422 case OMF_release:
3423 case OMF_autorelease:
3424 case OMF_retainCount:
3425 Diag(Loc: SelLoc, DiagID: diag::err_arc_illegal_explicit_message)
3426 << Sel << RecRange;
3427 break;
3428
3429 case OMF_performSelector:
3430 if (Method && NumArgs >= 1) {
3431 if (const auto *SelExp =
3432 dyn_cast<ObjCSelectorExpr>(Val: Args[0]->IgnoreParens())) {
3433 Selector ArgSel = SelExp->getSelector();
3434 ObjCMethodDecl *SelMethod =
3435 LookupInstanceMethodInGlobalPool(Sel: ArgSel,
3436 R: SelExp->getSourceRange());
3437 if (!SelMethod)
3438 SelMethod =
3439 LookupFactoryMethodInGlobalPool(Sel: ArgSel,
3440 R: SelExp->getSourceRange());
3441 if (SelMethod) {
3442 ObjCMethodFamily SelFamily = SelMethod->getMethodFamily();
3443 switch (SelFamily) {
3444 case OMF_alloc:
3445 case OMF_copy:
3446 case OMF_mutableCopy:
3447 case OMF_new:
3448 case OMF_init:
3449 // Issue error, unless ns_returns_not_retained.
3450 if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
3451 // selector names a +1 method
3452 Diag(Loc: SelLoc,
3453 DiagID: diag::err_arc_perform_selector_retains);
3454 Diag(Loc: SelMethod->getLocation(), DiagID: diag::note_method_declared_at)
3455 << SelMethod->getDeclName();
3456 }
3457 break;
3458 default:
3459 // +0 call. OK. unless ns_returns_retained.
3460 if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) {
3461 // selector names a +1 method
3462 Diag(Loc: SelLoc,
3463 DiagID: diag::err_arc_perform_selector_retains);
3464 Diag(Loc: SelMethod->getLocation(), DiagID: diag::note_method_declared_at)
3465 << SelMethod->getDeclName();
3466 }
3467 break;
3468 }
3469 }
3470 } else {
3471 // error (may leak).
3472 Diag(Loc: SelLoc, DiagID: diag::warn_arc_perform_selector_leaks);
3473 Diag(Loc: Args[0]->getExprLoc(), DiagID: diag::note_used_here);
3474 }
3475 }
3476 break;
3477 }
3478 }
3479
3480 DiagnoseCStringFormatDirectiveInObjCAPI(S&: SemaRef, Method, Sel, Args, NumArgs);
3481
3482 // Construct the appropriate ObjCMessageExpr instance.
3483 ObjCMessageExpr *Result;
3484 if (SuperLoc.isValid())
3485 Result = ObjCMessageExpr::Create(
3486 Context, T: ReturnType, VK, LBracLoc, SuperLoc, /*IsInstanceSuper=*/true,
3487 SuperType: ReceiverType, Sel, SelLocs: SelectorLocs, Method, Args: ArrayRef(Args, NumArgs),
3488 RBracLoc, isImplicit);
3489 else {
3490 Result = ObjCMessageExpr::Create(
3491 Context, T: ReturnType, VK, LBracLoc, Receiver, Sel, SeLocs: SelectorLocs, Method,
3492 Args: ArrayRef(Args, NumArgs), RBracLoc, isImplicit);
3493 if (!isImplicit)
3494 checkCocoaAPI(S&: SemaRef, Msg: Result);
3495 }
3496 if (Method) {
3497 bool IsClassObjectCall = ClassMessage;
3498 // 'self' message receivers in class methods should be treated as message
3499 // sends to the class object in order for the semantic checks to be
3500 // performed correctly. Messages to 'super' already count as class messages,
3501 // so they don't need to be handled here.
3502 if (Receiver && isSelfExpr(RExpr: Receiver)) {
3503 if (const auto *OPT = ReceiverType->getAs<ObjCObjectPointerType>()) {
3504 if (OPT->getObjectType()->isObjCClass()) {
3505 if (const auto *CurMeth = SemaRef.getCurMethodDecl()) {
3506 IsClassObjectCall = true;
3507 ReceiverType =
3508 Context.getObjCInterfaceType(Decl: CurMeth->getClassInterface());
3509 }
3510 }
3511 }
3512 }
3513 checkFoundationAPI(S&: SemaRef, Loc: SelLoc, Method, Args: ArrayRef(Args, NumArgs),
3514 ReceiverType, IsClassObjectCall);
3515 }
3516
3517 if (getLangOpts().ObjCAutoRefCount) {
3518 // In ARC, annotate delegate init calls.
3519 if (Result->getMethodFamily() == OMF_init &&
3520 (SuperLoc.isValid() || isSelfExpr(RExpr: Receiver))) {
3521 // Only consider init calls *directly* in init implementations,
3522 // not within blocks.
3523 ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(Val: SemaRef.CurContext);
3524 if (method && method->getMethodFamily() == OMF_init) {
3525 // The implicit assignment to self means we also don't want to
3526 // consume the result.
3527 Result->setDelegateInitCall(true);
3528 return Result;
3529 }
3530 }
3531
3532 // In ARC, check for message sends which are likely to introduce
3533 // retain cycles.
3534 checkRetainCycles(msg: Result);
3535 }
3536
3537 if (getLangOpts().ObjCWeak) {
3538 if (!isImplicit && Method) {
3539 if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) {
3540 bool IsWeak =
3541 Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak;
3542 if (!IsWeak && Sel.isUnarySelector())
3543 IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
3544 if (IsWeak && !SemaRef.isUnevaluatedContext() &&
3545 !getDiagnostics().isIgnored(DiagID: diag::warn_arc_repeated_use_of_weak,
3546 Loc: LBracLoc))
3547 SemaRef.getCurFunction()->recordUseOfWeak(Msg: Result, Prop);
3548 }
3549 }
3550 }
3551
3552 CheckObjCCircularContainer(Message: Result);
3553
3554 return SemaRef.MaybeBindToTemporary(E: Result);
3555}
3556
3557static void RemoveSelectorFromWarningCache(SemaObjC &S, Expr *Arg) {
3558 if (ObjCSelectorExpr *OSE =
3559 dyn_cast<ObjCSelectorExpr>(Val: Arg->IgnoreParenCasts())) {
3560 Selector Sel = OSE->getSelector();
3561 SourceLocation Loc = OSE->getAtLoc();
3562 auto Pos = S.ReferencedSelectors.find(Key: Sel);
3563 if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)
3564 S.ReferencedSelectors.erase(Iterator: Pos);
3565 }
3566}
3567
3568// ActOnInstanceMessage - used for both unary and keyword messages.
3569// ArgExprs is optional - if it is present, the number of expressions
3570// is obtained from Sel.getNumArgs().
3571ExprResult SemaObjC::ActOnInstanceMessage(Scope *S, Expr *Receiver,
3572 Selector Sel, SourceLocation LBracLoc,
3573 ArrayRef<SourceLocation> SelectorLocs,
3574 SourceLocation RBracLoc,
3575 MultiExprArg Args) {
3576 ASTContext &Context = getASTContext();
3577 if (!Receiver)
3578 return ExprError();
3579
3580 // A ParenListExpr can show up while doing error recovery with invalid code.
3581 if (isa<ParenListExpr>(Val: Receiver)) {
3582 ExprResult Result =
3583 SemaRef.MaybeConvertParenListExprToParenExpr(S, ME: Receiver);
3584 if (Result.isInvalid()) return ExprError();
3585 Receiver = Result.get();
3586 }
3587
3588 if (RespondsToSelectorSel.isNull()) {
3589 IdentifierInfo *SelectorId = &Context.Idents.get(Name: "respondsToSelector");
3590 RespondsToSelectorSel = Context.Selectors.getUnarySelector(ID: SelectorId);
3591 }
3592 if (Sel == RespondsToSelectorSel)
3593 RemoveSelectorFromWarningCache(S&: *this, Arg: Args[0]);
3594
3595 return BuildInstanceMessage(Receiver, ReceiverType: Receiver->getType(),
3596 /*SuperLoc=*/SourceLocation(), Sel,
3597 /*Method=*/nullptr, LBracLoc, SelectorLocs,
3598 RBracLoc, ArgsIn: Args);
3599}
3600
3601enum ARCConversionTypeClass {
3602 /// int, void, struct A
3603 ACTC_none,
3604
3605 /// id, void (^)()
3606 ACTC_retainable,
3607
3608 /// id*, id***, void (^*)(),
3609 ACTC_indirectRetainable,
3610
3611 /// void* might be a normal C type, or it might a CF type.
3612 ACTC_voidPtr,
3613
3614 /// struct A*
3615 ACTC_coreFoundation
3616};
3617
3618static bool isAnyRetainable(ARCConversionTypeClass ACTC) {
3619 return (ACTC == ACTC_retainable ||
3620 ACTC == ACTC_coreFoundation ||
3621 ACTC == ACTC_voidPtr);
3622}
3623
3624static bool isAnyCLike(ARCConversionTypeClass ACTC) {
3625 return ACTC == ACTC_none ||
3626 ACTC == ACTC_voidPtr ||
3627 ACTC == ACTC_coreFoundation;
3628}
3629
3630static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {
3631 bool isIndirect = false;
3632
3633 // Ignore an outermost reference type.
3634 if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
3635 type = ref->getPointeeType();
3636 isIndirect = true;
3637 }
3638
3639 // Drill through pointers and arrays recursively.
3640 while (true) {
3641 if (const PointerType *ptr = type->getAs<PointerType>()) {
3642 type = ptr->getPointeeType();
3643
3644 // The first level of pointer may be the innermost pointer on a CF type.
3645 if (!isIndirect) {
3646 if (type->isVoidType()) return ACTC_voidPtr;
3647 if (type->isRecordType()) return ACTC_coreFoundation;
3648 }
3649 } else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) {
3650 type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0);
3651 } else {
3652 break;
3653 }
3654 isIndirect = true;
3655 }
3656
3657 if (isIndirect) {
3658 if (type->isObjCARCBridgableType())
3659 return ACTC_indirectRetainable;
3660 return ACTC_none;
3661 }
3662
3663 if (type->isObjCARCBridgableType())
3664 return ACTC_retainable;
3665
3666 return ACTC_none;
3667}
3668
3669namespace {
3670 /// A result from the cast checker.
3671 enum ACCResult {
3672 /// Cannot be casted.
3673 ACC_invalid,
3674
3675 /// Can be safely retained or not retained.
3676 ACC_bottom,
3677
3678 /// Can be casted at +0.
3679 ACC_plusZero,
3680
3681 /// Can be casted at +1.
3682 ACC_plusOne
3683 };
3684 ACCResult merge(ACCResult left, ACCResult right) {
3685 if (left == right) return left;
3686 if (left == ACC_bottom) return right;
3687 if (right == ACC_bottom) return left;
3688 return ACC_invalid;
3689 }
3690
3691 /// A checker which white-lists certain expressions whose conversion
3692 /// to or from retainable type would otherwise be forbidden in ARC.
3693 class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> {
3694 typedef StmtVisitor<ARCCastChecker, ACCResult> super;
3695
3696 ASTContext &Context;
3697 ARCConversionTypeClass SourceClass;
3698 ARCConversionTypeClass TargetClass;
3699 bool Diagnose;
3700
3701 static bool isCFType(QualType type) {
3702 // Someday this can use ns_bridged. For now, it has to do this.
3703 return type->isCARCBridgableType();
3704 }
3705
3706 public:
3707 ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source,
3708 ARCConversionTypeClass target, bool diagnose)
3709 : Context(Context), SourceClass(source), TargetClass(target),
3710 Diagnose(diagnose) {}
3711
3712 using super::Visit;
3713 ACCResult Visit(Expr *e) {
3714 return super::Visit(S: e->IgnoreParens());
3715 }
3716
3717 ACCResult VisitStmt(Stmt *s) {
3718 return ACC_invalid;
3719 }
3720
3721 /// Null pointer constants can be casted however you please.
3722 ACCResult VisitExpr(Expr *e) {
3723 if (e->isNullPointerConstant(Ctx&: Context, NPC: Expr::NPC_ValueDependentIsNotNull))
3724 return ACC_bottom;
3725 return ACC_invalid;
3726 }
3727
3728 /// Constant initializer Objective-C literals can be safely casted.
3729 ACCResult VisitObjCObjectLiteral(ObjCObjectLiteral *OL) {
3730 // If we're casting to any retainable type, go ahead. Global
3731 // strings and constant literals are immune to retains, so this is bottom.
3732 if (OL->isGlobalAllocation() || isAnyRetainable(ACTC: TargetClass))
3733 return ACC_bottom;
3734
3735 return ACC_invalid;
3736 }
3737
3738 ACCResult VisitObjCStringLiteral(ObjCStringLiteral *SL) {
3739 return VisitObjCObjectLiteral(OL: SL);
3740 }
3741
3742 ACCResult VisitObjCBoxedExpr(ObjCBoxedExpr *OBE) {
3743 return VisitObjCObjectLiteral(OL: OBE);
3744 }
3745
3746 ACCResult VisitObjCArrayLiteral(ObjCArrayLiteral *AL) {
3747 return VisitObjCObjectLiteral(OL: AL);
3748 }
3749
3750 ACCResult VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *DL) {
3751 return VisitObjCObjectLiteral(OL: DL);
3752 }
3753
3754 /// Look through certain implicit and explicit casts.
3755 ACCResult VisitCastExpr(CastExpr *e) {
3756 switch (e->getCastKind()) {
3757 case CK_NullToPointer:
3758 return ACC_bottom;
3759
3760 case CK_NoOp:
3761 case CK_LValueToRValue:
3762 case CK_BitCast:
3763 case CK_CPointerToObjCPointerCast:
3764 case CK_BlockPointerToObjCPointerCast:
3765 case CK_AnyPointerToBlockPointerCast:
3766 return Visit(e: e->getSubExpr());
3767
3768 default:
3769 return ACC_invalid;
3770 }
3771 }
3772
3773 /// Look through unary extension.
3774 ACCResult VisitUnaryExtension(UnaryOperator *e) {
3775 return Visit(e: e->getSubExpr());
3776 }
3777
3778 /// Ignore the LHS of a comma operator.
3779 ACCResult VisitBinComma(BinaryOperator *e) {
3780 return Visit(e: e->getRHS());
3781 }
3782
3783 /// Conditional operators are okay if both sides are okay.
3784 ACCResult VisitConditionalOperator(ConditionalOperator *e) {
3785 ACCResult left = Visit(e: e->getTrueExpr());
3786 if (left == ACC_invalid) return ACC_invalid;
3787 return merge(left, right: Visit(e: e->getFalseExpr()));
3788 }
3789
3790 /// Look through pseudo-objects.
3791 ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {
3792 // If we're getting here, we should always have a result.
3793 return Visit(e: e->getResultExpr());
3794 }
3795
3796 /// Statement expressions are okay if their result expression is okay.
3797 ACCResult VisitStmtExpr(StmtExpr *e) {
3798 return Visit(S: e->getSubStmt()->body_back());
3799 }
3800
3801 /// Some declaration references are okay.
3802 ACCResult VisitDeclRefExpr(DeclRefExpr *e) {
3803 VarDecl *var = dyn_cast<VarDecl>(Val: e->getDecl());
3804 // References to global constants are okay.
3805 if (isAnyRetainable(ACTC: TargetClass) &&
3806 isAnyRetainable(ACTC: SourceClass) &&
3807 var &&
3808 !var->hasDefinition(Context) &&
3809 var->getType().isConstQualified()) {
3810
3811 // In system headers, they can also be assumed to be immune to retains.
3812 // These are things like 'kCFStringTransformToLatin'.
3813 if (Context.getSourceManager().isInSystemHeader(Loc: var->getLocation()))
3814 return ACC_bottom;
3815
3816 return ACC_plusZero;
3817 }
3818
3819 // Nothing else.
3820 return ACC_invalid;
3821 }
3822
3823 /// Some calls are okay.
3824 ACCResult VisitCallExpr(CallExpr *e) {
3825 if (FunctionDecl *fn = e->getDirectCallee())
3826 if (ACCResult result = checkCallToFunction(fn))
3827 return result;
3828
3829 return super::VisitCallExpr(S: e);
3830 }
3831
3832 ACCResult checkCallToFunction(FunctionDecl *fn) {
3833 // Require a CF*Ref return type.
3834 if (!isCFType(type: fn->getReturnType()))
3835 return ACC_invalid;
3836
3837 if (!isAnyRetainable(ACTC: TargetClass))
3838 return ACC_invalid;
3839
3840 // Honor an explicit 'not retained' attribute.
3841 if (fn->hasAttr<CFReturnsNotRetainedAttr>())
3842 return ACC_plusZero;
3843
3844 // Honor an explicit 'retained' attribute, except that for
3845 // now we're not going to permit implicit handling of +1 results,
3846 // because it's a bit frightening.
3847 if (fn->hasAttr<CFReturnsRetainedAttr>())
3848 return Diagnose ? ACC_plusOne
3849 : ACC_invalid; // ACC_plusOne if we start accepting this
3850
3851 // Recognize this specific builtin function, which is used by CFSTR.
3852 unsigned builtinID = fn->getBuiltinID();
3853 if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString)
3854 return ACC_bottom;
3855
3856 // Otherwise, don't do anything implicit with an unaudited function.
3857 if (!fn->hasAttr<CFAuditedTransferAttr>())
3858 return ACC_invalid;
3859
3860 // Otherwise, it's +0 unless it follows the create convention.
3861 if (ento::coreFoundation::followsCreateRule(FD: fn))
3862 return Diagnose ? ACC_plusOne
3863 : ACC_invalid; // ACC_plusOne if we start accepting this
3864
3865 return ACC_plusZero;
3866 }
3867
3868 ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) {
3869 return checkCallToMethod(method: e->getMethodDecl());
3870 }
3871
3872 ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) {
3873 ObjCMethodDecl *method;
3874 if (e->isExplicitProperty())
3875 method = e->getExplicitProperty()->getGetterMethodDecl();
3876 else
3877 method = e->getImplicitPropertyGetter();
3878 return checkCallToMethod(method);
3879 }
3880
3881 ACCResult checkCallToMethod(ObjCMethodDecl *method) {
3882 if (!method) return ACC_invalid;
3883
3884 // Check for message sends to functions returning CF types. We
3885 // just obey the Cocoa conventions with these, even though the
3886 // return type is CF.
3887 if (!isAnyRetainable(ACTC: TargetClass) || !isCFType(type: method->getReturnType()))
3888 return ACC_invalid;
3889
3890 // If the method is explicitly marked not-retained, it's +0.
3891 if (method->hasAttr<CFReturnsNotRetainedAttr>())
3892 return ACC_plusZero;
3893
3894 // If the method is explicitly marked as returning retained, or its
3895 // selector follows a +1 Cocoa convention, treat it as +1.
3896 if (method->hasAttr<CFReturnsRetainedAttr>())
3897 return ACC_plusOne;
3898
3899 switch (method->getSelector().getMethodFamily()) {
3900 case OMF_alloc:
3901 case OMF_copy:
3902 case OMF_mutableCopy:
3903 case OMF_new:
3904 return ACC_plusOne;
3905
3906 default:
3907 // Otherwise, treat it as +0.
3908 return ACC_plusZero;
3909 }
3910 }
3911 };
3912} // end anonymous namespace
3913
3914bool SemaObjC::isKnownName(StringRef name) {
3915 ASTContext &Context = getASTContext();
3916 if (name.empty())
3917 return false;
3918 LookupResult R(SemaRef, &Context.Idents.get(Name: name), SourceLocation(),
3919 Sema::LookupOrdinaryName);
3920 return SemaRef.LookupName(R, S: SemaRef.TUScope, AllowBuiltinCreation: false);
3921}
3922
3923template <typename DiagBuilderT>
3924static void addFixitForObjCARCConversion(
3925 Sema &S, DiagBuilderT &DiagB, CheckedConversionKind CCK,
3926 SourceLocation afterLParen, QualType castType, Expr *castExpr,
3927 Expr *realCast, const char *bridgeKeyword, const char *CFBridgeName) {
3928 // We handle C-style and implicit casts here.
3929 switch (CCK) {
3930 case CheckedConversionKind::Implicit:
3931 case CheckedConversionKind::ForBuiltinOverloadedOp:
3932 case CheckedConversionKind::CStyleCast:
3933 case CheckedConversionKind::OtherCast:
3934 break;
3935 case CheckedConversionKind::FunctionalCast:
3936 return;
3937 }
3938
3939 if (CFBridgeName) {
3940 if (CCK == CheckedConversionKind::OtherCast) {
3941 if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(Val: realCast)) {
3942 SourceRange range(NCE->getOperatorLoc(),
3943 NCE->getAngleBrackets().getEnd());
3944 SmallString<32> BridgeCall;
3945
3946 SourceManager &SM = S.getSourceManager();
3947 char PrevChar = *SM.getCharacterData(SL: range.getBegin().getLocWithOffset(Offset: -1));
3948 if (Lexer::isAsciiIdentifierContinueChar(c: PrevChar, LangOpts: S.getLangOpts()))
3949 BridgeCall += ' ';
3950
3951 BridgeCall += CFBridgeName;
3952 DiagB.AddFixItHint(FixItHint::CreateReplacement(RemoveRange: range, Code: BridgeCall));
3953 }
3954 return;
3955 }
3956 Expr *castedE = castExpr;
3957 if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(Val: castedE))
3958 castedE = CCE->getSubExpr();
3959 castedE = castedE->IgnoreImpCasts();
3960 SourceRange range = castedE->getSourceRange();
3961
3962 SmallString<32> BridgeCall;
3963
3964 SourceManager &SM = S.getSourceManager();
3965 char PrevChar = *SM.getCharacterData(SL: range.getBegin().getLocWithOffset(Offset: -1));
3966 if (Lexer::isAsciiIdentifierContinueChar(c: PrevChar, LangOpts: S.getLangOpts()))
3967 BridgeCall += ' ';
3968
3969 BridgeCall += CFBridgeName;
3970
3971 if (isa<ParenExpr>(Val: castedE)) {
3972 DiagB.AddFixItHint(FixItHint::CreateInsertion(InsertionLoc: range.getBegin(),
3973 Code: BridgeCall));
3974 } else {
3975 BridgeCall += '(';
3976 DiagB.AddFixItHint(FixItHint::CreateInsertion(InsertionLoc: range.getBegin(),
3977 Code: BridgeCall));
3978 DiagB.AddFixItHint(FixItHint::CreateInsertion(
3979 InsertionLoc: S.getLocForEndOfToken(Loc: range.getEnd()),
3980 Code: ")"));
3981 }
3982 return;
3983 }
3984
3985 if (CCK == CheckedConversionKind::CStyleCast) {
3986 DiagB.AddFixItHint(FixItHint::CreateInsertion(InsertionLoc: afterLParen, Code: bridgeKeyword));
3987 } else if (CCK == CheckedConversionKind::OtherCast) {
3988 if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(Val: realCast)) {
3989 std::string castCode = "(";
3990 castCode += bridgeKeyword;
3991 castCode += castType.getAsString();
3992 castCode += ")";
3993 SourceRange Range(NCE->getOperatorLoc(),
3994 NCE->getAngleBrackets().getEnd());
3995 DiagB.AddFixItHint(FixItHint::CreateReplacement(RemoveRange: Range, Code: castCode));
3996 }
3997 } else {
3998 std::string castCode = "(";
3999 castCode += bridgeKeyword;
4000 castCode += castType.getAsString();
4001 castCode += ")";
4002 Expr *castedE = castExpr->IgnoreImpCasts();
4003 SourceRange range = castedE->getSourceRange();
4004 if (isa<ParenExpr>(Val: castedE)) {
4005 DiagB.AddFixItHint(FixItHint::CreateInsertion(InsertionLoc: range.getBegin(),
4006 Code: castCode));
4007 } else {
4008 castCode += "(";
4009 DiagB.AddFixItHint(FixItHint::CreateInsertion(InsertionLoc: range.getBegin(),
4010 Code: castCode));
4011 DiagB.AddFixItHint(FixItHint::CreateInsertion(
4012 InsertionLoc: S.getLocForEndOfToken(Loc: range.getEnd()),
4013 Code: ")"));
4014 }
4015 }
4016}
4017
4018template <typename T>
4019static inline T *getObjCBridgeAttr(const TypedefType *TD) {
4020 TypedefNameDecl *TDNDecl = TD->getDecl();
4021 QualType QT = TDNDecl->getUnderlyingType();
4022 if (QT->isPointerType()) {
4023 QT = QT->getPointeeType();
4024 if (const RecordType *RT = QT->getAsCanonical<RecordType>()) {
4025 for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {
4026 if (auto *attr = Redecl->getAttr<T>())
4027 return attr;
4028 }
4029 }
4030 }
4031 return nullptr;
4032}
4033
4034static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,
4035 TypedefNameDecl *&TDNDecl) {
4036 while (const auto *TD = T->getAs<TypedefType>()) {
4037 TDNDecl = TD->getDecl();
4038 if (ObjCBridgeRelatedAttr *ObjCBAttr =
4039 getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD))
4040 return ObjCBAttr;
4041 T = TDNDecl->getUnderlyingType();
4042 }
4043 return nullptr;
4044}
4045
4046static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
4047 QualType castType,
4048 ARCConversionTypeClass castACTC,
4049 Expr *castExpr, Expr *realCast,
4050 ARCConversionTypeClass exprACTC,
4051 CheckedConversionKind CCK) {
4052 SourceLocation loc =
4053 (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
4054
4055 if (S.makeUnavailableInSystemHeader(loc,
4056 reason: UnavailableAttr::IR_ARCForbiddenConversion))
4057 return;
4058
4059 QualType castExprType = castExpr->getType();
4060 // Defer emitting a diagnostic for bridge-related casts; that will be
4061 // handled by CheckObjCBridgeRelatedConversions.
4062 TypedefNameDecl *TDNDecl = nullptr;
4063 if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
4064 ObjCBridgeRelatedAttrFromType(T: castType, TDNDecl)) ||
4065 (exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&
4066 ObjCBridgeRelatedAttrFromType(T: castExprType, TDNDecl)))
4067 return;
4068
4069 unsigned srcKind = 0;
4070 switch (exprACTC) {
4071 case ACTC_none:
4072 case ACTC_coreFoundation:
4073 case ACTC_voidPtr:
4074 srcKind = (castExprType->isPointerType() ? 1 : 0);
4075 break;
4076 case ACTC_retainable:
4077 srcKind = (castExprType->isBlockPointerType() ? 2 : 3);
4078 break;
4079 case ACTC_indirectRetainable:
4080 srcKind = 4;
4081 break;
4082 }
4083
4084 // Check whether this could be fixed with a bridge cast.
4085 SourceLocation afterLParen = S.getLocForEndOfToken(Loc: castRange.getBegin());
4086 SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
4087
4088 unsigned convKindForDiag = Sema::isCast(CCK) ? 0 : 1;
4089
4090 // Bridge from an ARC type to a CF type.
4091 if (castACTC == ACTC_retainable && isAnyRetainable(ACTC: exprACTC)) {
4092
4093 S.Diag(Loc: loc, DiagID: diag::err_arc_cast_requires_bridge)
4094 << convKindForDiag
4095 << 2 // of C pointer type
4096 << castExprType
4097 << unsigned(castType->isBlockPointerType()) // to ObjC|block type
4098 << castType
4099 << castRange
4100 << castExpr->getSourceRange();
4101 bool br = S.ObjC().isKnownName(name: "CFBridgingRelease");
4102 ACCResult CreateRule =
4103 ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(e: castExpr);
4104 assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
4105 if (CreateRule != ACC_plusOne)
4106 {
4107 auto DiagB = (CCK != CheckedConversionKind::OtherCast)
4108 ? S.Diag(Loc: noteLoc, DiagID: diag::note_arc_bridge)
4109 : S.Diag(Loc: noteLoc, DiagID: diag::note_arc_cstyle_bridge);
4110
4111 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
4112 castType, castExpr, realCast, bridgeKeyword: "__bridge ",
4113 CFBridgeName: nullptr);
4114 }
4115 if (CreateRule != ACC_plusZero)
4116 {
4117 auto DiagB = (CCK == CheckedConversionKind::OtherCast && !br)
4118 ? S.Diag(Loc: noteLoc, DiagID: diag::note_arc_cstyle_bridge_transfer)
4119 << castExprType
4120 : S.Diag(Loc: br ? castExpr->getExprLoc() : noteLoc,
4121 DiagID: diag::note_arc_bridge_transfer)
4122 << castExprType << br;
4123
4124 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
4125 castType, castExpr, realCast, bridgeKeyword: "__bridge_transfer ",
4126 CFBridgeName: br ? "CFBridgingRelease" : nullptr);
4127 }
4128
4129 return;
4130 }
4131
4132 // Bridge from a CF type to an ARC type.
4133 if (exprACTC == ACTC_retainable && isAnyRetainable(ACTC: castACTC)) {
4134 bool br = S.ObjC().isKnownName(name: "CFBridgingRetain");
4135 S.Diag(Loc: loc, DiagID: diag::err_arc_cast_requires_bridge)
4136 << convKindForDiag
4137 << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type
4138 << castExprType
4139 << 2 // to C pointer type
4140 << castType
4141 << castRange
4142 << castExpr->getSourceRange();
4143 ACCResult CreateRule =
4144 ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(e: castExpr);
4145 assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
4146 if (CreateRule != ACC_plusOne)
4147 {
4148 auto DiagB = (CCK != CheckedConversionKind::OtherCast)
4149 ? S.Diag(Loc: noteLoc, DiagID: diag::note_arc_bridge)
4150 : S.Diag(Loc: noteLoc, DiagID: diag::note_arc_cstyle_bridge);
4151 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
4152 castType, castExpr, realCast, bridgeKeyword: "__bridge ",
4153 CFBridgeName: nullptr);
4154 }
4155 if (CreateRule != ACC_plusZero)
4156 {
4157 auto DiagB = (CCK == CheckedConversionKind::OtherCast && !br)
4158 ? S.Diag(Loc: noteLoc, DiagID: diag::note_arc_cstyle_bridge_retained)
4159 << castType
4160 : S.Diag(Loc: br ? castExpr->getExprLoc() : noteLoc,
4161 DiagID: diag::note_arc_bridge_retained)
4162 << castType << br;
4163
4164 addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
4165 castType, castExpr, realCast, bridgeKeyword: "__bridge_retained ",
4166 CFBridgeName: br ? "CFBridgingRetain" : nullptr);
4167 }
4168
4169 return;
4170 }
4171
4172 S.Diag(Loc: loc, DiagID: diag::err_arc_mismatched_cast)
4173 << !convKindForDiag
4174 << srcKind << castExprType << castType
4175 << castRange << castExpr->getSourceRange();
4176}
4177
4178template <typename TB>
4179static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr,
4180 bool &HadTheAttribute, bool warn) {
4181 QualType T = castExpr->getType();
4182 HadTheAttribute = false;
4183 while (const auto *TD = T->getAs<TypedefType>()) {
4184 TypedefNameDecl *TDNDecl = TD->getDecl();
4185 if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
4186 if (const IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
4187 HadTheAttribute = true;
4188 if (Parm->isStr(Str: "id"))
4189 return true;
4190
4191 // Check for an existing type with this name.
4192 LookupResult R(S, DeclarationName(Parm), SourceLocation(),
4193 Sema::LookupOrdinaryName);
4194 if (S.LookupName(R, S: S.TUScope)) {
4195 NamedDecl *Target = R.getFoundDecl();
4196 if (Target && isa<ObjCInterfaceDecl>(Val: Target)) {
4197 ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Val: Target);
4198 if (const ObjCObjectPointerType *InterfacePointerType =
4199 castType->getAsObjCInterfacePointerType()) {
4200 ObjCInterfaceDecl *CastClass
4201 = InterfacePointerType->getObjectType()->getInterface();
4202 if ((CastClass == ExprClass) ||
4203 (CastClass && CastClass->isSuperClassOf(I: ExprClass)))
4204 return true;
4205 if (warn)
4206 S.Diag(Loc: castExpr->getBeginLoc(), DiagID: diag::warn_objc_invalid_bridge)
4207 << T << Target->getName() << castType->getPointeeType();
4208 return false;
4209 } else if (castType->isObjCIdType() ||
4210 (S.Context.ObjCObjectAdoptsQTypeProtocols(
4211 QT: castType, Decl: ExprClass)))
4212 // ok to cast to 'id'.
4213 // casting to id<p-list> is ok if bridge type adopts all of
4214 // p-list protocols.
4215 return true;
4216 else {
4217 if (warn) {
4218 S.Diag(Loc: castExpr->getBeginLoc(), DiagID: diag::warn_objc_invalid_bridge)
4219 << T << Target->getName() << castType;
4220 S.Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4221 S.Diag(Loc: Target->getBeginLoc(), DiagID: diag::note_declared_at);
4222 }
4223 return false;
4224 }
4225 }
4226 } else if (!castType->isObjCIdType()) {
4227 S.Diag(Loc: castExpr->getBeginLoc(),
4228 DiagID: diag::err_objc_cf_bridged_not_interface)
4229 << castExpr->getType() << Parm;
4230 S.Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4231 }
4232 return true;
4233 }
4234 return false;
4235 }
4236 T = TDNDecl->getUnderlyingType();
4237 }
4238 return true;
4239}
4240
4241template <typename TB>
4242static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr,
4243 bool &HadTheAttribute, bool warn) {
4244 QualType T = castType;
4245 HadTheAttribute = false;
4246 while (const auto *TD = T->getAs<TypedefType>()) {
4247 TypedefNameDecl *TDNDecl = TD->getDecl();
4248 if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
4249 if (const IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
4250 HadTheAttribute = true;
4251 if (Parm->isStr(Str: "id"))
4252 return true;
4253
4254 NamedDecl *Target = nullptr;
4255 // Check for an existing type with this name.
4256 LookupResult R(S, DeclarationName(Parm), SourceLocation(),
4257 Sema::LookupOrdinaryName);
4258 if (S.LookupName(R, S: S.TUScope)) {
4259 Target = R.getFoundDecl();
4260 if (Target && isa<ObjCInterfaceDecl>(Val: Target)) {
4261 ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Val: Target);
4262 if (const ObjCObjectPointerType *InterfacePointerType =
4263 castExpr->getType()->getAsObjCInterfacePointerType()) {
4264 ObjCInterfaceDecl *ExprClass
4265 = InterfacePointerType->getObjectType()->getInterface();
4266 if ((CastClass == ExprClass) ||
4267 (ExprClass && CastClass->isSuperClassOf(I: ExprClass)))
4268 return true;
4269 if (warn) {
4270 S.Diag(Loc: castExpr->getBeginLoc(),
4271 DiagID: diag::warn_objc_invalid_bridge_to_cf)
4272 << castExpr->getType()->getPointeeType() << T;
4273 S.Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4274 }
4275 return false;
4276 } else if (castExpr->getType()->isObjCIdType() ||
4277 (S.Context.QIdProtocolsAdoptObjCObjectProtocols(
4278 QT: castExpr->getType(), IDecl: CastClass)))
4279 // ok to cast an 'id' expression to a CFtype.
4280 // ok to cast an 'id<plist>' expression to CFtype provided plist
4281 // adopts all of CFtype's ObjetiveC's class plist.
4282 return true;
4283 else {
4284 if (warn) {
4285 S.Diag(Loc: castExpr->getBeginLoc(),
4286 DiagID: diag::warn_objc_invalid_bridge_to_cf)
4287 << castExpr->getType() << castType;
4288 S.Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4289 S.Diag(Loc: Target->getBeginLoc(), DiagID: diag::note_declared_at);
4290 }
4291 return false;
4292 }
4293 }
4294 }
4295 S.Diag(Loc: castExpr->getBeginLoc(),
4296 DiagID: diag::err_objc_ns_bridged_invalid_cfobject)
4297 << castExpr->getType() << castType;
4298 S.Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4299 if (Target)
4300 S.Diag(Loc: Target->getBeginLoc(), DiagID: diag::note_declared_at);
4301 return true;
4302 }
4303 return false;
4304 }
4305 T = TDNDecl->getUnderlyingType();
4306 }
4307 return true;
4308}
4309
4310void SemaObjC::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
4311 if (!getLangOpts().ObjC)
4312 return;
4313 // warn in presence of __bridge casting to or from a toll free bridge cast.
4314 ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(type: castExpr->getType());
4315 ARCConversionTypeClass castACTC = classifyTypeForARCConversion(type: castType);
4316 if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {
4317 bool HasObjCBridgeAttr;
4318 bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeNSCast<ObjCBridgeAttr>(
4319 S&: SemaRef, castType, castExpr, HadTheAttribute&: HasObjCBridgeAttr, warn: false);
4320 if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)
4321 return;
4322 bool HasObjCBridgeMutableAttr;
4323 bool ObjCBridgeMutableAttrWillNotWarn =
4324 CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(
4325 S&: SemaRef, castType, castExpr, HadTheAttribute&: HasObjCBridgeMutableAttr, warn: false);
4326 if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
4327 return;
4328
4329 if (HasObjCBridgeAttr)
4330 CheckObjCBridgeNSCast<ObjCBridgeAttr>(S&: SemaRef, castType, castExpr,
4331 HadTheAttribute&: HasObjCBridgeAttr, warn: true);
4332 else if (HasObjCBridgeMutableAttr)
4333 CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(
4334 S&: SemaRef, castType, castExpr, HadTheAttribute&: HasObjCBridgeMutableAttr, warn: true);
4335 }
4336 else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {
4337 bool HasObjCBridgeAttr;
4338 bool ObjCBridgeAttrWillNotWarn = CheckObjCBridgeCFCast<ObjCBridgeAttr>(
4339 S&: SemaRef, castType, castExpr, HadTheAttribute&: HasObjCBridgeAttr, warn: false);
4340 if (ObjCBridgeAttrWillNotWarn && HasObjCBridgeAttr)
4341 return;
4342 bool HasObjCBridgeMutableAttr;
4343 bool ObjCBridgeMutableAttrWillNotWarn =
4344 CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(
4345 S&: SemaRef, castType, castExpr, HadTheAttribute&: HasObjCBridgeMutableAttr, warn: false);
4346 if (ObjCBridgeMutableAttrWillNotWarn && HasObjCBridgeMutableAttr)
4347 return;
4348
4349 if (HasObjCBridgeAttr)
4350 CheckObjCBridgeCFCast<ObjCBridgeAttr>(S&: SemaRef, castType, castExpr,
4351 HadTheAttribute&: HasObjCBridgeAttr, warn: true);
4352 else if (HasObjCBridgeMutableAttr)
4353 CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(
4354 S&: SemaRef, castType, castExpr, HadTheAttribute&: HasObjCBridgeMutableAttr, warn: true);
4355 }
4356}
4357
4358void SemaObjC::CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr) {
4359 QualType SrcType = castExpr->getType();
4360 if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Val: castExpr)) {
4361 if (PRE->isExplicitProperty()) {
4362 if (ObjCPropertyDecl *PDecl = PRE->getExplicitProperty())
4363 SrcType = PDecl->getType();
4364 }
4365 else if (PRE->isImplicitProperty()) {
4366 if (ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter())
4367 SrcType = Getter->getReturnType();
4368 }
4369 }
4370
4371 ARCConversionTypeClass srcExprACTC = classifyTypeForARCConversion(type: SrcType);
4372 ARCConversionTypeClass castExprACTC = classifyTypeForARCConversion(type: castType);
4373 if (srcExprACTC != ACTC_retainable || castExprACTC != ACTC_coreFoundation)
4374 return;
4375 CheckObjCBridgeRelatedConversions(Loc: castExpr->getBeginLoc(), DestType: castType, SrcType,
4376 SrcExpr&: castExpr);
4377}
4378
4379bool SemaObjC::CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
4380 CastKind &Kind) {
4381 if (!getLangOpts().ObjC)
4382 return false;
4383 ARCConversionTypeClass exprACTC =
4384 classifyTypeForARCConversion(type: castExpr->getType());
4385 ARCConversionTypeClass castACTC = classifyTypeForARCConversion(type: castType);
4386 if ((castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) ||
4387 (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable)) {
4388 CheckTollFreeBridgeCast(castType, castExpr);
4389 Kind = (castACTC == ACTC_coreFoundation) ? CK_BitCast
4390 : CK_CPointerToObjCPointerCast;
4391 return true;
4392 }
4393 return false;
4394}
4395
4396bool SemaObjC::checkObjCBridgeRelatedComponents(
4397 SourceLocation Loc, QualType DestType, QualType SrcType,
4398 ObjCInterfaceDecl *&RelatedClass, ObjCMethodDecl *&ClassMethod,
4399 ObjCMethodDecl *&InstanceMethod, TypedefNameDecl *&TDNDecl, bool CfToNs,
4400 bool Diagnose) {
4401 ASTContext &Context = getASTContext();
4402 QualType T = CfToNs ? SrcType : DestType;
4403 ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);
4404 if (!ObjCBAttr)
4405 return false;
4406
4407 const IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
4408 const IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
4409 const IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
4410 if (!RCId)
4411 return false;
4412 NamedDecl *Target = nullptr;
4413 // Check for an existing type with this name.
4414 LookupResult R(SemaRef, DeclarationName(RCId), SourceLocation(),
4415 Sema::LookupOrdinaryName);
4416 if (!SemaRef.LookupName(R, S: SemaRef.TUScope)) {
4417 if (Diagnose) {
4418 Diag(Loc, DiagID: diag::err_objc_bridged_related_invalid_class) << RCId
4419 << SrcType << DestType;
4420 Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4421 }
4422 return false;
4423 }
4424 Target = R.getFoundDecl();
4425 if (Target && isa<ObjCInterfaceDecl>(Val: Target))
4426 RelatedClass = cast<ObjCInterfaceDecl>(Val: Target);
4427 else {
4428 if (Diagnose) {
4429 Diag(Loc, DiagID: diag::err_objc_bridged_related_invalid_class_name) << RCId
4430 << SrcType << DestType;
4431 Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4432 if (Target)
4433 Diag(Loc: Target->getBeginLoc(), DiagID: diag::note_declared_at);
4434 }
4435 return false;
4436 }
4437
4438 // Check for an existing class method with the given selector name.
4439 if (CfToNs && CMId) {
4440 Selector Sel = Context.Selectors.getUnarySelector(ID: CMId);
4441 ClassMethod = RelatedClass->lookupMethod(Sel, isInstance: false);
4442 if (!ClassMethod) {
4443 if (Diagnose) {
4444 Diag(Loc, DiagID: diag::err_objc_bridged_related_known_method)
4445 << SrcType << DestType << Sel << false;
4446 Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4447 }
4448 return false;
4449 }
4450 }
4451
4452 // Check for an existing instance method with the given selector name.
4453 if (!CfToNs && IMId) {
4454 Selector Sel = Context.Selectors.getNullarySelector(ID: IMId);
4455 InstanceMethod = RelatedClass->lookupMethod(Sel, isInstance: true);
4456 if (!InstanceMethod) {
4457 if (Diagnose) {
4458 Diag(Loc, DiagID: diag::err_objc_bridged_related_known_method)
4459 << SrcType << DestType << Sel << true;
4460 Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4461 }
4462 return false;
4463 }
4464 }
4465 return true;
4466}
4467
4468bool SemaObjC::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
4469 QualType DestType,
4470 QualType SrcType,
4471 Expr *&SrcExpr,
4472 bool Diagnose) {
4473 ASTContext &Context = getASTContext();
4474 ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(type: SrcType);
4475 ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(type: DestType);
4476 bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);
4477 bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
4478 if (!CfToNs && !NsToCf)
4479 return false;
4480
4481 ObjCInterfaceDecl *RelatedClass;
4482 ObjCMethodDecl *ClassMethod = nullptr;
4483 ObjCMethodDecl *InstanceMethod = nullptr;
4484 TypedefNameDecl *TDNDecl = nullptr;
4485 if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
4486 ClassMethod, InstanceMethod, TDNDecl,
4487 CfToNs, Diagnose))
4488 return false;
4489
4490 if (CfToNs) {
4491 // Implicit conversion from CF to ObjC object is needed.
4492 if (ClassMethod) {
4493 if (Diagnose) {
4494 std::string ExpressionString = "[";
4495 ExpressionString += RelatedClass->getNameAsString();
4496 ExpressionString += " ";
4497 ExpressionString += ClassMethod->getSelector().getAsString();
4498 SourceLocation SrcExprEndLoc =
4499 SemaRef.getLocForEndOfToken(Loc: SrcExpr->getEndLoc());
4500 // Provide a fixit: [RelatedClass ClassMethod SrcExpr]
4501 Diag(Loc, DiagID: diag::err_objc_bridged_related_known_method)
4502 << SrcType << DestType << ClassMethod->getSelector() << false
4503 << FixItHint::CreateInsertion(InsertionLoc: SrcExpr->getBeginLoc(),
4504 Code: ExpressionString)
4505 << FixItHint::CreateInsertion(InsertionLoc: SrcExprEndLoc, Code: "]");
4506 Diag(Loc: RelatedClass->getBeginLoc(), DiagID: diag::note_declared_at);
4507 Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4508
4509 QualType receiverType = Context.getObjCInterfaceType(Decl: RelatedClass);
4510 // Argument.
4511 Expr *args[] = { SrcExpr };
4512 ExprResult msg = BuildClassMessageImplicit(ReceiverType: receiverType, isSuperReceiver: false,
4513 Loc: ClassMethod->getLocation(),
4514 Sel: ClassMethod->getSelector(), Method: ClassMethod,
4515 Args: MultiExprArg(args, 1));
4516 SrcExpr = msg.get();
4517 }
4518 return true;
4519 }
4520 }
4521 else {
4522 // Implicit conversion from ObjC type to CF object is needed.
4523 if (InstanceMethod) {
4524 if (Diagnose) {
4525 std::string ExpressionString;
4526 SourceLocation SrcExprEndLoc =
4527 SemaRef.getLocForEndOfToken(Loc: SrcExpr->getEndLoc());
4528 if (InstanceMethod->isPropertyAccessor())
4529 if (const ObjCPropertyDecl *PDecl =
4530 InstanceMethod->findPropertyDecl()) {
4531 // fixit: ObjectExpr.propertyname when it is aproperty accessor.
4532 ExpressionString = ".";
4533 ExpressionString += PDecl->getNameAsString();
4534 Diag(Loc, DiagID: diag::err_objc_bridged_related_known_method)
4535 << SrcType << DestType << InstanceMethod->getSelector() << true
4536 << FixItHint::CreateInsertion(InsertionLoc: SrcExprEndLoc, Code: ExpressionString);
4537 }
4538 if (ExpressionString.empty()) {
4539 // Provide a fixit: [ObjectExpr InstanceMethod]
4540 ExpressionString = " ";
4541 ExpressionString += InstanceMethod->getSelector().getAsString();
4542 ExpressionString += "]";
4543
4544 Diag(Loc, DiagID: diag::err_objc_bridged_related_known_method)
4545 << SrcType << DestType << InstanceMethod->getSelector() << true
4546 << FixItHint::CreateInsertion(InsertionLoc: SrcExpr->getBeginLoc(), Code: "[")
4547 << FixItHint::CreateInsertion(InsertionLoc: SrcExprEndLoc, Code: ExpressionString);
4548 }
4549 Diag(Loc: RelatedClass->getBeginLoc(), DiagID: diag::note_declared_at);
4550 Diag(Loc: TDNDecl->getBeginLoc(), DiagID: diag::note_declared_at);
4551
4552 ExprResult msg = BuildInstanceMessageImplicit(
4553 Receiver: SrcExpr, ReceiverType: SrcType, Loc: InstanceMethod->getLocation(),
4554 Sel: InstanceMethod->getSelector(), Method: InstanceMethod, Args: {});
4555 SrcExpr = msg.get();
4556 }
4557 return true;
4558 }
4559 }
4560 return false;
4561}
4562
4563SemaObjC::ARCConversionResult
4564SemaObjC::CheckObjCConversion(SourceRange castRange, QualType castType,
4565 Expr *&castExpr, CheckedConversionKind CCK,
4566 bool Diagnose, bool DiagnoseCFAudited,
4567 BinaryOperatorKind Opc, bool IsReinterpretCast) {
4568 ASTContext &Context = getASTContext();
4569 QualType castExprType = castExpr->getType();
4570
4571 // For the purposes of the classification, we assume reference types
4572 // will bind to temporaries.
4573 QualType effCastType = castType;
4574 if (const ReferenceType *ref = castType->getAs<ReferenceType>())
4575 effCastType = ref->getPointeeType();
4576
4577 ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(type: castExprType);
4578 ARCConversionTypeClass castACTC = classifyTypeForARCConversion(type: effCastType);
4579 if (exprACTC == castACTC) {
4580 // Check for viability and report error if casting an rvalue to a
4581 // life-time qualifier.
4582 if (castACTC == ACTC_retainable &&
4583 (CCK == CheckedConversionKind::CStyleCast ||
4584 CCK == CheckedConversionKind::OtherCast) &&
4585 castType != castExprType) {
4586 const Type *DT = castType.getTypePtr();
4587 QualType QDT = castType;
4588 // We desugar some types but not others. We ignore those
4589 // that cannot happen in a cast; i.e. auto, and those which
4590 // should not be de-sugared; i.e typedef.
4591 if (const ParenType *PT = dyn_cast<ParenType>(Val: DT))
4592 QDT = PT->desugar();
4593 else if (const TypeOfType *TP = dyn_cast<TypeOfType>(Val: DT))
4594 QDT = TP->desugar();
4595 else if (const AttributedType *AT = dyn_cast<AttributedType>(Val: DT))
4596 QDT = AT->desugar();
4597 if (QDT != castType &&
4598 QDT.getObjCLifetime() != Qualifiers::OCL_None) {
4599 if (Diagnose) {
4600 SourceLocation loc = (castRange.isValid() ? castRange.getBegin()
4601 : castExpr->getExprLoc());
4602 Diag(Loc: loc, DiagID: diag::err_arc_nolifetime_behavior);
4603 }
4604 return ACR_error;
4605 }
4606 }
4607 return ACR_okay;
4608 }
4609
4610 // The life-time qualifier cast check above is all we need for ObjCWeak.
4611 // ObjCAutoRefCount has more restrictions on what is legal.
4612 if (!getLangOpts().ObjCAutoRefCount)
4613 return ACR_okay;
4614
4615 if (isAnyCLike(ACTC: exprACTC) && isAnyCLike(ACTC: castACTC)) return ACR_okay;
4616
4617 // Allow all of these types to be cast to integer types (but not
4618 // vice-versa).
4619 if (castACTC == ACTC_none && castType->isIntegralType(Ctx: Context))
4620 return ACR_okay;
4621
4622 // Allow casts between pointers to lifetime types (e.g., __strong id*)
4623 // and pointers to void (e.g., cv void *). Casting from void* to lifetime*
4624 // must be explicit.
4625 // Allow conversions between pointers to lifetime types and coreFoundation
4626 // pointers too, but only when the conversions are explicit.
4627 // Allow conversions requested with a reinterpret_cast that converts an
4628 // expression of type T* to type U*.
4629 if (exprACTC == ACTC_indirectRetainable &&
4630 (castACTC == ACTC_voidPtr ||
4631 (castACTC == ACTC_coreFoundation && SemaRef.isCast(CCK)) ||
4632 (IsReinterpretCast && effCastType->isAnyPointerType())))
4633 return ACR_okay;
4634 if (castACTC == ACTC_indirectRetainable &&
4635 (((exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) &&
4636 SemaRef.isCast(CCK)) ||
4637 (IsReinterpretCast && castExprType->isAnyPointerType())))
4638 return ACR_okay;
4639
4640 switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(e: castExpr)) {
4641 // For invalid casts, fall through.
4642 case ACC_invalid:
4643 break;
4644
4645 // Do nothing for both bottom and +0.
4646 case ACC_bottom:
4647 case ACC_plusZero:
4648 return ACR_okay;
4649
4650 // If the result is +1, consume it here.
4651 case ACC_plusOne:
4652 castExpr = ImplicitCastExpr::Create(Context, T: castExpr->getType(),
4653 Kind: CK_ARCConsumeObject, Operand: castExpr, BasePath: nullptr,
4654 Cat: VK_PRValue, FPO: FPOptionsOverride());
4655 SemaRef.Cleanup.setExprNeedsCleanups(true);
4656 return ACR_okay;
4657 }
4658
4659 // If this is a non-implicit cast from id or block type to a
4660 // CoreFoundation type, delay complaining in case the cast is used
4661 // in an acceptable context.
4662 if (exprACTC == ACTC_retainable && isAnyRetainable(ACTC: castACTC) &&
4663 SemaRef.isCast(CCK))
4664 return ACR_unbridged;
4665
4666 // Issue a diagnostic about a missing @-sign when implicit casting a cstring
4667 // to 'NSString *', instead of falling through to report a "bridge cast"
4668 // diagnostic.
4669 if (castACTC == ACTC_retainable && exprACTC == ACTC_none &&
4670 CheckConversionToObjCLiteral(DstType: castType, SrcExpr&: castExpr, Diagnose))
4671 return ACR_error;
4672
4673 // Do not issue "bridge cast" diagnostic when implicit casting
4674 // a retainable object to a CF type parameter belonging to an audited
4675 // CF API function. Let caller issue a normal type mismatched diagnostic
4676 // instead.
4677 if ((!DiagnoseCFAudited || exprACTC != ACTC_retainable ||
4678 castACTC != ACTC_coreFoundation) &&
4679 !(exprACTC == ACTC_voidPtr && castACTC == ACTC_retainable &&
4680 (Opc == BO_NE || Opc == BO_EQ))) {
4681 if (Diagnose)
4682 diagnoseObjCARCConversion(S&: SemaRef, castRange, castType, castACTC,
4683 castExpr, realCast: castExpr, exprACTC, CCK);
4684 return ACR_error;
4685 }
4686 return ACR_okay;
4687}
4688
4689/// Given that we saw an expression with the ARCUnbridgedCastTy
4690/// placeholder type, complain bitterly.
4691void SemaObjC::diagnoseARCUnbridgedCast(Expr *e) {
4692 // We expect the spurious ImplicitCastExpr to already have been stripped.
4693 assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
4694 CastExpr *realCast = cast<CastExpr>(Val: e->IgnoreParens());
4695
4696 SourceRange castRange;
4697 QualType castType;
4698 CheckedConversionKind CCK;
4699
4700 if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(Val: realCast)) {
4701 castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc());
4702 castType = cast->getTypeAsWritten();
4703 CCK = CheckedConversionKind::CStyleCast;
4704 } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(Val: realCast)) {
4705 castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange();
4706 castType = cast->getTypeAsWritten();
4707 CCK = CheckedConversionKind::OtherCast;
4708 } else {
4709 llvm_unreachable("Unexpected ImplicitCastExpr");
4710 }
4711
4712 ARCConversionTypeClass castACTC =
4713 classifyTypeForARCConversion(type: castType.getNonReferenceType());
4714
4715 Expr *castExpr = realCast->getSubExpr();
4716 assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);
4717
4718 diagnoseObjCARCConversion(S&: SemaRef, castRange, castType, castACTC, castExpr,
4719 realCast, exprACTC: ACTC_retainable, CCK);
4720}
4721
4722/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast
4723/// type, remove the placeholder cast.
4724Expr *SemaObjC::stripARCUnbridgedCast(Expr *e) {
4725 assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
4726 ASTContext &Context = getASTContext();
4727
4728 if (ParenExpr *pe = dyn_cast<ParenExpr>(Val: e)) {
4729 Expr *sub = stripARCUnbridgedCast(e: pe->getSubExpr());
4730 return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub);
4731 } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(Val: e)) {
4732 assert(uo->getOpcode() == UO_Extension);
4733 Expr *sub = stripARCUnbridgedCast(e: uo->getSubExpr());
4734 return UnaryOperator::Create(C: Context, input: sub, opc: UO_Extension, type: sub->getType(),
4735 VK: sub->getValueKind(), OK: sub->getObjectKind(),
4736 l: uo->getOperatorLoc(), CanOverflow: false,
4737 FPFeatures: SemaRef.CurFPFeatureOverrides());
4738 } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(Val: e)) {
4739 assert(!gse->isResultDependent());
4740 assert(!gse->isTypePredicate());
4741
4742 unsigned n = gse->getNumAssocs();
4743 SmallVector<Expr *, 4> subExprs;
4744 SmallVector<TypeSourceInfo *, 4> subTypes;
4745 subExprs.reserve(N: n);
4746 subTypes.reserve(N: n);
4747 for (const GenericSelectionExpr::Association assoc : gse->associations()) {
4748 subTypes.push_back(Elt: assoc.getTypeSourceInfo());
4749 Expr *sub = assoc.getAssociationExpr();
4750 if (assoc.isSelected())
4751 sub = stripARCUnbridgedCast(e: sub);
4752 subExprs.push_back(Elt: sub);
4753 }
4754
4755 return GenericSelectionExpr::Create(
4756 Context, GenericLoc: gse->getGenericLoc(), ControllingExpr: gse->getControllingExpr(), AssocTypes: subTypes,
4757 AssocExprs: subExprs, DefaultLoc: gse->getDefaultLoc(), RParenLoc: gse->getRParenLoc(),
4758 ContainsUnexpandedParameterPack: gse->containsUnexpandedParameterPack(), ResultIndex: gse->getResultIndex());
4759 } else {
4760 assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!");
4761 return cast<ImplicitCastExpr>(Val: e)->getSubExpr();
4762 }
4763}
4764
4765bool SemaObjC::CheckObjCARCUnavailableWeakConversion(QualType castType,
4766 QualType exprType) {
4767 ASTContext &Context = getASTContext();
4768 QualType canCastType =
4769 Context.getCanonicalType(T: castType).getUnqualifiedType();
4770 QualType canExprType =
4771 Context.getCanonicalType(T: exprType).getUnqualifiedType();
4772 if (isa<ObjCObjectPointerType>(Val: canCastType) &&
4773 castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
4774 canExprType->isObjCObjectPointerType()) {
4775 if (const ObjCObjectPointerType *ObjT =
4776 canExprType->getAs<ObjCObjectPointerType>())
4777 if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl())
4778 return !ObjI->isArcWeakrefUnavailable();
4779 }
4780 return true;
4781}
4782
4783/// Look for an ObjCReclaimReturnedObject cast and destroy it.
4784static Expr *maybeUndoReclaimObject(Expr *e) {
4785 Expr *curExpr = e, *prevExpr = nullptr;
4786
4787 // Walk down the expression until we hit an implicit cast of kind
4788 // ARCReclaimReturnedObject or an Expr that is neither a Paren nor a Cast.
4789 while (true) {
4790 if (auto *pe = dyn_cast<ParenExpr>(Val: curExpr)) {
4791 prevExpr = curExpr;
4792 curExpr = pe->getSubExpr();
4793 continue;
4794 }
4795
4796 if (auto *ce = dyn_cast<CastExpr>(Val: curExpr)) {
4797 if (auto *ice = dyn_cast<ImplicitCastExpr>(Val: ce))
4798 if (ice->getCastKind() == CK_ARCReclaimReturnedObject) {
4799 if (!prevExpr)
4800 return ice->getSubExpr();
4801 if (auto *pe = dyn_cast<ParenExpr>(Val: prevExpr))
4802 pe->setSubExpr(ice->getSubExpr());
4803 else
4804 cast<CastExpr>(Val: prevExpr)->setSubExpr(ice->getSubExpr());
4805 return e;
4806 }
4807
4808 prevExpr = curExpr;
4809 curExpr = ce->getSubExpr();
4810 continue;
4811 }
4812
4813 // Break out of the loop if curExpr is neither a Paren nor a Cast.
4814 break;
4815 }
4816
4817 return e;
4818}
4819
4820ExprResult SemaObjC::BuildObjCBridgedCast(SourceLocation LParenLoc,
4821 ObjCBridgeCastKind Kind,
4822 SourceLocation BridgeKeywordLoc,
4823 TypeSourceInfo *TSInfo,
4824 Expr *SubExpr) {
4825 ASTContext &Context = getASTContext();
4826 ExprResult SubResult = SemaRef.UsualUnaryConversions(E: SubExpr);
4827 if (SubResult.isInvalid()) return ExprError();
4828 SubExpr = SubResult.get();
4829
4830 QualType T = TSInfo->getType();
4831 QualType FromType = SubExpr->getType();
4832
4833 CastKind CK;
4834
4835 bool MustConsume = false;
4836 if (T->isDependentType() || SubExpr->isTypeDependent()) {
4837 // Okay: we'll build a dependent expression type.
4838 CK = CK_Dependent;
4839 } else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) {
4840 // Casting CF -> id
4841 CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast
4842 : CK_CPointerToObjCPointerCast);
4843 switch (Kind) {
4844 case OBC_Bridge:
4845 break;
4846
4847 case OBC_BridgeRetained: {
4848 bool br = isKnownName(name: "CFBridgingRelease");
4849 Diag(Loc: BridgeKeywordLoc, DiagID: diag::err_arc_bridge_cast_wrong_kind)
4850 << 2
4851 << FromType
4852 << (T->isBlockPointerType()? 1 : 0)
4853 << T
4854 << SubExpr->getSourceRange()
4855 << Kind;
4856 Diag(Loc: BridgeKeywordLoc, DiagID: diag::note_arc_bridge)
4857 << FixItHint::CreateReplacement(RemoveRange: BridgeKeywordLoc, Code: "__bridge");
4858 Diag(Loc: BridgeKeywordLoc, DiagID: diag::note_arc_bridge_transfer)
4859 << FromType << br
4860 << FixItHint::CreateReplacement(RemoveRange: BridgeKeywordLoc,
4861 Code: br ? "CFBridgingRelease "
4862 : "__bridge_transfer ");
4863
4864 Kind = OBC_Bridge;
4865 break;
4866 }
4867
4868 case OBC_BridgeTransfer:
4869 // We must consume the Objective-C object produced by the cast.
4870 MustConsume = true;
4871 break;
4872 }
4873 } else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) {
4874 // Okay: id -> CF
4875 CK = CK_BitCast;
4876 switch (Kind) {
4877 case OBC_Bridge:
4878 // Reclaiming a value that's going to be __bridge-casted to CF
4879 // is very dangerous, so we don't do it.
4880 SubExpr = maybeUndoReclaimObject(e: SubExpr);
4881 break;
4882
4883 case OBC_BridgeRetained:
4884 // Produce the object before casting it.
4885 SubExpr = ImplicitCastExpr::Create(Context, T: FromType, Kind: CK_ARCProduceObject,
4886 Operand: SubExpr, BasePath: nullptr, Cat: VK_PRValue,
4887 FPO: FPOptionsOverride());
4888 break;
4889
4890 case OBC_BridgeTransfer: {
4891 bool br = isKnownName(name: "CFBridgingRetain");
4892 Diag(Loc: BridgeKeywordLoc, DiagID: diag::err_arc_bridge_cast_wrong_kind)
4893 << (FromType->isBlockPointerType()? 1 : 0)
4894 << FromType
4895 << 2
4896 << T
4897 << SubExpr->getSourceRange()
4898 << Kind;
4899
4900 Diag(Loc: BridgeKeywordLoc, DiagID: diag::note_arc_bridge)
4901 << FixItHint::CreateReplacement(RemoveRange: BridgeKeywordLoc, Code: "__bridge ");
4902 Diag(Loc: BridgeKeywordLoc, DiagID: diag::note_arc_bridge_retained)
4903 << T << br
4904 << FixItHint::CreateReplacement(RemoveRange: BridgeKeywordLoc,
4905 Code: br ? "CFBridgingRetain " : "__bridge_retained");
4906
4907 Kind = OBC_Bridge;
4908 break;
4909 }
4910 }
4911 } else {
4912 Diag(Loc: LParenLoc, DiagID: diag::err_arc_bridge_cast_incompatible)
4913 << FromType << T << Kind
4914 << SubExpr->getSourceRange()
4915 << TSInfo->getTypeLoc().getSourceRange();
4916 return ExprError();
4917 }
4918
4919 Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK,
4920 BridgeKeywordLoc,
4921 TSInfo, SubExpr);
4922
4923 if (MustConsume) {
4924 SemaRef.Cleanup.setExprNeedsCleanups(true);
4925 Result = ImplicitCastExpr::Create(Context, T, Kind: CK_ARCConsumeObject, Operand: Result,
4926 BasePath: nullptr, Cat: VK_PRValue, FPO: FPOptionsOverride());
4927 }
4928
4929 return Result;
4930}
4931
4932ExprResult SemaObjC::ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc,
4933 ObjCBridgeCastKind Kind,
4934 SourceLocation BridgeKeywordLoc,
4935 ParsedType Type,
4936 SourceLocation RParenLoc,
4937 Expr *SubExpr) {
4938 ASTContext &Context = getASTContext();
4939 TypeSourceInfo *TSInfo = nullptr;
4940 QualType T = SemaRef.GetTypeFromParser(Ty: Type, TInfo: &TSInfo);
4941 if (Kind == OBC_Bridge)
4942 CheckTollFreeBridgeCast(castType: T, castExpr: SubExpr);
4943 if (!TSInfo)
4944 TSInfo = Context.getTrivialTypeSourceInfo(T, Loc: LParenLoc);
4945 return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,
4946 SubExpr);
4947}
4948
4949DeclResult SemaObjC::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
4950 IdentifierInfo *II) {
4951 SourceLocation Loc = Lookup.getNameLoc();
4952 ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl();
4953
4954 // Check for error condition which is already reported.
4955 if (!CurMethod)
4956 return DeclResult(true);
4957
4958 // There are two cases to handle here. 1) scoped lookup could have failed,
4959 // in which case we should look for an ivar. 2) scoped lookup could have
4960 // found a decl, but that decl is outside the current instance method (i.e.
4961 // a global variable). In these two cases, we do a lookup for an ivar with
4962 // this name, if the lookup sucedes, we replace it our current decl.
4963
4964 // If we're in a class method, we don't normally want to look for
4965 // ivars. But if we don't find anything else, and there's an
4966 // ivar, that's an error.
4967 bool IsClassMethod = CurMethod->isClassMethod();
4968
4969 bool LookForIvars;
4970 if (Lookup.empty())
4971 LookForIvars = true;
4972 else if (IsClassMethod)
4973 LookForIvars = false;
4974 else
4975 LookForIvars = (Lookup.isSingleResult() &&
4976 Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
4977 ObjCInterfaceDecl *IFace = nullptr;
4978 if (LookForIvars) {
4979 IFace = CurMethod->getClassInterface();
4980 ObjCInterfaceDecl *ClassDeclared;
4981 ObjCIvarDecl *IV = nullptr;
4982 if (IFace && (IV = IFace->lookupInstanceVariable(IVarName: II, ClassDeclared))) {
4983 // Diagnose using an ivar in a class method.
4984 if (IsClassMethod) {
4985 Diag(Loc, DiagID: diag::err_ivar_use_in_class_method) << IV->getDeclName();
4986 return DeclResult(true);
4987 }
4988
4989 // Diagnose the use of an ivar outside of the declaring class.
4990 if (IV->getAccessControl() == ObjCIvarDecl::Private &&
4991 !declaresSameEntity(D1: ClassDeclared, D2: IFace) &&
4992 !getLangOpts().DebuggerSupport)
4993 Diag(Loc, DiagID: diag::err_private_ivar_access) << IV->getDeclName();
4994
4995 // Success.
4996 return IV;
4997 }
4998 } else if (CurMethod->isInstanceMethod()) {
4999 // We should warn if a local variable hides an ivar.
5000 if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) {
5001 ObjCInterfaceDecl *ClassDeclared;
5002 if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(IVarName: II, ClassDeclared)) {
5003 if (IV->getAccessControl() != ObjCIvarDecl::Private ||
5004 declaresSameEntity(D1: IFace, D2: ClassDeclared))
5005 Diag(Loc, DiagID: diag::warn_ivar_use_hidden) << IV->getDeclName();
5006 }
5007 }
5008 } else if (Lookup.isSingleResult() &&
5009 Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
5010 // If accessing a stand-alone ivar in a class method, this is an error.
5011 if (const ObjCIvarDecl *IV =
5012 dyn_cast<ObjCIvarDecl>(Val: Lookup.getFoundDecl())) {
5013 Diag(Loc, DiagID: diag::err_ivar_use_in_class_method) << IV->getDeclName();
5014 return DeclResult(true);
5015 }
5016 }
5017
5018 // Didn't encounter an error, didn't find an ivar.
5019 return DeclResult(false);
5020}
5021
5022ExprResult SemaObjC::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
5023 IdentifierInfo *II,
5024 bool AllowBuiltinCreation) {
5025 // FIXME: Integrate this lookup step into LookupParsedName.
5026 DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II);
5027 if (Ivar.isInvalid())
5028 return ExprError();
5029 if (Ivar.isUsable())
5030 return BuildIvarRefExpr(S, Loc: Lookup.getNameLoc(),
5031 IV: cast<ObjCIvarDecl>(Val: Ivar.get()));
5032
5033 if (Lookup.empty() && II && AllowBuiltinCreation)
5034 SemaRef.LookupBuiltin(R&: Lookup);
5035
5036 // Sentinel value saying that we didn't do anything special.
5037 return ExprResult(false);
5038}
5039
5040ExprResult SemaObjC::BuildIvarRefExpr(Scope *S, SourceLocation Loc,
5041 ObjCIvarDecl *IV) {
5042 ASTContext &Context = getASTContext();
5043 ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl();
5044 assert(CurMethod && CurMethod->isInstanceMethod() &&
5045 "should not reference ivar from this context");
5046
5047 ObjCInterfaceDecl *IFace = CurMethod->getClassInterface();
5048 assert(IFace && "should not reference ivar from this context");
5049
5050 // If we're referencing an invalid decl, just return this as a silent
5051 // error node. The error diagnostic was already emitted on the decl.
5052 if (IV->isInvalidDecl())
5053 return ExprError();
5054
5055 // Check if referencing a field with __attribute__((deprecated)).
5056 if (SemaRef.DiagnoseUseOfDecl(D: IV, Locs: Loc))
5057 return ExprError();
5058
5059 // FIXME: This should use a new expr for a direct reference, don't
5060 // turn this into Self->ivar, just return a BareIVarExpr or something.
5061 IdentifierInfo &II = Context.Idents.get(Name: "self");
5062 UnqualifiedId SelfName;
5063 SelfName.setImplicitSelfParam(&II);
5064 CXXScopeSpec SelfScopeSpec;
5065 SourceLocation TemplateKWLoc;
5066 ExprResult SelfExpr =
5067 SemaRef.ActOnIdExpression(S, SS&: SelfScopeSpec, TemplateKWLoc, Id&: SelfName,
5068 /*HasTrailingLParen=*/false,
5069 /*IsAddressOfOperand=*/false);
5070 if (SelfExpr.isInvalid())
5071 return ExprError();
5072
5073 SelfExpr = SemaRef.DefaultLvalueConversion(E: SelfExpr.get());
5074 if (SelfExpr.isInvalid())
5075 return ExprError();
5076
5077 SemaRef.MarkAnyDeclReferenced(Loc, D: IV, MightBeOdrUse: true);
5078
5079 ObjCMethodFamily MF = CurMethod->getMethodFamily();
5080 if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
5081 !IvarBacksCurrentMethodAccessor(IFace, Method: CurMethod, IV))
5082 Diag(Loc, DiagID: diag::warn_direct_ivar_access) << IV->getDeclName();
5083
5084 ObjCIvarRefExpr *Result = new (Context)
5085 ObjCIvarRefExpr(IV, IV->getUsageType(objectType: SelfExpr.get()->getType()), Loc,
5086 IV->getLocation(), SelfExpr.get(), true, true);
5087
5088 if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
5089 if (!SemaRef.isUnevaluatedContext() &&
5090 !getDiagnostics().isIgnored(DiagID: diag::warn_arc_repeated_use_of_weak, Loc))
5091 SemaRef.getCurFunction()->recordUseOfWeak(E: Result);
5092 }
5093 if (getLangOpts().ObjCAutoRefCount && !SemaRef.isUnevaluatedContext())
5094 if (const BlockDecl *BD = SemaRef.CurContext->getInnermostBlockDecl())
5095 SemaRef.ImplicitlyRetainedSelfLocs.push_back(Elt: {Loc, BD});
5096
5097 return Result;
5098}
5099
5100QualType SemaObjC::FindCompositeObjCPointerType(ExprResult &LHS,
5101 ExprResult &RHS,
5102 SourceLocation QuestionLoc) {
5103 ASTContext &Context = getASTContext();
5104 QualType LHSTy = LHS.get()->getType();
5105 QualType RHSTy = RHS.get()->getType();
5106
5107 // Handle things like Class and struct objc_class*. Here we case the result
5108 // to the pseudo-builtin, because that will be implicitly cast back to the
5109 // redefinition type if an attempt is made to access its fields.
5110 if (LHSTy->isObjCClassType() &&
5111 (Context.hasSameType(T1: RHSTy, T2: Context.getObjCClassRedefinitionType()))) {
5112 RHS = SemaRef.ImpCastExprToType(E: RHS.get(), Type: LHSTy,
5113 CK: CK_CPointerToObjCPointerCast);
5114 return LHSTy;
5115 }
5116 if (RHSTy->isObjCClassType() &&
5117 (Context.hasSameType(T1: LHSTy, T2: Context.getObjCClassRedefinitionType()))) {
5118 LHS = SemaRef.ImpCastExprToType(E: LHS.get(), Type: RHSTy,
5119 CK: CK_CPointerToObjCPointerCast);
5120 return RHSTy;
5121 }
5122 // And the same for struct objc_object* / id
5123 if (LHSTy->isObjCIdType() &&
5124 (Context.hasSameType(T1: RHSTy, T2: Context.getObjCIdRedefinitionType()))) {
5125 RHS = SemaRef.ImpCastExprToType(E: RHS.get(), Type: LHSTy,
5126 CK: CK_CPointerToObjCPointerCast);
5127 return LHSTy;
5128 }
5129 if (RHSTy->isObjCIdType() &&
5130 (Context.hasSameType(T1: LHSTy, T2: Context.getObjCIdRedefinitionType()))) {
5131 LHS = SemaRef.ImpCastExprToType(E: LHS.get(), Type: RHSTy,
5132 CK: CK_CPointerToObjCPointerCast);
5133 return RHSTy;
5134 }
5135 // And the same for struct objc_selector* / SEL
5136 if (Context.isObjCSelType(T: LHSTy) &&
5137 (Context.hasSameType(T1: RHSTy, T2: Context.getObjCSelRedefinitionType()))) {
5138 RHS = SemaRef.ImpCastExprToType(E: RHS.get(), Type: LHSTy, CK: CK_BitCast);
5139 return LHSTy;
5140 }
5141 if (Context.isObjCSelType(T: RHSTy) &&
5142 (Context.hasSameType(T1: LHSTy, T2: Context.getObjCSelRedefinitionType()))) {
5143 LHS = SemaRef.ImpCastExprToType(E: LHS.get(), Type: RHSTy, CK: CK_BitCast);
5144 return RHSTy;
5145 }
5146 // Check constraints for Objective-C object pointers types.
5147 if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {
5148
5149 if (Context.getCanonicalType(T: LHSTy) == Context.getCanonicalType(T: RHSTy)) {
5150 // Two identical object pointer types are always compatible.
5151 return LHSTy;
5152 }
5153 const ObjCObjectPointerType *LHSOPT =
5154 LHSTy->castAs<ObjCObjectPointerType>();
5155 const ObjCObjectPointerType *RHSOPT =
5156 RHSTy->castAs<ObjCObjectPointerType>();
5157 QualType compositeType = LHSTy;
5158
5159 // If both operands are interfaces and either operand can be
5160 // assigned to the other, use that type as the composite
5161 // type. This allows
5162 // xxx ? (A*) a : (B*) b
5163 // where B is a subclass of A.
5164 //
5165 // Additionally, as for assignment, if either type is 'id'
5166 // allow silent coercion. Finally, if the types are
5167 // incompatible then make sure to use 'id' as the composite
5168 // type so the result is acceptable for sending messages to.
5169
5170 // FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
5171 // It could return the composite type.
5172 if (!(compositeType = Context.areCommonBaseCompatible(LHSOPT, RHSOPT))
5173 .isNull()) {
5174 // Nothing more to do.
5175 } else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
5176 compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;
5177 } else if (Context.canAssignObjCInterfaces(LHSOPT: RHSOPT, RHSOPT: LHSOPT)) {
5178 compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;
5179 } else if ((LHSOPT->isObjCQualifiedIdType() ||
5180 RHSOPT->isObjCQualifiedIdType()) &&
5181 Context.ObjCQualifiedIdTypesAreCompatible(LHS: LHSOPT, RHS: RHSOPT,
5182 ForCompare: true)) {
5183 // Need to handle "id<xx>" explicitly.
5184 // GCC allows qualified id and any Objective-C type to devolve to
5185 // id. Currently localizing to here until clear this should be
5186 // part of ObjCQualifiedIdTypesAreCompatible.
5187 compositeType = Context.getObjCIdType();
5188 } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
5189 compositeType = Context.getObjCIdType();
5190 } else {
5191 Diag(Loc: QuestionLoc, DiagID: diag::ext_typecheck_cond_incompatible_operands)
5192 << LHSTy << RHSTy << LHS.get()->getSourceRange()
5193 << RHS.get()->getSourceRange();
5194 QualType incompatTy = Context.getObjCIdType();
5195 LHS = SemaRef.ImpCastExprToType(E: LHS.get(), Type: incompatTy, CK: CK_BitCast);
5196 RHS = SemaRef.ImpCastExprToType(E: RHS.get(), Type: incompatTy, CK: CK_BitCast);
5197 return incompatTy;
5198 }
5199 // The object pointer types are compatible.
5200 LHS = SemaRef.ImpCastExprToType(E: LHS.get(), Type: compositeType, CK: CK_BitCast);
5201 RHS = SemaRef.ImpCastExprToType(E: RHS.get(), Type: compositeType, CK: CK_BitCast);
5202 return compositeType;
5203 }
5204 // Check Objective-C object pointer types and 'void *'
5205 if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
5206 if (getLangOpts().ObjCAutoRefCount) {
5207 // ARC forbids the implicit conversion of object pointers to 'void *',
5208 // so these types are not compatible.
5209 Diag(Loc: QuestionLoc, DiagID: diag::err_cond_voidptr_arc)
5210 << LHSTy << RHSTy << LHS.get()->getSourceRange()
5211 << RHS.get()->getSourceRange();
5212 LHS = RHS = true;
5213 return QualType();
5214 }
5215 QualType lhptee = LHSTy->castAs<PointerType>()->getPointeeType();
5216 QualType rhptee = RHSTy->castAs<ObjCObjectPointerType>()->getPointeeType();
5217 QualType destPointee =
5218 Context.getQualifiedType(T: lhptee, Qs: rhptee.getQualifiers());
5219 QualType destType = Context.getPointerType(T: destPointee);
5220 // Add qualifiers if necessary.
5221 LHS = SemaRef.ImpCastExprToType(E: LHS.get(), Type: destType, CK: CK_NoOp);
5222 // Promote to void*.
5223 RHS = SemaRef.ImpCastExprToType(E: RHS.get(), Type: destType, CK: CK_BitCast);
5224 return destType;
5225 }
5226 if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
5227 if (getLangOpts().ObjCAutoRefCount) {
5228 // ARC forbids the implicit conversion of object pointers to 'void *',
5229 // so these types are not compatible.
5230 Diag(Loc: QuestionLoc, DiagID: diag::err_cond_voidptr_arc)
5231 << LHSTy << RHSTy << LHS.get()->getSourceRange()
5232 << RHS.get()->getSourceRange();
5233 LHS = RHS = true;
5234 return QualType();
5235 }
5236 QualType lhptee = LHSTy->castAs<ObjCObjectPointerType>()->getPointeeType();
5237 QualType rhptee = RHSTy->castAs<PointerType>()->getPointeeType();
5238 QualType destPointee =
5239 Context.getQualifiedType(T: rhptee, Qs: lhptee.getQualifiers());
5240 QualType destType = Context.getPointerType(T: destPointee);
5241 // Add qualifiers if necessary.
5242 RHS = SemaRef.ImpCastExprToType(E: RHS.get(), Type: destType, CK: CK_NoOp);
5243 // Promote to void*.
5244 LHS = SemaRef.ImpCastExprToType(E: LHS.get(), Type: destType, CK: CK_BitCast);
5245 return destType;
5246 }
5247 return QualType();
5248}
5249
5250bool SemaObjC::CheckConversionToObjCLiteral(QualType DstType, Expr *&Exp,
5251 bool Diagnose) {
5252 if (!getLangOpts().ObjC)
5253 return false;
5254
5255 const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
5256 if (!PT)
5257 return false;
5258 const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
5259
5260 // Ignore any parens, implicit casts (should only be
5261 // array-to-pointer decays), and not-so-opaque values. The last is
5262 // important for making this trigger for property assignments.
5263 Expr *SrcExpr = Exp->IgnoreParenImpCasts();
5264 if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(Val: SrcExpr))
5265 if (OV->getSourceExpr())
5266 SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();
5267
5268 if (auto *SL = dyn_cast<StringLiteral>(Val: SrcExpr)) {
5269 if (!PT->isObjCIdType() && !(ID && ID->getIdentifier()->isStr(Str: "NSString")))
5270 return false;
5271 if (!SL->isOrdinary())
5272 return false;
5273
5274 if (Diagnose) {
5275 Diag(Loc: SL->getBeginLoc(), DiagID: diag::err_missing_atsign_prefix)
5276 << /*string*/ 0 << FixItHint::CreateInsertion(InsertionLoc: SL->getBeginLoc(), Code: "@");
5277 Exp = BuildObjCStringLiteral(AtLoc: SL->getBeginLoc(), S: SL).get();
5278 }
5279 return true;
5280 }
5281
5282 if ((isa<IntegerLiteral>(Val: SrcExpr) || isa<CharacterLiteral>(Val: SrcExpr) ||
5283 isa<FloatingLiteral>(Val: SrcExpr) || isa<ObjCBoolLiteralExpr>(Val: SrcExpr) ||
5284 isa<CXXBoolLiteralExpr>(Val: SrcExpr)) &&
5285 !SrcExpr->isNullPointerConstant(Ctx&: getASTContext(),
5286 NPC: Expr::NPC_NeverValueDependent)) {
5287 if (!ID || !ID->getIdentifier()->isStr(Str: "NSNumber"))
5288 return false;
5289 if (Diagnose) {
5290 Diag(Loc: SrcExpr->getBeginLoc(), DiagID: diag::err_missing_atsign_prefix)
5291 << /*number*/ 1
5292 << FixItHint::CreateInsertion(InsertionLoc: SrcExpr->getBeginLoc(), Code: "@");
5293 Expr *NumLit =
5294 BuildObjCNumericLiteral(AtLoc: SrcExpr->getBeginLoc(), Number: SrcExpr).get();
5295 if (NumLit)
5296 Exp = NumLit;
5297 }
5298 return true;
5299 }
5300
5301 return false;
5302}
5303
5304/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
5305ExprResult SemaObjC::ActOnObjCBoolLiteral(SourceLocation OpLoc,
5306 tok::TokenKind Kind) {
5307 assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&
5308 "Unknown Objective-C Boolean value!");
5309 ASTContext &Context = getASTContext();
5310 QualType BoolT = Context.ObjCBuiltinBoolTy;
5311 if (!Context.getBOOLDecl()) {
5312 LookupResult Result(SemaRef, &Context.Idents.get(Name: "BOOL"), OpLoc,
5313 Sema::LookupOrdinaryName);
5314 if (SemaRef.LookupName(R&: Result, S: SemaRef.getCurScope()) &&
5315 Result.isSingleResult()) {
5316 NamedDecl *ND = Result.getFoundDecl();
5317 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(Val: ND))
5318 Context.setBOOLDecl(TD);
5319 }
5320 }
5321 if (Context.getBOOLDecl())
5322 BoolT = Context.getBOOLType();
5323 return new (Context)
5324 ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc);
5325}
5326
5327ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr(
5328 llvm::ArrayRef<AvailabilitySpec> AvailSpecs, SourceLocation AtLoc,
5329 SourceLocation RParen) {
5330 ASTContext &Context = getASTContext();
5331 auto FindSpecVersion =
5332 [&](StringRef Platform,
5333 const llvm::Triple::OSType &OS) -> std::optional<VersionTuple> {
5334 auto Spec = llvm::find_if(Range&: AvailSpecs, P: [&](const AvailabilitySpec &Spec) {
5335 return Spec.getPlatform() == Platform;
5336 });
5337 // Transcribe the "ios" availability check to "maccatalyst" when compiling
5338 // for "maccatalyst" if "maccatalyst" is not specified.
5339 if (Spec == AvailSpecs.end() && Platform == "maccatalyst") {
5340 Spec = llvm::find_if(Range&: AvailSpecs, P: [&](const AvailabilitySpec &Spec) {
5341 return Spec.getPlatform() == "ios";
5342 });
5343 }
5344 // Use "anyappleos" spec if no platform-specific spec is found and the
5345 // target is an Apple OS.
5346 if (Spec == AvailSpecs.end()) {
5347 // Check if this OS is a Darwin/Apple OS.
5348 const llvm::Triple &Triple = Context.getTargetInfo().getTriple();
5349 if (Triple.isOSDarwin()) {
5350 Spec = llvm::find_if(Range&: AvailSpecs, P: [&](const AvailabilitySpec &Spec) {
5351 return Spec.getPlatform() == "anyappleos";
5352 });
5353 }
5354 }
5355 if (Spec == AvailSpecs.end())
5356 return std::nullopt;
5357
5358 return llvm::Triple::getCanonicalVersionForOS(
5359 OSKind: OS, Version: Spec->getVersion(),
5360 IsInValidRange: llvm::Triple::isValidVersionForOS(OSKind: OS, Version: Spec->getVersion()));
5361 };
5362
5363 VersionTuple Version;
5364 if (auto MaybeVersion =
5365 FindSpecVersion(Context.getTargetInfo().getPlatformName(),
5366 Context.getTargetInfo().getTriple().getOS()))
5367 Version = *MaybeVersion;
5368
5369 // The use of `@available` in the enclosing context should be analyzed to
5370 // warn when it's used inappropriately (i.e. not if(@available)).
5371 if (FunctionScopeInfo *Context = SemaRef.getCurFunctionAvailabilityContext())
5372 Context->HasPotentialAvailabilityViolations = true;
5373
5374 return new (Context)
5375 ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
5376}
5377
5378/// Prepare a conversion of the given expression to an ObjC object
5379/// pointer type.
5380CastKind SemaObjC::PrepareCastToObjCObjectPointer(ExprResult &E) {
5381 QualType type = E.get()->getType();
5382 if (type->isObjCObjectPointerType()) {
5383 return CK_BitCast;
5384 } else if (type->isBlockPointerType()) {
5385 SemaRef.maybeExtendBlockObject(E);
5386 return CK_BlockPointerToObjCPointerCast;
5387 } else {
5388 assert(type->isPointerType());
5389 return CK_CPointerToObjCPointerCast;
5390 }
5391}
5392
5393SemaObjC::ObjCLiteralKind SemaObjC::CheckLiteralKind(Expr *FromE) {
5394 FromE = FromE->IgnoreParenImpCasts();
5395 switch (FromE->getStmtClass()) {
5396 default:
5397 break;
5398 case Stmt::ObjCStringLiteralClass:
5399 // "string literal"
5400 return LK_String;
5401 case Stmt::ObjCArrayLiteralClass:
5402 // "array literal"
5403 return LK_Array;
5404 case Stmt::ObjCDictionaryLiteralClass:
5405 // "dictionary literal"
5406 return LK_Dictionary;
5407 case Stmt::BlockExprClass:
5408 return LK_Block;
5409 case Stmt::ObjCBoxedExprClass: {
5410 Expr *Inner = cast<ObjCBoxedExpr>(Val: FromE)->getSubExpr()->IgnoreParens();
5411 switch (Inner->getStmtClass()) {
5412 case Stmt::IntegerLiteralClass:
5413 case Stmt::FloatingLiteralClass:
5414 case Stmt::CharacterLiteralClass:
5415 case Stmt::ObjCBoolLiteralExprClass:
5416 case Stmt::CXXBoolLiteralExprClass:
5417 // "numeric literal"
5418 return LK_Numeric;
5419 case Stmt::ImplicitCastExprClass: {
5420 CastKind CK = cast<CastExpr>(Val: Inner)->getCastKind();
5421 // Boolean literals can be represented by implicit casts.
5422 if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast)
5423 return LK_Numeric;
5424 break;
5425 }
5426 default:
5427 break;
5428 }
5429 return LK_Boxed;
5430 }
5431 }
5432 return LK_None;
5433}
5434