summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-12-18 22:01:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-12-18 22:01:46 +0000
commit4eeaec46f7de16898a2feb440d064cd1eac1dc2f (patch)
tree518568cd030a335b88c9251b9a588a9caadc4972 /clang
parentd8a9e375582fea89906d89f7fca4cbf0b240346f (diff)
downloadbcm5719-llvm-4eeaec46f7de16898a2feb440d064cd1eac1dc2f.tar.gz
bcm5719-llvm-4eeaec46f7de16898a2feb440d064cd1eac1dc2f.zip
Fix name hiding and redeclaration checking for dependent local
using-declarations. llvm-svn: 290072
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp40
-rw-r--r--clang/lib/Sema/SemaLookup.cpp9
-rw-r--r--clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp39
3 files changed, 49 insertions, 39 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 4742995926f..ac643af1490 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9247,6 +9247,8 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
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(SourceLocation UsingLoc,
// 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(SourceLocation UsingLoc,
= 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?
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 1fc6d4fd515..38a7b8c127c 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -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.
diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
index 8f6638e6943..0ea4eeb1e9b 100644
--- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
+++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
@@ -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::Xs; // expected-note {{hidden by}}
+ struct Xs {};
+ (void)Xs;
+ Xs xs; // expected-error {{must use 'struct'}}
- 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::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}}
+ struct Ys {};
+ using T::Ys; // expected-note {{hidden by}}
+ (void)Ys;
+ Ys ys; // expected-error {{must use 'struct'}}
- 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}}
+ enum Ye {};
+ using T::Ye; // expected-note {{hidden by}}
+ Ye ye; // expected-error {{must use 'enum'}}
}
template<typename T> void type() {
OpenPOWER on IntegriCloud