[clang] a9909d2 - [clang][extractapi] Tie API and serialization to the FrontendAction

Daniel Grumberg via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 30 10:33:28 PDT 2022


Author: Daniel Grumberg
Date: 2022-03-30T18:32:58+01:00
New Revision: a9909d23e9bb8c4649cba1c14d479c28df4ca185

URL: https://github.com/llvm/llvm-project/commit/a9909d23e9bb8c4649cba1c14d479c28df4ca185
DIFF: https://github.com/llvm/llvm-project/commit/a9909d23e9bb8c4649cba1c14d479c28df4ca185.diff

LOG: [clang][extractapi] Tie API and serialization to the FrontendAction

Make the API records a property of the action instead of the ASTVisitor
so that it can be accessed outside the AST visitation and push back
serialization to the end of the frontend action.

This will allow accessing and modifying the API records outside of the
ASTVisitor, which is a prerequisite for supporting macros.

Added: 
    

Modified: 
    clang/include/clang/ExtractAPI/FrontendActions.h
    clang/lib/ExtractAPI/ExtractAPIConsumer.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/ExtractAPI/FrontendActions.h b/clang/include/clang/ExtractAPI/FrontendActions.h
index 4c9449fe73a92..2bdb61dc6994d 100644
--- a/clang/include/clang/ExtractAPI/FrontendActions.h
+++ b/clang/include/clang/ExtractAPI/FrontendActions.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H
 #define LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H
 
+#include "clang/ExtractAPI/API.h"
 #include "clang/Frontend/FrontendAction.h"
 
 namespace clang {
@@ -25,11 +26,19 @@ class ExtractAPIAction : public ASTFrontendAction {
                                                  StringRef InFile) override;
 
 private:
+  /// A representation of the APIs this action extracts.
+  std::unique_ptr<extractapi::APISet> API;
+
+  /// A stream to the output file of this action.
+  std::unique_ptr<raw_pwrite_stream> OS;
+
+  /// The product this action is extracting API information for.
+  std::string ProductName;
+
   /// The synthesized input buffer that contains all the provided input header
   /// files.
   std::unique_ptr<llvm::MemoryBuffer> Buffer;
 
-public:
   /// Prepare to execute the action on the given CompilerInstance.
   ///
   /// This is called before executing the action on any inputs. This generates a
@@ -37,8 +46,15 @@ class ExtractAPIAction : public ASTFrontendAction {
   /// list with it before actually executing the action.
   bool PrepareToExecuteAction(CompilerInstance &CI) override;
 
+  /// Called after executing the action on the synthesized input buffer.
+  ///
+  /// Note: Now that we have gathered all the API definitions to surface we can
+  /// emit them in this callback.
+  void EndSourceFileAction() override;
+
   static std::unique_ptr<llvm::raw_pwrite_stream>
   CreateOutputFile(CompilerInstance &CI, StringRef InFile);
+
   static StringRef getInputBufferName() { return "<extract-api-includes>"; }
 };
 

diff  --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index bcc01dbd710d8..10b28873611e9 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -41,8 +41,8 @@ namespace {
 /// information.
 class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
 public:
-  ExtractAPIVisitor(ASTContext &Context, Language Lang)
-      : Context(Context), API(Context.getTargetInfo().getTriple(), Lang) {}
+  ExtractAPIVisitor(ASTContext &Context, APISet &API)
+      : Context(Context), API(API) {}
 
   const APISet &getAPI() const { return API; }
 
@@ -489,43 +489,40 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
   }
 
   ASTContext &Context;
-  APISet API;
+  APISet &API;
 };
 
 class ExtractAPIConsumer : public ASTConsumer {
 public:
-  ExtractAPIConsumer(ASTContext &Context, StringRef ProductName, Language Lang,
-                     std::unique_ptr<raw_pwrite_stream> OS)
-      : Visitor(Context, Lang), ProductName(ProductName), OS(std::move(OS)) {}
+  ExtractAPIConsumer(ASTContext &Context, APISet &API)
+      : Visitor(Context, API) {}
 
   void HandleTranslationUnit(ASTContext &Context) override {
     // Use ExtractAPIVisitor to traverse symbol declarations in the context.
     Visitor.TraverseDecl(Context.getTranslationUnitDecl());
-
-    // Setup a SymbolGraphSerializer to write out collected API information in
-    // the Symbol Graph format.
-    // FIXME: Make the kind of APISerializer configurable.
-    SymbolGraphSerializer SGSerializer(Visitor.getAPI(), ProductName);
-    SGSerializer.serialize(*OS);
   }
 
 private:
   ExtractAPIVisitor Visitor;
-  std::string ProductName;
-  std::unique_ptr<raw_pwrite_stream> OS;
 };
 
 } // namespace
 
 std::unique_ptr<ASTConsumer>
 ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
-  std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);
+  OS = CreateOutputFile(CI, InFile);
   if (!OS)
     return nullptr;
-  return std::make_unique<ExtractAPIConsumer>(
-      CI.getASTContext(), CI.getInvocation().getFrontendOpts().ProductName,
-      CI.getFrontendOpts().Inputs.back().getKind().getLanguage(),
-      std::move(OS));
+
+  ProductName = CI.getFrontendOpts().ProductName;
+
+  // Now that we have enough information about the language options and the
+  // target triple, let's create the APISet before anyone uses it.
+  API = std::make_unique<APISet>(
+      CI.getTarget().getTriple(),
+      CI.getFrontendOpts().Inputs.back().getKind().getLanguage());
+
+  return std::make_unique<ExtractAPIConsumer>(CI.getASTContext(), *API);
 }
 
 bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
@@ -557,6 +554,18 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
   return true;
 }
 
+void ExtractAPIAction::EndSourceFileAction() {
+  if (!OS)
+    return;
+
+  // Setup a SymbolGraphSerializer to write out collected API information in
+  // the Symbol Graph format.
+  // FIXME: Make the kind of APISerializer configurable.
+  SymbolGraphSerializer SGSerializer(*API, ProductName);
+  SGSerializer.serialize(*OS);
+  OS->flush();
+}
+
 std::unique_ptr<raw_pwrite_stream>
 ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
   std::unique_ptr<raw_pwrite_stream> OS =


        


More information about the cfe-commits mailing list