Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Runtimes/Overlay/Windows/clang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ roots:
- name: module.modulemap
type: file
external-contents: "@CMAKE_CURRENT_SOURCE_DIR@/winsdk_um.modulemap"
- name: WinSDK.apinotes
type: file
external-contents: "@CMAKE_CURRENT_SOURCE_DIR@/WinSDK.apinotes"
- name: "@WindowsSdkDir@/Include/@WindowsSDKVersion@/shared"
type: directory
contents:
Expand Down Expand Up @@ -51,6 +54,7 @@ install(TARGETS ClangModules
EXPORT SwiftOverlayTargets)
install(FILES
ucrt.modulemap
WinSDK.apinotes
vcruntime.apinotes
vcruntime.modulemap
winsdk_um.modulemap
Expand Down
1 change: 1 addition & 0 deletions Runtimes/Resync.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ message(STATUS "Windows modulemaps[${StdlibSources}/Platform] -> ${CMAKE_CURRENT
copy_files(public/Platform Overlay/Windows/clang
FILES
ucrt.modulemap
WinSDK.apinotes
winsdk_um.modulemap
winsdk_shared.modulemap
vcruntime.modulemap
Expand Down
4 changes: 2 additions & 2 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3731,7 +3731,7 @@ void ClangImporter::lookupBridgingHeaderDecls(
if (filter(macroNode)) {
auto MI = macroNode.getAsMacro();
Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
if (Decl *imported = Impl.importMacro(Name, macroNode))
if (Decl *imported = Impl.importMacro(Name, macroNode, II))
receiver(imported);
}
}
Expand Down Expand Up @@ -3809,7 +3809,7 @@ bool ClangImporter::lookupDeclsFromHeader(StringRef Filename,
ClangNode MacroNode = Info;
if (filter(MacroNode)) {
auto Name = Impl.getNameImporter().importMacroName(II, Info);
if (auto *Imported = Impl.importMacro(Name, MacroNode))
if (auto *Imported = Impl.importMacro(Name, MacroNode, II))
receiver(Imported);
}
});
Expand Down
8 changes: 8 additions & 0 deletions lib/ClangImporter/ClangIncludePaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,14 @@ void GetWindowsFileMappings(
fileMapping.redirectedFiles.emplace_back(std::string(WinSDKInjection),
AuxiliaryFile);

llvm::sys::path::remove_filename(WinSDKInjection);
llvm::sys::path::append(WinSDKInjection, "WinSDK.apinotes");
AuxiliaryFile = GetPlatformAuxiliaryFile("windows", "WinSDK.apinotes",
VFS, SearchPathOpts);
if (!AuxiliaryFile.empty())
fileMapping.redirectedFiles.emplace_back(std::string(WinSDKInjection),
AuxiliaryFile);

llvm::sys::path::remove_filename(WinSDKInjection);
llvm::sys::path::remove_filename(WinSDKInjection);
llvm::sys::path::append(WinSDKInjection, "shared", "module.modulemap");
Expand Down
122 changes: 107 additions & 15 deletions lib/ClangImporter/ImportMacro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "ImporterImpl.h"
#include "SwiftDeclSynthesizer.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Attr.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/AST/Expr.h"
#include "swift/AST/ParameterList.h"
Expand All @@ -40,6 +41,40 @@
using namespace swift;
using namespace importer;

static Type importMacroTypeOverride(ClangImporter::Implementation &Impl,
DeclContext *DC,
const clang::IdentifierInfo *II,
const clang::MacroInfo *macro,
ClangNode ClangN) {
if (!II)
return Type();

clang::Sema &S = Impl.getClangSema();
auto Info = S.ProcessAPINotes(ClangN.getOwningClangModule(), II,
macro->getDefinitionLoc());
if (!Info || Info->getType().empty())
return Type();

if (!S.ParseTypeFromStringCallback)
return Type();

// Resolve the APINotes 'Type:' annotation. Parsing the C type string is left
// to Clang's parser (via ParseTypeFromStringCallback); we only trigger it.
auto Ty = S.ParseTypeFromStringCallback(Info->getType(), "<API Notes>",
macro->getDefinitionLoc());
if (!Ty.isUsable())
return Type();

clang::QualType QualTy = clang::Sema::GetTypeFromParser(Ty.get());
if (QualTy.isNull())
return Type();

return Impl.importTypeIgnoreIUO(
QualTy, ImportTypeKind::Value,
ImportDiagnosticAdder(Impl, macro, macro->getDefinitionLoc()),
isInSystemModule(DC), Bridgeability::None, ImportTypeAttrs());
}

template <typename T = clang::Expr>
static const T *
parseNumericLiteral(ClangImporter::Implementation &impl,
Expand All @@ -61,16 +96,32 @@ getTokenSpelling(ClangImporter::Implementation &impl, const clang::Token &tok) {
return tokenSpelling;
}

static bool applyCUnsignedIntegerCastExpr(llvm::APSInt &Value,
clang::QualType Ty,
const clang::ASTContext &C) {
if (Ty.isNull() || !Ty->isIntegerType() || Ty->isBooleanType() ||
!Ty->isUnsignedIntegerOrEnumerationType())
return false;

Value = Value.extOrTrunc(C.getIntWidth(Ty));
Value.setIsUnsigned(true);
return true;
}

static ValueDecl *
createMacroConstant(ClangImporter::Implementation &Impl,
const clang::MacroInfo *macro,
const clang::IdentifierInfo *II,
Identifier name,
DeclContext *dc,
Type type,
const clang::APValue &value,
ConstantConvertKind convertKind,
bool isStatic,
ClangNode ClangN) {
if (Type T = importMacroTypeOverride(Impl, dc, II, macro, ClangN))
type = T;

Impl.ImportedMacroConstants[macro] = {value, type};
return SwiftDeclSynthesizer(Impl).createConstant(name, dc, type, value,
convertKind, isStatic,
Expand All @@ -80,6 +131,7 @@ createMacroConstant(ClangImporter::Implementation &Impl,
static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
DeclContext *DC,
const clang::MacroInfo *MI,
const clang::IdentifierInfo *II,
Identifier name,
const clang::Token *signTok,
const clang::Token &tok,
Expand Down Expand Up @@ -139,6 +191,8 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
value.flipAllBits();
}
}
applyCUnsignedIntegerCastExpr(value, castType,
Impl.getClangASTContext());

// Make sure the destination type actually conforms to the builtin literal
// protocol or is Bool before attempting to import, otherwise we'll crash
Expand All @@ -151,7 +205,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
!ctx.getIntBuiltinInitDecl(constantTyNominal)) {
return nullptr;
}
return createMacroConstant(Impl, MI, name, DC, constantType,
return createMacroConstant(Impl, MI, II, name, DC, constantType,
clang::APValue(value),
ConstantConvertKind::None,
/*static*/ false, ClangN);
Expand Down Expand Up @@ -179,7 +233,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
if (!ctx.getFloatBuiltinInitDecl(constantTyNominal))
return nullptr;

return createMacroConstant(Impl, MI, name, DC, constantType,
return createMacroConstant(Impl, MI, II, name, DC, constantType,
clang::APValue(value),
ConstantConvertKind::None,
/*static*/ false, ClangN);
Expand Down Expand Up @@ -235,14 +289,16 @@ static ValueDecl *importStringLiteral(ClangImporter::Implementation &Impl,
static ValueDecl *importLiteral(ClangImporter::Implementation &Impl,
DeclContext *DC,
const clang::MacroInfo *MI,
const clang::IdentifierInfo *II,
Identifier name,
const clang::Token &tok,
ClangNode ClangN,
clang::QualType castType) {
switch (tok.getKind()) {
case clang::tok::numeric_constant: {
ValueDecl *importedNumericLiteral = importNumericLiteral(
Impl, DC, MI, name, /*signTok*/ nullptr, tok, ClangN, castType);
Impl, DC, MI, II, name, /*signTok*/ nullptr, tok, ClangN,
castType);
if (!importedNumericLiteral) {
Impl.addImportDiagnostic(
&tok, Diagnostic(diag::macro_not_imported_invalid_numeric_literal),
Expand Down Expand Up @@ -382,7 +438,7 @@ getIntegerConstantForMacroToken(ClangImporter::Implementation &impl,
macroNode = moduleMacro;
}
auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo);
(void)impl.importMacro(importedID, macroNode);
(void)impl.importMacro(importedID, macroNode, rawID);

auto searcher = impl.ImportedMacroConstants.find(macroInfo);
if (searcher == impl.ImportedMacroConstants.end()) {
Expand Down Expand Up @@ -502,6 +558,7 @@ ValueDecl *importDeclAlias(ClangImporter::Implementation &clang,
static ValueDecl *importMacro(ClangImporter::Implementation &impl,
llvm::SmallSet<StringRef, 4> &visitedMacros,
DeclContext *DC, Identifier name,
const clang::IdentifierInfo *II,
const clang::MacroInfo *macro, ClangNode ClangN,
clang::QualType castType) {
if (name.empty()) return nullptr;
Expand Down Expand Up @@ -598,7 +655,8 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,

// If it's a literal token, we might be able to translate the literal.
if (tok.isLiteral()) {
return importLiteral(impl, DC, macro, name, tok, ClangN, castType);
return importLiteral(impl, DC, macro, II, name, tok, ClangN,
castType);
}

if (tok.is(clang::tok::identifier)) {
Expand Down Expand Up @@ -632,8 +690,8 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,

// FIXME: This was clearly intended to pass the cast type down, but
// doing so would be a behavior change.
return importMacro(impl, visitedMacros, DC, name, macroID, ClangN,
/*castType*/ {});
return importMacro(impl, visitedMacros, DC, name, II, macroID,
ClangN, /*castType*/ {});
}
}

Expand Down Expand Up @@ -662,7 +720,7 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,

if (isSignToken(first) && second.is(clang::tok::numeric_constant)) {
ValueDecl *importedNumericLiteral = importNumericLiteral(
impl, DC, macro, name, &first, second, ClangN, castType);
impl, DC, macro, II, name, &first, second, ClangN, castType);
if (!importedNumericLiteral) {
impl.addImportDiagnostic(
macro, Diagnostic(diag::macro_not_imported, name.str()),
Expand Down Expand Up @@ -861,7 +919,18 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
return nullptr;
}

return createMacroConstant(impl, macro, name, DC, resultSwiftType,
if (applyCUnsignedIntegerCastExpr(resultValue, castType,
impl.getClangASTContext())) {
resultSwiftType = impl.importTypeIgnoreIUO(
castType, ImportTypeKind::Value,
ImportDiagnosticAdder(impl, macro, macro->getDefinitionLoc()),
isInSystemModule(DC), Bridgeability::None, ImportTypeAttrs());
if (!resultSwiftType)
return nullptr;
}

return createMacroConstant(impl, macro, II, name, DC,
resultSwiftType,
clang::APValue(resultValue),
ConstantConvertKind::None,
/*isStatic=*/false, ClangN);
Expand Down Expand Up @@ -905,12 +974,20 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
return nullptr;
}

ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
ClangNode macroNode) {
ValueDecl *ClangImporter::Implementation::importMacro(
Identifier name, ClangNode macroNode,
const clang::IdentifierInfo *II) {
const clang::MacroInfo *macro = macroNode.getAsMacro();
if (!macro)
return nullptr;

if (!II) {
if (const auto *M = macroNode.getAsModuleMacro())
II = M->getName();
else
II = getClangPreprocessor().getIdentifierInfo(name.str());
}

PrettyStackTraceStringAction stackRAII{"importing macro", name.str()};

// Look for macros imported with the same name.
Expand Down Expand Up @@ -949,19 +1026,20 @@ ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
// result.

DeclContext *DC;
if (const clang::Module *module =
importer::getClangOwningModule(macroNode, getClangASTContext())) {
const clang::Module *Module =
importer::getClangOwningModule(macroNode, getClangASTContext());
if (Module) {
// Get the parent module because currently we don't model Clang submodules
// in Swift.
DC = getWrapperForModule(module->getTopLevelModule());
DC = getWrapperForModule(Module->getTopLevelModule());
} else {
DC = ImportedHeaderUnit;
}

llvm::SmallSet<StringRef, 4> visitedMacros;
visitedMacros.insert(name.str());
auto valueDecl =
::importMacro(*this, visitedMacros, DC, name, macro, macroNode,
::importMacro(*this, visitedMacros, DC, name, II, macro, macroNode,
/*castType*/ {});

// Update the entry for the value we just imported.
Expand All @@ -976,6 +1054,20 @@ ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
assert(entryIter != llvm::reverse(ImportedMacros[name]).end() &&
"placeholder not found");
entryIter->second = valueDecl;

// If APINotes renamed this macro and we imported it under its original C
// name, mark this declaration as unavailable and redirect to the Swift
// name, mirroring how renamed Clang declarations are imported. The Swift
// name is whatever importMacroName resolves for the original identifier; if
// it differs from the name we imported under, this is the renamed-from C
// name.
Identifier imported = getNameImporter().importMacroName(II, macro, Module);
if (!imported.empty() && imported != name) {
ASTContext &AST = valueDecl->getASTContext();
valueDecl->addAttribute(AvailableAttr::createUnavailableInSwift(
AST, /*Message=*/StringRef(),
/*Rename=*/AST.AllocateCopy(imported.str())));
}
}

return valueDecl;
Expand Down
24 changes: 17 additions & 7 deletions lib/ClangImporter/ImportName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2540,16 +2540,26 @@ Identifier ImportedName::getBaseIdentifier(ASTContext &ctx) const {
}

Identifier
NameImporter::importMacroName(const clang::IdentifierInfo *clangIdentifier,
const clang::MacroInfo *macro) {
NameImporter::importMacroName(const clang::IdentifierInfo *II,
const clang::MacroInfo *MI,
const clang::Module *M) {
// If we're supposed to ignore this macro, return an empty identifier.
if (::shouldIgnoreMacro(clangIdentifier->getName(), macro,
getClangPreprocessor()))
if (::shouldIgnoreMacro(II->getName(), MI, getClangPreprocessor()))
return Identifier();

// No transformation is applied to the name.
StringRef name = clangIdentifier->getName();
return swiftCtx.getIdentifier(name);
// Honor an APINotes 'SwiftName:' override, if one applies. A macro constant
// can only be renamed to a simple identifier, so reject function, operator,
// and member names, which are meaningless here.
if (auto notes = getClangSema().ProcessAPINotes(M, II, MI->getDefinitionLoc())) {
if (!notes->SwiftName.empty()) {
ParsedDeclName ident = parseDeclName(notes->SwiftName);
if (ident && !ident.isOperator() && !ident.IsFunctionName && !ident.isMember())
return swiftCtx.getIdentifier(ident.BaseName);
}
}

// Otherwise, no transformation is applied to the name.
return swiftCtx.getIdentifier(II->getName());
}

ImportedName NameImporter::importName(const clang::NamedDecl *decl,
Expand Down
9 changes: 7 additions & 2 deletions lib/ClangImporter/ImportName.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,13 @@ class NameImporter {
llvm::function_ref<bool(ImportedName, ImportNameVersion)> action);

/// Imports the name of the given Clang macro into Swift.
Identifier importMacroName(const clang::IdentifierInfo *clangIdentifier,
const clang::MacroInfo *macro);
///
/// If APINotes provides a 'SwiftName:' for the macro, that name is used;
/// \p M allows module APINotes sidecars to be consulted in addition to
/// location-based notes.
Identifier importMacroName(const clang::IdentifierInfo *II,
const clang::MacroInfo *MI,
const clang::Module *M = nullptr);

ASTContext &getContext() { return swiftCtx; }
const LangOptions &getLangOpts() const { return swiftCtx.LangOpts; }
Expand Down
3 changes: 2 additions & 1 deletion lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
///
/// \returns The imported declaration, or null if the macro could not be
/// translated into Swift.
ValueDecl *importMacro(Identifier name, ClangNode macroNode);
ValueDecl *importMacro(Identifier name, ClangNode macroNode,
const clang::IdentifierInfo *II = nullptr);

/// Map a Clang identifier name to its imported Swift equivalent.
StringRef getSwiftNameFromClangName(StringRef name);
Expand Down
Loading