xref: /llvm-project/clang/lib/Sema/SemaBase.cpp (revision d2884444472e92a8282f4d215a27128ac83a26b9)
1 #include "clang/Sema/SemaBase.h"
2 #include "clang/Sema/Sema.h"
3 
4 namespace clang {
5 
6 SemaBase::SemaBase(Sema &S) : SemaRef(S) {}
7 
8 ASTContext &SemaBase::getASTContext() const { return SemaRef.Context; }
9 DiagnosticsEngine &SemaBase::getDiagnostics() const { return SemaRef.Diags; }
10 const LangOptions &SemaBase::getLangOpts() const { return SemaRef.LangOpts; }
11 
12 SemaBase::ImmediateDiagBuilder::~ImmediateDiagBuilder() {
13   // If we aren't active, there is nothing to do.
14   if (!isActive())
15     return;
16 
17   // Otherwise, we need to emit the diagnostic. First clear the diagnostic
18   // builder itself so it won't emit the diagnostic in its own destructor.
19   //
20   // This seems wasteful, in that as written the DiagnosticBuilder dtor will
21   // do its own needless checks to see if the diagnostic needs to be
22   // emitted. However, because we take care to ensure that the builder
23   // objects never escape, a sufficiently smart compiler will be able to
24   // eliminate that code.
25   Clear();
26 
27   // Dispatch to Sema to emit the diagnostic.
28   SemaRef.EmitCurrentDiagnostic(DiagID);
29 }
30 
31 const SemaBase::SemaDiagnosticBuilder &
32 operator<<(const SemaBase::SemaDiagnosticBuilder &Diag,
33            const PartialDiagnostic &PD) {
34   if (Diag.ImmediateDiag)
35     PD.Emit(*Diag.ImmediateDiag);
36   else if (Diag.PartialDiagId)
37     Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD;
38   return Diag;
39 }
40 
41 void SemaBase::SemaDiagnosticBuilder::AddFixItHint(
42     const FixItHint &Hint) const {
43   if (ImmediateDiag)
44     ImmediateDiag->AddFixItHint(Hint);
45   else if (PartialDiagId)
46     S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint);
47 }
48 
49 llvm::DenseMap<CanonicalDeclPtr<const FunctionDecl>,
50                std::vector<PartialDiagnosticAt>> &
51 SemaBase::SemaDiagnosticBuilder::getDeviceDeferredDiags() const {
52   return S.DeviceDeferredDiags;
53 }
54 
55 Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc, unsigned DiagID,
56                                            bool DeferHint) {
57   bool IsError =
58       getDiagnostics().getDiagnosticIDs()->isDefaultMappingAsError(DiagID);
59   bool ShouldDefer = getLangOpts().CUDA && getLangOpts().GPUDeferDiag &&
60                      DiagnosticIDs::isDeferrable(DiagID) &&
61                      (DeferHint || SemaRef.DeferDiags || !IsError);
62   auto SetIsLastErrorImmediate = [&](bool Flag) {
63     if (IsError)
64       SemaRef.IsLastErrorImmediate = Flag;
65   };
66   if (!ShouldDefer) {
67     SetIsLastErrorImmediate(true);
68     return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc,
69                                  DiagID, SemaRef.getCurFunctionDecl(), SemaRef);
70   }
71 
72   SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice
73                                  ? SemaRef.CUDADiagIfDeviceCode(Loc, DiagID)
74                                  : SemaRef.CUDADiagIfHostCode(Loc, DiagID);
75   SetIsLastErrorImmediate(DB.isImmediate());
76   return DB;
77 }
78 
79 Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc,
80                                            const PartialDiagnostic &PD,
81                                            bool DeferHint) {
82   return Diag(Loc, PD.getDiagID(), DeferHint) << PD;
83 }
84 
85 } // namespace clang
86