r346677 - Implement P1094R2 (nested inline namespaces)
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 12 11:59:28 PST 2018
On Mon, 12 Nov 2018 at 09:22, Erich Keane via cfe-commits <
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
> 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/2b6fd603/attachment-0001.html>
More information about the cfe-commits
mailing list