// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // The nested-name-specifier of a qualified declarator-id shall not begin with a decltype-specifier. class foo { static int i; void func(); }; int decltype(foo())::i; // expected-error{{'decltype' cannot be used to name a declaration}} void decltype(foo())::func() { // expected-error{{'decltype' cannot be used to name a declaration}} } template class tfoo { static int i; void func(); }; template int decltype(tfoo())::i; // expected-error{{nested name specifier 'decltype(tfoo())::' for declaration does not refer into a class, class template or class template partial specialization}} template void decltype(tfoo())::func() { // expected-error{{nested name specifier 'decltype(tfoo())::' for declaration does not refer into a class, class template or class template partial specialization}} } // An init-declarator named with a qualified-id can refer to an element of the // inline namespace set of the named namespace. namespace inline_namespaces { namespace N { inline namespace M { void f(); // expected-note {{possible target}} void g(); extern int m; // expected-note {{candidate}} extern int n; struct S; // expected-note {{candidate}} struct T; enum E : int; // expected-note {{candidate}} enum F : int; template void ft(); // expected-note {{here}} template void gt(); // expected-note {{here}} template extern int mt; // expected-note {{here}} expected-warning {{extension}} template extern int nt; // expected-note {{here}} expected-warning {{extension}} template struct U; // expected-note {{here}} template struct V; // expected-note {{here}} } // When named by unqualified-id, we do *not* look in the inline namespace // set. void f() {} // expected-note {{possible target}} int m; // expected-note {{candidate}} struct S {}; // expected-note {{candidate}} enum E : int {}; // expected-note {{candidate}} static_assert(&f != &M::f, ""); // expected-error {{reference to overloaded function could not be resolved}} static_assert(&m != &M::m, ""); // expected-error {{ambiguous}} typedef S X; // expected-error {{ambiguous}} typedef E Y; // expected-error {{ambiguous}} // When named by (unqualified) template-id, we do look in the inline // namespace set. See [namespace.def]p8, [temp.explicit]p3, // [temp.expl.spec]p2. // // This is not explicitly specified for partial specializations, but // that is just a language defect. template<> void ft() {} template void ft(); // expected-error {{undefined}} template int mt; template<> int mt; template int mt; template int mt; // expected-error {{undefined}} template struct U {}; template<> struct U {}; template struct U; template struct U; // expected-error {{undefined}} } // When named by qualified-id, we *do* look in the inline namespace set. void N::g() {} int N::n; struct N::T {}; enum N::F : int {}; static_assert(&N::g == &N::M::g, ""); static_assert(&N::n == &N::M::n, ""); typedef N::T X; typedef N::M::T X; typedef N::F Y; typedef N::M::F Y; template<> void N::gt() {} template void N::gt(); // expected-error {{undefined}} template int N::nt; template<> int N::nt; template int N::nt; template int N::nt; // expected-error {{undefined}} template struct N::V {}; template<> struct N::V {}; template struct N::V; template struct N::V; // expected-error {{undefined}} struct Q {}; // Perversely, inline anonymous namespaces can cause an ostensibly // external-linkage declaration to acquire internal linkage when // redeclared with a qualified name. inline namespace { struct Q {} q; int f_in_inline(); extern int v_in_inline; typedef int t_in_inline; } // FIXME: These "extra qualification" warnings are bogus: the qualification // changes the meaning of the program. int inline_namespaces::f_in_inline() { // expected-warning {{extra qualification}} // Finds ::Q, not inline_namespaces::Q Q x = q; return 0; } int inline_namespaces::v_in_inline = // expected-warning {{extra qualification}} (Q(q), 0); }