Skip to content

Commit

Permalink
Add support for DeclRefExpr in SyntaxTree, by generating IdExpressions
Browse files Browse the repository at this point in the history
Reviewers: gribozavr2

Reviewed By: gribozavr2

Subscribers: hlopko, gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D81168
  • Loading branch information
Eduardo Caldas authored and gribozavr committed Jun 18, 2020
1 parent e7ac984 commit 1b2f6b4
Show file tree
Hide file tree
Showing 4 changed files with 753 additions and 82 deletions.
61 changes: 59 additions & 2 deletions clang/include/clang/Tooling/Syntax/Nodes.h
Expand Up @@ -45,6 +45,7 @@ enum class NodeKind : uint16_t {
BinaryOperatorExpression,
CxxNullPtrExpression,
IntegerLiteralExpression,
IdExpression,

// Statements.
UnknownStatement,
Expand Down Expand Up @@ -84,7 +85,10 @@ enum class NodeKind : uint16_t {
ArraySubscript,
TrailingReturnType,
ParametersAndQualifiers,
MemberPointer
MemberPointer,
NestedNameSpecifier,
NameSpecifier,
UnqualifiedId
};
/// For debugging purposes.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K);
Expand Down Expand Up @@ -150,7 +154,10 @@ enum class NodeRole : uint8_t {
ArraySubscript_sizeExpression,
TrailingReturnType_declarator,
ParametersAndQualifiers_parameter,
ParametersAndQualifiers_trailingReturn
ParametersAndQualifiers_trailingReturn,
IdExpression_id,
IdExpression_qualifier,
NestedNameSpecifier_specifier
};
/// For debugging purposes.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeRole R);
Expand All @@ -177,6 +184,56 @@ class Expression : public Tree {
}
};

/// A sequence of these specifiers make a `nested-name-specifier`.
/// e.g. the `std::` or `vector<int>::` in `std::vector<int>::size`.
class NameSpecifier final : public Tree {
public:
NameSpecifier() : Tree(NodeKind::NameSpecifier) {}
static bool classof(const Node *N) {
return N->kind() == NodeKind::NameSpecifier;
}
};

/// Models a `nested-name-specifier`. C++ [expr.prim.id.qual]
/// e.g. the `std::vector<int>::` in `std::vector<int>::size`.
class NestedNameSpecifier final : public Tree {
public:
NestedNameSpecifier() : Tree(NodeKind::NestedNameSpecifier) {}
static bool classof(const Node *N) {
return N->kind() <= NodeKind::NestedNameSpecifier;
}
std::vector<syntax::NameSpecifier *> specifiers();
};

/// Models an `unqualified-id`. C++ [expr.prim.id.unqual]
/// e.g. the `size` in `std::vector<int>::size`.
class UnqualifiedId final : public Tree {
public:
UnqualifiedId() : Tree(NodeKind::UnqualifiedId) {}
static bool classof(const Node *N) {
return N->kind() == NodeKind::UnqualifiedId;
}
};

/// Models an `id-expression`, e.g. `std::vector<int>::size`.
/// C++ [expr.prim.id]
/// id-expression:
/// unqualified-id
/// qualified-id
/// qualified-id:
/// nested-name-specifier template_opt unqualified-id
class IdExpression final : public Expression {
public:
IdExpression() : Expression(NodeKind::IdExpression) {}
static bool classof(const Node *N) {
return N->kind() == NodeKind::IdExpression;
}
syntax::NestedNameSpecifier *qualifier();
// TODO after expose `id-expression` from `DependentScopeDeclRefExpr`:
// Add accessor for `template_opt`.
syntax::UnqualifiedId *unqualifiedId();
};

/// An expression of an unknown kind, i.e. one not currently handled by the
/// syntax tree.
class UnknownExpression final : public Expression {
Expand Down
39 changes: 39 additions & 0 deletions clang/lib/Tooling/Syntax/BuildTree.cpp
Expand Up @@ -608,6 +608,45 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
return true;
}

syntax::NestedNameSpecifier *
BuildNestedNameSpecifier(NestedNameSpecifierLoc QualifierLoc) {
if (!QualifierLoc)
return nullptr;
for (auto it = QualifierLoc; it; it = it.getPrefix()) {
auto *NS = new (allocator()) syntax::NameSpecifier;
Builder.foldNode(Builder.getRange(it.getLocalSourceRange()), NS, nullptr);
Builder.markChild(NS, syntax::NodeRole::NestedNameSpecifier_specifier);
}
auto *NNS = new (allocator()) syntax::NestedNameSpecifier;
Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), NNS,
nullptr);
return NNS;
}

