[clang] 15bf0e5 - [clang][extract-api] Use correct language info from inputs

Zixu Wang via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 29 10:06:29 PDT 2022


Author: Zixu Wang
Date: 2022-03-29T10:06:08-07:00
New Revision: 15bf0e567375c977cf7d7b48465eb1561e890b54

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

LOG: [clang][extract-api] Use correct language info from inputs

The current way of getting the `clang::Language` from `LangOptions` does
not handle Objective-C correctly because `clang::Language::ObjC` does
not correspond to any `LangStandard`. This patch passes the correct
`Language` from the frontend input information.

Differential Revision: https://reviews.llvm.org/D122495

Added: 
    clang/test/ExtractAPI/language.c

Modified: 
    clang/include/clang/ExtractAPI/API.h
    clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
    clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h
index eb72450f87d23..b22d110475908 100644
--- a/clang/include/clang/ExtractAPI/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -309,8 +309,8 @@ class APISet {
   /// Get the target triple for the ExtractAPI invocation.
   const llvm::Triple &getTarget() const { return Target; }
 
-  /// Get the language options used to parse the APIs.
-  const LangOptions &getLangOpts() const { return LangOpts; }
+  /// Get the language used by the APIs.
+  Language getLanguage() const { return Lang; }
 
   const GlobalRecordMap &getGlobals() const { return Globals; }
   const EnumRecordMap &getEnums() const { return Enums; }
@@ -328,8 +328,8 @@ class APISet {
   /// \returns a StringRef of the copied string in APISet::Allocator.
   StringRef copyString(StringRef String);
 
-  APISet(const llvm::Triple &Target, const LangOptions &LangOpts)
-      : Target(Target), LangOpts(LangOpts) {}
+  APISet(const llvm::Triple &Target, Language Lang)
+      : Target(Target), Lang(Lang) {}
 
 private:
   /// BumpPtrAllocator to store generated/copied strings.
@@ -338,7 +338,7 @@ class APISet {
   llvm::BumpPtrAllocator StringAllocator;
 
   const llvm::Triple Target;
-  const LangOptions LangOpts;
+  const Language Lang;
 
   GlobalRecordMap Globals;
   EnumRecordMap Enums;

diff  --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index 0636e6de7cc26..dc3e067a837e2 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -41,9 +41,8 @@ namespace {
 /// information.
 class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
 public:
-  explicit ExtractAPIVisitor(ASTContext &Context)
-      : Context(Context),
-        API(Context.getTargetInfo().getTriple(), Context.getLangOpts()) {}
+  ExtractAPIVisitor(ASTContext &Context, Language Lang)
+      : Context(Context), API(Context.getTargetInfo().getTriple(), Lang) {}
 
   const APISet &getAPI() const { return API; }
 
@@ -309,9 +308,9 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
 
 class ExtractAPIConsumer : public ASTConsumer {
 public:
-  ExtractAPIConsumer(ASTContext &Context, StringRef ProductName,
+  ExtractAPIConsumer(ASTContext &Context, StringRef ProductName, Language Lang,
                      std::unique_ptr<raw_pwrite_stream> OS)
-      : Visitor(Context), ProductName(ProductName), OS(std::move(OS)) {}
+      : Visitor(Context, Lang), ProductName(ProductName), OS(std::move(OS)) {}
 
   void HandleTranslationUnit(ASTContext &Context) override {
     // Use ExtractAPIVisitor to traverse symbol declarations in the context.
@@ -339,6 +338,7 @@ ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
     return nullptr;
   return std::make_unique<ExtractAPIConsumer>(
       CI.getASTContext(), CI.getInvocation().getFrontendOpts().ProductName,
+      CI.getFrontendOpts().Inputs.back().getKind().getLanguage(),
       std::move(OS));
 }
 

diff  --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index 54276f6cf1de1..cde81ecf0abd4 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -151,11 +151,9 @@ Optional<Object> serializeAvailability(const AvailabilityInfo &Avail) {
   return Availbility;
 }
 
-/// Get the short language name string for interface language references.
-StringRef getLanguageName(const LangOptions &LangOpts) {
-  auto LanguageKind =
-      LangStandard::getLangStandardForKind(LangOpts.LangStd).getLanguage();
-  switch (LanguageKind) {
+/// Get the language name string for interface language references.
+StringRef getLanguageName(Language Lang) {
+  switch (Lang) {
   case Language::C:
     return "c";
   case Language::ObjC:
@@ -185,11 +183,10 @@ StringRef getLanguageName(const LangOptions &LangOpts) {
 ///
 /// The identifier property of a symbol contains the USR for precise and unique
 /// references, and the interface language name.
-Object serializeIdentifier(const APIRecord &Record,
-                           const LangOptions &LangOpts) {
+Object serializeIdentifier(const APIRecord &Record, Language Lang) {
   Object Identifier;
   Identifier["precise"] = Record.USR;
-  Identifier["interfaceLanguage"] = getLanguageName(LangOpts);
+  Identifier["interfaceLanguage"] = getLanguageName(Lang);
 
   return Identifier;
 }
@@ -335,10 +332,9 @@ Object serializeNames(const APIRecord &Record) {
 /// The Symbol Graph symbol kind property contains a shorthand \c identifier
 /// which is prefixed by the source language name, useful for tooling to parse
 /// the kind, and a \c displayName for rendering human-readable names.
-Object serializeSymbolKind(const APIRecord &Record,
-                           const LangOptions &LangOpts) {
-  auto AddLangPrefix = [&LangOpts](StringRef S) -> std::string {
-    return (getLanguageName(LangOpts) + "." + S).str();
+Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
+  auto AddLangPrefix = [&Lang](StringRef S) -> std::string {
+    return (getLanguageName(Lang) + "." + S).str();
   };
 
   Object Kind;
@@ -420,8 +416,8 @@ SymbolGraphSerializer::serializeAPIRecord(const APIRecord &Record) const {
 
   Object Obj;
   serializeObject(Obj, "identifier",
-                  serializeIdentifier(Record, API.getLangOpts()));
-  serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLangOpts()));
+                  serializeIdentifier(Record, API.getLanguage()));
+  serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLanguage()));
   serializeObject(Obj, "names", serializeNames(Record));
   serializeObject(
       Obj, "location",

diff  --git a/clang/test/ExtractAPI/language.c b/clang/test/ExtractAPI/language.c
new file mode 100644
index 0000000000000..274e6b930340d
--- /dev/null
+++ b/clang/test/ExtractAPI/language.c
@@ -0,0 +1,166 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s at INPUT_DIR@%/t at g" %t/c.reference.output.json.in >> \
+// RUN: %t/c.reference.output.json
+// RUN: sed -e "s at INPUT_DIR@%/t at g" %t/objc.reference.output.json.in >> \
+// RUN: %t/objc.reference.output.json
+
+// RUN: %clang -extract-api -x c-header -target arm64-apple-macosx \
+// RUN: %t/c.h -o %t/c.output.json | FileCheck -allow-empty %s
+// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
+// RUN: %t/objc.h -o %t/objc.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/c.output.json >> %t/c.output-normalized.json
+// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
+// RUN: %t/objc.output.json >> %t/objc.output-normalized.json
+
+// RUN: 
diff  %t/c.reference.output.json %t/c.output-normalized.json
+// RUN: 
diff  %t/objc.reference.output.json %t/objc.output-normalized.json
+
+// CHECK-NOT: error:
+// CHECK-NOT: warning:
+
+//--- c.h
+char c;
+
+//--- objc.h
+char objc;
+
+//--- c.reference.output.json.in
+{
+  "metadata": {
+    "formatVersion": {
+      "major": 0,
+      "minor": 5,
+      "patch": 3
+    },
+    "generator": "?"
+  },
+  "module": {
+    "name": "",
+    "platform": {
+      "architecture": "arm64",
+      "operatingSystem": {
+        "minimumVersion": {
+          "major": 11,
+          "minor": 0,
+          "patch": 0
+        },
+        "name": "macosx"
+      },
+      "vendor": "apple"
+    }
+  },
+  "relationhips": [],
+  "symbols": [
+    {
+      "declarationFragments": [
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:C",
+          "spelling": "char"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "identifier",
+          "spelling": "c"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@c"
+      },
+      "kind": {
+        "displayName": "Global Variable",
+        "identifier": "c.var"
+      },
+      "location": {
+        "character": 6,
+        "line": 1,
+        "uri": "file://INPUT_DIR/c.h"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "c"
+          }
+        ],
+        "title": "c"
+      }
+    }
+  ]
+}
+//--- objc.reference.output.json.in
+{
+  "metadata": {
+    "formatVersion": {
+      "major": 0,
+      "minor": 5,
+      "patch": 3
+    },
+    "generator": "?"
+  },
+  "module": {
+    "name": "",
+    "platform": {
+      "architecture": "arm64",
+      "operatingSystem": {
+        "minimumVersion": {
+          "major": 11,
+          "minor": 0,
+          "patch": 0
+        },
+        "name": "macosx"
+      },
+      "vendor": "apple"
+    }
+  },
+  "relationhips": [],
+  "symbols": [
+    {
+      "declarationFragments": [
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:C",
+          "spelling": "char"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "identifier",
+          "spelling": "objc"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "objective-c",
+        "precise": "c:@objc"
+      },
+      "kind": {
+        "displayName": "Global Variable",
+        "identifier": "objective-c.var"
+      },
+      "location": {
+        "character": 6,
+        "line": 1,
+        "uri": "file://INPUT_DIR/objc.h"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "objc"
+          }
+        ],
+        "title": "objc"
+      }
+    }
+  ]
+}


        


More information about the cfe-commits mailing list