8000 Merge pull request #10899 from swiftlang/egorzhdan/20240723-allow-qua… · swiftlang/llvm-project@d25ca79 · GitHub
[go: up one dir, main page]

Skip to content

Commit d25ca79

Browse files
authored
Merge pull request #10899 from swiftlang/egorzhdan/20240723-allow-qual-swift-name
[Clang][Sema] Allow qualified type names in `swift_name` attribute
2 parents 1f8532e + 2df5b2b commit d25ca79

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

clang/lib/Sema/SemaSwift.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ static bool isValidSwiftErrorResultType(QualType Ty) {
7272
return isValidSwiftContextType(Ty);
7373
}
7474

75+
static bool isValidSwiftContextName(StringRef ContextName) {
76+
// ContextName might be qualified, e.g. 'MyNamespace.MyStruct'.
77+
SmallVector<StringRef, 1> ContextNameComponents;
78+
ContextName.split(ContextNameComponents, '.');
79+
return all_of(ContextNameComponents, [&](StringRef Component) {
80+
return isValidAsciiIdentifier(Component);
81+
});
82+
}
83+
7584
void SemaSwift::handleAttrAttr(Decl *D, const ParsedAttr &AL) {
7685
if (AL.isInvalid() || AL.isUsedAsTypeAttr())
7786
return;
@@ -356,11 +365,11 @@ static bool validateSwiftFunctionName(Sema &S, const ParsedAttr &AL,
356365

357366
// Split at the first '.', if it exists, which separates the context name
358367
// from the base name.
359-
std::tie(ContextName, BaseName) = BaseName.split('.');
368+
std::tie(ContextName, BaseName) = BaseName.rsplit('.');
360369
if (BaseName.empty()) {
361370
BaseName = ContextName;
362371
ContextName = StringRef();
363-
} else if (ContextName.empty() || !isValidAsciiIdentifier(ContextName)) {
372+
} else if (ContextName.empty() || !isValidSwiftContextName(ContextName)) {
364373
S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
365374
<< AL << /*context*/ 1;
366375
return false;
@@ -584,11 +593,11 @@ bool SemaSwift::DiagnoseName(Decl *D, StringRef Name, SourceLocation Loc,
584593
!IsAsync) {
585594
StringRef ContextName, BaseName;
586595

587-
std::tie(ContextName, BaseName) = Name.split('.');
596+
std::tie(ContextName, BaseName) = Name.rsplit('.');
588597
if (BaseName.empty()) {
589598
BaseName = ContextName;
590599
ContextName = StringRef();
591-
} else if (!isValidAsciiIdentifier(ContextName)) {
600+
} else if (!isValidSwiftContextName(ContextName)) {
592601
Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
593602
<< AL << /*context*/ 1;
594603
return false;

clang/test/SemaObjCXX/attr-swift_name-cxx.mm

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,43 @@
11
// RUN: %clang_cc1 -verify -fsyntax-only -fobjc-arc -fblocks %s
22

3+
#define SWIFT_NAME(name) __attribute__((swift_name(name)))
34
#define SWIFT_ASYNC_NAME(name) __attribute__((__swift_async_name__(name)))
45

6+
namespace MyNS {
7+
struct NestedStruct {};
8+
}
9+
10+
void nestedStruct_method(MyNS::NestedStruct) SWIFT_NAME("MyNS.NestedStruct.method(self:)");
11+
void nestedStruct_methodConstRef(const MyNS::NestedStruct&) SWIFT_NAME("MyNS.NestedStruct.methodConstRef(self:)");
12+
void nestedStruct_invalidContext1(MyNS::NestedStruct) SWIFT_NAME(".MyNS.NestedStruct.invalidContext1(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
13+
void nestedStruct_invalidContext2(MyNS::NestedStruct) SWIFT_NAME("MyNS::NestedStruct.invalidContext2(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
14+
void nestedStruct_invalidContext3(MyNS::NestedStruct) SWIFT_NAME("::MyNS::NestedStruct.invalidContext3(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
15+
void nestedStruct_invalidContext4(MyNS::NestedStruct) SWIFT_NAME("MyNS..NestedStruct.invalidContext4(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
16+
void nestedStruct_invalidContext5(MyNS::NestedStruct) SWIFT_NAME("MyNS.NestedStruct.invalidContext5.(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the base name}}
17+
void nestedStruct_invalidContext6(MyNS::NestedStruct) SWIFT_NAME("MyNS.NestedStruct::invalidContext6(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the base name}}
18+
19+
namespace MyNS {
20+
namespace MyDeepNS {
21+
struct DeepNestedStruct {};
22+
}
23+
}
24+
25+
void deepNestedStruct_method(MyNS::MyDeepNS::DeepNestedStruct) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.method(self:)");
26+
void deepNestedStruct_methodConstRef(const MyNS::MyDeepNS::DeepNestedStruct&) SWIFT_NAME("MyNS.MyDeepNS.DeepNestedStruct.methodConstRef(self:)");
27+
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}}
28+
29+
typedef MyNS::MyDeepNS::DeepNestedStruct DeepNestedStructTypedef;
30+
31+
void deepNestedStructTypedef_method(DeepNestedStructTypedef) SWIFT_NAME("DeepNestedStructTypedef.method(self:)");
32+
void deepNestedStructTypedef_methodQualName(MyNS::MyDeepNS::DeepNestedStruct) SWIFT_NAME("DeepNestedStructTypedef.method(self:)");
33+
34+
struct TopLevelStruct {
35+
struct StructInStruct {};
36+
};
37+
38+
void structInStruct_method(TopLevelStruct::StructInStruct) SWIFT_NAME("TopLevelStruct.StructInStruct.method(self:)");
39+
void structInStruct_invalidContext(TopLevelStruct::StructInStruct) SWIFT_NAME("TopLevelStruct::StructInStruct.method(self:)"); // expected-warning {{'swift_name' attribute has invalid identifier for the context name}}
40+
541
typedef int (^CallbackTy)(void);
642

743
class CXXClass {

0 commit comments

Comments
 (0)
0