Tools • iOS, OS X • 52:09
Apple continues to invest in the LLVM compiler technology, and that investment has been paying off in spades. Get details on the latest improvements to the compiler and static analyzer. See how to get the most out of these tools with settings in Xcode.
Speakers: Evan Cheng, Bob Wilson, Anna Zaks
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
[Applause]
Thank you. [applause] Good afternoon! Welcome to "What's New in the LLVM Compiler?" My name is Evan. Let's-- shall we start? What's our mission? We want to provide the Best-in-Class tools for you, for the developers, the lifelines of our platforms. We want to make sure you have the best tools to build your awesome apps.
We want to support the best-- the latest hardware, be Macs, iOS devices. We want to make sure we can build your codes so they run as fast as they can on the unit-- latest iPhone, the iPads and the Macs. I want to make sure the performance is great.
We're not satisfied if we cannot squeeze every ounce of performance in audio applications. And we want to make sure you have the great productivity. We want our tools to run fast and we want to provide you with the best diagnoses. We want to give you as much information we can to make your job easy.
So let's take a look at what have we done in different areas. First, let's talk about the support for the latest hardware, armv7s architecture. This is something you may have seen. This is not new in Xcode 5 but there's something new happened during the last year. The iPhone 5-- for the iPhone 5, we have the Apple A6 chip, that's something Apple built and very proud of it. We worked very closely with our team to make sure the compiler generate the best code words. If you care about performance on your app on the latest iPhone and the latest iPads, you want to build your application for this architecture.
This is simple because this is already a part of the standard architecture for iOS apps so we encourage you, just go with it, don't pick and choose, just use the standard architecture and you'd get the best performance for your apps. Next, let's talk about Intel AVX. AVX stands for Advanced Vector Extension. Anything with the word "Advanced" sounds great there. It must be good, you should use it.
So Intel AVX is not new. It's been around for a couple of years, but this year you have-- you have heard, we have just announced Haswell-Based Macs, they have Intel AVX2, so AVX was all about getting the best performance with your loop with a lot of parallels in, a lot of floating point computation code. AVX2 takes a little step further and bring the same kind of power to the-- your integer code. It had a few more other kind of instructions to make it easy to vectorize your code so you definitely want to take advantage of AVX2.
So using AVX2 is easy but it's not quite, kind of, work-free. You do want to make sure your app does runtime checks to make the hardware you're running the code support AVX2. So you may want to partition your code to have a special version that only run on AVX2 and compile with the -mavx2 instruction, I mean, -2avx2, -mavx2 option.
If you have any questions about this, feel free to come by to our labs. We'll be happy to talk to you about it and also we'll be talking a lot more about AVX2 and many other things we talked about today in tomorrow's session, that's-- we're we going to focus on how you can using the LLVM technology to fully optimize your code. So if you use AVX2 in Xcode 5, it's pretty simple, go to the Build Configuration and just enable Additional Vector Extension, choose AVX2.
This is going to be important to get your code to performance-- to the best you can on the Haswell-Based Macs. Next, let's focus on performance. We've done a lot of work in this area. We have many new features, a lot of work we're very, very proud of. We're so proud of, in fact, we've made a video, I'd like to show you today. I'm just kidding. [Laughter]
[ Laughter & Applause ]
They will be editing the video for a long time before I can show you anything. But let's take a quick look what we have done for you. So the compiler has definitely improved a lot. The performance has gotten better every year. This past year as you've seen, just a quick chart-- a few examples, we're getting quite a bit of performance of your code. So if you're just building your application with the new LLVM compiler in Xcode 5, you're going to get some significant improvement for your code. So it ranges differently depends on what kind of code you're writing.
If your iOS app, you're going to see the same kind of performance but a bit more. We've been really, really focused on this and we're working really closely with our team to bring you the best compiler technology in this area. So here you can see across the board teams of 20, 30 percent performance gains just by switching to the latest Xcode 5 and using-- latest Apple LLVM compiler.
One other thing I want to talk to you very briefly about, Strict Aliasing, this is technology we introduced in Xcode and Apple LLVM compiler about a year or so ago. The only difference here is, you know, during the past year, we have enabled by default in 4.-- Xcode 4.6.
I just want to bring this to your attention, in case you have some any kind of legacy code that's still building and shipping with the older Xcode, you might be-- want to be aware of this change. So I'm not going to go into a lot of details but strict aliasing is basically using the type of informations to do more advanced than pointer analysis. The reason we turn on strict aliasing is simple, its performance. It's a-- few percentage is here and there, but in some cases, we see significant wins such as 20 percent improvement for some simulation benchmarks.
So again, just want to remind you, if you are legacy code, they might be using some illegal scenes such as typecasting from one type to another that's not compatible from floating point to integer or vice-versa. If you want it, you have code that does this, please switch to a well understood [inaudible] such as-- unions to do the cut-- type conversion and you'd be home free.
Chances are, since we've been-- you've been shipping your application with Xcode 4.6, this is working perfectly for you, there's absolutely nothing for you to worry about. One other thing I wanted to bring to your attention is Link-time Optimization. Again, this is not a new feature. What's new is we've put so much effort into Link-time Optimization during last year and we feel so great about it. We have enabled it using it to build some key Apple technologies in the Mac and iOS release.
So some examples such as Apple LLVM compiler itself is built with LTO. This can have the benefit of compiling your code up to 6-- 6 percent faster. The iOS Kernel, that's important application, can do some of the-- IO-- performance can be up to 20-- 20 percent faster and in addition to performance, sometimes you have [inaudible] benefit such as iOS iMovie app that got 25 percent smaller just by building with LTO. So we think LTO is great. You definitely want to try it out.
But in case you have a really massive application, this could have impact on the build time because LTO is about bringing everything about your application into last stage and do the all the optimization, compilation at that time. So if you find you were building with LTO and that's taking too much time and maybe and you're running out of memory, you consider dropping the debugging full level to a Line table only, that can have a significant improvement to the real time.
Something new in Xcode 5, here's the Auto Vectorizer. We talked about this in "What's New in Xcode?" this morning. This is something that we built from the grown up during the past year. This is already showing amazing results. This is certainly some really computation intensive code and can have 2 to 5 to 8 times the benefit for you-- for your computation intensive loop.
And this works great for both iOS and OS X applications so you can have portable code that you write simple code that works perfectly for all the-- for both platforms. So previously, if you are familiar with ARM NEON intrinsics, you may be using-- intrinsics to kind of get the best performance on your loop. And now we're saying, all you have to do is you just write simple scalar code and let the compiler do the rest for you. It's that simple, it's that powerful, you definitely want to try it. [applause] Thank you.
[Applause] So the auto-vectorizer, again, is new in Xcode 5, go to the Build Setting and choose vectorize loops, and let us know, we're really proud of this technology and we think we-- you'll get a lot of benefit from it. Again, this is something we're going to go into a lot more details in tomorrow's session. What we're going to talk about, how to optimize your code using the LLVM.
The last thing, if you've been playing with the new Xcode 5, you may-- may have noticed a new optimization level, -Ofast. What is this? Well, think about it as if it's a turbo button for your application. You press it and you go-- your code goes fast. So through -Ofast, it turn out all the -03 optimizations, squeezing as much performance out of your code as possible. It turn on the vectorization, it turn on the -ffast-math optimization. For floating point code, that can have a significant performance benefits.
So what do you want to do is for your release build, choose -Ofast, not with Debug Build, only the Release Build. So a quick disclaimer, there's a few things you should be aware about -Ofast, particularly, because you used -ffast-math. You can do aggressive optimization such as re-association of your floating-point expressions and many other things can have subtle impact precisions of your code. So if your application has to be incongruous precise as using-- floating point, test carefully. We believe for the majority of the code, this will just work fine but please test and let us know how it works.
And one other thing is, this doesn't turn on LTO for you automatically. We want to control that separately becomes the compile to impact. So that's all I want to talk about-- about performance. Next up, I would like to ask, Bob Wilson to come up, about all the work we have done to improve your productivities. Thank you.
[ Applause ]
Thanks Evan. So the Apple LLVM Compiler can help your apps to run faster. It can also improve your productivity and help you develop higher quality apps with fewer bugs. So in the rest of the session, we're going to go through a number of different ways that the compiler can help with that.
By updating the compiler and some of the other tools, we give you a more consistent experience with an easier installation and update process. We've got some new C++ features that make it easier to express the code that you want and we've improved the compiler warnings and the static analyzer to help you catch bugs before you have to go and spend a lot of time debugging your app. And finally, we've got a great new feature that makes it easier to document your code right in the comments. So let's dive into these starting with the compiler and tool updates.
So Apple has been using the gnu gcc compiler for quite a few years but a few years back, we decided we really wanted a better compiler. We wanted better performance, we wanted tighter integration in the Xcode, we wanted more helpful diagnostic messages that really explain to you when there's a problem in your code in a way that makes sense and you could easily see how to fix it.
So we began to invest in the llvm compiler and for a number of years now, we've shipped both gcc and the llvm compiler side by side, as well as the hybrid llvm-gcc to ease that transition away from gcc to the llvm compiler. And I'm really pleased to say that this year, in Xcode 5, the gnu is gone. We only have the llvm compiler.
[ Applause ]
Yeah, as I said, that makes me happy too. The good news for you is this gives you a consistent experience. And in the past, if you've been building with gcc, you'd see inconsistencies between the diagnostics reported to you in Xcode while you're editing, which are coming from LLVM and the messages, the problems you'd see at build time using gcc. And all of that mess has gone now. There's just one compiler and everything is consistent. It's also really good news because it means we can focus our efforts on adding new features in just one compiler and move forward at an even faster rate.
So I'm going to come back and talk about some of those advances in LLVM in just a minute but before I do that, I want to go over a related topic which is the command line tools. If you're not already familiar with the command line tools, this is a package that we provide separately from Xcode that is useful for building open source and other common Unix software on the Mac.
And it consists of two basic components, there's a set of tools such as the compiler that install in the /usr/bin directory and then there's the Mac OS X SDK, with headers and /usr/include, libraries and user lib, and also in System Library/Frameworks. This is what the command line tools look like on Mountain Lion.
Now if you're an Xcode developer, you've got Xcode but you just want to go and build some open source code, you may find yourself still needing to install the command line tools even though you already got Xcode. And the reason for that is that the standard Unix convention is that the compiler and the other tools live in /usr/bin and that's not where Xcode puts them.
So new in Mavericks, we have the inspiration that Xcode already has all of those same tools, it already has the OS X SDK so there's no reason to make you go and download this separate package just to get those same things. And the way this works is that the Mavericks OS comes with a set of shims installed in /usr/bin.
These shims are just really small, simple wrapper executables that know where to find Xcode and where to find the corresponding tools inside of Xcode. So if you run the compiler from /usr/bin via one of these shims, it just reinvokes the compiler from Xcode for you automatically. So the summary of this is if you have Xcode and you're on Mavericks, there's no longer any need to ever download the command line tools.
[applause] So what if you don't have Xcode? What then? Well, if you-- say you've got a brand new Mac and you try to run the compiler from /usr/bin, you'll get this message telling you, "Hey, you need some tools," and it's giving you choice. You can click on that Get Xcode button, it'll bring you to the apps store and you can install Xcode just as in the normal way. You can also choose Install which will install a standalone set of command line tools.
Let's take a closer look at what that looks like. This is about the Mavericks version of command line tools. We have the same shims in /usr/bin and the tools now install into library developer command line tools and the shims forward to that location automatically in the same way that they would forward to Xcode.
My favorite feature about this is it's hooked up to software update. On Mountain Lion, if you've got-- if a new version of command line tools was released, it's up to you to remember that you need to go and install it. With Mavericks, you'll get a notification in the apps store to tell you that an update is available and you just go in it and install it in the same way. So that update process is so much smoother now.
It's also easier to remove the tools. Say that you had installed the command line tools separately. Maybe, you were in a coffee shop or something and you-- you needed to download a compiler quickly, with a low bandwidth connection, the command line tools are much smaller, but then when you get home, you got more bandwidth, you probably want to install Xcode, now you're left with these tools, you don't need them anymore.
On Mountain Lion, it was really hard to ever remove the command line tools because they were scattered throughout your root file system. Now, they're all in one place, Library/Developer/ CommandLineTools. And if you've got Xcode, you can just blow that folder away and everything will continue working. So again, just to summarize, the command line tools make it really easy to install and update and even remove in a way that Mountain Lion didn't provide.
But before we get back to the compiler, there's-- there's one issue I want to let you know about. Notice that we've only talked about one part of the command line tools which is the tools themselves in /usr/bin. Remember, there's that SO 10 SDK? And it's moved. It's no longer installed in the /directory.
This is the problem for the compiler because the compiler knows where that SDK is installed. But if you've got, make files or scripts or anything else that refers to files in usr/include, usr/lib, or System/Library/Frameworks with hard coded paths then you're going to need to fix those things up so that they know where to find that Mac OS X SDK.
How do you know? Where is it installed? We do have something to help with that. xcrun is a tool you may be familiar with. It's been included with Xcode for a long time. Like those shims, it's just a wrapper, it knows where to find tools in Xcode and you can use it to run them.
It's now included with a command line tools and it has a new option. If you run xcrun -- show-sdk-path -- sdk and a short name like macosx, it will print out the full path to the SDK and you can use this to programmatically update make files or scripts with the full path to the SDK.
And related feature, since xcrun knows where the SDK is, you can also use this to tell the compiler where the SDK is. In the past, you'd have to use the -isys root option to the compiler and give it the full paths to the SDK you want to use and those full paths are often quite long. If you're on the command line, it's a lot to type.
Well now, you can use xcrun, give it a short name, like iPhone OS or Mac OS X and it will communicate that through to the compiler so you don't have to type the whole path. You can also set the SDKROOT environment variable and xcrun will notice and pick that up and use that to set the SDK.
So try out the new command line tools, I hope you like them, and now let's get back to the compiler, starting with C++. C++11 is a major update to the C++ language. This is something that we've been working on rolling out in Xcode for a while now. This year, in Apple LLVM version 5.0, we have complete support for everything in C++11 with the sole exception of thread local storage.
Here's a list of some of the major features we've added in the last year and I don't have time to go into all of these in any detail. So I just-- to give you a taste if I wanted to single out one of them to look at a little more closely, which is Inheriting Constructors, and let's look at this with an example.
I've got here a simple class. It's got an integer A field and a float B field and a set of constructors that let you specify the initial values for various combinations of those fields using default values for the things you didn't specify. Now I want to make a derive class Y with those same constructors.
And I just want to pass the same values along to the base class constructors. There's a lot of boiler-plate code here and it's also error prone to maintain. If you make a change in the base class, you've got to go and update all the drive classes in ways that match.
And C++11 inheriting constructors let you replace all that boiler plate which just using X::X. And all this does is tell the compiler if-- if I see a use of one of these constructors that matches the signature from the base class, just implicitly declare that, and it will invoke the constructor from the base class as you'd expect.
Notice though, I've added an int c field in the derive class. How do we initialize that? Well, there-- there's a lot of different ways you could do it and C++11 has a number of features that help with this. I want to-- since it fits nicely in this example, I wanted to talk about one way to do that.
This is not a new feature this year but it's something that's been around for a while which is non-static data member initializers. You can now set the initial value right in the class and this tells the compiler if I don't have some other values set in the constructor to use that as a default value.
Notice we can use the same thing in the base class X to set the values of fields A and B, and then remove a lot of the complexity from the constructors there. So together, inheriting constructors, a non-static data member initializers, take the simple example and make it a lot more clear and concise and easy to maintain.
While we're on the topic of C++, there's one other important piece which is the Runtime Library. We've been going through a transition from the older GNU lib standard C++ library to the new LLVM libc++. And if you want to use a lot of those features from C++11, you really need libc++ to support them. It supports the number of the language features and it also has a number of new library components that come with C++11.
One thing that is new this year is that we've made this the compiler default if you're deploying to iOS 7 or OS X Mavericks. If you want to deploy back as far as iOS 5 or OS X Lion, you can still choose to use libc++ by going to the Xcode build settings, look for C++ standard library and choose libc++.
So again, C++11 is a huge change to the language. If you're a C++ programmer, I strongly encourage you to check it out and there's a lot of great new features there that can make you more productive. Our next topic is about Compiler Warnings. So as you're writing your code and building, the compiler is-- is looking closely at that code and in the process, we can catch errors or-- and warn you about them so that you can fix them quickly without having to spend a lot of time debugging.
So there's three different categories of changes that I want to talk about related to compiler warnings. First, we have some new compiler warnings. We have a number of warnings that have been around for awhile but we've identified them as being really important and we're going to now enable them by default in new projects. And finally, there's a few warnings that are really serious, it cause serious problems and we're now going to treat them as errors by default.
So let's-- dive into this starting with the new compiler warnings. The first one is unsequenced modification. This is a warning about non-portable code. C-based languages don't define the order of some operations and I'll give you an example in just a minute, but if you have some code working with a different compiler from a different platform or-- or wherever and you move to using the LLVM compiler, it may behave differently in a way that causes a bug.
Let's look at an example. This simple function is supposed to just increment a value and return it but there's a problem. There's actually two assignments to the value X here, the equal operator does an assignment, the plus, plus, post increment operator does a separate assignment and the order between those two is not defined by the language.
Some compilers may do them in one order, some may do it in the other order. So the LLVM compiler now gives you a warning about this. It's an indication to you, you need to look at your code and figure out how to rewrite that so that the ordering is well-defined.
Let's go on to the next new warning which is about integer overflow. In some cases, the compiler can determine that an integer operation is going to overflow. This is almost certain to cause a bug at runtime so we now warn about that. For example, if we're multiplying two constants, they're big numbers, not that big, but when you multiply them the product is too big to even fit in a 32-bit integer.
So the LLVM compiler will now warn about this and tell you, this doesn't fit. The obvious solution in a case like this would be to use a larger size integer such as long longs. You can use long long constants and a long long return value and the warning goes away. So those are two new warnings. Let's talk about some of the warnings that we're now going to enable by default.
Unused functions, this is an easy one. While you're editing your project, it's not that uncommon to leave behind some pieces of code that are no longer used. And if those are in static functions either in declarations or actual definitions with the function body like I've shown here, the compiler can detect this and warn you, and this is just an opportunity for you to clean up your code, remove some of that unused craft and make it easier to maintain. We're going to now enable this by default in new projects.
Implicit Boolean conversions is another warning like that, enabled by default. This is especially helpful in C++, and let's see an example. Here, I've got a helper function that I've declared and I want to check and see if the helper is available, I'm going to call it. The compiler warns and says, "If you take the address of the function, it will always evaluate to true." So the conditional here isn't doing what we expect.
In a case like this, you probably meant to make that a weak import. And you just need to add the weak attribute on that function declaration to tell the compiler that this value, this function pointer maybe zero and without the warning goes away. So this again is a serious problem enabled by default, the warning is enabled by default.
A similar issue is with Enum conversions. Here's an example of that. I've got two Enums, a set of shapes and a set of circles and I want to-- I have a draw function that can draw that and I try to draw a blue circle but I-- I got the order wrong. It's supposed to be Draw Circle Blue, instead of Draw Blue Circle.
The implicit Enum conversion warning detects that. It would actually warn twice here, ones for each of the arguments, because they're both in the wrong order. Again, this is something that's trivial to fix. If you have a problem like this, you really want to fix it right away and so we're now enabling this warning by default.
Undeclared selectors, let's look at an example. I want to make a timer, an NS timer to go off in 60 seconds and when that timer goes off, I want to send the close message to the current object, but I've got a typo. Instead of close with an "S" I wrote close with a "Z" and the undeclared selector warning will catch this. The last category of warnings that I want to talk about are two issues that are so serious, we're going to treat them as errors by default.
Mismatched Return Types, this is where you're simply missing a return value and here's an example of that. I had intended to make a safe square root function based on the realization you can't compute the square root of a negative value so I'm checking if the input is less than zero, I'll just return. But I didn't think about the fact that the function needs to return something, is declared to return a float.
The compiler catches this of course says, "You're missing a return value." A problem like this is really serious because it's going to lead to undefined behavior and your program is going to crash or it's just going to do something really wrong. So this is now going to be treated as an error by default in new projects.
Another very serious problem like that is Unintentional Root Classes. This is more of a typo kind of problem. I'm declaring a new interface, my class, and I just forgot to specify the base class. The compiler again catches this and suggest that you declare an NS object base class or-- or maybe some other base class that would be more appropriate in your code.
This, too, we are going to treat as an error by default. Now, if you really did intend for that to be a root class, you can add NS root class before the add interface just to tell the compiler, "Yeah, this is really what I meant." So to summarize all these warning changes, we have two new warnings: unsequenced modifications and integer overflow.
We have four warnings that are now going to be enabled by default in new projects, unused functions, implicit Boolean and Enum conversions and undeclared selectors, and finally, two warnings that are really serious: mismatch return types and unintentional root classes that we're going to treat as errors by default in new projects.
So just as the warnings can help you catch bugs, the LLVM compiler provides a really powerful feature to go deeper in analyzing your code and finding more subtle issues and so to talk about that, I'd like to invite up Anna Zaks to talk about the Static Analyzer and finish up the rest of the session.
[ Applause ]
Thank you, Bob. First, I'm going to talk about the new and exciting features we've added to the static analyzer over the past year. And for those of you who had never used the static analyzer, you'll get to learn it-- learn about what it is all about and how it can help you in your development cycle.
So everyone agrees that bugs are bad and as Bob has just mentioned, compiler warnings might pinpoint some of those bugs to you. So how the analyzer issues are different from compiler warnings and why should you use the static analyzer? Well, the static analyzer performs much deeper analysis of your program.
It systematically explores every paths for your program which allows it to find those hard to reproduce edge case bugs. The static analyzer that ships to this Xcode 5 finds new kinds of bugs. It performs deeper record analysis especially for objective-C and C++ and it also exposes new workflows that will allow you to tailor analysis power to your specific setting. So let's first talk about the new kinds of bugs analyzer can find.
Most of you are familiar with NSDictionary and NSMutableDictionary APIs that this code snippet is using. However, let's bring here the Apple documentation site that will tell us exactly what this method does. So the Apple documentation tells us that this method creates a dictionary with a given key and value pair. However, look at the fine print. Here in the parameter section, it also tells us that if the value is nil, then an exception will be thrown at runtime.
And the runtime exception is not something any of us want to happen on the user's iPad or an iPhone while our application is being run there. So how can the static analyzer help? Well, let's go back to our code snippet and suppose here that the default object was set to nil earlier along the execution path.
So if the analyzer knows this, it can-- it will warn you and it will remind you that this API should not be used in this way. And of course if you've switched to the new literal syntax, they're also going to warn but with a slightly different error message.
Well, mostly you will say, "This code is too simple. I don't try code like that. I don't set an object to nil and immediately create an array." Well, we've run the analyzer with this warning turned on, on several large Objective-C code bases and it found issues in every single one of them.
Here's an example from a large Objective-C code base where the analyzer warns. Here it tells you that the object inModifiedKeys is-- could be nil and it is used to create a dictionary so when the analyzer reports an issue to you, not only does it point to the line number where the issue occurred but it also explains to you why this problem has happened.
And the analyzer explains issues by showing you a path through your program on which the-- the problem occurs. So in just-- in order to see the path, you just click on the issue and the path gets displayed. And notice at the top of the editor window, you'll also see analyzer issue navigation bar that will allow you to step through this task and examine each step along the way.
So let's see what actually happens here. Why the analyzer thinks there is a problem? Well, first, we call postNotificationName method. And here we-- in-- the creator's third argument for this method call, the special case, the case when inModifiedKeys object is nil. So we say, "If inModifiedKeys object is not nil, create a dictionary, otherwise, just pass a nil and use that as a third argument." This program keeps running along the same paths and later on the same API is gone and called again and here, the programmer just forgot to check for-- they don't check if inModifiedKeys is nil. They just-- just called it-- they just create a dictionary and use it at the third argument. So clearly there is an inconsistency here and this is what the analyzer notices and this is why it reports the issue.
So we've-- we've also stand a lot of time and we've greatly improved our C++ support. So here's another example of a new-- of warning that we've added to C++. Here, we-- we allocate an object and later on be freed. So, of course, the problem here is that object allocators was new, should be the allocated with delete, because calling a free function will not call the distractor of the object so this might result in memory or resource leaks which are hard to find at runtime.
So we've added several new warnings over the past year. We are going to warn if you're trying to add a nil element to NSMutableArray or nil key or value to NSMutableDictionary. We also warn on use-after-free in C++, mismatched deallocators and creation references to null in C++. And of course these new warnings just add on top of the growing body of the analyzer issues that we've added over the years.
And know that both old and new issues greatly benefit from the power of the analysis because again a factor to finding bugs in your programs is actually understanding what your program does. For example, when you call a method, what happens? Some of you might remember that last year, we've added cross function reasoning for C functions. Well, this year, we've extended it to objective-C and C++.
And we found that this greatly benefit the power of analysis because it's so natural for people to split their cord into subfunctions or submethods. I'm going to explain to you how this works and why this important by showing you how the analyzer operates behind the scenes, on this code snippet. So as I mentioned earlier, the analyzer analyzes your program by systemically exploring every paths through your program.
And it has to be statically without running your program. And in order to do that, it extracts away the values of your variables and constructs a draft from extract system states-- of extract system states and transitions between them. So let's construct such a draft for this code snippet.
The analyzer starts with the initial state and then as it evaluates the statement in your program, it construct a second state, so here we create, allocate an object, localized its name. Notice here how the analyzer splits the path to capture the fact that L could be nil and from now on is going to explore both of these paths.
So now let's go back and see what happened when the analyzed or when the simulated this last method call. So previously the analyzer had to use the most pessimistic assumptions about what a method call could do. However, it's silly. If the method implementation is available to us, we should use that. So let's go back and replay how this will work now.
So in this case, the analyzer knows that the type of object A is asset and given the object type and the method name, we can just very high assurance detect which method will be called at runtime. And this-- if this method's implementation is in the same source file or one of the included headers, then we can bring the method implementation and use it while we simulate this method call.
So here what will happen, the analyzer will simulate a method call, add localized name to the properties map, add regular name through the properties map and return. Now, let's see what happens on-- along the path on which L is nil. Again, we simulate a method call and next we add nil to the dictionary.
And here the analyzer notice that this is a problem, adding a nil to NSMutableDictionary is against the rules so it's going to warn you. So if you were going to run this code through Xcode right now, this is what you would see, you would see a path through both-- both of the methods that shows you how the problem could have occurred.
As I mentioned previously, we've also extended this cross method reasoning to C++ so here's another example, C++ example. Here, we allocate a buffer and we use autopointer to yield with memory management for us. So if you were to run this code through the analyzer, the analyzer is actually going to report a bug. It's going to tell us that here the memory is allocated with operator array new or news square bracket and it should be deallocator as operator array delete, however it tells us that deallocators was operator delete.
Notice here that we don't see the-- the allocation side so what happens actually if we click on this warning to extend it, we'll see that the analyzer sees the distractor of autopointer and it sees which the allocation method it uses there and this is what's required to report this problem. So this just highlights how important the cross method reasoning is for C++ since so much implementation detail is hidden in the headers.
OK, so to summarize, what made this possible? If you do path specific tracking of object types, we reason about constructors and destructors in C++. Also, if your method implementation is either in the given source file or in one of the included headers, the analyzer will be able to use it while it's simulating a method call. However, like the compiler, the analyzer only reasons about one source file at a time. So if your method implementation is in another source file, it will not be able to see the [inaudible] during the analysis.
So now, I'm sure you're all excited about going to have and running the analyzer on your code and the only question you have is how do I do that? How do I trigger analysis of my project? Well, there are several ways of doing that. So first, we can go to Xcode and choose product analyze and that is going to trigger analysis of your whole project that minute or that second from within Xcode.
However, often what you've done-- do is you've analyzed the project before and you've changed one or two files and you just want to reanalyze those files. So we've added a new feature in Xcode 5, you can go to product perform action and choose to analyze a single file, that's much faster.
Well, some of you might want to have continuous feedback from the analyzer as part of your active development. You can go to build settings for Xcode and you can choose to analyze during build. What that will do is it will trigger analysis every time you build your project.
If you have a project that analyzer warning is free, then we highly recommend that you use aesthetic analysis as part of your continuous integration. You can do that by just adding Xcode build analyze to your integration-- continuous integration script of choice or you can set up a bot through Xcode by going to product create bot.
And for more information about creating a bot that rruns the aesthetic analyzer and other stuff, please attend the session that will happen right after this session in Presidio, "Continuous Integration with Xcode 5." Now, I've told you how to choose which code to analyze and when to trigger the analysis. However, what you also can control is the analysis power. There are two analysis mode, there is Shallow, shallow for quick analysis, and there is Deep for more thorough analysis that might find more issues but might take significantly longer.
And here are the defaults that you can change by going to the Xcode build settings. So the default for-- mode for analysis with-- during analyze action is deep and the analyze action is what's gets used when you go to product-- product menu choose analyze or what gets used when you use analyzer as part of your continuous integration. The default mode of analysis during build is shallow because this is when you want a very fast turnaround. Now, if there is one thing to remember, that is we suggest you always analyze your project in deep mode as part of your qualifications.
Now, last but not least, let's talk about your comments. So most of you had heard this question before, where is the documentation, or maybe some of you always write the documentation then you've probably asked this question before. And a very handy way of writing the documentation is to use structured comments such as Doxygen.
This is very useful because the documentation stays-- has more chance of staying up-to-date, it's easier to write, it stays with your code, however, up to now, the compiler and Xcode only pays special attention to your code but skips your comments. Well, in Xcode 5, the Xcode 5 pays attention to everything you wrote including your comments and this allows us to provide a great user experience and developer experience. Let's see what that means.
So previously, if you went to Xcode and option clicked on a method to see what it does, if the method was not declared in the system header, this is all you would see, it will just tell you, the header-- which just tell you the header where this method was declared which is useful but not so useful. Well, now, what will happen is we will generate and display to you the documentation that is based on your comment.
Another way of viewing quick help is through quick help inspector. You can configure Xcode to display it on the right-hand side of the Xcode window. And then whenever you hover your cursor over-- over a given method name, that documentation will be displayed there. No-- no need to option click.
Now, another way of using your comments is code completion so whenever a user-- someone who's using your API types the name of the method, not only will-- will it display its full signature but will also display the comment that is based on your-- the connotation that's based on your comment or the brief section of your comment.
Now, let's talk about how this feature works. This feature is powered by the compiler. The compiler parses your comments along with your code and attaches comments to the declarations and this allows us to create a very precise representation of your whole program that includes your comments and this precise representation, not only allows us to show you your comments back but also give you active feedback about them.
So we've also added a new warning that's called Wdocumentation and you can turn it on by going to build settings and choosing-- turning documentation comments to-- from no to yes. What this warning does is it tries to make sure that your comments stay up-to-date and don't have some simple errors that the analyzer can find-- that the compiler can find.
I'll give you some examples. So here is the first example, here we have a method whose signature changed. This method used to return an error code, however, now it returns a void. Notice here that the comment is stale and the compiler notices this and it tells you that you should probably change the stale comment, this method does not return anything anymore.
Here is yet another example. Here we have-- started writing this documentation and probably we got distracted because we forgot to fill in the brief section. Again the compiler is going to warn us-- warn and tell us, "Hey, you definitely meant to fill this in but you just forgot." Here is yet another example. Here, we have a method that takes two arguments: name and bundle. However, we've mistyped bundle and instead of writing bundle, we wrote bungle.
Not-- not only the compiler notices this but it's also a little bit psychic. It's going to issue a Fix-it and it will tell you, "didn't you mean bungle-- bundle?" And the only action necessary for you to fix this problem is to just click enter and your code will be-- all header.
[ Applause ]
So we've added support to structured comments such as Doxygen and HeaderDoc and HeaderDoc is Apple-structured comment format. For more information about this structured-- comment format, please visit the website that I've listed at the bottom of the slide. We highly encourage you to write your documentation and using structured comments and instantly see them appear in quick help and code completion. If you'd like to hear feedback about your comments from the compiler, don't forget to turn on the connotation comments warning, it's all wired up, ready for your comments.
So to summarize, we've covered a lot of topics today. Now, the LLVM compiler is stronger than ever. It produces faster apps by providing support for latest hardware and having-- enabling new, aggressive optimizations, it also-- we also want to make sure that you can focus on writing your features so we streamlined the development process by making the tools installation easier, providing almost complete C++11 support, providing stricter warnings, deeper analyzing-- analysis and taking full use of your comments in the ID to make it easier for you to concentrate and focus on the code.
For more information, please contact our Developers Tools Evangelist and visit these websites. If you want to learn more about the new optimizations that Evan talked about, please visit Optimize Your Code Using LLVM Session tomorrow. There will be also two related sessions today: Advances in Objective-C at 4:30 and Continuous Integration with Xcode 5 right after this session at 3:15 in Presidio. Thank you all for coming and enjoy the rest of your day.
[ Applause ]
[ Silence ]