This is an archive of the discontinued LLVM Phabricator instance.

FileCheck [8/12]: Define numeric var from expr
ClosedPublic

Authored by thopre on Apr 7 2019, 4:21 PM.

Details

Summary

This patch is part of a patch series to add support for FileCheck
numeric expressions. This specific patch lift the restriction for a
numeric expression to either be a variable definition or a numeric
expression to try to match.

This commit allows a numeric variable to be set to the result of the
evaluation of a numeric expression after it has been matched
successfully. When it happens, the variable is allowed to be used on
the same line since its value is known at match time.

It also makes use of this possibility to reuse the parsing code to
parse a command-line definition by crafting a mirror string of the
-D option with the equal sign replaced by a colon sign, e.g. for option
'-D#NUMVAL=10' it creates the string
'-D#NUMVAL=10 (parsed as #NUMVAL:10)' where the numeric expression
is parsed to define NUMVAL. This result in a few tests needing updating
for the location diagnostics on top of the tests for the new feature.

It also enables empty numeric expression which match any number without
defining a variable. This is done here rather than in commit #5 of the
patch series because it requires to dissociate automatic regex insertion
in RegExStr from variable definition which would make commit #5 even
bigger than it already is.

Copyright:

  • Linaro (changes up to diff 183612 of revision D55940)
  • GraphCore (changes in later versions of revision D55940 and in new revision created off D55940)

Event Timeline

thopre created this revision.Apr 7 2019, 4:21 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 7 2019, 4:21 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
thopre updated this revision to Diff 194298.Apr 9 2019, 5:40 AM

Use camel case in new functions

thopre updated this revision to Diff 194483.Apr 10 2019, 4:44 AM

Make numeric variable constructor explicit

tra removed a subscriber: tra.Apr 11 2019, 1:17 PM
thopre updated this revision to Diff 197120.Apr 29 2019, 8:36 AM

Rebase on latest changes

thopre updated this revision to Diff 198021.May 3 2019, 8:34 AM

Rebase on latest changes

thopre updated this revision to Diff 198022.May 3 2019, 8:42 AM

Run clang-format

thopre updated this revision to Diff 198030.May 3 2019, 9:14 AM

Remove duplicate empty lines in numeric-expressions.txt

thopre updated this revision to Diff 198093.May 3 2019, 2:31 PM
  • Add checks in ParseExpr unit test to have same coverage as ParseNumericVariable
  • Reorganize NumericVariableValueGetClearSet since variable can now be created undefined
thopre updated this revision to Diff 198444.May 7 2019, 5:32 AM

Rebase on top of latest changes

thopre updated this revision to Diff 198548.May 7 2019, 3:29 PM

Rebase on top of latest changes

thopre updated this revision to Diff 198646.May 8 2019, 6:53 AM

Rebase on top of latest changes

thopre updated this revision to Diff 198950.May 9 2019, 4:51 PM

Rebase on top of latest changes

thopre updated this revision to Diff 199139.May 11 2019, 7:14 AM

Rebase on top of latest changes

thopre updated this revision to Diff 199237.May 13 2019, 3:58 AM

Rebase on top of latest changes

thopre updated this revision to Diff 199396.May 14 2019, 3:53 AM

Rebase on top of latest changes

rnk removed a reviewer: rnk.May 14 2019, 11:29 AM
rnk removed a subscriber: rnk.
thopre updated this revision to Diff 200474.May 21 2019, 5:55 AM

rebase on top of latest changes

thopre updated this revision to Diff 200551.May 21 2019, 11:15 AM

rebase on top of latest changes

thopre updated this revision to Diff 201983.May 29 2019, 10:52 AM

Rebase on top of latest changes in patch series

thopre updated this revision to Diff 203210.Jun 5 2019, 11:21 AM

Rebase on top of latest changes in the series

thopre updated this revision to Diff 204639.Jun 13 2019, 3:23 PM

Rebase on latest changes in the patch series

thopre updated this revision to Diff 205468.Jun 18 2019, 4:32 PM

Rebase on top of latest changes in the patch series

thopre updated this revision to Diff 205754.Jun 20 2019, 2:16 AM

Fix style for function parameter immediates

