-
Notifications
You must be signed in to change notification settings - Fork 10.2k
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
[cxx-interop] Import the attributes from clang decl for synthesized s… #73559
base: main
Are you sure you want to change the base?
Conversation
@swift-ci Please smoke test |
@swift-ci Please test |
getterImpl->getClangDecl())) { | ||
Impl.importAttributes(clangDeclForOperatorStar, pointeeProperty); | ||
} | ||
|
||
result->addMember(pointeeProperty); | ||
} | ||
} |
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.
This logic looks quite specific to the synthesized pointee
property. Are there other synthesized properties where this is necessary? If so, I wonder if we can factor this out in to a method and call this from other places as well.
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 discussed this with @egorzhdan and @beccadax . I think this problem should be there for other synthesized properties also (like computed properties). But I wanted to get feedback from people by making a patch only for pointee property and then think about solving this problem in general for all synthesized properties.
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.
Thanks @fahadnayyar! The overall logic looks good to me, but I have a couple comments.
test/Interop/Cxx/operators/OperatorStar/Inputs/cxx-operator-star.h
Outdated
Show resolved
Hide resolved
FuncDecl *getterImpl = getterAndSetter.first ? getterAndSetter.first | ||
: getterAndSetter.second; | ||
if (auto clangDeclForOperatorStar = | ||
dyn_cast_or_null<clang::NamedDecl>( |
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.
Can getterImpl->getClangDecl()
ever be null? Looks like it would always be non-null, so I think we should just unconditionally cast<clang::NamedDecl>
and have an assertion if the getter's Clang decl ended up being null, since that would indicate a problem in our reasoning about this code path.
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.
Yes, getterImpl->getClangDecl()
was null for some lit test cases like these:
// ***------- TEST 1
// Swift:
let derivedConstIterWithUD = DerivedFromConstIteratorPrivatelyWithUsingDecl()
let _ = derivedConstIterWithUD.pointee
// C++:
struct ConstIterator {
private:
int value = 234;
public:
int &operator*() { return value; }
};
struct DerivedFromConstIteratorPrivatelyWithUsingDecl : private ConstIterator {
using ConstIterator::operator*;
};
// ***------- TEST 2
// Swift:
let stars = DerivedFromConstIteratorPrivatelyWithUsingDecl()
let res = stars.pointee
// C++:
struct ConstIterator {
private:
int value = 234;
public:
const int &operator*() const { return value; }
};
struct DerivedFromConstIteratorPrivatelyWithUsingDecl : private ConstIterator {
using ConstIterator::operator*;
};
// ***------- TEST 3
// Swift:
let stars = DerivedFromAmbiguousOperatorStarPrivatelyWithUsingDecl()
let res = stars.pointee
// C++:
struct AmbiguousOperatorStar {
private:
int value = 567;
public:
int &operator*() { return value; }
const int &operator*() const { return value; }
};
struct DerivedFromAmbiguousOperatorStarPrivatelyWithUsingDecl
: private AmbiguousOperatorStar {
using AmbiguousOperatorStar::operator*;
};
So maybe the problem is when calling pointee property C++ types which inherits operator* from their parent/base class like using AmbiguousOperatorStar::operator*
and using ConstIterator::operator*
@egorzhdan do you have thoughts about why getterImpl->getClangDecl()
is null for these cases? I was assuming that __myoperatorstar
function should always have a clangDecl
from which it is mapped.
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.
Oh right, that makes sense. C++ members that were instantiated from using-shadow-decls have no corresponding Clang decl. This is because we synthesize a Swift decl that dispatches the call to the underlying Clang decl.
(Ideally we would synthesize a decl on the Clang side, not on the Swift side, to help us avoid this kind of issues)
Could you please add a comment mentioning the inheritance quirk?
82b9297
to
07ab93a
Compare
…wift pointee property
07ab93a
to
5246332
Compare
|
||
mutable int value; | ||
|
||
int *operator->() const { return &value; } |
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.
We don't import operator->
into Swift, so this decl is ignored.
(It's OK to keep it in the test if you'd like, just FYI)
FuncDecl *getterImpl = getterAndSetter.first ? getterAndSetter.first | ||
: getterAndSetter.second; | ||
if (auto clangDeclForOperatorStar = | ||
dyn_cast_or_null<clang::NamedDecl>( |
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.
Oh right, that makes sense. C++ members that were instantiated from using-shadow-decls have no corresponding Clang decl. This is because we synthesize a Swift decl that dispatches the call to the underlying Clang decl.
(Ideally we would synthesize a decl on the Clang side, not on the Swift side, to help us avoid this kind of issues)
Could you please add a comment mentioning the inheritance quirk?
return *operator->(); | ||
} | ||
}; | ||
|
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.
Could you please add a test that checks that inherited operator*
gets the correct attributes, e.g. struct DerivedHasOperatorStar : HasOperatorStar
@@ -78,3 +78,13 @@ let _ = derivedConstIterWithUD.pointee | |||
|
|||
var derivedIntWrapper = DerivedFromLoadableIntWrapperWithUsingDecl() | |||
derivedIntWrapper += LoadableIntWrapper() | |||
|
|||
func TestPointeeAvailable() { |
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.
Minor: let's remove the func
wrappers to keep this consistent with the rest of the test
@@ -2522,6 +2522,17 @@ namespace { | |||
VarDecl *pointeeProperty = | |||
synthesizer.makeDereferencedPointeeProperty( | |||
getterAndSetter.first, getterAndSetter.second); | |||
|
|||
// Import the attributes from dereference operator clang decl to | |||
// pointee property swift decl. |
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.
Minor: let's capitalize Swift
.
Attributes like availability were not being copied from clang decl of C++ operator * to swift decl of pointee property. Because of this pointee property was not hidden in swift even if C++ operator * (dereference operator) was marked with attribute((availability(swift, unavailable))).
rdar://116775023