On Mon, 12 Nov 2018 at 09:22, Erich Keane via cfe-commits < 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 > 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