r305020 - [ASTMatchers] Add support for boolean literals

Peter Wu via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 8 15:00:39 PDT 2017


Author: lekensteyn
Date: Thu Jun  8 17:00:38 2017
New Revision: 305020

URL: http://llvm.org/viewvc/llvm-project?rev=305020&view=rev
Log:
[ASTMatchers] Add support for boolean literals

Summary:
Recognize boolean literals for future extensions ("equals(true)").
Note that a specific VariantValue constructor is added to resolve
ambiguity (like "Value = 5") between unsigned and bool.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D33093

Modified:
    cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h
    cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h
    cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
    cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
    cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp
    cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
    cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp

Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h?rev=305020&r1=305019&r2=305020&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h Thu Jun  8 17:00:38 2017
@@ -19,8 +19,9 @@
 /// \code
 /// Grammar for the expressions supported:
 /// <Expression>        := <Literal> | <NamedValue> | <MatcherExpression>
-/// <Literal>           := <StringLiteral> | <Unsigned>
+/// <Literal>           := <StringLiteral> | <Boolean> | <Unsigned>
 /// <StringLiteral>     := "quoted string"
+/// <Boolean>           := true | false
 /// <Unsigned>          := [0-9]+
 /// <NamedValue>        := <Identifier>
 /// <MatcherExpression> := <Identifier>(<ArgumentList>) |

Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h?rev=305020&r1=305019&r2=305020&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h Thu Jun  8 17:00:38 2017
@@ -35,6 +35,7 @@ class ArgKind {
  public:
   enum Kind {
     AK_Matcher,
+    AK_Boolean,
     AK_Unsigned,
     AK_String
   };
@@ -241,6 +242,7 @@ struct VariantMatcher::TypedMatcherOps f
 /// copy/assignment.
 ///
 /// Supported types:
+///  - \c bool
 ///  - \c unsigned
 ///  - \c llvm::StringRef
 ///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
@@ -253,14 +255,23 @@ public:
   VariantValue &operator=(const VariantValue &Other);
 
   /// \brief Specific constructors for each supported type.
+  VariantValue(bool Boolean);
   VariantValue(unsigned Unsigned);
   VariantValue(StringRef String);
   VariantValue(const VariantMatcher &Matchers);
 
+  /// \brief Constructs an \c unsigned value (disambiguation from bool).
+  VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
+
   /// \brief Returns true iff this is not an empty value.
   explicit operator bool() const { return hasValue(); }
   bool hasValue() const { return Type != VT_Nothing; }
 
+  /// \brief Boolean value functions.
+  bool isBoolean() const;
+  bool getBoolean() const;
+  void setBoolean(bool Boolean);
+
   /// \brief Unsigned value functions.
   bool isUnsigned() const;
   unsigned getUnsigned() const;
@@ -303,6 +314,7 @@ private:
   /// \brief All supported value types.
   enum ValueType {
     VT_Nothing,
+    VT_Boolean,
     VT_Unsigned,
     VT_String,
     VT_Matcher
@@ -311,6 +323,7 @@ private:
   /// \brief All supported value types.
   union AllValues {
     unsigned Unsigned;
+    bool Boolean;
     std::string *String;
     VariantMatcher *Matcher;
   };

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h?rev=305020&r1=305019&r2=305020&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h Thu Jun  8 17:00:38 2017
@@ -65,6 +65,16 @@ template <class T> struct ArgTypeTraits<
   }
 };
 
