Coolbeans, will do! Thanks for the review. -Erich
From: Richard Smith [mailto:rich...@metafoo.co.uk] Sent: Monday, November 12, 2018 11:59 AM To: Keane, Erich <erich.ke...@intel.com> Cc: cfe-commits <cfe-commits@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@lists.llvm.org<mailto:cfe-commits@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@+7 {{nested namespace definition is a C++17 extension; define each namespace separately}} +// expected-warning@+6 {{inline nested namespace definition is a C++2a extension}} +#elif __cplusplus <= 201703L +// expected-warning@+4 {{inline nested namespace definition is a C++2a extension}} +#else +// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}} +#endif +namespace valid1::valid2::inline valid3::inline valid4::valid5{} +// expected-note@-1 2 {{previous definition is here}} + +#if __cplusplus <= 201402L +// expected-warning@+3 {{nested namespace definition is a C++17 extension; define each namespace separately}} +#endif +//expected-warning@+1 2 {{inline namespace reopened as a non-inline namespace}} +namespace valid1::valid2::valid3::valid4::valid5{} + +#if __cplusplus <= 201402L +// expected-warning@+7 {{nested namespace definition is a C++17 extension; define each namespace separately}} +// expected-warning@+6 {{inline nested namespace definition is a C++2a extension}} +#elif __cplusplus <= 201703L +// expected-warning@+4 {{inline nested namespace definition is a C++2a extension}} +#else +// expected-warning@+2 {{inline nested namespace definition is incompatible with C++ standards before C++2a}} +#endif +namespace valid1::valid2::inline valid3::inline valid4::valid5{} +// expected-note@-1 2 {{previous definition is here}} + +namespace valid1 { + namespace valid2 { +//expected-warning@+1 {{inline namespace reopened as a non-inline namespace}} + namespace valid3 { +//expected-warning@+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@lists.llvm.org<mailto:cfe-commits@lists.llvm.org> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits