diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -27,6 +27,7 @@ #include "clang/Basic/AttrKinds.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/TypeTraits.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" @@ -214,6 +215,35 @@ static llvm::Optional getBestGuess(const VariantValue &Value); }; +template <> struct ArgTypeTraits { +private: + static Optional + getUnaryOrTypeTraitKind(llvm::StringRef ClauseKind) { + // FIXME: Type traits should probably be in a `.def` to make less error + // prone. + return llvm::StringSwitch>(ClauseKind) + .Case("UETT_SizeOf", UETT_SizeOf) + .Case("UETT_AlignOf", UETT_AlignOf) + .Case("UETT_VecStep", UETT_VecStep) + .Case("UETT_OpenMPRequiredSimdAlign", UETT_OpenMPRequiredSimdAlign) + .Case("UETT_PreferredAlignOf", UETT_PreferredAlignOf) + .Default(llvm::None); + } + +public: + static bool is(const VariantValue &Value) { + return Value.isString() && getUnaryOrTypeTraitKind(Value.getString()); + } + + static UnaryExprOrTypeTrait get(const VariantValue &Value) { + return *getUnaryOrTypeTraitKind(Value.getString()); + } + + static ArgKind getKind() { return ArgKind(ArgKind::AK_String); } + + static llvm::Optional getBestGuess(const VariantValue &Value); +}; + /// Matcher descriptor interface. /// /// Provides a \c create() method that constructs the matcher from the provided diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp b/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp @@ -95,3 +95,17 @@ "OMPC_"); return llvm::None; } + +llvm::Optional +clang::ast_matchers::dynamic::internal::ArgTypeTraits< + clang::UnaryExprOrTypeTrait>::getBestGuess(const VariantValue &Value) { + static constexpr llvm::StringRef Allowed[] = { + "UETT_SizeOf", "UETT_AlignOf", + "UETT_VecStep", "UETT_OpenMPRequiredSimdAlign", + "UETT_PreferredAlignOf", + }; + if (Value.isString()) + return ::getBestGuess(Value.getString(), llvm::makeArrayRef(Allowed), + "UETT_"); + return llvm::None; +} diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -95,9 +95,6 @@ RegistryMaps::RegistryMaps() { // TODO: Here is the list of the missing matchers, grouped by reason. // - // Need Variant/Parser fixes: - // ofKind - // // Polymorphic + argument overload: // findAll // @@ -458,6 +455,7 @@ REGISTER_MATCHER(objcThrowStmt); REGISTER_MATCHER(objcTryStmt); REGISTER_MATCHER(ofClass); + REGISTER_MATCHER(ofKind); REGISTER_MATCHER(ompDefaultClause); REGISTER_MATCHER(ompExecutableDirective); REGISTER_MATCHER(on); diff --git a/clang/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/clang/unittests/ASTMatchers/Dynamic/ParserTest.cpp --- a/clang/unittests/ASTMatchers/Dynamic/ParserTest.cpp +++ b/clang/unittests/ASTMatchers/Dynamic/ParserTest.cpp @@ -242,6 +242,14 @@ EXPECT_TRUE(matches("void f(int a, int x);", M)); EXPECT_FALSE(matches("void f(int x, int a);", M)); + Code = "unaryExprOrTypeTraitExpr(ofKind(\"UETT_SizeOf\"))"; + llvm::Optional UnaryExprSizeOf( + Parser::parseMatcherExpression(Code, nullptr, nullptr, &Error)); + EXPECT_EQ("", Error.toStringFull()); + Matcher MStmt = UnaryExprSizeOf->unconditionalConvertTo(); + EXPECT_TRUE(matches("unsigned X = sizeof(int);", MStmt)); + EXPECT_FALSE(matches("unsigned X = alignof(int);", MStmt)); + Code = "hasInitializer(\n binaryOperator(hasLHS(\"A\")))"; EXPECT_TRUE(!Parser::parseMatcherExpression(Code, &Error).hasValue()); EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n"