std::vector<std::pair<unsigned, unsigned>> Ranges; // Always sorted.
};
-// Dump a node for debugging.
-// DynTypedNode::print() doesn't include the kind of node, which is useful.
-void printNode(llvm::raw_ostream &OS, const DynTypedNode &N,
- const PrintingPolicy &PP) {
+// Show the type of a node for debugging.
+void printNodeKind(llvm::raw_ostream &OS, const DynTypedNode &N) {
if (const TypeLoc *TL = N.get<TypeLoc>()) {
// TypeLoc is a hierarchy, but has only a single ASTNodeKind.
// Synthesize the name from the Type subclass (except for QualifiedTypeLoc).
} else {
OS << N.getNodeKind().asStringRef();
}
- OS << " ";
- N.print(OS, PP);
}
std::string printNodeToString(const DynTypedNode &N, const PrintingPolicy &PP) {
std::string S;
llvm::raw_string_ostream OS(S);
- printNode(OS, N, PP);
+ printNodeKind(OS, N);
+ OS << " ";
return std::move(OS.str());
}
pop();
return true;
}
+ // QualifiedTypeLoc is handled strangely in RecursiveASTVisitor: the derived
+ // TraverseTypeLoc is not called for the inner UnqualTypeLoc.
+ // This means we'd never see 'int' in 'const int'! Work around that here.
+ // (The reason for the behavior is to avoid traversing the nested Type twice,
+ // but we ignore TraverseType anyway).
+ bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QX) {
+ return traverseNode<TypeLoc>(
+ &QX, [&] { return TraverseTypeLoc(QX.getUnqualifiedLoc()); });
+ }
// Uninteresting parts of the AST that don't have locations within them.
bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; }
bool TraverseType(QualType) { return true; }
: '.');
else
OS.indent(Indent);
- printNode(OS, N.ASTNode, PrintPolicy);
+ printNodeKind(OS, N.ASTNode);
+ OS << ' ';
+ N.ASTNode.print(OS, PrintPolicy);
OS << "\n";
for (const Node *Child : N.Children)
print(OS, *Child, Indent + 2);
}
+std::string SelectionTree::Node::kind() const {
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ printNodeKind(OS, ASTNode);
+ return std::move(OS.str());
+}
+
// Decide which selection emulates a "point" query in between characters.
static std::pair<unsigned, unsigned> pointBounds(unsigned Offset, FileID FID,
ASTContext &AST) {
// Walk up the AST to get the DeclContext of this Node,
// which is not the node itself.
const DeclContext& getDeclContext() const;
+ // Printable node kind, like "CXXRecordDecl" or "AutoTypeLoc".
+ std::string kind() const;
};
// The most specific common ancestor of all the selected nodes.
// If there is no selection, this is nullptr.
}
std::string nodeKind(const SelectionTree::Node *N) {
- if (!N)
- return "<null>";
- return N->ASTNode.getNodeKind().asStringRef().str();
+ return N ? N->kind() : "<null>";
}
std::vector<const SelectionTree::Node *> allNodes(const SelectionTree &T) {
struct AAA { struct BBB { static int ccc(); };};
int x = AAA::[[B^B^B]]::ccc();
)cpp",
- "TypeLoc",
+ "RecordTypeLoc",
},
{
R"cpp(
struct AAA { struct BBB { static int ccc(); };};
int x = AAA::[[B^BB^]]::ccc();
)cpp",
- "TypeLoc",
+ "RecordTypeLoc",
},
{
R"cpp(
R"cpp(
[[^void]] (*S)(int) = nullptr;
)cpp",
- "TypeLoc",
+ "BuiltinTypeLoc",
},
{
R"cpp(
[[void (*S)^(int)]] = nullptr;
)cpp",
- "TypeLoc",
+ "FunctionProtoTypeLoc",
},
{
R"cpp(
[[void (^*S)(int)]] = nullptr;
)cpp",
- "TypeLoc",
+ "FunctionProtoTypeLoc",
},
{
R"cpp(
R"cpp(
[[void ^(*S)(int)]] = nullptr;
)cpp",
- "TypeLoc",
+ "FunctionProtoTypeLoc",
},
// Point selections.
{"int bar; void foo() [[{ foo (); }]]^", "CompoundStmt"},
// Tricky case: FunctionTypeLoc in FunctionDecl has a hole in it.
- {"[[^void]] foo();", "TypeLoc"},
- {"[[void foo^()]];", "TypeLoc"},
+ {"[[^void]] foo();", "BuiltinTypeLoc"},
+ {"[[void foo^()]];", "FunctionProtoTypeLoc"},
{"[[^void foo^()]];", "FunctionDecl"},
{"[[void ^foo()]];", "FunctionDecl"},
// Tricky case: two VarDecls share a specifier.
{"[[st^ruct {int x;}]] y;", "CXXRecordDecl"},
{"[[struct {int x;} ^y]];", "VarDecl"},
{"struct {[[int ^x]];} y;", "FieldDecl"},
+ // FIXME: the AST has no location info for qualifiers.
+ {"const [[a^uto]] x = 42;", "AutoTypeLoc"},
+ {"[[co^nst auto x = 42]];", "VarDecl"},
{"^", nullptr},
{"void foo() { [[foo^^]] (); }", "DeclRefExpr"},
{"int x = 42^;", nullptr},
// Node types that have caused problems in the past.
- {"template <typename T> void foo() { [[^T]] t; }", "TypeLoc"},
+ {"template <typename T> void foo() { [[^T]] t; }",
+ "TemplateTypeParmTypeLoc"},
// No crash
{