clang: lib/Sema/SemaSwift.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

22

25

27 StringRef Name) {

28 if (const auto *PrevSNA = D->getAttr()) {

29 if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) {

30 Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)

31 << PrevSNA << &SNA

32 << (PrevSNA->isRegularKeywordAttribute() ||

33 SNA.isRegularKeywordAttribute());

34 Diag(SNA.getLoc(), diag::note_conflicting_attribute);

35 }

36

38 }

40}

41

42

48

49

60

61

67 } else {

69 }

71 return false;

73}

74

76

78 ContextName.split(ContextNameComponents, '.');

79 return all_of(ContextNameComponents, [&](StringRef Component) {

81 });

82}

83

86 return;

87

88

89

90 StringRef Str;

91 if (SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str)) {

93 return;

94 }

95

97}

98

100

101

102 StringRef BT;

103 if (SemaRef.checkStringLiteralArgumentAttr(AL, 0, BT))

104 return;

105

106

107

108 if (const auto *Other = D->getAttr()) {

109 if (Other->getSwiftType() != BT)

110 Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;

111 return;

112 }

113

115}

116

119 if (!PT)

120 return false;

121

123

124

126 if (const auto *ID = OPT->getInterfaceDecl())

128 return true;

129

130

132 if (auto *RD = PT->getPointeeType()->getAsRecordDecl();

134 return true;

135

136 return false;

137}

138

140 auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {

143 return true;

144 }

145

146 S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)

147 << AL << isa(D);

148 return false;

149 };

150

151 auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {

152

153

154

157 return true;

158

159 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)

162 return false;

163 };

164

165 auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {

168 return true;

169

170 S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)

173 return false;

174 };

175

177 return;

178

180 SwiftErrorAttr::ConventionKind Convention;

181 if (!SwiftErrorAttr::ConvertStrToConventionKind(

183 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)

185 return;

186 }

187

188 switch (Convention) {

189 case SwiftErrorAttr::None:

190

191 break;

192

193 case SwiftErrorAttr::NonNullError:

194 if (!hasErrorParameter(SemaRef, D, AL))

195 return;

196 break;

197

198 case SwiftErrorAttr::NullResult:

199 if (!hasErrorParameter(SemaRef, D, AL) || !hasPointerResult(SemaRef, D, AL))

200 return;

201 break;

202

203 case SwiftErrorAttr::NonZeroResult:

204 case SwiftErrorAttr::ZeroResult:

205 if (!hasErrorParameter(SemaRef, D, AL) || !hasIntegerResult(SemaRef, D, AL))

206 return;

207 break;

208 }

209

211 SwiftErrorAttr(getASTContext(), AL, Convention));

212}

213

215 const SwiftAsyncErrorAttr *ErrorAttr,

216 const SwiftAsyncAttr *AsyncAttr) {

217 if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {

218 if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {

219 S.Diag(AsyncAttr->getLocation(),

220 diag::err_swift_async_error_without_swift_async)

221 << AsyncAttr << isa(D);

222 }

223 return;

224 }

225

227 D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());

228

229

230 const auto *FuncTy = HandlerParam->getType()

235 if (FuncTy)

236 BlockParams = FuncTy->getParamTypes();

237

238 switch (ErrorAttr->getConvention()) {

239 case SwiftAsyncErrorAttr::ZeroArgument:

240 case SwiftAsyncErrorAttr::NonZeroArgument: {

241 uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();

243 S.Diag(ErrorAttr->getLocation(),

244 diag::err_attribute_argument_out_of_bounds)

245 << ErrorAttr << 2;

246 return;

247 }

250 StringRef ConvStr =

251 ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument

252 ? "zero_argument"

253 : "nonzero_argument";

254 S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)

255 << ErrorAttr << ConvStr << ParamIdx << ErrorParam;

256 return;

257 }

258 break;

259 }

260 case SwiftAsyncErrorAttr::NonNullError: {

261 bool AnyErrorParams = false;

262 for (QualType Param : BlockParams) {

263

265 if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {

267 AnyErrorParams = true;

268 break;

269 }

270 }

271 }

272

273 if (const auto *PtrTy = Param->getAs<PointerType>()) {

274 if (auto *RD = PtrTy->getPointeeType()->getAsRecordDecl();

276 AnyErrorParams = true;

277 break;

278 }

279 }

280 }

281

282 if (!AnyErrorParams) {

283 S.Diag(ErrorAttr->getLocation(),

284 diag::err_swift_async_error_no_error_parameter)

285 << ErrorAttr << isa(D);

286 return;

287 }

288 break;

289 }

290 case SwiftAsyncErrorAttr::None:

291 break;

292 }

293}

294

