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