How does Clang Staic Analyzer deal with DeclRefExpr?

Hi all,

I am confused on the behavior of Analyzer dealing with DeclRefExpr. For an example:
1 int a, b;
2 a = 56;
3 b = a;
4 a = b - 8;

I wanted to print the Stmt information in the checkPostStmt(), and I got the results below:

IntegerLiteral 0x4dbc078 ‘int’ 56

BinaryOperator 0x4dbc098 ‘int’ ‘=’

-DeclRefExpr 0x4dbc050 ‘int’ lvalue Var 0x4d8bc80 ‘a’ ‘int’
`-IntegerLiteral 0x4dbc078 ‘int’ 56

ImplicitCastExpr 0x4dbc110 ‘int’
`-DeclRefExpr 0x4dbc0e8 ‘int’ lvalue Var 0x4d8bc80 ‘a’ ‘int’

BinaryOperator 0x4dbc128 ‘int’ ‘=’

-DeclRefExpr 0x4dbc0c0 ‘int’ lvalue Var 0x4d8bcf0 ‘b’ ‘int’
-ImplicitCastExpr **0x4dbc110** 'int' <LValueToRValue> -DeclRefExpr 0x4dbc0e8 ‘int’ lvalue Var 0x4d8bc80 ‘a’ ‘int’

ImplicitCastExpr 0x4dbc1c0 ‘int’
`-DeclRefExpr 0x4dbc178 ‘int’ lvalue Var 0x4d8bcf0 ‘b’ ‘int’

IntegerLiteral 0x4dbc1a0 ‘int’ 8

BinaryOperator 0x4dbc1d8 ‘int’ ‘-’

-ImplicitCastExpr 0x4dbc1c0 ‘int’
-DeclRefExpr 0x4dbc178 'int' lvalue Var 0x4d8bcf0 'b' 'int' -IntegerLiteral 0x4dbc1a0 ‘int’ 8

BinaryOperator 0x4dbc200 ‘int’ ‘=’

-DeclRefExpr 0x4dbc150 ‘int’ lvalue Var 0x4d8bc80 ‘a’ ‘int’
-BinaryOperator **0x4dbc1d8** 'int' '-' -ImplicitCastExpr 0x4dbc1c0 'int' <LValueToRValue> -DeclRefExpr 0x4dbc178 ‘int’ lvalue Var 0x4d8bcf0 ‘b’ ‘int’
`-IntegerLiteral 0x4dbc1a0 ‘int’ 8

As we know, the Environment provides us a chance to get the corresponding value of some expression. So, when evaluating the value of BinOp 0x4dbc200 ‘int’ ‘=’, it can use the value of BinOp 0x4dbc1d8 ‘int’ ‘-’, which has been evaluated already.

Now I want to know that how Analyzer evaluates ‘b = a’ in Line 3. In other words, how does Analyzer know the value of a when evaluating ImplicitCastExpr 0x4dbc110 ‘int’ ? Does Analyzer get the value of a from Environment?

Thanks a lot.

Hi, Arthur. I’d like to refer you to the Checker Developer Manual at http://clang-analyzer.llvm.org/checker_dev_manual.html#analyzer. In particular, the Environment is used to map expressions to values. The Store is used to map memory regions to the values they contain.

In this example (“b = a”), we need to evaluate ‘a’-the-DeclRefExpr, whose value is the VarRegion for ‘a’. After that, we evaluate the LValueToRValue cast, which loads the value currently stored in the VarRegion for ‘a’ (from the Store). Then we evaluate the assignment, which updates the Store to record that the VarRegion for ‘b’ now contains the value we just loaded. (I skipped the DeclRefExpr for ‘b’, but that also needs to be evaluated so that we know which memory region is being updated.)

Most of the analyzer, including almost all checkers, shouldn’t need to directly access the Environment or the Store; they should instead just use the methods on ProgramState.

Hope that helps,
Jordan

Thank you, Jordan. Your reply really helps me.

I have another question. Is it true that the Analyzer doesn’t give checkers chances to evaluate UnaryExprOrTypeTraitExpr(sizeof/alignof), ParenExpr and MemberExpr? If I want to catch these kinds of Expr in my checker, what can I do?

Thank you.

ParenExpr is pretty much always treated as transparent, so I don’t feel bad about not allowing checkers to evaluate it. UnaryExprOrTypeTraitExpr can be completely evaluated by the compiler, so I’m not sure what sort of path-sensitive analysis you’d want there. (If you’re just trying to check syntactic properties, an AST walk would be better.) MemberExpr should certainly have a pre-call check. Patches welcome?

(if not, I’ll get to it soon-ish)
Jordan

ParenExpr isn’t even in the CFG, so it’s not actually possible for the analyzer to hand it to a checker. Are you sure you’re not better off with a RecursiveASTVisitor or with the AST matchers?

Jordan

Okay, should be working in r197059. Thanks for bringing this up!

Jordan

In article <136FAAF3-BC16-4A29-AE6C-3B9E373948F7@apple.com>,
    Jordan Rose <jordan_rose@apple.com> writes:

ParenExpr is pretty much always treated as transparent, so I don't feel bad
about not allowing checkers to evaluate it.

Does this imply that I can't write a checker that calls out
unnecessary parenthesis?

You can, but it has to do it using an AST walk, not a path-sensitive simulation.

Jordan

I am getting a build error when I try to make clang under CentOS 6.5 (64bit).

The error is:

/opt/clang+llvm-src/clang+llvm-svn/Release+Asserts/lib/libclang.so: undefined reference to `clang::ento::objc_retain::CallEffects::getEffect(clang::FunctionDecl const*)'
/opt/clang+llvm-src/clang+llvm-svn/Release+Asserts/lib/libclang.so: undefined reference to `clang::ento::objc_retain::CallEffects::getEffect(clang::ObjCMethodDecl const*)'

My configuration options are:

../llvm/configure --target=i386-redhat-linux-gnu --build=i386-redhat-linux-gnu --host=i386-redhat-linux-gnu --enable-optimized --prefix=/opt/clang+llvm-svn CXX=/opt/clang+llvm-3.3/bin/i386-redhat-linux-gnu-clang++ CC=/opt/clang+llvm-3.3/bin/i386-redhat-linux-gnu-clang LD=/opt/clang+llvm-3.3/bin/i386-redhat-linux-gnu-clang++

Is there anything else I should try? Or is the build broken?
This message is intended only for the addressee and may contain information that is company confidential or privileged. Any technical data in this message may be exported only in accordance with the U.S. International Traffic in Arms Regulations (22 CFR Parts 120-130) or the Export Administration Regulations (15 CFR Parts 730-774). Unauthorized use is strictly prohibited and may be unlawful. If you are not the intended recipient, or the person responsible for delivering to the intended recipient, you should not read, copy, disclose or otherwise use this message. If you have received this email in error, please delete it, and advise the sender immediately.

It has been fixed (partially) since r197116, FYI.

Thank you for the heads up.

Hi Jordan,

Thank you very much! Now I can catch these kinds of Expr. :slight_smile: