[clang] f833aab - [clang][extract-api] Enable processing of multiple headers
Daniel Grumberg via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 23 12:05:38 PDT 2022
Author: Daniel Grumberg
Date: 2022-03-23T19:05:19Z
New Revision: f833aab0d0bf1bd9e9903a1398e429f431532f5f
URL: https://github.com/llvm/llvm-project/commit/f833aab0d0bf1bd9e9903a1398e429f431532f5f
DIFF: https://github.com/llvm/llvm-project/commit/f833aab0d0bf1bd9e9903a1398e429f431532f5f.diff
LOG: [clang][extract-api] Enable processing of multiple headers
Before actually executing the ExtractAPIAction, clear the
CompilationInstance's input list and replace it with a single
synthesized file that just includes (or imports in ObjC) all the inputs.
Depends on D122141
Differential Revision: https://reviews.llvm.org/D122175
Added:
clang/test/ExtractAPI/global_record_multifile.c
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 e43b6cf9212d6..4c9449fe73a92 100644
--- a/clang/include/clang/ExtractAPI/FrontendActions.h
+++ b/clang/include/clang/ExtractAPI/FrontendActions.h
@@ -24,9 +24,22 @@ class ExtractAPIAction : public ASTFrontendAction {
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
+private:
+ /// 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
+ /// single header that includes all of CI's inputs and replaces CI's input
+ /// list with it before actually executing the action.
+ bool PrepareToExecuteAction(CompilerInstance &CI) override;
+
static std::unique_ptr<llvm::raw_pwrite_stream>
CreateOutputFile(CompilerInstance &CI, StringRef InFile);
+ static StringRef getInputBufferName() { return "<extract-api-includes>"; }
};
} // namespace clang
diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index 7007d08e839be..0636e6de7cc26 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -27,6 +27,9 @@
#include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -339,6 +342,35 @@ ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::move(OS));
}
+bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
+ auto &Inputs = CI.getFrontendOpts().Inputs;
+ if (Inputs.empty())
+ return true;
+
+ auto Kind = Inputs[0].getKind();
+
+ // Convert the header file inputs into a single input buffer.
+ SmallString<256> HeaderContents;
+ for (const FrontendInputFile &FIF : Inputs) {
+ if (Kind.isObjectiveC())
+ HeaderContents += "#import";
+ else
+ HeaderContents += "#include";
+ HeaderContents += " \"";
+ HeaderContents += FIF.getFile();
+ HeaderContents += "\"\n";
+ }
+
+ Buffer = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents,
+ getInputBufferName());
+
+ // Set that buffer up as our "real" input in the CompilerInstance.
+ Inputs.clear();
+ Inputs.emplace_back(Buffer->getMemBufferRef(), Kind, /*IsSystem*/ false);
+
+ return true;
+}
+
std::unique_ptr<raw_pwrite_stream>
ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<raw_pwrite_stream> OS =
diff --git a/clang/test/ExtractAPI/global_record_multifile.c b/clang/test/ExtractAPI/global_record_multifile.c
new file mode 100644
index 0000000000000..cc5448e838298
--- /dev/null
+++ b/clang/test/ExtractAPI/global_record_multifile.c
@@ -0,0 +1,371 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s at INPUT_DIR@%/t at g" %t/reference.output.json.in >> \
+// RUN: %t/reference.output.json
+// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
+// RUN: %t/input1.h %t/input2.h %t/input3.h -o %t/output.json | FileCheck -allow-empty %s
+
+// Generator version is not consistent across test runs, normalize it.
+// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
+// RUN: %t/output.json >> %t/output-normalized.json
+// RUN:
diff %t/reference.output.json %t/output-normalized.json
+
+// CHECK-NOT: error:
+// CHECK-NOT: warning:
+
+//--- input1.h
+int num;
+
+//--- input2.h
+/**
+ * \brief Add two numbers.
+ * \param [in] x A number.
+ * \param [in] y Another number.
+ * \param [out] res The result of x + y.
+ */
+void add(const int x, const int y, int *res);
+
+//--- input3.h
+char unavailable __attribute__((unavailable));
+
+//--- reference.output.json.in
+{
+ "metadata": {
+ "formatVersion": {
+ "major": 0,
+ "minor": 5,
+ "patch": 3
+ },
+ "generator": "?"
+ },
+ "module": {
+ "name": "GlobalRecord",
+ "platform": {
+ "architecture": "arm64",
+ "operatingSystem": {
+ "minimumVersion": {
+ "major": 11,
+ "minor": 0,
+ "patch": 0
+ },
+ "name": "macosx"
+ },
+ "vendor": "apple"
+ }
+ },
+ "relationhips": [],
+ "symbols": [
+ {
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "num"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@num"
+ },
+ "kind": {
+ "displayName": "Global Variable",
+ "identifier": "c.var"
+ },
+ "location": {
+ "character": 5,
+ "line": 1,
+ "uri": "file://INPUT_DIR/input1.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "num"
+ }
+ ],
+ "title": "num"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:v",
+ "spelling": "void"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "add"
+ },
+ {
+ "kind": "text",
+ "spelling": "("
+ },
+ {
+ "kind": "keyword",
+ "spelling": "const"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "x"
+ },
+ {
+ "kind": "text",
+ "spelling": ", "
+ },
+ {
+ "kind": "keyword",
+ "spelling": "const"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "y"
+ },
+ {
+ "kind": "text",
+ "spelling": ", "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
+ },
+ {
+ "kind": "text",
+ "spelling": " *"
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "res"
+ },
+ {
+ "kind": "text",
+ "spelling": ")"
+ }
+ ],
+ "docComment": {
+ "lines": [
+ {
+ "range": {
+ "end": {
+ "character": 4,
+ "line": 1
+ },
+ "start": {
+ "character": 4,
+ "line": 1
+ }
+ },
+ "text": ""
+ },
+ {
+ "range": {
+ "end": {
+ "character": 27,
+ "line": 2
+ },
+ "start": {
+ "character": 3,
+ "line": 2
+ }
+ },
+ "text": " \\brief Add two numbers."
+ },
+ {
+ "range": {
+ "end": {
+ "character": 30,
+ "line": 3
+ },
+ "start": {
+ "character": 3,
+ "line": 3
+ }
+ },
+ "text": " \\param [in] x A number."
+ },
+ {
+ "range": {
+ "end": {
+ "character": 36,
+ "line": 4
+ },
+ "start": {
+ "character": 3,
+ "line": 4
+ }
+ },
+ "text": " \\param [in] y Another number."
+ },
+ {
+ "range": {
+ "end": {
+ "character": 41,
+ "line": 5
+ },
+ "start": {
+ "character": 3,
+ "line": 5
+ }
+ },
+ "text": " \\param [out] res The result of x + y."
+ },
+ {
+ "range": {
+ "end": {
+ "character": 4,
+ "line": 6
+ },
+ "start": {
+ "character": 1,
+ "line": 6
+ }
+ },
+ "text": " "
+ }
+ ]
+ },
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@F at add"
+ },
+ "kind": {
+ "displayName": "Function",
+ "identifier": "c.func"
+ },
+ "location": {
+ "character": 6,
+ "line": 7,
+ "uri": "file://INPUT_DIR/input2.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "add"
+ }
+ ],
+ "title": "add"
+ },
+ "parameters": {
+ "parameters": [
+ {
+ "declarationFragments": [
+ {
+ "kind": "keyword",
+ "spelling": "const"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "x"
+ }
+ ],
+ "name": "x"
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "keyword",
+ "spelling": "const"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "y"
+ }
+ ],
+ "name": "y"
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
+ },
+ {
+ "kind": "text",
+ "spelling": " *"
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "res"
+ }
+ ],
+ "name": "res"
+ }
+ ],
+ "returns": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:v",
+ "spelling": "void"
+ }
+ ]
+ }
+ }
+ ]
+}
More information about the cfe-commits
mailing list