8000 🍒[Clang][Sema] Allow qualified type names in `swift_name` attribute by egorzhdan · Pull Request #10911 · swiftlang/llvm-project · GitHub
[go: up one dir, main page]

Skip to content

🍒[Clang][Sema] Allow qualified type names in swift_name attribute #10911

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 email 8000 s.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2025
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
17 changes: 13 additions & 4 deletions clang/lib/Sema/SemaSwift.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ static bool isValidSwiftErrorResultType(QualType Ty) {
return isValidSwiftContextType(Ty);
}

static bool isValidSwiftContextName(StringRef ContextName) {
// ContextName might be qualified, e.g. 'MyNamespace.MyStruct'.
SmallVector<StringRef, 1> ContextNameComponents;
ContextName.split(ContextNameComponents, '.');
return all_of(ContextNameComponents, [&](StringRef Component) {
return isValidAsciiIdentifier(Component);
});
}

void SemaSwift::handleAttrAttr(Decl *D, const ParsedAttr &AL) {
if (AL.isInvalid() || AL.isUsedAsTypeAttr())
return;
Expand Down Expand Up @@ -356,11 +365,11 @@ static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL,

// Split at the first '.', if it exists, which separates the context name
// from the base name.
std::tie(ContextName, BaseName) = BaseName.split('.');
std::tie(ContextName, BaseName) = BaseName.rsplit('.');
if (BaseName.empty()) {
BaseName = ContextName;
ContextName = StringRef();
} else if (ContextName.empty() || !isValidAsciiIdentifier(ContextName)) {
} else if (ContextName.empty() || !isValidSwiftContextName(ContextName)) {
S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
<< AL << /*context*/ 1;
return false;
Expand Down Expand Up @@ -584,11 +593,11 @@ bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,
!IsAsync) {
StringRef ContextName, BaseName;

std::tie(ContextName, BaseName) = Name.split('.');
std::tie(ContextName, BaseName) = Name.rsplit('.');
if (BaseName.empty()) {
BaseName = ContextName;
ContextName = StringRef();
} else if (!isValidAsciiIdentifier(ContextName)) {
} else if (!isValidSwiftContextName(ContextName)) {
Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
<< AL << /*context*/ 1;
return false;
Expand Down
36 changes: 36 additions & 0 deletions clang/test/SemaObjCXX/attr-swift_name-cxx.mm
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
// RUN: %clang_cc1 -verify -fsyntax-only -fobjc-arc -fblocks %s

#define SWIFT_NAME(name) __attribute__((swift_name(name)))
#define SWIFT_ASYNC_NAME(name) __attribute__((__swift_async_name__(name)))

namespace MyNS {
struct NestedStruct {};
}

void nestedStruct_method(MyNS::NestedStruct) SWIFT_NAME("MyNS.NestedStruct.method(self:)");
void nestedStruct_methodConstRef(const MyNS::NestedStruct&) SWIFT_NAME("MyNS.NestedStruct.methodConstRef(self:)");
void nestedStruct_invalidContext1(MyNS::NestedStruct) SWIFT_NAME(".MyNS.NestedStruct.invalidContext1(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
void nestedStruct_invalidContext2(MyNS::NestedStruct) SWIFT_NAME("MyNS::NestedStruct.invalidContext2(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
void nestedStruct_invalidContext3(MyNS::NestedStruct) SWIFT_NAME("::MyNS::NestedStruct.invalidContext3(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
vo 828B id nestedStruct_invalidContext4(MyNS::NestedStruct) SWIFT_NAME("MyNS..NestedStruct.invalidContext4(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
void nestedStruct_invalidContext5(MyNS::NestedStruct) SWIFT_NAME("MyNS.NestedStruct.invalidContext5.(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the base name}}
void nestedStruct_invalidContext6(MyNS::NestedStruct) SWIFT_NAME("MyNS.NestedStruct::invalidContext6(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the base name}}

namespace MyNS {
namespace MyDeepNS {
struct DeepNestedStruct {};
}
}

void deepNestedStruct_method(MyNS::MyDeepNS::DeepNestedStruct) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.method(self:)");
void deepNestedStruct_methodConstRef(const MyNS::MyDeepNS::DeepNestedStruct&) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.methodConstRef(self:)");
void deepNestedStruct_invalidContext(const MyNS::MyDeepNS::DeepNestedStruct&) SWIFT_NAME("MyNS::MyDeepNS::DeepNestedStruct.methodConstRef(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}

typedef MyNS::MyDeepNS::DeepNestedStruct DeepNestedStructTypedef;

void deepNestedStructTypedef_method(DeepNestedStructTypedef) SWIFT_NAME("DeepNestedStructTypedef.method(self:)");
void deepNestedStructTypedef_methodQualName(MyNS::MyDeepNS::DeepNestedStruct) SWIFT_NAME("DeepNestedStructTypedef.method(self:)");

struct TopLevelStruct {
struct StructInStruct {};
};

void structInStruct_method(TopLevelStruct::StructInStruct) SWIFT_NAME("TopLevelStruct.StructInStruct.method(self:)");
void structInStruct_invalidContext(TopLevelStruct::StructInStruct) SWIFT_NAME("TopLevelStruct::StructInStruct.method(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}

typedef int (^CallbackTy)(void);

class CXXClass {
Expand Down
0