Author: rsmith Date: Sun Dec 18 16:01:46 2016 New Revision: 290072 URL: http://llvm.org/viewvc/llvm-project?rev=290072&view=rev Log: Fix name hiding and redeclaration checking for dependent local using-declarations.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=290072&r1=290071&r2=290072&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Dec 18 16:01:46 2016 @@ -9247,6 +9247,8 @@ bool Sema::CheckUsingDeclRedeclaration(S const CXXScopeSpec &SS, SourceLocation NameLoc, const LookupResult &Prev) { + NestedNameSpecifier *Qual = SS.getScopeRep(); + // C++03 [namespace.udecl]p8: // C++0x [namespace.udecl]p10: // A using-declaration is a declaration and can therefore be used @@ -9254,10 +9256,28 @@ bool Sema::CheckUsingDeclRedeclaration(S // allowed. // // That's in non-member contexts. - if (!CurContext->getRedeclContext()->isRecord()) + if (!CurContext->getRedeclContext()->isRecord()) { + // A dependent qualifier outside a class can only ever resolve to an + // enumeration type. Therefore it conflicts with any other non-type + // declaration in the same scope. + // FIXME: How should we check for dependent type-type conflicts at block + // scope? + if (Qual->isDependent() && !HasTypenameKeyword) { + for (auto *D : Prev) { + if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D)) { + bool OldCouldBeEnumerator = + isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D); + Diag(NameLoc, + OldCouldBeEnumerator ? diag::err_redefinition + : diag::err_redefinition_different_kind) + << Prev.getLookupName(); + Diag(D->getLocation(), diag::note_previous_definition); + return true; + } + } + } return false; - - NestedNameSpecifier *Qual = SS.getScopeRep(); + } for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { NamedDecl *D = *I; @@ -9275,19 +9295,7 @@ bool Sema::CheckUsingDeclRedeclaration(S = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { DTypename = true; DQual = UD->getQualifier(); - } else if (!isa<TypeDecl>(D) && Qual->isDependent() && - !HasTypenameKeyword) { - // A dependent qualifier outside a class can only ever resolve to an - // enumeration type. Therefore it conflicts with any other non-type - // declaration in the same scope. - // FIXME: How should we check for dependent type-type conflicts at block - // scope? - Diag(NameLoc, diag::err_redefinition_different_kind) - << Prev.getLookupName(); - Diag(D->getLocation(), diag::note_previous_definition); - return true; - } - else continue; + } else continue; // using decls differ if one says 'typename' and the other doesn't. // FIXME: non-dependent using decls? Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=290072&r1=290071&r2=290072&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Sun Dec 18 16:01:46 2016 @@ -450,15 +450,18 @@ static bool canHideTag(NamedDecl *D) { // Given a set of declarations in a single declarative region [...] // exactly one declaration shall declare a class name or enumeration name // that is not a typedef name and the other declarations shall all refer to - // the same variable or enumerator, or all refer to functions and function - // templates; in this case the class name or enumeration name is hidden. + // the same variable, non-static data member, or enumerator, or all refer + // to functions and function templates; in this case the class name or + // enumeration name is hidden. // C++ [basic.scope.hiding]p2: // A class name or enumeration name can be hidden by the name of a // variable, data member, function, or enumerator declared in the same // scope. + // An UnresolvedUsingValueDecl always instantiates to one of these. D = D->getUnderlyingDecl(); return isa<VarDecl>(D) || isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D) || - isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D); + isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D) || + isa<UnresolvedUsingValueDecl>(D); } /// Resolves the result kind of this lookup. Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp?rev=290072&r1=290071&r2=290072&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp Sun Dec 18 16:01:46 2016 @@ -87,12 +87,12 @@ namespace PR21933 { extern int a(); // expected-error {{different kind of symbol}} a(); - extern int b(); - using T::b; + extern int b(); // expected-note {{previous}} + using T::b; // expected-error {{different kind of symbol}} b(); - using T::c; - using U::c; + using T::c; // expected-note {{previous}} + using U::c; // expected-error-re {{redefinition of 'c'{{$}}}} c(); } @@ -101,29 +101,28 @@ namespace PR21933 { typedef struct {} Xt; // expected-error {{different kind of symbol}} (void)Xt; - using T::Xs; // expected-note {{candidate}} - struct Xs {}; // expected-note {{candidate}} - // FIXME: This is wrong, the using declaration hides the type. - Xs xs; // expected-error {{ambiguous}} - - using T::Xe; // expected-note {{candidate}} - enum Xe {}; // expected-note {{candidate}} - // FIXME: This is wrong, the using declaration hides the type. - Xe xe; // expected-error {{ambiguous}} + using T::Xs; // expected-note {{hidden by}} + struct Xs {}; + (void)Xs; + Xs xs; // expected-error {{must use 'struct'}} + + using T::Xe; // expected-note {{hidden by}} + enum Xe {}; + (void)Xe; + Xe xe; // expected-error {{must use 'enum'}} typedef struct {} Yt; // expected-note {{candidate}} using T::Yt; // eypected-error {{different kind of symbol}} expected-note {{candidate}} Yt yt; // expected-error {{ambiguous}} - struct Ys {}; // expected-note {{candidate}} - using T::Ys; // expected-note {{candidate}} - // FIXME: This is wrong, the using declaration hides the type. - Ys ys; // expected-error {{ambiguous}} - - enum Ye {}; // expected-note {{candidate}} - using T::Ye; // expected-note {{candidate}} - // FIXME: This is wrong, the using declaration hides the type. - Ye ye; // expected-error {{ambiguous}} + struct Ys {}; + using T::Ys; // expected-note {{hidden by}} + (void)Ys; + Ys ys; // expected-error {{must use 'struct'}} + + enum Ye {}; + using T::Ye; // expected-note {{hidden by}} + Ye ye; // expected-error {{must use 'enum'}} } template<typename T> void type() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits