From: Reid Kleckner Date: Tue, 20 Oct 2015 18:12:08 +0000 (+0000) Subject: Look through using decls when classifying implicit member access X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=921c7cf4a8ba1ee52179bee429ee4c3e8cc5b251;p=clang Look through using decls when classifying implicit member access Clang will now accept this valid C++11 code: struct A { int field; }; struct B : A { using A::field; enum { TheSize = sizeof(field) }; }; Previously we would classify the 'field' reference as something other than a field, and then forget to apply the C++11 rule to allow non-static data member references in unevaluated contexts. This usually arises in class templates that want to reference fields of a dependent base in an unevaluated context outside of an instance method. Such contexts do not allow references to 'this', so the only way to access the field is with a using decl and an implicit member reference. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@250839 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 52dfceccb9..9c345f8a69 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -102,8 +102,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, bool hasNonInstance = false; bool isField = false; BaseSet Classes; - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { - NamedDecl *D = *I; + for (NamedDecl *D : R) { + // Look through any using decls. + D = D->getUnderlyingDecl(); if (D->isCXXInstanceMember()) { isField |= isa(D) || isa(D) || @@ -111,8 +112,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, CXXRecordDecl *R = cast(D->getDeclContext()); Classes.insert(R->getCanonicalDecl()); - } - else + } else hasNonInstance = true; } diff --git a/test/SemaCXX/using-decl-1.cpp b/test/SemaCXX/using-decl-1.cpp index ca532692c1..5afd15f8b5 100644 --- a/test/SemaCXX/using-decl-1.cpp +++ b/test/SemaCXX/using-decl-1.cpp @@ -327,3 +327,16 @@ namespace PR24033 { using PR24033::st; // expected-error {{target of using declaration conflicts with declaration already in scope}} } } + +namespace field_use { +struct A { int field; }; +struct B : A { + // Previously Clang rejected this valid C++11 code because it didn't look + // through the UsingShadowDecl. + using A::field; +#if __cplusplus < 201103L + // expected-error@+2 {{invalid use of non-static data member 'field'}} +#endif + enum { X = sizeof(field) }; +}; +}