From 04f627f6b9aeda924a83e75d281ab27a546d3515 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Fri, 3 Jan 2020 12:05:14 +0100 Subject: [PATCH] [Syntax] Build spanning SimpleDecalration for classes, structs, etc When they are free-standing, e.g. `struct X;` or `struct X {};`. Although this complicates the common case (of free-standing class declarations), this ensures the less common case (e.g. `struct X {} a;`) are handled uniformly and produce similar syntax trees. --- clang/lib/Tooling/Syntax/BuildTree.cpp | 10 ++-- clang/unittests/Tooling/Syntax/TreeTest.cpp | 81 ++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index f61c5ff..7357cab 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -343,9 +343,13 @@ public: } bool WalkUpFromTagDecl(TagDecl *C) { - // Avoid building UnknownDeclaration here, syntatically 'struct X {}' and - // similar are part of declaration specifiers and do not introduce a new - // top-level declaration. + // FIXME: build the ClassSpecifier node. + if (C->isFreeStanding()) { + // Class is a declaration specifier and needs a spanning declaration node. + Builder.foldNode(Builder.getRange(C), + new (allocator()) syntax::SimpleDeclaration); + return true; + } return true; } diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp index 4de3530..b54d063 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -591,6 +591,50 @@ namespace foo = a; |-a `-; )txt"}, + // Free-standing classes, must live inside a SimpleDeclaration. + {R"cpp( +sturct X; +struct X {}; + +struct Y *y1; +struct Y {} *y2; + +struct {} *a1; + )cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-sturct +| |-X +| `-; +|-SimpleDeclaration +| |-struct +| |-X +| |-{ +| |-} +| `-; +|-SimpleDeclaration +| |-struct +| |-Y +| |-* +| |-y1 +| `-; +|-SimpleDeclaration +| |-struct +| |-Y +| |-{ +| |-} +| |-* +| |-y2 +| `-; +`-SimpleDeclaration + |-struct + |-{ + |-} + |-* + |-a1 + `-; +)txt"}, {R"cpp( namespace ns {} using namespace ::ns; @@ -646,24 +690,25 @@ template struct X { | |-class | `-T |-> - |-struct - |-X - |-{ - |-UsingDeclaration - | |-using - | |-T - | |-:: - | |-foo - | `-; - |-UsingDeclaration - | |-using - | |-typename - | |-T - | |-:: - | |-bar - | `-; - |-} - `-; + `-SimpleDeclaration + |-struct + |-X + |-{ + |-UsingDeclaration + | |-using + | |-T + | |-:: + | |-foo + | `-; + |-UsingDeclaration + | |-using + | |-typename + | |-T + | |-:: + | |-bar + | `-; + |-} + `-; )txt"}, {R"cpp( using type = int; -- 2.7.4