Skip to content

Commit 10fa705

Browse files
committed
ClangImporter: enhance the importer to alias declarations
Import simple CPP macro aliases as aliases in Swift. Extend the macro importer to import the following construct: ``` #define alias aliasee ``` as the following Swift construct: ``` @_transparent @inline(__always) var alias: type(of: aliasee) { aliasee } ``` This improves the QoI for Windows where there is a universal define (`UNICODE`) which normally is used for translating APIs between ANSI and Unicode variants, e.g.: ``` #if defined(UNICODE) #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif ```
1 parent 9753d23 commit 10fa705

File tree

5 files changed

+125
-1
lines changed

5 files changed

+125
-1
lines changed

lib/ClangImporter/ImportMacro.cpp

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTContext.h"
2121
#include "swift/AST/DiagnosticsClangImporter.h"
2222
#include "swift/AST/Expr.h"
23+
#include "swift/AST/ParameterList.h"
2324
#include "swift/AST/Stmt.h"
2425
#include "swift/AST/Types.h"
2526
#include "swift/Basic/Assertions.h"
@@ -31,6 +32,7 @@
3132
#include "clang/Lex/MacroInfo.h"
3233
#include "clang/Lex/Preprocessor.h"
3334
#include "clang/Sema/DelayedDiagnostic.h"
35+
#include "clang/Sema/Lookup.h"
3436
#include "clang/Sema/Sema.h"
3537
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
3638
#include "llvm/ADT/SmallString.h"
@@ -371,6 +373,59 @@ getIntegerConstantForMacroToken(ClangImporter::Implementation &impl,
371373
return std::nullopt;
372374
}
373375

376+
namespace {
377+
ValueDecl *importDeclAlias(ClangImporter::Implementation &clang,
378+
swift::DeclContext *DC, const clang::ValueDecl *D,
379+
Identifier alias) {
380+
swift::ValueDecl *VD =
381+
dyn_cast_or_null<ValueDecl>(clang.importDecl(D, clang.CurrentVersion));
382+
if (VD == nullptr)
383+
return nullptr;
384+
385+
ImportedType Ty =
386+
clang.importType(D->getType(), ImportTypeKind::Abstract,
387+
[&clang, &D](Diagnostic &&Diag) {
388+
clang.addImportDiagnostic(D, std::move(Diag),
389+
D->getLocation());
390+
}, /*AllowsNSUIntegerAsInt*/true,
391+
Bridgeability::None, { });
392+
swift::Type AccessorTy = FunctionType::get({}, Ty.getType(), ASTExtInfo{});
393+
swift::ASTContext &Ctx = DC->getASTContext();
394+
395+
/* Storage */
396+
swift::VarDecl *V =
397+
new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Var,
398+
SourceLoc(), alias, DC);
399+
V->setAccess(swift::AccessLevel::Public);
400+
V->setInterfaceType(Ty.getType());
401+
V->getAttrs().add(new (Ctx) TransparentAttr(/*Implicit*/true));
402+
V->getAttrs().add(new (Ctx) InlineAttr(InlineKind::Always));
403+
404+
/* Accessor */
405+
swift::AccessorDecl *G =
406+
AccessorDecl::createImplicit(Ctx, AccessorKind::Get, V, false, false,
407+
TypeLoc(), AccessorTy, DC);
408+
G->setAccess(swift::AccessLevel::Public);
409+
G->setInterfaceType(AccessorTy);
410+
G->setParameters(ParameterList::create(Ctx, {}));
411+
G->getAttrs().add(new (Ctx) TransparentAttr(/*Implicit*/true));
412+
413+
DeclRefExpr *DRE =
414+
new (Ctx) DeclRefExpr(ConcreteDeclRef(VD), {}, /*Implicit*/true,
415+
AccessSemantics::Ordinary, Ty.getType());
416+
ReturnStmt *RS = ReturnStmt::createImplicit(Ctx, DRE);
417+
418+
G->setBody(BraceStmt::createImplicit(Ctx, {RS}),
419+
AbstractFunctionDecl::BodyKind::TypeChecked);
420+
421+
/* Bind */
422+
V->setImplInfo(StorageImplInfo::getImmutableComputed());
423+
V->setAccessors(SourceLoc(), {G}, SourceLoc());
424+
425+
return V;
426+
}
427+
}
428+
374429
static ValueDecl *importMacro(ClangImporter::Implementation &impl,
375430
llvm::SmallSet<StringRef, 4> &visitedMacros,
376431
DeclContext *DC, Identifier name,
@@ -509,7 +564,14 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
509564
}
510565
}
511566

512-
// FIXME: If the identifier refers to a declaration, alias it?
567+
/* Create an alias for any Decl */
568+
clang::Sema &S = impl.getClangSema();
569+
clang::LookupResult R(S, {{tok.getIdentifierInfo()}, {}},
570+
clang::Sema::LookupAnyName);
571+
if (S.LookupName(R, S.TUScope))
572+
if (R.getResultKind() == clang::LookupResult::LookupResultKind::Found)
573+
if (const auto *VD = dyn_cast<clang::ValueDecl>(R.getFoundDecl()))
574+
return importDeclAlias(impl, DC, VD, name);
513575
}
514576

515577
// TODO(https://github.com/apple/swift/issues/57735): Seems rare to have a single token that is neither a literal nor an identifier, but add diagnosis.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#if defined(UNICODE)
4+
#define F FW
5+
#define V VW
6+
#else
7+
#define F FA
8+
#define V VA
9+
#endif
10+
11+
extern const unsigned int VA;
12+
extern const unsigned long long VW;
13+
14+
void FA(unsigned int);
15+
void FW(unsigned long long);
16+
17+
#define InvalidCall DoesNotExist

test/ClangImporter/Inputs/custom-modules/module.modulemap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,7 @@ module CommonName {
275275
module "Weird C Module" {
276276
header "WeirdCModule.h"
277277
}
278+
279+
module Aliases {
280+
header "Aliases.h"
281+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-typecheck-verify-swift -I %S/Inputs/custom-modules
3+
4+
import Aliases
5+
6+
func f() {
7+
InvalidCall() // expected-error{{cannot find 'InvalidCall' in scope}}
8+
}

test/ClangImporter/alias.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-typcheck-verify-swift -I %S/Inputs/custom-modules %s
3+
// RUN: %target-swift-frontend -I %S/Inputs/custom-modules -parse-as-library -module-name Alias -Osize -emit-ir -o - %s | %FileCheck %s -check-prefix CHECK-ANSI-IR
4+
// RUN: %target-typecheck-verify-swift -I %S/Inputs/custom-modules %s -Xcc -DUNICODE
5+
// RUN: %target-swift-frontend -I %S/Inputs/custom-modules -parse-as-library -module-name Alias -Osize -emit-ir -o - %s -Xcc -DUNICODE | %FileCheck %s -check-prefix CHECK-UNICODE-IR
6+
7+
// expected-no-diagnostics
8+
9+
import Aliases
10+
11+
func f() {
12+
F(V)
13+
}
14+
15+
// CHECK-ANSI-IR: define hidden swiftcc void @"$s5Alias1fyyF"(){{.*}}{
16+
// CHECK-ANSI-IR: entry:
17+
// CHECK-ANSI-IR: %0 = load i32, ptr @VA, align 8
18+
// CHECK-ANSI-IR: tail call void @FA(i32 %0)
19+
// CHECK-ANSI-IR: ret void
20+
// CHECK-ANSI-IR: }
21+
22+
// CHECK-ANSI-IR: declare dso_local void @FA(i32 noundef)
23+
// CHECK-ANSI-IR-NOT: declare dso_local void @FW(i64 noundef)
24+
25+
// CHECK-UNICODE-IR: define hidden swiftcc void @"$s5Alias1fyyF"(){{.*}}{
26+
// CHECK-UNICODE-IR: entry:
27+
// CHECK-UNICODE-IR: %0 = load i64, ptr @VW, align 8
28+
// CHECK-UNICODE-IR: tail call void @FW(i64 %0)
29+
// CHECK-UNICODE-IR: ret void
30+
// CHECK-UNICODE-IR: }
31+
32+
// CHECK-UNICODE-IR: declare dso_local void @FW(i64 noundef)
33+
// CHECK-UNICODE-IR-NOT: declare dso_local void @FA(i32 noundef)

0 commit comments

Comments
 (0)