SlideShare a Scribd company logo
Going Native Highlights
Introduction to Variadic Templates.
          Clang overview.
Variadic Templates

• Fundamentals
• Usage
• Samples




             Quickoffice Proprietary and Confidential - Not for Disclosure   2
Fundamentals

Class declaration:


template<typename... Ts>
class A
{
};


Function declaration:


template<typename... Ts>
voidfoo(const Ts&... vs)
{
}
                        Quickoffice Proprietary and Confidential - Not for Disclosure   3
What is Ts and vs?

• Ts is an alias for a list of types
• vs is an alias for a list of values


typedef Ts MyList; // error!
Ts var;// error!
auto copy = vs;// error!




                     Quickoffice Proprietary and Confidential - Not for Disclosure   4
Parameters Packs Usage

• Get pack size


size_t items = sizeof...(Ts); // or vs


• Expand back


template<typename... Ts>
voidfoo(const Ts&... Vs) {
    goo(1, std::forward<Ts>(vs)..., 42);
}




                      Quickoffice Proprietary and Confidential - Not for Disclosure   5
Expansion rules



Usage                           Expansion result
Ts...                           T1, … , Tn
Ts&...                          T1&, … , Tn&
A<Ts, B>::foo...                A<T1, B>::foo , … , A<Tn, B>::foo
A<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
Where to use?

• Initializer lists
int a[] = { vs... };


• Base class specifier
template<typename... Ts>
struct A : B<Ts>...
{
};


• Class members initializer lists
template<typename... Us>
A(Us... vs) : B<Ts>(vs)... {}


                       Quickoffice Proprietary and Confidential - Not for Disclosure   7
Where to use?

• Template arguments lists
std::map<Ts...>foo;


• Exception specifications


• Capture lists
template<class... Ts>
voidfoo(Ts... vs) {
autolamda = [&vs...] { returngoo(vs...); }
lamda();
}



                      Quickoffice Proprietary and Confidential - Not for Disclosure   8
Multiple expansions


template<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
Where is used?


•   std::make_shared
template<class T, class... Ts>
shared_ptr<T>make_shared(Ts&&... vs);


•   std::vector::emplace_back
template<class... Args>
voidemplace_back(Args&&... args);




                   Quickoffice Proprietary and Confidential - Not for Disclosure   10
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
Typesafeprintf

• Adaptation routines
template<class T>
Typenameenable_if<is_integral<T>::value, long>::type
normalizeArg(Targ) { returnarg; }

template<class T>
typenameenable_if<is_floating_point<T>::value, double>::type
normalizeArg(Targ) { returnarg; }

template<class T>
typenameenable_if<is_pointer<T>::value, T>::type
normalizeArg(Targ) { returnarg; }

constchar* normalizeArg(const string&arg)
{ returnarg.c_str(); }

                         Quickoffice Proprietary and Confidential - Not for Disclosure   12
Typesafeprintf



// Not really safe yet
template<typename... Ts>
intsafe_printf(constchar* format, const Ts&... ts)
{
returnprintf(format, normalizeArg(ts)...);
}




                     Quickoffice Proprietary and Confidential - Not for Disclosure   13
Typesafeprintf

• Implement verification routine for argument-less call


voidcheck_printf(constchar * f)
{
for (; *f; ++f)
{
if (*f != ’%’ || *++f == ’%’) continue;
throwExc("Bad format");
    }
}




                      Quickoffice Proprietary and Confidential - Not for Disclosure   14
Typesafeprintf

template<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
Typesafeprintf

• Final step

template<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
Clang
•   Motivation
•   Diagnostics
•   Static analysis
•   Dynamic analysis
•   Current state
•   Tool sample




                 Quickoffice Proprietary and Confidential - Not for Disclosure   17
Why?

• Performance
• Diagnostics
• Tools




                Quickoffice Proprietary and Confidential - Not for Disclosure   18
Why?

intw = 0;
for (inti = 0; i<3; i++)
w += w * 2;



