diff options
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 10 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 37 | ||||
| -rw-r--r-- | clang/test/CXX/drs/dr3xx.cpp | 10 | ||||
| -rw-r--r-- | clang/test/Parser/cxx1z-nested-namespace-definition.cpp | 38 | ||||
| -rw-r--r-- | clang/test/Parser/nested-namespaces-recovery.cpp | 24 | ||||
| -rw-r--r-- | clang/www/cxx_status.html | 5 |
6 files changed, 77 insertions, 47 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 7c9ee21d0c2..e9efc45fff2 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -200,8 +200,14 @@ def err_unexpected_namespace_attributes_alias : Error< def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; def err_namespace_nonnamespace_scope : Error< "namespaces can only be defined in global or namespace scope">; -def err_nested_namespaces_with_double_colon : Error< - "nested namespace definition must define each namespace separately">; +def ext_nested_namespace_definition : ExtWarn< + "nested namespace definition is a C++1z extension; " + "define each namespace separately">, InGroup<CXX1z>; +def warn_cxx14_compat_nested_namespace_definition : Warning< + "nested namespace definition is incompatible with C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; +def err_inline_nested_namespace_definition : Error< + "nested namespace definition cannot be 'inline'">; def err_expected_semi_after_attribute_list : Error< "expected ';' after attribute list">; def err_expected_semi_after_static_assert : Error< diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index e5cf84a74f9..223046c90d9 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -110,39 +110,36 @@ Decl *Parser::ParseNamespace(unsigned Context, BalancedDelimiterTracker T(*this, tok::l_brace); if (T.consumeOpen()) { - if (!ExtraIdent.empty()) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) - << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); - } - if (Ident) Diag(Tok, diag::err_expected) << tok::l_brace; else Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; - return nullptr; } if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() || getCurScope()->getFnParent()) { - if (!ExtraIdent.empty()) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) - << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); - } Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace); return nullptr; } - if (!ExtraIdent.empty()) { + if (ExtraIdent.empty()) { + // Normal namespace definition, not a nested-namespace-definition. + } else if (InlineLoc.isValid()) { + Diag(InlineLoc, diag::err_inline_nested_namespace_definition); + } else if (getLangOpts().CPlusPlus1z) { + Diag(ExtraNamespaceLoc[0], + diag::warn_cxx14_compat_nested_namespace_definition); + } else { TentativeParsingAction TPA(*this); SkipUntil(tok::r_brace, StopBeforeMatch); Token rBraceToken = Tok; TPA.Revert(); if (!rBraceToken.is(tok::r_brace)) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); } else { std::string NamespaceFix; @@ -156,7 +153,7 @@ Decl *Parser::ParseNamespace(unsigned Context, for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i) RBraces += "} "; - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()), NamespaceFix) @@ -195,11 +192,11 @@ Decl *Parser::ParseNamespace(unsigned Context, } /// ParseInnerNamespace - Parse the contents of a namespace. -void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, - std::vector<IdentifierInfo*>& Ident, - std::vector<SourceLocation>& NamespaceLoc, - unsigned int index, SourceLocation& InlineLoc, - ParsedAttributes& attrs, +void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, + std::vector<IdentifierInfo *> &Ident, + std::vector<SourceLocation> &NamespaceLoc, + unsigned int index, SourceLocation &InlineLoc, + ParsedAttributes &attrs, BalancedDelimiterTracker &Tracker) { if (index == Ident.size()) { while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { @@ -216,7 +213,9 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, return; } - // Parse improperly nested namespaces. + // Handle a nested namespace definition. + // FIXME: Preserve the source information through to the AST rather than + // desugaring it here. ParseScope NamespaceScope(this, Scope::DeclScope); Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), diff --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp index 8b8bcf1ad98..59deacae3a6 100644 --- a/clang/test/CXX/drs/dr3xx.cpp +++ b/clang/test/CXX/drs/dr3xx.cpp @@ -182,9 +182,15 @@ namespace dr308 { // dr308: yes namespace dr311 { // dr311: yes namespace X { namespace Y {} } - namespace X::Y {} // expected-error {{must define each namespace separately}} + namespace X::Y {} +#if __cplusplus <= 201402L + // expected-error@-2 {{define each namespace separately}} +#endif namespace X { - namespace X::Y {} // expected-error {{must define each namespace separately}} + namespace X::Y {} +#if __cplusplus <= 201402L + // expected-error@-2 {{define each namespace separately}} +#endif } // FIXME: The diagnostics here are not very good. namespace ::dr311::X {} // expected-error 2+{{}} // expected-warning {{extra qual}} diff --git a/clang/test/Parser/cxx1z-nested-namespace-definition.cpp b/clang/test/Parser/cxx1z-nested-namespace-definition.cpp new file mode 100644 index 00000000000..96f34c540ac --- /dev/null +++ b/clang/test/Parser/cxx1z-nested-namespace-definition.cpp @@ -0,0 +1,38 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: not %clang_cc1 -x c++ -fixit %t -Werror -DFIXIT +// RUN: %clang_cc1 -x c++ %t -DFIXIT +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z -Wc++14-compat + +namespace foo1::foo2::foo3 { +#if __cplusplus <= 201400L +// expected-warning@-2 {{nested namespace definition is a C++1z extension; define each namespace separately}} +#else +// expected-warning@-4 {{nested namespace definition is incompatible with C++ standards before C++1z}} +#endif + int foo(int x) { return x; } +} + +#ifndef FIXIT +inline namespace goo::bar { // expected-error {{nested namespace definition cannot be 'inline'}} expected-warning 0-1{{C++11 feature}} + int n; +} + +int m = goo::bar::n; +#endif + +int foo(int x) { + return foo1::foo2::foo3::foo(x); +} + +namespace bar1 { + namespace bar2 { + namespace bar3 { + int bar(int x) { return x; } + } + } +} + +int bar(int x) { + return bar1::bar2::bar3::bar(x); +} diff --git a/clang/test/Parser/nested-namespaces-recovery.cpp b/clang/test/Parser/nested-namespaces-recovery.cpp deleted file mode 100644 index d45938bb3e6..00000000000 --- a/clang/test/Parser/nested-namespaces-recovery.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: cp %s %t -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: not %clang_cc1 -x c++ -fixit %t -// RUN: %clang_cc1 -x c++ %t - -namespace foo1::foo2::foo3 { // expected-error {{nested namespace definition must define each namespace separately}} - int foo(int x) { return x; } -} - -int foo(int x) { - return foo1::foo2::foo3::foo(x); -} - -namespace bar1 { - namespace bar2 { - namespace bar3 { - int bar(int x) { return x; } - } - } -} - -int bar(int x) { - return bar1::bar2::bar3::bar(x); -} diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 565349ab029..20617147f52 100644 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -552,6 +552,11 @@ as the draft C++1z standard evolves.</p> <td><!--<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4051.html">-->N4295<!--</a>--></td> <td class="svn" align="center">SVN</td> </tr> + <tr> + <td>Nested namespace definition</td> + <td><!--<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4051.html">-->N4230<!--</a>--></td> + <td class="svn" align="center">SVN</td> + </tr> </table> <h2 id="ts">Technical specifications and standing documents</h2> |