arichardson added inline comments.Jun 20 2019, 2:59 AM
llvm/include/llvm/Support/FileCheck.h
143

I would call this isKnownAtMatchTime() or isValueKnownAtMatchTime(). To me isMatchTimeKnown() sounds like "is the time of the match known?" which obviously doesn't make any sense in this context but the longer name means I know what the function does without find the documentation comment.

626

"if defining such a variable is invalid" slightly easier to parse for me.

642

Here and in the other functions: maybe use Optional<size_t> instead of a magic value of zero for line numbers?
I don't have a strong opinion here, I just think it might make it more obvious that the line number can also not be a line number but rather "this came from the command line".

llvm/lib/Support/FileCheck.cpp
27

I think !ExpressionAST is the more commonly used style.

thopre updated this revision to Diff 209243.Jul 11 2019, 9:09 AM
thopre marked 4 inline comments as done.
  • Rebase on latest changes in the patch series
  • Address most comments
llvm/include/llvm/Support/FileCheck.h
642

I'll schedule a patch to that effect before this one since changing this might touch some area not currently touched by this patch. Keeping your comment open for now, will close it once I've added the patch to the patch series.

thopre updated this revision to Diff 209488.Jul 12 2019, 7:59 AM

Rebase on top of latest changes in patch series

thopre updated this revision to Diff 209708.Jul 13 2019, 4:11 PM

Add more unit tests

jhenderson added inline comments.Jul 16 2019, 2:50 AM
llvm/docs/CommandGuide/FileCheck.rst
632

If I'm not mistaken, the %<fmtspec> bit isn't implemented in this patch?

llvm/include/llvm/Support/FileCheck.h
113

Add to this comment what the value of the variable is if ExpressionAST is null.

llvm/lib/Support/FileCheck.cpp
37

This is unchecked in builds without assertions.

39

I can't parse this string here. I can't even really figure out what this means to suggest an alternative.

48–50

I'm not sure this second sentence is necessary?

546

You don't need the explicit StringRef(...) here. Just do MatchRegexp = "[0-9]+";

597

DefineCmdlineVariables doesn't conform to style guide. I haven't bothered looking it up, but I imagine this comment is a bit stale, or the function needs renaming?

1814

Suffix3? What happened to Suffix2?

Honestly, these names don't make a huge amount of sense to me.

Also, do we need all of them? As far as I can see, Suffix1 and Suffix3 are only used once each, so should just be inlined.

1817

DefNo -> DefIndex

("No" here is not sufficiently clear as to its context, IMO).

1827

Should this be parseNumericSubstitutionBlock?

1852

This comment sounds like a lie? You aren't skipping the error here...

1862–1871

"Parse the definition both to check that the syntax is correct and to create ..."

1875

Why is the expression being evaluated here? This probably needs a comment.

thopre updated this revision to Diff 210058.Jul 16 2019, 3:49 AM
thopre marked 14 inline comments as done.

Address review comments

thopre added inline comments.Jul 16 2019, 3:49 AM
llvm/lib/Support/FileCheck.cpp
37

That's fine. setValue is called after substitution has happened and match was successful. Therefore ExpressionAST ought to evaluate fine. This is just in case code is reworked in the future and this invariant is broken.

jhenderson added inline comments.Jul 16 2019, 3:59 AM
llvm/lib/Support/FileCheck.cpp
37

It isn't. LLVM Errors and Expecteds HAVE to be checked. If they aren't it will lead to an abort. From the Programmer's Manual:

All Error instances, whether success or failure, must be either checked or moved from (via std::move or a return) before they are destructed. Accidentally discarding an unchecked error will cause a program abort at the point where the unchecked value’s destructor is run, making it easy to identify and fix violations of this rule.

thopre updated this revision to Diff 210062.Jul 16 2019, 4:27 AM
thopre marked 2 inline comments as done.

Address review comments

llvm/lib/Support/FileCheck.cpp
37

Oh my bad, didn't make the connection with the Expected type. I think an abort would be fine in this case since that error should never occur in any of the executions. By that I mean that code path should be dead (that function will not be called if the expression does not evaluate). If it does, it's a bug somewhere in the code.

Does that make sense? I've added some comments on the expectation for the caller both in the declaration and just on top of the assert since that was missing.

probinson added inline comments.Jul 16 2019, 9:58 AM
llvm/docs/CommandGuide/FileCheck.rst
632

Where is <constraint> described?

llvm/lib/Support/FileCheck.cpp
40

You should check the Expected return value with something other than an assert. It is not sufficient to claim that the caller should call this only when the Expected result must be success. The contract for using Expected is that you will check the result. You could do something like

if (!EvaluatedValue || *EvaluatedValue != NewValue)
  llvm_unreachable("New value does not match expression for this variable");
471

? this should be the default, you should not have to say = StringRef() explicitly.

FTR, I haven't done a rigorous check of all the different new code paths to ensure you've got testing for them all, I'm afraid - the change is too large to sensibly do that, although I accept that it probably needs to be this large.

llvm/lib/Support/FileCheck.cpp
40

I think cantFail is intended for the kind of situation we're in here.

42

Isn't the assertion that the eval() function succeeded. In that case, let's talk about that. "Failed to evaluate expression when sanity checking variable value" or something to that effect.

1815

Won't this create a StringRef to a temporary?

1823

Append a copy of the command-line...

1834

Prefix1 + DefIndex + Prefix2 is used twice, once in each part of the if. If you factor it out into a separate variable, it'll be much easier to read, I think, and you can then get rid of Prefix1 and Prefix2 as separate variables. You can even fold them into the place where DefIndex is created, to avoid additional non-Twine string concatenations:

std::string SomeName = ("Global define #" + Twine(++I) + ": ").str();

1875

"Now evaluate the expression, whose value this variable should be set to, since the expression of a command-line variable definition should only use variables defined earlier on the command-line."

llvm/test/FileCheck/numeric-defines-diagnostics.txt
5

By the way, if you were to use --match-full-lines, you wouldn't need to use the regular expression in the last line of each of these checks, and your arrow would point closer to where it should be.

llvm/test/FileCheck/numeric-defines.txt
4

There should probably be a test case like the original, i.e. with no expression, just a literal numeric value.

llvm/test/FileCheck/numeric-expression.txt
91

This is allowed? That's surprising to me, although I suppose it's a natural consequence of the rules.

172

"when a variable"

174

Double dashes here, please.

Is it worth checking the error message in this context, to show that the failure is due to the expression match rather than due to something to do with the definition?

llvm/unittests/Support/FileCheckTest.cpp
85

Perhaps "Variable defined by numeric expression:" would make more sense.

88

"UseUnique" doesn't seem to line up with what this test is supposed to be doing, from what I can tell. What is "Unique" about it?

94

FoobarVar is the "undefined variable being set", right? In that case, I think a more purposeful name might be useful, e.g. FromVarExprVar or something like that. Happy with alternative names though.

332

I might be being dumb here, but where does the "same line" come into the following 4 EXPECTs?

394

How about EXPECT_FALSE/TRUE(Test.matchExpect(""));?

561

There are probably many other places where this is a problem already, but this should be ASSERT_TRUE, since the test cannot continue if it fails, and will crash on the next line (probably). Perhaps a separate commit to clean those up would be appropriate.

thopre updated this revision to Diff 210410.Jul 17 2019, 2:08 PM
thopre marked 23 inline comments as done.
  • Address review comments
  • rebase on top of @LINE substitution fix
jhenderson added inline comments.Jul 18 2019, 2:02 AM
llvm/lib/Support/FileCheck.cpp
38

clang-format?

Rephrase the second string to "Value being set to different from variable evaluation"

1875

This comment hasn't been addressed.

llvm/test/FileCheck/numeric-defines-diagnostics.txt
5

This has been marked as Done, but I don't see any changes?

llvm/unittests/Support/FileCheckTest.cpp
85

I wanted the "Undefined" bit deleting. I don't think it's needed.

thopre added inline comments.Jul 18 2019, 3:08 AM
llvm/lib/Support/FileCheck.cpp
1875

