Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
4482 | This doesn't look all that safe - you're using a None value to indicate failure, but no current code path does that and none of the callers seem to check for failure. I get the feeling this is correct and I don't have enough context to understand why... how about you :-) |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
4482 | APValue() is a valid representation for an object of class type, representing a class object that is outside its lifetime, so I think it's OK to use this representation, if we can be sure that this only happens along error paths. (It's not ideal, though.) If we can't be sure this happens only along error paths, then we should produce a diagnostic here. Perhaps feed an EvalInfo& and a source location into every caller of this function and produce a diagnostic if we end up querying the default-initialized value of an incomplete-but-valid class type. Or perhaps we could check that the class is complete and valid from every caller of this function instead. (I think that we guarantee that, for a valid complete class type, all transitive subobjects are of valid complete types, so checking this only once at the top level before calling into getDefaultInitValue should be enough.) |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
4482 | Thanks for the suggestions. oh, yeah, I missed that the Foo Decl is invalid, so checking the class decl is valid at every caller of getDefaultInitValue should work -- it would also fix other potential issues, looks like here we guarantee that the VarDecl is valid, but don't verify the decl which the VarDecl's type refers to is valid in all callers. Given the fact that the VarDecl e is valid and class Foo Decl is invalid, another option to fix the crash is to invalidate this VarDecl. Should we invalidate the VarDecl if the type of the VarDecl refers to an invalid decl? My gut feeling is that it is worth keeping the VarDecl valid, so that more related AST nodes will be built (for better recovery and diagnostics), though it seems unsafe. |
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
4482 | I think keeping the VarDecl valid is probably the better choice, to allow us to build downstream uses of it. Also, because variables can be redeclared, we could have something like struct A; extern A v; struct A { invalid; }; -- and we can't reasonably retroactively mark v as invalid in this case, so we can't guarantee that the type of every valid variable is itself valid. (We *could* guarantee that the type of every valid variable *definition* is valid, but that will lead to inconsistencies where defining the variable causes later behavior of references to the variable to change.) It's really unfortunate that we don't have a good definition of what "valid" means for a variable, or really any listing of what invariants we maintain in the AST in the presence of invalid nodes. :( This is one of the things I would work on if I had time... |
Update per Richard's comment: do the error check in getDefaultInitValue, and
modify every caller of it to support the error handling.
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
4482 |
yeah, that makes sense, thanks for the explanation. I have updated the patch -- now the getDefaultInitValue() does error check. If fails, return APValue() which will only happen on error paths. Since it changes non-trivial amount of code, would be nice if you can take a look.
that would be nice to have, and given that we have containsErrors, the meanings of them are subtle (sometimes I got confused by these concepts). Would you like me to help here? happy to help though I don't fully understand clang yet. |
Minor suggestions but this LGTM.
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
4478–4480 | It would be useful to mention here that this only happens if we encounter something invalid (so that callers know they don't need to produce a nice diagnostic). | |
4482 |
If you're motivated, this might be a good way to learn more about Clang :) You'll certainly discover things that no-one knows about Clang (and a fair few bugs) if you add something like the LLVM IR verifier for the Clang AST. | |
5947–5951 | Nit: you're inconsistently using if (!get) Success = false; here and Success &= get; above and below. I'd prefer it if you expressed this the same way in all three cases in this function. | |
9086 | This is the only place where we produce a diagnostic after getDefaultInitValue fails. It'd be more consistent to just return false here. |
Thanks for the review!
clang/lib/AST/ExprConstant.cpp | ||
---|---|---|
4482 | oh, I thought it's just something low-hanging fruit like clarifying comments/documentation. Adding verifier to clang AST looks promising and ambitious (personally I like it), but would probably require a lot of work. | |
5947–5951 | oops, made it consistent with Success &= |
It would be useful to mention here that this only happens if we encounter something invalid (so that callers know they don't need to produce a nice diagnostic).