<div dir="auto">Hi!<div dir="auto"><br></div><div dir="auto">Do you have something in mind like this: <a href="https://reviews.llvm.org/D33672">https://reviews.llvm.org/D33672</a> ?</div><div dir="auto"><br></div><div dir="auto">Regards,</div><div dir="auto">Gábor</div></div><br><div class="gmail_quote"><div dir="ltr">Artem Dergachev via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> ezt írta (időpont: 2018. okt. 25., Cs 4:32):<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
Your overall plan sounds good, and i believe that such checker will be <br>
very useful, i'd love to have such check in the analyzer. If you want to <br>
post it upstream, i encourage you to start early by publishing <br>
prototypes on Phabricator for code reviews, even when you think they're <br>
not ready, just because code reviews are cool!<br>
<br>
Path-sensitive analysis is indeed useful here because sometimes it's not <br>
immediately obvious from the code which values are possible for the <br>
sub-expression. Defining the buggy state can be a bit annoying because <br>
enum values can be non-contiguous and/or numerous; the former means that <br>
you'll potentially need to make a lot of State->assume(...) calls and <br>
see if none of the states with assumptions are null; the latter means <br>
that you'll need to make sure you identify segments of values to avoid <br>
calling assume() for *every* enum item. I also recommend <br>
ConstraintManager::assumeInclusiveRange() for direct assumptions over <br>
segments.<br>
<br>
Your questions so far are AST questions, not specific to the analyzer. <br>
First of all, notice that every expression has a (qualified) type, which <br>
is the type of the value it evaluates to, and it can always be obtained <br>
via Expr::getType(). It may be void (eg., call expression for a function <br>
that returns void), but it's always there.<br>
<br>
For cast-expression, as you might have already guessed, the type of the <br>
expression is the target type of the cast. Because, well, that's the <br>
whole point of the cast. This takes care of question 2.<br>
<br>
Most functions return not raw Types but QualType objects that are types <br>
with qualifiers. You can always use the overloaded operator->() on the <br>
QualType to access the underlying Type; there's also <br>
QualType::getTypePtr(), but if you think you need it - most likely you <br>
don't.<br>
<br>
Now, types, like statements or declarations, are a hierarchy. Some types <br>
are integer types, some are array or structure types, some are enum <br>
types. Enum types are represented by the EnumType class, to which you <br>
can try to dyn_cast<>() your type. Or, even better, use Type::getAs<>(), <br>
which can be accessed directly with operator->() on QualType.<br>
<br>
If dyn_cast<>()/getAs<>() is successful - your type is an enum and you <br>
have a pointer to an EnumType object, so you can call <br>
EnumType::getDecl() to find the *declaration* of the enum in the code.<br>
<br>
Also if the enum hides under a typedef, then the type wouldn't be an <br>
EnumType but it'd be a TypedefType, so the cast would fail. The easy way <br>
to get rid of typedefs is to do QualType::getCanonicalType().<br>
<br>
Some declarations are forward declarations. You might need to do <br>
EnumDecl::getDefinition() to find the actual definition. Maybe you don't <br>
need that: i don't remember what operations are allowed on incomplete <br>
enum types.<br>
<br>
Once you have your EnumDecl that is the definition, you can iterate over <br>
EnumDecl::enumerators() to see what values are present.<br>
<br>
In Clang there are a lot more cast kinds of expressions than you <br>
probably expect, so you might want to take a look at the list of casts <br>
in clang/AST/OperationKinds.def and see which ones do you need; i don't <br>
think it'll be important at first, but just in case.<br>
<br>
In order to quickly catch up on the basics, i also recommend the AST <br>
tutorial by Manuel Klimek at <a href="https://www.youtube.com/watch?v=VqCkCDFLSsc" rel="noreferrer noreferrer" target="_blank">https://www.youtube.com/watch?v=VqCkCDFLSsc</a><br>
<br>
<br>
On 10/24/18 5:16 PM, Alexander Zaitsev via cfe-dev wrote:<br>
><br>
> Hello. I am newbie in Clang Static Analyzer and I am trying to write <br>
> new Clang Static Analyzer check, which is aimed to find issues with <br>
> casting values to enum: if we cast anything which is no presented in <br>
> target enum it will be unspecified/undefined behavior(depends on C++ <br>
> version).<br>
><br>
> So my plan is:<br>
><br>
> 1. Find all casts in source code. Seems like<br>
> 'check::PreStmt<CastExpr>>' it's what I need.<br>
> 2. In my implementation of `checkPreStmt` method I must get target<br>
> type from CastExpr, but I don't know, how to do it - can you help<br>
> with it?<br>
> 3. Then if target type in Cast is Enum, I must get all values from<br>
> this Enum and compare it with all possible values which can be<br>
> presented by CastExpr->getSubExpr() - here I don't know how to<br>
> evaluate CastExpr->getSubExpr() and how to get all values from Enum.<br>
><br>
> Do you have any ideas?<br>
><br>
> -- <br>
> Best regards,<br>
> Alexander Zaitsev<br>
><br>
><br>
> _______________________________________________<br>
> cfe-dev mailing list<br>
> <a href="mailto:cfe-dev@lists.llvm.org" target="_blank" rel="noreferrer">cfe-dev@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" rel="noreferrer">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>