$ gcc -fsyntax-only test.c
test.c:2: error: expected identifier or ‘(’ before ‘for’
test.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘<’ token
test.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘++’
   token




                       Quickoffice Proprietary and Confidential - Not for Disclosure   19
Why?

“... is there a reason for not making the
 [GCC] front ends dynamic libraries
which could be linked by any program
that 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
Why?

#define FOO 0
intfoo() {
intx;
// ...
x = x + FOO;
// ...
returnx;
}

#define FOO 0
intfoo() {
intx;
// ...
x = x;
// ...
returnx;
}
                Quickoffice Proprietary and Confidential - Not for Disclosure   21
Diagnostics



template<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
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.cpp:1:38:error:'arr' declared as an array with a negative size
template <int N>struct S1 { intarr[N - 5]; };
^~~~~
test.cpp:2:49: note: in instantiation of template class 'S1<4>' requested here
template <typename T>struct S2 { S1<sizeof(T)> s1; };
^
test.cpp:3:45: note: in instantiation of template class 'S2<int>' requested here
template <typename T> void foo(Tx) { S2<T> s2; }
^
test.cpp:4:15: note: in instantiation of function template specialization 'foo<int>'
    requested here
void test() { foo(42); }
^
1 error generated.




                         Quickoffice Proprietary and Confidential - Not for Disclosure   23
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
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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.cpp
test.cpp: In function ‘void test()’:
test.cpp:4: error: ‘b’ was not declared in this scope




                         Quickoffice Proprietary and Confidential - Not for Disclosure   25
Diagnostics



structBaseType {};
structDerivedType : publicBaseType {
staticintbase_type;
DerivedType() : basetype() {}
};




                  Quickoffice Proprietary and Confidential - Not for Disclosure   26
Diagnostics

% clang++ -std=c++11 -fsyntax-only typo1.cpp
typo1.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() {}
^~~~~~~~
BaseType
typo1.cpp:2:22: note: base class 'BaseType' specified here
structDerivedType : public BaseType {
^~~~~~~~~~~~~~~

1 error generated.




                     Quickoffice Proprietary and Confidential - Not for Disclosure   27
Diagnostics



#include <sys/stat.h>
intfoo(intx, struct stat* P)
{
return P->st_blocksize * 2;
}




                    Quickoffice Proprietary and Confidential - Not for Disclosure   28
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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 here
struct stat __DARWIN_STRUCT_STAT64;
         ^
/usr/include/sys/stat.h:212:12: note: expanded from macro
    '__DARWIN_STRUCT_STAT64'
blksize_tst_blksize; /*... */ 
^
1 error generated.




                   Quickoffice Proprietary and Confidential - Not for Disclosure   29
Diagnostics



template<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
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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 here
x.g<int, float, double>();
     ^
1 error generated.




                      Quickoffice Proprietary and Confidential - Not for Disclosure   31
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
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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
Diagnostics



intfoo() {
int arr[42];
// ...
return arr[42];
}




                  Quickoffice Proprietary and Confidential - Not for Disclosure   34
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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 here
int arr[42];
   ^
1 warning generated.




                    Quickoffice Proprietary and Confidential - Not for Disclosure   35
Diagnostics



staticconstlonglong
DiskCacheSize = 8<<30; // 8 Gigs




                   Quickoffice Proprietary and Confidential - Not for Disclosure   36
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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
Diagnostics



voidtest(boolb, doublex, doubley)
{
if (b || x<y&&x>0)
    {
// ...
    }
}




                   Quickoffice Proprietary and Confidential - Not for Disclosure   38
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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
Diagnostics



constexprintarr_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
Diagnostics

$ clang++ -std=c++11 -fsyntax-only test.cpp
test.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 here
intarr[arr_size];
   ^
1 warning generated.




                    Quickoffice Proprietary and Confidential - Not for Disclosure   41
Static Analysis

structmutex {
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
Static Analysis

struct [[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
Static Analysis

struct __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
Diagnostics

$ clang++ -std=c++11 -fsyntax-only -Wthread-safety test.cpp
test.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
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
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
Sample ASTConsumer


classPrintFunctionsConsumer : 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
Thirdparty tools

http://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.cc
or foo.h should #include a .h file that exports the declaration of
that symbol. The include-what-you-use tool is a program that
can be built with the clang libraries in order to analyze
#includes of source files to find include-what-you-use
violations, and suggest fixes for them.




                 Quickoffice Proprietary and Confidential - Not for Disclosure   49

More Related Content

KEY
Inside PyMongo - MongoNYC
PDF
Ds lab handouts
PPTX
C# 6.0 Preview
PDF
C programs
PDF
C program
PDF
RAII and ScopeGuard
PDF
Pyconie 2012
PPT
Paradigmas de Linguagens de Programacao - Aula #4
Inside PyMongo - MongoNYC
Ds lab handouts
C# 6.0 Preview
C programs
C program
RAII and ScopeGuard
Pyconie 2012
Paradigmas de Linguagens de Programacao - Aula #4

What's hot (20)

PPTX
Templates
DOCX
Data Structure Project File
PDF
[C++ Korea] Effective Modern C++ Study, Item 11 - 13
PDF
Data struture lab
PDF
李建忠、侯捷设计模式讲义
PPT
Handling Exceptions In C &amp; C++ [Part B] Ver 2
PDF
Coding Guidelines - Crafting Clean Code
PDF
TDD in C - Recently Used List Kata
DOCX
Data structure new lab manual
PPTX
12. Java Exceptions and error handling
PPTX
Best Bugs from Games: Fellow Programmers' Mistakes
PPTX
SoCal Code Camp 2015: An introduction to Java 8
PPT
Introduzione al TDD
PDF
Writing beautiful code with Java 8
DOCX
Simulado java se 7 programmer
PDF
7 functions
PDF
C++11 smart pointer
PPTX
Applying Compiler Techniques to Iterate At Blazing Speed
DOCX
Algoritmos sujei
Templates
Data Structure Project File
[C++ Korea] Effective Modern C++ Study, Item 11 - 13
Data struture lab
李建忠、侯捷设计模式讲义
Handling Exceptions In C &amp; C++ [Part B] Ver 2
Coding Guidelines - Crafting Clean Code
TDD in C - Recently Used List Kata
Data structure new lab manual
12. Java Exceptions and error handling
Best Bugs from Games: Fellow Programmers' Mistakes
SoCal Code Camp 2015: An introduction to Java 8
Introduzione al TDD
Writing beautiful code with Java 8
Simulado java se 7 programmer
7 functions
C++11 smart pointer
Applying Compiler Techniques to Iterate At Blazing Speed
Algoritmos sujei
Ad

Viewers also liked (20)

PDF
PPTX
Diapositiva 1
PPT
DOCX
Getting Started
DOCX
Quickword How To
DOC
evernote Quickword How To
PPTX
New_PPTX_FileSavedOnEvernote_19
PDF
File Manager How To
DOCX
Quickword How To
DOC
Quickword How To
PPT
mac_pp_2011
PPT
what you cannot recover
PPT
PPTX_FileSavedAsOnGoogleDocs_31
POT
mac_pp_2011
DOCX
PDF
QAducation Cursusinformatie2012v2
DOCX
Long lists
Diapositiva 1
Getting Started
Quickword How To
evernote Quickword How To
New_PPTX_FileSavedOnEvernote_19
File Manager How To
Quickword How To
Quickword How To
mac_pp_2011
what you cannot recover
PPTX_FileSavedAsOnGoogleDocs_31
mac_pp_2011
QAducation Cursusinformatie2012v2
Long lists
Ad

Similar to report (20)

PDF
Debugging and Profiling C++ Template Metaprograms
PDF
App secforum2014 andrivet-cplusplus11-metaprogramming_applied_to_software_obf...
PPTX
Fundamentals of computer programming by Dr. A. Charan Kumari
PPTX
The operation principles of PVS-Studio static code analyzer
PPTX
Static code analysis: what? how? why?
PPTX
Object Oriented Design and Programming Unit-04
PDF
Découvrir dtrace en ligne de commande.
PPTX
C++ idioms.pptx
PPTX
C++ Intro C++ Intro C++ Intro C++ Intro C++ Intro
PPTX
Summary of C++17 features
PPTX
TEMPLATES IN JAVA
PDF
Getting Started Cpp
PDF
Lec-1c.pdf
PPT
Paradigmas de Linguagens de Programacao - Aula #5
PPTX
C Programming Homework Help
PPT
02basics
PPTX
CS 1106 - UNIT -3 notes for students to learn
PPTX
ppl unit 3.pptx ppl unit 3 usefull can understood
PDF
Headache from using mathematical software
PDF
Picking Mushrooms after Cppcheck
Debugging and Profiling C++ Template Metaprograms
App secforum2014 andrivet-cplusplus11-metaprogramming_applied_to_software_obf...
Fundamentals of computer programming by Dr. A. Charan Kumari
The operation principles of PVS-Studio static code analyzer
Static code analysis: what? how? why?
Object Oriented Design and Programming Unit-04
Découvrir dtrace en ligne de commande.
C++ idioms.pptx
C++ Intro C++ Intro C++ Intro C++ Intro C++ Intro
Summary of C++17 features
TEMPLATES IN JAVA
Getting Started Cpp
Lec-1c.pdf
Paradigmas de Linguagens de Programacao - Aula #5
C Programming Homework Help
02basics
CS 1106 - UNIT -3 notes for students to learn
ppl unit 3.pptx ppl unit 3 usefull can understood
Headache from using mathematical software
Picking Mushrooms after Cppcheck

More from Quickoffice Test (20)

DOC
DOCX
PPT
PPTX
DOC
PPTX
egnyte rename
DOCX
Quickword How To
DOCX
Docx test
PPT
Presentation
DOCX
PPTX
PPT
!!!zzz To
DOC
!!!zzz itttest1
DOCX
Ciao_questa_è_una_prova_da_Quickoffice
PPT
1 georgia
egnyte rename
Quickword How To
Docx test
Presentation
!!!zzz To
!!!zzz itttest1
Ciao_questa_è_una_prova_da_Quickoffice
1 georgia

report

  • 1. Going Native Highlights Introduction to Variadic Templates. Clang overview.
  • 2. Variadic Templates • Fundamentals • Usage • Samples Quickoffice Proprietary and Confidential - Not for Disclosure 2
  • 3. Fundamentals Class declaration: template<typename... Ts> class A { }; Function declaration: template<typename... Ts> voidfoo(const Ts&... vs) { } Quickoffice Proprietary and Confidential - Not for Disclosure 3
  • 4. What is Ts and vs? • Ts is an alias for a list of types • vs is an alias for a list of values typedef Ts MyList; // error! Ts var;// error! auto copy = vs;// error! Quickoffice Proprietary and Confidential - Not for Disclosure 4
  • 5. Parameters Packs Usage • Get pack size size_t items = sizeof...(Ts); // or vs • Expand back template<typename... Ts> voidfoo(const Ts&... Vs) { goo(1, std::forward<Ts>(vs)..., 42); } Quickoffice Proprietary and Confidential - Not for Disclosure 5
  • 6. Expansion rules Usage Expansion result Ts... T1, … , Tn Ts&... T1&, … , Tn& A<Ts, B>::foo... A<T1, B>::foo , … , A<Tn, B>::foo A<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. Where to use? • Initializer lists int a[] = { vs... }; • Base class specifier template<typename... Ts> struct A : B<Ts>... { }; • Class members initializer lists template<typename... Us> A(Us... vs) : B<Ts>(vs)... {} Quickoffice Proprietary and Confidential - Not for Disclosure 7
  • 8. Where to use? • Template arguments lists std::map<Ts...>foo; • Exception specifications • Capture lists template<class... Ts> voidfoo(Ts... vs) { autolamda = [&vs...] { returngoo(vs...); } lamda(); } Quickoffice Proprietary and Confidential - Not for Disclosure 8
  • 9. Multiple expansions template<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. Where is used? • std::make_shared template<class T, class... Ts> shared_ptr<T>make_shared(Ts&&... vs); • std::vector::emplace_back template<class... Args> voidemplace_back(Args&&... args); Quickoffice Proprietary and Confidential - Not for Disclosure 10
  • 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. Typesafeprintf • Adaptation routines template<class T> Typenameenable_if<is_integral<T>::value, long>::type normalizeArg(Targ) { returnarg; } template<class T> typenameenable_if<is_floating_point<T>::value, double>::type normalizeArg(Targ) { returnarg; } template<class T> typenameenable_if<is_pointer<T>::value, T>::type normalizeArg(Targ) { returnarg; } constchar* normalizeArg(const string&arg) { returnarg.c_str(); } Quickoffice Proprietary and Confidential - Not for Disclosure 12
  • 13. Typesafeprintf // Not really safe yet template<typename... Ts> intsafe_printf(constchar* format, const Ts&... ts) { returnprintf(format, normalizeArg(ts)...); } Quickoffice Proprietary and Confidential - Not for Disclosure 13
  • 14. Typesafeprintf • Implement verification routine for argument-less call voidcheck_printf(constchar * f) { for (; *f; ++f) { if (*f != ’%’ || *++f == ’%’) continue; throwExc("Bad format"); } } Quickoffice Proprietary and Confidential - Not for Disclosure 14
  • 15. Typesafeprintf template<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. Typesafeprintf • Final step template<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. Clang • Motivation • Diagnostics • Static analysis • Dynamic analysis • Current state • Tool sample Quickoffice Proprietary and Confidential - Not for Disclosure 17
  • 18. Why? • Performance • Diagnostics • Tools Quickoffice Proprietary and Confidential - Not for Disclosure 18
  • 19. Why? intw = 0; for (inti = 0; i<3; i++) w += w * 2; $ gcc -fsyntax-only test.c test.c:2: error: expected identifier or ‘(’ before ‘for’ test.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘<’ token test.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘++’ token Quickoffice Proprietary and Confidential - Not for Disclosure 19
  • 20. Why? “... is there a reason for not making the [GCC] front ends dynamic libraries which could be linked by any program that 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. Why? #define FOO 0 intfoo() { intx; // ... x = x + FOO; // ... returnx; } #define FOO 0 intfoo() { intx; // ... x = x; // ... returnx; } Quickoffice Proprietary and Confidential - Not for Disclosure 21
  • 22. Diagnostics template<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. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.cpp:1:38:error:'arr' declared as an array with a negative size template <int N>struct S1 { intarr[N - 5]; }; ^~~~~ test.cpp:2:49: note: in instantiation of template class 'S1<4>' requested here template <typename T>struct S2 { S1<sizeof(T)> s1; }; ^ test.cpp:3:45: note: in instantiation of template class 'S2<int>' requested here template <typename T> void foo(Tx) { S2<T> s2; } ^ test.cpp:4:15: note: in instantiation of function template specialization 'foo<int>' requested here void test() { foo(42); } ^ 1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 23
  • 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. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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.cpp test.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. Diagnostics structBaseType {}; structDerivedType : publicBaseType { staticintbase_type; DerivedType() : basetype() {} }; Quickoffice Proprietary and Confidential - Not for Disclosure 26
  • 27. Diagnostics % clang++ -std=c++11 -fsyntax-only typo1.cpp typo1.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() {} ^~~~~~~~ BaseType typo1.cpp:2:22: note: base class 'BaseType' specified here structDerivedType : public BaseType { ^~~~~~~~~~~~~~~ 1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 27
  • 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. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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 here struct stat __DARWIN_STRUCT_STAT64; ^ /usr/include/sys/stat.h:212:12: note: expanded from macro '__DARWIN_STRUCT_STAT64' blksize_tst_blksize; /*... */ ^ 1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 29
  • 30. Diagnostics template<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. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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 here x.g<int, float, double>(); ^ 1 error generated. Quickoffice Proprietary and Confidential - Not for Disclosure 31
  • 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. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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. Diagnostics intfoo() { int arr[42]; // ... return arr[42]; } Quickoffice Proprietary and Confidential - Not for Disclosure 34
  • 35. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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 here int arr[42]; ^ 1 warning generated. Quickoffice Proprietary and Confidential - Not for Disclosure 35
  • 36. Diagnostics staticconstlonglong DiskCacheSize = 8<<30; // 8 Gigs Quickoffice Proprietary and Confidential - Not for Disclosure 36
  • 37. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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. Diagnostics voidtest(boolb, doublex, doubley) { if (b || x<y&&x>0) { // ... } } Quickoffice Proprietary and Confidential - Not for Disclosure 38
  • 39. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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. Diagnostics constexprintarr_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. Diagnostics $ clang++ -std=c++11 -fsyntax-only test.cpp test.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 here intarr[arr_size]; ^ 1 warning generated. Quickoffice Proprietary and Confidential - Not for Disclosure 41
  • 42. Static Analysis structmutex { 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. Static Analysis struct [[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. Static Analysis struct __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. Diagnostics $ clang++ -std=c++11 -fsyntax-only -Wthread-safety test.cpp test.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. 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. 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. Sample ASTConsumer classPrintFunctionsConsumer : 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. Thirdparty tools http://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.cc or foo.h should #include a .h file that exports the declaration of that symbol. The include-what-you-use tool is a program that can be built with the clang libraries in order to analyze #includes of source files to find include-what-you-use violations, and suggest fixes for them. Quickoffice Proprietary and Confidential - Not for Disclosure 49