diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -117,9 +117,16 @@
C++ Language Changes in Clang
-----------------------------
+- The oldest supported GNU libstdc++ is now 4.8.3 (released 2014-05-22).
+ Clang workarounds for bugs in earlier versions have been removed.
+
- ...
-C++1z Feature Support
+C++20 Feature Support
+^^^^^^^^^^^^^^^^^^^^^
+...
+
+C++2b Feature Support
^^^^^^^^^^^^^^^^^^^^^
...
diff --git a/clang/docs/Toolchain.rst b/clang/docs/Toolchain.rst
--- a/clang/docs/Toolchain.rst
+++ b/clang/docs/Toolchain.rst
@@ -340,9 +340,10 @@
libstdc++ (GNU)
^^^^^^^^^^^^^^^
-`libstdc++ `_ is GCC's implementation
-of the C++ standard library. Clang supports a wide range of versions of
-libstdc++, from around version 4.2 onwards, and will implicitly work around
-some bugs in older versions of libstdc++.
+`libstdc++ `_ is GCC's
+implementation of the C++ standard library. Clang supports libstdc++
+4.8.3 (released 2014-05-22) and later. Historically Clang implemented
+workarounds for issues discovered in libstdc++, and these are removed
+as fixed libstdc++ becomes sufficiently old.
You can instruct Clang to use libstdc++ with the ``-stdlib=libstdc++`` flag.
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -10874,26 +10874,6 @@
NamespaceDecl *PrevNS) {
assert(*IsInline != PrevNS->isInline());
- // HACK: Work around a bug in libstdc++4.6's , where
- // std::__atomic[0,1,2] are defined as non-inline namespaces, then reopened as
- // inline namespaces, with the intention of bringing names into namespace std.
- //
- // We support this just well enough to get that case working; this is not
- // sufficient to support reopening namespaces as inline in general.
- if (*IsInline && II && II->getName().startswith("__atomic") &&
- S.getSourceManager().isInSystemHeader(Loc)) {
- // Mark all prior declarations of the namespace as inline.
- for (NamespaceDecl *NS = PrevNS->getMostRecentDecl(); NS;
- NS = NS->getPreviousDecl())
- NS->setInline(*IsInline);
- // Patch up the lookup table for the containing namespace. This isn't really
- // correct, but it's good enough for this particular case.
- for (auto *I : PrevNS->decls())
- if (auto *ND = dyn_cast(I))
- PrevNS->getParent()->makeDeclVisibleInContext(ND);
- return;
- }
-
if (PrevNS->isInline())
// The user probably just forgot the 'inline', so suggest that it
// be added back.
diff --git a/clang/test/SemaCXX/libstdcxx_atomic_ns_hack.cpp b/clang/test/SemaCXX/libstdcxx_atomic_ns_hack.cpp
--- a/clang/test/SemaCXX/libstdcxx_atomic_ns_hack.cpp
+++ b/clang/test/SemaCXX/libstdcxx_atomic_ns_hack.cpp
@@ -7,29 +7,28 @@
// namespace to be converted from non-inline to inline in this one specific
// case.
+// the last 4.6 release was 2013, so the hack is removed. This checks __atomic
+// is not special.
#ifdef BE_THE_HEADER
#pragma clang system_header
namespace std {
- namespace __atomic0 {
- typedef int foobar;
- }
- namespace __atomic1 {
- typedef void foobar;
- }
+namespace __atomic0 { // expected-note {{previous definition}}
+typedef int foobar;
+} // namespace __atomic0
+namespace __atomic1 {
+typedef void foobar;
+} // namespace __atomic1
- inline namespace __atomic0 {}
-}
+inline namespace __atomic0 {} // expected-error {{cannot be reopened as inline}}
+} // namespace std
#else
#define BE_THE_HEADER
#include "libstdcxx_atomic_ns_hack.cpp"
-std::foobar fb;
-
-using T = void; // expected-note {{here}}
-using T = std::foobar; // expected-error {{different types ('std::foobar' (aka 'int') vs 'void')}}
+std::foobar fb; // expected-error {{no type named 'foobar' in namespace}}
#endif