Skip to content

Commit a39f60b

Browse files
committed
[ClangImporter] Import constant values for 'const' globals
1 parent aaec5aa commit a39f60b

File tree

2 files changed

+126
-6
lines changed

2 files changed

+126
-6
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,12 +4590,37 @@ namespace {
45904590
auto introducer = Impl.shouldImportGlobalAsLet(decl->getType())
45914591
? VarDecl::Introducer::Let
45924592
: VarDecl::Introducer::Var;
4593-
auto result = Impl.createDeclWithClangNode<VarDecl>(
4594-
decl, importer::convertClangAccess(decl->getAccess()),
4595-
/*IsStatic*/ isStatic, introducer,
4596-
Impl.importSourceLoc(decl->getLocation()), name, dc);
4597-
result->setIsObjC(false);
4598-
result->setIsDynamic(false);
4593+
4594+
ValueDecl *result = nullptr;
4595+
4596+
// If the variable is const (we're importing it as a let), and has an
4597+
// initializer, then ask Clang for its constant value and synthesize a
4598+
// getter with that value.
4599+
if (introducer == VarDecl::Introducer::Let && decl->hasInit()) {
4600+
auto val = decl->evaluateValue();
4601+
// For now, only import integer and float constants. If in the future
4602+
// SwiftDeclSynthesizer::createConstant becomes able to import more
4603+
// types, we can lift this restriction.
4604+
if (val && (val->isFloat() || val->isInt())) {
4605+
auto type = Impl.importTypeIgnoreIUO(
4606+
decl->getType(), ImportTypeKind::Value,
4607+
ImportDiagnosticAdder(Impl, decl, decl->getLocation()),
4608+
isInSystemModule(dc), Bridgeability::None, ImportTypeAttrs());
4609+
result = synthesizer.createConstant(
4610+
name, dc, type, *val, ConstantConvertKind::None, isStatic, decl,
4611+
importer::convertClangAccess(decl->getAccess()));
4612+
}
4613+
}
4614+
4615+
// Otherwise, import as an external declaration
4616+
if (!result) {
4617+
result = Impl.createDeclWithClangNode<VarDecl>(
4618+
decl, importer::convertClangAccess(decl->getAccess()),
4619+
/*IsStatic*/ isStatic, introducer,
4620+
Impl.importSourceLoc(decl->getLocation()), name, dc);
4621+
result->setIsObjC(false);
4622+
result->setIsDynamic(false);
4623+
}
45994624

46004625
// If imported as member, the member should be final.
46014626
if (dc->getSelfClassDecl())

test/ClangImporter/const_values.swift

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %t/src/main.swift \
5+
// RUN: -import-bridging-header %t/src/test.h \
6+
// RUN: -module-name main -I %t -emit-sil | %FileCheck %s
7+
8+
//--- test.h
9+
#include <stdbool.h>
10+
11+
#define MACRO_INT 42
12+
13+
const int const_int = 42;
14+
static int static_int = 42;
15+
static const int static_const_int = 42;
16+
17+
static const bool static_const_bool = true;
18+
static const char static_const_char = 42;
19+
static const long static_const_long = 42;
20+
static const float static_const_float = 42.0;
21+
static const double static_const_double = 42.0;
22+
23+
//--- main.swift
24+
func foo() {
25+
print(MACRO_INT)
26+
27+
print(const_int)
28+
print(static_int)
29+
print(static_const_int)
30+
31+
print(static_const_bool)
32+
print(static_const_char)
33+
print(static_const_long)
34+
print(static_const_float)
35+
print(static_const_double)
36+
}
37+
38+
// Only 'static' cannot get the getter imported, because it's not guaranteed to be constant.
39+
// CHECK: sil_global public_external @static_int : $Int32
40+
41+
// CHECK: sil shared [transparent] @$sSC9MACRO_INTs5Int32Vvg : $@convention(thin) () -> Int32 {
42+
// CHECK-NEXT: bb0:
43+
// CHECK-NEXT: %0 = integer_literal $Builtin.Int32, 42
44+
// CHECK-NEXT: %1 = struct $Int32 (%0)
45+
// CHECK-NEXT: return %1
46+
// CHECK-NEXT: }
47+
48+
// CHECK: sil shared [transparent] @$sSo9const_ints5Int32Vvg : $@convention(thin) () -> Int32 {
49+
// CHECK-NEXT: bb0:
50+
// CHECK-NEXT: %0 = integer_literal $Builtin.Int32, 42
51+
// CHECK-NEXT: %1 = struct $Int32 (%0)
52+
// CHECK-NEXT: return %1
53+
// CHECK-NEXT: }
54+
55+
// CHECK: sil shared [transparent] @$sSo16static_const_ints5Int32Vvg : $@convention(thin) () -> Int32 {
56+
// CHECK-NEXT: bb0:
57+
// CHECK-NEXT: %0 = integer_literal $Builtin.Int32, 42
58+
// CHECK-NEXT: %1 = struct $Int32 (%0)
59+
// CHECK-NEXT: return %1
60+
// CHECK-NEXT: }
61+
62+
// CHECK: sil shared [transparent] @$sSo17static_const_boolSbvg : $@convention(thin) () -> Bool {
63+
// CHECK-NEXT: bb0:
64+
// CHECK-NEXT: %0 = integer_literal $Builtin.Int1, -1
65+
// CHECK-NEXT: %1 = struct $Bool (%0)
66+
// CHECK-NEXT: return %1
67+
// CHECK-NEXT: }
68+
69+
// CHECK: sil shared [transparent] @$sSo17static_const_chars4Int8Vvg : $@convention(thin) () -> Int8 {
70+
// CHECK-NEXT: bb0:
71+
// CHECK-NEXT: %0 = integer_literal $Builtin.Int8, 42
72+
// CHECK-NEXT: %1 = struct $Int8 (%0)
73+
// CHECK-NEXT: return %1
74+
// CHECK-NEXT: }
75+
76+
// CHECK: sil shared [transparent] @$sSo17static_const_longSivg : $@convention(thin) () -> Int {
77+
// CHECK-NEXT: bb0:
78+
// CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 42
79+
// CHECK-NEXT: %1 = struct $Int (%0)
80+
// CHECK-NEXT: return %1
81+
// CHECK-NEXT: }
82+
83+
// CHECK: sil shared [transparent] @$sSo18static_const_floatSfvg : $@convention(thin) () -> Float {
84+
// CHECK-NEXT: bb0:
85+
// CHECK-NEXT: %0 = float_literal $Builtin.FPIEEE32, 0x42280000 // 42
86+
// CHECK-NEXT: %1 = struct $Float (%0)
87+
// CHECK-NEXT: return %1
88+
// CHECK-NEXT: }
89+
90+
// CHECK: sil shared [transparent] @$sSo19static_const_doubleSdvg : $@convention(thin) () -> Double {
91+
// CHECK-NEXT: bb0:
92+
// CHECK-NEXT: %0 = float_literal $Builtin.FPIEEE64, 0x4045000000000000 // 42
93+
// CHECK-NEXT: %1 = struct $Double (%0)
94+
// CHECK-NEXT: return %1
95+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)