forked from OSchip/llvm-project
[SyntaxTree] Ignore implicit non-leaf `CXXConstructExpr`
Differential Revision: https://reviews.llvm.org/D86699
This commit is contained in:
parent
83d82d1fb1
commit
2325d6b42f
|
@ -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 @@ public:
|
|||
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);
|
||||
|
|
|
@ -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,19 +3958,190 @@ 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
|
||||
| `-')'
|
||||
`-';'
|
||||
)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"}));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue