-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Re-implement namespaces using enums + extensions. #35085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_SECOND_HEADER_H | ||
#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_SECOND_HEADER_H | ||
|
||
#include "classes.h" | ||
|
||
struct ClassesNS1::ClassesNS2::DefinedInDefs { | ||
const char *basicMember() { | ||
return "ClassesNS1::ClassesNS2::DefinedInDefs::basicMember"; | ||
} | ||
}; | ||
|
||
#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_SECOND_HEADER_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_H | ||
#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_H | ||
|
||
namespace ClassesNS1 { | ||
struct BasicStruct { | ||
const char *basicMember() { return "ClassesNS1::BasicStruct::basicMember"; } | ||
}; | ||
struct ForwardDeclaredStruct; | ||
} // namespace ClassesNS1 | ||
|
||
struct ClassesNS1::ForwardDeclaredStruct { | ||
const char *basicMember() { | ||
return "ClassesNS1::ForwardDeclaredStruct::basicMember"; | ||
} | ||
}; | ||
|
||
namespace ClassesNS1 { | ||
namespace ClassesNS2 { | ||
struct BasicStruct { | ||
const char *basicMember() { | ||
return "ClassesNS1::ClassesNS2::BasicStruct::basicMember"; | ||
} | ||
}; | ||
struct ForwardDeclaredStruct; | ||
struct DefinedInDefs; | ||
} // namespace ClassesNS2 | ||
} // namespace ClassesNS1 | ||
|
||
namespace ClassesNS1 { | ||
struct ClassesNS2::ForwardDeclaredStruct { | ||
const char *basicMember() { | ||
return "ClassesNS1::ClassesNS2::ForwardDeclaredStruct::basicMember"; | ||
} | ||
}; | ||
} // namespace ClassesNS1 | ||
|
||
namespace ClassesNS3 { | ||
struct BasicStruct { | ||
const char *basicMember() { return "ClassesNS3::BasicStruct::basicMember"; } | ||
}; | ||
} // namespace ClassesNS3 | ||
|
||
#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_CLASSES_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTIONS_SECOND_HEADER_H | ||
#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTIONS_SECOND_HEADER_H | ||
|
||
#include "free-functions.h" | ||
|
||
inline const char *FunctionsNS1::definedInDefs() { | ||
return "FunctionsNS1::definedInDefs"; | ||
} | ||
|
||
#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTIONS_SECOND_HEADER_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTION_H | ||
#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTION_H | ||
|
||
namespace FunctionsNS1 { | ||
inline const char *basicFunctionTopLevel() { | ||
return "FunctionsNS1::basicFunctionTopLevel"; | ||
} | ||
inline const char *forwardDeclared(); | ||
inline const char *definedOutOfLine(); | ||
} // namespace FunctionsNS1 | ||
|
||
namespace FunctionsNS1 { | ||
inline const char *forwardDeclared() { return "FunctionsNS1::forwardDeclared"; } | ||
} // namespace FunctionsNS1 | ||
|
||
inline const char *FunctionsNS1::definedOutOfLine() { | ||
return "FunctionsNS1::definedOutOfLine"; | ||
} | ||
|
||
namespace FunctionsNS1 { | ||
namespace FunctionsNS2 { | ||
inline const char *basicFunctionSecondLevel() { | ||
return "FunctionsNS1::FunctionsNS2::basicFunctionSecondLevel"; | ||
} | ||
} // namespace FunctionsNS2 | ||
} // namespace FunctionsNS1 | ||
|
||
namespace FunctionsNS1 { | ||
namespace FunctionsNS2 { | ||
namespace FunctionsNS3 { | ||
inline const char *basicFunctionLowestLevel() { | ||
return "FunctionsNS1::FunctionsNS2::FunctionsNS3::basicFunctionLowestLevel"; | ||
} | ||
} // namespace FunctionsNS3 | ||
} // namespace FunctionsNS2 | ||
} // namespace FunctionsNS1 | ||
|
||
namespace FunctionsNS1 { | ||
inline const char *definedInDefs(); | ||
} | ||
|
||
namespace FunctionsNS1 { | ||
inline const char *sameNameInChild() { return "FunctionsNS1::sameNameInChild"; } | ||
inline const char *sameNameInSibling() { | ||
return "FunctionsNS1::sameNameInSibling"; | ||
} | ||
namespace FunctionsNS2 { | ||
inline const char *sameNameInChild() { | ||
return "FunctionsNS1::FunctionsNS2::sameNameInChild"; | ||
} | ||
} // namespace FunctionsNS2 | ||
} // namespace FunctionsNS1 | ||
|
||
namespace FunctionsNS4 { | ||
inline const char *sameNameInSibling() { | ||
return "FunctionsNS4::sameNameInSibling"; | ||
} | ||
} // namespace FunctionsNS4 | ||
|
||
#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_FREE_FUNCTION_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module Classes { | ||
header "classes.h" | ||
} | ||
|
||
module ClassesSecondHeader { | ||
// TODO: we shouldn't have to include both of these, and the decls defined in | ||
// these headers should be added to the correct module: SR-14214. | ||
header "classes.h" | ||
header "classes-second-header.h" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not make classes-second-header.h include classes.h? As written in the module map, classes.h belongs to two modules. Similarly in other header pairs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does include "classes.h". But both headers are required to be able to use the imported APIs. I'll investigate because we should be able to see the stuff that's "defined in defs" without "importing" both headers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh sorry indeed it does. I was thinking of templates-second-header.h. But yes, it would be best if classes.h (and other first-level headers) could be a part of only one module. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, here's the problem: when we find a declaration, we immediately look for the definition and see if we can import that. This means Swift thinks all of these APIs are part of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good, thank you! |
||
} | ||
|
||
module FreeFunctions { | ||
header "free-functions.h" | ||
} | ||
|
||
module FreeFunctionsSecondHeader { | ||
header "free-functions.h" | ||
header "free-functions-second-header.h" | ||
} | ||
|
||
module Templates { | ||
header "templates.h" | ||
} | ||
|
||
module TemplatesSecondHeader { | ||
header "templates.h" | ||
header "templates-second-header.h" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#ifndef TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_SECOND_HEADER_H | ||
#define TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_SECOND_HEADER_H | ||
|
||
template <class T> | ||
const char *TemplatesNS1::basicFunctionTemplateDefinedInDefs(T) { | ||
return "TemplatesNS1::basicFunctionTemplateDefinedInDefs"; | ||
} | ||
|
||
template <class> struct TemplatesNS1::BasicClassTemplateDefinedInDefs { | ||
const char *basicMember() { | ||
return "TemplatesNS1::BasicClassTemplateDefinedInDefs::basicMember"; | ||
} | ||
}; | ||
|
||
using BasicClassTemplateDefinedInDefsChar = | ||
TemplatesNS1::BasicClassTemplateDefinedInDefs<char>; | ||
|
||
#endif // TEST_INTEROP_CXX_NAMESPACE_INPUTS_TEMPLATES_SECOND_HEADER_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally, I created a separate
__Cxx
module for this, but I thinkImportedHeaderUnit
(__ObjC
) works fine, so there's really no reason to add another one. Once we decide how we want to handle apps that use both Objective-C and C++ interop, we might conditionally name this__Cxx
instead of__ObjC
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the only question is, whether it is possible to have a conflict between any existing entity in
__ObjC
and these new namespace-enums. I think a conflict is only possible if someone had an actual C enum in the global namespace, and a top-level namespace of the same name; however that is not allowed in C++.So using
__ObjC
makes sense. I think even when we enable C++ interop by default, the module can continue to be called__ObjC
, because why break ABI.