Skip to content

Commit f0d5cb9

Browse files
committed
[cxx-interop] Lazily instanciate var types and compute their type.
1 parent bea8a3d commit f0d5cb9

File tree

9 files changed

+82
-46
lines changed

9 files changed

+82
-46
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace swift {
3333

3434
class ConcreteDeclRef;
3535
class Decl;
36+
class VarDecl;
3637
class DeclContext;
3738
class EffectiveClangContext;
3839
class SwiftLookupTable;
@@ -267,6 +268,10 @@ class ClangModuleLoader : public ModuleLoader {
267268
virtual Type importFunctionReturnType(const clang::FunctionDecl *clangDecl,
268269
DeclContext *dc) = 0;
269270

271+
virtual Type importVarDeclType(const clang::VarDecl *clangDecl,
272+
VarDecl *swiftDecl,
273+
DeclContext *dc) = 0;
274+
270275
/// Find the lookup table that corresponds to the given Clang module.
271276
///
272277
/// \param clangModule The module, or null to indicate that we're talking

include/swift/ClangImporter/ClangImporter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,10 @@ class ClangImporter final : public ClangModuleLoader {
487487
Type importFunctionReturnType(const clang::FunctionDecl *clangDecl,
488488
DeclContext *dc) override;
489489

490+
Type importVarDeclType(const clang::VarDecl *clangDecl,
491+
VarDecl *swiftDecl,
492+
DeclContext *dc) override;
493+
490494
Optional<std::string>
491495
getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
492496
StringRef SwiftPCHHash);

lib/ClangImporter/ClangImporter.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5236,6 +5236,48 @@ Type ClangImporter::importFunctionReturnType(
52365236
return dc->getASTContext().getNeverType();
52375237
}
52385238

5239+
Type ClangImporter::importVarDeclType(
5240+
const clang::VarDecl *decl, VarDecl *swiftDecl, DeclContext *dc) {
5241+
if (decl->getTemplateInstantiationPattern())
5242+
Impl.getClangSema().InstantiateVariableDefinition(
5243+
decl->getLocation(),
5244+
const_cast<clang::VarDecl *>(decl));
5245+
5246+
// If the declaration is const, consider it audited.
5247+
// We can assume that loading a const global variable doesn't
5248+
// involve an ownership transfer.
5249+
bool isAudited = decl->getType().isConstQualified();
5250+
5251+
auto declType = decl->getType();
5252+
5253+
// Special case: NS Notifications
5254+
if (isNSNotificationGlobal(decl))
5255+
if (auto newtypeDecl = findSwiftNewtype(decl, Impl.getClangSema(),
5256+
Impl.CurrentVersion))
5257+
declType = Impl.getClangASTContext().getTypedefType(newtypeDecl);
5258+
5259+
bool isInSystemModule =
5260+
cast<ClangModuleUnit>(dc->getModuleScopeContext())->isSystemModule();
5261+
5262+
// Note that we deliberately don't bridge most globals because we want to
5263+
// preserve pointer identity.
5264+
auto importedType =
5265+
Impl.importType(declType,
5266+
(isAudited ? ImportTypeKind::AuditedVariable
5267+
: ImportTypeKind::Variable),
5268+
ImportDiagnosticAdder(Impl, decl, decl->getLocation()),
5269+
isInSystemModule, Bridgeability::None,
5270+
getImportTypeAttrs(decl));
5271+
5272+
if (!importedType)
5273+
return nullptr;
5274+
5275+
if (importedType.isImplicitlyUnwrapped())
5276+
swiftDecl->setImplicitlyUnwrappedOptional(true);
5277+
5278+
return importedType.getType();
5279+
}
5280+
52395281
bool ClangImporter::isInOverlayModuleForImportedModule(
52405282
const DeclContext *overlayDC,
52415283
const DeclContext *importedDC) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2684,17 +2684,6 @@ namespace {
26842684
if (isSpecializationDepthGreaterThan(def, 8))
26852685
return nullptr;
26862686

2687-
// If we have an inline data member, it won't get eagerly instantiated
2688-
// when we instantiate the class. So, make sure we do that now to catch
2689-
// any instantiation errors.
2690-
for (auto member : decl->decls()) {
2691-
if (auto varDecl = dyn_cast<clang::VarDecl>(member)) {
2692-
if (varDecl->getTemplateInstantiationPattern())
2693-
clangSema.InstantiateVariableDefinition(varDecl->getLocation(),
2694-
varDecl);
2695-
}
2696-
}
2697-
26982687
return VisitCXXRecordDecl(def);
26992688
}
27002689

@@ -3390,7 +3379,6 @@ namespace {
33903379
}
33913380

33923381
Decl *VisitVarDecl(const clang::VarDecl *decl) {
3393-
33943382
// Variables are imported as... variables.
33953383
ImportedName importedName;
33963384
Optional<ImportedName> correctSwiftName;
@@ -3403,34 +3391,6 @@ namespace {
34033391
if (!dc)
34043392
return nullptr;
34053393

3406-
// If the declaration is const, consider it audited.
3407-
// We can assume that loading a const global variable doesn't
3408-
// involve an ownership transfer.
3409-
bool isAudited = decl->getType().isConstQualified();
3410-
3411-
auto declType = decl->getType();
3412-
3413-
// Special case: NS Notifications
3414-
if (isNSNotificationGlobal(decl))
3415-
if (auto newtypeDecl = findSwiftNewtype(decl, Impl.getClangSema(),
3416-
Impl.CurrentVersion))
3417-
declType = Impl.getClangASTContext().getTypedefType(newtypeDecl);
3418-
3419-
// Note that we deliberately don't bridge most globals because we want to
3420-
// preserve pointer identity.
3421-
auto importedType =
3422-
Impl.importType(declType,
3423-
(isAudited ? ImportTypeKind::AuditedVariable
3424-
: ImportTypeKind::Variable),
3425-
ImportDiagnosticAdder(Impl, decl, decl->getLocation()),
3426-
isInSystemModule(dc), Bridgeability::None,
3427-
getImportTypeAttrs(decl));
3428-
3429-
if (!importedType)
3430-
return nullptr;
3431-
3432-
auto type = importedType.getType();
3433-
34343394
// If we've imported this variable as a member, it's a static
34353395
// member.
34363396
bool isStatic = false;
@@ -3451,9 +3411,6 @@ namespace {
34513411
name, dc);
34523412
result->setIsObjC(false);
34533413
result->setIsDynamic(false);
3454-
result->setInterfaceType(type);
3455-
Impl.recordImplicitUnwrapForDecl(result,
3456-
importedType.isImplicitlyUnwrapped());
34573414

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

lib/Sema/TypeCheckDecl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,6 +2365,14 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const {
23652365

23662366
case DeclKind::Var: {
23672367
auto *VD = cast<VarDecl>(D);
2368+
2369+
if (auto clangDecl = VD->getClangDecl()) {
2370+
auto clangVarDecl = cast<clang::VarDecl>(clangDecl);
2371+
2372+
return VD->getASTContext().getClangModuleLoader()->importVarDeclType(
2373+
clangVarDecl, VD, VD->getDeclContext());
2374+
}
2375+
23682376
auto *namingPattern = VD->getNamingPattern();
23692377
if (!namingPattern) {
23702378
return ErrorType::get(Context);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
template<class T>
2+
struct Bad {
3+
typename T::doesnotexist x;
4+
};
5+
6+
struct X {
7+
static Bad<int> b;
8+
};

test/Interop/Cxx/static/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ module ConstexprStaticMemberVarErrors {
2727
header "constexpr-static-member-var-errors.h"
2828
requires cplusplus
2929
}
30+
31+
module InvalidStaticMemberVar {
32+
header "invalid-static-member-var.h"
33+
requires cplusplus
34+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-experimental-cxx-interop | %FileCheck %s
2+
3+
import InvalidStaticMemberVar
4+
5+
func test(i: X) { }
6+
7+
// CHECK-NOT: error

test/Interop/Cxx/static/constexpr-static-member-var-errors.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// Check that we properly report the error and don't crash when importing an
44
// invalid decl.
55

6-
// CHECK: error: type 'int' cannot be used prior to '::' because it has no members
7-
// CHECK: {{note: in instantiation of template class 'GetTypeValue<int>' requested here|note: in instantiation of static data member 'GetTypeValue<int>::value' requested here}}
6+
// Windows doesn't fail at all here which seems ok (and probably should be the case for other platforms too).
7+
// XFAIL: windows
88

99
// CHECK: error: type 'int' cannot be used prior to '::' because it has no members
10-
// CHECK: note: in instantiation of static data member 'GetTypeValueInline<int>::value' requested here
10+
// CHECK: {{note: in instantiation of template class 'GetTypeValue<int>' requested here|note: in instantiation of static data member 'GetTypeValue<int>::value' requested here}}

0 commit comments

Comments
 (0)