@@ -36,9 +36,8 @@ void SymbolicValue::print(llvm::raw_ostream &os, unsigned indent) const {
36
36
os << " uninit\n " ;
37
37
return ;
38
38
case RK_Unknown: {
39
- std::pair<SILNode *, UnknownReason> unknown = getUnknownValue ();
40
- os << " unknown(" << (int )unknown.second << " ): " ;
41
- unknown.first ->dump ();
39
+ os << " unknown(" << (int )getUnknownReason () << " ): " ;
40
+ getUnknownNode ()->dump ();
42
41
return ;
43
42
}
44
43
case RK_Metatype:
@@ -485,6 +484,88 @@ ArrayRef<SymbolicValue> SymbolicValue::getAggregateValue() const {
485
484
return ArrayRef<SymbolicValue>(value.aggregate , aux.aggregate_numElements );
486
485
}
487
486
487
+ // ===----------------------------------------------------------------------===//
488
+ // Unknown
489
+ // ===----------------------------------------------------------------------===//
490
+
491
+ namespace swift {
492
+ // / When the value is Unknown, this contains information about the unfoldable
493
+ // / part of the computation.
494
+ struct alignas (SourceLoc) UnknownSymbolicValue final
495
+ : private llvm::TrailingObjects<UnknownSymbolicValue, SourceLoc> {
496
+ friend class llvm ::TrailingObjects<UnknownSymbolicValue, SourceLoc>;
497
+
498
+ // / The value that was unfoldable.
499
+ SILNode *node;
500
+
501
+ // / A more explanatory reason for the value being unknown.
502
+ UnknownReason reason;
503
+
504
+ // / The number of elements in the call stack.
505
+ unsigned call_stack_size;
506
+
507
+ static UnknownSymbolicValue *create (SILNode *node, UnknownReason reason,
508
+ ArrayRef<SourceLoc> elements,
509
+ llvm::BumpPtrAllocator &allocator) {
510
+ auto byteSize =
511
+ UnknownSymbolicValue::totalSizeToAlloc<SourceLoc>(elements.size ());
512
+ auto rawMem = allocator.Allocate (byteSize, alignof (UnknownSymbolicValue));
513
+
514
+ // Placement-new the value inside the memory we just allocated.
515
+ auto value = ::new (rawMem) UnknownSymbolicValue (
516
+ node, reason, static_cast <unsigned >(elements.size ()));
517
+ std::uninitialized_copy (elements.begin (), elements.end (),
518
+ value->getTrailingObjects <SourceLoc>());
519
+ return value;
520
+ }
521
+
522
+ ArrayRef<SourceLoc> getCallStack () const {
523
+ return {getTrailingObjects<SourceLoc>(), call_stack_size};
524
+ }
525
+
526
+ // This is used by the llvm::TrailingObjects base class.
527
+ size_t numTrailingObjects (OverloadToken<SourceLoc>) const {
528
+ return call_stack_size;
529
+ }
530
+
531
+ private:
532
+ UnknownSymbolicValue () = delete ;
533
+ UnknownSymbolicValue (const UnknownSymbolicValue &) = delete ;
534
+ UnknownSymbolicValue (SILNode *node, UnknownReason reason,
535
+ unsigned call_stack_size)
536
+ : node (node), reason (reason), call_stack_size (call_stack_size) {}
537
+ };
538
+ } // namespace swift
539
+
540
+ SymbolicValue SymbolicValue::getUnknown (SILNode *node, UnknownReason reason,
541
+ llvm::ArrayRef<SourceLoc> callStack,
542
+ llvm::BumpPtrAllocator &allocator) {
543
+ auto *rawCallStack = allocator.Allocate <SourceLoc>(callStack.size ());
544
+ std::uninitialized_copy (callStack.begin (), callStack.end (), rawCallStack);
545
+
546
+ assert (node && " node must be present" );
547
+ SymbolicValue result;
548
+ result.representationKind = RK_Unknown;
549
+ result.value .unknown =
550
+ UnknownSymbolicValue::create (node, reason, callStack, allocator);
551
+ return result;
552
+ }
553
+
554
+ ArrayRef<SourceLoc> SymbolicValue::getUnknownCallStack () const {
555
+ assert (getKind () == Unknown);
556
+ return value.unknown ->getCallStack ();
557
+ }
558
+
559
+ SILNode *SymbolicValue::getUnknownNode () const {
560
+ assert (getKind () == Unknown);
561
+ return value.unknown ->node ;
562
+ }
563
+
564
+ UnknownReason SymbolicValue::getUnknownReason () const {
565
+ assert (getKind () == Unknown);
566
+ return value.unknown ->reason ;
567
+ }
568
+
488
569
// ===----------------------------------------------------------------------===//
489
570
// Enums
490
571
// ===----------------------------------------------------------------------===//
@@ -751,16 +832,35 @@ SymbolicValue SymbolicValue::lookThroughSingleElementAggregates() const {
751
832
}
752
833
}
753
834
835
+ // / Emits an explanatory note if there is useful information to note or if there
836
+ // / is an interesting SourceLoc to point at.
837
+ // / Returns true if a diagnostic was emitted.
838
+ static bool emitNoteDiagnostic (SILInstruction *badInst, UnknownReason reason,
839
+ SILLocation fallbackLoc, std::string error) {
840
+ auto loc = skipInternalLocations (badInst->getDebugLocation ()).getLocation ();
841
+ if (loc.isNull ()) {
842
+ // If we have important clarifying information, make sure to emit it.
843
+ if (reason == UnknownReason::Default || fallbackLoc.isNull ())
844
+ return false ;
845
+ loc = fallbackLoc;
846
+ }
847
+
848
+ auto &module = badInst->getModule ();
849
+ diagnose (module .getASTContext (), loc.getSourceLoc (), diag::tf_op_misuse_note,
850
+ error)
851
+ .highlight (loc.getSourceRange ());
852
+ return true ;
853
+ }
854
+
754
855
// / Given that this is an 'Unknown' value, emit diagnostic notes providing
755
856
// / context about what the problem is.
756
857
void SymbolicValue::emitUnknownDiagnosticNotes (SILLocation fallbackLoc) {
757
- std::pair<SILNode *, UnknownReason> unknown = getUnknownValue ();
758
- auto badInst = dyn_cast<SILInstruction>(unknown.first );
858
+ auto badInst = dyn_cast<SILInstruction>(getUnknownNode ());
759
859
if (!badInst)
760
860
return ;
761
861
762
862
std::string error;
763
- switch (unknown. second ) {
863
+ switch (getUnknownReason () ) {
764
864
case UnknownReason::Default:
765
865
error = " could not fold operation" ;
766
866
break ;
@@ -779,17 +879,27 @@ void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
779
879
break ;
780
880
}
781
881
782
- auto &module = badInst->getModule ();
882
+ bool emittedFirstNote =
883
+ emitNoteDiagnostic (badInst, getUnknownReason (), fallbackLoc, error);
783
884
784
- auto loc = skipInternalLocations (badInst->getDebugLocation ()).getLocation ();
785
- if (loc.isNull ()) {
786
- // If we have important clarifying information, make sure to emit it.
787
- if (unknown.second == UnknownReason::Default || fallbackLoc.isNull ())
788
- return ;
789
- loc = fallbackLoc;
885
+ auto &module = badInst->getModule ();
886
+ auto &SM = module .getASTContext ().SourceMgr ;
887
+ unsigned originalDiagnosticLineNumber =
888
+ SM.getLineNumber (fallbackLoc.getSourceLoc ());
889
+ for (auto &sourceLoc : llvm::reverse (getUnknownCallStack ())) {
890
+ // Skip known sources.
891
+ if (!sourceLoc.isValid ())
892
+ continue ;
893
+ // Also skip notes that point to the same line as the original error, for
894
+ // example in:
895
+ // #assert(foo(bar()))
896
+ // it is not useful to get three diagnostics referring to the same line.
897
+ if (SM.getLineNumber (sourceLoc) == originalDiagnosticLineNumber)
898
+ continue ;
899
+
900
+ auto diag = emittedFirstNote ? diag::constexpr_called_from
901
+ : diag::constexpr_not_evaluable;
902
+ diagnose (module .getASTContext (), sourceLoc, diag);
903
+ emittedFirstNote = true ;
790
904
}
791
-
792
- diagnose (module .getASTContext (), loc.getSourceLoc (), diag::tf_op_misuse_note,
793
- error)
794
- .highlight (loc.getSourceRange ());
795
905
}
0 commit comments