This revision was automatically updated to reflect the committed changes. Closed by commit rGbed75faf7d76: [Clang] Reject programs declaring namespace std to be inline (authored by rZhBoYao).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D156063/new/ https://reviews.llvm.org/D156063 Files: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp =================================================================== --- clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp +++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s // FIXME: We should probably suppress the warning on reopening an inline // namespace without the inline keyword if it's not the first opening of the @@ -16,3 +16,11 @@ inline namespace {} // expected-note {{previous definition}} namespace {} // expected-warning {{inline namespace reopened as a non-inline namespace}} } + +namespace std {} +inline namespace std {} // expected-error{{cannot declare the namespace 'std' to be inline}} +inline namespace std::foo {} // expected-error{{cannot declare the namespace 'std' to be inline}} + // expected-error@-1{{nested namespace definition cannot be 'inline'}} +namespace foo::inline std {} // expected-note {{previous definition}} +namespace foo { inline namespace std {} } // OK +namespace foo { namespace std {} } // expected-warning {{inline namespace reopened as a non-inline namespace}} Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -11388,6 +11388,20 @@ NamespaceDecl *PrevNS = nullptr; if (II) { + // C++ [namespace.std]p7: + // A translation unit shall not declare namespace std to be an inline + // namespace (9.8.2). + // + // Precondition: the std namespace is in the file scope and is declared to + // be inline + auto DiagnoseInlineStdNS = [&]() { + assert(IsInline && II->isStr("std") && + CurContext->getRedeclContext()->isTranslationUnit() && + "Precondition of DiagnoseInlineStdNS not met"); + Diag(InlineLoc, diag::err_inline_namespace_std) + << SourceRange(InlineLoc, InlineLoc.getLocWithOffset(6)); + IsInline = false; + }; // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not // have been previously defined in the declarative region in @@ -11408,7 +11422,10 @@ if (PrevNS) { // This is an extended namespace definition. - if (IsInline != PrevNS->isInline()) + if (IsInline && II->isStr("std") && + CurContext->getRedeclContext()->isTranslationUnit()) + DiagnoseInlineStdNS(); + else if (IsInline != PrevNS->isInline()) DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II, &IsInline, PrevNS); } else if (PrevDecl) { @@ -11420,6 +11437,8 @@ // Continue on to push Namespc as current DeclContext and return it. } else if (II->isStr("std") && CurContext->getRedeclContext()->isTranslationUnit()) { + if (IsInline) + DiagnoseInlineStdNS(); // This is the first "real" definition of the namespace "std", so update // our cache of the "std" namespace to point at this definition. PrevNS = getStdNamespace(); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1579,6 +1579,8 @@ InGroup<InlineNamespaceReopenedNoninline>; def err_inline_namespace_mismatch : Error< "non-inline namespace cannot be reopened as inline">; +def err_inline_namespace_std : Error< + "cannot declare the namespace 'std' to be inline">; def err_unexpected_friend : Error< "friends can only be classes or functions">; Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -84,6 +84,7 @@ directly rather than instantiating the definition from the standard library. - Implemented `CWG2518 <https://wg21.link/CWG2518>`_ which allows ``static_assert(false)`` to not be ill-formed when its condition is evaluated in the context of a template definition. +- Declaring namespace std to be an inline namespace is now prohibited, `[namespace.std]p7`. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^
Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp =================================================================== --- clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp +++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s // FIXME: We should probably suppress the warning on reopening an inline // namespace without the inline keyword if it's not the first opening of the @@ -16,3 +16,11 @@ inline namespace {} // expected-note {{previous definition}} namespace {} // expected-warning {{inline namespace reopened as a non-inline namespace}} } + +namespace std {} +inline namespace std {} // expected-error{{cannot declare the namespace 'std' to be inline}} +inline namespace std::foo {} // expected-error{{cannot declare the namespace 'std' to be inline}} + // expected-error@-1{{nested namespace definition cannot be 'inline'}} +namespace foo::inline std {} // expected-note {{previous definition}} +namespace foo { inline namespace std {} } // OK +namespace foo { namespace std {} } // expected-warning {{inline namespace reopened as a non-inline namespace}} Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -11388,6 +11388,20 @@ NamespaceDecl *PrevNS = nullptr; if (II) { + // C++ [namespace.std]p7: + // A translation unit shall not declare namespace std to be an inline + // namespace (9.8.2). + // + // Precondition: the std namespace is in the file scope and is declared to + // be inline + auto DiagnoseInlineStdNS = [&]() { + assert(IsInline && II->isStr("std") && + CurContext->getRedeclContext()->isTranslationUnit() && + "Precondition of DiagnoseInlineStdNS not met"); + Diag(InlineLoc, diag::err_inline_namespace_std) + << SourceRange(InlineLoc, InlineLoc.getLocWithOffset(6)); + IsInline = false; + }; // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not // have been previously defined in the declarative region in @@ -11408,7 +11422,10 @@ if (PrevNS) { // This is an extended namespace definition. - if (IsInline != PrevNS->isInline()) + if (IsInline && II->isStr("std") && + CurContext->getRedeclContext()->isTranslationUnit()) + DiagnoseInlineStdNS(); + else if (IsInline != PrevNS->isInline()) DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II, &IsInline, PrevNS); } else if (PrevDecl) { @@ -11420,6 +11437,8 @@ // Continue on to push Namespc as current DeclContext and return it. } else if (II->isStr("std") && CurContext->getRedeclContext()->isTranslationUnit()) { + if (IsInline) + DiagnoseInlineStdNS(); // This is the first "real" definition of the namespace "std", so update // our cache of the "std" namespace to point at this definition. PrevNS = getStdNamespace(); Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1579,6 +1579,8 @@ InGroup<InlineNamespaceReopenedNoninline>; def err_inline_namespace_mismatch : Error< "non-inline namespace cannot be reopened as inline">; +def err_inline_namespace_std : Error< + "cannot declare the namespace 'std' to be inline">; def err_unexpected_friend : Error< "friends can only be classes or functions">; Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -84,6 +84,7 @@ directly rather than instantiating the definition from the standard library. - Implemented `CWG2518 <https://wg21.link/CWG2518>`_ which allows ``static_assert(false)`` to not be ill-formed when its condition is evaluated in the context of a template definition. +- Declaring namespace std to be an inline namespace is now prohibited, `[namespace.std]p7`. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits