Author: jyknight Date: Tue Dec 29 10:44:11 2015 New Revision: 256564 URL: http://llvm.org/viewvc/llvm-project?rev=256564&view=rev Log: [TrailingObjects] Use a different technique to determine if a getDecl member function exists on a class.
The previous trick depended on inheriting from the class it was checking, which will fail when I start marking things 'final'. Attempt #2: now with a special #ifdef branch for MSVC. Hopefully *this* actually builds with all supported compilers... Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=256564&r1=256563&r2=256564&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Tue Dec 29 10:44:11 2015 @@ -558,22 +558,32 @@ bool matchesFirstInPointerRange(const Ma return false; } -/// \brief Metafunction to determine if type T has a member called getDecl. +// Metafunction to determine if type T has a member called +// getDecl. +#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__) +// For old versions of MSVC, we use a weird nonstandard __if_exists +// statement, since before MSVC2015, it was not standards-conformant +// enough to compile the usual code below. template <typename T> struct has_getDecl { - struct Default { int getDecl; }; - struct Derived : T, Default { }; - - template<typename C, C> struct CheckT; - - // If T::getDecl exists, an ambiguity arises and CheckT will - // not be instantiable. This makes f(...) the only available - // overload. - template<typename C> - static char (&f(CheckT<int Default::*, &C::getDecl>*))[1]; - template<typename C> static char (&f(...))[2]; - - static bool const value = sizeof(f<Derived>(nullptr)) == 2; + __if_exists(T::getDecl) { + enum { value = 1 }; + } + __if_not_exists(T::getDecl) { + enum { value = 0 }; + } }; +#else +// There is a default template inheriting from "false_type". Then, a +// partial specialization inherits from "true_type". However, this +// specialization will only exist when the call to getDecl() isn't an +// error -- it vanishes by SFINAE when the member doesn't exist. +template <typename> struct type_sink_to_void { typedef void type; }; +template <typename T, typename = void> struct has_getDecl : std::false_type {}; +template <typename T> +struct has_getDecl< + T, typename type_sink_to_void<decltype(std::declval<T>().getDecl())>::type> + : std::true_type {}; +#endif /// \brief Matches overloaded operators with a specific name. /// _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits