@@ -475,3 +475,78 @@ void ExpandChildTypeRefinementContextsRequest::cacheResult(
475
475
TRC->Children = children;
476
476
TRC->setNeedsExpansion (false );
477
477
}
478
+
479
+ // / Emit an error message, dump each context with its corresponding label, and
480
+ // / abort.
481
+ static void
482
+ verificationError (ASTContext &ctx, llvm::StringRef msg,
483
+ std::initializer_list<
484
+ std::pair<const char *, const TypeRefinementContext *>>
485
+ labelsAndNodes) {
486
+ llvm::errs () << msg << " \n " ;
487
+ for (auto pair : labelsAndNodes) {
488
+ auto label = std::get<0 >(pair);
489
+ auto context = std::get<1 >(pair);
490
+ llvm::errs () << label << " :\n " ;
491
+ context->print (llvm::errs (), ctx.SourceMgr );
492
+ }
493
+ abort ();
494
+ }
495
+
496
+ void TypeRefinementContext::verify (const TypeRefinementContext *parent,
497
+ ASTContext &ctx) const {
498
+ // Verify the children first.
499
+ for (auto child : Children) {
500
+ child->verify (this , ctx);
501
+ }
502
+
503
+ // Verify that the children are in sorted order and that their source ranges
504
+ // do not overlap.
505
+ auto &srcMgr = ctx.SourceMgr ;
506
+ if (Children.size () > 1 ) {
507
+ auto const *previous = Children.front ();
508
+ for (auto const *current : ArrayRef (Children).drop_front ()) {
509
+ if (!srcMgr.isAtOrBefore (previous->getSourceRange ().Start ,
510
+ current->getSourceRange ().Start ))
511
+ verificationError (
512
+ ctx, " out of order children" ,
513
+ {{" child 1" , previous}, {" child 2" , current}, {" parent" , this }});
514
+
515
+ if (srcMgr.containsLoc (previous->getSourceRange (),
516
+ current->getSourceRange ().Start ))
517
+ verificationError (
518
+ ctx, " overlapping children" ,
519
+ {{" child 1" , previous}, {" child 2" , current}, {" parent" , this }});
520
+
521
+ previous = current;
522
+ }
523
+ }
524
+
525
+ // Only root nodes are allowed to have no parent.
526
+ if (!parent) {
527
+ if (getReason () != Reason::Root)
528
+ verificationError (ctx, " interior node without parent" , {{" node" , this }});
529
+ return ;
530
+ }
531
+
532
+ // All nodes with a parent must have a valid source range.
533
+ if (!SrcRange.isValid ())
534
+ verificationError (ctx, " invalid source range" , {{" node" , this }});
535
+
536
+ if (getReason () != Reason::Root) {
537
+ auto parentRange = parent->SrcRange ;
538
+ if (parentRange.isValid () &&
539
+ !(srcMgr.isAtOrBefore (parentRange.Start , SrcRange.Start ) &&
540
+ srcMgr.isAtOrBefore (SrcRange.End , parentRange.End )))
541
+ verificationError (ctx, " child source range not contained" ,
542
+ {{" child" , this }, {" parent" , this }});
543
+ }
544
+
545
+ if (!AvailabilityInfo.isContainedIn (parent->AvailabilityInfo ))
546
+ verificationError (ctx, " child availability range not contained" ,
547
+ {{" child" , this }, {" parent" , this }});
548
+ }
549
+
550
+ void TypeRefinementContext::verify (ASTContext &ctx) {
551
+ verify (nullptr , ctx);
552
+ }
0 commit comments