This means all cross-module references and all mangled names will
consistently use the Swift 4 name (the canonical type), no special
handling required.
The main thing we lose here is that the Swift 4 names of imported
types become usable in Swift 3 mode without any diagnostics, similar
to how most language features introduced in Swift 4 are available in
Swift 3 mode. It also implies that the Swift 4 name will show up in
demangled names.
rdar://problem/31616162
- Add CompilerInvocation::getPCHHash
This will be used when creating a unique filename for a persistent
precompiled bridging header.
- Automatically generate and use a precompiled briding header
When we're given both -import-objc-header and -pch-output-dir
arguments, we will try to:
- Validate what we think the PCH filename should be for the bridging
header, based on the Swift PCH hash and the clang module hash.
- If we're successful, we'll just use it.
- If it's out of date or something else is wrong, we'll try to
emit it.
- This gives us a single filename which we can `stat` to check for the
validity of our code completion cache, which is keyed off of module
name, module filename, and module file age.
- Cache code completion results from imported modules
If we just have a single .PCH file imported, we can use that file as
part of the key used to cache declarations in a module. Because
multiple files can contribute to the __ObjC module, we've always given
it the phony filename "<imports>", which never exists, so `stat`-ing it
always fails and we never cache declarations in it.
This is extremely problematic for projects with huge bridging headers.
In the case where we have a single PCH import, this can bring warm code
completion times down to about 500ms from over 2-3s, so it can provide a
nice performance win for IDEs.
- Add a new test that performs two code-completion requests with a bridging header.
- Add some -pch-output-dir flags to existing SourceKit tests that import a bridging
header.
rdar://problem/31198982
We synthesize fake source locations for module imports that come from
Swift code; these locations have to be both valid and distinct for
Clang to use. We've mostly been getting away with simply making fake
offsets from the main file, but after the offsets start exceeding the
size of the buffer they start pointing into some /other/ file, and
then if Clang's SourceManager tries to order those locations it gets
/very/ confused.
This commit fixes that by allocating a 256K buffer of zeros and using
offsets into that instead. The hope is that a read-only mmap'd buffer
of zeros that never gets read (except possibly to look for newlines)
will be cheap to allocate.
(Why not just make the main file buffer 256K? Because we actually try
to parse that, and there's really no reason for the lexer to go crawl
through that file eagerly.)
This test case isn't the best because it doesn't actually fail in the
old code, but if only the assertion was added we at least hit that.
I did verify with the reproducing project I have that we no longer
hit this issue.
rdar://problem/30924269
There is a subtle incompatibility between the way bridging headers handle
module imports and the way clang's normal module-loading works (as done
by -emit-pch in bridging PCH, in particular).
When importing a submodule, Swift implicitly imports its supermodule. This
is part of Swift's treatment of modules and fine, we're not changing it
here.
But if client code imports a submodule, then tries to use a type that is
only defined in its supermodule, not the submodule, this _should_ cause
a parse error (and does in clang alone, or when generating a PCH).
Unfortunately Swift's "implicit parent import" currently happens
eagerly, so the supermodule is imported and its type is defined as soon
as the submodule is imported, which in turn suppresses the error.
This in turn means that client code thinks their code "works" and then
"breaks" when they turn on bridging PCH. What _should_ happen here is
that the (actually broken) client code should not be accepted in the first
place, neither bridging PCH nor textual bridging-header import.
This commit merely changes textual bridging-header import from eager
import to deferred parent-import, like bridging PCH does. This reconciles
the difference in behaviour between the two, at the cost of a source-compat
break.
rdar://30615193
Previously some decls (TypeAliasDecl and ExtensionDecl) had bits
explicitly marking whether they've been validated, while other decls
just deduced this from hasInterfaceType. The doing the latter doesn't
work when the interface type can be computed before doing full
validation (such as protocols and associatedtypes, which have trivial
interface types), and so an explicit bit is adopted for all decls.
Extensive cross-language tooling support needs to bridge decl names between two different languages more freely. This SourceKit request is designed to translate Objc names to Swift names and vice versa. Working similarly to cursor-info requisition, the name translation request requires a Swift reference to a Swift/Clang decl, and the preferred name to translate from, and language kind that the given name belongs to. If the translation succeeds, SourceKit service responds with the corresponding name than belongs to the other kind of language.
Newly introduced keys:
“key.namekind": “source.lang.name.kind.objc” | "source.lang.name.kind.swift"
“key.basename”: “name"
“key.argnames”: [“name"]
“key.selectorpieces”: [“name[:]"]
This commit only implements translation from Objc to Swift.
We can also avoid walking the members of said protocols in the
archetype builder and when looking for nested types, because of course
there are no associated types in imported Objective-C protocols.
The AST verifier is unhappy when an accessor's imported name gets
selector-split but its parameters don't have that recorded. Although
we're not using this for anything today, it seems best to keep the
two in sync.
rdar://problem/29889051
Previously it wouldn't run the verifier again if no new modules were
imported, even if more decls had been loaded since last time. This
likely only affects script-mode files (main.swift-like).
...and avoid making aliases from one unavailable declaration to another.
If it's unavailable, we can just import it as a normal case and not
worry about it. This fixes an issue where Sema would try to diagnose
the body of an "alias" for referring to unavailable declarations.
(Background: enum cases in Swift have to have unique values, so we
import any duplicate values as static properties. Pattern matching
logic has a hack to recognize these particular static properties as
being "case-like".)
This commit also sinks enum element uniqueness checking into importing
the enum, instead of keeping a global map we never consult again. This
should save a small bit of memory.
rdar://problem/30025723
We're trying to get rid of implicit bridging-header imports, as a feature.
These are IMPORTED_HEADER blocks left in modules built with bridging
headers, that trigger re-importing the bridging header into any client
that imports the module.
As a half-way measure to deprecating them, we add a warning here that
triggers when an implicit bridging-header import occurs that is _not_
suppressed as redundant by clang.
The typedef `swift::Module` was a temporary solution that allowed
`swift::Module` to be renamed to `swift::ModuleDecl` without requiring
every single callsite to be modified.
Modify all the callsites, and get rid of the typedef.
There's really not that much code shared between the accessor and
non-accessor cases in importMethodType, so split them up.
The one change here is that previously a method could /think/ it was
an accessor, but not be treated as one if the property decl has a
different getter or setter. Now such a method is just dropped by the
importer completely. It's intended that this is not a behavioral
change in that no real code should have such an AST.
This is building towards always having a consistent type for property
setters added in handlePropertyRedeclaration, which is
rdar://problem/29422993.
Once upon a time this was agnostic of the declaration being imported
(and possibly even still merged with importFunctionType) but that
hasn't been true for a while. If we're passing the ObjCMethodDecl
and ImportedName anyway, we don't need to separately pass the result
type, whether it's noreturn, and the Swift name as separate arguments.
No intended functionality change.
Remove all occurrences of a "useSwift2Name" bool, and replace it with
version plumbing. This means that ImportDecl is now entirely
version-based, and the importer Impl knows versions. This will be
needed for marking Swift 3 names as deprecated, when there is a new
Swift 4 name.
NFC.
Rather than use importName using a set of options of what to choose,
phrase the API in terms of language version. Be explicit about what
version is being requested at the call site, as it's a necessary
consideration for the client.
Previously, for an Objective-C class method declaration that could be
imported as init, we were making 4 decls:
1) The Swift 2 init
2) The Swift 2 class method decl (suppressing init formation)
3) The Swift 3 init (omitting needless words)
4) The Swift 3 class method decl (suppressing init formation and
omitting needless words)
Decls 1), 2), and 4) exist for diagnostics and redirect the user at
3). But, 4) does not correspond to any actual Swift version name and
producing it correctly would require the user to understand how
omit-needless-words and other importer magic operates. It provides
very limited value and more importantly gets in the way of future
Clang importer refactoring. We’d like to turn Decl importing into
something that is simpler and language-version parameterized, but
there is no real Swift version to correspond to decl 4).
Therefore we will be making the following decls:
1) The "raw" decl, the name as it would appear to the user if they
copy-pasted Objective-C code
2) The name as it appeared in Swift 2 (which could be an init)
3) The name as it appeared in Swift 3 (which could be an init and omit
needless words)
This aligns with the language versions we want to import as in the
future: raw, swift2, swift3, …, and current.
Note that swift-ide-test prunes decls that are unavailable in the
current Swift version, so the Swift 2 non-init decls are not printed
out, though they are still present. Tests were updated and expanded to
ensure this was still the case.
ImportDecl has an alternate decl quasi-escape-hatch where it can
create alternative declarations for the same original Clang node. But,
it was limited at one, which worked accidentally in the case of
VisitObjCMethodDecl's attempts at importing a factory-init-suppressed
root-class method that points to the imported-as-init Swift
declaration.
This commit changes that to a TinyPtrVector, to support the upcoming
occasional case where we have more.
Drop the ImportNameSwiftContext, which was merely used to pass around
some global state. Instead, pass the relevant parts
directly. Additionally, remove the 2-phase initialization of a
NameImporter from the module writers, as they are only invoked once
per Clang instance anyways, we can hold a local instance. Also
streamlines some APIs.
NFC
During normal import, the name for a foreign entity may be requested
many times. As we have more and more complex logic to compute these
new names, the overhead of potential re-computations adds up. This
cache is hit about 1/3rd of the time when running a simple
CoreGraphics test case.
NFC
Now that we have per-Clang-instance NameImporters, we can drop the
2-phase initialization that was internally present in
NameImporter. This lets NameImporter host the EnumInfoCache directly,
and streamlines the APIs.
NFC
Banish the abomination that is clangSemaOverride, a previously
necessary evil. When building the module caches, different Clang
instances will be spawned than the one used by the normal
importer. Since we want to reuse code and get the same name both ways,
this meant threading through alternative clang Semas and preprocessors
throughtout, some of the time. This broke the abstraction and
encapsulation of the Impl, complicated the programming model, and
otherwise made effective caching hard.
Now that we’ve done enough ImportName refactoring, we can create a
NameImporter per Clang instance, and encapsulate naming therein. We
can now remove the sema overrides, as we have already done to the
preprocessor overrides.
This shifts the 2-phase initialization problem to the Impl and the
Clang module writers.
NFC
Delay initialization of the EnumInfoCache until a Clang instance is
ready, simplifying its interface and allowing us to finally make this
per-Clang-instance. This will allow us to further de-couple ImportName
from the importer imply, as well as allow us to use a more efficient
and simpler caching mechanism. It is now owned by the NameImporter.
NFC.
SwiftNameLookupExtension and ClangImporter::Implementation were
friends, but as time goes on they have drifted apart. As part of the
ImportName refactoring, these are being decoupled to facilitate
multiple-name importing, and fight the existing false encapsulation
present in the Impl.
SwiftNameLookupExtension is now spun off into its own entity, and can
evolve to have and use its own de-coupled NameImporter.
Finally, SwiftNameLookupExtension no longer stors a reference to
ClangImporter::Implementation, a false encapsulation. Instead, it uses
a NameImporter of its own, and merely keeps a reference to the lookup
table map.
Future directions include making the NameImporter specific to a Clang
instance, meaning that we can effectively cache Clang entities better
(and not resort to EnumInfoCache's stringly keyed caches). We can also
then drop all notions of a "ClangOverride" and other messy phase
entanglement.
NFC
Change more methods on the Impl to be static, passing down an
ASTContext if necessary. While this does ugly up the functions
slightly with the extra parameter, it decouples them from the Impl,
which has been a false abstraction when building the lookup
tables. These can all be moved to a more appropriate place in the
future.
NFC
addEntryToLookupTable is one of the laggards holding back the
Impl-free Clang lookup table effort. Make a static variant, now that
we have the convenient NameImporter.
NFC
Name Importer wraps references to the Swift context and other needed
encapsulation. The eventual goal is to allow name lookup tables to
live separately from the Impl, and do better Clang-instance-based
caching in the future, as well as general separation of concerns.
NFC
Pull omitNeedlessWordsInFunctionName off of the Impl, and into a
static function local to ImportName.cpp. Separate it out from the Impl
entirely. Though this adds a couple of extra ugly parameters, it's one
of the last bits of tie-in between importFullName and the Impl.
By refactoring out PlatformAvailability from the ClangImporter, we can
more easily refactor out isUnavailableInSwift from the impl, which
will free us up to do more flexible import naming.
Introduces new files ClangAdapter.h/cpp, which will serve as a
convenient place to put code reasoning about Clang details. Refactors
out most Clang-related is*, has*, and get* methods from the
ImporterImpl. In the future, an adapter class could help serve to
seperate the concerns of the importer from the details of how to
correctly use Clang APIs.