I'm confused by what aspect of this you want to be explained. The reworded text seems to explain why is the expression evaluated but I thought you were asking why is it evaluated *here*. If the former, the text should be reworded further to remove the mention about errors and only say that the value of a variable can be given by an expression using variable earlier on the command line. If the latter, then the "only" becomes important since we are saying both that it is safe to evaluate now (we have the value of all variables) and that we should be doing it now (there is no input to match, all variables used are defined either from earlier command-line or from literal values).

llvm/test/FileCheck/numeric-defines-diagnostics.txt
5

Rather further away since the previous line would still need {{ and escaping for [ while the caret check would not need anything. It does reduce the amount of syntax for that line but it also make other lines slightly more difficult to read since I have to remote the space after the colon due to the --strict-whitespace:

NUMERRCLIFMT:Global defines:1:46: error: invalid variable name

Do you think it's worth doing? I can schedule a separate patch if yes.

llvm/test/FileCheck/numeric-expression.txt
91

As you said it's a natural consequence and I thought it could actually be useful (to check you have a number in an error message but don't care about the value) so I didn't forbid it.

llvm/unittests/Support/FileCheckTest.cpp
88

There is already a FooVarUse of type FileCheckNumericVariableUse. This one is a unique_ptr of that type. I've renamed into FooVarUsePtr.

561

Wasn't aware of ASSERT_TRUE. Another patch to schedule.

thopre marked 2 inline comments as done.Jul 18 2019, 3:13 AM
thopre added inline comments.
llvm/lib/Support/FileCheck.cpp
1875

Sorry, forgot to submit my replies. Done marks automatically get pushed when submitting a new revision.

llvm/test/FileCheck/numeric-defines-diagnostics.txt
5

Marked it done because I wrote a reply and was expecting an answer about whether you think it is actually worth it. In the event you think it is indeed worth it, I would only mark the answer as done once the work has been completed.

Unfortunately I forgot to submit my replies.

thopre updated this revision to Diff 210523.Jul 18 2019, 3:25 AM
thopre marked 3 inline comments as done.

Fix more review comments

jhenderson added inline comments.Jul 18 2019, 3:51 AM
llvm/lib/Support/FileCheck.cpp
1875

The message content is fine as it stands in the current version. I've just suggested some grammar improvements. I think the meaning remains the same with them.

llvm/test/FileCheck/numeric-defines-diagnostics.txt
5

I guess it's not worth it. I just find the whole caret checking basically unreadable due to the regex as it stands. It feels quite fragile too.

Since you've got --strict-whitespace on, you could simplify the caret's line a little:
NUMERRCLIFMT-NEXT: {{^}} ^
(with appropriate numbers of spaces).

I don't think the trailing $ is important, really, in this case, but could be persuaded either way. In that case though, I'd put that in it's own {{$}} pattern. If you are happy with that, then please schedule a patch for that.

probinson added inline comments.Jul 18 2019, 6:42 AM
llvm/test/FileCheck/numeric-expression.txt
91

So [[#]] is equivalent to {{[0-9]+}} ? Might be worth a note in the documentation.

thopre updated this revision to Diff 210562.Jul 18 2019, 7:33 AM
thopre marked 4 inline comments as done.

Address remaining review comments

jhenderson accepted this revision.Jul 18 2019, 7:43 AM

LGTM, I think. You'd best get someone else (e.g. @probinson) to confirm too.

This revision is now accepted and ready to land.Jul 18 2019, 7:43 AM

A couple of minor things, otherwise LGTM.

llvm/docs/CommandGuide/FileCheck.rst
639–640

constraint?

llvm/include/llvm/Support/FileCheck.h
114

"it is set from a value in the input" ? This is not a statement about what the ctor does, it sounds like an expectation.
"Otherwise, it should be set later from a value in the input." ?

thopre updated this revision to Diff 211339.Jul 23 2019, 11:25 AM
thopre marked 2 inline comments as done.
  • Remove reference to expression constraint, this is patch 11/12 material
  • Clarify what the FileCheckNumericVariable constructor does and what is rather an expectation
probinson accepted this revision.Jul 23 2019, 12:51 PM
This revision was automatically updated to reflect the committed changes.
craig.topper added inline comments.
llvm/trunk/lib/Support/FileCheck.cpp
345 ↗(On Diff #211365)

gcc 7.3.1 seems to be unhappy with this line. I think it wants a std::move around ExpressionAST.