297 SwiftAsyncErrorAttr::ConventionKind ConvKind;

298 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(

300 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)

302 return;

303 }

304

306 switch (ConvKind) {

307 case SwiftAsyncErrorAttr::ZeroArgument:

308 case SwiftAsyncErrorAttr::NonZeroArgument: {

310 return;

311

314 return;

315 break;

316 }

317 case SwiftAsyncErrorAttr::NonNullError:

318 case SwiftAsyncErrorAttr::None: {

320 return;

321 break;

322 }

323 }

324

328

329 if (auto *AsyncAttr = D->getAttr())

331}

332

333

334

335

336

337

338

339

340

343 unsigned &SwiftParamCount,

344 bool &IsSingleParamInit) {

345 SwiftParamCount = 0;

346 IsSingleParamInit = false;

347

348

349 bool IsGetter = false, IsSetter = false;

350 if (Name.consume_front("getter:"))

351 IsGetter = true;

352 else if (Name.consume_front("setter:"))

353 IsSetter = true;

354

355 if (Name.empty() || Name.back() != ')') {

356 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;

357 return false;

358 }

359

360 bool IsMember = false;

361 StringRef ContextName, BaseName, Parameters;

362

363 std::tie(BaseName, Parameters) = Name.split('(');

364

365

366

367 std::tie(ContextName, BaseName) = BaseName.rsplit('.');

368 if (BaseName.empty()) {

369 BaseName = ContextName;

370 ContextName = StringRef();

372 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)

373 << AL << 1;

374 return false;

375 } else {

376 IsMember = true;

377 }

378

380 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)

381 << AL << 0;

382 return false;

383 }

384

385 bool IsSubscript = BaseName == "subscript";

386

387 if (IsSubscript && !IsGetter && !IsSetter) {

388 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)

389 << AL << 0;

390 return false;

391 }

392

393 if (Parameters.empty()) {

394 S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;

395 return false;

396 }

397

398 assert(Parameters.back() == ')' && "expected ')'");

399 Parameters = Parameters.drop_back();

400

401 if (Parameters.empty()) {

402

403 if (IsSubscript) {

404 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)

405 << AL << 1;

406 return false;

407 }

408

409 if (IsSetter) {

410 S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;

411 return false;

412 }

413

414 return true;

415 }

416

417 if (Parameters.back() != ':') {

418 S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;

419 return false;

420 }

421

422 StringRef CurrentParam;

423 std::optional SelfLocation;

424 unsigned NewValueCount = 0;

425 std::optional NewValueLocation;

426 do {

427 std::tie(CurrentParam, Parameters) = Parameters.split(':');

428

430 S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)

431 << AL << 2;

432 return false;

433 }

434

435 if (IsMember && CurrentParam == "self") {

436

437

438

439 if (SelfLocation) {

440 S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;

441 return false;

442 }

443

444

445 SelfLocation = SwiftParamCount;

446 } else if (CurrentParam == "newValue") {

447

448

449

450

451 ++NewValueCount;

452

453 NewValueLocation = SwiftParamCount;

454 }

455

456 ++SwiftParamCount;

457 } while (!Parameters.empty());

458

459

460 if (IsSubscript && !SelfLocation) {

461 S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)

462 << AL << 2;

463 return false;

464 }

465

466 IsSingleParamInit =

467 SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";

468

469

470 if (IsGetter || IsSetter) {

471

472 unsigned NumExpectedParams = IsGetter ? 0 : 1;

473 unsigned ParamDiag = IsGetter

474 ? diag::warn_attr_swift_name_getter_parameters

475 : diag::warn_attr_swift_name_setter_parameters;

476

477

478 if (SelfLocation)

479 ++NumExpectedParams;

480

481

482

483 if (IsSubscript) {

484 if (SwiftParamCount < NumExpectedParams) {

485 S.Diag(Loc, ParamDiag) << AL;

486 return false;

487 }

488

489

490

491 if (IsSetter) {

492 if (!NewValueLocation) {

493 S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)

494 << AL;

495 return false;

496 }

497 if (NewValueCount > 1) {

499 diag::warn_attr_swift_name_subscript_setter_multiple_newValues)

500 << AL;

501 return false;

502 }

503 } else {

504

505 if (NewValueLocation) {

506 S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)

507 << AL;

508 return false;

509 }

510 }

511 } else {

512

513 if (SwiftParamCount != NumExpectedParams) {

514 S.Diag(Loc, ParamDiag) << AL;

515 return false;

516 }

517 }

518 }

519

520 return true;

521}

522

