Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-15586] import Foundation hides declarations (derived from C) in other modules on Linux. #57889

Open
YOCKOW opened this issue Dec 13, 2021 · 6 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@YOCKOW
Copy link
Collaborator

YOCKOW commented Dec 13, 2021

Previous ID SR-15586
Radar rdar://problem/88618172
Original Reporter @YOCKOW
Type Bug
Environment
  • OS: Ubuntu 20.04

  • Swift: Swift version 5.5.1 (swift-5.5.1-RELEASE)

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: b3998f08d2120933f50adee706bb7dd1

relates to:

  • SR-15532 Compiler doesn't load public property declarations in another module under some conditions.
  • SR-15822 Existence of modulemap disables declarations in simple C headers in some cases.

Issue Description:

NOTE: This issue is probably related to SR-15532.

How to reproduce

Step 1: Prepare 3 files; "c.h", "library.swift", and "user.swift"

c.h

// c.h
#ifndef C_H__________
#define C_H__________
#include <netinet/in.h>
#endif

library.swift

// library.swift
public typealias A = in_addr
extension A {
  public var foo: String { return "foo" }
}

user.swift

// user.swift
import Foundation // Removing this line brings success!
import MyLibR
let a = A()
print(a.foo)

Step 2: Compile "library.swift" as library named "MyLibR" using "c.h"

swiftc library.swift -import-objc-header c.h -emit-module -emit-library -module-name MyLibR

Step 3: Compile "user.swift"

swiftc user.swift -I. -L. -lMyLibR -o ./userR

Results

macOS + Swift 5.5

"user.swift" is compiled successfully.

Linux + Swift 5.5

"user.swift" cannot be compiled with the error message below:

user.swift:4:9: error: cannot find 'A' in scope
let a = A()
        ^

Discussion

  • import Foundation is not necessary in "user.swift". As described in the file, "user.swift" can be compiled successfully even on Linux when import Foundation is removed.

  • import Glibc instead of import Foundation also causes the failure.

@YOCKOW
Copy link
Collaborator Author

YOCKOW commented Jan 17, 2022

ModuleFileSharedCore's TopLevelDecls for MyLibR seems empty on Linux (with import Glibc)...

EDIT:
NO.
getDeclChecked does fail.

EDIT2:
More elaborated;
ModuleFile::resolveCrossReference seems to fail.

@YOCKOW
Copy link
Collaborator Author

YOCKOW commented Jan 22, 2022

Compiler steps when "user.swift" is compiled (as far as I can see):

1. Tries to resolve the type named "A".
2. Looks it up in the module "MyLibR". (ModuleFile::lookupValue)
3. Turns out to need cross-reference. (DeclDeserializer::deserializeDeclCommon)
4. Gets the base module: Its name is "Darwin" on macOS, but is "__ObjC" on Linux. (ModuleFile::resolveCrossReference)
5. Looks up the type named "in_addr". (LookupByName::lookupInModule)


Next...
It is different where "in_addr" is (not) found.

env result
macOS with import Foundation "in_addr" is found in ImportCache > ImportSet > TransitiveImports > (module implicit "Darwin" interface type='module<Darwin>' access=public non_swift).
macOS without import Foundation The same as above.
Linux with import Foundation Not Found (TransitiveImports is empty.)
Linux without import Foundation "in_addr" is found with LookupByName::doLocalLookup in "__ObjC".

Difference on Linux between with/without import Foundation is that...

Linux with import Foundation __ObjC's "Lookup Table" contains only __swift: TU: __swift.
Linux without import Foundation __ObjC's "Lookup Table" contains (maybe) all C symbols.

The "Lookup Table" is owner's BridgingHeaderLookupTable in both cases.


I don't know why such differences exist...

@YOCKOW
Copy link
Collaborator Author

YOCKOW commented Jan 27, 2022

#include "c.h" is gone at Parser->ParseTopLevelDecl(parsed) in ClangImporter::Implementation::importHeader .

May "import GlibC" change the status of ClangParser or ClangPreprocessor?

EDIT:
Contents of sourceBuffer is `#include "c.h"` on both cases.
But first token is EOF in the case with import GlibC, on the other hand, it is typedef in the case without import GlibC.

EDIT2:
I finally found that import GlibC(SwiftGlibC) enables "include guard"s such as `#define _NETINET_IN_H` without adding any declarations in the C headers to BridgingHeaderLookup. It means that `#include "c.h"` is blocked by the guard when there is preceding import GlibC.
To fix it,
(1) Disable "include guard"s.
OR
(2) Add all declarations while importing GlibC.

@YOCKOW
Copy link
Collaborator Author

YOCKOW commented Jan 31, 2022

@DougGregor
Could you give us some advice on how/when ClangImporter should expose decls in SwiftGlibc in this case?

@YOCKOW
Copy link
Collaborator Author

YOCKOW commented Feb 4, 2022

I filed the reduced case as SR-15582 which indicates that this issue does matter on any platforms.

@weissi
Copy link
Member

weissi commented Feb 8, 2022

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

2 participants