Skip to content
Merged
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 include/swift/ClangImporter/ClangModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ class ClangModuleUnit final : public LoadedFile {
}
};

// Strips the inline namespaces from inner until we reach outer or a
// non-inline namespace. Returns the stripped nominal type or null when
// something unexpected happened during stripping.
NominalType *stripInlineNamespaces(NominalType *outer, NominalType *inner);
}

#endif
17 changes: 16 additions & 1 deletion lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3433,7 +3433,7 @@ class DarwinLegacyFilterDeclConsumer : public swift::VisibleDeclConsumer {
/// Translate a MacroDefinition to a ClangNode, either a ModuleMacro for
/// a definition imported from a module or a MacroInfo for a macro defined
/// locally.
ClangNode getClangNodeForMacroDefinition(clang::MacroDefinition &M) {
static ClangNode getClangNodeForMacroDefinition(clang::MacroDefinition &M) {
if (!M.getModuleMacros().empty())
return ClangNode(M.getModuleMacros().back()->getMacroInfo());
if (auto *MD = M.getLocalDirective())
Expand Down Expand Up @@ -9044,3 +9044,18 @@ swift::importer::getCxxRefConventionWithAttrs(const clang::Decl *decl) {

return std::nullopt;
}

NominalType *swift::stripInlineNamespaces(NominalType *outer,
NominalType *inner) {
if (!outer || !inner || inner == outer)
return nullptr;
auto CDInner = inner->getDecl()->getClangDecl();
while (inner && isa_and_nonnull<clang::NamespaceDecl>(CDInner) &&
cast<clang::NamespaceDecl>(CDInner)->isInline() &&
inner->getCanonicalType() != outer->getCanonicalType()) {
CDInner = cast<clang::Decl>(CDInner->getDeclContext());
inner = dyn_cast<NominalType>(inner->getParent().getPointer());
}

return inner;
}
2 changes: 1 addition & 1 deletion lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10610,7 +10610,7 @@ ClangImporter::Implementation::importDeclContextOf(
// Treat friend decls like top-level decls.
if (functionDecl->getFriendObjectKind()) {
// Find the top-level decl context.
while (isa<clang::NamedDecl>(dc))
while (!dc->isFileContext())
dc = dc->getParent();
}

Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1495,7 +1495,7 @@ RValue RValueEmitter::visitDerivedToBaseExpr(DerivedToBaseExpr *E,
RValue RValueEmitter::visitMetatypeConversionExpr(MetatypeConversionExpr *E,
SGFContext C) {
SILValue metaBase =
SGF.emitRValueAsSingleValue(E->getSubExpr()).getUnmanagedValue();
SGF.emitRValueAsSingleValue(E->getSubExpr()).getUnmanagedValue();

// Metatype conversion casts in the AST might not be reflected as
// such in the SIL type system, for example, a cast from DynamicSelf.Type
Expand Down
41 changes: 34 additions & 7 deletions lib/Sema/TypeOfReference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,20 @@
#include "TypeCheckType.h"
#include "TypeChecker.h"
#include "swift/AST/ConformanceLookup.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Effects.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/MacroDefinition.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeTransform.h"
#include "swift/Sema/ConstraintSystem.h"
#include "swift/Sema/PreparedOverload.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Statistic.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/Statistic.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Sema/ConstraintSystem.h"
#include "swift/Sema/PreparedOverload.h"

using namespace swift;
using namespace constraints;
Expand Down Expand Up @@ -1646,11 +1649,12 @@ static void addSelfConstraint(ConstraintSystem &cs, Type objectTy, Type selfTy,
PreparedOverloadBuilder *preparedOverload) {
assert(!selfTy->is<ProtocolType>());

// Otherwise, use a subtype constraint for classes to cope with inheritance.
// Otherwise, use a subtype constraint for classes to cope with
// inheritance.
if (selfTy->getClassOrBoundGenericClass()) {
cs.addConstraint(ConstraintKind::Subtype, objectTy, selfTy,
cs.getConstraintLocator(locator), /*isFavored=*/false,
preparedOverload);
cs.getConstraintLocator(locator),
/*isFavored=*/false, preparedOverload);
return;
}

Expand Down Expand Up @@ -1950,6 +1954,29 @@ ConstraintSystem::getTypeOfMemberReferencePre(
value, /*isCurriedInstanceReference*/ !hasAppliedSelf, functionRefInfo);
openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels);

// Adjust for C++ inline namespaces.
if (const auto *FT = openedType->getAs<FunctionType>()) {
auto openedParams = FT->getParams();
assert(openedParams.size() == 1);
auto param = openedParams.front();

Type selfObjTy = param.getPlainType();
bool wasMetaType = false;
if (param.getPlainType()->is<MetatypeType>()) {
selfObjTy = param.getPlainType()->getMetatypeInstanceType();
wasMetaType = true;
}
if (auto *objectTyNominal = baseObjTy->getAs<NominalType>()) {
if (auto *selfTyNominal = selfObjTy->getAs<NominalType>())
if (auto newSelfTy =
swift::stripInlineNamespaces(objectTyNominal, selfTyNominal))
openedType = FunctionType::get(
param.withType(wasMetaType ? Type(MetatypeType::get(newSelfTy))
: Type(newSelfTy)),
FT->getResult(), FT->getExtInfo());
}
}

Type baseOpenedTy = baseObjTy;

// If we are looking at a member of an existential, open the existential.
Expand Down

This file was deleted.

50 changes: 50 additions & 0 deletions test/Interop/Cxx/namespace/inline-namespace-function-call.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: %target-swift-frontend -c -verify -verify-ignore-unknown -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop -verify

//--- Inputs/module.modulemap
module namespaces {
header "test.h"
requires cplusplus
}
//--- Inputs/test.h
namespace Parent {
inline namespace InlineChild {
inline namespace InlineChild2 {
void functionInInlineChild2();
int GlobalVariableInInlineChild2;
struct GlobalTypeInInlineChild2 {};
} // namespace InlineChild2
void functionInInlineChild();
int GlobalVariableInInlineChild;
struct GlobalTypeInInlineChild {};
namespace Child {
void functionInInlineChildsNonInlineNamespace();
} // namespace Child
} // namespace InlineChild
} // namespace Parent

//--- test.swift

import namespaces;

func test() {
Parent.functionInInlineChild()
Parent.GlobalVariableInInlineChild = 1
Parent.functionInInlineChild2()
Parent.GlobalVariableInInlineChild2 = 2
Parent.InlineChild.functionInInlineChild()
Parent.InlineChild.GlobalVariableInInlineChild = 3
Parent.InlineChild.functionInInlineChild2()
Parent.InlineChild.GlobalVariableInInlineChild2 = 4
Parent.InlineChild.InlineChild2.functionInInlineChild2()
Parent.InlineChild.InlineChild2.GlobalVariableInInlineChild2 = 5
// FIXME: fix the below case.
Parent.Child.functionInInlineChildsNonInlineNamespace() // expected-error {{failed to produce diagnostic for expression}}
Parent.InlineChild.Child.functionInInlineChildsNonInlineNamespace()
}

func testTypes(x: Parent.GlobalTypeInInlineChild, y: Parent.GlobalTypeInInlineChild2,
x2: Parent.InlineChild.GlobalTypeInInlineChild,
y2: Parent.InlineChild.GlobalTypeInInlineChild2,
y3: Parent.InlineChild.InlineChild2.GlobalTypeInInlineChild2) {}