Summary:
For the constructor Foo() : classmember(arg) {}
The AST looks like:
- CXXCtorInitializer classmember(arg)
- CXXConstructExpr classmember(arg)
- DeclRefExpr: arg
We want the 'classmember' to be associated with the CXXCtorInitializer, not the
CXXConstructExpr. (CXXConstructExpr is known to have bad ranges).
So just early-claim it.
Thanks @hokein for tracking down/reducing the bug.
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits, hokein
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70312
#include "Logger.h"
#include "SourceCode.h"
#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecursiveASTVisitor.h"
// int (*[[s]])();
else if (auto *VD = llvm::dyn_cast<VarDecl>(D))
return VD->getLocation();
+ } else if (const auto* CCI = N.get<CXXCtorInitializer>()) {
+ // : [[b_]](42)
+ return CCI->getMemberLocation();
}
return SourceRange();
}
// Tricky case: two VarDecls share a specifier.
{"[[int ^a]], b;", "VarDecl"},
{"[[int a, ^b]];", "VarDecl"},
+ // Tricky case: CXXConstructExpr wants to claim the whole init range.
+ {
+ R"cpp(
+ class X { X(int); };
+ class Y {
+ X x;
+ Y() : [[^x(4)]] {}
+ };
+ )cpp",
+ "CXXCtorInitializer", // Not the CXXConstructExpr!
+ },
// Tricky case: anonymous struct is a sibling of the VarDecl.
{"[[st^ruct {int x;}]] y;", "CXXRecordDecl"},
{"[[struct {int x;} ^y]];", "VarDecl"},