524 const ParsedAttr &AL, bool IsAsync) {

527 unsigned ParamCount;

528

529 if (const auto *Method = dyn_cast(D)) {

530 ParamCount = Method->getSelector().getNumArgs();

531 Params = Method->parameters().slice(0, ParamCount);

532 } else {

534

535 ParamCount = F->getNumParams();

536 Params = F->parameters();

537

538 if (!F->hasWrittenPrototype()) {

539 Diag(Loc, diag::warn_attribute_wrong_decl_type)

542 return false;

543 }

544 }

545

546

547 if (IsAsync) {

548 if (ParamCount == 0) {

549 Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)

550 << AL << isa(D);

551 return false;

552 }

553 ParamCount -= 1;

554 }

555

556 unsigned SwiftParamCount;

557 bool IsSingleParamInit;

559 IsSingleParamInit))

560 return false;

561

562 bool ParamCountValid;

563 if (SwiftParamCount == ParamCount) {

564 ParamCountValid = true;

565 } else if (SwiftParamCount > ParamCount) {

566 ParamCountValid = IsSingleParamInit && ParamCount == 0;

567 } else {

568

569

570

571 unsigned MaybeOutParamCount =

572 llvm::count_if(Params, [](const ParmVarDecl *Param) -> bool {

573 QualType ParamTy = Param->getType();

576 return false;

577 });

578

579 ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;

580 }

581

582 if (!ParamCountValid) {

583 Diag(Loc, diag::warn_attr_swift_name_num_params)

584 << (SwiftParamCount > ParamCount) << AL << ParamCount

585 << SwiftParamCount;

586 return false;

587 }

592 !IsAsync) {

593 StringRef ContextName, BaseName;

594

595 std::tie(ContextName, BaseName) = Name.rsplit('.');

596 if (BaseName.empty()) {

597 BaseName = ContextName;

598 ContextName = StringRef();

600 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)

601 << AL << 1;

602 return false;

603 }

604

606 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)

607 << AL << 0;

608 return false;

609 }

610 } else {

611 Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;

612 return false;

613 }

614 return true;

615}

616

618 StringRef Name;

620 if (SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))

621 return;

622

623 if (DiagnoseName(D, Name, Loc, AL, false))

624 return;

625

627}

628

630 StringRef Name;

632 if (SemaRef.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))

633 return;

634

635 if (DiagnoseName(D, Name, Loc, AL, true))

636 return;

637

640}

641

643

645 return;

646

648 Diag(AL.getLoc(), diag::err_attribute_argument_type)

650 return;

651 }

652

653 SwiftNewTypeAttr::NewtypeKind Kind;

655 if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {

656 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;

657 return;

658 }

659

661 Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)

663 return;

664 }

665

668}

669

672 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)

674 return;

675 }

676

677 SwiftAsyncAttr::Kind Kind;

679 if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {

680 Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;

681 return;

682 }

683

685 if (Kind == SwiftAsyncAttr::None) {

686

688 return;

689 } else {

690

692 return;

693

695 if (SemaRef.checkFunctionOrMethodParameterIndex(D, AL, 2, HandlerIdx, Idx))

696 return;

697

700 QualType CompletionBlockType = CompletionBlock->getType();

702 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)

703 << CompletionBlock->getType();

704 return;

705 }

709 Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type)

710 << CompletionBlock->getType();

711 return;

712 }

713 }

714

715 auto *AsyncAttr =

718

719 if (auto *ErrorAttr = D->getAttr())

721}

722

727

729 if (existingAttr->getABI() != abi) {

730 Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)

733 existingAttr->isRegularKeywordAttribute());

734 Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);

735 return;

736 }

737 }

738

739 switch (abi) {

742 llvm_unreachable("explicit attribute for non-swift parameter ABI?");

744 llvm_unreachable("explicit attribute for ordinary parameter ABI?");

745

748 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)

750 }

751 D->addAttr(::new (Context) SwiftContextAttr(Context, CI));

752 return;

753

756 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)

758 }

759 D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));

760 return;

761

764 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)

766 }

767 D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));

768 return;

769

772 Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)

774 }

775 D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));

776 return;

777 }

778 llvm_unreachable("bad parameter ABI attribute");

779}

780

781}

This file declares semantic analysis for Objective-C.

This file declares semantic analysis functions specific to Swift.

Defines various enumerations that describe declaration and type specifiers.

static QualType getPointeeType(const MemRegion *R)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

bool isRegularKeywordAttribute() const

SourceLocation getLoc() const

Decl - This represents one declaration (or definition), e.g.

bool isInvalidDecl() const

SourceLocation getLocation() const

This represents one expression.

Represents a prototype with parameter type info, e.g.

FunctionType - C99 6.7.5.3 - Function Declarators.

QualType getReturnType() const

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

A simple pair of identifier info and location.

