Author: rsmith Date: Wed May 4 21:13:49 2016 New Revision: 268594 URL: http://llvm.org/viewvc/llvm-project?rev=268594&view=rev Log: Fix implementation of C++'s restrictions on using-declarations referring to enumerators:
* an unscoped enumerator whose enumeration is a class member is itself a class member, so can only be the subject of a class-scope using-declaration. * a scoped enumerator cannot be the subject of a class-scope using-declaration. Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp - copied, changed from r268583, cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp - copied, changed from r268583, cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp Removed: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/test/CXX/drs/dr4xx.cpp cfe/trunk/test/SemaCXX/enum-scoped.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=268594&r1=268593&r2=268594&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May 4 21:13:49 2016 @@ -396,7 +396,9 @@ def note_using_decl_class_member_workaro "use %select{an alias declaration|a typedef declaration|a reference}0 " "instead">; def err_using_decl_can_not_refer_to_namespace : Error< - "using declaration cannot refer to namespace">; + "using declaration cannot refer to a namespace">; +def err_using_decl_can_not_refer_to_scoped_enum : Error< + "using declaration cannot refer to a scoped enumerator">; def err_using_decl_constructor : Error< "using declaration cannot refer to a constructor">; def warn_cxx98_compat_using_decl_constructor : Warning< Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=268594&r1=268593&r2=268594&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed May 4 21:13:49 2016 @@ -7738,7 +7738,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec // function will silently decide not to build a shadow decl, which // will pre-empt further diagnostics. // - // We don't need to do this in C++0x because we do the check once on + // We don't need to do this in C++11 because we do the check once on // the qualifier. // // FIXME: diagnose the following if we care enough: @@ -8227,7 +8227,7 @@ NamedDecl *Sema::BuildUsingDeclaration(S } } - // C++0x N2914 [namespace.udecl]p6: + // C++14 [namespace.udecl]p6: // A using-declaration shall not name a namespace. if (R.getAsSingle<NamespaceDecl>()) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) @@ -8235,6 +8235,16 @@ NamedDecl *Sema::BuildUsingDeclaration(S return BuildInvalid(); } + // C++14 [namespace.udecl]p7: + // A using-declaration shall not name a scoped enumerator. + if (auto *ED = R.getAsSingle<EnumConstantDecl>()) { + if (cast<EnumDecl>(ED->getDeclContext())->isScoped()) { + Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum) + << SS.getRange(); + return BuildInvalid(); + } + } + UsingDecl *UD = BuildValid(); // The normal rules do not apply to inheriting constructor declarations. @@ -8359,8 +8369,10 @@ bool Sema::CheckUsingDeclQualifier(Sourc // If we weren't able to compute a valid scope, it must be a // dependent class scope. - if (!NamedContext || NamedContext->isRecord()) { - auto *RD = dyn_cast_or_null<CXXRecordDecl>(NamedContext); + if (!NamedContext || NamedContext->getRedeclContext()->isRecord()) { + auto *RD = NamedContext + ? cast<CXXRecordDecl>(NamedContext->getRedeclContext()) + : nullptr; if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD)) RD = nullptr; @@ -8444,7 +8456,7 @@ bool Sema::CheckUsingDeclQualifier(Sourc return true; if (getLangOpts().CPlusPlus11) { - // C++0x [namespace.udecl]p3: + // C++11 [namespace.udecl]p3: // In a using-declaration used as a member-declaration, the // nested-name-specifier shall name a base class of the class // being defined. Removed: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp?rev=268593&view=auto ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp (removed) @@ -1,46 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -// C++0x N2914. - -struct B { - void f(char); - void g(char); - enum E { e }; - union { int x; }; -}; - -class C { - int g(); -}; - -class D2 : public B { - using B::f; - using B::e; - using B::x; - using C::g; // expected-error{{using declaration refers into 'C::', which is not a base class of 'D2'}} -}; - -namespace test1 { - struct Base { - int foo(); - }; - - struct Unrelated { - int foo(); - }; - - struct Subclass : Base { - }; - - namespace InnerNS { - int foo(); - } - - // We should be able to diagnose these without instantiation. - template <class T> struct C : Base { - using InnerNS::foo; // expected-error {{not a class}} - using Base::bar; // expected-error {{no member named 'bar'}} - using Unrelated::foo; // expected-error {{not a base class}} - using C::foo; // expected-error {{refers to its own class}} - using Subclass::foo; // expected-error {{not a base class}} - }; -} Copied: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp (from r268583, cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp) URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp?p2=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp&p1=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp&r1=268583&r2=268594&rev=268594&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp Wed May 4 21:13:49 2016 @@ -1,22 +1,48 @@ +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -// C++0x N2914. +// RUN: %clang_cc1 -fsyntax-only -verify %s struct B { void f(char); void g(char); enum E { e }; union { int x; }; + + enum class EC { ec }; // expected-warning 0-1 {{C++11}} + + void f2(char); + void g2(char); + enum E2 { e2 }; + union { int x2; }; }; class C { int g(); }; +struct D : B {}; + class D2 : public B { using B::f; + using B::E; using B::e; using B::x; using C::g; // expected-error{{using declaration refers into 'C::', which is not a base class of 'D2'}} + + // These are valid in C++98 but not in C++11. + using D::f2; + using D::E2; + using D::e2; + using D::x2; +#if __cplusplus >= 201103L + // expected-error@-5 {{using declaration refers into 'D::', which is not a base class of 'D2'}} + // expected-error@-5 {{using declaration refers into 'D::', which is not a base class of 'D2'}} + // expected-error@-5 {{using declaration refers into 'D::', which is not a base class of 'D2'}} + // expected-error@-5 {{using declaration refers into 'D::', which is not a base class of 'D2'}} +#endif + + using B::EC; + using B::EC::ec; // expected-error {{not a class}} expected-warning 0-1 {{C++11}} }; namespace test1 { @@ -35,12 +61,22 @@ namespace test1 { int foo(); } + struct B : Base { + }; + // We should be able to diagnose these without instantiation. template <class T> struct C : Base { using InnerNS::foo; // expected-error {{not a class}} using Base::bar; // expected-error {{no member named 'bar'}} using Unrelated::foo; // expected-error {{not a base class}} - using C::foo; // expected-error {{refers to its own class}} - using Subclass::foo; // expected-error {{not a base class}} + + // In C++98, it's hard to see that these are invalid, because indirect + // references to base class members are permitted. + using C::foo; + using Subclass::foo; +#if __cplusplus >= 201103L + // expected-error@-3 {{refers to its own class}} + // expected-error@-3 {{not a base class}} +#endif }; } Removed: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp?rev=268593&view=auto ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp (removed) @@ -1,8 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// C++0x N2914. - -namespace A { - namespace B { } -} - -using A::B; // expected-error{{using declaration cannot refer to namespace}} Copied: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp (from r268583, cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp) URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp?p2=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp&p1=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp&r1=268583&r2=268594&rev=268594&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp Wed May 4 21:13:49 2016 @@ -1,8 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// C++0x N2914. namespace A { namespace B { } } -using A::B; // expected-error{{using declaration cannot refer to namespace}} +using A::B; // expected-error{{using declaration cannot refer to a namespace}} Modified: cfe/trunk/test/CXX/drs/dr4xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr4xx.cpp?rev=268594&r1=268593&r2=268594&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr4xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr4xx.cpp Wed May 4 21:13:49 2016 @@ -702,8 +702,8 @@ namespace dr460 { // dr460: yes namespace X { namespace Q { int n; } } namespace Y { using X; // expected-error {{requires a qualified name}} - using dr460::X; // expected-error {{cannot refer to namespace}} - using X::Q; // expected-error {{cannot refer to namespace}} + using dr460::X; // expected-error {{cannot refer to a namespace}} + using X::Q; // expected-error {{cannot refer to a namespace}} } } Modified: cfe/trunk/test/SemaCXX/enum-scoped.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum-scoped.cpp?rev=268594&r1=268593&r2=268594&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/enum-scoped.cpp (original) +++ cfe/trunk/test/SemaCXX/enum-scoped.cpp Wed May 4 21:13:49 2016 @@ -298,8 +298,8 @@ namespace PR18044 { int E::*p; // expected-error {{does not point into a class}} using E::f; // expected-error {{no member named 'f'}} - using E::a; // ok! - E b = a; + using E::a; // expected-error {{using declaration cannot refer to a scoped enumerator}} + E b = a; // expected-error {{undeclared}} } namespace test11 { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits