report

296 views

Published on

From Dropbox

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
296
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

report

  1. 1. Going Native HighlightsIntroduction to Variadic Templates. Clang overview.
  2. 2. Variadic Templates• Fundamentals• Usage• Samples Quickoffice Proprietary and Confidential - Not for Disclosure 2
  3. 3. FundamentalsClass declaration:template<typename... Ts>class A{};Function declaration:template<typename... Ts>voidfoo(const Ts&... vs){} Quickoffice Proprietary and Confidential - Not for Disclosure 3
  4. 4. What is Ts and vs?• Ts is an alias for a list of types• vs is an alias for a list of valuestypedef Ts MyList; // error!Ts var;// error!auto copy = vs;// error! Quickoffice Proprietary and Confidential - Not for Disclosure 4
  5. 5. Parameters Packs Usage• Get pack sizesize_t items = sizeof...(Ts); // or vs• Expand backtemplate<typename... Ts>voidfoo(const Ts&... Vs) { goo(1, std::forward<Ts>(vs)..., 42);} Quickoffice Proprietary and Confidential - Not for Disclosure 5
  6. 6. Expansion rulesUsage Expansion resultTs... T1, … , TnTs&... T1&, … , Tn&A<Ts, B>::foo... A<T1, B>::foo , … , A<Tn, B>::fooA<const Ts&, Us>... A<const T1&, U1>, … , A<constTn&, Un>pow(vs,42)... pow(v1, 42), … , pow(vn, 42) Quickoffice Proprietary and Confidential - Not for Disclosure 6
  7. 7. Where to use?• Initializer listsint a[] = { vs... };• Base class specifiertemplate<typename... Ts>struct A : B<Ts>...{};• Class members initializer liststemplate<typename... Us>A(Us... vs) : B<Ts>(vs)... {} Quickoffice Proprietary and Confidential - Not for Disclosure 7
  8. 8. Where to use?• Template arguments listsstd::map<Ts...>foo;• Exception specifications• Capture liststemplate<class... Ts>voidfoo(Ts... vs) {autolamda = [&vs...] { returngoo(vs...); }lamda();} Quickoffice Proprietary and Confidential - Not for Disclosure 8
  9. 9. Multiple expansionstemplate<class... Ts>voidfoo(Ts... vs){goo(A<Ts...>::hoo(vs)...);goo(A<Ts...>::hoo(vs...));goo(A<Ts>::hoo(vs)...);} Quickoffice Proprietary and Confidential - Not for Disclosure 9
  10. 10. Where is used?• std::make_sharedtemplate<class T, class... Ts>shared_ptr<T>make_shared(Ts&&... vs);• std::vector::emplace_backtemplate<class... Args>voidemplace_back(Args&&... args); Quickoffice Proprietary and Confidential - Not for Disclosure 10
  11. 11. Typesafeprintf• Stock printf: – Fast – Thread-safe – Convenient – Ubiquitously known – Utterly unsafe• Goal: add verification of the provided parameters Quickoffice Proprietary and Confidential - Not for Disclosure 11
  12. 12. Typesafeprintf• Adaptation routinestemplate<class T>Typenameenable_if<is_integral<T>::value, long>::typenormalizeArg(Targ) { returnarg; }template<class T>typenameenable_if<is_floating_point<T>::value, double>::typenormalizeArg(Targ) { returnarg; }template<class T>typenameenable_if<is_pointer<T>::value, T>::typenormalizeArg(Targ) { returnarg; }constchar* normalizeArg(const string&arg){ returnarg.c_str(); } Quickoffice Proprietary and Confidential - Not for Disclosure 12
  13. 13. Typesafeprintf// Not really safe yettemplate<typename... Ts>intsafe_printf(constchar* format, const Ts&... ts){returnprintf(format, normalizeArg(ts)...);} Quickoffice Proprietary and Confidential - Not for Disclosure 13
  14. 14. Typesafeprintf• Implement verification routine for argument-less callvoidcheck_printf(constchar * f){for (; *f; ++f){if (*f != ’%’ || *++f == ’%’) continue;throwExc("Bad format"); }} Quickoffice Proprietary and Confidential - Not for Disclosure 14
  15. 15. Typesafeprintftemplate<class T, typename... Ts>voidcheck_printf(constchar * f, const T&t, const Ts&... ts){for (; *f; ++f) {if (*f != ’%’ || *++f == ’%’) continue;switch (*f) {default: throwExc("Invalid format char: %", *f);case ’f’: case ’g’:ENFORCE(is_floating_point<T>::value);break;case ’s’: . . . }returncheck_printf(++f, ts...); // AHA!!! }throwExc("Too few format specifiers.");} Quickoffice Proprietary and Confidential - Not for Disclosure 15
  16. 16. Typesafeprintf• Final steptemplate<typename... Ts>intsafe_printf(constchar* format, const Ts&... ts){check_printf(format, normalizeArg(ts)...);returnprintf(format, normalizeArg(ts)...);} Quickoffice Proprietary and Confidential - Not for Disclosure 16
  17. 17. Clang• Motivation• Diagnostics• Static analysis• Dynamic analysis• Current state• Tool sample Quickoffice Proprietary and Confidential - Not for Disclosure 17
  18. 18. Why?• Performance• Diagnostics• Tools Quickoffice Proprietary and Confidential - Not for Disclosure 18
  19. 19. Why?intw = 0;for (inti = 0; i<3; i++)w += w * 2;$ gcc -fsyntax-only test.ctest.c:2: error: expected identifier or ‘(’ before ‘for’test.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘<’ tokentest.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘++’ token Quickoffice Proprietary and Confidential - Not for Disclosure 19
  20. 20. Why?“... is there a reason for not making the [GCC] front ends dynamic librarieswhich could be linked by any programthat wants to parse source code?” “One of our main goals for GCC is to prevent any parts of it from being used together with non-free software. Thus, we have deliberately avoided many things that might possibly have the effect of facilitating such usage...” - Richard Stallman Quickoffice Proprietary and Confidential - Not for Disclosure 20
  21. 21. Why?#define FOO 0intfoo() {intx;// ...x = x + FOO;// ...returnx;}#define FOO 0intfoo() {intx;// ...x = x;// ...returnx;} Quickoffice Proprietary and Confidential - Not for Disclosure 21
  22. 22. Diagnosticstemplate<int N>struct S1 { intarr[N - 5]; };template<typename T>struct S2 { S1<sizeof(T)> s1; };template<typename T>voidfoo(Tx) { S2<T> s2; }void test() { foo(42); } Quickoffice Proprietary and Confidential - Not for Disclosure 22
  23. 23. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:1:38:error:arr declared as an array with a negative sizetemplate <int N>struct S1 { intarr[N - 5]; };^~~~~test.cpp:2:49: note: in instantiation of template class S1<4> requested heretemplate <typename T>struct S2 { S1<sizeof(T)> s1; };^test.cpp:3:45: note: in instantiation of template class S2<int> requested heretemplate <typename T> void foo(Tx) { S2<T> s2; }^test.cpp:4:15: note: in instantiation of function template specialization foo<int> requested herevoid test() { foo(42); }^1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 23
  24. 24. Diagnostics#define M1(x, y, z) y();#define M2(x, y, z) M1(x, y, z)void test() { M2(a, b, c);} Quickoffice Proprietary and Confidential - Not for Disclosure 24
  25. 25. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:4:11: error: use of undeclared identifier b’ M2(a, b, c);^test.cpp:2:27: note: expanded from macro M2#define M2(x, y, z) M1(x, y, z)^test.cpp:1:21: note: expanded from macro M1#define M1(x, y, z) y();^1 error generated.$ g++ -fsyntax-only test.cpptest.cpp: In function ‘void test()’:test.cpp:4: error: ‘b’ was not declared in this scope Quickoffice Proprietary and Confidential - Not for Disclosure 25
  26. 26. DiagnosticsstructBaseType {};structDerivedType : publicBaseType {staticintbase_type;DerivedType() : basetype() {}}; Quickoffice Proprietary and Confidential - Not for Disclosure 26
  27. 27. Diagnostics% clang++ -std=c++11 -fsyntax-only typo1.cpptypo1.cpp:4:19: error:initializer basetype does not name a non-static data member or base class; did you mean the base class BaseType’?DerivedType() : basetype() {}^~~~~~~~BaseTypetypo1.cpp:2:22: note: base class BaseType specified herestructDerivedType : public BaseType {^~~~~~~~~~~~~~~1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 27
  28. 28. Diagnostics#include <sys/stat.h>intfoo(intx, struct stat* P){return P->st_blocksize * 2;} Quickoffice Proprietary and Confidential - Not for Disclosure 28
  29. 29. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:3:13:error:no member named st_blocksize in stat; did you mean st_blksize? return P->st_blocksize*2; ^~~~~~~~~~~~st_blksize/usr/include/sys/stat.h:225:13: note: st_blksize declared herestruct stat __DARWIN_STRUCT_STAT64; ^/usr/include/sys/stat.h:212:12: note: expanded from macro __DARWIN_STRUCT_STAT64blksize_tst_blksize; /*... */ ^1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 29
  30. 30. Diagnosticstemplate<class T, class U>struct S {};template<typename... Ts>voidf(Ts...);template<typename... Ts>struct X {template<typename... Us>voidg() {f(S<Ts, Us>()...); }};voidtest(X<int, float>x){x.g<int, float, double>();} Quickoffice Proprietary and Confidential - Not for Disclosure 30
  31. 31. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:8:22: error: pack expansion contains parameter packs Ts and Us that have different lengths (2 vs. 3)f(S<Ts, Us>()...); ~~ ~~ ^test.cpp:14:7: note: in instantiation of function template specialization X<int, float>::g<int, float, double> requested herex.g<int, float, double>(); ^1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 31
  32. 32. Diagnostics#include <memory.h>struct S { int a, b, c; float vec[16]; };voidtest(S *s){// ...memset(s, 0, sizeof(s));// ...} Quickoffice Proprietary and Confidential - Not for Disclosure 32
  33. 33. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:5:25: warning: argument to sizeof in memset call is the same expression as the destination; did you mean to dereference it? [- Wsizeof-pointer-memaccess]memset(s, 0, sizeof(s)); ~ ^1 warning generated. Quickoffice Proprietary and Confidential - Not for Disclosure 33
  34. 34. Diagnosticsintfoo() {int arr[42];// ...return arr[42];} Quickoffice Proprietary and Confidential - Not for Disclosure 34
  35. 35. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:4:12: warning: array index of 42 indexes past the end of an array (that contains 42 elements) [-Warray-bounds] return arr[42]; ^ ~~test.cpp:2:5: note: array arr declared hereint arr[42]; ^1 warning generated. Quickoffice Proprietary and Confidential - Not for Disclosure 35
  36. 36. DiagnosticsstaticconstlonglongDiskCacheSize = 8<<30; // 8 Gigs Quickoffice Proprietary and Confidential - Not for Disclosure 36
  37. 37. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:2:23: warning: signed shift result (0x200000000) requires 35 bits to represent, but int only has 32 bits [-Wshift-overflow]DiskCacheSize = 8 << 30; // 8 Gigs ~ ^ ~~1 warning generated. Quickoffice Proprietary and Confidential - Not for Disclosure 37
  38. 38. Diagnosticsvoidtest(boolb, doublex, doubley){if (b || x<y&&x>0) {// ... }} Quickoffice Proprietary and Confidential - Not for Disclosure 38
  39. 39. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:2:19: warning: && within || [-Wlogical-op-parentheses] if (b || x<y&&x> 0) { ~~ ~~~~~~^~~~~~~~test.cpp:2:19: note: place parentheses around the && expression to silence this warning if (b || x<y&&x> 0) { ^ ( )1 warning generated. Quickoffice Proprietary and Confidential - Not for Disclosure 39
  40. 40. Diagnosticsconstexprintarr_size = 42;constexprint N = 44;voidf(int);int test(){intarr[arr_size];// ...f(arr[N]);// ...if (N <arr_size) returnarr[N];return0;} Quickoffice Proprietary and Confidential - Not for Disclosure 40
  41. 41. Diagnostics$ clang++ -std=c++11 -fsyntax-only test.cpptest.cpp:7:7: warning: array index of 44 indexes past the end of an array (that contains 42 elements) [-Warray-bounds]f(arr[N]); ^ ~test.cpp:5:5:note: array arr declared hereintarr[arr_size]; ^1 warning generated. Quickoffice Proprietary and Confidential - Not for Disclosure 41
  42. 42. Static Analysisstructmutex {void lock();void unlock();};mutexm;intx;boolfoo();bool bar();void test() {m.lock();while (foo()) {m.unlock();if (bar()) {if (x<42&&foo()){continue; } }m.lock(); }} Quickoffice Proprietary and Confidential - Not for Disclosure 42
  43. 43. Static Analysisstruct [[ts::lockable]] mutex {void lock() [[ts::exclusive_lock_function]];void unlock() [[ts::unlock_function]];};mutexm;intx [[ts::guarded_by(m)]];boolfoo() [[ts::exclusive_locks_required(m)]];bool bar();void test() {m.lock();while (foo()) {m.unlock();if (bar()) {if (x<42&&foo()){continue; } }m.lock(); }} Quickoffice Proprietary and Confidential - Not for Disclosure 43
  44. 44. Static Analysisstruct __attribute__((lockable)) mutex {void lock() __attribute__((exclusive_lock_function));void unlock() __attribute__((unlock_function));};mutexm;intx__attribute__((guarded_by(m)));boolfoo() __attribute__((exclusive_locks_required(m)));bool bar();void test() {m.lock();while (foo()) {m.unlock();if (bar()) {if (x<42&&foo()){continue; } }m.lock(); }} Quickoffice Proprietary and Confidential - Not for Disclosure 44
  45. 45. Diagnostics$ clang++ -std=c++11 -fsyntax-only -Wthread-safety test.cpptest.cpp:11:5: warning: expecting mutex m to be locked at start of each loop [-Wthread-safety]m.lock(); ^test.cpp:11:5: warning:mutex m is still locked at the end of function [- Wthread-safety]test.cpp:15:17: warning: reading variable x requires locking m [- Wthread-safety] if (x< 42 &&foo()) { ^test.cpp:19:9: warning:mutex m is still locked at the end of its scope [- Wthread-safety]m.lock(); ^4 warnings generated. Quickoffice Proprietary and Confidential - Not for Disclosure 45
  46. 46. Current Status• Platforms: + Linux + Mac OS X – Windows• C++11 features: + Almost all features implemented in v2.9+/SVN – Missing features: • Generalized attributes • Inheriting constructors • Concurrency Quickoffice Proprietary and Confidential - Not for Disclosure 46
  47. 47. Brief architecture overview• GCC compatible• Library based architecture – libsupport, libsystem, libbasic, libast, liblex, libparse, libsema, libcodegen, librewrite, libanalysis, libindex• One kind of as AST for C++/C and Objective-C• Visitor interface ASTConsumer for Front-end actions Quickoffice Proprietary and Confidential - Not for Disclosure 47
  48. 48. Sample ASTConsumerclassPrintFunctionsConsumer : publicASTConsumer{public:virtualvoidHandleTopLevelDecl(DeclGroupRef DG) {for (DeclGroupRef::iterator it = DG.begin(); it != DG.end(); ++it) {constDecl* D = *it;if (constNamedDecl* ND = dyn_cast<NamedDecl>(D))llvm::errs() << ” topleveldecl : ” ”<< ND->getNameAsString()<< ” ” n ”; } }}; Quickoffice Proprietary and Confidential - Not for Disclosure 48
  49. 49. Thirdparty toolshttp://code.google.com/p/include-what-you-use/"Include what you use" means this: for every symbol (type,function variable, or macro) that you use in foo.cc, either foo.ccor foo.h should #include a .h file that exports the declaration ofthat symbol. The include-what-you-use tool is a program thatcan be built with the clang libraries in order to analyze#includes of source files to find include-what-you-useviolations, and suggest fixes for them. Quickoffice Proprietary and Confidential - Not for Disclosure 49

×