LibJSGCPluginAction.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <clang/AST/ASTConsumer.h>
  8. #include <clang/AST/RecursiveASTVisitor.h>
  9. #include <clang/Frontend/FrontendAction.h>
  10. struct LibJSCellMacro {
  11. enum class Type {
  12. JSCell,
  13. JSObject,
  14. JSEnvironment,
  15. JSPrototypeObject,
  16. WebPlatformObject,
  17. };
  18. struct Arg {
  19. std::string text;
  20. clang::SourceLocation location;
  21. };
  22. clang::SourceRange range;
  23. Type type;
  24. std::vector<Arg> args;
  25. static char const* type_name(Type);
  26. };
  27. using LibJSCellMacroMap = std::unordered_map<unsigned int, std::vector<LibJSCellMacro>>;
  28. class LibJSPPCallbacks : public clang::PPCallbacks {
  29. public:
  30. LibJSPPCallbacks(clang::Preprocessor& preprocessor, LibJSCellMacroMap& macro_map)
  31. : m_preprocessor(preprocessor)
  32. , m_macro_map(macro_map)
  33. {
  34. }
  35. virtual void LexedFileChanged(clang::FileID curr_fid, LexedFileChangeReason, clang::SrcMgr::CharacteristicKind, clang::FileID, clang::SourceLocation) override;
  36. virtual void MacroExpands(clang::Token const& name_token, clang::MacroDefinition const& definition, clang::SourceRange range, clang::MacroArgs const* args) override;
  37. private:
  38. clang::Preprocessor& m_preprocessor;
  39. std::vector<unsigned int> m_curr_fid_hash_stack;
  40. LibJSCellMacroMap& m_macro_map;
  41. };
  42. class LibJSGCVisitor : public clang::RecursiveASTVisitor<LibJSGCVisitor> {
  43. public:
  44. explicit LibJSGCVisitor(clang::ASTContext& context, LibJSCellMacroMap const& macro_map, bool detect_invalid_function_members)
  45. : m_context(context)
  46. , m_macro_map(macro_map)
  47. , m_detect_invalid_function_members(detect_invalid_function_members)
  48. {
  49. }
  50. bool VisitCXXRecordDecl(clang::CXXRecordDecl*);
  51. private:
  52. struct CellMacroExpectation {
  53. LibJSCellMacro::Type type;
  54. std::string base_name;
  55. };
  56. void validate_record_macros(clang::CXXRecordDecl const&);
  57. CellMacroExpectation get_record_cell_macro_expectation(clang::CXXRecordDecl const&);
  58. clang::ASTContext& m_context;
  59. LibJSCellMacroMap const& m_macro_map;
  60. bool m_detect_invalid_function_members;
  61. };
  62. class LibJSGCASTConsumer : public clang::ASTConsumer {
  63. public:
  64. LibJSGCASTConsumer(clang::CompilerInstance&, bool detect_invalid_function_members);
  65. private:
  66. virtual void HandleTranslationUnit(clang::ASTContext& context) override;
  67. clang::CompilerInstance& m_compiler;
  68. LibJSCellMacroMap m_macro_map;
  69. bool m_detect_invalid_function_members;
  70. };
  71. class LibJSGCPluginAction : public clang::PluginASTAction {
  72. public:
  73. virtual bool ParseArgs(clang::CompilerInstance const&, std::vector<std::string> const& args) override
  74. {
  75. m_detect_invalid_function_members = std::find(args.begin(), args.end(), "detect-invalid-function-members") != args.end();
  76. return true;
  77. }
  78. virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef) override
  79. {
  80. return std::make_unique<LibJSGCASTConsumer>(compiler, m_detect_invalid_function_members);
  81. }
  82. ActionType getActionType() override
  83. {
  84. return AddAfterMainAction;
  85. }
  86. private:
  87. bool m_detect_invalid_function_members { false };
  88. };