diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index 5a09d45649694c..a544fc1827b7d4 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -237,16 +237,16 @@ class List : public Tree { /// /// Useful for discovering the correct delimiter to use when adding /// elements to empty or one-element lists. - clang::tok::TokenKind getDelimiterTokenKind(); + clang::tok::TokenKind getDelimiterTokenKind() const; - TerminationKind getTerminationKind(); + TerminationKind getTerminationKind() const; /// Whether this list can be empty in syntactically and semantically correct /// code. /// /// This list may be empty when the source code has errors even if /// canBeEmpty() returns false. - bool canBeEmpty(); + bool canBeEmpty() const; }; } // namespace syntax diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 1c705f6fd7cfdc..1edd2583105aa9 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -223,7 +223,7 @@ void syntax::Node::assertInvariants() const { else assert(getParent() != nullptr); - auto *T = dyn_cast(this); + const auto *T = dyn_cast(this); if (!T) return; for (const auto *C = T->getFirstChild(); C; C = C->getNextSibling()) { @@ -232,6 +232,19 @@ void syntax::Node::assertInvariants() const { assert(!C->isDetached()); assert(C->getParent() == T); } + + const auto *L = dyn_cast(T); + if (!L) + return; + for (const auto *C = T->getFirstChild(); C; C = C->getNextSibling()) { + assert(C->getRole() == NodeRole::ListElement || + C->getRole() == NodeRole::ListDelimiter); + if (C->getRole() == NodeRole::ListDelimiter) { + assert(isa(C)); + assert(cast(C)->getToken()->kind() == L->getDelimiterTokenKind()); + } + } + #endif } @@ -273,7 +286,7 @@ syntax::Node *syntax::Tree::findChild(NodeRole R) { return nullptr; } -bool classof(const syntax::Node *N) { +bool syntax::List::classof(const syntax::Node *N) { switch (N->getKind()) { case syntax::NodeKind::NestedNameSpecifier: case syntax::NodeKind::CallArguments: @@ -372,7 +385,7 @@ std::vector syntax::List::getElementsAsNodes() { return children; } -clang::tok::TokenKind syntax::List::getDelimiterTokenKind() { +clang::tok::TokenKind syntax::List::getDelimiterTokenKind() const { switch (this->getKind()) { case NodeKind::NestedNameSpecifier: return clang::tok::coloncolon; @@ -385,7 +398,7 @@ clang::tok::TokenKind syntax::List::getDelimiterTokenKind() { } } -syntax::List::TerminationKind syntax::List::getTerminationKind() { +syntax::List::TerminationKind syntax::List::getTerminationKind() const { switch (this->getKind()) { case NodeKind::NestedNameSpecifier: return TerminationKind::Terminated; @@ -398,7 +411,7 @@ syntax::List::TerminationKind syntax::List::getTerminationKind() { } } -bool syntax::List::canBeEmpty() { +bool syntax::List::canBeEmpty() const { switch (this->getKind()) { case NodeKind::NestedNameSpecifier: return false;