r346677 - Implement P1094R2 (nested inline namespaces)
Keane, Erich via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 12 12:48:03 PST 2018
Coolbeans, will do! Thanks for the review.
-Erich
From: Richard Smith [mailto:richard at metafoo.co.uk]
Sent: Monday, November 12, 2018 11:59 AM
To: Keane, Erich <erich.keane at intel.com>
Cc: cfe-commits <cfe-commits at lists.llvm.org>
Subject: Re: r346677 - Implement P1094R2 (nested inline namespaces)
On Mon, 12 Nov 2018 at 09:22, Erich Keane via cfe-commits <cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>> wrote:
Author: erichkeane
Date: Mon Nov 12 09:19:48 2018
New Revision: 346677
URL: http://llvm.org/viewvc/llvm-project?rev=346677&view=rev
Log:
Implement P1094R2 (nested inline namespaces)
As approved for the Working Paper in San Diego, support annotating
inline namespaces with 'inline'.
Change-Id: I51a654e11ffb475bf27cccb2458768151619e384
Added:
cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp (with props)
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/www/cxx_status.html
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=346677&r1=346676&r2=346677&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Nov 12 09:19:48 2018
@@ -222,6 +222,11 @@ def ext_nested_namespace_definition : Ex
def warn_cxx14_compat_nested_namespace_definition : Warning<
"nested namespace definition is incompatible with C++ standards before C++17">,
InGroup<CXXPre17Compat>, DefaultIgnore;
+def ext_inline_nested_namespace_definition : ExtWarn<
+ "inline nested namespace definition is a C++2a extension">, InGroup<CXX2a>;
+def warn_cxx17_compat_inline_nested_namespace_definition : Warning<
+ "inline nested namespace definition is incompatible with C++ standards before"
+ " C++2a">, InGroup<CXXPre2aCompat>, DefaultIgnore;
def err_inline_nested_namespace_definition : Error<
"nested namespace definition cannot be 'inline'">;
def err_expected_semi_after_attribute_list : Error<
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=346677&r1=346676&r2=346677&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Nov 12 09:19:48 2018
@@ -2659,9 +2659,16 @@ private:
DeclGroupPtrTy ParseNamespace(DeclaratorContext Context,
SourceLocation &DeclEnd,
SourceLocation InlineLoc = SourceLocation());
- void ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
- std::vector<IdentifierInfo *> &Ident,
- std::vector<SourceLocation> &NamespaceLoc,
+
+ struct InnerNamespaceInfo {
+ SourceLocation NamespaceLoc;
+ SourceLocation InlineLoc;
+ SourceLocation IdentLoc;
+ IdentifierInfo *Ident;
+ };
+ using InnerNamespaceInfoList = llvm::SmallVector<InnerNamespaceInfo, 4>;
+
+ void ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
unsigned int index, SourceLocation &InlineLoc,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker);
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=346677&r1=346676&r2=346677&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Nov 12 09:19:48 2018
@@ -33,24 +33,23 @@ using namespace clang;
/// may either be a top level namespace or a block-level namespace alias. If
/// there was an inline keyword, it has already been parsed.
///
-/// namespace-definition: [C++ 7.3: basic.namespace]
+/// namespace-definition: [C++: namespace.def]
/// named-namespace-definition
/// unnamed-namespace-definition
+/// nested-namespace-definition
+///
+/// named-namespace-definition:
+/// 'inline'[opt] 'namespace' attributes[opt] identifier '{' namespace-body '}'
///
/// unnamed-namespace-definition:
/// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'
///
-/// named-namespace-definition:
-/// original-namespace-definition
-/// extension-namespace-definition
+/// nested-namespace-definition:
+/// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt] identifier '{' namespace-body '}'
///
-/// original-namespace-definition:
-/// 'inline'[opt] 'namespace' identifier attributes[opt]
-/// '{' namespace-body '}'
-///
-/// extension-namespace-definition:
-/// 'inline'[opt] 'namespace' original-namespace-name
-/// '{' namespace-body '}'
+/// enclosing-namespace-specifier:
+/// identifier
+/// enclosing-namespace-specifier '::' 'inline'[opt] identifier
///
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
@@ -70,9 +69,8 @@ Parser::DeclGroupPtrTy Parser::ParseName
SourceLocation IdentLoc;
IdentifierInfo *Ident = nullptr;
- std::vector<SourceLocation> ExtraIdentLoc;
- std::vector<IdentifierInfo*> ExtraIdent;
- std::vector<SourceLocation> ExtraNamespaceLoc;
+ InnerNamespaceInfoList ExtraNSs;
+ SourceLocation FirstNestedInlineLoc;
ParsedAttributesWithRange attrs(AttrFactory);
SourceLocation attrLoc;
@@ -88,15 +86,29 @@ Parser::DeclGroupPtrTy Parser::ParseName
if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
IdentLoc = ConsumeToken(); // eat the identifier.
- while (Tok.is(tok::coloncolon) && NextToken().is(tok::identifier)) {
- ExtraNamespaceLoc.push_back(ConsumeToken());
- ExtraIdent.push_back(Tok.getIdentifierInfo());
- ExtraIdentLoc.push_back(ConsumeToken());
+ while (Tok.is(tok::coloncolon) &&
+ (NextToken().is(tok::identifier) ||
+ (NextToken().is(tok::kw_inline) &&
+ GetLookAheadToken(2).is(tok::identifier)))) {
+
+ InnerNamespaceInfo Info;
+ Info.NamespaceLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_inline)) {
+ Info.InlineLoc = ConsumeToken();
+ if (FirstNestedInlineLoc.isInvalid())
+ FirstNestedInlineLoc = Info.InlineLoc;
+ }
+
+ Info.Ident = Tok.getIdentifierInfo();
+ Info.IdentLoc = ConsumeToken();
+
+ ExtraNSs.push_back(Info);
}
}
// A nested namespace definition cannot have attributes.
- if (!ExtraNamespaceLoc.empty() && attrLoc.isValid())
+ if (!ExtraNSs.empty() && attrLoc.isValid())
Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute);
// Read label attributes, if present.
@@ -138,13 +150,21 @@ Parser::DeclGroupPtrTy Parser::ParseName
return nullptr;
}
- if (ExtraIdent.empty()) {
+ if (ExtraNSs.empty()) {
// Normal namespace definition, not a nested-namespace-definition.
} else if (InlineLoc.isValid()) {
Diag(InlineLoc, diag::err_inline_nested_namespace_definition);
+ } else if (getLangOpts().CPlusPlus2a) {
+ Diag(ExtraNSs[0].NamespaceLoc,
+ diag::warn_cxx14_compat_nested_namespace_definition);
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc,
+ diag::warn_cxx17_compat_inline_nested_namespace_definition);
} else if (getLangOpts().CPlusPlus17) {
- Diag(ExtraNamespaceLoc[0],
+ Diag(ExtraNSs[0].NamespaceLoc,
diag::warn_cxx14_compat_nested_namespace_definition);
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);
} else {
TentativeParsingAction TPA(*this);
SkipUntil(tok::r_brace, StopBeforeMatch);
@@ -152,26 +172,31 @@ Parser::DeclGroupPtrTy Parser::ParseName
TPA.Revert();
if (!rBraceToken.is(tok::r_brace)) {
- Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition)
- << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
+ Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)
+ << SourceRange(ExtraNSs.front().NamespaceLoc,
+ ExtraNSs.back().IdentLoc);
} else {
std::string NamespaceFix;
- for (std::vector<IdentifierInfo*>::iterator I = ExtraIdent.begin(),
- E = ExtraIdent.end(); I != E; ++I) {
+ for (const auto &ExtraNS : ExtraNSs) {
NamespaceFix += " { namespace ";
We should include "inline" here if it was specified. (Eg,"namespace A::inline B" prior to C++17 should produce a fixit rewriting to "namespace A { inline namespace B {".)
- NamespaceFix += (*I)->getName();
+ NamespaceFix += ExtraNS.Ident->getName();
}
std::string RBraces;
- for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i)
+ for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i)
RBraces += "} ";
- Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition)
- << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(),
- ExtraIdentLoc.back()),
- NamespaceFix)
+ Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)
+ << FixItHint::CreateReplacement(
+ SourceRange(ExtraNSs.front().NamespaceLoc,
+ ExtraNSs.back().IdentLoc),
+ NamespaceFix)
<< FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces);
}
+
+ // Warn about nested inline namespaces.
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);
}
// If we're still good, complain about inline namespaces in non-C++0x now.
@@ -192,8 +217,7 @@ Parser::DeclGroupPtrTy Parser::ParseName
// Parse the contents of the namespace. This includes parsing recovery on
// any improperly nested namespaces.
- ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0,
- InlineLoc, attrs, T);
+ ParseInnerNamespace(ExtraNSs, 0, InlineLoc, attrs, T);
// Leave the namespace scope.
NamespaceScope.Exit();
@@ -206,13 +230,11 @@ Parser::DeclGroupPtrTy Parser::ParseName
}
/// ParseInnerNamespace - Parse the contents of a namespace.
-void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
- std::vector<IdentifierInfo *> &Ident,
- std::vector<SourceLocation> &NamespaceLoc,
+void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
unsigned int index, SourceLocation &InlineLoc,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker) {
- if (index == Ident.size()) {
+ if (index == InnerNSs.size()) {
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -233,13 +255,13 @@ void Parser::ParseInnerNamespace(std::ve
ParseScope NamespaceScope(this, Scope::DeclScope);
UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
- getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index],
- Ident[index], Tracker.getOpenLocation(), attrs,
- ImplicitUsingDirectiveDecl);
+ getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc,
+ InnerNSs[index].IdentLoc, InnerNSs[index].Ident,
+ Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl);
assert(!ImplicitUsingDirectiveDecl &&
"nested namespace definition cannot define anonymous namespace");
- ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
+ ParseInnerNamespace(InnerNSs, ++index, InlineLoc,
attrs, Tracker);
NamespaceScope.Exit();
Added: cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp?rev=346677&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp (added)
+++ cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp Mon Nov 12 09:19:48 2018
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++17
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++2a -Wc++17-compat
+
+namespace inline foo1::foo2::foo3 { // expected-error {{expected identifier or '{'}} expected-error {{use of undeclared identifier 'foo1'}}
+}
+
+inline namespace foo4::foo5::foo6 { // expected-error {{nested namespace definition cannot be 'inline'}}}
+}
+
+#if __cplusplus <= 201402L
+// expected-warning at +7 {{nested namespace definition is a C++17 extension; define each namespace separately}}
+// expected-warning at +6 {{inline nested namespace definition is a C++2a extension}}
+#elif __cplusplus <= 201703L
+// expected-warning at +4 {{inline nested namespace definition is a C++2a extension}}
+#else
+// expected-warning at +2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}}
+#endif
+namespace valid1::valid2::inline valid3::inline valid4::valid5{}
+// expected-note at -1 2 {{previous definition is here}}
+
+#if __cplusplus <= 201402L
+// expected-warning at +3 {{nested namespace definition is a C++17 extension; define each namespace separately}}
+#endif
+//expected-warning at +1 2 {{inline namespace reopened as a non-inline namespace}}
+namespace valid1::valid2::valid3::valid4::valid5{}
+
+#if __cplusplus <= 201402L
+// expected-warning at +7 {{nested namespace definition is a C++17 extension; define each namespace separately}}
+// expected-warning at +6 {{inline nested namespace definition is a C++2a extension}}
+#elif __cplusplus <= 201703L
+// expected-warning at +4 {{inline nested namespace definition is a C++2a extension}}
+#else
+// expected-warning at +2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}}
+#endif
+namespace valid1::valid2::inline valid3::inline valid4::valid5{}
+// expected-note at -1 2 {{previous definition is here}}
+
+namespace valid1 {
+ namespace valid2 {
+//expected-warning at +1 {{inline namespace reopened as a non-inline namespace}}
+ namespace valid3 {
+//expected-warning at +1 {{inline namespace reopened as a non-inline namespace}}
+ namespace valid4 {
+ namespace valid5 {
+ }
+ }
+ }
+ }
+}
+
Propchange: cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp
------------------------------------------------------------------------------
svn:keywords = "Author Date Id Rev URL"
Propchange: cfe/trunk/test/Parser/cxx2a-inline-nested-namespace-definition.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=346677&r1=346676&r2=346677&view=diff
==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Mon Nov 12 09:19:48 2018
@@ -1011,7 +1011,7 @@ as the draft C++2a standard evolves.
<tr>
<td>Nested inline namespaces</td>
<td><a href="http://wg21.link/p1094r2">P1094R2</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
</table>
</details>
_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181112/99424568/attachment-0001.html>
More information about the cfe-commits
mailing list