eduucaldas created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
eduucaldas requested review of this revision.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D86699
Files:
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
Index: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
===================================================================
--- clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
+++ clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
@@ -1745,19 +1745,15 @@
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
Index: clang/lib/Tooling/Syntax/BuildTree.cpp
===================================================================
--- clang/lib/Tooling/Syntax/BuildTree.cpp
+++ clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -44,8 +44,80 @@
using namespace clang;
+static Expr *ignoreExprNodesImpl(Expr *E) { return E; }
+template <typename FnTy, typename... FnTys>
+static Expr *ignoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&...Fns) {
+ return ignoreExprNodesImpl(Fn(E), std::forward<FnTys>(Fns)...);
+}
+
+template <typename... FnTys>
+static Expr *ignoreUntilFixedPoint(Expr *E, FnTys &&...Fns) {
+ Expr *LastE = nullptr;
+ while (E != LastE) {
+ LastE = E;
+ E = ignoreExprNodesImpl(E, std::forward<FnTys>(Fns)...);
+ assert(E->getSourceRange() == LastE->getSourceRange());
+ }
+ return E;
+}
+
+static Expr *ignoreImplicitCXXConstructExpr(Expr *E) {
+ if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
+ auto NumArgs = C->getNumArgs();
+ if (NumArgs == 1 || (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
+ auto *A = C->getArg(0);
+ if (A->getSourceRange() == E->getSourceRange())
+ return A;
+ }
+ }
+ return E;
+}
+
+static Expr *ignoreImplicitCast(Expr *E) {
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+
+ auto *UnderlyingE = ICE->getSubExpr();
+ assert(UnderlyingE->getSourceRange() == E->getSourceRange());
+ return UnderlyingE;
+ }
+ return E;
+}
+
+static Expr *ignoreFull(Expr *E) {
+ if (auto *FE = dyn_cast<FullExpr>(E)) {
+ auto *UnderlyingE = FE->getSubExpr();
+ assert(UnderlyingE->getSourceRange() == E->getSourceRange());
+ return UnderlyingE;
+ }
+ return E;
+}
+
+static Expr *ignoreMaterializeTemporary(Expr *E) {
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ auto *UnderlyingE = MTE->getSubExpr();
+ assert(UnderlyingE->getSourceRange() == E->getSourceRange());
+ return UnderlyingE;
+ }
+ return E;
+}
+
+static Expr *ignoreCXXBindTemporary(Expr *E) {
+ if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E)) {
+ auto *UnderlyingE = BTE->getSubExpr();
+ assert(UnderlyingE->getSourceRange() == E->getSourceRange());
+ return UnderlyingE;
+ }
+ return E;
+}
+
+static Expr *ignoreImplicit(Expr *E) {
+ return ignoreUntilFixedPoint(E, ignoreCXXBindTemporary, ignoreImplicitCast,
+ ignoreMaterializeTemporary, ignoreFull,
+ ignoreImplicitCXXConstructExpr);
+}
+
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.
@@ -703,7 +775,7 @@
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);
}
@@ -1575,7 +1647,7 @@
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);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits