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