{"id":646,"date":"2018-03-12T14:18:21","date_gmt":"2018-03-12T14:18:21","guid":{"rendered":"http:\/\/cppdepend.com\/blog\/?p=646"},"modified":"2019-03-13T22:55:38","modified_gmt":"2019-03-13T22:55:38","slug":"hacking-on-clang-to-demystify-the-temporary-objects","status":"publish","type":"post","link":"https:\/\/cppdepend.com\/blog\/hacking-on-clang-to-demystify-the-temporary-objects\/","title":{"rendered":"Hacking on Clang to demystify the temporary objects"},"content":{"rendered":"<p>It is sometimes necessary for the C++ compiler to create temporary objects.They are used during:<\/p>\n<ul>\n<li>Reference initialization.<\/li>\n<li>Evaluation of expressions including standard type conversions.<\/li>\n<li>Argument passing.<\/li>\n<li>Function returns.<\/li>\n<li>Evaluation of the throw\u00a0expression.<\/li>\n<\/ul>\n<p><!--more--><\/p>\n<p>For non-trivial classes, the creation and destruction of temporary objects can be expensive in terms of processing time and memory usage. In this case, you should minimize their introduction. \u00a0The C++ compiler does eliminate some temporary objects, but it cannot eliminate all of them.<\/p>\n<p>It\u2019s not always easy to detect where the temporary objects are introduced, as Herb Sutter explains\u00a0in his\u00a0<a href=\"http:\/\/www.gotw.ca\/gotw\/002.htm\">sample<\/a>. The compiler has this information, but it\u2019s possible to get\u00a0the places where the temporary objects are introduced from the compiler? And if it\u2019s not the case, is it easy to modify it and report them?<\/p>\n<p>In our case we will use Clang, it\u2019s very flexible and\u00a0provides many ways to customize its behavior. Indeed a major design concept for clang is its use of a library-based architecture. In this design, various parts of the front-end can be cleanly divided into separate libraries which can then be mixed up for different needs and uses. In addition, the library-based approach encourages good interfaces and makes it easier for new developers to get involved (because they only need to understand small pieces of the big picture).<\/p>\n<p>The Clang compiler has three phase:<\/p>\n<ul>\n<li>The front end that parses source code, checking it for errors, and builds a language-specific Abstract Syntax Tree (AST) to represent the input code.<\/li>\n<li>The optimizer: its goal is to do some optimization on the AST generated by the front end.<\/li>\n<li>The back end: that generate the final code to be executed by the machine, it depends on the target.<\/li>\n<\/ul>\n<p><a href=\"http:\/\/cppdepend.files.wordpress.com\/2012\/10\/latfig1.gif\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-637\" title=\"latfig1\" src=\"http:\/\/cppdepend.files.wordpress.com\/2012\/10\/latfig1.gif?w=595\" alt=\"\" \/><\/a><\/p>\n<p>In our case we will focus more on the front end phase, the goal is to get the Abstart Syntax Tree (AST) for a source code, and\u00a0check if some useful data about the temporary objects are reported.<\/p>\n<p>Let\u2019s\u00a0 explore the AST of\u00a0 this minimal source code :<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-345\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast2.png\" alt=\"ast2\" width=\"484\" height=\"186\" \/><\/a><\/p>\n<p>To generate the AST we can execute the clang front end parser using the -cc1 switch.<\/p>\n<pre>clang -cc1 -ast-dump test.cpp\r\n<\/pre>\n<p>And here\u2019s the AST generated for the GetTest function:<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast11.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-359\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast11.png\" alt=\"ast1\" width=\"778\" height=\"180\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>In this AST two information are related to the temporary objects:\u00a0<strong>nrvo<\/strong>\u00a0and\u00a0<strong>elidable<\/strong>.<\/p>\n<p>Named Return Value Optimization is a compiler optimization technique that involves eliminating the temporary object created to hold a function\u2019s return value. NRVO eliminates the copy constructor and destructor of a stack-based return value. This optimizes out the redundant copy constructor and destructor calls and thus improves overall performance. For more details, you can refer to its\u00a0<a href=\"http:\/\/en.wikipedia.org\/wiki\/Return_value_optimization\">wiki page<\/a>.<\/p>\n<p>And the copy elision refers to a compiler optimization technique that eliminates unnecessary copying of objects. For more details, you can refer to its\u00a0<a href=\"http:\/\/en.wikipedia.org\/wiki\/Copy_elision\">wiki page<\/a>.<\/p>\n<p>It\u2019s interesting that the clang tell us where a nrvo is applied, but it&#8217;s not reporting explicitly where the temporary objects are created. Let\u2019s go inside the AST dumper source code and try to report them.<\/p>\n<p><strong>How ASTDumper works?<\/strong><\/p>\n<p>The compiler parses a program and represents the parsed\u00a0program as an abstract syntax tree (AST). The AST has many different\u00a0kinds of nodes, such as Assignment, Variable Reference, and Arithmetic\u00a0Expression nodes. After generating the AST, Clang invokes some front end actions that traverse it and do some treatments, the ASTDumpAction is one of them, it\u00a0permits to dump\u00a0the AST in the console.<\/p>\n<p>ASTDumper is declared like this<\/p>\n<pre>  class ASTDumper\r\n      : public ConstDeclVisitor, public ConstStmtVisitor,\r\n        public ConstCommentVisitor \r\n<\/pre>\n<p>The visitor pattern is the recommended pattern when we need to traverse a structure and do a specific treatment for each node of this structure.<\/p>\n<p>Here are some methods invoked when the AST is traversed, each one is related to a specific AST node.<\/p>\n<pre>void VisitNamespaceDecl(const NamespaceDecl *D);\r\nvoid VisitUsingDirectiveDecl(const UsingDirectiveDecl *D);\r\nvoid VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);\r\nvoid VisitTypeAliasDecl(const TypeAliasDecl *D);\r\nvoid VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D);\r\nvoid VisitCXXRecordDecl(const CXXRecordDecl *D);\r\nvoid VisitStaticAssertDecl(const StaticAssertDecl *D);\r\n<\/pre>\n<p><strong>Hacking the Clang AST dumper<\/strong><\/p>\n<p>Our goal is to report the temporary objects created, so we have to track the object creation and identify which AST node is concerned by the object construction.<\/p>\n<p>In case of clang the VisitCXXConstructExpr is invoked when a C++ object must be created, here\u2019s its implementation:<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast5.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-347\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast5.png\" alt=\"ast5\" width=\"681\" height=\"149\" \/><\/a><\/p>\n<p>As we can see there\u2019s no test if the object created is temporary or not, but the good news is that CXXConstructExpr has the method\u00a0IsTemporaryObject which\u00a0determine whether the result of this expression is a temporary object of the given class type.<\/p>\n<p>Let\u2019s change the implementation to add another condition:<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast6.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-348\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast6.png\" alt=\"ast6\" width=\"674\" height=\"179\" \/><\/a><\/p>\n<p>Here\u2019s the new AST printed after the modification<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-346\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/ast3.png\" alt=\"ast3\" width=\"779\" height=\"168\" \/><\/a><\/p>\n<p>After adding few lines of code, the ASTDumper report now explicitly where the temporary objects are created.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>The duo LLVM\/Clang is not just a compiler, but a powerful infrastructure to develop your own C\/C++\/Objective-C tools, it\u2019s not difficult to understand how it works, and easy to customize as you like. Don\u2019t hesitate to download the Clang source code, do some modifications and rebuild it, it will help special students to know how compilers work.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It is sometimes necessary for the C++ compiler to create temporary objects.They are used during: Reference initialization. Evaluation of expressions including standard type conversions. Argument passing. Function returns. Evaluation of the throw\u00a0expression.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[25,13,48],"class_list":["post-646","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-clang","tag-cpp","tag-memory"],"_links":{"self":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/646","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/comments?post=646"}],"version-history":[{"count":3,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/646\/revisions"}],"predecessor-version":[{"id":1247,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/646\/revisions\/1247"}],"wp:attachment":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/media?parent=646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/categories?post=646"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/tags?post=646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}