xref: /llvm-project/clang/unittests/Tooling/SourceCodeBuildersTest.cpp (revision 6ad0788c332bb2043142954d300c49ac3e537f34)
1 //===- unittest/Tooling/SourceCodeBuildersTest.cpp ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Tooling/Transformer/SourceCodeBuilders.h"
10 #include "clang/AST/Type.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/ASTMatchers/ASTMatchers.h"
13 #include "clang/Tooling/Tooling.h"
14 #include "llvm/Testing/Support/SupportHelpers.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17 #include <optional>
18 
19 using namespace clang;
20 using namespace tooling;
21 using namespace ast_matchers;
22 
23 namespace {
24 using MatchResult = MatchFinder::MatchResult;
25 using llvm::ValueIs;
26 
27 // Create a valid translation unit from a statement.
wrapSnippet(StringRef StatementCode)28 static std::string wrapSnippet(StringRef StatementCode) {
29   return ("namespace std {\n"
30           "template <typename T> struct unique_ptr {\n"
31           "  T* operator->() const;\n"
32           "  T& operator*() const;\n"
33           "};\n"
34           "template <typename T> struct shared_ptr {\n"
35           "  T* operator->() const;\n"
36           "  T& operator*() const;\n"
37           "};\n"
38           "}\n"
39           "struct A { void super(); };\n"
40           "struct S : public A { S(); S(int); int Field; };\n"
41           "S operator+(const S &a, const S &b);\n"
42           "struct Smart {\n"
43           "  S* operator->() const;\n"
44           "  S& operator*() const;\n"
45           "};\n"
46           "auto test_snippet = []{" +
47           StatementCode + "};")
48       .str();
49 }
50 
wrapMatcher(const StatementMatcher & Matcher)51 static DeclarationMatcher wrapMatcher(const StatementMatcher &Matcher) {
52   return varDecl(hasName("test_snippet"),
53                  hasDescendant(compoundStmt(hasAnySubstatement(Matcher))));
54 }
55 
56 struct TestMatch {
57   // The AST unit from which `result` is built. We bundle it because it backs
58   // the result. Users are not expected to access it.
59   std::unique_ptr<ASTUnit> AstUnit;
60   // The result to use in the test. References `ast_unit`.
61   MatchResult Result;
62 };
63 
64 // Matches `Matcher` against the statement `StatementCode` and returns the
65 // result. Handles putting the statement inside a function and modifying the
66 // matcher correspondingly. `Matcher` should match one of the statements in
67 // `StatementCode` exactly -- that is, produce exactly one match. However,
68 // `StatementCode` may contain other statements not described by `Matcher`.
matchStmt(StringRef StatementCode,StatementMatcher Matcher)69 static std::optional<TestMatch> matchStmt(StringRef StatementCode,
70                                           StatementMatcher Matcher) {
71   auto AstUnit = buildASTFromCodeWithArgs(wrapSnippet(StatementCode),
72                                           {"-Wno-unused-value"});
73   if (AstUnit == nullptr) {
74     ADD_FAILURE() << "AST construction failed";
75     return std::nullopt;
76   }
77   ASTContext &Context = AstUnit->getASTContext();
78   auto Matches = ast_matchers::match(wrapMatcher(Matcher), Context);
79   // We expect a single, exact match for the statement.
80   if (Matches.size() != 1) {
81     ADD_FAILURE() << "Wrong number of matches: " << Matches.size();
82     return std::nullopt;
83   }
84   return TestMatch{std::move(AstUnit), MatchResult(Matches[0], &Context)};
85 }
86 
testPredicate(bool (* Pred)(const Expr &),StringRef Snippet,bool Expected)87 static void testPredicate(bool (*Pred)(const Expr &), StringRef Snippet,
88                           bool Expected) {
89   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
90   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
91   EXPECT_EQ(Expected, Pred(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr")))
92       << "Snippet: " << Snippet;
93 }
94 
95 // Tests the predicate on the call argument, assuming `Snippet` is a function
96 // call.
testPredicateOnArg(bool (* Pred)(const Expr &),StringRef Snippet,bool Expected)97 static void testPredicateOnArg(bool (*Pred)(const Expr &), StringRef Snippet,
98                                bool Expected) {
99   auto StmtMatch = matchStmt(
100       Snippet, expr(ignoringImplicit(callExpr(hasArgument(
101                    0, ignoringElidableConstructorCall(expr().bind("arg")))))));
102   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
103   EXPECT_EQ(Expected, Pred(*StmtMatch->Result.Nodes.getNodeAs<Expr>("arg")))
104       << "Snippet: " << Snippet;
105 }
106 
TEST(SourceCodeBuildersTest,needParensAfterUnaryOperator)107 TEST(SourceCodeBuildersTest, needParensAfterUnaryOperator) {
108   testPredicate(needParensAfterUnaryOperator, "3 + 5;", true);
109   testPredicate(needParensAfterUnaryOperator, "true ? 3 : 5;", true);
110   testPredicate(needParensAfterUnaryOperator, "S(3) + S(5);", true);
111 
112   testPredicate(needParensAfterUnaryOperator, "int x; x;", false);
113   testPredicate(needParensAfterUnaryOperator, "int(3.0);", false);
114   testPredicate(needParensAfterUnaryOperator, "void f(); f();", false);
115   testPredicate(needParensAfterUnaryOperator, "int a[3]; a[0];", false);
116   testPredicate(needParensAfterUnaryOperator, "S x; x.Field;", false);
117   testPredicate(needParensAfterUnaryOperator, "int x = 1; --x;", false);
118   testPredicate(needParensAfterUnaryOperator, "int x = 1; -x;", false);
119 }
120 
TEST(SourceCodeBuildersTest,needParensAfterUnaryOperatorInImplicitConversion)121 TEST(SourceCodeBuildersTest, needParensAfterUnaryOperatorInImplicitConversion) {
122   // The binary operation will be embedded in various implicit
123   // expressions. Verify they are ignored.
124   testPredicateOnArg(needParensAfterUnaryOperator, "void f(S); f(3 + 5);",
125                      true);
126 }
127 
TEST(SourceCodeBuildersTest,mayEverNeedParens)128 TEST(SourceCodeBuildersTest, mayEverNeedParens) {
129   testPredicate(mayEverNeedParens, "3 + 5;", true);
130   testPredicate(mayEverNeedParens, "true ? 3 : 5;", true);
131   testPredicate(mayEverNeedParens, "int x = 1; --x;", true);
132   testPredicate(mayEverNeedParens, "int x = 1; -x;", true);
133 
134   testPredicate(mayEverNeedParens, "int x; x;", false);
135   testPredicate(mayEverNeedParens, "int(3.0);", false);
136   testPredicate(mayEverNeedParens, "void f(); f();", false);
137   testPredicate(mayEverNeedParens, "int a[3]; a[0];", false);
138   testPredicate(mayEverNeedParens, "S x; x.Field;", false);
139 }
140 
TEST(SourceCodeBuildersTest,mayEverNeedParensInImplictConversion)141 TEST(SourceCodeBuildersTest, mayEverNeedParensInImplictConversion) {
142   // The binary operation will be embedded in various implicit
143   // expressions. Verify they are ignored.
144   testPredicateOnArg(mayEverNeedParens, "void f(S); f(3 + 5);", true);
145 }
146 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeUniquePtr)147 TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeUniquePtr) {
148   std::string Snippet = "std::unique_ptr<int> P; P;";
149   auto StmtMatch =
150       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
151   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
152   EXPECT_TRUE(
153       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
154                              *StmtMatch->Result.Context))
155       << "Snippet: " << Snippet;
156 }
157 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeSharedPtr)158 TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeSharedPtr) {
159   std::string Snippet = "std::shared_ptr<int> P; P;";
160   auto StmtMatch =
161       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
162   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
163   EXPECT_TRUE(
164       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
165                              *StmtMatch->Result.Context))
166       << "Snippet: " << Snippet;
167 }
168 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeUnknownTypeFalse)169 TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeUnknownTypeFalse) {
170   std::string Snippet = "Smart P; P;";
171   auto StmtMatch =
172       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
173   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
174   EXPECT_FALSE(
175       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
176                              *StmtMatch->Result.Context))
177       << "Snippet: " << Snippet;
178 }
179 
TEST(SourceCodeBuildersTest,isKnownPointerLikeTypeNormalTypeFalse)180 TEST(SourceCodeBuildersTest, isKnownPointerLikeTypeNormalTypeFalse) {
181   std::string Snippet = "int *P; P;";
182   auto StmtMatch =
183       matchStmt(Snippet, declRefExpr(hasType(qualType().bind("ty"))));
184   ASSERT_TRUE(StmtMatch) << "Snippet: " << Snippet;
185   EXPECT_FALSE(
186       isKnownPointerLikeType(*StmtMatch->Result.Nodes.getNodeAs<QualType>("ty"),
187                              *StmtMatch->Result.Context))
188       << "Snippet: " << Snippet;
189 }
190 
testBuilder(std::optional<std::string> (* Builder)(const Expr &,const ASTContext &),StringRef Snippet,StringRef Expected)191 static void testBuilder(
192     std::optional<std::string> (*Builder)(const Expr &, const ASTContext &),
193     StringRef Snippet, StringRef Expected) {
194   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
195   ASSERT_TRUE(StmtMatch);
196   EXPECT_THAT(Builder(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
197                       *StmtMatch->Result.Context),
198               ValueIs(std::string(Expected)));
199 }
200 
testBuildAccess(StringRef Snippet,StringRef Expected,PLTClass C=PLTClass::Pointer)201 static void testBuildAccess(StringRef Snippet, StringRef Expected,
202                             PLTClass C = PLTClass::Pointer) {
203   auto StmtMatch = matchStmt(Snippet, expr().bind("expr"));
204   ASSERT_TRUE(StmtMatch);
205   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
206                           *StmtMatch->Result.Context, C),
207               ValueIs(std::string(Expected)));
208 }
209 
TEST(SourceCodeBuildersTest,BuildParensUnaryOp)210 TEST(SourceCodeBuildersTest, BuildParensUnaryOp) {
211   testBuilder(buildParens, "-4;", "(-4)");
212 }
213 
TEST(SourceCodeBuildersTest,BuildParensBinOp)214 TEST(SourceCodeBuildersTest, BuildParensBinOp) {
215   testBuilder(buildParens, "4 + 4;", "(4 + 4)");
216 }
217 
TEST(SourceCodeBuildersTest,BuildParensValue)218 TEST(SourceCodeBuildersTest, BuildParensValue) {
219   testBuilder(buildParens, "4;", "4");
220 }
221 
TEST(SourceCodeBuildersTest,BuildParensSubscript)222 TEST(SourceCodeBuildersTest, BuildParensSubscript) {
223   testBuilder(buildParens, "int a[3]; a[0];", "a[0]");
224 }
225 
TEST(SourceCodeBuildersTest,BuildParensCall)226 TEST(SourceCodeBuildersTest, BuildParensCall) {
227   testBuilder(buildParens, "int f(int); f(4);", "f(4)");
228 }
229 
TEST(SourceCodeBuildersTest,BuildAddressOfValue)230 TEST(SourceCodeBuildersTest, BuildAddressOfValue) {
231   testBuilder(buildAddressOf, "S x; x;", "&x");
232 }
233 
TEST(SourceCodeBuildersTest,BuildAddressOfPointerDereference)234 TEST(SourceCodeBuildersTest, BuildAddressOfPointerDereference) {
235   testBuilder(buildAddressOf, "S *x; *x;", "x");
236 }
237 
TEST(SourceCodeBuildersTest,BuildAddressOfPointerDereferenceIgnoresParens)238 TEST(SourceCodeBuildersTest, BuildAddressOfPointerDereferenceIgnoresParens) {
239   testBuilder(buildAddressOf, "S *x; *(x);", "x");
240 }
241 
TEST(SourceCodeBuildersTest,BuildAddressOfBinaryOperation)242 TEST(SourceCodeBuildersTest, BuildAddressOfBinaryOperation) {
243   testBuilder(buildAddressOf, "S x; x + x;", "&(x + x)");
244 }
245 
TEST(SourceCodeBuildersTest,BuildAddressOfImplicitThis)246 TEST(SourceCodeBuildersTest, BuildAddressOfImplicitThis) {
247   StringRef Snippet = R"cc(
248     struct Struct {
249       void foo() {}
250       void bar() {
251         foo();
252       }
253     };
254   )cc";
255   auto StmtMatch = matchStmt(
256       Snippet,
257       cxxMemberCallExpr(onImplicitObjectArgument(cxxThisExpr().bind("expr"))));
258   ASSERT_TRUE(StmtMatch);
259   EXPECT_THAT(buildAddressOf(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
260                              *StmtMatch->Result.Context),
261               ValueIs(std::string("this")));
262 }
263 
TEST(SourceCodeBuildersTest,BuildDereferencePointer)264 TEST(SourceCodeBuildersTest, BuildDereferencePointer) {
265   testBuilder(buildDereference, "S *x; x;", "*x");
266 }
267 
TEST(SourceCodeBuildersTest,BuildDereferenceValueAddress)268 TEST(SourceCodeBuildersTest, BuildDereferenceValueAddress) {
269   testBuilder(buildDereference, "S x; &x;", "x");
270 }
271 
TEST(SourceCodeBuildersTest,BuildDereferenceValueAddressIgnoresParens)272 TEST(SourceCodeBuildersTest, BuildDereferenceValueAddressIgnoresParens) {
273   testBuilder(buildDereference, "S x; &(x);", "x");
274 }
275 
TEST(SourceCodeBuildersTest,BuildDereferenceBinaryOperation)276 TEST(SourceCodeBuildersTest, BuildDereferenceBinaryOperation) {
277   testBuilder(buildDereference, "S *x; x + 1;", "*(x + 1)");
278 }
279 
TEST(SourceCodeBuildersTest,BuildDotValue)280 TEST(SourceCodeBuildersTest, BuildDotValue) {
281   testBuilder(buildDot, "S x; x;", "x.");
282 }
283 
TEST(SourceCodeBuildersTest,BuildDotPointerDereference)284 TEST(SourceCodeBuildersTest, BuildDotPointerDereference) {
285   testBuilder(buildDot, "S *x; *x;", "x->");
286 }
287 
TEST(SourceCodeBuildersTest,BuildDotPointerDereferenceIgnoresParens)288 TEST(SourceCodeBuildersTest, BuildDotPointerDereferenceIgnoresParens) {
289   testBuilder(buildDot, "S *x; *(x);", "x->");
290 }
291 
TEST(SourceCodeBuildersTest,BuildDotBinaryOperation)292 TEST(SourceCodeBuildersTest, BuildDotBinaryOperation) {
293   testBuilder(buildDot, "S x; x + x;", "(x + x).");
294 }
295 
TEST(SourceCodeBuildersTest,BuildDotPointerDereferenceExprWithParens)296 TEST(SourceCodeBuildersTest, BuildDotPointerDereferenceExprWithParens) {
297   testBuilder(buildDot, "S *x; *(x + 1);", "(x + 1)->");
298 }
299 
TEST(SourceCodeBuildersTest,BuildArrowPointer)300 TEST(SourceCodeBuildersTest, BuildArrowPointer) {
301   testBuilder(buildArrow, "S *x; x;", "x->");
302 }
303 
TEST(SourceCodeBuildersTest,BuildArrowValueAddress)304 TEST(SourceCodeBuildersTest, BuildArrowValueAddress) {
305   testBuilder(buildArrow, "S x; &x;", "x.");
306 }
307 
TEST(SourceCodeBuildersTest,BuildArrowValueAddressIgnoresParens)308 TEST(SourceCodeBuildersTest, BuildArrowValueAddressIgnoresParens) {
309   testBuilder(buildArrow, "S x; &(x);", "x.");
310 }
311 
TEST(SourceCodeBuildersTest,BuildArrowBinaryOperation)312 TEST(SourceCodeBuildersTest, BuildArrowBinaryOperation) {
313   testBuilder(buildArrow, "S *x; x + 1;", "(x + 1)->");
314 }
315 
TEST(SourceCodeBuildersTest,BuildArrowValueAddressWithParens)316 TEST(SourceCodeBuildersTest, BuildArrowValueAddressWithParens) {
317   testBuilder(buildArrow, "S x; &(true ? x : x);", "(true ? x : x).");
318 }
319 
TEST(SourceCodeBuildersTest,BuildAccessValue)320 TEST(SourceCodeBuildersTest, BuildAccessValue) {
321   testBuildAccess("S x; x;", "x.");
322 }
323 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereference)324 TEST(SourceCodeBuildersTest, BuildAccessPointerDereference) {
325   testBuildAccess("S *x; *x;", "x->");
326 }
327 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereferenceIgnoresParens)328 TEST(SourceCodeBuildersTest, BuildAccessPointerDereferenceIgnoresParens) {
329   testBuildAccess("S *x; *(x);", "x->");
330 }
331 
TEST(SourceCodeBuildersTest,BuildAccessValueBinaryOperation)332 TEST(SourceCodeBuildersTest, BuildAccessValueBinaryOperation) {
333   testBuildAccess("S x; x + x;", "(x + x).");
334 }
335 
TEST(SourceCodeBuildersTest,BuildAccessPointerDereferenceExprWithParens)336 TEST(SourceCodeBuildersTest, BuildAccessPointerDereferenceExprWithParens) {
337   testBuildAccess("S *x; *(x + 1);", "(x + 1)->");
338 }
339 
TEST(SourceCodeBuildersTest,BuildAccessPointer)340 TEST(SourceCodeBuildersTest, BuildAccessPointer) {
341   testBuildAccess("S *x; x;", "x->");
342 }
343 
TEST(SourceCodeBuildersTest,BuildAccessValueAddress)344 TEST(SourceCodeBuildersTest, BuildAccessValueAddress) {
345   testBuildAccess("S x; &x;", "x.");
346 }
347 
TEST(SourceCodeBuildersTest,BuildAccessValueAddressIgnoresParens)348 TEST(SourceCodeBuildersTest, BuildAccessValueAddressIgnoresParens) {
349   testBuildAccess("S x; &(x);", "x.");
350 }
351 
TEST(SourceCodeBuildersTest,BuildAccessPointerBinaryOperation)352 TEST(SourceCodeBuildersTest, BuildAccessPointerBinaryOperation) {
353   testBuildAccess("S *x; x + 1;", "(x + 1)->");
354 }
355 
TEST(SourceCodeBuildersTest,BuildAccessValueAddressWithParens)356 TEST(SourceCodeBuildersTest, BuildAccessValueAddressWithParens) {
357   testBuildAccess("S x; &(true ? x : x);", "(true ? x : x).");
358 }
359 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointer)360 TEST(SourceCodeBuildersTest, BuildAccessSmartPointer) {
361   testBuildAccess("std::unique_ptr<int> x; x;", "x->");
362 }
363 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerAsValue)364 TEST(SourceCodeBuildersTest, BuildAccessSmartPointerAsValue) {
365   testBuildAccess("std::unique_ptr<int> x; x;", "x.", PLTClass::Value);
366 }
367 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerDeref)368 TEST(SourceCodeBuildersTest, BuildAccessSmartPointerDeref) {
369   testBuildAccess("std::unique_ptr<int> x; *x;", "x->");
370 }
371 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerDerefAsValue)372 TEST(SourceCodeBuildersTest, BuildAccessSmartPointerDerefAsValue) {
373   testBuildAccess("std::unique_ptr<int> x; *x;", "(*x).", PLTClass::Value);
374 }
375 
TEST(SourceCodeBuildersTest,BuildAccessSmartPointerMemberCall)376 TEST(SourceCodeBuildersTest, BuildAccessSmartPointerMemberCall) {
377   StringRef Snippet = R"cc(
378     Smart x;
379     x->Field;
380   )cc";
381   auto StmtMatch =
382       matchStmt(Snippet, memberExpr(hasObjectExpression(expr().bind("expr"))));
383   ASSERT_TRUE(StmtMatch);
384   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
385                           *StmtMatch->Result.Context),
386               ValueIs(std::string("x->")));
387 }
388 
TEST(SourceCodeBuildersTest,BuildAccessIgnoreImplicit)389 TEST(SourceCodeBuildersTest, BuildAccessIgnoreImplicit) {
390   StringRef Snippet = R"cc(
391     S x;
392     A *a;
393     a = &x;
394   )cc";
395   auto StmtMatch =
396       matchStmt(Snippet, binaryOperator(isAssignmentOperator(),
397                                         hasRHS(expr().bind("expr"))));
398   ASSERT_TRUE(StmtMatch);
399   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
400                           *StmtMatch->Result.Context),
401               ValueIs(std::string("x.")));
402 }
403 
TEST(SourceCodeBuildersTest,BuildAccessImplicitThis)404 TEST(SourceCodeBuildersTest, BuildAccessImplicitThis) {
405   StringRef Snippet = R"cc(
406     struct Struct {
407       void foo() {}
408       void bar() {
409         foo();
410       }
411     };
412   )cc";
413   auto StmtMatch = matchStmt(
414       Snippet,
415       cxxMemberCallExpr(onImplicitObjectArgument(cxxThisExpr().bind("expr"))));
416   ASSERT_TRUE(StmtMatch);
417   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
418                           *StmtMatch->Result.Context),
419               ValueIs(std::string()));
420 }
421 
TEST(SourceCodeBuildersTest,BuildAccessImplicitThisIgnoreImplicitCasts)422 TEST(SourceCodeBuildersTest, BuildAccessImplicitThisIgnoreImplicitCasts) {
423   StringRef Snippet = "struct B : public A { void f() { super(); } };";
424   auto StmtMatch = matchStmt(
425       Snippet,
426       cxxMemberCallExpr(onImplicitObjectArgument(expr().bind("expr"))));
427   ASSERT_TRUE(StmtMatch);
428   EXPECT_THAT(buildAccess(*StmtMatch->Result.Nodes.getNodeAs<Expr>("expr"),
429                           *StmtMatch->Result.Context),
430               ValueIs(std::string()));
431 }
432 } // namespace
433