<span style="color: rgb(51, 51, 51); font-family: Verdana, 宋体, Helvetica, sans-serif; font-size: 14px;">Thanks Artem, Aleksei for those precious information.</span><br style="z-index: 0; color: rgb(51, 51, 51); font-family: Verdana, 宋体, Helvetica, sans-serif; font-size: 14px;"><div style="z-index: 0; margin: 0px; padding: 0px; zoom: 1; color: rgb(51, 51, 51); font-family: Verdana, 宋体, Helvetica, sans-serif; font-size: 14px;"><br style="z-index: 0;"><div style="z-index: 0; margin: 0px; padding: 0px; zoom: 1;"><div style="z-index: 0; margin: 0px; padding: 0px; zoom: 1;">Yes, I observed exactly the same thing about MaterializeTemporaryExpr and I actually spent quite sometime trace into the clang's codebase and reached to the exactly same place in the link: createTemporaryRegionIfNeeded. My workaround was inspired by one of the example checkers, that uses a checkPostStmt on MaterializeTemporaryExpr. Thanks for pointing out this.<br style="z-index: 0;"><div style="z-index: 0; margin: 0px; padding: 0px; zoom: 1;"><br style="z-index: 0;"><div style="z-index: 0; margin: 0px; padding: 0px; zoom: 1;">Aleksei, thanks for pointing out the getQualifiedNameAsString, I didn't know I could use that . I personally prefers it because getParent()->getName() doesn't contain the namespace, but only the class name. So to make it safe, I need to go all the way up to traverse all parent decls, and getQualifiedNameAsString already does the thing for me.<br style="z-index: 0;"><div style="z-index: 0; margin: 0px; padding: 0px; zoom: 1;"><br style="z-index: 0;">Thanks for taking your time to answer my question. I appreciate it.<br style="z-index: 0;"></div><div><br></div><div>Now I observed some other weird thing, and I wonder if anyone has seen this before and knows any solution.</div><div><br></div><div>As a reminder, the checker I am writing is for a particular class T in my company's code base and the checker is to ensure T.ok() == true before calling T.value().</div><div><br></div><div>The above is actually a over-simplification to my task. The class T actually has a member, Let's say s_ (in type S) to keep track of the status, so T.ok() actually returns s_.ok(). And type S is used directly by a few other classes and macros which are used to creates T. So to make the check fully working, I also need to model the behaviors of S and a few other classes.</div><div><br></div><div>Fortunately, T are template class and therefore all method implementations are visible to current TU. I was thinking, it is a whole lot easier if I can just model the behavior of S, and rely on inline evaluation in the static analyzer. In most cases, it works, except I found the following corner case (suppose T has a conversion constructor from X: T(X&&) and default move constructor T(T&&)):</div><div><br></div><div>X f();</div><div>T t = f();</div><div><br></div><div>This is essentially constructs a temporary T t2{f()} and then doing a move T t{std::move(t2)}. It looks fine if everything is inlined, however, the inline doesn't work because t2 is a temporary. I dived into the code base and what happened is</div><div><br></div><div>1. At the end of <a href="https://clang.llvm.org/doxygen/ExprEngineCXX_8cpp_source.html#!00183">ExprEngine::getRegionForConstructedObject</a>, it is marked as improperly modeled target region:</div><div><span style="color: rgb(0, 0, 0); font-family: monospace, fixed; font-size: 13px; text-indent: -53px; white-space: pre-wrap; background-color: rgb(251, 252, 253);">CallOpts.</span><a class="code" href="https://clang.llvm.org/doxygen/structclang_1_1ento_1_1ExprEngine_1_1EvalCallOptions.html#a339aa5a5b9aecfa8a844647b8d211eb0" style="color: rgb(70, 101, 162); text-decoration-line: none; font-family: monospace, fixed; font-size: 13px; text-indent: -53px; white-space: pre-wrap; background-color: rgb(251, 252, 253);">IsCtorOrDtorWithImproperlyModeledTargetRegion</a><span style="color: rgb(0, 0, 0); font-family: monospace, fixed; font-size: 13px; text-indent: -53px; white-space: pre-wrap; background-color: rgb(251, 252, 253);"> = </span><span class="keyword" style="color: rgb(0, 128, 0); font-family: monospace, fixed; font-size: 13px; text-indent: -53px; white-space: pre-wrap; background-color: rgb(251, 252, 253);">true</span><span style="color: rgb(0, 0, 0); font-family: monospace, fixed; font-size: 13px; text-indent: -53px; white-space: pre-wrap; background-color: rgb(251, 252, 253);">;</span></div><div><span style="color: rgb(0, 0, 0); font-family: monospace, fixed; font-size: 13px; text-indent: -53px; white-space: pre-wrap; background-color: rgb(251, 252, 253);"><br></span></div><div><div>2. In <a href="https://clang.llvm.org/doxygen/ExprEngineCallAndReturn_8cpp_source.html#!00677">ExprEngine::mayInlineCallKind</a>, it returns false if the flag is set:</div></div><div><pre id="c1" class="stx-plain" style="margin-top: 0px; margin-bottom: 0px; color: rgb(0, 0, 0); z-index: 50; position: relative; padding-top: 0.5em; outline: none; font-size: medium;"><span class="stx-line" id="c1_674" style="display: block;"> <span class="stx-comment" style="color: rgb(136, 0, 0);">// If we did not find the correct this-region, it would be pointless</span>
</span><span class="stx-line" id="c1_675" style="display: block;"> <span class="stx-comment" style="color: rgb(136, 0, 0);">// to inline the constructor. Instead we will simply invalidate</span>
</span><span class="stx-line" id="c1_676" style="display: block;"> <span class="stx-comment" style="color: rgb(136, 0, 0);">// the fake temporary target.</span>
</span><span class="stx-line" id="c1_677" style="display: block;"> <span class="stx-keyword" style="color: rgb(0, 0, 136);">if</span> (<a class="MainCss-annotationInternalLink" href="https://cs.corp.google.com/piper///depot/google3/third_party/llvm/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?l=618&ct=xref_jump_to_def&gsn=CallOpts&rcl=186553626" style="text-decoration-line: none; color: rgb(85, 26, 139);">CallOpts</a>.<a class="MainCss-annotationInternalLink" href="https://cs.corp.google.com/piper///depot/google3/third_party/llvm/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?l=62&ct=xref_jump_to_def&gsn=IsCtorOrDtorWithImproperlyModeledTargetRegion&rcl=186553626" style="text-decoration-line: none; color: rgb(85, 26, 139);"><span id="m_c1_0" class="chl" style="background: rgb(136, 255, 184); font-weight: bold; line-height: 1em;">IsCtorOrDtorWithImproperlyModeledTargetRegion</span></a>)
</span><span class="stx-line" id="c1_678" style="display: block;"> <span class="stx-keyword" style="color: rgb(0, 0, 136);">return</span> <a class="MainCss-annotationInternalLink" href="https://cs.corp.google.com/piper///depot/google3/third_party/llvm/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?l=623&ct=xref_jump_to_def&gsn=CIP_DisallowedOnce&rcl=186553626" style="text-decoration-line: none; color: rgb(85, 26, 139);">CIP_DisallowedOnce</a>;</span></pre></div><div><br></div><div>I am not an expert in C++ compiler. I just wonder why it can't allocates a temporary region for temporary variables? Having this special case means I need to model all T's constructors, which is really annoying. Does anyone knows some workarounds? Thanks.</div><div><br></div><div><br></div></div></div></div></div></div><div id="origbody"><div style="background: #f2f2f2;">----- Original Message -----<br>From: Artem Dergachev <noqnoqneo@gmail.com><br>To: Aleksei Sidorin <a.sidorin@samsung.com>, Li Kan <likan_999.student@sina.com>, cfe-dev@lists.llvm.org<br>Subject: Re: [cfe-dev] Static analyzer question on how to tell if a Decl is a particular c++ function, or a particular class<br>Date: 2018-02-16 02:26<br></div><br><br>Yeah, the traditional way to see if this is a certain method of a <br>certain class is to compare the name of the method <br>(CXXMethodDecl->getName()) and the class <br>(CXXMethodDecl->getParent()->getName()), as strings, to the desired <br>strings. getQualifiedNameAsString() works fine, but it's considered slow <br>for whatever reason (i've never observed it personally). ASTMatchers <br>would also work, even if a bit of an overkill. Don't forget to check the <br>method's argument number and types as well. We have an effort to make <br>this whole common idiom more simple via CallDescription, but it doesn't <br>work for C++ methods yet.<br>With C++, you'll need to be aware of the bug we're currently having with <br>object lifetime extension. If you're identifying the object by its <br>memory region (which is correct), you'd occasionally notice that the <br>region for a C++ temporary object may change along the analysis even if <br>no copy-construction occurs. It has been making our new C++ checkers <br>(most noticeably, the iterator checker) more difficult to write than <br>they needed to be. More details in <br>http://lists.llvm.org/pipermail/cfe-dev/2018-February/056898.html - i'm <br>hoping to do something about it soon.<br>On 15/02/2018 1:35 AM, Aleksei Sidorin via cfe-dev wrote:<br>> Hello Li,<br>><br>> What you're doing is mostly fine. I can only add some potentially <br>> useful info inline.<br>><br>> 14.02.2018 23:04, Li Kan via cfe-dev пишет:<br>>> Hi folks,<br>>><br>>> If this is not the correct mailing list for this question, please let <br>>> me know.<br>> You're in the right place. Welcome :)<br>><br>>> I am trying to write a static analyzer for code base of my current <br>>> job. The particular static analyzer I am writing involves a <br>>> particular class of my company's code base. Let's say it is T. I want <br>>> to write a checker to ensure T.ok() is called before T.value() is called.<br>>><br>>> Static analyzer is perfect for this type of check as it requires path <br>>> sensitive checks. When I trying to write the checker, I basically <br>>> checks for pre-call and post-call. I want to tell if a CallEvent is <br>>> T.ok() and T.value(). Currently what I am doing is:<br>>> 1. From CallEvent, I cast to CXXMemberCall, and getOriginExpr(), then <br>>> call getMethodDecl().<br>> You can also try to do the following chain: <br>> dyn_cast_or_null<CXXMethodDecl>(CallEvent.getDecl()) to obtain <br>> CXXMethodDecl.<br>><br>>> 2. From CXXMethodDecl, I first call getThisType(), then call <br>>> getAsCXXRecordDecl(), then getQualifiedNameAsString(), and compare <br>>> with qualified name of T, to make sure it is member of T.<br>> To obtain parent class declaration from CXXMethodDecl, you can use <br>> getParent() method. So, the pseudocode will look like <br>> "MethodDecl->getParent()->getQualifiedNameAsString()".<br>><br>>> 3. From CXXMethodDecl, I call getNameAsString() to get the method <br>>> name, and compare them with "ok" and "value".<br>> This looks OK. But it can be useful to know that <br>> getQualifiedNameAsString() for CXXMethodDecl will also include parent <br>> name. So, you can just check if MethodDecl->getQualifiedNameAsString() <br>> is equal to "T::value" or "T::ok".<br>><br>>> It works, but it looks complicated, and involves string comparison, <br>>> which I assume is slow. Is there a easier way, blessed by clang <br>>> static analyzer official teams, that tell if a MethodDecl, or <br>>> CXXRecordDecl, is the function or class I am interested in?<br>>><br>>> The ideal way is, there is one-time call to lookup the MethodDecl for <br>>> T::ok() and T::value(), and CXXRecordDecl for T. Then ever since <br>>> then, I just need to compare the pointers.<br>> This is possible. You can just launch a simple matcher against AST:<br>> cxxMethodDecl(hasName("::T::value"))<br>> and get CXXMethodDecl you need and compare with it later.<br>><br>>> Another way is, the first time I found it is T, T::ok() or <br>>> T::value(), I save the pointer of CXXRecordDecl or MethodDecl, and <br>>> use the pointers later. Is this the reliable (assume I use the <br>>> pointer canonical decl will not change) and blessed way to do it? If <br>>> it is, is my steps above the correct and simplest way to determine it <br>>> is T::ok or T::value? Is there some better and more reliable way?<br>> I think it is reliable enough: pointers to canonical declarations <br>> don't change in AST.<br>>><br>>> Thanks.<br>>><br>>><br>>> _______________________________________________<br>>> cfe-dev mailing list<br>>> cfe-dev@lists.llvm.org<br>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br>><br>><br>> -- <br>> Best regards,<br>> Aleksei Sidorin,<br>> SRR, Samsung Electronics<br>><br>><br>> _______________________________________________<br>> cfe-dev mailing list<br>> cfe-dev@lists.llvm.org<br>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br></div>