Skip to content

Commit 16e4cfa

Browse files
[ObjcHeader] Fix objc header generation when pch is explicited passed
When swift-frontend is explicitly passed the pch file as bridging header on command-line through `-import-objc-header`, it needs to print the original source file name if needed to the generated objc header. rdar://109411245
1 parent ee5b3b1 commit 16e4cfa

File tree

9 files changed

+68
-6
lines changed

9 files changed

+68
-6
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ class ClangImporter final : public ClangModuleLoader {
403403
/// if we need to persist a PCH for later reuse.
404404
bool canReadPCH(StringRef PCHFilename);
405405

406+
/// Reads the original source file name from PCH.
407+
std::string getOriginalSourceFile(StringRef PCHFilename);
408+
406409
/// Makes a temporary replica of the ClangImporter's CompilerInstance, reads a
407410
/// module map into the replica and emits a PCM file for one of the modules it
408411
/// declares. Delegates to clang for everything except construction of the

include/swift/Frontend/Frontend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,9 @@ class CompilerInstance {
667667
/// file.
668668
SourceFile *getIDEInspectionFile() const;
669669

670+
/// Retrieve the printing path for bridging header.
671+
std::string getBridgingHeaderPath() const;
672+
670673
private:
671674
/// Set up the file system by loading and validating all VFS overlay YAML
672675
/// files. If the process of validating VFS files failed, or the overlay

lib/ClangImporter/ClangImporter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,12 @@ bool ClangImporter::canReadPCH(StringRef PCHFilename) {
915915
llvm_unreachable("unhandled result");
916916
}
917917

918+
std::string ClangImporter::getOriginalSourceFile(StringRef PCHFilename) {
919+
return clang::ASTReader::getOriginalSourceFile(
920+
PCHFilename.str(), Impl.Instance->getFileManager(),
921+
Impl.Instance->getPCHContainerReader(), Impl.Instance->getDiagnostics());
922+
}
923+
918924
Optional<std::string>
919925
ClangImporter::getPCHFilename(const ClangImporterOptions &ImporterOptions,
920926
StringRef SwiftPCHHash, bool &isExplicit) {

lib/Frontend/Frontend.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,26 @@ SourceFile *CompilerInstance::getIDEInspectionFile() const {
818818
return evaluateOrDefault(eval, IDEInspectionFileRequest{mod}, nullptr);
819819
}
820820

821+
static inline bool isPCHFilenameExtension(StringRef path) {
822+
return llvm::sys::path::extension(path)
823+
.endswith(file_types::getExtension(file_types::TY_PCH));
824+
}
825+
826+
std::string CompilerInstance::getBridgingHeaderPath() const {
827+
const FrontendOptions &opts = Invocation.getFrontendOptions();
828+
if (!isPCHFilenameExtension(opts.ImplicitObjCHeaderPath))
829+
return opts.ImplicitObjCHeaderPath;
830+
831+
auto clangImporter =
832+
static_cast<ClangImporter *>(getASTContext().getClangModuleLoader());
833+
834+
// No clang importer created. Report error?
835+
if (!clangImporter)
836+
return std::string();
837+
838+
return clangImporter->getOriginalSourceFile(opts.ImplicitObjCHeaderPath);
839+
}
840+
821841
bool CompilerInstance::setUpInputs() {
822842
// Adds to InputSourceCodeBufferIDs, so may need to happen before the
823843
// per-input setup.

lib/FrontendTool/FrontendTool.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -912,17 +912,14 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
912912

913913
if ((!Context.hadError() || opts.AllowModuleWithCompilerErrors) &&
914914
opts.InputsAndOutputs.hasClangHeaderOutputPath()) {
915-
std::string BridgingHeaderPathForPrint;
916-
if (!opts.ImplicitObjCHeaderPath.empty()) {
915+
std::string BridgingHeaderPathForPrint = Instance.getBridgingHeaderPath();
916+
if (!BridgingHeaderPathForPrint.empty()) {
917917
if (opts.BridgingHeaderDirForPrint.has_value()) {
918918
// User specified preferred directory for including, use that dir.
919919
llvm::SmallString<32> Buffer(*opts.BridgingHeaderDirForPrint);
920920
llvm::sys::path::append(Buffer,
921-
llvm::sys::path::filename(opts.ImplicitObjCHeaderPath));
921+
llvm::sys::path::filename(BridgingHeaderPathForPrint));
922922
BridgingHeaderPathForPrint = (std::string)Buffer;
923-
} else {
924-
// By default, include the given bridging header path directly.
925-
BridgingHeaderPathForPrint = opts.ImplicitObjCHeaderPath;
926923
}
927924
}
928925
hadAnyError |= printAsClangHeaderIfNeeded(
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import Foundation;
2+
3+
@protocol TestProto
4+
@property id strongProp;
5+
@end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#import <Foundation.h>
2+
3+
@interface ObjCClass : NSObject
4+
5+
- (nullable id)swiftMethod;
6+
7+
@end
8+

test/PrintAsObjC/Inputs/custom-modules/module.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,8 @@ module objc_implementation {
6363
header "objc_implementation/objc_implementation.h"
6464
export *
6565
}
66+
67+
module bridging_header {
68+
header "bridging_header/bridging_header.h"
69+
export *
70+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// REQUIRES: objc_interop
2+
3+
// RUN: %empty-directory(%t)
4+
5+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-pch -o %t/bridging-header.pch %S/Inputs/bridging_header-Bridging-Header.h
6+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -I %S/Inputs/custom-modules -import-objc-header %t/bridging-header.pch -import-underlying-module -o %t %s -disable-objc-attr-requires-foundation-module -emit-objc-header-path %t/bridging_header-Swift.h
7+
8+
// RUN: %FileCheck %s --input-file %t/bridging_header-Swift.h
9+
10+
// CHECK: bridging_header-Bridging-Header.h
11+
// CHECK-NOT: bridging-header.pch
12+
13+
@objc class Test : NSObject, TestProto {
14+
var strongProp: Any?
15+
}

0 commit comments

Comments
 (0)