@@ -4408,63 +4408,67 @@ const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
4408
4408
// /
4409
4409
// / Where `r` refers to the value returned by the function
4410
4410
class ResultNameDecl : public ValueDecl {
4411
-
4411
+ friend class ContractSpecifierDecl ;
4412
4412
// / The canonical declaration of a result name is the result name declared in
4413
4413
// / the first post condition (with a result name) on a particular function.
4414
4414
// /
4415
4415
// / The canonical decl is used as the key for the value of the return value
4416
4416
// / during codegen and constant evaluation. This is necessary because the
4417
4417
// / changes to the return value in the post conditions must be visible to
4418
4418
// / subsequent post conditions.
4419
- ResultNameDecl *CanonicalResultNameDecl = nullptr ;
4419
+ // /
4420
+ // FIXME(EricWF): Remove this? I think we can dig the canonical result name
4421
+ // out of the decl context? But I think that will be rather bug prone. Maybe
4422
+ // we could make the ContractSpecifierDecl a DeclContext and dig it up from
4423
+ // there?
4424
+ ResultNameDecl *CanonicalResultName = nullptr ;
4425
+
4426
+ // / Whether this result name is using a dummy placeholder type to represent
4427
+ // / the deduced return type of a non-template function until the actual return
4428
+ // / type is known.
4429
+ // /
4430
+ // / Result names are only allowed on non-template functions with deduced
4431
+ // / return types if that function declaration is also a definition.
4420
4432
bool HasInventedPlaceholderType = false ;
4421
4433
4422
4434
ResultNameDecl (DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id,
4423
- QualType T, ResultNameDecl *CanonicalResultNameDecl = nullptr ,
4435
+ QualType T, ResultNameDecl *CanonicalDecl = nullptr ,
4424
4436
bool HasInventedPlaceholderType = false )
4425
4437
: ValueDecl(Decl::ResultName, DC, IdLoc, Id, T),
4426
- CanonicalResultNameDecl (CanonicalResultNameDecl),
4427
- HasInventedPlaceholderType(HasInventedPlaceholderType) {
4428
- assert (!CanonicalResultNameDecl ||
4429
- CanonicalResultNameDecl->CanonicalResultNameDecl == nullptr );
4430
- assert (!CanonicalResultNameDecl || CanonicalResultNameDecl->getType () == T);
4438
+ HasInventedPlaceholderType (HasInventedPlaceholderType) {}
4439
+
4440
+ void setCanonicalResultName (ResultNameDecl *CRND) {
4441
+ assert (CRND != this &&
4442
+ " setCanonicalResultName called on the canonical result" );
4443
+ this ->CanonicalResultName = CRND;
4431
4444
}
4432
4445
4433
4446
void anchor () override ;
4434
4447
4435
4448
public:
4436
4449
friend class ASTDeclReader ;
4437
4450
4438
- static ResultNameDecl *
4439
- Create (ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
4440
- IdentifierInfo *Id, QualType T,
4441
- ResultNameDecl *CanonicalResultNameDecl = nullptr ,
4442
- bool HasInventedPlaceholderType = false );
4451
+ static ResultNameDecl *Create (ASTContext &C, DeclContext *DC,
4452
+ SourceLocation IdLoc, IdentifierInfo *Id,
4453
+ QualType T, ResultNameDecl *CRND = nullptr ,
4454
+ bool HasInventedPlaceholderType = false );
4443
4455
static ResultNameDecl *CreateDeserialized (ASTContext &C, GlobalDeclID ID);
4444
4456
4445
4457
using ValueDecl::getDeclName;
4446
4458
using ValueDecl::setType;
4447
4459
4448
- void setCanonicalResultNameDecl (ResultNameDecl *D) {
4449
- CanonicalResultNameDecl = D;
4450
- }
4451
-
4452
4460
// / Returns true if this declaration is the canonical result name declaration
4453
4461
// / (This is true if it doesn't reference another result name).
4454
- bool isCanonicalResultNameDecl () const {
4455
- return CanonicalResultNameDecl == nullptr ;
4462
+ bool isCanonicalResultName () const {
4463
+ return getCanonicalResultName () == this ;
4456
4464
}
4457
4465
4458
- ResultNameDecl *getCanonicalResultNameDecl () {
4459
- if (CanonicalResultNameDecl)
4460
- return CanonicalResultNameDecl;
4461
- return this ;
4466
+ ResultNameDecl *getCanonicalResultName () {
4467
+ return CanonicalResultName ? CanonicalResultName : this ;
4462
4468
}
4463
4469
4464
- const ResultNameDecl *getCanonicalResultNameDecl () const {
4465
- if (CanonicalResultNameDecl)
4466
- return CanonicalResultNameDecl;
4467
- return this ;
4470
+ const ResultNameDecl *getCanonicalResultName () const {
4471
+ return CanonicalResultName ? CanonicalResultName : this ;
4468
4472
}
4469
4473
4470
4474
bool hasInventedPlaceholderType () const { return HasInventedPlaceholderType; }
@@ -4473,13 +4477,20 @@ class ResultNameDecl : public ValueDecl {
4473
4477
static bool classofKind (Kind K) { return K == Decl::ResultName; }
4474
4478
};
4475
4479
4476
- // / Represents a C++11 static_assert declaration.
4480
+ // / Represents a series of contracts on a function declaration.
4481
+ // / For instance:
4482
+ // /
4483
+ // / int foo(const int x) pre(x) post(r : x < r);
4484
+ // /
4485
+ // / This declaration also stores whether any of the contracts are invalid.
4477
4486
class ContractSpecifierDecl final
4478
4487
: public Decl,
4479
4488
private llvm::TrailingObjects<ContractSpecifierDecl, ContractStmt *> {
4489
+ friend class TrailingObjects ;
4480
4490
friend class ASTDeclReader ;
4481
4491
friend class ASTDeclWriter ;
4482
4492
4493
+ // / The number of contracts in this sequence.
4483
4494
unsigned NumContracts;
4484
4495
4485
4496
static bool IsPreconditionPred (const ContractStmt *);
@@ -4496,65 +4507,64 @@ class ContractSpecifierDecl final
4496
4507
ContractSpecifierDecl (DeclContext *DC, SourceLocation Loc,
4497
4508
ArrayRef<ContractStmt *> Contracts, bool IsInvalid);
4498
4509
4499
- void setContracts (ArrayRef<ContractStmt *> Contracts) {
4500
- assert (*getTrailingObjects<ContractStmt *>() == nullptr );
4501
- std::copy (Contracts.begin (), Contracts.end (),
4502
- getTrailingObjects<ContractStmt *>());
4503
- }
4510
+ void setContracts (ArrayRef<ContractStmt *> Contracts);
4504
4511
4505
4512
using FilterRangeT = llvm::iterator_range<llvm::filter_iterator<
4506
4513
ArrayRef<ContractStmt *>::iterator, bool (*)(const ContractStmt *)>>;
4507
4514
4508
4515
virtual void anchor ();
4509
4516
4510
4517
public:
4511
- friend class TrailingObjects ;
4512
-
4513
- using PreconditionRangeT = FilterRangeT;
4514
- using PostconditionRangeT = FilterRangeT;
4518
+ static ContractSpecifierDecl *Create (ASTContext &C, DeclContext *DC,
4519
+ SourceLocation Loc,
4520
+ ArrayRef<ContractStmt *> Contracts,
4521
+ bool IsInvalid);
4522
+ static ContractSpecifierDecl *
4523
+ CreateDeserialized (ASTContext &C, GlobalDeclID ID, unsigned NumContracts);
4515
4524
4525
+ public:
4516
4526
ArrayRef<ContractStmt *> contracts () const {
4517
4527
return llvm::ArrayRef (getTrailingObjects<ContractStmt *>(), NumContracts);
4518
4528
}
4519
4529
4530
+ // / Returns a range representing the preconditions in this contract sequence
4531
+ // / (in order of declaration)
4520
4532
auto preconditions () const {
4521
4533
return llvm::make_filter_range (contracts (), IsPreconditionPred);
4522
4534
}
4523
4535
4536
+ // / Returns a range representing the postconditions in this contract sequence
4537
+ // / (in order of declaration).
4524
4538
auto postconditions () const {
4525
4539
return llvm::make_filter_range (contracts (), IsPostconditionPred);
4526
4540
}
4527
4541
4542
+ // / Returns a range representing the result names in this contract sequence
4543
+ // / (in order of declaration).
4528
4544
auto result_names () const {
4529
4545
return llvm::make_filter_range (
4530
4546
llvm::map_range (postconditions (), ExtractResultName),
4531
4547
[](ResultNameDecl *R) { return R != nullptr ; });
4532
4548
}
4533
4549
4550
+ // / Returns true if this function contract sequence contains result names &
4551
+ // / those result names use an invented placeholder type to allow us to delay
4552
+ // / the deduction of the return type.
4534
4553
bool hasInventedPlaceholdersTypes () const ;
4535
4554
4536
4555
unsigned getNumContracts () const { return NumContracts; }
4537
- unsigned getNumPreconditions () const {
4538
- return std::distance (preconditions ().begin (), preconditions ().end ());
4539
- }
4540
-
4541
- unsigned getNumPostconditions () const {
4542
- return std::distance (postconditions ().begin (), postconditions ().end ());
4543
- }
4544
4556
4557
+ // / True if and only if there is a postcondition with a result name in this
4558
+ // / contract sequence.
4545
4559
bool hasCanonicalResultName () const ;
4546
- ResultNameDecl *getCanonicalResultName () const ;
4547
4560
4548
- SourceRange getSourceRange () const override LLVM_READONLY;
4561
+ // / Returns the canonical result name for this contract sequence.
4562
+ const ResultNameDecl *getCanonicalResultName () const ;
4549
4563
4550
- friend class ASTDeclReader ;
4564
+ // / Update the declaration context of this contract sequence and of any result name declarations contained within it.
4565
+ void setOwningFunction (DeclContext *FD);
4551
4566
4552
- static ContractSpecifierDecl *Create (ASTContext &C, DeclContext *DC,
4553
- SourceLocation Loc,
4554
- ArrayRef<ContractStmt *> Contracts,
4555
- bool IsInvalid);
4556
- static ContractSpecifierDecl *
4557
- CreateDeserialized (ASTContext &C, GlobalDeclID ID, unsigned NumContracts);
4567
+ SourceRange getSourceRange () const override LLVM_READONLY;
4558
4568
4559
4569
static bool classof (const Decl *D) { return classofKind (D->getKind ()); }
4560
4570
static bool classofKind (Kind K) { return K == Decl::ContractSpecifier; }
0 commit comments