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