|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // This file defines a bunch of recurring problems in the Chromium C++ code. | 
|  | // | 
|  | // Checks that are implemented: | 
|  | // - Constructors/Destructors should not be inlined if they are of a complex | 
|  | //   class type. | 
|  | // - Missing "virtual" keywords on methods that should be virtual. | 
|  | // - Non-annotated overriding virtual methods. | 
|  | // - Virtual methods with nonempty implementations in their headers. | 
|  | // - Classes that derive from base::RefCounted / base::RefCountedThreadSafe | 
|  | //   should have protected or private destructors. | 
|  | // - WeakPtrFactory members that refer to their outer class should be the last | 
|  | //   member. | 
|  | // - Enum types with a xxxx_LAST or xxxxLast const actually have that constant | 
|  | //   have the maximal value for that type. | 
|  |  | 
|  | #ifndef TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_ | 
|  | #define TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_ | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "clang/AST/AST.h" | 
|  | #include "clang/AST/ASTConsumer.h" | 
|  | #include "clang/AST/Attr.h" | 
|  | #include "clang/AST/CXXInheritance.h" | 
|  | #include "clang/AST/RecursiveASTVisitor.h" | 
|  | #include "clang/AST/TypeLoc.h" | 
|  | #include "clang/Basic/SourceManager.h" | 
|  | #include "clang/Basic/SourceLocation.h" | 
|  |  | 
|  | #include "CheckIPCVisitor.h" | 
|  | #include "ChromeClassTester.h" | 
|  | #include "Options.h" | 
|  | #include "SuppressibleDiagnosticBuilder.h" | 
|  |  | 
|  | namespace chrome_checker { | 
|  |  | 
|  | // Searches for constructs that we know we don't want in the Chromium code base. | 
|  | class FindBadConstructsConsumer | 
|  | : public clang::RecursiveASTVisitor<FindBadConstructsConsumer>, | 
|  | public ChromeClassTester { | 
|  | public: | 
|  | FindBadConstructsConsumer(clang::CompilerInstance& instance, | 
|  | const Options& options); | 
|  |  | 
|  | void Traverse(clang::ASTContext& context); | 
|  |  | 
|  | // RecursiveASTVisitor: | 
|  | bool TraverseDecl(clang::Decl* decl); | 
|  | bool VisitTagDecl(clang::TagDecl* tag_decl); | 
|  | bool VisitVarDecl(clang::VarDecl* var_decl); | 
|  | bool VisitTemplateSpecializationType(clang::TemplateSpecializationType* spec); | 
|  | bool VisitCallExpr(clang::CallExpr* call_expr); | 
|  |  | 
|  | // ChromeClassTester overrides: | 
|  | void CheckChromeClass(clang::SourceLocation record_location, | 
|  | clang::CXXRecordDecl* record) override; | 
|  | void CheckChromeEnum(clang::SourceLocation enum_location, | 
|  | clang::EnumDecl* enum_decl) override; | 
|  |  | 
|  | private: | 
|  | // The type of problematic ref-counting pattern that was encountered. | 
|  | enum RefcountIssue { None, ImplicitDestructor, PublicDestructor }; | 
|  |  | 
|  | void CheckCtorDtorWeight(clang::SourceLocation record_location, | 
|  | clang::CXXRecordDecl* record); | 
|  |  | 
|  | bool InTestingNamespace(const clang::Decl* record); | 
|  | bool IsMethodInBannedOrTestingNamespace(const clang::CXXMethodDecl* method); | 
|  |  | 
|  | // Returns a diagnostic builder that only emits the diagnostic if the spelling | 
|  | // location (the actual characters that make up the token) is not in an | 
|  | // ignored file. This is useful for situations where the token might originate | 
|  | // from a macro in a system header: warning isn't useful, since system headers | 
|  | // generally can't be easily updated. | 
|  | SuppressibleDiagnosticBuilder ReportIfSpellingLocNotIgnored( | 
|  | clang::SourceLocation loc, | 
|  | unsigned diagnostic_id); | 
|  |  | 
|  | void CheckVirtualMethods(clang::SourceLocation record_location, | 
|  | clang::CXXRecordDecl* record, | 
|  | bool warn_on_inline_bodies); | 
|  | void CheckVirtualSpecifiers(const clang::CXXMethodDecl* method); | 
|  | void CheckVirtualBodies(const clang::CXXMethodDecl* method); | 
|  |  | 
|  | void CountType(const clang::Type* type, | 
|  | int* trivial_member, | 
|  | int* non_trivial_member, | 
|  | int* templated_non_trivial_member); | 
|  |  | 
|  | static RefcountIssue CheckRecordForRefcountIssue( | 
|  | const clang::CXXRecordDecl* record, | 
|  | clang::SourceLocation& loc); | 
|  | bool IsRefCounted(const clang::CXXBaseSpecifier* base, | 
|  | clang::CXXBasePath& path); | 
|  | static bool HasPublicDtorCallback(const clang::CXXBaseSpecifier* base, | 
|  | clang::CXXBasePath& path, | 
|  | void* user_data); | 
|  | void PrintInheritanceChain(const clang::CXXBasePath& path); | 
|  | unsigned DiagnosticForIssue(RefcountIssue issue); | 
|  | void CheckRefCountedDtors(clang::SourceLocation record_location, | 
|  | clang::CXXRecordDecl* record); | 
|  |  | 
|  | void CheckWeakPtrFactoryMembers(clang::SourceLocation record_location, | 
|  | clang::CXXRecordDecl* record); | 
|  | void CheckVarDecl(clang::VarDecl* decl); | 
|  |  | 
|  | void ParseFunctionTemplates(clang::TranslationUnitDecl* decl); | 
|  |  | 
|  | unsigned diag_method_requires_override_; | 
|  | unsigned diag_redundant_virtual_specifier_; | 
|  | unsigned diag_base_method_virtual_and_final_; | 
|  | unsigned diag_no_explicit_dtor_; | 
|  | unsigned diag_public_dtor_; | 
|  | unsigned diag_protected_non_virtual_dtor_; | 
|  | unsigned diag_weak_ptr_factory_order_; | 
|  | unsigned diag_bad_enum_last_value_; | 
|  | unsigned diag_auto_deduced_to_a_pointer_type_; | 
|  | unsigned diag_note_inheritance_; | 
|  | unsigned diag_note_implicit_dtor_; | 
|  | unsigned diag_note_public_dtor_; | 
|  | unsigned diag_note_protected_non_virtual_dtor_; | 
|  |  | 
|  | std::unique_ptr<CheckIPCVisitor> ipc_visitor_; | 
|  | }; | 
|  |  | 
|  | }  // namespace chrome_checker | 
|  |  | 
|  | #endif  // TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_ |