+template <> struct ArgTypeTraits<bool> {
+  static bool is(const VariantValue &Value) { return Value.isBoolean(); }
+  static bool get(const VariantValue &Value) {
+    return Value.getBoolean();
+  }
+  static ArgKind getKind() {
+    return ArgKind(ArgKind::AK_Boolean);
+  }
+};
+
 template <> struct ArgTypeTraits<unsigned> {
   static bool is(const VariantValue &Value) { return Value.isUnsigned(); }
   static unsigned get(const VariantValue &Value) {

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp?rev=305020&r1=305019&r2=305020&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp Thu Jun  8 17:00:38 2017
@@ -153,8 +153,16 @@ private:
             break;
           ++TokenLength;
         }
-        Result.Kind = TokenInfo::TK_Ident;
-        Result.Text = Code.substr(0, TokenLength);
+        if (TokenLength == 4 && Code.startswith("true")) {
+          Result.Kind = TokenInfo::TK_Literal;
+          Result.Value = true;
+        } else if (TokenLength == 5 && Code.startswith("false")) {
+          Result.Kind = TokenInfo::TK_Literal;
+          Result.Value = false;
+        } else {
+          Result.Kind = TokenInfo::TK_Ident;
+          Result.Text = Code.substr(0, TokenLength);
+        }
         Code = Code.drop_front(TokenLength);
       } else {
         Result.Kind = TokenInfo::TK_InvalidChar;

Modified: cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp?rev=305020&r1=305019&r2=305020&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp Thu Jun  8 17:00:38 2017
@@ -24,6 +24,8 @@ std::string ArgKind::asString() const {
   switch (getArgKind()) {
   case AK_Matcher:
     return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
+  case AK_Boolean:
+    return "boolean";
   case AK_Unsigned:
     return "unsigned";
   case AK_String:
@@ -247,6 +249,10 @@ VariantValue::VariantValue(const Variant
   *this = Other;
 }
 
+VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
+  setBoolean(Boolean);
+}
+
 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
   setUnsigned(Unsigned);
 }
@@ -265,6 +271,9 @@ VariantValue &VariantValue::operator=(co
   if (this == &Other) return *this;
   reset();
   switch (Other.Type) {
+  case VT_Boolean:
+    setBoolean(Other.getBoolean());
+    break;
   case VT_Unsigned:
     setUnsigned(Other.getUnsigned());
     break;
@@ -290,6 +299,7 @@ void VariantValue::reset() {
     delete Value.Matcher;
     break;
   // Cases that do nothing.
+  case VT_Boolean:
   case VT_Unsigned:
   case VT_Nothing:
     break;
@@ -297,6 +307,21 @@ void VariantValue::reset() {
   Type = VT_Nothing;
 }
 
+bool VariantValue::isBoolean() const {
+  return Type == VT_Boolean;
+}
+
+bool VariantValue::getBoolean() const {
+  assert(isBoolean());
+  return Value.Boolean;
+}
+
+void VariantValue::setBoolean(bool NewValue) {
+  reset();
+  Type = VT_Boolean;
+  Value.Boolean = NewValue;
+}
+
 bool VariantValue::isUnsigned() const {
   return Type == VT_Unsigned;
 }
@@ -344,6 +369,12 @@ void VariantValue::setMatcher(const Vari
 
 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
   switch (Kind.getArgKind()) {
+  case ArgKind::AK_Boolean:
+    if (!isBoolean())
+      return false;
+    *Specificity = 1;
+    return true;
+
   case ArgKind::AK_Unsigned:
     if (!isUnsigned())
       return false;
@@ -383,6 +414,7 @@ std::string VariantValue::getTypeAsStrin
   switch (Type) {
   case VT_String: return "String";
   case VT_Matcher: return getMatcher().getTypeAsString();
+  case VT_Boolean: return "Boolean";
   case VT_Unsigned: return "Unsigned";
   case VT_Nothing: return "Nothing";
   }

Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=305020&r1=305019&r2=305020&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Thu Jun  8 17:00:38 2017
@@ -75,6 +75,15 @@ public:
   ExpectedMatchersTy ExpectedMatchers;
 };
 
+TEST(ParserTest, ParseBoolean) {
+  MockSema Sema;
+  Sema.parse("true");
+  Sema.parse("false");
+  EXPECT_EQ(2U, Sema.Values.size());
+  EXPECT_EQ(true, Sema.Values[0].getBoolean());
+  EXPECT_EQ(false, Sema.Values[1].getBoolean());
+}
+
 TEST(ParserTest, ParseUnsigned) {
   MockSema Sema;
   Sema.parse("0");

Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp?rev=305020&r1=305019&r2=305020&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp Thu Jun  8 17:00:38 2017
@@ -75,12 +75,14 @@ TEST(VariantValueTest, Assignment) {
   EXPECT_TRUE(Value.isString());
   EXPECT_EQ("A", Value.getString());
   EXPECT_TRUE(Value.hasValue());
+  EXPECT_FALSE(Value.isBoolean());
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isMatcher());
   EXPECT_EQ("String", Value.getTypeAsString());
 
   Value = VariantMatcher::SingleMatcher(recordDecl());
   EXPECT_TRUE(Value.hasValue());
+  EXPECT_FALSE(Value.isBoolean());
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
   EXPECT_TRUE(Value.isMatcher());
@@ -88,15 +90,25 @@ TEST(VariantValueTest, Assignment) {
   EXPECT_FALSE(Value.getMatcher().hasTypedMatcher<UnaryOperator>());
   EXPECT_EQ("Matcher<Decl>", Value.getTypeAsString());
 
+  Value = true;
+  EXPECT_TRUE(Value.isBoolean());
+  EXPECT_EQ(true, Value.getBoolean());
+  EXPECT_TRUE(Value.hasValue());
+  EXPECT_FALSE(Value.isUnsigned());
+  EXPECT_FALSE(Value.isMatcher());
+  EXPECT_FALSE(Value.isString());
+
   Value = 17;
   EXPECT_TRUE(Value.isUnsigned());
   EXPECT_EQ(17U, Value.getUnsigned());
+  EXPECT_FALSE(Value.isBoolean());
   EXPECT_TRUE(Value.hasValue());
   EXPECT_FALSE(Value.isMatcher());
   EXPECT_FALSE(Value.isString());
 
   Value = VariantValue();
   EXPECT_FALSE(Value.hasValue());
+  EXPECT_FALSE(Value.isBoolean());
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
   EXPECT_FALSE(Value.isMatcher());




More information about the cfe-commits mailing list