/// 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) {}
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...
// 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
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) {
// 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]);
}
}
}
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&,