r206176 - Add support for named values in the parser.
Samuel Benzaquen
sbenza at google.com
Mon Apr 14 06:51:21 PDT 2014
Author: sbenza
Date: Mon Apr 14 08:51:21 2014
New Revision: 206176
URL: http://llvm.org/viewvc/llvm-project?rev=206176&view=rev
Log:
Add support for named values in the parser.
Summary: Add support for named values in the parser.
Reviewers: pcc
CC: cfe-commits, klimek
Differential Revision: http://llvm-reviews.chandlerc.com/D3276
Modified:
cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h
cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h
cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h
cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h
cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp
cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Diagnostics.h Mon Apr 14 08:51:21 2014
@@ -60,11 +60,12 @@ public:
enum ErrorType {
ET_None = 0,
- ET_RegistryNotFound = 1,
+ ET_RegistryMatcherNotFound = 1,
ET_RegistryWrongArgCount = 2,
ET_RegistryWrongArgType = 3,
ET_RegistryNotBindable = 4,
ET_RegistryAmbiguousOverload = 5,
+ ET_RegistryValueNotFound = 6,
ET_ParserStringError = 100,
ET_ParserNoOpenParen = 101,
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=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Parser.h Mon Apr 14 08:51:21 2014
@@ -18,13 +18,14 @@
///
/// \code
/// Grammar for the expressions supported:
-/// <Expression> := <Literal> | <MatcherExpression>
+/// <Expression> := <Literal> | <NamedValue> | <MatcherExpression>
/// <Literal> := <StringLiteral> | <Unsigned>
/// <StringLiteral> := "quoted string"
/// <Unsigned> := [0-9]+
-/// <MatcherExpression> := <MatcherName>(<ArgumentList>) |
-/// <MatcherName>(<ArgumentList>).bind(<StringLiteral>)
-/// <MatcherName> := [a-zA-Z]+
+/// <NamedValue> := <Identifier>
+/// <MatcherExpression> := <Identifier>(<ArgumentList>) |
+/// <Identifier>(<ArgumentList>).bind(<StringLiteral>)
+/// <Identifier> := [a-zA-Z]+
/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
/// \endcode
///
@@ -62,6 +63,17 @@ public:
public:
virtual ~Sema();
+ /// \brief Lookup a value by name.
+ ///
+ /// This can be used in the Sema layer to declare known constants or to
+ /// allow to split an expression in pieces.
+ ///
+ /// \param Name The name of the value to lookup.
+ ///
+ /// \return The named value. It could be any type that VariantValue
+ /// supports. An empty value means that the name is not recognized.
+ virtual VariantValue getNamedValue(StringRef Name);
+
/// \brief Process a matcher expression.
///
/// All the arguments passed here have already been processed.
@@ -89,15 +101,26 @@ public:
///
/// \param MatcherName The matcher name found by the parser.
///
- /// \param NameRange The location of the name in the matcher source.
- /// Useful for error reporting.
- ///
- /// \return The matcher constructor, or Optional<MatcherCtor>() if an error
- /// occurred. In that case, \c Error will contain a description of the
- /// error.
+ /// \return The matcher constructor, or Optional<MatcherCtor>() if not
+ /// found.
virtual llvm::Optional<MatcherCtor>
- lookupMatcherCtor(StringRef MatcherName, const SourceRange &NameRange,
- Diagnostics *Error) = 0;
+ lookupMatcherCtor(StringRef MatcherName) = 0;
+ };
+
+ /// \brief Sema implementation that uses the matcher registry to process the
+ /// tokens.
+ class RegistrySema : public Parser::Sema {
+ public:
+ virtual ~RegistrySema();
+
+ llvm::Optional<MatcherCtor>
+ lookupMatcherCtor(StringRef MatcherName) override;
+
+ VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) override;
};
/// \brief Parse a matcher expression, creating matchers from the registry.
@@ -160,7 +183,9 @@ private:
Diagnostics *Error);
bool parseExpressionImpl(VariantValue *Value);
- bool parseMatcherExpressionImpl(VariantValue *Value);
+ bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
+ VariantValue *Value);
+ bool parseIdentifierPrefixImpl(VariantValue *Value);
void addCompletion(const TokenInfo &CompToken, StringRef TypedText,
StringRef Decl);
Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/Registry.h Mon Apr 14 08:51:21 2014
@@ -55,11 +55,8 @@ public:
/// \brief Look up a matcher in the registry by name,
///
/// \return An opaque value which may be used to refer to the matcher
- /// constructor, or Optional<MatcherCtor>() if not found. In that case
- /// \c Error will contain the description of the error.
- static llvm::Optional<MatcherCtor>
- lookupMatcherCtor(StringRef MatcherName, const SourceRange &NameRange,
- Diagnostics *Error);
+ /// constructor, or Optional<MatcherCtor>() if not found.
+ static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
/// \brief Compute the list of completions for \p Context.
///
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=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h Mon Apr 14 08:51:21 2014
@@ -78,7 +78,8 @@ public:
/// \brief Clones the provided matchers.
///
/// They should be the result of a polymorphic matcher.
- static VariantMatcher PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
+ static VariantMatcher
+ PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
/// \brief Creates a 'variadic' operator matcher.
///
@@ -208,6 +209,10 @@ public:
VariantValue(const std::string &String);
VariantValue(const VariantMatcher &Matchers);
+ /// \brief Returns true iff this is not an empty value.
+ LLVM_EXPLICIT operator bool() const { return hasValue(); }
+ bool hasValue() const { return Type != VT_Nothing; }
+
/// \brief Unsigned value functions.
bool isUnsigned() const;
unsigned getUnsigned() const;
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Diagnostics.cpp Mon Apr 14 08:51:21 2014
@@ -87,7 +87,7 @@ StringRef contextTypeToFormatString(Diag
StringRef errorTypeToFormatString(Diagnostics::ErrorType Type) {
switch (Type) {
- case Diagnostics::ET_RegistryNotFound:
+ case Diagnostics::ET_RegistryMatcherNotFound:
return "Matcher not found: $0";
case Diagnostics::ET_RegistryWrongArgCount:
return "Incorrect argument count. (Expected = $0) != (Actual = $1)";
@@ -98,6 +98,8 @@ StringRef errorTypeToFormatString(Diagno
case Diagnostics::ET_RegistryAmbiguousOverload:
// TODO: Add type info about the overload error.
return "Ambiguous matcher overload.";
+ case Diagnostics::ET_RegistryValueNotFound:
+ return "Value not found: $0";
case Diagnostics::ET_ParserStringError:
return "Error parsing string token: <$0>";
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Parser.cpp Mon Apr 14 08:51:21 2014
@@ -258,6 +258,10 @@ private:
Parser::Sema::~Sema() {}
+VariantValue Parser::Sema::getNamedValue(StringRef Name) {
+ return VariantValue();
+}
+
struct Parser::ScopedContextEntry {
Parser *P;
@@ -274,12 +278,43 @@ struct Parser::ScopedContextEntry {
}
};
+/// \brief Parse expressions that start with an identifier.
+///
+/// This function can parse named values and matchers.
+/// In case of failure it will try to determine the user's intent to give
+/// an appropriate error message.
+bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
+ const TokenInfo NameToken = Tokenizer->consumeNextToken();
+
+ if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
+ // Parse as a named value.
+ if (const VariantValue NamedValue = S->getNamedValue(NameToken.Text)) {
+ *Value = NamedValue;
+ return true;
+ }
+ // If the syntax is correct and the name is not a matcher either, report
+ // unknown named value.
+ if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
+ Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
+ Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
+ !S->lookupMatcherCtor(NameToken.Text)) {
+ Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
+ << NameToken.Text;
+ return false;
+ }
+ // Otherwise, fallback to the matcher parser.
+ }
+
+ // Parse as a matcher expression.
+ return parseMatcherExpressionImpl(NameToken, Value);
+}
+
/// \brief Parse and validate a matcher expression.
/// \return \c true on success, in which case \c Value has the matcher parsed.
/// If the input is malformed, or some argument has an error, it
/// returns \c false.
-bool Parser::parseMatcherExpressionImpl(VariantValue *Value) {
- const TokenInfo NameToken = Tokenizer->consumeNextToken();
+bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
+ VariantValue *Value) {
assert(NameToken.Kind == TokenInfo::TK_Ident);
const TokenInfo OpenToken = Tokenizer->consumeNextToken();
if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
@@ -288,8 +323,14 @@ bool Parser::parseMatcherExpressionImpl(
return false;
}
- llvm::Optional<MatcherCtor> Ctor =
- S->lookupMatcherCtor(NameToken.Text, NameToken.Range, Error);
+ llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
+
+ if (!Ctor) {
+ Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
+ << NameToken.Text;
+ // Do not return here. We need to continue to give completion suggestions.
+ }
+
std::vector<ParserValue> Args;
TokenInfo EndToken;
@@ -425,7 +466,7 @@ bool Parser::parseExpressionImpl(Variant
return true;
case TokenInfo::TK_Ident:
- return parseMatcherExpressionImpl(Value);
+ return parseIdentifierPrefixImpl(Value);
case TokenInfo::TK_CodeCompletion:
addExpressionCompletions();
@@ -457,27 +498,23 @@ Parser::Parser(CodeTokenizer *Tokenizer,
Diagnostics *Error)
: Tokenizer(Tokenizer), S(S), Error(Error) {}
-class RegistrySema : public Parser::Sema {
-public:
- virtual ~RegistrySema() {}
- llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
- const SourceRange &NameRange,
- Diagnostics *Error) {
- return Registry::lookupMatcherCtor(MatcherName, NameRange, Error);
- }
- VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
- const SourceRange &NameRange,
- StringRef BindID,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) {
- if (BindID.empty()) {
- return Registry::constructMatcher(Ctor, NameRange, Args, Error);
- } else {
- return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
- Error);
- }
+Parser::RegistrySema::~RegistrySema() {}
+
+llvm::Optional<MatcherCtor>
+Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
+ return Registry::lookupMatcherCtor(MatcherName);
+}
+
+VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
+ MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID,
+ ArrayRef<ParserValue> Args, Diagnostics *Error) {
+ if (BindID.empty()) {
+ return Registry::constructMatcher(Ctor, NameRange, Args, Error);
+ } else {
+ return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
+ Error);
}
-};
+}
bool Parser::parseExpression(StringRef Code, VariantValue *Value,
Diagnostics *Error) {
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Mon Apr 14 08:51:21 2014
@@ -325,17 +325,12 @@ static llvm::ManagedStatic<RegistryMaps>
} // anonymous namespace
// static
-llvm::Optional<MatcherCtor>
-Registry::lookupMatcherCtor(StringRef MatcherName, const SourceRange &NameRange,
- Diagnostics *Error) {
+llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
ConstructorMap::const_iterator it =
RegistryData->constructors().find(MatcherName);
- if (it == RegistryData->constructors().end()) {
- Error->addError(NameRange, Error->ET_RegistryNotFound) << MatcherName;
- return llvm::Optional<MatcherCtor>();
- }
-
- return it->second;
+ return it == RegistryData->constructors().end()
+ ? llvm::Optional<MatcherCtor>()
+ : it->second;
}
namespace {
Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Mon Apr 14 08:51:21 2014
@@ -39,9 +39,7 @@ public:
Errors.push_back(Error.toStringFull());
}
- llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
- const SourceRange &NameRange,
- Diagnostics *Error) {
+ llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) {
const ExpectedMatchersTy::value_type *Matcher =
&*ExpectedMatchers.find(MatcherName);
return reinterpret_cast<MatcherCtor>(Matcher);
@@ -175,6 +173,29 @@ TEST(ParserTest, FullParserTest) {
EXPECT_TRUE(matches("void f(int a, int x);", M));
EXPECT_FALSE(matches("void f(int x, int a);", M));
+ // Test named values.
+ struct NamedSema : public Parser::RegistrySema {
+ public:
+ virtual VariantValue getNamedValue(StringRef Name) {
+ if (Name == "nameX")
+ return std::string("x");
+ if (Name == "param0")
+ return VariantMatcher::SingleMatcher(hasParameter(0, hasName("a")));
+ return VariantValue();
+ }
+ };
+ NamedSema Sema;
+ llvm::Optional<DynTypedMatcher> HasParameterWithNamedValues(
+ Parser::parseMatcherExpression(
+ "functionDecl(param0, hasParameter(1, hasName(nameX)))", &Sema,
+ &Error));
+ EXPECT_EQ("", Error.toStringFull());
+ M = HasParameterWithNamedValues->unconditionalConvertTo<Decl>();
+
+ EXPECT_TRUE(matches("void f(int a, int x);", M));
+ EXPECT_FALSE(matches("void f(int x, int a);", M));
+
+
EXPECT_TRUE(!Parser::parseMatcherExpression(
"hasInitializer(\n binaryOperator(hasLHS(\"A\")))",
&Error).hasValue());
@@ -208,6 +229,10 @@ TEST(ParserTest, Errors) {
"1:9: Error parsing matcher. Found token <123> while looking for ','.",
ParseWithError("Foo(\"A\" 123)"));
EXPECT_EQ(
+ "1:1: Error parsing argument 1 for matcher stmt.\n"
+ "1:6: Value not found: someValue",
+ ParseWithError("stmt(someValue)"));
+ EXPECT_EQ(
"1:1: Matcher not found: Foo\n"
"1:4: Error parsing matcher. Found end-of-code while looking for ')'.",
ParseWithError("Foo("));
Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Mon Apr 14 08:51:21 2014
@@ -35,21 +35,15 @@ public:
return Out;
}
- llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
- Diagnostics *Error = 0) {
- Diagnostics DummyError;
- if (!Error) Error = &DummyError;
- llvm::Optional<MatcherCtor> Ctor =
- Registry::lookupMatcherCtor(MatcherName, SourceRange(), Error);
- EXPECT_EQ("", DummyError.toStringFull());
- return Ctor;
+ llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) {
+ return Registry::lookupMatcherCtor(MatcherName);
}
VariantMatcher constructMatcher(StringRef MatcherName,
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
VariantMatcher Out;
if (Ctor)
Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
@@ -62,7 +56,7 @@ public:
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
VariantMatcher Out;
if (Ctor)
Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
@@ -76,7 +70,7 @@ public:
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
VariantMatcher Out;
if (Ctor)
Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp?rev=206176&r1=206175&r2=206176&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp Mon Apr 14 08:51:21 2014
@@ -26,6 +26,7 @@ TEST(VariantValueTest, Unsigned) {
EXPECT_TRUE(Value.isUnsigned());
EXPECT_EQ(kUnsigned, Value.getUnsigned());
+ EXPECT_TRUE(Value.hasValue());
EXPECT_FALSE(Value.isString());
EXPECT_FALSE(Value.isMatcher());
}
@@ -38,6 +39,7 @@ TEST(VariantValueTest, String) {
EXPECT_EQ(kString, Value.getString());
EXPECT_EQ("String", Value.getTypeAsString());
+ EXPECT_TRUE(Value.hasValue());
EXPECT_FALSE(Value.isUnsigned());
EXPECT_FALSE(Value.isMatcher());
}
@@ -45,6 +47,7 @@ TEST(VariantValueTest, String) {
TEST(VariantValueTest, DynTypedMatcher) {
VariantValue Value = VariantMatcher::SingleMatcher(stmt());
+ EXPECT_TRUE(Value.hasValue());
EXPECT_FALSE(Value.isUnsigned());
EXPECT_FALSE(Value.isString());
@@ -74,11 +77,13 @@ TEST(VariantValueTest, Assignment) {
VariantValue Value = std::string("A");
EXPECT_TRUE(Value.isString());
EXPECT_EQ("A", Value.getString());
+ EXPECT_TRUE(Value.hasValue());
EXPECT_FALSE(Value.isUnsigned());
EXPECT_FALSE(Value.isMatcher());
EXPECT_EQ("String", Value.getTypeAsString());
Value = VariantMatcher::SingleMatcher(recordDecl());
+ EXPECT_TRUE(Value.hasValue());
EXPECT_FALSE(Value.isUnsigned());
EXPECT_FALSE(Value.isString());
EXPECT_TRUE(Value.isMatcher());
@@ -89,16 +94,36 @@ TEST(VariantValueTest, Assignment) {
Value = 17;
EXPECT_TRUE(Value.isUnsigned());
EXPECT_EQ(17U, Value.getUnsigned());
+ EXPECT_TRUE(Value.hasValue());
EXPECT_FALSE(Value.isMatcher());
EXPECT_FALSE(Value.isString());
Value = VariantValue();
+ EXPECT_FALSE(Value.hasValue());
EXPECT_FALSE(Value.isUnsigned());
EXPECT_FALSE(Value.isString());
EXPECT_FALSE(Value.isMatcher());
EXPECT_EQ("Nothing", Value.getTypeAsString());
}
+TEST(VariantValueTest, ImplicitBool) {
+ VariantValue Value;
+ bool IfTrue = false;
+ if (Value) {
+ IfTrue = true;
+ }
+ EXPECT_FALSE(IfTrue);
+ EXPECT_TRUE(!Value);
+
+ Value = std::string();
+ IfTrue = false;
+ if (Value) {
+ IfTrue = true;
+ }
+ EXPECT_TRUE(IfTrue);
+ EXPECT_FALSE(!Value);
+}
+
TEST(VariantValueTest, Matcher) {
EXPECT_TRUE(matches("class X {};", VariantValue(VariantMatcher::SingleMatcher(
recordDecl(hasName("X"))))
More information about the cfe-commits
mailing list