Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 73d6e7e

Browse files
committed
[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... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@256564 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 8b91542 commit 73d6e7e

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

include/clang/ASTMatchers/ASTMatchersInternal.h

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -558,22 +558,32 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
558558
return false;
559559
}
560560

561-
/// \brief Metafunction to determine if type T has a member called getDecl.
561+
// Metafunction to determine if type T has a member called
562+
// getDecl.
563+
#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__)
564+
// For old versions of MSVC, we use a weird nonstandard __if_exists
565+
// statement, since before MSVC2015, it was not standards-conformant
566+
// enough to compile the usual code below.
562567
template <typename T> struct has_getDecl {
563-
struct Default { int getDecl; };
564-
struct Derived : T, Default { };
565-
566-
template<typename C, C> struct CheckT;
567-
568-
// If T::getDecl exists, an ambiguity arises and CheckT will
569-
// not be instantiable. This makes f(...) the only available
570-
// overload.
571-
template<typename C>
572-
static char (&f(CheckT<int Default::*, &C::getDecl>*))[1];
573-
template<typename C> static char (&f(...))[2];
574-
575-
static bool const value = sizeof(f<Derived>(nullptr)) == 2;
568+
__if_exists(T::getDecl) {
569+
enum { value = 1 };
570+
}
571+
__if_not_exists(T::getDecl) {
572+
enum { value = 0 };
573+
}
576574
};
575+
#else
576+
// There is a default template inheriting from "false_type". Then, a
577+
// partial specialization inherits from "true_type". However, this
578+
// specialization will only exist when the call to getDecl() isn't an
579+
// error -- it vanishes by SFINAE when the member doesn't exist.
580+
template <typename> struct type_sink_to_void { typedef void type; };
581+
template <typename T, typename = void> struct has_getDecl : std::false_type {};
582+
template <typename T>
583+
struct has_getDecl<
584+
T, typename type_sink_to_void<decltype(std::declval<T>().getDecl())>::type>
585+
: std::true_type {};
586+
#endif
577587

578588
/// \brief Matches overloaded operators with a specific name.
579589
///

0 commit comments

Comments
 (0)