[llvm-commits] [llvm] r170036 - in /llvm/trunk: include/llvm/Support/YAMLTraits.h lib/Support/YAMLTraits.cpp

Nick Kledzik kledzik at apple.com
Thu Dec 13 15:04:34 PST 2012


My trait stuff that I committed yesterday builds with clang and Visual Studio, but was failing with gcc-4.x on various *nix platforms.  To unblock the build  bots, I used #if 0 to conditionalize away the failing test cases in unittests/Support/YAMLIOTest.cpp. 

I reconfigured llvm to build with an old llvm-gcc-4.2 compiler I have, and saw many compilation errors with YAMLIOTest.cpp.  I used some different SFINAE techniques and now have trait testing that works with gcc-4.2 and clang.    

Ben and Michael, could you try putting in this new include/llvm/Support/YAMLTraits.h, enabling the tests in unittests/Support/YAMLIOTest.cpp, and build SupportTests with your compiler to verify these traits work?  Thanks!

-------------- next part --------------
A non-text attachment was scrubbed...
Name: YAMLTraits.h
Type: application/octet-stream
Size: 35129 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121213/81753c7d/attachment.obj>
-------------- next part --------------


-Nick


Index: include/llvm/Support/YAMLTraits.h
===================================================================
--- include/llvm/Support/YAMLTraits.h	(revision 170156)
+++ include/llvm/Support/YAMLTraits.h	(working copy)
@@ -227,10 +227,9 @@
 };
 
 
-// Test if SequenceTraits<T> is defined on type T
-// and SequenceTraits<T>::flow is *not* defined.
+// Test if SequenceTraits<T> is defined on type T.
 template <class T>
-struct has_SequenceTraits
+struct has_SequenceMethodTraits
 {
   typedef size_t (*Signature_size)(class IO&, T&);
 
@@ -240,43 +239,59 @@
   template <typename U>
   static double test(...);
 
-  template <typename U> static
-  char flowtest( char[sizeof(&U::flow)] ) ;
+public:
+  static bool const value =  (sizeof(test<SequenceTraits<T> >(0)) == 1);
+};
 
-  template <typename U>
-  static double flowtest(...);
 
+// has_FlowTraits<int> will cause an error with some compilers because
+// it subclasses int.  Using this wrapper only instantiates the
+// real has_FlowTraits only if the template type is a class.
+template <typename T, bool Enabled = llvm::is_class<T>::value>
+class has_FlowTraits
+{
 public:
-  static bool const value =  (sizeof(test<SequenceTraits<T> >(0)) == 1)
-                          && (sizeof(flowtest<T>(0)) != 1);
+   static const bool value = false;
 };
 
-
-// Test if SequenceTraits<T> is defined on type T
-// and SequenceTraits<T>::flow is defined.
+// Some older gcc compilers don't support straight forward tests
+// for members, so test for ambiguity cause by the base and derived
+// classes both defining the member.
 template <class T>
-struct has_FlowSequenceTraits
+struct has_FlowTraits<T, true>
 {
-  typedef size_t (*Signature_size)(class IO&, T&);
+  struct Fallback { bool flow; };
+  struct Derived : T, Fallback { };
 
-  template <typename U>
-  static char test(SameType<Signature_size, &U::size>*);
+  template<typename C>
+  static char (&f(SameType<bool Fallback::*, &C::flow>*))[1];
 
-  template <typename U>
-  static double test(...);
+  template<typename C>
+  static char (&f(...))[2];
 
-  template <typename U> static
-  char flowtest( char[sizeof(&U::flow)] ) ;
-
-  template <typename U>
-  static double flowtest(...);
-
 public:
-  static bool const value =  (sizeof(test<SequenceTraits<T> >(0)) == 1)
-                          && (sizeof(flowtest<T>(0)) == 1);
+  static bool const value = sizeof(f<Derived>(0)) == 2;
 };
 
 
+
+// Test if SequenceTraits<T> is defined on type T
+// and SequenceTraits<T>::flow is *not* defined.
+template<typename T>
+struct has_SequenceTraits : public  llvm::integral_constant<bool,
+                                         has_SequenceMethodTraits<T>::value
+                                      && !has_FlowTraits<T>::value > { };
+
+
+// Test if SequenceTraits<T> is defined on type T
+// and SequenceTraits<T>::flow is defined.
+template<typename T>
+struct has_FlowSequenceTraits : public llvm::integral_constant<bool,
+                                         has_SequenceMethodTraits<T>::value
+                                      && has_FlowTraits<T>::value > { };
+
+
+
 // Test if DocumentListTraits<T> is defined on type T
 template <class T>
 struct has_DocumentListTraits



More information about the llvm-commits mailing list