NoQ added a comment.

> Would you mind me committing as is?

Np, please do, the patch is great regardless!



================
Comment at: lib/StaticAnalyzer/Checkers/PaddingChecker.cpp:352-355
+  if (Checker->AllowedPad < 0)
+    
Mgr.getDiagnostics().Report(diag::err_analyzer_checker_option_invalid_input)
+        << (llvm::Twine() + Checker->getTagDescription() + ":AllowedPad").str()
+        << "a non-negative";
----------------
Szelethus wrote:
> NoQ wrote:
> > Szelethus wrote:
> > > NoQ wrote:
> > > > 
> > > > I passively wish for a certain amount of de-duplication that wouldn't 
> > > > require every checker to obtain a diagnostics engine every time it 
> > > > tries to read an option. Eg.,
> > > > ```lang=c++
> > > >   auto *Checker = Mgr.registerChecker<PaddingChecker>();
> > > >   Checker->AllowedPad = Mgr.getAnalyzerOptions()
> > > >           .getCheckerIntegerOption(Checker, "AllowedPad", 24);
> > > >   if (Checker->AllowedPad < 0)
> > > >     Mgr.reportInvalidOptionValue(Checker, "AllowedPad", "a 
> > > > non-negative");
> > > > ```
> > > > 
> > > > Or maybe even something like that:
> > > > 
> > > > ```lang=c++
> > > >   auto *Checker = Mgr.registerChecker<PaddingChecker>();
> > > >   Checker->AllowedPad = Mgr.getAnalyzerOptions()
> > > >           .getCheckerIntegerOption(Checker, "AllowedPad", 24,
> > > >                   [](int x) -> Option<std::string> {
> > > >                       if (x < 0) {
> > > >                         // Makes getCheckerIntegerOption() emit a 
> > > > diagnostic
> > > >                         // and return the default value.
> > > >                         return "a non-negative";
> > > >                       }
> > > >                       // Makes getCheckerIntegerOption() successfully 
> > > > return
> > > >                       // the user-specified value.
> > > >                       return None;
> > > >                   });
> > > > ```
> > > > I.e., a validator lambda.
> > > First one, sure. I'm a little unsure about the second: No other 
> > > "options"-like classes have access to a `DiagnosticsEngine` in clang, as 
> > > far as I'm aware, and I guess keeping `AnalyzerOptions` as simple is 
> > > possible is preferred. Not only that, but a validator lambda seems an to 
> > > be an overkill (though really-really cool) solution. Your first bit of 
> > > code is far more readable IMO.
> > Hmm, in the first example we'll also have to manually reset the option to 
> > the default value if it is invalid, which is also annoying - even if easy 
> > to understand, it's also easy to forget.
> > 
> > And with that and a bit of polish, the lambda approach isn't really much 
> > more verbose, and definitely involves less duplication:
> > 
> > ```lang=c++
> > auto *Checker = Mgr.registerChecker<PaddingChecker>();
> > Checker->AllowedPad = Mgr.getAnalyzerOptions()
> >         .getCheckerIntegerOption(Checker, "AllowedPad", 24);
> > if (Checker->AllowedPad < 0) {
> >   Mgr.reportInvalidOptionValue(Checker, "AllowedPad", "a non-negative 
> > value");
> >   Checker->AllowedPad = 24;
> > }
> > ```
> > vs.
> > ```lang=c++
> > auto *Checker = Mgr.registerChecker<PaddingChecker>();
> > Checker->AllowedPad = Mgr.getAnalyzerOptions()
> >         .getCheckerIntegerOption(Checker, "AllowedPad", /*Default=*/ 24,
> >                                  /*Validate=*/ [](int x) { return x >= 0; },
> >                                  /*ValidMsg=*/ "a non-negative value");
> > ```
> Alright, so I've given this a lot of thought, here's where I'm standing on 
> the issue:
> 
> * I would prefer not to add `DiagnosticsEngine` to `AnalyzerOptions`. In 
> fact, I'd prefer not to add it even as a parameter to one of it's methods -- 
> designwise, it should be a simple mapping of the command line parameters, not 
> doing any complicated hackery.
> * You got me convinced the validator lambda thing ;). However, a nice 
> implementation of this (emphasis on //nice//) is most definitely a bigger 
> undertaking.
> * Once we're at the topic of "easy to forget", we could also verify 
> compile-time whether checker options are actually used -- what I'm thinking 
> here, is something like this:
> 
> ```
> auto *Checker = Mgr.registerChecker<PaddingChecker>();
> Mgr.initFieldWithOption(Checker, "AllowedPad",
>                         // Note that we should be able
>                         // to know the default value.
>                         Checker->AllowedPad,
>                         // We could make this optional by defining a
>                         // default validator...
>                         /*Validate=*/ [](int x) { return x >= 0; },
>                         // ...aaaand a default error message.
>                         /*ValidMsg=*/ "a non-negative value");
> ```
> `CheckerManager` later (once all checker registry functions finished) could 
> validate, with the help of `CheckerRegistry`, whether
> * All options for a given checker were queried for,
> * The supplied checker options is valid, if not, restore them in 
> compatibility mode, emit an error otherwise,
> * No list is complete without a third item.
> 
> For now, I admit, I have little interest in this. Would you mind me 
> committing as is?
> Once we're at the topic of "easy to forget", we could also verify 
> compile-time whether checker options are actually used -- what I'm thinking 
> here, is something like this:
> ```lang=c++
> auto *Checker = Mgr.registerChecker<PaddingChecker>();
> Mgr.initFieldWithOption(Checker, "AllowedPad",
>                         // Note that we should be able
>                         // to know the default value.
>                         Checker->AllowedPad,
>                         // We could make this optional by defining a
>                         // default validator...
>                         /*Validate=*/ [](int x) { return x >= 0; },
>                         // ...aaaand a default error message.
>                         /*ValidMsg=*/ "a non-negative value");
> ```
For **ULTIMATE** reliability and reusability, i'd also use a pointer-to-member 
argument instead of a pass-by-reference out-parameter, so that make sure that 
the value is indeed stored in the checker:
```lang=c++
Mgr.initFieldWithOption(Checker, "AllowedPad",
                        &PaddingChecker::AllowedPad,
                        ...)
```
(sorry, couldn't help myself)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57850/new/

https://reviews.llvm.org/D57850



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to