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 | const SemaBase::SemaDiagnosticBuilder & |
33 | operator<<(const SemaBase::SemaDiagnosticBuilder &Diag, |
34 | const PartialDiagnostic &PD) { |
35 | if (Diag.ImmediateDiag) |
36 | PD.Emit(DB: *Diag.ImmediateDiag); |
37 | else if (Diag.PartialDiagId) |
38 | Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD; |
39 | return Diag; |
40 | } |
41 | |
42 | void SemaBase::SemaDiagnosticBuilder::AddFixItHint( |
43 | const FixItHint &Hint) const { |
44 | if (ImmediateDiag) |
45 | ImmediateDiag->AddFixItHint(Hint); |
46 | else if (PartialDiagId) |
47 | S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint); |
48 | } |
49 | |
50 | llvm::DenseMap<CanonicalDeclPtr<const FunctionDecl>, |
51 | std::vector<PartialDiagnosticAt>> & |
52 | SemaBase::SemaDiagnosticBuilder::getDeviceDeferredDiags() const { |
53 | return S.DeviceDeferredDiags; |
54 | } |
55 | |
56 | Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc, unsigned DiagID, |
57 | bool DeferHint) { |
58 | bool IsError = |
59 | getDiagnostics().getDiagnosticIDs()->isDefaultMappingAsError(DiagID); |
60 | bool ShouldDefer = getLangOpts().CUDA && getLangOpts().GPUDeferDiag && |
61 | DiagnosticIDs::isDeferrable(DiagID) && |
62 | (DeferHint || SemaRef.DeferDiags || !IsError); |
63 | auto SetIsLastErrorImmediate = [&](bool Flag) { |
64 | if (IsError) |
65 | SemaRef.IsLastErrorImmediate = Flag; |
66 | }; |
67 | if (!ShouldDefer) { |
68 | SetIsLastErrorImmediate(true); |
69 | return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, |
70 | DiagID, SemaRef.getCurFunctionDecl(), SemaRef); |
71 | } |
72 | |
73 | SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice |
74 | ? SemaRef.CUDA().DiagIfDeviceCode(Loc, DiagID) |
75 | : SemaRef.CUDA().DiagIfHostCode(Loc, DiagID); |
76 | SetIsLastErrorImmediate(DB.isImmediate()); |
77 | return DB; |
78 | } |
79 | |
80 | Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc, |
81 | const PartialDiagnostic &PD, |
82 | bool DeferHint) { |
83 | return Diag(Loc, DiagID: PD.getDiagID(), DeferHint) << PD; |
84 | } |
85 | |
86 | } // namespace clang |
87 | |