bool WalkUpFromDeclRefExpr(DeclRefExpr *S) {
if (auto *NNS = BuildNestedNameSpecifier(S->getQualifierLoc()))
Builder.markChild(NNS, syntax::NodeRole::IdExpression_qualifier);

auto *unqualifiedId = new (allocator()) syntax::UnqualifiedId;
// Get `UnqualifiedId` from `DeclRefExpr`.
// FIXME: Extract this logic so that it can be used by `MemberExpr`,
// and other semantic constructs, now it is tied to `DeclRefExpr`.
if (!S->hasExplicitTemplateArgs()) {
Builder.foldNode(Builder.getRange(S->getNameInfo().getSourceRange()),
unqualifiedId, nullptr);
} else {
auto templateIdSourceRange =
SourceRange(S->getNameInfo().getBeginLoc(), S->getRAngleLoc());
Builder.foldNode(Builder.getRange(templateIdSourceRange), unqualifiedId,
nullptr);
}
Builder.markChild(unqualifiedId, syntax::NodeRole::IdExpression_id);

Builder.foldNode(Builder.getExprRange(S),
new (allocator()) syntax::IdExpression, S);
return true;
}

bool WalkUpFromIntegerLiteral(IntegerLiteral *S) {
Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
Builder.foldNode(Builder.getExprRange(S),
Expand Down
37 changes: 35 additions & 2 deletions clang/lib/Tooling/Syntax/Nodes.cpp
Expand Up @@ -28,6 +28,10 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) {
return OS << "PostfixUnaryOperatorExpression";
case NodeKind::BinaryOperatorExpression:
return OS << "BinaryOperatorExpression";
case NodeKind::UnqualifiedId:
return OS << "UnqualifiedId";
case NodeKind::IdExpression:
return OS << "IdExpression";
case NodeKind::UnknownStatement:
return OS << "UnknownStatement";
case NodeKind::DeclarationStatement:
Expand Down Expand Up @@ -94,6 +98,10 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) {
return OS << "ParametersAndQualifiers";
case NodeKind::MemberPointer:
return OS << "MemberPointer";
case NodeKind::NameSpecifier:
return OS << "NameSpecifier";
case NodeKind::NestedNameSpecifier:
return OS << "NestedNameSpecifier";
}
llvm_unreachable("unknown node kind");
}
Expand Down Expand Up @@ -158,10 +166,35 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeRole R) {
return OS << "ParametersAndQualifiers_parameter";
case syntax::NodeRole::ParametersAndQualifiers_trailingReturn:
return OS << "ParametersAndQualifiers_trailingReturn";
case syntax::NodeRole::IdExpression_id:
return OS << "IdExpression_id";
case syntax::NodeRole::IdExpression_qualifier:
return OS << "IdExpression_qualifier";
case syntax::NodeRole::NestedNameSpecifier_specifier:
return OS << "NestedNameSpecifier_specifier";
}
llvm_unreachable("invalid role");
}

std::vector<syntax::NameSpecifier *> syntax::NestedNameSpecifier::specifiers() {
std::vector<syntax::NameSpecifier *> Children;
for (auto *C = firstChild(); C; C = C->nextSibling()) {
assert(C->role() == syntax::NodeRole::NestedNameSpecifier_specifier);
Children.push_back(llvm::cast<syntax::NameSpecifier>(C));
}
return Children;
}

syntax::NestedNameSpecifier *syntax::IdExpression::qualifier() {
return llvm::cast_or_null<syntax::NestedNameSpecifier>(
findChild(syntax::NodeRole::IdExpression_qualifier));
}

syntax::UnqualifiedId *syntax::IdExpression::unqualifiedId() {
return llvm::cast_or_null<syntax::UnqualifiedId>(
findChild(syntax::NodeRole::IdExpression_id));
}

syntax::Leaf *syntax::IntegerLiteralExpression::literalToken() {
return llvm::cast_or_null<syntax::Leaf>(
findChild(syntax::NodeRole::LiteralToken));
Expand Down Expand Up @@ -315,8 +348,8 @@ syntax::Leaf *syntax::CompoundStatement::lbrace() {
std::vector<syntax::Statement *> syntax::CompoundStatement::statements() {
std::vector<syntax::Statement *> Children;
for (auto *C = firstChild(); C; C = C->nextSibling()) {
if (C->role() == syntax::NodeRole::CompoundStatement_statement)
Children.push_back(llvm::cast<syntax::Statement>(C));
assert(C->role() == syntax::NodeRole::CompoundStatement_statement);
Children.push_back(llvm::cast<syntax::Statement>(C));
}
return Children;
}
Expand Down

0 comments on commit 1b2f6b4

Please sign in to comment.