forked from OSchip/llvm-project
[clangd] Support "usedAsMutableReference" in member initializations
That is, mark constructor parameters being used to initialize non-const reference members. Reviewed By: nridge Differential Revision: https://reviews.llvm.org/D128977
This commit is contained in:
parent
865737581a
commit
b1fbc0519c
|
@ -523,6 +523,8 @@ llvm::Optional<HighlightingModifier> scopeModifier(const Type *T) {
|
|||
/// e.g. highlights dependent names and 'auto' as the underlying type.
|
||||
class CollectExtraHighlightings
|
||||
: public RecursiveASTVisitor<CollectExtraHighlightings> {
|
||||
using Base = RecursiveASTVisitor<CollectExtraHighlightings>;
|
||||
|
||||
public:
|
||||
CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
|
||||
|
||||
|
@ -533,6 +535,13 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
|
||||
if (Init->isMemberInitializer())
|
||||
if (auto *Member = Init->getMember())
|
||||
highlightMutableReferenceArgument(Member->getType(), Init->getInit());
|
||||
return Base::TraverseConstructorInitializer(Init);
|
||||
}
|
||||
|
||||
bool VisitCallExpr(CallExpr *E) {
|
||||
// Highlighting parameters passed by non-const reference does not really
|
||||
// make sense for literals...
|
||||
|
@ -542,8 +551,8 @@ public:
|
|||
// FIXME: consider highlighting parameters of some other overloaded
|
||||
// operators as well
|
||||
llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
|
||||
if (const auto callOp = dyn_cast<CXXOperatorCallExpr>(E)) {
|
||||
switch (callOp->getOperator()) {
|
||||
if (auto *CallOp = dyn_cast<CXXOperatorCallExpr>(E)) {
|
||||
switch (CallOp->getOperator()) {
|
||||
case OO_Call:
|
||||
case OO_Subscript:
|
||||
Args = Args.drop_front(); // Drop object parameter
|
||||
|
@ -559,6 +568,33 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void highlightMutableReferenceArgument(QualType T, const Expr *Arg) {
|
||||
if (!Arg)
|
||||
return;
|
||||
|
||||
// Is this parameter passed by non-const reference?
|
||||
// FIXME The condition T->idDependentType() could be relaxed a bit,
|
||||
// e.g. std::vector<T>& is dependent but we would want to highlight it
|
||||
if (!T->isLValueReferenceType() ||
|
||||
T.getNonReferenceType().isConstQualified() || T->isDependentType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
llvm::Optional<SourceLocation> Location;
|
||||
|
||||
// FIXME Add "unwrapping" for ArraySubscriptExpr and UnaryOperator,
|
||||
// e.g. highlight `a` in `a[i]`
|
||||
// FIXME Handle dependent expression types
|
||||
if (auto *DR = dyn_cast<DeclRefExpr>(Arg))
|
||||
Location = DR->getLocation();
|
||||
else if (auto *M = dyn_cast<MemberExpr>(Arg))
|
||||
Location = M->getMemberLoc();
|
||||
|
||||
if (Location)
|
||||
H.addExtraModifier(*Location,
|
||||
HighlightingModifier::UsedAsMutableReference);
|
||||
}
|
||||
|
||||
void
|
||||
highlightMutableReferenceArguments(const FunctionDecl *FD,
|
||||
llvm::ArrayRef<const Expr *const> Args) {
|
||||
|
@ -571,31 +607,7 @@ public:
|
|||
// highlighting modifier to the corresponding expression
|
||||
for (size_t I = 0;
|
||||
I < std::min(size_t(ProtoType->getNumParams()), Args.size()); ++I) {
|
||||
auto T = ProtoType->getParamType(I);
|
||||
|
||||
// Is this parameter passed by non-const reference?
|
||||
// FIXME The condition !T->idDependentType() could be relaxed a bit,
|
||||
// e.g. std::vector<T>& is dependent but we would want to highlight it
|
||||
if (T->isLValueReferenceType() &&
|
||||
!T.getNonReferenceType().isConstQualified() &&
|
||||
!T->isDependentType()) {
|
||||
if (auto *Arg = Args[I]) {
|
||||
llvm::Optional<SourceLocation> Location;
|
||||
|
||||
// FIXME Add "unwrapping" for ArraySubscriptExpr and UnaryOperator,
|
||||
// e.g. highlight `a` in `a[i]`
|
||||
// FIXME Handle dependent expression types
|
||||
if (auto *DR = dyn_cast<DeclRefExpr>(Arg)) {
|
||||
Location = DR->getLocation();
|
||||
} else if (auto *M = dyn_cast<MemberExpr>(Arg)) {
|
||||
Location = M->getMemberLoc();
|
||||
}
|
||||
|
||||
if (Location)
|
||||
H.addExtraModifier(*Location,
|
||||
HighlightingModifier::UsedAsMutableReference);
|
||||
}
|
||||
}
|
||||
highlightMutableReferenceArgument(ProtoType->getParamType(I), Args[I]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -745,6 +745,23 @@ sizeof...($TemplateParameter[[Elements]]);
|
|||
int &operator[](int &);
|
||||
int operator[](int) const;
|
||||
};
|
||||
struct $Class_decl[[ClassWithStaticMember]] {
|
||||
static inline int $StaticField_decl_static[[j]] = 0;
|
||||
};
|
||||
struct $Class_decl[[ClassWithRefMembers]] {
|
||||
$Class_decl[[ClassWithRefMembers]](int $Parameter_decl[[i]])
|
||||
: $Field[[i1]]($Parameter[[i]]),
|
||||
$Field_readonly[[i2]]($Parameter[[i]]),
|
||||
$Field[[i3]]($Parameter_usedAsMutableReference[[i]]),
|
||||
$Field_readonly[[i4]]($Class[[ClassWithStaticMember]]::$StaticField_static[[j]]),
|
||||
$Field[[i5]]($Class[[ClassWithStaticMember]]::$StaticField_static_usedAsMutableReference[[j]])
|
||||
{}
|
||||
int $Field_decl[[i1]];
|
||||
const int &$Field_decl_readonly[[i2]];
|
||||
int &$Field_decl[[i3]];
|
||||
const int &$Field_decl_readonly[[i4]];
|
||||
int &$Field_decl[[i5]];
|
||||
};
|
||||
void $Function_decl[[fun]](int, const int,
|
||||
int*, const int*,
|
||||
int&, const int&,
|
||||
|
|
Loading…
Reference in New Issue