// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_
#define TOOLS_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_
#include "CheckFieldsVisitor.h"
#include "CheckFinalizerVisitor.h"
#include "CheckForbiddenFieldsVisitor.h"
#include "CheckGCRootsVisitor.h"
#include "Config.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Frontend/CompilerInstance.h"
class RecordInfo;
// All error/warning reporting methods under one roof.
//
class DiagnosticsReporter {
public:
explicit DiagnosticsReporter(clang::CompilerInstance&);
bool hasErrorOccurred() const;
clang::DiagnosticsEngine::Level getErrorLevel() const;
void ClassMustLeftMostlyDeriveGC(RecordInfo* info);
void ClassRequiresTraceMethod(RecordInfo* info);
void BaseRequiresTracing(RecordInfo* derived,
clang::CXXMethodDecl* trace,
clang::CXXRecordDecl* base);
void FieldsImproperlyTraced(RecordInfo* info,
clang::CXXMethodDecl* trace);
void ClassContainsInvalidFields(
RecordInfo* info,
const CheckFieldsVisitor::Errors& errors);
void ClassContainsGCRoots(RecordInfo* info,
const CheckGCRootsVisitor::Errors& errors);
void ClassContainsGCRootRefs(RecordInfo* info,
const CheckGCRootsVisitor::Errors& errors);
void ClassContainsForbiddenFields(
RecordInfo* info,
const CheckForbiddenFieldsVisitor::Errors& errors);
void FinalizerAccessesFinalizedFields(
clang::CXXMethodDecl* dtor,
const CheckFinalizerVisitor::Errors& errors);
void ClassMustDeclareGCMixinTraceMethod(RecordInfo* info);
void OverriddenNonVirtualTrace(RecordInfo* info,
clang::CXXMethodDecl* trace,
clang::CXXMethodDecl* overridden);
void MissingTraceDispatchMethod(RecordInfo* info);
void VirtualAndManualDispatch(RecordInfo* info,
clang::CXXMethodDecl* dispatch);
void MissingTraceDispatch(const clang::FunctionDecl* dispatch,
RecordInfo* receiver);
void MissingFinalizeDispatch(const clang::FunctionDecl* dispatch,
RecordInfo* receiver);
void StackAllocatedDerivesGarbageCollected(RecordInfo* info, BasePoint* base);
void ClassOverridesNew(RecordInfo* info, clang::CXXMethodDecl* newop);
void ClassDeclaresPureVirtualTrace(RecordInfo* info,
clang::CXXMethodDecl* trace);
void LeftMostBaseMustBePolymorphic(RecordInfo* derived,
clang::CXXRecordDecl* base);
void BaseClassMustDeclareVirtualTrace(RecordInfo* derived,
clang::CXXRecordDecl* base);
void ClassMustCRTPItself(const RecordInfo* derived,
const clang::CXXRecordDecl* base,
const clang::CXXBaseSpecifier* base_spec);
void TraceMethodForStackAllocatedClass(RecordInfo* parent,
clang::CXXMethodDecl* trace);
void NoteManualDispatchMethod(clang::CXXMethodDecl* dispatch);
void NoteBaseRequiresTracing(BasePoint* base);
void NoteFieldRequiresTracing(RecordInfo* holder, clang::FieldDecl* field);
void NoteFieldShouldNotBeTraced(RecordInfo* holder, clang::FieldDecl* field);
void NotePartObjectContainsGCRoot(FieldPoint* point);
void NotePartObjectContainsGCRootRef(FieldPoint* point);
void NoteFieldContainsGCRoot(FieldPoint* point);
void NoteFieldContainsGCRootRef(FieldPoint* point);
void NoteField(FieldPoint* point, unsigned note);
void NoteField(clang::FieldDecl* field, unsigned note);
void NoteOverriddenNonVirtualTrace(clang::CXXMethodDecl* overridden);
// Used by FindBadPatterns.
void UniquePtrUsedWithGC(const clang::Expr* expr,
const clang::FunctionDecl* bad_function,
const clang::CXXRecordDecl* gc_type);
void OptionalDeclUsedWithGC(const clang::Decl* decl,
const clang::CXXRecordDecl* optional,
const clang::CXXRecordDecl* gc_type);
void OptionalNewExprUsedWithGC(const clang::Expr* expr,
const clang::CXXRecordDecl* optional,
const clang::CXXRecordDecl* gc_type);
void RawPtrOrRefDeclUsedWithGC(const clang::Decl* decl,
const clang::CXXRecordDecl* optional,
const clang::CXXRecordDecl* gc_type);
void RawPtrOrRefNewExprUsedWithGC(const clang::Expr* expr,
const clang::CXXRecordDecl* optional,
const clang::CXXRecordDecl* gc_type);
void VariantUsedWithGC(const clang::Expr* expr,
const clang::CXXRecordDecl* variant,
const clang::CXXRecordDecl* gc_type);
void CollectionOfGCed(const clang::Decl* decl,
const clang::CXXRecordDecl* collection,
const clang::CXXRecordDecl* gc_type);
void CollectionOfGCed(const clang::Expr* expr,
const clang::CXXRecordDecl* collection,
const clang::CXXRecordDecl* gc_type);
void CollectionOfMembers(const clang::Decl* decl,
const clang::CXXRecordDecl* collection,
const clang::CXXRecordDecl* gc_type);
void CollectionOfMembers(const clang::Expr* expr,
const clang::CXXRecordDecl* collection,
const clang::CXXRecordDecl* gc_type);
void MemberOnStack(const clang::VarDecl* var);
void AdditionalPadding(const clang::RecordDecl* var, size_t padding);
void WeakPtrToGCed(const clang::Decl* decl,
const clang::CXXRecordDecl* weak_ptr,
const clang::CXXRecordDecl* gc_type);
void GCedField(const clang::FieldDecl* field,
const clang::CXXRecordDecl* gctype);
void GCedVar(const clang::VarDecl* var, const clang::CXXRecordDecl* gctype);
private:
clang::DiagnosticBuilder ReportDiagnostic(
clang::SourceLocation location,
unsigned diag_id);
void ReportMissingDispatchMethod(RecordInfo* info, unsigned error);
void ReportMissingDispatch(const clang::FunctionDecl* dispatch,
RecordInfo* receiver,
unsigned error);
clang::CompilerInstance& instance_;
clang::DiagnosticsEngine& diagnostic_;
unsigned diag_class_must_left_mostly_derive_gc_;
unsigned diag_class_requires_trace_method_;
unsigned diag_base_requires_tracing_;
unsigned diag_fields_require_tracing_;
unsigned diag_fields_improperly_traced_;
unsigned diag_class_contains_invalid_fields_;
unsigned diag_class_contains_gc_root_;
unsigned diag_class_contains_gc_root_ref_;
unsigned diag_finalizer_accesses_finalized_field_;
unsigned diag_overridden_non_virtual_trace_;
unsigned diag_missing_trace_dispatch_method_;
unsigned diag_virtual_and_manual_dispatch_;
unsigned diag_missing_trace_dispatch_;
unsigned diag_missing_finalize_dispatch_;
unsigned diag_stack_allocated_derives_gc_;
unsigned diag_class_overrides_new_;
unsigned diag_class_declares_pure_virtual_trace_;
unsigned diag_left_most_base_must_be_polymorphic_;
unsigned diag_base_class_must_declare_virtual_trace_;
unsigned diag_class_must_crtp_itself_;
unsigned diag_weak_ptr_to_gc_managed_class_;
unsigned diag_gced_field_;
unsigned diag_gced_var_;
unsigned diag_base_requires_tracing_note_;
unsigned diag_field_requires_tracing_note_;
unsigned diag_field_should_not_be_traced_note_;
unsigned diag_raw_ptr_to_gc_managed_class_note_;
unsigned diag_ref_ptr_to_gc_managed_class_note_;
unsigned diag_reference_ptr_to_gc_managed_class_note_;
unsigned diag_unique_ptr_to_gc_managed_class_note_;
unsigned diag_raw_ptr_to_traceable_class_note_;
unsigned diag_ref_ptr_to_traceable_class_note_;
unsigned diag_reference_ptr_to_traceable_class_note_;
unsigned diag_unique_ptr_to_traceable_class_note_;
unsigned diag_member_to_gc_unmanaged_class_note_;
unsigned diag_stack_allocated_field_note_;
unsigned diag_member_in_unmanaged_class_note_;
unsigned diag_ptr_to_member_in_unmanaged_class_note_;
unsigned diag_part_object_to_gc_derived_class_note_;
unsigned diag_part_object_contains_gc_root_note_;
unsigned diag_part_object_contains_gc_root_ref_note_;
unsigned diag_field_contains_gc_root_note_;
unsigned diag_field_contains_gc_root_ref_note_;
unsigned diag_finalized_field_note_;
unsigned diag_overridden_non_virtual_trace_note_;
unsigned diag_manual_dispatch_method_note_;
unsigned diag_iterator_to_gc_managed_collection_note_;
unsigned diag_trace_method_of_stack_allocated_parent_;
unsigned diag_member_in_stack_allocated_class_;
unsigned diag_member_on_stack_;
unsigned diag_additional_padding_;
unsigned diag_part_object_in_unmanaged_;
unsigned diag_task_runner_timer_in_gc_class_note;
unsigned diag_forbidden_field_part_object_class_note;
unsigned diag_mojo_remote_in_gc_class_note;
unsigned diag_mojo_receiver_in_gc_class_note;
unsigned diag_mojo_associated_remote_in_gc_class_note;
unsigned diag_mojo_associated_receiver_in_gc_class_note;
unsigned diag_unique_ptr_used_with_gc_;
unsigned diag_optional_decl_used_with_gc_;
unsigned diag_optional_new_expr_used_with_gc_;
unsigned diag_raw_ptr_or_ref_decl_used_with_gc_;
unsigned diag_raw_ptr_or_ref_new_expr_used_with_gc_;
unsigned diag_variant_used_with_gc_;
unsigned diag_collection_of_gced_;
unsigned diag_collection_of_members_;
};
#endif // TOOLS_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_