|
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;
|
@@ -13119,9 +12923,7 @@ class Sema final {
|
13119 | 12923 | /// Diagnostics that are emitted only if we discover that the given function
|
13120 | 12924 | /// must be codegen'ed. Because handling these correctly adds overhead to
|
13121 | 12925 | /// compilation, this is currently only enabled for CUDA compilations.
|
13122 |
| - llvm::DenseMap<CanonicalDeclPtr<const FunctionDecl>, |
13123 |
| - std::vector<PartialDiagnosticAt>> |
13124 |
| - DeviceDeferredDiags; |
| 12926 | + SemaDiagnosticBuilder::DeferredDiagnosticsType DeviceDeferredDiags; |
13125 | 12927 |
|
13126 | 12928 | /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the
|
13127 | 12929 | /// key in a hashtable, both the FD and location are hashed.
|
|
0 commit comments