]> granicus.if.org Git - clang/commitdiff
Fix bug in using shadow decl checking: a using shadow decl should not conflict
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 27 Feb 2016 02:36:43 +0000 (02:36 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 27 Feb 2016 02:36:43 +0000 (02:36 +0000)
with a prior UsingDecl -- those should not even really be found by the lookup
here, except that we use the same lookup results for two different checks, and
the other check needs them.

This happens to work in *almost all* cases, because either the lookup results
list the UsingDecl first (and the NonTag result gets replaced by something
else) or because the problematic declaration is a function (which causes us to
use different logic to detect conflicts). This can also be triggered from a
state only reachable through modules (where the name lookup results can contain
multiple UsingDecls in the same scope).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@262105 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/using-decl-1.cpp

index 38901203416691499f91a89cf8b43995cf06928b..e7c3b6af0277024415d50fa6bb6fde838ccc37f1 100644 (file)
@@ -7796,6 +7796,12 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
   for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
          I != E; ++I) {
     NamedDecl *D = (*I)->getUnderlyingDecl();
+    // We can have UsingDecls in our Previous results because we use the same
+    // LookupResult for checking whether the UsingDecl itself is a valid
+    // redeclaration.
+    if (isa<UsingDecl>(D))
+      continue;
+
     if (IsEquivalentForUsingDecl(Context, D, Target)) {
       if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
         PrevShadow = Shadow;
index ec45b3109a0b64ec98fc062a131d1bf0d04bbc67..e17612d277c8485cd908ed85ef8b86384d904eac 100644 (file)
@@ -338,3 +338,26 @@ struct B : A {
   enum { X = sizeof(field) };
 };
 }
+
+namespace tag_vs_var {
+  namespace N {
+    struct X {};
+
+    struct Y {};
+    int Y;
+
+    int Z;
+  }
+  using N::X;
+  using N::Y;
+  using N::Z;
+
+  namespace N {
+    int X;
+
+    struct Z {};
+  }
+  using N::X;
+  using N::Y;
+  using N::Z;
+}