Skip to content

Commit 0d59587

Browse files
authored
Merge pull request #73559 from fahadnayyar/attribute-operator-star
[cxx-interop] Import the attributes from clang decl for synthesized s…
2 parents 56cb980 + 1d8ddc2 commit 0d59587

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

lib/ClangImporter/ImportDecl.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,15 @@ namespace {
25232523
VarDecl *pointeeProperty =
25242524
synthesizer.makeDereferencedPointeeProperty(
25252525
getterAndSetter.first, getterAndSetter.second);
2526+
2527+
// Import the attributes from clang decl of dereference operator to
2528+
// synthesized pointee property.
2529+
FuncDecl *getterOrSetterImpl = getterAndSetter.first
2530+
? getterAndSetter.first
2531+
: getterAndSetter.second;
2532+
Impl.importAttributesFromClangDeclToSynthesizedSwiftDecl(
2533+
getterOrSetterImpl, pointeeProperty);
2534+
25262535
result->addMember(pointeeProperty);
25272536
}
25282537
}
@@ -3321,6 +3330,10 @@ namespace {
33213330
// This is a pre-increment operator. We synthesize a
33223331
// non-mutating function called `successor() -> Self`.
33233332
FuncDecl *successorFunc = synthesizer.makeSuccessorFunc(func);
3333+
3334+
// Import the clang decl attributes to synthesized successor function.
3335+
Impl.importAttributesFromClangDeclToSynthesizedSwiftDecl(func, successorFunc);
3336+
33243337
typeDecl->addMember(successorFunc);
33253338

33263339
Impl.markUnavailable(func, "use .successor()");
@@ -8236,6 +8249,17 @@ static bool isUsingMacroName(clang::SourceManager &SM,
82368249
return content == MacroName;
82378250
}
82388251

8252+
void ClangImporter::Implementation::importAttributesFromClangDeclToSynthesizedSwiftDecl(Decl *sourceDecl, Decl* synthesizedDecl)
8253+
{
8254+
// sourceDecl->getClangDecl() can be null because some lazily instantiated cases like C++ members that were instantiated from using-shadow-decls have no corresponding Clang decl.
8255+
// FIXME: Need to include the cases where correspondoing clang decl is not present.
8256+
if (auto clangDeclForSource =
8257+
dyn_cast_or_null<clang::NamedDecl>(
8258+
sourceDecl->getClangDecl())) {
8259+
importAttributes(clangDeclForSource, synthesizedDecl);
8260+
}
8261+
}
8262+
82398263
/// Import Clang attributes as Swift attributes.
82408264
void ClangImporter::Implementation::importAttributes(
82418265
const clang::NamedDecl *ClangDecl,

lib/ClangImporter/ImporterImpl.h

+9
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,15 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
10641064
/// in the given module.
10651065
SourceFile &getClangSwiftAttrSourceFile(ModuleDecl &module);
10661066

1067+
/// Utility function to import Clang attributes from a source Swift decl to
1068+
/// synthesized Swift decl.
1069+
///
1070+
/// \param SourceDecl The Swift decl to copy the atteribute from.
1071+
/// \param SynthesizedDecl The synthesized Swift decl to attach attributes to.
1072+
void
1073+
importAttributesFromClangDeclToSynthesizedSwiftDecl(Decl *SourceDecl,
1074+
Decl *SynthesizedDecl);
1075+
10671076
/// Import attributes from the given Clang declaration to its Swift
10681077
/// equivalent.
10691078
///

test/Interop/Cxx/operators/Inputs/member-inline.h

+43
Original file line numberDiff line numberDiff line change
@@ -492,4 +492,47 @@ class HasStaticOperatorCallWithConstOperator {
492492
}
493493
};
494494

495+
struct ClassWithOperatorStarAvailable {
496+
int value;
497+
498+
public:
499+
int &operator*() { return value; }
500+
};
501+
502+
struct DerivedClassWithOperatorStarAvailable : ClassWithOperatorStarAvailable {
503+
};
504+
505+
struct ClassWithOperatorStarUnavailable {
506+
int value;
507+
508+
public:
509+
int &operator*() __attribute__((availability(swift, unavailable))) {
510+
return value;
511+
}
512+
};
513+
514+
struct DerivedClassWithOperatorStarUnavailable
515+
: ClassWithOperatorStarUnavailable {};
516+
517+
struct ClassWithSuccessorAvailable {
518+
int value;
519+
520+
public:
521+
ClassWithSuccessorAvailable &operator++() {
522+
value++;
523+
return *this;
524+
}
525+
};
526+
527+
struct ClassWithSuccessorUnavailable {
528+
int value;
529+
530+
public:
531+
ClassWithSuccessorUnavailable &operator++()
532+
__attribute__((availability(swift, unavailable))) {
533+
value++;
534+
return *this;
535+
}
536+
};
537+
495538
#endif

test/Interop/Cxx/operators/member-inline-typechecker.swift

+19
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,22 @@ let _ = derivedConstIterWithUD.pointee
7878

7979
var derivedIntWrapper = DerivedFromLoadableIntWrapperWithUsingDecl()
8080
derivedIntWrapper += LoadableIntWrapper()
81+
82+
let classWithSuccessorAvailable = ClassWithSuccessorAvailable()
83+
let _ = classWithSuccessorAvailable.successor();
84+
let classWithSuccessorUnavailable = ClassWithSuccessorUnavailable()
85+
let _ = classWithSuccessorUnavailable.successor(); // expected-error {{'successor()' is unavailable in Swift}}
86+
87+
var classWithOperatorStarAvailable = ClassWithOperatorStarAvailable()
88+
let _ = classWithOperatorStarAvailable.pointee
89+
let derivedClassWithOperatorStarAvailable = DerivedClassWithOperatorStarAvailable()
90+
let _ = derivedClassWithOperatorStarAvailable.pointee
91+
92+
var classWithOperatorStarUnavailable = ClassWithOperatorStarUnavailable()
93+
let _ = classWithOperatorStarUnavailable.pointee // expected-error {{'pointee' is unavailable in Swift}}
94+
95+
// FIXME: The below test should also fail with 'pointee' is unavailable in Swift error,
96+
// but currently pointee is not hidden in derived classes.
97+
let derivedClassWithOperatorStarUnavailable = DerivedClassWithOperatorStarUnavailable()
98+
let _ = derivedClassWithOperatorStarUnavailable.pointee
99+

0 commit comments

Comments
 (0)