[cfe-commits] r100790 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/libstdcxx_is_pod_hack.cpp test/SemaCXX/libstdcxx_map_base_hack.cpp

Douglas Gregor dgregor at apple.com
Thu Apr 8 11:16:15 PDT 2010


Author: dgregor
Date: Thu Apr  8 13:16:15 2010
New Revision: 100790

URL: http://llvm.org/viewvc/llvm-project?rev=100790&view=rev
Log:
Introduce an egregious hack to work around a bug in libstdc++ 4.2.x's
<tr1/hashtable> header, where a friend class template
std::tr1::__detail::_Map_base is declared with the wrong template
parameters. GCC doesn't catch the problem, so Clang does a little
back-flip to avoid diagnosing just this one instance of the problem.


Added:
    cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp   (with props)
Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=100790&r1=100789&r2=100790&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Apr  8 13:16:15 2010
@@ -688,19 +688,52 @@
       return 0;
     }
 
+    bool AdoptedPreviousTemplateParams = false;
     if (PrevClassTemplate) {
+      bool Complain = true;
+
+      // HACK: libstdc++ 4.2.1 contains an ill-formed friend class
+      // template for struct std::tr1::__detail::_Map_base, where the
+      // template parameters of the friend declaration don't match the
+      // template parameters of the original declaration. In this one
+      // case, we don't complain about the ill-formed friend
+      // declaration.
+      if (isFriend && Pattern->getIdentifier() && 
+          Pattern->getIdentifier()->isStr("_Map_base") &&
+          DC->isNamespace() &&
+          cast<NamespaceDecl>(DC)->getIdentifier() &&
+          cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) {
+        DeclContext *DCParent = DC->getParent();
+        if (DCParent->isNamespace() &&
+            cast<NamespaceDecl>(DCParent)->getIdentifier() &&
+            cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) {
+          DeclContext *DCParent2 = DCParent->getParent();
+          if (DCParent2->isNamespace() &&
+              cast<NamespaceDecl>(DCParent2)->getIdentifier() &&
+              cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") &&
+              DCParent2->getParent()->isTranslationUnit())
+            Complain = false;
+        }
+      }
+
       TemplateParameterList *PrevParams
         = PrevClassTemplate->getTemplateParameters();
 
       // Make sure the parameter lists match.
       if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams,
-                                                  /*Complain=*/true,
-                                                  Sema::TPL_TemplateMatch))
-        return 0;
+                                                  Complain, 
+                                                  Sema::TPL_TemplateMatch)) {
+        if (Complain)
+          return 0;
+
+        AdoptedPreviousTemplateParams = true;
+        InstParams = PrevParams;
+      }
 
       // Do some additional validation, then merge default arguments
       // from the existing declarations.
-      if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
+      if (!AdoptedPreviousTemplateParams &&
+          SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
                                              Sema::TPC_ClassTemplate))
         return 0;
     }

Modified: cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp?rev=100790&r1=100789&r2=100790&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp (original)
+++ cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp Thu Apr  8 13:16:15 2010
@@ -1,5 +1,11 @@
 // RUN: %clang_cc1 -fsyntax-only %s
 
+// This is a test for an egregious hack in Clang that works around
+// issues with GCC's evolution. libstdc++ 4.2.x uses __is_pod as an
+// identifier (to declare a struct template like the one below), while
+// GCC 4.3 and newer make __is_pod a keyword. Clang treats __is_pod as
+// a keyword *unless* it is introduced following the struct keyword.
+
 template<typename T>
 struct __is_pod {
 };

Added: cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp?rev=100790&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp (added)
+++ cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp Thu Apr  8 13:16:15 2010
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+
+// libstdc++ 4.2.x contains a bug where a friend struct template
+// declaration for std::tr1::__detail::_Map base has different
+// template arguments than the real declaration. Clang has an
+// egregious hack to work around this problem, since we can't modify
+// all of the world's libstdc++'s.
+
+namespace std { namespace tr1 { namespace __detail {
+  template<typename _Key, typename _Value, typename _Ex, bool __unique,
+	   typename _Hashtable>
+    struct _Map_base { };
+
+} } } 
+
+namespace std { namespace tr1 {
+  template<typename T>
+  struct X1 {
+    template<typename _Key2, typename _Pair, typename _Hashtable>
+    friend struct __detail::_Map_base;
+  };
+
+} }
+
+std::tr1::X1<int> x1i;

Propchange: cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaCXX/libstdcxx_map_base_hack.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list