r184395 - Add a workaround for a libstdc++-4.2 <tr1/hashtable> bug. This header uses

Richard Smith richard-llvm at metafoo.co.uk
Wed Jun 19 19:18:32 PDT 2013


Author: rsmith
Date: Wed Jun 19 21:18:31 2013
New Revision: 184395

URL: http://llvm.org/viewvc/llvm-project?rev=184395&view=rev
Log:
Add a workaround for a libstdc++-4.2 <tr1/hashtable> bug. This header uses

  return false;

in a function returning a pointer. 'false' was a null pointer constant in C++98
but is not in C++11. Punch a very small hole in the initialization rules in
C++11 mode to allow this specific case in system headers.

Added:
    cfe/trunk/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp
Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=184395&r1=184394&r2=184395&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jun 19 21:18:31 2013
@@ -4135,6 +4135,24 @@ static void TryUserDefinedConversion(Sem
   }
 }
 
+/// An egregious hack for compatibility with libstdc++-4.2: in <tr1/hashtable>,
+/// a function with a pointer return type contains a 'return false;' statement.
+/// In C++11, 'false' is not a null pointer, so this breaks the build of any
+/// code using that header.
+///
+/// Work around this by treating 'return false;' as zero-initializing the result
+/// if it's used in a pointer-returning function in a system header.
+static bool isLibstdcxxPointerReturnFalseHack(Sema &S,
+                                              const InitializedEntity &Entity,
+                                              const Expr *Init) {
+  return S.getLangOpts().CPlusPlus11 &&
+         Entity.getKind() == InitializedEntity::EK_Result &&
+         Entity.getType()->isPointerType() &&
+         isa<CXXBoolLiteralExpr>(Init) &&
+         !cast<CXXBoolLiteralExpr>(Init)->getValue() &&
+         S.getSourceManager().isInSystemHeader(Init->getExprLoc());
+}
+
 /// The non-zero enum values here are indexes into diagnostic alternatives.
 enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };
 
@@ -4571,9 +4589,11 @@ InitializationSequence::InitializationSe
     AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
   } else if (ICS.isBad()) {
     DeclAccessPair dap;
-    if (Initializer->getType() == Context.OverloadTy && 
-          !S.ResolveAddressOfOverloadedFunction(Initializer
-                      , DestType, false, dap))
+    if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {
+      AddZeroInitializationStep(Entity.getType());
+    } else if (Initializer->getType() == Context.OverloadTy &&
+               !S.ResolveAddressOfOverloadedFunction(Initializer, DestType,
+                                                     false, dap))
       SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
     else
       SetFailed(InitializationSequence::FK_ConversionFailed);

Added: cfe/trunk/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp?rev=184395&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp (added)
+++ cfe/trunk/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp Wed Jun 19 21:18:31 2013
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify
+
+// This is a test for an egregious hack in Clang that works around
+// an issue with GCC's <type_traits> implementation. std::common_type
+// relies on pre-standard rules for decltype(), in which it doesn't
+// produce reference types so frequently.
+
+#ifdef BE_THE_HEADER
+
+#pragma GCC system_header
+namespace std {
+  namespace tr1 {
+    template<typename T> struct hashnode;
+    template<typename T> struct hashtable {
+      typedef hashnode<T> node;
+      node *find_node() {
+        // This is ill-formed in C++11, per core issue 903, but we accept
+        // it anyway in a system header.
+        return false;
+      }
+    };
+  }
+}
+
+#else
+
+#define BE_THE_HEADER
+#include "libstdcxx_pointer_return_false_hack.cpp"
+
+auto *test1 = std::tr1::hashtable<int>().find_node();
+
+void *test2() { return false; } // expected-error {{cannot initialize}}
+
+#endif





More information about the cfe-commits mailing list