PR17731: When determining whether a tag and a non-tag were declared in the same
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Oct 2013 01:02:04 +0000 (01:02 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 30 Oct 2013 01:02:04 +0000 (01:02 +0000)
scope, be careful about function-scope declarations (which are not declared in
their semantic context).

llvm-svn: 193671

clang/lib/Sema/SemaLookup.cpp
clang/test/CXX/basic/basic.scope/basic.scope.hiding/p2.cpp

index cca0f22..dba0759 100644 (file)
@@ -337,6 +337,21 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) {
   delete Paths;
 }
 
+/// Get a representative context for a declaration such that two declarations
+/// will have the same context if they were found within the same scope.
+DeclContext *getContextForScopeMatching(Decl *D) {
+  // For function-local declarations, use that function as the context. This
+  // doesn't account for scopes within the function; the caller must deal with
+  // those.
+  DeclContext *DC = D->getLexicalDeclContext();
+  if (DC->isFunctionOrMethod())
+    return DC;
+
+  // Otherwise, look at the semantic context of the declaration. The
+  // declaration must have been found there.
+  return D->getDeclContext()->getRedeclContext();
+}
+
 /// Resolves the result kind of this lookup.
 void LookupResult::resolveKind() {
   unsigned N = Decls.size();
@@ -437,8 +452,8 @@ void LookupResult::resolveKind() {
   // even if they're not visible. (ref?)
   if (HideTags && HasTag && !Ambiguous &&
       (HasFunction || HasNonFunction || HasUnresolved)) {
-    if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals(
-         Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext()))
+    if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals(
+            getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1])))
       Decls[UniqueTagIndex] = Decls[--N];
     else
       Ambiguous = true;
index 911df98..1d2b525 100644 (file)
@@ -22,3 +22,48 @@ void f() {
   Y(1); // okay
 }
 
+namespace PR17731 {
+  void f() {
+    struct S { S() {} };
+    int S(void);
+    int a = S();
+    struct S b;
+    {
+      int S(void);
+      int a = S();
+      struct S c = b;
+    }
+    {
+      struct S { S() {} }; // expected-note {{candidate}}
+      int a = S(); // expected-error {{no viable conversion from 'S'}}
+      struct S c = b; // expected-error {{no viable conversion from 'struct S'}}
+    }
+  }
+  void g() {
+    int S(void);
+    struct S { S() {} };
+    int a = S();
+    struct S b;
+    {
+      int S(void);
+      int a = S();
+      struct S c = b;
+    }
+    {
+      struct S { S() {} }; // expected-note {{candidate}}
+      int a = S(); // expected-error {{no viable conversion from 'S'}}
+      struct S c = b; // expected-error {{no viable conversion from 'struct S'}}
+    }
+  }
+
+  struct A {
+    struct B;
+    void f();
+    int B;
+  };
+  struct A::B {};
+  void A::f() {
+    B = 123;
+    struct B b;
+  }
+}