Skip to content

Commit f4871ea

Browse files
committed
[clangd] Support pseudo-obj expr, opaque values, and property references in findExplicitReferences()
Reviewers: ilya-biryukov, dgoldman Subscribers: MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D72508
1 parent 243f52b commit f4871ea

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

clang-tools-extra/clangd/FindTarget.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ llvm::SmallVector<ReferenceLoc, 2> refInDecl(const Decl *D) {
619619

620620
llvm::SmallVector<ReferenceLoc, 2> refInExpr(const Expr *E) {
621621
struct Visitor : ConstStmtVisitor<Visitor> {
622-
// FIXME: handle more complicated cases, e.g. ObjC, designated initializers.
622+
// FIXME: handle more complicated cases: more ObjC, designated initializers.
623623
llvm::SmallVector<ReferenceLoc, 2> Refs;
624624

625625
void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) {
@@ -660,6 +660,14 @@ llvm::SmallVector<ReferenceLoc, 2> refInExpr(const Expr *E) {
660660
/*IsDecl=*/false,
661661
{E->getPack()}});
662662
}
663+
664+
void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) {
665+
Refs.push_back(ReferenceLoc{
666+
NestedNameSpecifierLoc(), E->getLocation(),
667+
/*IsDecl=*/false,
668+
// Select the getter, setter, or @property depending on the call.
669+
explicitReferenceTargets(DynTypedNode::create(*E), {})});
670+
}
663671
};
664672

665673
Visitor V;
@@ -780,6 +788,20 @@ class ExplicitReferenceCollector
780788
return true;
781789
}
782790

791+
bool TraverseOpaqueValueExpr(OpaqueValueExpr *OVE) {
792+
visitNode(DynTypedNode::create(*OVE));
793+
// Not clear why the source expression is skipped by default...
794+
// FIXME: can we just make RecursiveASTVisitor do this?
795+
return RecursiveASTVisitor::TraverseStmt(OVE->getSourceExpr());
796+
}
797+
798+
bool TraversePseudoObjectExpr(PseudoObjectExpr *POE) {
799+
visitNode(DynTypedNode::create(*POE));
800+
// Traverse only the syntactic form to find the *written* references.
801+
// (The semantic form also contains lots of duplication)
802+
return RecursiveASTVisitor::TraverseStmt(POE->getSyntacticForm());
803+
}
804+
783805
// We re-define Traverse*, since there's no corresponding Visit*.
784806
// TemplateArgumentLoc is the only way to get locations for references to
785807
// template template parameters.

clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ class FindExplicitReferencesTest : public ::testing::Test {
590590
// parsing.
591591
TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
592592
TU.ExtraArgs.push_back("-std=c++2a");
593+
TU.ExtraArgs.push_back("-xobjective-c++");
593594

594595
auto AST = TU.build();
595596
auto *TestDecl = &findDecl(AST, "foo");
@@ -1124,7 +1125,37 @@ TEST_F(FindExplicitReferencesTest, All) {
11241125
"3: targets = {foo::bar}, decl\n"
11251126
"4: targets = {T}\n"
11261127
"5: targets = {t}, decl\n"
1127-
"6: targets = {t}\n"}};
1128+
"6: targets = {t}\n"},
1129+
// Objective-C: properties
1130+
{
1131+
R"cpp(
1132+
@interface I {}
1133+
@property(retain) I* x;
1134+
@property(retain) I* y;
1135+
@end
1136+
I *f;
1137+
void foo() {
1138+
$0^f.$1^x.$2^y = 0;
1139+
}
1140+
)cpp",
1141+
"0: targets = {f}\n"
1142+
"1: targets = {I::x}\n"
1143+
"2: targets = {I::y}\n"},
1144+
// Objective-C: implicit properties
1145+
{
1146+
R"cpp(
1147+
@interface I {}
1148+
-(I*)x;
1149+
-(void)setY:(I*)y;
1150+
@end
1151+
I *f;
1152+
void foo() {
1153+
$0^f.$1^x.$2^y = 0;
1154+
}
1155+
)cpp",
1156+
"0: targets = {f}\n"
1157+
"1: targets = {I::x}\n"
1158+
"2: targets = {I::setY:}\n"}};
11281159

11291160
for (const auto &C : Cases) {
11301161
llvm::StringRef ExpectedCode = C.first;

0 commit comments

Comments
 (0)