IdentifierInfo * getIdentifierInfo() const

Represents a pointer to an Objective C object.

A single parameter index whose accessors require each use to make explicit the parameter index encodi...

unsigned getASTIndex() const

Get the parameter index as it would normally be encoded at the AST level of representation: zero-orig...

A parameter attribute which changes the argument-passing ABI rule for the parameter.

Represents a parameter to a function.

ParsedAttr - Represents a syntactic attribute.

bool checkExactlyNumArgs(class Sema &S, unsigned Num) const

Check if the attribute has exactly as many args as Num.

IdentifierLoc * getArgAsIdent(unsigned Arg) const

void setInvalid(bool b=true) const

bool isArgIdent(unsigned Arg) const

Expr * getArgAsExpr(unsigned Arg) const

bool isUsedAsTypeAttr() const

PointerType - C99 6.7.5.1 - Pointer Declarators.

A (possibly-)qualified type.

LangAS getAddressSpace() const

Return the address space of this type.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

bool isConstQualified() const

Determine whether this type is const-qualified.

Base for LValueReferenceType and RValueReferenceType.

ASTContext & getASTContext() const

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

bool isCFError(RecordDecl *D)

IdentifierInfo * getNSErrorIdent()

Retrieve the identifier "NSError".

void handleBridge(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:99

void handleAsyncAttr(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:670

bool DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc, const ParsedAttr &AL, bool IsAsync)

Do a check to make sure Name looks like a legal argument for the swift_name attribute applied to decl...

Definition SemaSwift.cpp:523

void handleAsyncName(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:629

SwiftNameAttr * mergeNameAttr(Decl *D, const SwiftNameAttr &SNA, StringRef Name)

Definition SemaSwift.cpp:26

void handleNewType(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:642

SemaSwift(Sema &S)

Definition SemaSwift.cpp:24

void handleError(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:139

void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, ParameterABI abi)

Definition SemaSwift.cpp:723

void handleAsyncError(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:295

void handleName(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:617

void handleAttrAttr(Decl *D, const ParsedAttr &AL)

Definition SemaSwift.cpp:84

Sema - This implements semantic analysis and AST building for C.

Encodes a location in the source.

bool isBlockPointerType() const

bool isPointerType() const

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

bool isIntegralType(const ASTContext &Ctx) const

Determine whether this type is an integral type.

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

const T * getAs() const

Member-template getAs'.

bool hasPointerRepresentation() const

Whether this type is represented natively as a pointer.

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

The JSON file list parser is used to communicate input to InstallAPI.

static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, const SwiftAsyncErrorAttr *ErrorAttr, const SwiftAsyncAttr *AsyncAttr)

Definition SemaSwift.cpp:214

bool isa(CodeGen::Address addr)

@ ExpectedFunctionWithProtoType

static bool isValidSwiftErrorResultType(QualType Ty)

Pointers and references to pointers in the default address space.

Definition SemaSwift.cpp:62

llvm::StringRef getParameterABISpelling(ParameterABI kind)

QualType getFunctionOrMethodResultType(const Decl *D)

static bool isValidSwiftContextName(StringRef ContextName)

Definition SemaSwift.cpp:75

const ParmVarDecl * getFunctionOrMethodParam(const Decl *D, unsigned Idx)

static bool isErrorParameter(Sema &S, QualType QT)

Definition SemaSwift.cpp:117

LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)

Return true if this is a valid ASCII identifier.

static bool isValidSwiftIndirectResultType(QualType Ty)

Pointers and references in the default address space.

Definition SemaSwift.cpp:50

QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx)

@ AANT_ArgumentIdentifier

ParameterABI

Kinds of parameter ABI.

@ SwiftAsyncContext

This parameter (which must have pointer type) uses the special Swift asynchronous context-pointer ABI...

@ SwiftErrorResult

This parameter (which must have pointer-to-pointer type) uses the special Swift error-result ABI trea...

@ Ordinary

This parameter uses ordinary ABI rules for its type.

@ SwiftIndirectResult

This parameter (which must have pointer type) is a Swift indirect result parameter.

@ SwiftContext

This parameter (which must have pointer type) uses the special Swift context-pointer ABI treatment.

static bool isValidSwiftContextType(QualType Ty)

Pointer-like types in the default address space.

Definition SemaSwift.cpp:43

static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc, StringRef Name, unsigned &SwiftParamCount, bool &IsSingleParamInit)

Definition SemaSwift.cpp:341

unsigned getFunctionOrMethodNumParams(const Decl *D)

getFunctionOrMethodNumParams - Return number of function or method parameters.

U cast(CodeGen::Address addr)

@ Other

Other implicit parameter.