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