Skip to content

Commit c2bf16c

Browse files
committed
Clang importer: start building a Swift name -> Clang declarations table.
When we parse a bridging header, start building a mapping from Swift names (both base names and full names) to the Clang declarations that have those names in particular Clang contexts. For now, just provide the ability to build the table (barely) and dump it out; we'll grow it's contents in time.
1 parent f44f4a5 commit c2bf16c

File tree

10 files changed

+350
-3
lines changed

10 files changed

+350
-3
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ class ClangImporter final : public ClangModuleLoader {
259259
// Print statistics from the Clang AST reader.
260260
void printStatistics() const override;
261261

262+
/// Dump Swift lookup tables.
263+
void dumpSwiftLookupTables();
264+
262265
/// Given the path of a Clang module, collect the names of all its submodules
263266
/// and their corresponding visibility. Calling this function does not load the
264267
/// module.

include/swift/ClangImporter/ClangImporterOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ class ClangImporterOptions {
7373
// If true, infer default arguments for nullable pointers (nil) and
7474
// option sets ([]).
7575
bool InferDefaultArguments = false;
76+
77+
/// If true, we should use the Swift name lookup tables rather than
78+
/// Clang's name lookup facilities.
79+
bool UseSwiftLookupTables = false;
7680
};
7781

7882
} // end namespace swift

lib/ClangImporter/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_swift_library(swiftClangImporter
1414
ImportDecl.cpp
1515
ImportMacro.cpp
1616
ImportType.cpp
17+
SwiftLookupTable.cpp
1718
LINK_LIBRARIES
1819
swiftAST
1920
)

