summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td10
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp37
-rw-r--r--clang/test/CXX/drs/dr3xx.cpp10
-rw-r--r--clang/test/Parser/cxx1z-nested-namespace-definition.cpp38
-rw-r--r--clang/test/Parser/nested-namespaces-recovery.cpp24
-rw-r--r--clang/www/cxx_status.html5
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>
OpenPOWER on IntegriCloud