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