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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to