r290072 - Fix name hiding and redeclaration checking for dependent local
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Sun Dec 18 14:01:46 PST 2016
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() {
More information about the cfe-commits
mailing list