diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -309,8 +309,8 @@ /// 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 @@ /// \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 @@ 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 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -41,9 +41,8 @@ /// information. class ExtractAPIVisitor : public RecursiveASTVisitor { 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 ExtractAPIConsumer : public ASTConsumer { public: - ExtractAPIConsumer(ASTContext &Context, StringRef ProductName, + ExtractAPIConsumer(ASTContext &Context, StringRef ProductName, Language Lang, std::unique_ptr 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 @@ return nullptr; return std::make_unique( 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 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -151,11 +151,9 @@ 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 @@ /// /// 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 @@ /// 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 @@ 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 --- /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@INPUT_DIR@%/t@g" %t/c.reference.output.json.in >> \ +// RUN: %t/c.reference.output.json +// RUN: sed -e "s@INPUT_DIR@%/t@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" + } + } + ] +}