Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Speaking of the StaticAnalyzer, I think setting some default value is a fair point, and I think it's a good practice.
In our case, we initialized that field from the registration function, like this:
void ento::registerMoveChecker(CheckerManager &mgr) { MoveChecker *chk = mgr.registerChecker<MoveChecker>(); chk->setAggressiveness( mgr.getAnalyzerOptions().getCheckerStringOption(chk, "WarnOn"), mgr); // <--- initialized here }
clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp | ||
---|---|---|
187 | By looking at the default value of the Move.WarnOn checker option here, we should probably initialize this field to the default value matching the default value of the config. |
In our case, we initialized that field from the registration function, like this:
void ento::registerMoveChecker(CheckerManager &mgr) { MoveChecker *chk = mgr.registerChecker<MoveChecker>(); chk->setAggressiveness( mgr.getAnalyzerOptions().getCheckerStringOption(chk, "WarnOn"), mgr); // <--- initialized here }
Yes, While investigating other Coverity bugs about uninitialized scaler fields in StaticAnalyzer, i noticed about the registration function.
clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp | ||
---|---|---|
187 | void setAggressiveness(StringRef Str, CheckerManager &Mgr) { Aggressiveness = llvm::StringSwitch<AggressivenessKind>(Str) .Case("KnownsOnly", AK_KnownsOnly) .Case("KnownsAndLocals", AK_KnownsAndLocals) .Case("All", AK_All) .Default(AK_Invalid); if (Aggressiveness == AK_Invalid) Mgr.reportInvalidCheckerOptionValue(this, "WarnOn", "either \"KnownsOnly\", \"KnownsAndLocals\" or \"All\" string value"); By looking at the codes above, my understanding was that default value is AK_Invalid. Thank you @steakhal for the pointer and the explanation. |
I'm not opposed to these changes, but please note that these changes mean is will no longer be possible to use ubsan to discover when these data members are used before having been assigned an appropriate value. That is only a concern when an appropriate value would differ from the member initializers added via this change. I haven't reviewed the changes in depth, so I don't know if there are any such cases for which such a concern is applicable.
clang/include/clang/Parse/Parser.h | ||
---|---|---|
1190 | @tahonermann I feel like we should have a default member initializer for any member that by default is not initialized. I realize in this case there currently should be no way for this to be bot initialized but that may not stay true and I don't believe there will be a penalty for doing this since it is initialized in the mem-initializer-list and therefore the default init should be omitted when calling the constructor. |
clang/include/clang/Parse/Parser.h | ||
---|---|---|
1190 | I think that is very reasonable and I'm not opposed to such a policy. Per my other comment, the trade off to always initializing is that a default initializer can prevent use of tools like ubsan to discover when an appropriate (presumably non-default) value has not been assigned. I suspect (but have no data to draw on) that adding a default member initializer prevents more bugs than would be found by tools like ubsan detecting use of an uninitialized data member that should have a (non-default) assigned value. I'm definitely in favor of using default member initializers over mem-initializer-list! |
clang/include/clang/Parse/Parser.h | ||
---|---|---|
1190 |
Agreed. That is motivated me to add default initialization.
Thanks @tahonermann for the information! i was not aware of this ubsan tool. @shafik and @tahonermann, thank you for your comments. Do you think we should hold off these changes for merging? |
@tahonermann I feel like we should have a default member initializer for any member that by default is not initialized. I realize in this case there currently should be no way for this to be bot initialized but that may not stay true and I don't believe there will be a penalty for doing this since it is initialized in the mem-initializer-list and therefore the default init should be omitted when calling the constructor.