[clang] 2325d6b - [SyntaxTree] Ignore implicit non-leaf `CXXConstructExpr`
Eduardo Caldas via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 8 02:44:34 PDT 2020
Author: Eduardo Caldas
Date: 2020-09-08T09:44:23Z
New Revision: 2325d6b42f096bf93d2ab0bed7096759e5c96ce8
URL: https://github.com/llvm/llvm-project/commit/2325d6b42f096bf93d2ab0bed7096759e5c96ce8
DIFF: https://github.com/llvm/llvm-project/commit/2325d6b42f096bf93d2ab0bed7096759e5c96ce8.diff
LOG: [SyntaxTree] Ignore implicit non-leaf `CXXConstructExpr`
Differential Revision: https://reviews.llvm.org/D86699
Added:
Modified:
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index a9f326439a2a..e5389ae4eff4 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/IgnoreExpr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TypeLoc.h"
@@ -44,8 +45,28 @@
using namespace clang;
+// Ignores the implicit `CXXConstructExpr` for copy/move constructor calls
+// generated by the compiler, as well as in implicit conversions like the one
+// wrapping `1` in `X x = 1;`.
+static Expr *IgnoreImplicitConstructorSingleStep(Expr *E) {
+ if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
+ auto NumArgs = C->getNumArgs();
+ if (NumArgs == 1 || (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
+ Expr *A = C->getArg(0);
+ if (C->getParenOrBraceRange().isInvalid())
+ return A;
+ }
+ }
+ return E;
+}
+
+static Expr *IgnoreImplicit(Expr *E) {
+ return IgnoreExprNodes(E, IgnoreImplicitSingleStep,
+ IgnoreImplicitConstructorSingleStep);
+}
+
LLVM_ATTRIBUTE_UNUSED
-static bool isImplicitExpr(Expr *E) { return E->IgnoreImplicit() != E; }
+static bool isImplicitExpr(Expr *E) { return IgnoreImplicit(E) != E; }
namespace {
/// Get start location of the Declarator from the TypeLoc.
@@ -740,7 +761,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
for (auto *D : DS->decls())
Builder.noticeDeclWithoutSemicolon(D);
} else if (auto *E = dyn_cast_or_null<Expr>(S)) {
- return RecursiveASTVisitor::TraverseStmt(E->IgnoreImplicit());
+ return RecursiveASTVisitor::TraverseStmt(IgnoreImplicit(E));
}
return RecursiveASTVisitor::TraverseStmt(S);
}
@@ -1579,7 +1600,7 @@ void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) {
void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
if (!Child)
return;
- Child = Child->IgnoreImplicit();
+ Child = IgnoreImplicit(Child);
syntax::Tree *ChildNode = Mapping.find(Child);
assert(ChildNode != nullptr);
diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
index aab20008a497..fe89e0d7d1a2 100644
--- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
+++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
@@ -1745,19 +1745,15 @@ TEST_P(SyntaxTreeTest, OverloadedOperator_Plus) {
struct X {
friend X operator+(X, const X&);
};
-// FIXME: Remove additional `UnknownExpression` wrapping `x`. For that, ignore
-// implicit copy constructor called on `x`. This should've been ignored already,
-// as we `IgnoreImplicit` when traversing an `Stmt`.
void test(X x, X y) {
[[x + y]];
}
)cpp",
{R"txt(
BinaryOperatorExpression Expression
-|-UnknownExpression LeftHandSide
-| `-IdExpression
-| `-UnqualifiedId UnqualifiedId
-| `-'x'
+|-IdExpression LeftHandSide
+| `-UnqualifiedId UnqualifiedId
+| `-'x'
|-'+' OperatorToken
`-IdExpression RightHandSide
`-UnqualifiedId UnqualifiedId
@@ -3821,26 +3817,137 @@ TranslationUnit Detached
)txt"));
}
+TEST_P(SyntaxTreeTest, InitDeclarator_Equal) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S { S(int);};
+void test() {
+ [[S s = 1]];
+}
+)cpp",
+ {R"txt(
+SimpleDeclaration
+|-'S'
+`-SimpleDeclarator Declarator
+ |-'s'
+ |-'='
+ `-IntegerLiteralExpression
+ `-'1' LiteralToken
+)txt"}));
+}
+
TEST_P(SyntaxTreeTest, InitDeclarator_Brace) {
if (!GetParam().isCXX11OrLater()) {
return;
}
- EXPECT_TRUE(treeDumpEqual(
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
R"cpp(
-int a {};
+struct S {
+ S();
+ S(int);
+ S(int, float);
+};
+void test(){
+ // FIXME: 's...' is a declarator and '{...}' is initializer
+ [[S s0{}]];
+ [[S s1{1}]];
+ [[S s2{1, 2.}]];
+}
)cpp",
- R"txt(
-TranslationUnit Detached
-`-SimpleDeclaration
- |-'int'
- |-SimpleDeclarator Declarator
- | |-'a'
- | `-UnknownExpression
- | `-UnknownExpression
- | |-'{'
- | `-'}'
- `-';'
-)txt"));
+ {R"txt(
+SimpleDeclaration
+|-'S'
+`-SimpleDeclarator Declarator
+ `-UnknownExpression
+ |-'s0'
+ |-'{'
+ `-'}'
+ )txt",
+ R"txt(
+SimpleDeclaration
+|-'S'
+`-SimpleDeclarator Declarator
+ `-UnknownExpression
+ |-'s1'
+ |-'{'
+ |-IntegerLiteralExpression
+ | `-'1' LiteralToken
+ `-'}'
+ )txt",
+ R"txt(
+SimpleDeclaration
+|-'S'
+`-SimpleDeclarator Declarator
+ `-UnknownExpression
+ |-'s2'
+ |-'{'
+ |-IntegerLiteralExpression
+ | `-'1' LiteralToken
+ |-','
+ |-FloatingLiteralExpression
+ | `-'2.' LiteralToken
+ `-'}'
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, InitDeclarator_EqualBrace) {
+ if (!GetParam().isCXX11OrLater()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ S();
+ S(int);
+ S(int, float);
+};
+void test() {
+ // FIXME: '= {...}' is initializer
+ [[S s0 = {}]];
+ [[S s1 = {1}]];
+ [[S s2 = {1, 2.}]];
+}
+)cpp",
+ {R"txt(
+SimpleDeclaration
+|-'S'
+`-SimpleDeclarator Declarator
+ |-'s0'
+ |-'='
+ `-UnknownExpression
+ |-'{'
+ `-'}'
+ )txt",
+ R"txt(
+SimpleDeclaration
+|-'S'
+`-SimpleDeclarator Declarator
+ |-'s1'
+ |-'='
+ `-UnknownExpression
+ |-'{'
+ |-IntegerLiteralExpression
+ | `-'1' LiteralToken
+ `-'}'
+ )txt",
+ R"txt(
+SimpleDeclaration
+|-'S'
+`-SimpleDeclarator Declarator
+ |-'s2'
+ |-'='
+ `-UnknownExpression
+ |-'{'
+ |-IntegerLiteralExpression
+ | `-'1' LiteralToken
+ |-','
+ |-FloatingLiteralExpression
+ | `-'2.' LiteralToken
+ `-'}'
+)txt"}));
}
TEST_P(SyntaxTreeTest, InitDeclarator_Paren) {
@@ -3851,15 +3958,134 @@ TEST_P(SyntaxTreeTest, InitDeclarator_Paren) {
R"cpp(
struct S {
S(int);
+ S(int, float);
};
-[[S s(1);]]
+// FIXME: 's...' is a declarator and '(...)' is initializer
+[[S s1(1);]]
+[[S s2(1, 2.);]]
)cpp",
{R"txt(
SimpleDeclaration
|-'S'
|-SimpleDeclarator Declarator
| `-UnknownExpression
-| |-'s'
+| |-'s1'
+| |-'('
+| |-IntegerLiteralExpression
+| | `-'1' LiteralToken
+| `-')'
+`-';'
+ )txt",
+ R"txt(
+SimpleDeclaration
+|-'S'
+|-SimpleDeclarator Declarator
+| `-UnknownExpression
+| |-'s2'
+| |-'('
+| |-IntegerLiteralExpression
+| | `-'1' LiteralToken
+| |-','
+| |-FloatingLiteralExpression
+| | `-'2.' LiteralToken
+| `-')'
+`-';'
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, ImplicitConversion_Argument) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct X {
+ X(int);
+};
+void TakeX(const X&);
+void test() {
+ [[TakeX(1)]];
+}
+)cpp",
+ {R"txt(
+CallExpression Expression
+|-IdExpression Callee
+| `-UnqualifiedId UnqualifiedId
+| `-'TakeX'
+|-'(' OpenParen
+|-CallArguments Arguments
+| `-IntegerLiteralExpression ListElement
+| `-'1' LiteralToken
+`-')' CloseParen
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, ImplicitConversion_Return) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct X {
+ X(int);
+};
+X CreateX(){
+ [[return 1;]]
+}
+)cpp",
+ {R"txt(
+ReturnStatement Statement
+|-'return' IntroducerKeyword
+|-IntegerLiteralExpression ReturnValue
+| `-'1' LiteralToken
+`-';'
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, ConstructorCall_ZeroArguments) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct X {
+ X();
+};
+X test() {
+ [[return X();]]
+}
+)cpp",
+ {R"txt(
+ReturnStatement Statement
+|-'return' IntroducerKeyword
+|-UnknownExpression ReturnValue
+| |-'X'
+| |-'('
+| `-')'
+`-';'
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, ConstructorCall_OneArgument) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct X {
+ X(int);
+};
+X test() {
+ // FIXME: Remove `UnknownExpression` due to implicit `CXXFunctionalCastExpr`
+ [[return X(1);]]
+}
+)cpp",
+ {R"txt(
+ReturnStatement Statement
+|-'return' IntroducerKeyword
+|-UnknownExpression ReturnValue
+| `-UnknownExpression
+| |-'X'
| |-'('
| |-IntegerLiteralExpression
| | `-'1' LiteralToken
@@ -3868,6 +4094,58 @@ SimpleDeclaration
)txt"}));
}
+TEST_P(SyntaxTreeTest, ConstructorCall_MultipleArguments) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct X {
+ X(int, char);
+};
+X test() {
+ [[return X(1, '2');]]
+}
+)cpp",
+ {R"txt(
+ReturnStatement Statement
+|-'return' IntroducerKeyword
+|-UnknownExpression ReturnValue
+| |-'X'
+| |-'('
+| |-IntegerLiteralExpression
+| | `-'1' LiteralToken
+| |-','
+| |-CharacterLiteralExpression
+| | `-''2'' LiteralToken
+| `-')'
+`-';'
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, TypeConversion_FunctionalNotation) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+float test() {
+ [[return float(1);]]
+}
+)cpp",
+ {R"txt(
+ReturnStatement Statement
+|-'return' IntroducerKeyword
+|-UnknownExpression ReturnValue
+| |-'float'
+| |-'('
+| |-IntegerLiteralExpression
+| | `-'1' LiteralToken
+| `-')'
+`-';'
+)txt"}));
+}
+
TEST_P(SyntaxTreeTest, ArrayDeclarator_Simple) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(
More information about the cfe-commits
mailing list