forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
1 parent
f44f4a5
commit c2bf16c
Showing
10 changed files
with
350 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
//===--- SwiftLookupTable.cpp - Swift Lookup Table ------------------------===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See http://swift.org/LICENSE.txt for license information | ||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file implements support for Swift name lookup tables stored in Clang | ||
// modules. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#include "SwiftLookupTable.h" | ||
#include "swift/Basic/STLExtras.h" | ||
#include "clang/AST/DeclObjC.h" | ||
using namespace swift; | ||
|
||
bool SwiftLookupTable::matchesContext(clang::DeclContext *foundContext, | ||
clang::DeclContext *requestedContext) { | ||
/// If the requested context was null, we match. | ||
if (!requestedContext) | ||
return true; | ||
|
||
// If the contexts match, we match. | ||
if (foundContext == requestedContext) | ||
return true; | ||
|
||
// If we found something in an Objective-C protocol to which a class | ||
// conforms, we match. | ||
if (auto objcProto = dyn_cast<clang::ObjCProtocolDecl>(foundContext)) { | ||
if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(requestedContext)) { | ||
return objcClass->ClassImplementsProtocol(objcProto, | ||
/*lookupCategory=*/true); | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl) { | ||
clang::DeclContext *context | ||
= decl->getDeclContext()->getRedeclContext()->getPrimaryContext(); | ||
|
||
// First, check whether there is already a full name entry. | ||
auto knownFull = FullNameTable.find(name); | ||
if (knownFull == FullNameTable.end()) { | ||
// We didn't have a full name entry, so record that in the base | ||
// name table. | ||
BaseNameTable[name.getBaseName()].push_back(name); | ||
|
||
// Insert the entry into the full name table. We're done. | ||
FullTableEntry newEntry; | ||
newEntry.Context = context; | ||
newEntry.Decls.push_back(decl); | ||
(void)FullNameTable.insert({name, { newEntry }}); | ||
return; | ||
} | ||
|
||
// Check whether there is already an entry with the same context. | ||
auto &fullEntries = knownFull->second; | ||
for (auto &fullEntry : fullEntries) { | ||
if (fullEntry.Context == context) { | ||
fullEntry.Decls.push_back(decl); | ||
return; | ||
} | ||
} | ||
|
||
// This is a new context for this name. Add it. | ||
FullTableEntry newEntry; | ||
newEntry.Context = context; | ||
newEntry.Decls.push_back(decl); | ||
fullEntries.push_back(newEntry); | ||
} | ||
|
||
void SwiftLookupTable::dump() const { | ||
// Dump the base name -> full name mappings. | ||
SmallVector<Identifier, 4> baseNames; | ||
for (const auto &entry : BaseNameTable) { | ||
baseNames.push_back(entry.first); | ||
} | ||
std::sort(baseNames.begin(), baseNames.end(), | ||
[&](Identifier x, Identifier y) { | ||
return x.compare(y) < 0; | ||
}); | ||
llvm::errs() << "Base -> full name mappings:\n"; | ||
for (auto baseName : baseNames) { | ||
llvm::errs() << " " << baseName.str() << " --> "; | ||
const auto &fullNames = BaseNameTable.find(baseName)->second; | ||
interleave(fullNames.begin(), fullNames.end(), | ||
[](DeclName fullName) { | ||
llvm::errs() << fullName; | ||
}, | ||
[] { | ||
llvm::errs() << ", "; | ||
}); | ||
llvm::errs() << "\n"; | ||
} | ||
llvm::errs() << "\n"; | ||
|
||
// Dump the full name -> full table entry mappings. | ||
SmallVector<DeclName, 4> fullNames; | ||
for (const auto &entry : FullNameTable) { | ||
fullNames.push_back(entry.first); | ||
} | ||
std::sort(fullNames.begin(), fullNames.end(), | ||
[](DeclName x, DeclName y) { | ||
return x.compare(y) < 0; | ||
}); | ||
llvm::errs() << "Full name -> entry mappings:\n"; | ||
for (auto fullName : fullNames) { | ||
llvm::errs() << " " << fullName << ":\n"; | ||
const auto &fullEntries = FullNameTable.find(fullName)->second; | ||
for (const auto &fullEntry : fullEntries) { | ||
llvm::errs() << " "; | ||
if (fullEntry.Context->isTranslationUnit()) { | ||
llvm::errs() << "TU"; | ||
} else if (auto named = dyn_cast<clang::NamedDecl>(fullEntry.Context)) { | ||
named->printName(llvm::errs()); | ||
llvm::errs(); | ||
} else { | ||
llvm::errs() << "<unknown>"; | ||
} | ||
llvm::errs() << ": "; | ||
|
||
interleave(fullEntry.Decls.begin(), fullEntry.Decls.end(), | ||
[](clang::NamedDecl *decl) { | ||
decl->printName(llvm::errs()); | ||
}, | ||
[] { | ||
llvm::errs() << ", "; | ||
}); | ||
llvm::errs() << "\n"; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
//===--- SwiftLookupTable.h - Swift Lookup Table ----------------*- C++ -*-===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See http://swift.org/LICENSE.txt for license information | ||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file implements support for Swift name lookup tables stored in Clang | ||
// modules. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#ifndef SWIFT_CLANGIMPORTER_SWIFTLOOKUPTABLE_H | ||
#define SWIFT_CLANGIMPORTER_SWIFTLOOKUPTABLE_H | ||
|
||
#include "swift/Basic/LLVM.h" | ||
#include "swift/AST/Identifier.h" | ||
#include "llvm/ADT/DenseMap.h" | ||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/ADT/TinyPtrVector.h" | ||
|
||
namespace clang { | ||
class NamedDecl; | ||
class DeclContext; | ||
} | ||
|
||
namespace swift { | ||
|
||
/// A lookup table that maps Swift names to the set of Clang | ||
/// declarations with that particular name. | ||
/// | ||
/// The names of C entities can undergo significant transformations | ||
/// when they are mapped into Swift, which makes Clang's name lookup | ||
/// mechanisms useless when searching for the Swift name of | ||
/// entities. This lookup table provides efficient access to the C | ||
/// entities based on their Swift names, and is used by the Clang | ||
/// importer to satisfy the Swift compiler's queries. | ||
class SwiftLookupTable { | ||
/// An entry in the table of C entities indexed by full Swift name. | ||
struct FullTableEntry { | ||
/// The context in which the entities with the given name occur, e.g., | ||
/// a class, struct, translation unit, etc. | ||
/// | ||
/// Many Clang DeclContexts can have redeclarations, so this entry | ||
/// is always the canonical DeclContext for the entity. | ||
clang::DeclContext *Context; | ||
|
||
/// The set of Clang declarations with this name and in this | ||
/// context. | ||
llvm::TinyPtrVector<clang::NamedDecl *> Decls; | ||
}; | ||
|
||
/// A table mapping from the full name of Swift entities to all of | ||
/// the C entities that have that name, in all contexts. | ||
llvm::DenseMap<DeclName, SmallVector<FullTableEntry, 2>> FullNameTable; | ||
|
||
/// A table mapping from the base name of a Swift name to all of the | ||
/// full Swift names based on that identifier. | ||
llvm::DenseMap<Identifier, SmallVector<DeclName, 2>> BaseNameTable; | ||
|
||
/// Determine whether the given context we found matches the | ||
/// requested context. | ||
bool matchesContext(clang::DeclContext *foundContext, | ||
clang::DeclContext *requestedContext); | ||
public: | ||
/// Add an entry to the lookup table. | ||
/// | ||
/// \param name The Swift name of the entry. | ||
/// \param decl The Clang declaration to add. | ||
void addEntry(DeclName name, clang::NamedDecl *decl); | ||
|
||
/// Lookup the set of declarations with the given base name. | ||
/// | ||
/// \param baseName The base name to search for. All results will | ||
/// have this base name. | ||
/// | ||
/// \param context The context in which the resulting set of | ||
/// declarations should reside. This may be null to indicate that | ||
/// all results from all contexts should be produced. | ||
ArrayRef<clang::NamedDecl *> | ||
lookup(Identifier baseName, | ||
clang::DeclContext *context, | ||
SmallVectorImpl<clang::NamedDecl *> &scratch); | ||
|
||
/// Lookup the set of declarations with the given full name. | ||
/// | ||
/// \param name The full name to search for. All results will have | ||
/// this full name. | ||
/// | ||
/// \param context The context in which the resulting set of | ||
/// declarations should reside. This may be null to indicate that | ||
/// all results from all contexts should be produced. | ||
ArrayRef<clang::NamedDecl *> | ||
lookup(DeclName name, | ||
clang::DeclContext *context, | ||
SmallVectorImpl<clang::NamedDecl *> &scratch); | ||
|
||
/// Dump the internal representation of this lookup table. | ||
void dump() const; | ||
}; | ||
|
||
} | ||
|
||
#endif // SWIFT_CLANGIMPORTER_SWIFTLOOKUPTABLE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#define SWIFT_NAME(X) __attribute__((swift_name(#X))) | ||
|
||
int SNFoo SWIFT_NAME(Bar); | ||
|
||
struct SWIFT_NAME(SomeStruct) SNSomeStruct { | ||
double X SWIFT_NAME(x); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// RUN: %target-swift-ide-test -dump-importer-lookup-table -source-filename %s -import-objc-header %S/Inputs/swift_name.h > %t.log 2>&1 | ||
// RUN: FileCheck %s < %t.log | ||
|
||
// CHECK: Base -> full name mappings: | ||
// CHECK-NEXT: Bar --> Bar | ||
// CHECK-NEXT: SomeStruct --> SomeStruct | ||
|
||
// CHECK: Full name -> entry mappings: | ||
// CHECK-NEXT: Bar: | ||
// CHECK-NEXT: TU: SNFoo | ||
// CHECK-NEXT: SomeStruct: | ||
// CHECK-NEXT: TU: SNSomeStruct |
Oops, something went wrong.