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