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 | DeclContext *SemaBase::getCurContext() const { return SemaRef.CurContext; } |
13 | |
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, DB: *this); |
31 | } |
32 | |
33 | PartialDiagnostic SemaBase::PDiag(unsigned DiagID) { |
34 | return PartialDiagnostic(DiagID, SemaRef.Context.getDiagAllocator()); |
35 | } |
36 | |
37 | const SemaBase::SemaDiagnosticBuilder & |
38 | operator<<(const SemaBase::SemaDiagnosticBuilder &Diag, |
39 | const PartialDiagnostic &PD) { |
40 | if (Diag.ImmediateDiag) |
41 | PD.Emit(DB: *Diag.ImmediateDiag); |
42 | else if (Diag.PartialDiagId) |
43 | Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD; |
44 | return Diag; |
45 | } |
46 | |
47 | 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>> & |
57 | SemaBase::SemaDiagnosticBuilder::getDeviceDeferredDiags() const { |
58 | return S.DeviceDeferredDiags; |
59 | } |
60 | |
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 | |
85 | Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc, |
86 | const PartialDiagnostic &PD, |
87 | bool DeferHint) { |
88 | return Diag(Loc, DiagID: PD.getDiagID(), DeferHint) << PD; |
89 | } |
90 | |
91 | SemaBase::SemaDiagnosticBuilder SemaBase::DiagCompat(SourceLocation Loc, |
92 | unsigned CompatDiagId, |
93 | bool DeferHint) { |
94 | return Diag(Loc, |
95 | DiagID: DiagnosticIDs::getCXXCompatDiagId(LangOpts: getLangOpts(), CompatDiagId), |
96 | DeferHint); |
97 | } |
98 | } // namespace clang |
99 | |