lib/ClangImporter/ClangImporter.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,18 @@ bool ClangImporter::Implementation::importHeader(
736736

737737
clang::Parser::DeclGroupPtrTy parsed;
738738
while (!Parser->ParseTopLevelDecl(parsed)) {
739-
if (trackParsedSymbols && parsed) {
739+
if (parsed && (trackParsedSymbols || UseSwiftLookupTables)) {
740740
for (auto *D : parsed.get()) {
741-
addBridgeHeaderTopLevelDecls(D);
741+
if (trackParsedSymbols)
742+
addBridgeHeaderTopLevelDecls(D);
743+
744+
if (UseSwiftLookupTables) {
745+
if (auto named = dyn_cast<clang::NamedDecl>(D)) {
746+
Identifier name = importName(named);
747+
if (!name.empty())
748+
BridgingHeaderLookupTable.addEntry(name, named);
749+
}
750+
}
742751
}
743752
}
744753
}
@@ -1021,7 +1030,8 @@ ClangImporter::Implementation::Implementation(ASTContext &ctx,
10211030
InferImplicitProperties(opts.InferImplicitProperties),
10221031
ImportForwardDeclarations(opts.ImportForwardDeclarations),
10231032
OmitNeedlessWords(opts.OmitNeedlessWords),
1024-
InferDefaultArguments(opts.InferDefaultArguments)
1033+
InferDefaultArguments(opts.InferDefaultArguments),
1034+
UseSwiftLookupTables(opts.UseSwiftLookupTables)
10251035
{
10261036
// Add filters to determine if a Clang availability attribute
10271037
// applies in Swift, and if so, what is the cutoff for deprecated
@@ -3306,3 +3316,11 @@ void ClangImporter::getMangledName(raw_ostream &os,
33063316

33073317
Impl.Mangler->mangleName(clangDecl, os);
33083318
}
3319+
3320+
void ClangImporter::dumpSwiftLookupTables() {
3321+
Impl.dumpSwiftLookupTables();
3322+
}
3323+
3324+
void ClangImporter::Implementation::dumpSwiftLookupTables() {
3325+
BridgingHeaderLookupTable.dump();
3326+
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_CLANG_IMPORTER_IMPL_H
1818
#define SWIFT_CLANG_IMPORTER_IMPL_H
1919

20+
#include "SwiftLookupTable.h"
2021
#include "swift/ClangImporter/ClangImporter.h"
2122
#include "swift/AST/ASTContext.h"
2223
#include "swift/AST/LazyResolver.h"
@@ -251,6 +252,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
251252
const bool ImportForwardDeclarations;
252253
const bool OmitNeedlessWords;
253254
const bool InferDefaultArguments;
255+
const bool UseSwiftLookupTables;
254256

255257
constexpr static const char * const moduleImportBufferName =
256258
"<swift-imported-modules>";
@@ -289,6 +291,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
289291
/// if type checking has begun.
290292
llvm::PointerIntPair<LazyResolver *, 1, bool> typeResolver;
291293

294+
/// The Swift lookup table for the bridging header.
295+
SwiftLookupTable BridgingHeaderLookupTable;
296+
292297
public:
293298
/// \brief Mapping of already-imported declarations.
294299
llvm::DenseMap<const clang::Decl *, Decl *> ImportedDecls;
@@ -1177,6 +1182,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
11771182
ASD->setSetterAccessibility(Accessibility::Public);
11781183
return D;
11791184
}
1185+
1186+
/// Dump the Swift-specific name lookup tables we generate.
1187+
void dumpSwiftLookupTables();
11801188
};
11811189

11821190
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
//===--- SwiftLookupTable.cpp - Swift Lookup Table ------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements support for Swift name lookup tables stored in Clang
14+
// modules.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
#include "SwiftLookupTable.h"
18+
#include "swift/Basic/STLExtras.h"
19+
#include "clang/AST/DeclObjC.h"
20+
using namespace swift;
21+
22+
bool SwiftLookupTable::matchesContext(clang::DeclContext *foundContext,
23+
clang::DeclContext *requestedContext) {
24+
/// If the requested context was null, we match.
25+
if (!requestedContext)
26+
return true;
27+
28+
// If the contexts match, we match.
29+
if (foundContext == requestedContext)
30+
return true;
31+
32+
// If we found something in an Objective-C protocol to which a class
33+
// conforms, we match.
34+
if (auto objcProto = dyn_cast<clang::ObjCProtocolDecl>(foundContext)) {
35+
if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(requestedContext)) {
36+
return objcClass->ClassImplementsProtocol(objcProto,
37+
/*lookupCategory=*/true);
38+
}
39+
}
40+
41+
return false;
42+
}
43+
44+
void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl) {
45+
clang::DeclContext *context
46+
= decl->getDeclContext()->getRedeclContext()->getPrimaryContext();
47+
48+
// First, check whether there is already a full name entry.
49+
auto knownFull = FullNameTable.find(name);
50+
if (knownFull == FullNameTable.end()) {
51+
// We didn't have a full name entry, so record that in the base
52+
// name table.
53+
BaseNameTable[name.getBaseName()].push_back(name);
54+
55+
// Insert the entry into the full name table. We're done.
56+
FullTableEntry newEntry;
57+
newEntry.Context = context;
58+
newEntry.Decls.push_back(decl);
59+
(void)FullNameTable.insert({name, { newEntry }});
60+
return;
61+
}
62+
63+
// Check whether there is already an entry with the same context.
64+
auto &fullEntries = knownFull->second;
65+
for (auto &fullEntry : fullEntries) {
66+
if (fullEntry.Context == context) {
67+
fullEntry.Decls.push_back(decl);
68+
return;
69+
}
70+
}
71+
72+
// This is a new context for this name. Add it.
73+
FullTableEntry newEntry;
74+
newEntry.Context = context;
75+
newEntry.Decls.push_back(decl);
76+
fullEntries.push_back(newEntry);
77+
}
78+
79+
void SwiftLookupTable::dump() const {
80+
// Dump the base name -> full name mappings.
81+
SmallVector<Identifier, 4> baseNames;
82+
for (const auto &entry : BaseNameTable) {
83+
baseNames.push_back(entry.first);
84+
}
85+
std::sort(baseNames.begin(), baseNames.end(),
86+
[&](Identifier x, Identifier y) {
87+
return x.compare(y) < 0;
88+
});
89+
llvm::errs() << "Base -> full name mappings:\n";
90+
for (auto baseName : baseNames) {
91+
llvm::errs() << " " << baseName.str() << " --> ";
92+
const auto &fullNames = BaseNameTable.find(baseName)->second;
93+
interleave(fullNames.begin(), fullNames.end(),
94+
[](DeclName fullName) {
95+
llvm::errs() << fullName;
96+
},
97+
[] {
98+
llvm::errs() << ", ";
99+
});
100+
llvm::errs() << "\n";
101+
}
102+
llvm::errs() << "\n";
103+
104+
// Dump the full name -> full table entry mappings.
105+
SmallVector<DeclName, 4> fullNames;
106+
for (const auto &entry : FullNameTable) {
107+
fullNames.push_back(entry.first);
108+
}
109+
std::sort(fullNames.begin(), fullNames.end(),
110+
[](DeclName x, DeclName y) {
111+
return x.compare(y) < 0;
112+
});
113+
llvm::errs() << "Full name -> entry mappings:\n";
114+
for (auto fullName : fullNames) {
115+
llvm::errs() << " " << fullName << ":\n";
116+
const auto &fullEntries = FullNameTable.find(fullName)->second;
117+
for (const auto &fullEntry : fullEntries) {
118+
llvm::errs() << " ";
119+
if (fullEntry.Context->isTranslationUnit()) {
120+
llvm::errs() << "TU";
121+
} else if (auto named = dyn_cast<clang::NamedDecl>(fullEntry.Context)) {
122+
named->printName(llvm::errs());
123+
llvm::errs();
124+
} else {
125+
llvm::errs() << "<unknown>";
126+
}
127+
llvm::errs() << ": ";
128+
129+
interleave(fullEntry.Decls.begin(), fullEntry.Decls.end(),
130+
[](clang::NamedDecl *decl) {
131+
decl->printName(llvm::errs());
132+
},
133+
[] {
134+
llvm::errs() << ", ";
135+
});
136+
llvm::errs() << "\n";
137+
}
138+
}
139+
}

lib/ClangImporter/SwiftLookupTable.h

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===--- SwiftLookupTable.h - Swift Lookup Table ----------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements support for Swift name lookup tables stored in Clang
14+
// modules.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
#ifndef SWIFT_CLANGIMPORTER_SWIFTLOOKUPTABLE_H
18+
#define SWIFT_CLANGIMPORTER_SWIFTLOOKUPTABLE_H
19+
20+
#include "swift/Basic/LLVM.h"
21+
#include "swift/AST/Identifier.h"
22+
#include "llvm/ADT/DenseMap.h"
23+
#include "llvm/ADT/SmallVector.h"
24+
#include "llvm/ADT/TinyPtrVector.h"
25+
26+
namespace clang {
27+
class NamedDecl;
28+
class DeclContext;
29+
}
30+
31+
namespace swift {
32+
33+
/// A lookup table that maps Swift names to the set of Clang
34+
/// declarations with that particular name.
35+
///
36+
/// The names of C entities can undergo significant transformations
37+
/// when they are mapped into Swift, which makes Clang's name lookup
38+
/// mechanisms useless when searching for the Swift name of
39+
/// entities. This lookup table provides efficient access to the C
40+
/// entities based on their Swift names, and is used by the Clang
41+
/// importer to satisfy the Swift compiler's queries.
42+
class SwiftLookupTable {
43+
/// An entry in the table of C entities indexed by full Swift name.
44+
struct FullTableEntry {
45+
/// The context in which the entities with the given name occur, e.g.,
46+
/// a class, struct, translation unit, etc.
47+
///
48+
/// Many Clang DeclContexts can have redeclarations, so this entry
49+
/// is always the canonical DeclContext for the entity.
50+
clang::DeclContext *Context;
51+
52+
/// The set of Clang declarations with this name and in this
53+
/// context.
54+
llvm::TinyPtrVector<clang::NamedDecl *> Decls;
55+
};
56+
57+
/// A table mapping from the full name of Swift entities to all of
58+
/// the C entities that have that name, in all contexts.
59+
llvm::DenseMap<DeclName, SmallVector<FullTableEntry, 2>> FullNameTable;
60+
61+
/// A table mapping from the base name of a Swift name to all of the
62+
/// full Swift names based on that identifier.
63+
llvm::DenseMap<Identifier, SmallVector<DeclName, 2>> BaseNameTable;
64+
65+
/// Determine whether the given context we found matches the
66+
/// requested context.
67+
bool matchesContext(clang::DeclContext *foundContext,
68+
clang::DeclContext *requestedContext);
69+
public:
70+
/// Add an entry to the lookup table.
71+
///
72+
/// \param name The Swift name of the entry.
73+
/// \param decl The Clang declaration to add.
74+
void addEntry(DeclName name, clang::NamedDecl *decl);
75+
76+
/// Lookup the set of declarations with the given base name.
77+
///
78+
/// \param baseName The base name to search for. All results will
79+
/// have this base name.
80+
///
81+
/// \param context The context in which the resulting set of
82+
/// declarations should reside. This may be null to indicate that
83+
/// all results from all contexts should be produced.
84+
ArrayRef<clang::NamedDecl *>
85+
lookup(Identifier baseName,
86+
clang::DeclContext *context,
87+
SmallVectorImpl<clang::NamedDecl *> &scratch);
88+
89+
/// Lookup the set of declarations with the given full name.
90+
///
91+
/// \param name The full name to search for. All results will have
92+
/// this full name.
93+
///
94+
/// \param context The context in which the resulting set of
95+
/// declarations should reside. This may be null to indicate that
96+
/// all results from all contexts should be produced.
97+
ArrayRef<clang::NamedDecl *>
98+
lookup(DeclName name,
99+
clang::DeclContext *context,
100+
SmallVectorImpl<clang::NamedDecl *> &scratch);
101+
102+
/// Dump the internal representation of this lookup table.
103+
void dump() const;
104+
};
105+
106+
}
107+
108+
#endif // SWIFT_CLANGIMPORTER_SWIFTLOOKUPTABLE_H

test/IDE/Inputs/swift_name.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#define SWIFT_NAME(X) __attribute__((swift_name(#X)))
2+
3+
int SNFoo SWIFT_NAME(Bar);
4+
5+
struct SWIFT_NAME(SomeStruct) SNSomeStruct {
6+
double X SWIFT_NAME(x);
7+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-ide-test -dump-importer-lookup-table -source-filename %s -import-objc-header %S/Inputs/swift_name.h > %t.log 2>&1
2+
// RUN: FileCheck %s < %t.log
3+
4+
// CHECK: Base -> full name mappings:
5+
// CHECK-NEXT: Bar --> Bar
6+
// CHECK-NEXT: SomeStruct --> SomeStruct
7+
8+
// CHECK: Full name -> entry mappings:
9+
// CHECK-NEXT: Bar:
10+
// CHECK-NEXT: TU: SNFoo
11+
// CHECK-NEXT: SomeStruct:
12+
// CHECK-NEXT: TU: SNSomeStruct

0 commit comments

Comments
 (0)