forked from OSchip/llvm-project
Implement DR482: namespace members can be redeclared with a qualified name
within their namespace, and such a redeclaration isn't required to be a definition any more. Update DR status page to say Clang 3.4 instead of SVN and add new Clang 3.5 category (but keep Clang 3.4 yellow for now). llvm-svn: 196481
This commit is contained in:
parent
14e92c2c62
commit
a230224be4
clang
include/clang/Basic
lib/Sema
test
www
|
@ -4458,6 +4458,9 @@ def warn_member_extra_qualification : Warning<
|
|||
"extra qualification on member %0">, InGroup<Microsoft>;
|
||||
def err_member_extra_qualification : Error<
|
||||
"extra qualification on member %0">;
|
||||
def warn_namespace_member_extra_qualification : Warning<
|
||||
"extra qualification on member %0">,
|
||||
InGroup<DiagGroup<"extra-qualification">>;
|
||||
def err_member_qualification : Error<
|
||||
"non-friend class member %0 cannot have a qualified name">;
|
||||
def note_member_def_close_match : Note<"member declaration nearly matches">;
|
||||
|
|
|
@ -4115,33 +4115,31 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
|
|||
/// \returns true if we cannot safely recover from this error, false otherwise.
|
||||
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
|
||||
DeclarationName Name,
|
||||
SourceLocation Loc) {
|
||||
SourceLocation Loc) {
|
||||
DeclContext *Cur = CurContext;
|
||||
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
|
||||
Cur = Cur->getParent();
|
||||
|
||||
// C++ [dcl.meaning]p1:
|
||||
// A declarator-id shall not be qualified except for the definition
|
||||
// of a member function (9.3) or static data member (9.4) outside of
|
||||
// its class, the definition or explicit instantiation of a function
|
||||
// or variable member of a namespace outside of its namespace, or the
|
||||
// definition of an explicit specialization outside of its namespace,
|
||||
// or the declaration of a friend function that is a member of
|
||||
// another class or namespace (11.3). [...]
|
||||
|
||||
// The user provided a superfluous scope specifier that refers back to the
|
||||
// class or namespaces in which the entity is already declared.
|
||||
|
||||
// If the user provided a superfluous scope specifier that refers back to the
|
||||
// class in which the entity is already declared, diagnose and ignore it.
|
||||
//
|
||||
// class X {
|
||||
// void X::f();
|
||||
// };
|
||||
//
|
||||
// Note, it was once ill-formed to give redundant qualification in all
|
||||
// contexts, but that rule was removed by DR482.
|
||||
if (Cur->Equals(DC)) {
|
||||
Diag(Loc, LangOpts.MicrosoftExt? diag::warn_member_extra_qualification
|
||||
: diag::err_member_extra_qualification)
|
||||
<< Name << FixItHint::CreateRemoval(SS.getRange());
|
||||
SS.clear();
|
||||
if (Cur->isRecord()) {
|
||||
Diag(Loc, LangOpts.MicrosoftExt ? diag::warn_member_extra_qualification
|
||||
: diag::err_member_extra_qualification)
|
||||
<< Name << FixItHint::CreateRemoval(SS.getRange());
|
||||
SS.clear();
|
||||
} else {
|
||||
Diag(Loc, diag::warn_namespace_member_extra_qualification) << Name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the qualifying scope encloses the scope of the original
|
||||
// declaration.
|
||||
|
@ -7248,11 +7246,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
}
|
||||
}
|
||||
|
||||
} else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() &&
|
||||
} else if (!D.isFunctionDefinition() &&
|
||||
isa<CXXMethodDecl>(NewFD) && NewFD->isOutOfLine() &&
|
||||
!isFriend && !isFunctionTemplateSpecialization &&
|
||||
!isExplicitSpecialization) {
|
||||
// An out-of-line member function declaration must also be a
|
||||
// definition (C++ [dcl.meaning]p1).
|
||||
// definition (C++ [class.mfct]p2).
|
||||
// Note that this is not the case for explicit specializations of
|
||||
// function templates or member functions of class templates, per
|
||||
// C++ [temp.expl.spec]p2. We also allow these declarations as an
|
||||
|
|
|
@ -12133,11 +12133,13 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
|
|||
// If there is no declaration, there was an error parsing it.
|
||||
if (D == 0 || D->isInvalidDecl()) return;
|
||||
|
||||
// We should only get called for declarations with scope specifiers, like:
|
||||
// int foo::bar;
|
||||
assert(D->isOutOfLine());
|
||||
EnterDeclaratorContext(S, D->getDeclContext());
|
||||
|
||||
// We will always have a nested name specifier here, but this declaration
|
||||
// might not be out of line if the specifier names the current namespace:
|
||||
// extern int n;
|
||||
// int ::n = 0;
|
||||
if (D->isOutOfLine())
|
||||
EnterDeclaratorContext(S, D->getDeclContext());
|
||||
|
||||
// If we are parsing the initializer for a static data member, push a
|
||||
// new expression evaluation context that is associated with this static
|
||||
// data member.
|
||||
|
@ -12152,10 +12154,10 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
|
|||
if (D == 0 || D->isInvalidDecl()) return;
|
||||
|
||||
if (isStaticDataMember(D))
|
||||
PopExpressionEvaluationContext();
|
||||
PopExpressionEvaluationContext();
|
||||
|
||||
assert(D->isOutOfLine());
|
||||
ExitDeclaratorContext(S);
|
||||
if (D->isOutOfLine())
|
||||
ExitDeclaratorContext(S);
|
||||
}
|
||||
|
||||
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
|
||||
|
|
|
@ -29,9 +29,17 @@ namespace NS {
|
|||
template<typename T> void wibble(T);
|
||||
}
|
||||
namespace NS {
|
||||
void NS::foo() {} // expected-error{{extra qualification on member 'foo'}}
|
||||
int NS::bar; // expected-error{{extra qualification on member 'bar'}}
|
||||
struct NS::X { }; // expected-error{{extra qualification on member 'X'}}
|
||||
template<typename T> struct NS::Y; // expected-error{{extra qualification on member 'Y'}}
|
||||
template<typename T> void NS::wibble(T) { } // expected-error{{extra qualification on member 'wibble'}}
|
||||
// Under DR482, these are all valid, except for forward-declaring a struct
|
||||
// with a nested-name-specifier.
|
||||
void NS::foo(); // expected-warning {{extra qualification}}
|
||||
extern int NS::bar; // expected-warning {{extra qualification}}
|
||||
struct NS::X; // expected-error {{forward declaration of struct cannot have a nested name specifier}} expected-warning {{extra qualification}}
|
||||
template<typename T> struct NS::Y; // expected-error {{forward declaration of struct cannot have a nested name specifier}} expected-warning {{extra qualification}}
|
||||
template<typename T> void NS::wibble(T); // expected-warning {{extra qualification}}
|
||||
|
||||
void NS::foo() {} // expected-warning{{extra qualification on member 'foo'}}
|
||||
int NS::bar; // expected-warning{{extra qualification on member 'bar'}}
|
||||
struct NS::X { }; // expected-warning{{extra qualification on member 'X'}}
|
||||
template<typename T> struct NS::Y { }; // expected-warning{{extra qualification on member 'Y'}}
|
||||
template<typename T> void NS::wibble(T) { } // expected-warning{{extra qualification on member 'wibble'}}
|
||||
}
|
||||
|
|
|
@ -592,11 +592,10 @@ namespace dr155 { // dr155: dup 632
|
|||
struct S { int n; } s = { { 1 } }; // expected-warning {{braces around scalar initializer}}
|
||||
}
|
||||
|
||||
namespace dr159 { // dr159: no
|
||||
namespace dr159 { // dr159: 3.5
|
||||
namespace X { void f(); }
|
||||
void f();
|
||||
// FIXME: This should be accepted.
|
||||
void dr159::f() {} // expected-error {{extra qualification}}
|
||||
void dr159::f() {} // expected-warning {{extra qualification}}
|
||||
void dr159::X::f() {}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// expected-no-diagnostics
|
||||
// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
|
||||
namespace dr408 { // dr408: 3.4
|
||||
template<int N> void g() { int arr[N != 1 ? 1 : -1]; }
|
||||
|
@ -30,3 +30,37 @@ namespace dr408 { // dr408: 3.4
|
|||
template<> int R<int>::arr[2];
|
||||
template void R<int>::f();
|
||||
}
|
||||
|
||||
namespace dr482 { // dr482: 3.5
|
||||
extern int a;
|
||||
void f();
|
||||
|
||||
int dr482::a = 0; // expected-warning {{extra qualification}}
|
||||
void dr482::f() {} // expected-warning {{extra qualification}}
|
||||
|
||||
inline namespace X { // expected-error 0-1{{C++11 feature}}
|
||||
extern int b;
|
||||
void g();
|
||||
struct S;
|
||||
}
|
||||
int dr482::b = 0; // expected-warning {{extra qualification}}
|
||||
void dr482::g() {} // expected-warning {{extra qualification}}
|
||||
struct dr482::S {}; // expected-warning {{extra qualification}}
|
||||
|
||||
void dr482::f(); // expected-warning {{extra qualification}}
|
||||
void dr482::g(); // expected-warning {{extra qualification}}
|
||||
|
||||
// FIXME: The following are valid in DR482's wording, but these are bugs in
|
||||
// the wording which we deliberately don't implement.
|
||||
namespace N { typedef int type; }
|
||||
typedef int N::type; // expected-error {{typedef declarator cannot be qualified}}
|
||||
struct A {
|
||||
struct B;
|
||||
struct A::B {}; // expected-error {{extra qualification}}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
enum class C;
|
||||
enum class A::C {}; // expected-error {{extra qualification}}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ template<typename T> int S<T>::a, S<T>::b; // expected-error {{can only declare
|
|||
|
||||
template<typename T> struct A { static A a; } A<T>::a; // expected-error {{expected ';' after struct}} \
|
||||
expected-error {{use of undeclared identifier 'T'}} \
|
||||
expected-error{{extra qualification}}
|
||||
expected-error {{no member named 'a'}} \
|
||||
expected-warning {{extra qualification}}
|
||||
|
||||
template<typename T> struct B { } f(); // expected-error {{expected ';' after struct}} \
|
||||
expected-error {{requires a type specifier}}
|
||||
|
|
|
@ -160,7 +160,7 @@ namespace N {
|
|||
void f();
|
||||
// FIXME: if we move this to a separate definition of N, things break!
|
||||
}
|
||||
void ::global_func2(int) { } // expected-error{{extra qualification on member 'global_func2'}}
|
||||
void ::global_func2(int) { } // expected-warning{{extra qualification on member 'global_func2'}}
|
||||
|
||||
void N::f() { } // okay
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#29">29</a></td>
|
||||
<td>CD1</td>
|
||||
<td>Linkage of locally declared functions</td>
|
||||
<td class="svn" align="center">SVN</td>
|
||||
<td class="svn" align="center">Clang 3.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#30">30</a></td>
|
||||
|
@ -523,7 +523,7 @@
|
|||
<tr>
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#81">81</a></td>
|
||||
<td>NAD</td>
|
||||
<td>Null pointers and C compatibility</td>
|
||||
<td>Null pointers and C compatability</td>
|
||||
<td class="na" align="center">N/A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -854,7 +854,7 @@
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#136">136</a></td>
|
||||
<td>CD1</td>
|
||||
<td>Default arguments and friend declarations</td>
|
||||
<td class="svn" align="center">SVN</td>
|
||||
<td class="svn" align="center">Clang 3.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#137">137</a></td>
|
||||
|
@ -992,7 +992,7 @@
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#159">159</a></td>
|
||||
<td>TC1</td>
|
||||
<td>Namespace qualification in declarators</td>
|
||||
<td class="none" align="center">No</td>
|
||||
<td class="svn" align="center">SVN</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#160">160</a></td>
|
||||
|
@ -2488,7 +2488,7 @@ of class templates</td>
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#408">408</a></td>
|
||||
<td>CD2</td>
|
||||
<td>sizeof applied to unknown-bound array static data member of template</td>
|
||||
<td class="svn" align="center">SVN</td>
|
||||
<td class="svn" align="center">Clang 3.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#409">409</a></td>
|
||||
|
@ -2932,7 +2932,7 @@ of class templates</td>
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#482">482</a></td>
|
||||
<td>DRWP</td>
|
||||
<td>Qualified declarators in redeclarations</td>
|
||||
<td class="none" align="center">Unknown</td>
|
||||
<td class="svn" align="center">SVN</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#483">483</a></td>
|
||||
|
@ -8159,7 +8159,7 @@ and <I>POD class</I></td>
|
|||
<tr class="open">
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1391">1391</a></td>
|
||||
<td>drafting</td>
|
||||
<td>Conversions to parameter types with non-deduced template arguments</td>
|
||||
<td>Conversions to parameter types with non deduced template arguments</td>
|
||||
<td align="center">Not resolved</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -101,9 +101,12 @@ def availability(issue):
|
|||
if status == 'unknown':
|
||||
avail = 'Unknown'
|
||||
avail_style = ' class="none"'
|
||||
elif status == '3.4':
|
||||
elif status == '3.5':
|
||||
avail = 'SVN'
|
||||
avail_style = ' class="svn"'
|
||||
elif status == '3.4':
|
||||
avail = 'Clang %s' % status
|
||||
avail_style = ' class="svn"'
|
||||
elif status in ('3.1', '3.2', '3.3'):
|
||||
avail = 'Clang %s' % status
|
||||
avail_style = ' class="full"'
|
||||
|
|
Loading…
Reference in New Issue