|
55 | 55 | #include "clang/Sema/ObjCMethodList.h" |
56 | 56 | #include "clang/Sema/Ownership.h" |
57 | 57 | #include "clang/Sema/Scope.h" |
| 58 | +#include "clang/Sema/SemaBase.h" |
58 | 59 | #include "clang/Sema/SemaConcept.h" |
59 | 60 | #include "clang/Sema/TypoCorrection.h" |
60 | 61 | #include "clang/Sema/Weak.h" |
@@ -422,7 +423,7 @@ enum class TemplateDeductionResult { |
422 | 423 |
|
423 | 424 | /// Sema - This implements semantic analysis and AST building for C. |
424 | 425 | /// \nosubgrouping |
425 | | -class Sema final { |
| 426 | +class Sema final : public SemaBase { |
426 | 427 | // Table of Contents |
427 | 428 | // ----------------- |
428 | 429 | // 1. Semantic Analysis (Sema.cpp) |
@@ -512,195 +513,6 @@ class Sema final { |
512 | 513 | /// |
513 | 514 | void addExternalSource(ExternalSemaSource *E); |
514 | 515 |
|
515 | | - /// Helper class that creates diagnostics with optional |
516 | | - /// template instantiation stacks. |
517 | | - /// |
518 | | - /// This class provides a wrapper around the basic DiagnosticBuilder |
519 | | - /// class that emits diagnostics. ImmediateDiagBuilder is |
520 | | - /// responsible for emitting the diagnostic (as DiagnosticBuilder |
521 | | - /// does) and, if the diagnostic comes from inside a template |
522 | | - /// instantiation, printing the template instantiation stack as |
523 | | - /// well. |
524 | | - class ImmediateDiagBuilder : public DiagnosticBuilder { |
525 | | - Sema &SemaRef; |
526 | | - unsigned DiagID; |
527 | | - |
528 | | - public: |
529 | | - ImmediateDiagBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID) |
530 | | - : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {} |
531 | | - ImmediateDiagBuilder(DiagnosticBuilder &&DB, Sema &SemaRef, unsigned DiagID) |
532 | | - : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {} |
533 | | - |
534 | | - // This is a cunning lie. DiagnosticBuilder actually performs move |
535 | | - // construction in its copy constructor (but due to varied uses, it's not |
536 | | - // possible to conveniently express this as actual move construction). So |
537 | | - // the default copy ctor here is fine, because the base class disables the |
538 | | - // source anyway, so the user-defined ~ImmediateDiagBuilder is a safe no-op |
539 | | - // in that case anwyay. |
540 | | - ImmediateDiagBuilder(const ImmediateDiagBuilder &) = default; |
541 | | - |
542 | | - ~ImmediateDiagBuilder() { |
543 | | - // If we aren't active, there is nothing to do. |
544 | | - if (!isActive()) |
545 | | - return; |
546 | | - |
547 | | - // Otherwise, we need to emit the diagnostic. First clear the diagnostic |
548 | | - // builder itself so it won't emit the diagnostic in its own destructor. |
549 | | - // |
550 | | - // This seems wasteful, in that as written the DiagnosticBuilder dtor will |
551 | | - // do its own needless checks to see if the diagnostic needs to be |
552 | | - // emitted. However, because we take care to ensure that the builder |
553 | | - // objects never escape, a sufficiently smart compiler will be able to |
554 | | - // eliminate that code. |
555 | | - Clear(); |
556 | | - |
557 | | - // Dispatch to Sema to emit the diagnostic. |
558 | | - SemaRef.EmitCurrentDiagnostic(DiagID); |
559 | | - } |
560 | | - |
561 | | - /// Teach operator<< to produce an object of the correct type. |
562 | | - template <typename T> |
563 | | - friend const ImmediateDiagBuilder & |
564 | | - operator<<(const ImmediateDiagBuilder &Diag, const T &Value) { |
565 | | - const DiagnosticBuilder &BaseDiag = Diag; |
566 | | - BaseDiag << Value; |
567 | | - return Diag; |
568 | | - } |
569 | | - |
570 | | - // It is necessary to limit this to rvalue reference to avoid calling this |
571 | | - // function with a bitfield lvalue argument since non-const reference to |
572 | | - // bitfield is not allowed. |
573 | | - template <typename T, |
574 | | - typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>> |
575 | | - const ImmediateDiagBuilder &operator<<(T &&V) const { |
576 | | - const DiagnosticBuilder &BaseDiag = *this; |
577 | | - BaseDiag << std::move(V); |
578 | | - return *this; |
579 | | - } |
580 | | - }; |
581 | | - |
582 | | - /// A generic diagnostic builder for errors which may or may not be deferred. |
583 | | - /// |
584 | | - /// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch) |
585 | | - /// which are not allowed to appear inside __device__ functions and are |
586 | | - /// allowed to appear in __host__ __device__ functions only if the host+device |
587 | | - /// function is never codegen'ed. |
588 | | - /// |
589 | | - /// To handle this, we use the notion of "deferred diagnostics", where we |
590 | | - /// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed. |
591 | | - /// |
592 | | - /// This class lets you emit either a regular diagnostic, a deferred |
593 | | - /// diagnostic, or no diagnostic at all, according to an argument you pass to |
594 | | - /// its constructor, thus simplifying the process of creating these "maybe |
595 | | - /// deferred" diagnostics. |
596 | | - class SemaDiagnosticBuilder { |
597 | | - public: |
598 | | - enum Kind { |
599 | | - /// Emit no diagnostics. |
600 | | - K_Nop, |
601 | | - /// Emit the diagnostic immediately (i.e., behave like Sema::Diag()). |
602 | | - K_Immediate, |
603 | | - /// Emit the diagnostic immediately, and, if it's a warning or error, also |
604 | | - /// emit a call stack showing how this function can be reached by an a |
605 | | - /// priori known-emitted function. |
606 | | - K_ImmediateWithCallStack, |
607 | | - /// Create a deferred diagnostic, which is emitted only if the function |
608 | | - /// it's attached to is codegen'ed. Also emit a call stack as with |
609 | | - /// K_ImmediateWithCallStack. |
610 | | - K_Deferred |
611 | | - }; |
612 | | - |
613 | | - SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID, |
614 | | - const FunctionDecl *Fn, Sema &S); |
615 | | - SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D); |
616 | | - SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default; |
617 | | - |
618 | | - // The copy and move assignment operator is defined as deleted pending |
619 | | - // further motivation. |
620 | | - SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete; |
621 | | - SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete; |
622 | | - |
623 | | - ~SemaDiagnosticBuilder(); |
624 | | - |
625 | | - bool isImmediate() const { return ImmediateDiag.has_value(); } |
626 | | - |
627 | | - /// Convertible to bool: True if we immediately emitted an error, false if |
628 | | - /// we didn't emit an error or we created a deferred error. |
629 | | - /// |
630 | | - /// Example usage: |
631 | | - /// |
632 | | - /// if (SemaDiagnosticBuilder(...) << foo << bar) |
633 | | - /// return ExprError(); |
634 | | - /// |
635 | | - /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably |
636 | | - /// want to use these instead of creating a SemaDiagnosticBuilder yourself. |
637 | | - operator bool() const { return isImmediate(); } |
638 | | - |
639 | | - template <typename T> |
640 | | - friend const SemaDiagnosticBuilder & |
641 | | - operator<<(const SemaDiagnosticBuilder &Diag, const T &Value) { |
642 | | - if (Diag.ImmediateDiag) |
643 | | - *Diag.ImmediateDiag << Value; |
644 | | - else if (Diag.PartialDiagId) |
645 | | - Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second |
646 | | - << Value; |
647 | | - return Diag; |
648 | | - } |
649 | | - |
650 | | - // It is necessary to limit this to rvalue reference to avoid calling this |
651 | | - // function with a bitfield lvalue argument since non-const reference to |
652 | | - // bitfield is not allowed. |
653 | | - template <typename T, |
654 | | - typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>> |
655 | | - const SemaDiagnosticBuilder &operator<<(T &&V) const { |
656 | | - if (ImmediateDiag) |
657 | | - *ImmediateDiag << std::move(V); |
658 | | - else if (PartialDiagId) |
659 | | - S.DeviceDeferredDiags[Fn][*PartialDiagId].second << std::move(V); |
660 | | - return *this; |
661 | | - } |
662 | | - |
663 | | - friend const SemaDiagnosticBuilder & |
664 | | - operator<<(const SemaDiagnosticBuilder &Diag, const PartialDiagnostic &PD) { |
665 | | - if (Diag.ImmediateDiag) |
666 | | - PD.Emit(*Diag.ImmediateDiag); |
667 | | - else if (Diag.PartialDiagId) |
668 | | - Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD; |
669 | | - return Diag; |
670 | | - } |
671 | | - |
672 | | - void AddFixItHint(const FixItHint &Hint) const { |
673 | | - if (ImmediateDiag) |
674 | | - ImmediateDiag->AddFixItHint(Hint); |
675 | | - else if (PartialDiagId) |
676 | | - S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint); |
677 | | - } |
678 | | - |
679 | | - friend ExprResult ExprError(const SemaDiagnosticBuilder &) { |
680 | | - return ExprError(); |
681 | | - } |
682 | | - friend StmtResult StmtError(const SemaDiagnosticBuilder &) { |
683 | | - return StmtError(); |
684 | | - } |
685 | | - operator ExprResult() const { return ExprError(); } |
686 | | - operator StmtResult() const { return StmtError(); } |
687 | | - operator TypeResult() const { return TypeError(); } |
688 | | - operator DeclResult() const { return DeclResult(true); } |
689 | | - operator MemInitResult() const { return MemInitResult(true); } |
690 | | - |
691 | | - private: |
692 | | - Sema &S; |
693 | | - SourceLocation Loc; |
694 | | - unsigned DiagID; |
695 | | - const FunctionDecl *Fn; |
696 | | - bool ShowCallStack; |
697 | | - |
698 | | - // Invariant: At most one of these Optionals has a value. |
699 | | - // FIXME: Switch these to a Variant once that exists. |
700 | | - std::optional<ImmediateDiagBuilder> ImmediateDiag; |
701 | | - std::optional<unsigned> PartialDiagId; |
702 | | - }; |
703 | | - |
704 | 516 | void PrintStats() const; |
705 | 517 |
|
706 | 518 | /// Warn that the stack is nearly exhausted. |
@@ -742,14 +554,6 @@ class Sema final { |
742 | 554 |
|
743 | 555 | void addImplicitTypedef(StringRef Name, QualType T); |
744 | 556 |
|
745 | | - /// Emit a diagnostic. |
746 | | - SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, |
747 | | - bool DeferHint = false); |
748 | | - |
749 | | - /// Emit a partial diagnostic. |
750 | | - SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD, |
751 | | - bool DeferHint = false); |
752 | | - |
753 | 557 | /// Whether uncompilable error has occurred. This includes error happens |
754 | 558 | /// in deferred diagnostics. |
755 | 559 | bool hasUncompilableErrorOccurred() const; |
@@ -13115,9 +12919,7 @@ class Sema final { |
13115 | 12919 | /// Diagnostics that are emitted only if we discover that the given function |
13116 | 12920 | /// must be codegen'ed. Because handling these correctly adds overhead to |
13117 | 12921 | /// compilation, this is currently only enabled for CUDA compilations. |
13118 | | - llvm::DenseMap<CanonicalDeclPtr<const FunctionDecl>, |
13119 | | - std::vector<PartialDiagnosticAt>> |
13120 | | - DeviceDeferredDiags; |
| 12922 | + SemaDiagnosticBuilder::DeferredDiagnosticsType DeviceDeferredDiags; |
13121 | 12923 |
|
13122 | 12924 | /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the |
13123 | 12925 | /// key in a hashtable, both the FD and location are hashed. |
|
0 commit comments