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