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

37 D->dropAttr();

38 }

40}

41

42

47}

48

49

55 } else {

57 }

59}

60

61

67 } else {

69 }

71 return false;

73}

74

77 return;

78

79

80

81 StringRef Str;

84 return;

85 }

86

88}

89

91

92

93 StringRef BT;

95 return;

96

97

98

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

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

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

102 return;

103 }

104

106}

107

110 if (!PT)

111 return false;

112

114

115

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

119 return true;

120

121

123 if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())

125 return true;

126

127 return false;

128}

129

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

134 return true;

135 }

136

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

138 << AL << isa(D);

139 return false;

140 };

141

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

143

144

145

148 return true;

149

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

152 << 1;

153 return false;

154 };

155

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

159 return true;

160

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

163 << 0;

164 return false;

165 };

166

167 if (D->isInvalidDecl())

168 return;

169

171 SwiftErrorAttr::ConventionKind Convention;

172 if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(),

173 Convention)) {

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

175 << AL << Loc->Ident;

176 return;

177 }

178

179 switch (Convention) {

180 case SwiftErrorAttr::None:

181

182 break;

183

184 case SwiftErrorAttr::NonNullError:

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

186 return;

187 break;

188

189 case SwiftErrorAttr::NullResult:

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

191 return;

192 break;

193

194 case SwiftErrorAttr::NonZeroResult:

195 case SwiftErrorAttr::ZeroResult:

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

197 return;

198 break;

199 }

200

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

203}

204

206 const SwiftAsyncErrorAttr *ErrorAttr,

207 const SwiftAsyncAttr *AsyncAttr) {

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

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

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

211 diag::err_swift_async_error_without_swift_async)

212 << AsyncAttr << isa(D);

213 }

214 return;

215 }

216

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

219

220

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

226 if (FuncTy)

227 BlockParams = FuncTy->getParamTypes();

228

229 switch (ErrorAttr->getConvention()) {

230 case SwiftAsyncErrorAttr::ZeroArgument:

231 case SwiftAsyncErrorAttr::NonZeroArgument: {

232 uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();

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

235 diag::err_attribute_argument_out_of_bounds)

236 << ErrorAttr << 2;

237 return;

238 }

241 StringRef ConvStr =

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

243 ? "zero_argument"

244 : "nonzero_argument";

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

246 << ErrorAttr << ConvStr << ParamIdx << ErrorParam;

247 return;

248 }

249 break;

250 }

251 case SwiftAsyncErrorAttr::NonNullError: {

252 bool AnyErrorParams = false;

253 for (QualType Param : BlockParams) {

254

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

258 AnyErrorParams = true;

259 break;

260 }

261 }

262 }

263

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

265 if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {

267 AnyErrorParams = true;

268 break;

269 }

270 }

271 }

272 }

273

274 if (!AnyErrorParams) {

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

276 diag::err_swift_async_error_no_error_parameter)

277 << ErrorAttr << isa(D);

278 return;

279 }

280 break;

281 }

282 case SwiftAsyncErrorAttr::None:

283 break;

284 }

285}

286

289 SwiftAsyncErrorAttr::ConventionKind ConvKind;

290 if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(),

291 ConvKind)) {

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

293 << AL << IDLoc->Ident;

294 return;

295 }

296

298 switch (ConvKind) {

299 case SwiftAsyncErrorAttr::ZeroArgument:

300 case SwiftAsyncErrorAttr::NonZeroArgument: {

302 return;

303

306 return;

307 break;

308 }

309 case SwiftAsyncErrorAttr::NonNullError:

310 case SwiftAsyncErrorAttr::None: {

312 return;

313 break;

314 }

315 }

316

319 D->addAttr(ErrorAttr);

320

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

323}

324

325

326

327

328

329

330

331

332

335 unsigned &SwiftParamCount,

336 bool &IsSingleParamInit) {

337 SwiftParamCount = 0;

338 IsSingleParamInit = false;

339

340

341 bool IsGetter = false, IsSetter = false;

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

343 IsGetter = true;

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

345 IsSetter = true;

346

347 if (Name.back() != ')') {

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

349 return false;

350 }

351

352 bool IsMember = false;

353 StringRef ContextName, BaseName, Parameters;

354

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

356

357

358

359 std::tie(ContextName, BaseName) = BaseName.split('.');

360 if (BaseName.empty()) {

361 BaseName = ContextName;

362 ContextName = StringRef();

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

365 << AL << 1;

366 return false;

367 } else {

368 IsMember = true;

369 }

370

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

373 << AL << 0;

374 return false;

375 }

376

377 bool IsSubscript = BaseName == "subscript";

378

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

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

381 << AL << 0;

382 return false;

383 }

384

385 if (Parameters.empty()) {

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

387 return false;

388 }

389

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

391 Parameters = Parameters.drop_back();

392

393 if (Parameters.empty()) {

394

395 if (IsSubscript) {

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

397 << AL << 1;

398 return false;

399 }

400

401 if (IsSetter) {

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

403 return false;

404 }

405

406 return true;

407 }

408

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

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

411 return false;

412 }

413

414 StringRef CurrentParam;

415 std::optional SelfLocation;

416 unsigned NewValueCount = 0;

417 std::optional NewValueLocation;

418 do {

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

420

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

423 << AL << 2;

424 return false;

425 }

426

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

428

429

430

431 if (SelfLocation) {

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

433 return false;

434 }

435

436

437 SelfLocation = SwiftParamCount;

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

439

440

441

442

443 ++NewValueCount;

444

445 NewValueLocation = SwiftParamCount;

446 }

447

448 ++SwiftParamCount;

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

450

451

452 if (IsSubscript && !SelfLocation) {

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

454 << AL << 2;

455 return false;

456 }

