Hi djasper, klimek,
Qualify all types used in AST matcher macros. This makes it possible to
put AST matchers in user code into a namespace other than clang::ast_matchers
and this way prevent ODR violations that could happen when a matcher with the
same name is defined in multiple translation units. Updated comments
accordingly.
http://reviews.llvm.org/D10501
Files:
include/clang/ASTMatchers/ASTMatchersMacros.h
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/ASTMatchers/ASTMatchersMacros.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersMacros.h
+++ include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -20,17 +20,21 @@
// to only have the functions (which is all the user cares about) in the
// 'ast_matchers' namespace and hide the boilerplate.
//
-// To define a matcher in user code, always put it into the clang::ast_matchers
-// namespace and refer to the internal types via the 'internal::':
+// To define a matcher in user code, always put it into an unnamed namespace
+// inside the clang::ast_matchers namespace and refer to the internal types via
+// the 'internal::'. This would help to prevent ODR violations in case a
+// matcher with the same name is defined in multiple translation units:
//
// namespace clang {
// namespace ast_matchers {
+// namespace {
// AST_MATCHER_P(MemberExpr, Member,
// internal::Matcher<ValueDecl>, InnerMatcher) {
// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
// }
-// } // end namespace ast_matchers
-// } // end namespace clang
+// } // namespace
+// } // namespace ast_matchers
+// } // namespace clang
//
//===----------------------------------------------------------------------===//
@@ -40,15 +44,16 @@
/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
/// defines a zero parameter function named DefineMatcher() that returns a
/// ReturnType object.
-#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
- inline ReturnType DefineMatcher##_getInstance(); \
- inline ReturnType DefineMatcher() { \
- return internal::MemoizedMatcher< \
- ReturnType, DefineMatcher##_getInstance>::getInstance(); \
- } \
+#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
+ inline ReturnType DefineMatcher##_getInstance(); \
+ inline ReturnType DefineMatcher() { \
+ return ::clang::ast_matchers::internal::MemoizedMatcher< \
+ ReturnType, DefineMatcher##_getInstance>::getInstance(); \
+ } \
inline ReturnType DefineMatcher##_getInstance()
-/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { ... }
+/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
+/// ... }
/// defines a single-parameter function named DefineMatcher() that returns a
/// ReturnType object.
///
@@ -61,10 +66,10 @@
#define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) \
AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \
0)
-#define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, \
- Param, OverloadId) \
- inline ReturnType DefineMatcher(ParamType const &Param); \
- typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &); \
+#define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, \
+ Param, OverloadId) \
+ inline ReturnType DefineMatcher(ParamType const &Param); \
+ typedef ReturnType(&DefineMatcher##_Type##OverloadId)(ParamType const &); \
inline ReturnType DefineMatcher(ParamType const &Param)
/// \brief AST_MATCHER(Type, DefineMatcher) { ... }
@@ -78,22 +83,26 @@
/// Builder: a BoundNodesTreeBuilder*.
///
/// The code should return true if 'Node' matches.
-#define AST_MATCHER(Type, DefineMatcher) \
- namespace internal { \
- class matcher_##DefineMatcher##Matcher : public MatcherInterface<Type> { \
- public: \
- explicit matcher_##DefineMatcher##Matcher() {} \
- bool matches(const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const override; \
- }; \
- } \
- inline internal::Matcher<Type> DefineMatcher() { \
- return internal::makeMatcher( \
- new internal::matcher_##DefineMatcher##Matcher()); \
- } \
- inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
- const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+#define AST_MATCHER(Type, DefineMatcher) \
+ namespace internal { \
+ class matcher_##DefineMatcher##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
+ explicit matcher_##DefineMatcher##Matcher() {} \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher() { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
+ new internal::matcher_##DefineMatcher##Matcher()); \
+ } \
+ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that returns a
@@ -108,34 +117,38 @@
/// Builder: a BoundNodesTreeBuilder*.
///
/// The code should return true if 'Node' matches.
-#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \
+#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \
AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0)
#define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, \
OverloadId) \
namespace internal { \
class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<Type> { \
- public: \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
ParamType const &A##Param) \
: Param(A##Param) {} \
- bool matches(const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const override; \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
\
- private: \
+ private: \
ParamType const Param; \
}; \
} \
- inline internal::Matcher<Type> DefineMatcher(ParamType const &Param) { \
- return internal::makeMatcher( \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
+ ParamType const &Param) { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
} \
- typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
- ParamType const &Param); \
+ typedef ::clang::ast_matchers::internal::Matcher<Type>( \
+ &DefineMatcher##_Type##OverloadId)(ParamType const &Param); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
- const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
/// \brief AST_MATCHER_P2(
/// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
@@ -160,30 +173,34 @@
ParamType2, Param2, OverloadId) \
namespace internal { \
class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<Type> { \
- public: \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
ParamType2 const &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
- bool matches(const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const override; \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
\
- private: \
+ private: \
ParamType1 const Param1; \
ParamType2 const Param2; \
}; \
} \
- inline internal::Matcher<Type> DefineMatcher(ParamType1 const &Param1, \
- ParamType2 const &Param2) { \
- return internal::makeMatcher( \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
+ ParamType1 const &Param1, ParamType2 const &Param2) { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
Param2)); \
} \
- typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
- ParamType1 const &Param1, ParamType2 const &Param2); \
+ typedef ::clang::ast_matchers::internal::Matcher<Type>( \
+ &DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \
+ ParamType2 const &Param2); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
- const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
/// macros.
@@ -193,34 +210,38 @@
/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
/// extract the TypeList object.
-#define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \
- void(internal::TypeList<__VA_ARGS__>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \
+ void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>)
/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
/// from the calling context.
-#define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \
- namespace internal { \
- template <typename NodeType> \
- class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \
- public: \
- bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const override; \
- }; \
- } \
- inline internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \
- DefineMatcher() { \
- return internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \
- } \
- template <typename NodeType> \
- bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \
- const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+#define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \
+ namespace internal { \
+ template <typename NodeType> \
+ class matcher_##DefineMatcher##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \
+ DefineMatcher() { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \
+ } \
+ template <typename NodeType> \
+ bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \
+ const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that is
@@ -231,43 +252,49 @@
/// of the matcher Matcher<NodeType> returned by the function matcher().
///
/// FIXME: Pull out common code with above macro?
-#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \
- Param) \
- AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \
+#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \
+ Param) \
+ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \
Param, 0)
#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, \
ParamType, Param, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT> \
class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<NodeType> { \
- public: \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
ParamType const &A##Param) \
: Param(A##Param) {} \
- bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const override; \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
\
- private: \
+ private: \
ParamType const Param; \
}; \
} \
- inline internal::PolymorphicMatcherWithParam1< \
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
- ReturnTypesF> DefineMatcher(ParamType const &Param) { \
- return internal::PolymorphicMatcherWithParam1< \
+ ReturnTypesF> \
+ DefineMatcher(ParamType const &Param) { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
ReturnTypesF>(Param); \
} \
- typedef internal::PolymorphicMatcherWithParam1< \
+ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
ParamType const &Param); \
template <typename NodeType, typename ParamT> \
- bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
- NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+ bool internal:: \
+ matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
+ const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
+ const
/// \brief AST_POLYMORPHIC_MATCHER_P2(
/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
@@ -288,72 +315,83 @@
namespace internal { \
template <typename NodeType, typename ParamT1, typename ParamT2> \
class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<NodeType> { \
- public: \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
ParamType2 const &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
- bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const override; \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
\
- private: \
+ private: \
ParamType1 const Param1; \
ParamType2 const Param2; \
}; \
} \
- inline internal::PolymorphicMatcherWithParam2< \
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2, ReturnTypesF> DefineMatcher(ParamType1 const &Param1, \
- ParamType2 const &Param2) { \
- return internal::PolymorphicMatcherWithParam2< \
+ ParamType2, ReturnTypesF> \
+ DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2, ReturnTypesF>(Param1, Param2); \
} \
- typedef internal::PolymorphicMatcherWithParam2< \
+ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
ParamType1 const &Param1, ParamType2 const &Param2); \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
- NodeType, ParamT1, ParamT2>::matches( \
- const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+ NodeType, ParamT1, ParamT2>:: \
+ matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
+ const
/// \brief Creates a variadic matcher for both a specific \c Type as well as
/// the corresponding \c TypeLoc.
-#define AST_TYPE_MATCHER(NodeType, MatcherName) \
- const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName
+#define AST_TYPE_MATCHER(NodeType, MatcherName) \
+ const ::clang::ast_matchers::internal::VariadicDynCastAllOfMatcher< \
+ Type, NodeType> MatcherName
// FIXME: add a matcher for TypeLoc derived classes using its custom casting
// API (no longer dyn_cast) if/when we need such matching
/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
/// the matcher \c MatcherName that can be used to traverse from one \c Type
/// to another.
///
-/// For a specific \c SpecificType, the traversal is done using
+/// For a specific \c SpecificType, the traversal is done using
/// \c SpecificType::FunctionName. The existence of such a function determines
/// whether a corresponding matcher can be used on \c SpecificType.
-#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
- namespace internal { \
- template <typename T> struct TypeMatcher##MatcherName##Getter { \
- static QualType (T::*value())() const { return &T::FunctionName; } \
- }; \
- } \
- const internal::TypeTraversePolymorphicMatcher< \
- QualType, internal::TypeMatcher##MatcherName##Getter, \
- internal::TypeTraverseMatcher, ReturnTypesF>::Func MatcherName
+#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> \
+ struct TypeMatcher##MatcherName##Getter { \
+ static QualType (T::*value())() const { return &T::FunctionName; } \
+ }; \
+ } \
+ const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
+ QualType, \
+ ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName
/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
-#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
- namespace internal { \
- template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
- static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
- }; \
- } \
- const internal::TypeTraversePolymorphicMatcher< \
- TypeLoc, internal::TypeLocMatcher##MatcherName##Getter, \
- internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \
+#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> \
+ struct TypeLocMatcher##MatcherName##Getter { \
+ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
+ }; \
+ } \
+ const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
+ TypeLoc, \
+ ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName##Loc; \
AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
#endif
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits