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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Sema/SemaExprObjC.cpp