457

458 IsSingleParamInit =

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

460

461

462 if (IsGetter || IsSetter) {

463

464 unsigned NumExpectedParams = IsGetter ? 0 : 1;

465 unsigned ParamDiag = IsGetter

466 ? diag::warn_attr_swift_name_getter_parameters

467 : diag::warn_attr_swift_name_setter_parameters;

468

469

470 if (SelfLocation)

471 ++NumExpectedParams;

472

473

474

475 if (IsSubscript) {

476 if (SwiftParamCount < NumExpectedParams) {

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

478 return false;

479 }

480

481

482

483 if (IsSetter) {

484 if (!NewValueLocation) {

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

486 << AL;

487 return false;

488 }

489 if (NewValueCount > 1) {

491 diag::warn_attr_swift_name_subscript_setter_multiple_newValues)

492 << AL;

493 return false;

494 }

495 } else {

496

497 if (NewValueLocation) {

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

499 << AL;

500 return false;

501 }

502 }

503 } else {

504

505 if (SwiftParamCount != NumExpectedParams) {

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

507 return false;

508 }

509 }

510 }

511

512 return true;

513}

514

516 const ParsedAttr &AL, bool IsAsync) {

517 if (isa(D) || isa(D)) {

519 unsigned ParamCount;

520

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

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

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

524 } else {

525 const auto *F = cast(D);

526

527 ParamCount = F->getNumParams();

528 Params = F->parameters();

529

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

531 Diag(Loc, diag::warn_attribute_wrong_decl_type)

534 return false;

535 }

536 }

537

538

539 if (IsAsync) {

540 if (ParamCount == 0) {

541 Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)

542 << AL << isa(D);

543 return false;

544 }

545 ParamCount -= 1;

546 }

547

548 unsigned SwiftParamCount;

549 bool IsSingleParamInit;

551 IsSingleParamInit))

552 return false;

553

554 bool ParamCountValid;

555 if (SwiftParamCount == ParamCount) {

556 ParamCountValid = true;

557 } else if (SwiftParamCount > ParamCount) {

558 ParamCountValid = IsSingleParamInit && ParamCount == 0;

559 } else {

560

561

562

563 unsigned MaybeOutParamCount =

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

568 return false;

569 });

570

571 ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;

572 }

573

574 if (!ParamCountValid) {

575 Diag(Loc, diag::warn_attr_swift_name_num_params)

576 << (SwiftParamCount > ParamCount) << AL << ParamCount

577 << SwiftParamCount;

578 return false;

579 }

580 } else if ((isa(D) || isa(D) ||

581 isa(D) || isa(D) ||

582 isa(D) || isa(D) || isa(D) ||

583 isa(D) || isa(D)) &&

584 !IsAsync) {

585 StringRef ContextName, BaseName;

586

587 std::tie(ContextName, BaseName) = Name.split('.');

588 if (BaseName.empty()) {

589 BaseName = ContextName;

590 ContextName = StringRef();

592 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)

593 << AL << 1;

594 return false;

595 }

596

598 Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)

599 << AL << 0;

600 return false;

601 }

602 } else {

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

604 return false;

605 }

606 return true;

607}

608

610 StringRef Name;

613 return;

614

616 return;

617

619}

620

622 StringRef Name;

625 return;

626

628 return;

629

632}

633

635

637 return;

638

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

642 return;

643 }

644

645 SwiftNewTypeAttr::NewtypeKind Kind;

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

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

649 return;

650 }

651

652 if (!isa(D)) {

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

655 return;

656 }

657

660}

661

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

666 return;

667 }

668

669 SwiftAsyncAttr::Kind Kind;

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

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

673 return;

674 }

675

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

678

680 return;

681 } else {

682

684 return;

685

688 return;

689

692 QualType CompletionBlockType = CompletionBlock->getType();

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

695 << CompletionBlock->getType();

696 return;

697 }

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

702 << CompletionBlock->getType();

703 return;

704 }

705 }

706

707 auto *AsyncAttr =

709 D->addAttr(AsyncAttr);

710

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

713}

714

719

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

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

725 existingAttr->isRegularKeywordAttribute());

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

727 return;

728 }

729 }

730

731 switch (abi) {

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

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

737

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

742 }

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

744 return;

745

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

750 }

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

752 return;

753

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

758 }

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

760 return;

761

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

766 }

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

768 return;

769 }

770 llvm_unreachable("bad parameter ABI attribute");

771}

772

773}

enum clang::sema::@1725::IndirectLocalPathEntry::EntryKind Kind

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.

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.

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.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

Base for LValueReferenceType and RValueReferenceType.

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)

Emit a diagnostic.

ASTContext & getASTContext() const

bool isCFError(RecordDecl *D)

IdentifierInfo * getNSErrorIdent()

Retrieve the identifier "NSError".

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

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

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...

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

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

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

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

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

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

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

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

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

bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)

If Expr is a valid integer constant, get the value of the integer expression and return success or fa...

bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI, unsigned AttrArgNum, const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis=false)

Check if IdxExpr is a valid parameter index for a function or instance method D.

bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)

Check if the argument E is a ASCII string literal.

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)

@ ExpectedFunctionWithProtoType

static bool isValidSwiftErrorResultType(QualType Ty)

Pointers and references to pointers in the default address space.

llvm::StringRef getParameterABISpelling(ParameterABI kind)

QualType getFunctionOrMethodResultType(const Decl *D)

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

static bool isErrorParameter(Sema &S, QualType QT)

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.

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.

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

unsigned getFunctionOrMethodNumParams(const Decl *D)

getFunctionOrMethodNumParams - Return number of function or method parameters.

@ Other

Other implicit parameter.

Wraps an identifier and optional source location for the identifier.