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