[PATCH] D22808: [Tooling] skip anonymous namespaces when checking if typeLoc references a type decl from a different canonical namespace.

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 26 08:00:41 PDT 2016


This revision was automatically updated to reflect the committed changes.
Closed by commit rL276754: [Tooling] skip anonymous namespaces when checking if typeLoc references a… (authored by ioeric).

Changed prior to commit:
  https://reviews.llvm.org/D22808?vs=65511&id=65520#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D22808

Files:
  cfe/trunk/lib/Tooling/Core/Lookup.cpp
  cfe/trunk/unittests/Tooling/LookupTest.cpp

Index: cfe/trunk/lib/Tooling/Core/Lookup.cpp
===================================================================
--- cfe/trunk/lib/Tooling/Core/Lookup.cpp
+++ cfe/trunk/lib/Tooling/Core/Lookup.cpp
@@ -16,33 +16,46 @@
 using namespace clang;
 using namespace clang::tooling;
 
-static bool isInsideDifferentNamespaceWithSameName(const DeclContext *DeclA,
-                                                   const DeclContext *DeclB) {
+// Returns true if the context in which the type is used and the context in
+// which the type is declared are the same semantical namespace but different
+// lexical namespaces.
+static bool
+usingFromDifferentCanonicalNamespace(const DeclContext *FromContext,
+                                     const DeclContext *UseContext) {
   while (true) {
-    // Look past non-namespaces on DeclA.
-    while (DeclA && !isa<NamespaceDecl>(DeclA))
-      DeclA = DeclA->getParent();
-
-    // Look past non-namespaces on DeclB.
-    while (DeclB && !isa<NamespaceDecl>(DeclB))
-      DeclB = DeclB->getParent();
+    // Look past non-namespaces and anonymous namespaces on FromContext.
+    // We can skip anonymous namespace because:
+    // 1. `FromContext` and `UseContext` must be in the same anonymous
+    // namespaces since referencing across anonymous namespaces is not possible.
+    // 2. If `FromContext` and `UseContext` are in the same anonymous namespace,
+    // the function will still return `false` as expected.
+    while (FromContext &&
+           (!isa<NamespaceDecl>(FromContext) ||
+            cast<NamespaceDecl>(FromContext)->isAnonymousNamespace()))
+      FromContext = FromContext->getParent();
+
+    // Look past non-namespaces and anonymous namespaces on UseContext.
+    while (UseContext &&
+           (!isa<NamespaceDecl>(UseContext) ||
+            cast<NamespaceDecl>(UseContext)->isAnonymousNamespace()))
+      UseContext = UseContext->getParent();
 
     // We hit the root, no namespace collision.
-    if (!DeclA || !DeclB)
+    if (!FromContext || !UseContext)
       return false;
 
     // Literally the same namespace, not a collision.
-    if (DeclA == DeclB)
+    if (FromContext == UseContext)
       return false;
 
     // Now check the names. If they match we have a different namespace with the
     // same name.
-    if (cast<NamespaceDecl>(DeclA)->getDeclName() ==
-        cast<NamespaceDecl>(DeclB)->getDeclName())
+    if (cast<NamespaceDecl>(FromContext)->getDeclName() ==
+        cast<NamespaceDecl>(UseContext)->getDeclName())
       return true;
 
-    DeclA = DeclA->getParent();
-    DeclB = DeclB->getParent();
+    FromContext = FromContext->getParent();
+    UseContext = UseContext->getParent();
   }
 }
 
@@ -98,8 +111,8 @@
   const bool in_global_namespace =
       isa<TranslationUnitDecl>(FromDecl->getDeclContext());
   if (class_name_only && !in_global_namespace &&
-      !isInsideDifferentNamespaceWithSameName(FromDecl->getDeclContext(),
-                                              UseContext)) {
+      !usingFromDifferentCanonicalNamespace(FromDecl->getDeclContext(),
+                                            UseContext)) {
     auto Pos = ReplacementString.rfind("::");
     return Pos != StringRef::npos ? ReplacementString.substr(Pos + 2)
                                   : ReplacementString;
Index: cfe/trunk/unittests/Tooling/LookupTest.cpp
===================================================================
--- cfe/trunk/unittests/Tooling/LookupTest.cpp
+++ cfe/trunk/unittests/Tooling/LookupTest.cpp
@@ -103,6 +103,14 @@
   };
   Visitor.runOver(
       "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
+
+  Visitor.OnCall = [&](CallExpr *Expr) {
+    EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
+  };
+  Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
+                  "namespace a { namespace b { namespace {"
+                  "void f() { foo(); }"
+                  "} } }\n");
 }
 
 } // end anonymous namespace


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D22808.65520.patch
Type: text/x-patch
Size: 3999 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160726/a6f6f897/attachment.bin>


More information about the cfe-commits mailing list