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(DB: *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, DiagID: PD.getDiagID(), DeferHint) << PD; |
88 | } |
89 | |
90 | } // namespace clang |
91 | |