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