diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index 3aba3bf44547c..fe282dfb19e8a 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Basic/FileEntry.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -167,6 +168,12 @@ std::optional getRelativeIncludeName(const CompilerInstance &CI, return std::nullopt; } +std::optional getRelativeIncludeName(const CompilerInstance &CI, + FileEntryRef FE, + bool *IsQuoted = nullptr) { + return getRelativeIncludeName(CI, FE.getNameAsRequested(), IsQuoted); +} + struct LocationFileChecker { bool operator()(SourceLocation Loc) { // If the loc refers to a macro expansion we need to first get the file @@ -187,11 +194,9 @@ struct LocationFileChecker { if (ExternalFileEntries.count(*File)) return false; - StringRef FileName = SM.getFileManager().getCanonicalName(*File); - // Try to reduce the include name the same way we tried to include it. bool IsQuoted = false; - if (auto IncludeName = getRelativeIncludeName(CI, FileName, &IsQuoted)) + if (auto IncludeName = getRelativeIncludeName(CI, *File, &IsQuoted)) if (llvm::any_of(KnownFiles, [&IsQuoted, &IncludeName](const auto &KnownFile) { return KnownFile.first.equals(*IncludeName) && diff --git a/clang/test/ExtractAPI/vfs_redirected_include.m b/clang/test/ExtractAPI/vfs_redirected_include.m new file mode 100644 index 0000000000000..9ba7e1dedb601 --- /dev/null +++ b/clang/test/ExtractAPI/vfs_redirected_include.m @@ -0,0 +1,211 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Setup framework root +// RUN: mkdir -p %t/Frameworks/MyFramework.framework/Headers +// RUN: cp %t/MyFramework.h %t/Frameworks/MyFramework.framework/Headers/ +// RUN: cp %t/MyHeader.h %t/Frameworks/MyFramework.framework/Headers/ + +// RUN: sed -e "s@SRCROOT@%{/t:regex_replacement}@g" \ +// RUN: %t/reference.output.json.in >> %t/reference.output.json + +// Create VFS overlay from framework headers to SRCROOT +// RUN: sed -e "s@SRCROOT@%{/t:regex_replacement}@g" -e "s@DSTROOT@%{/t:regex_replacement}@g" \ +// RUN: %t/vfsoverlay.yaml.in >> %t/vfsoverlay.yaml + +// Input headers use paths to the framework root/DSTROOT +// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \ +// RUN: -triple arm64-apple-macosx \ +// RUN: -iquote%t -ivfsoverlay %t/vfsoverlay.yaml -F%t/Frameworks \ +// RUN: -x objective-c-header \ +// RUN: %t/Frameworks/MyFramework.framework/Headers/MyFramework.h \ +// RUN: %t/Frameworks/MyFramework.framework/Headers/MyHeader.h \ +// RUN: %t/QuotedHeader.h \ +// RUN: -o %t/output.json 2>&1 -verify | 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: : +// CHECK-NEXT: #import +// CHECK-NEXT: #import +// CHECK-NEXT: #import "QuotedHeader.h" + +//--- vfsoverlay.yaml.in +{ + "case-sensitive": "false", + "roots": [ + { + "contents": [ + { + "external-contents": "SRCROOT/MyHeader.h", + "name": "MyHeader.h", + "type": "file" + } + ], + "name": "DSTROOT/Frameworks/MyFramework.framework/Headers", + "type": "directory" + } + ], + "version": 0 +} + +//--- MyFramework.h +// Umbrella for MyFramework +#import +// expected-no-diagnostics + +//--- MyHeader.h +#import +int MyInt; +// expected-no-diagnostics + +//--- QuotedHeader.h +char MyChar; +// expected-no-diagnostics + +//--- Frameworks/OtherFramework.framework/Headers/OtherHeader.h +int OtherInt; +// expected-no-diagnostics + +//--- reference.output.json.in +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 5, + "patch": 3 + }, + "generator": "?" + }, + "module": { + "name": "MyFramework", + "platform": { + "architecture": "arm64", + "operatingSystem": { + "minimumVersion": { + "major": 11, + "minor": 0, + "patch": 0 + }, + "name": "macosx" + }, + "vendor": "apple" + } + }, + "relationships": [], + "symbols": [ + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:I", + "spelling": "int" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "MyInt" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "objective-c", + "precise": "c:@MyInt" + }, + "kind": { + "displayName": "Global Variable", + "identifier": "objective-c.var" + }, + "location": { + "position": { + "character": 4, + "line": 1 + }, + "uri": "file://SRCROOT/MyHeader.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "MyInt" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "MyInt" + } + ], + "title": "MyInt" + }, + "pathComponents": [ + "MyInt" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:C", + "spelling": "char" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "MyChar" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "objective-c", + "precise": "c:@MyChar" + }, + "kind": { + "displayName": "Global Variable", + "identifier": "objective-c.var" + }, + "location": { + "position": { + "character": 5, + "line": 0 + }, + "uri": "file://SRCROOT/QuotedHeader.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "MyChar" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "MyChar" + } + ], + "title": "MyChar" + }, + "pathComponents": [ + "MyChar" + ] + } + ] +}