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