Summary:
public
Introduce additional parameter for functions returning struct types - instead of returning it, populate output parameter.
This diff just changes method signature, there are more coming
Reviewed By: jberdine
Differential Revision: D2864842
fb-gh-sync-id: 52fc12c
Summary:
public
Remove some of the explicit pattern matches in favor of using trans_state.var_exp for
init lists and compound literals
Reviewed By: jvillard
Differential Revision: D2855203
fb-gh-sync-id: ce929f6
Summary:
public
Add optional field to trans_state that denotes variable that is being initialized.
This information will be used by certain constructs (such as c++ constructors or
list initialization).
Passing it in trans_state will enable us to deal with more complicated AST structures where
there might be multiple nodes between variable declaration and its initialization.
Reviewed By: jvillard
Differential Revision: D2854988
fb-gh-sync-id: c100380
Summary: public use Sil.exp to pass variable to initialize instead of res_trans containing this Sil.exp.
Reviewed By: jvillard
Differential Revision: D2854981
fb-gh-sync-id: 0cb37f3
Summary:
public
otherwise Infer cannot know the type of the temporary variable
Reviewed By: dulmarod
Differential Revision: D2845054
fb-gh-sync-id: cf5fb8d
Summary:
public
Get newest version of facebook-clang-plugin that replaces pointers from strings to ints.
Fix all compilation issues infer has
Reviewed By: jvillard
Differential Revision: D2815144
fb-gh-sync-id: e93d4b3
Summary:
public
Add destructor calls on delete expression.
While not the most important, it is the simplest case of adding destructor calls.
This will help us in the future with more complex cases.
Reviewed By: ddino
Differential Revision: D2773483
fb-gh-sync-id: 4df9c73
Summary:
public
This diff cleans up the detection of assertion failures in C, C++ and Objective C which was previously hacked on top of the tracing mode for Java. The code is also generalized to detect any custom errors which can be defined using the `__infer_fail` builtin, and the case of assertion failure is now just the specific case of translating `assert` using `__infer_fail` directly in the clang frontend.
Reviewed By: jberdine
Differential Revision: D2786574
fb-gh-sync-id: dd1e1cf
Summary:
public
Move the naming of types to it own module, so that it can be used by modules `Sil` depends from like `Procname`
Reviewed By: jberdine
Differential Revision: D2773148
fb-gh-sync-id: a89f595
Summary:
public
Move the representation of data-structure into it own module, so that it can be used by modules `Sil` depends from like `Procname`.
Reviewed By: jberdine
Differential Revision: D2772791
fb-gh-sync-id: cda4e3a
Summary:
public
Factor resolving default parameters from common method/constructor translation function.
This is done in preparation to use same function for generating destructor calls.
Reviewed By: dulmarod
Differential Revision: D2769291
fb-gh-sync-id: 9c35cf8
Summary:
public
Remove trans_state.parent_line_number because it's not used anymore.
This slightly cleans up codebase
Reviewed By: ddino
Differential Revision: D2755050
fb-gh-sync-id: b1b7e8e
Summary:
public there was a problem with
templated method names that had '/' in its names.
This happened for names like this: `method_name<(anonymous lambda in path/to/src:1:1)>`
Plus random fix to backend logging
Reviewed By: dulmarod
Differential Revision: D2749359
fb-gh-sync-id: b9a0fcd
Summary:
public This continues the work on adding builtins for getters and setters
and removing the generated code from the frontend. This is extending it to setters and
removing the preanalysis that is no longer needed.
Reviewed By: akotulski
Differential Revision: D2734499
fb-gh-sync-id: 7cf5749
Summary:
public
Add support for decl statements inside condition of switch statement
Reviewed By: ddino
Differential Revision: D2734213
fb-gh-sync-id: d60021d
Summary:
public
Change semantics of res_trans_cond inside switchStmt_trans to include
condition node (as opposed to children nodes only).
This way, meaning will be consistent with conditions inside if and while
Reviewed By: ddino
Differential Revision: D2734185
fb-gh-sync-id: 866eee2
Summary:
public
Conditional operator in C++ allows to return lvalues as a result of the operator.
Make infer frontend smart enough to detect when that happens and treat this
case correctly
Reviewed By: ddino
Differential Revision: D2729468
fb-gh-sync-id: f4a110d
Summary:
public Using the new information from the plugin that links method decls in objc with their
properties if they are getters. Setters to be done in next diff.
Reviewed By: ddino
Differential Revision: D2729511
fb-gh-sync-id: dc58894
Summary:
public
Modify do_branch inside conditionalOperator_trans:
1. Remove TempJoinNode optimization - instead create join node as usually. It produces one more node, but it's much cleaner
2. Claim priority inside do_branch instead of appending instructions to node created by children
3. Use compute_results_to_parent to some extent
4. Random changes to loop_instruction and trans_assertion_failure to make tests pass
Reviewed By: ddino
Differential Revision: D2708076
fb-gh-sync-id: d429167
Summary: public These two functions were doing very same things.
After last refactor code of both functions started to look very similar.
Reviewed By: dulmarod
Differential Revision: D2707502
fb-gh-sync-id: b0559a3
Summary: public
We were generating getters and setters in the frontend, and then removing them if they were not needed
in the preanalysis. This diff adds a builtin getter that gets called if we are going to skip the function. That
means, if there was a getter written by the developers we still use that one rather than the builtin.
Code for setter and cleanup of preanalysis will come in a next diff.
Reviewed By: jvillard
Differential Revision: D2702890
fb-gh-sync-id: d65f25e
Summary: public
Use PriorityNode.compute_results_to_parent in BinaryOperator_trans.
There is no functional change intended
Reviewed By: ddino
Differential Revision: D2696382
fb-gh-sync-id: 4e75761
Summary: public
Refactor compute_results_to_parent to call collect_res_trans directly there.
So the job of PriorityNode.compute_results_to_parent is the following:
Given list of [res_trans_1; res_trans_2; ... ; res_trans_n],
1. Connect nodes linearly (ie. res_trans_1 with res_trans_2, res_trans_2 with res_trans_3) etc.
If res_trans_k has no nodes, try connecting res_trans_k-1 with res_trans_k+1 (this is what collect_res_trans always did)
2. Collect all ids, instrs and exps into one res_trans
3. Create node if needed and put there same ids and instrs as usual.
4. Connect new node with existing ones
4. Return new node structrue with exps = []
This will make function usable in more places so we don't have to create nodes over and over again
Reviewed By: ddino
Differential Revision: D2696351
fb-gh-sync-id: 9f4a9b4
Summary: public Make it uniform with other function call translations. This is just reordering, no functional change intended
Reviewed By: dulmarod
Differential Revision: D2696370
fb-gh-sync-id: 63656e3
Summary: public
Nodes in these functions can be created later (after translation of subexpressions is done).
Change triggers many differences in .dot files, but they are all about different numbering of
nodes.
There is no functional change in this diff.
Reviewed By: dulmarod
Differential Revision: D2699703
fb-gh-sync-id: a7b8d2a
Summary: public
In both functions, there is no need to pass anything in succ_nodes since nodes will be connected later anyway.
This will allow to create node later (will be done in separate diff)
Reviewed By: dulmarod
Differential Revision: D2699693
fb-gh-sync-id: 4396d31
Summary: public
Infer gets confused with this cast. It happens when objects try
to access superclass field/method, but we shouldn't change type in
this case (for the sake of backend)
Reviewed By: dulmarod
Differential Revision: D2663905
fb-gh-sync-id: bbf1cb2
Summary: public
Not finding C++ method in decl map was considered impossible to happen.
It turns out it can happen because ast exporter wasn't exporting template
instantiations.
So instead, pick a default when method decl is not found. This will be right in
most cases and will allow us to analyze rest of the function without crashing
frontend
Reviewed By: dulmarod
Differential Revision: D2695653
fb-gh-sync-id: 4077c59
Summary: public
Using clang's method resolution. This means that, in method calls, clang gives you a pointer to the declaration of the method.
In some cases though, clang doesn't find the right method. For example, when it finds a method in a category, we
need to make it into a method in the corresponding class, because that's how we treat categories in Infer. Moreover,
when it finds a method in a protocol, that is not useful for us, since the implementation will be in some class. Finally,
sometimes the call is on an object of type id, in which case clang doesn't know what is the correct declaration. In
those cases, we fall back to what we were doing before of approximating the method resolution. We also refactor
some of the code.
Reviewed By: akotulski
Differential Revision: D2679766
fb-gh-sync-id: b79bb85
Summary: public
Support MaterializeTemporaryExpr which happens often in real life C++.
For example, it will happen in this code:
std::vector<int> v;
v.push_back(1);
// it's because std::vector<int>::push_back(const int &)
Strategy is to create variable that will store value of init expression (to provide storage)
and then return variable as a result of an expression
Reviewed By: ddino
Differential Revision: D2674340
fb-gh-sync-id: 077ed6a
Summary: public
Translate C++ overloaded operator calls. AST of their children looks slightly differently
which means that we have to be more permissive in params_trans.exps.
Difference:
CXXMemberCallExpr:
MemberExpr:
'ThisExpr' (it's part of method decl ref evaluation)
MethodDeclRef
Param1
Param2
...
CXXOperatorCallExpr
MethodDeclRef/FunctionDeclRef
'ThisExpr' (it's part of parameters list evaluation)
Param1
Param2
...
Reviewed By: dulmarod
Differential Revision: D2679503
fb-gh-sync-id: 1437f73
Summary: public
Add support for translation and calling c++ static methods.
They can be called in two ways:
ClassName::method()
classInstance.method()
Both of them have the same meaning, but AST produced is different
Reviewed By: dulmarod
Differential Revision: D2636489
fb-gh-sync-id: 9294a3f
Summary: public Plugin already exports fully qualified name, we don't need
to reconstruct it in ocaml again.
It wasn't used anywhere so this diff shouldn't change any behavior
Reviewed By: dulmarod
Differential Revision: D2668588
fb-gh-sync-id: 1ed1d61
Summary: public
New qual_name exporting logic in facebook-clang-plugins handles anonymous
classes in much better way. This allows us to simplify name generation for
classes that don't rely on a type of the object (which could be wrong for
methods from superclasses).
Reviewed By: dulmarod
Differential Revision: D2663810
fb-gh-sync-id: 08146b8
Summary: public
The static and global variables used in blocks don't appear in the ast as captured.
We need them however to try and find retain cycles involving those variables.
This diff adds a way of collecting the static variables used in blocks and treat them
like we treat other captured variables to find retain cycles.
Reviewed By: ddino
Differential Revision: D2663727
fb-gh-sync-id: d5b44ec
Summary: public
When method was called from within other method,
the type of `this` parameter didn't have pointer in type.
This was due to wrong logic that stripped pointer out of the
type.
We still need to strip the type when dereferencing reference variable.
Reviewed By: dulmarod
Differential Revision: D2652012
fb-gh-sync-id: 44552ac
Summary: public
Move dealing with init expressions from VarDecl_trans to standalone function.
This will be useful for constructor initializer.
I didn't improve anything, just moved stuff around so that no test breaks.
Main change is that we pass Sil code responsible for LHS (var dereference) as
result_trans.
Currently we assume that var_result_trans will have no nodes, no instructions,
no ids. This is true for current usages (it's always Sil.Lvar expression), but in the future it
will change.
Reviewed By: dulmarod
Differential Revision: D2647108
fb-gh-sync-id: cae60b6
Summary: public
returnStmt_trans adds all ids and instrs to its node. It shouldn't return them to parent then.
Reviewed By: dulmarod
Differential Revision: D2636829
fb-gh-sync-id: eb554b9
Summary: public This diff changes the way we treat enums in Infer.
1. The semantics of the translation is now correct, it was a bit incorrect before.
2. We don't add the enum types to the tenv anymore, which saves a lot of disk space
and avoids errors in the backend dealing with the enum type.
Reviewed By: akotulski
Differential Revision: D2641903
fb-gh-sync-id: 6295e5f
Summary: public
C++ allows to have one variable declared+initialized as a condition statement.
Handle these cases properly for `if` and `while` statements.
Reviewed By: dulmarod
Differential Revision: D2625774
fb-gh-sync-id: bac95b8
Summary: public
Translate CXXConstructExpr that are parts of variable initialization.
Reviewed By: dulmarod
Differential Revision: D2570750
fb-gh-sync-id: 708a457
Summary: public
Type of `this` argument to c++ method call has pointer type.
It's either raw pointer (for `->`) or reference (for `.`).
It was already correct in method declaration and method parameters, but it wasn't correct in method calls. Same thing will apply to constructor expressions.
As a result of this change, we won't expand type when calling methods.
Change to ast_expressions.ml fixes problem with autogenerating getters/setters that produced lvalue types after LValueToRValue cast.
Reviewed By: dulmarod
Differential Revision: D2605756
fb-gh-sync-id: 1027600
Summary: public
Update clang plugin version that has following changes:
1. Don't dump DeclContext as a part of BlockDecl
2. Add location information to C++ constructor initializers
This diff is making infer compatible with these changes by
1. Making infer compile
2. Reading location information from c++ constructor initializers so we don't miss update to line number
Reviewed By: dulmarod
Differential Revision: D2575066
fb-gh-sync-id: 6dc594a
Summary: public
Refactor translation of C++ method calls so that we get two parts:
1. Get Sil code for method address and this expression
2. Given method address, this expression and list of paramter statements, create Call instruction
This will allow us to share more code with C++ constructor calls that do (1) differently, but
(2) will be shared
Reviewed By: dulmarod
Differential Revision: D2570712
fb-gh-sync-id: 9c6c3e4
Summary: public
Adds incomplete translation of constructor bodies. Treat constructors as
methods with something 'extra'.
We still don't translate initializer lists, just pass the information to cTrans
where it's ignored
Reviewed By: dulmarod
Differential Revision: D2550214
fb-gh-sync-id: 102c13a
Summary: public
modules are better for namespacing.
How I made this diff:
1. moved list_* functions from utils.ml{,i} to iList.ml{,i}
2. shell commands:
grep '^val ' infer/src/backend/iList.mli | cut -f 2 -d ' ' | tr '\n' ' '
# gives a list of former list_ functions that IList implements, fed into the loops below:
LISTNAMES=" compare equal append combine exists filter flatten flatten_options find fold_left fold_left2 for_all for_all2 hd iter iter2 length fold_right map mem nth partition rev rev_append rev_map sort split stable_sort tl drop_first drop_last rev_with_acc remove_duplicates remove_irrelevant_duplicates merge_sorted_nodup intersect mem_assoc assoc map2 to_string"
# replace " list_*" function calls with IList.* ones
for i in $LISTNAMES; do find . -name '*.ml' -exec sed -i -e "s/ list_$i\b/ IList.$i/g" \{\} \; ; done
# replace (list_* functions with (IList.* ones
for i in $LISTNAMES; do find . -name '*.ml' -exec sed -i -e "s/(list_$i\b/(IList.$i/g" \{\} \; ; done
# ditto with [
for i in $LISTNAMES; do find . -name '*.ml' -exec sed -i -e "s/\[list_$i\b/[IList.$i/g" \{\} \; ; done
3. Then fix up the rest by hand. In particular, stuff that called Utils.list_*
explicitely, and stuff that used the "Fail" exception that has moved to
IList. (may revisit this in the future)
Reviewed By: jeremydubreil, cristianoc
Differential Revision: D2550241
fb-gh-sync-id: cd64b10
Summary: public
C++ assignment operation result is lvalue, while in C it was rvalue.
This leads to different AST produced by clang for then same code!
Use language information from clang (`-x` flag) to distinguish these cases.
More specifically, let's look at following code:
int r;
int f = (r = 3);
// type of (r = 3) expression:
// C/objC -> int rvalue
// C++/objC++ -> int lvalue
Existing code did extra dereference because it was rvalue in C and there was no cast afterwards
in C++ there will be extra LValueToRvalue cast when neccesary so we don't have to do extra dereference manually
Reference:
http://en.cppreference.com/w/c/language/value_category (search for 'assignment and compound assignment operators')
NOTE: AST output doesn't change when something is hidden behind `extern "C"`, so we should use global language information
Reviewed By: ddino
Differential Revision: D2549866
fb-gh-sync-id: b193b11
Summary: public Two cases were not handled properly so far:
1. Declaration of a reference variable missed reference bit in type
2. Parameters to a function expecting T& had type T.
The way to distinguish reference types from value types is to look
whether parameter is type 'T rvalue' or type 'T lvalue' (xvalue probably as well)
Unfortunately, we can't just say 'T lvalue' = 'T&' because it would break
a lot of things in our frontend.
However, we know that when parameter to a function call has type 'T lvalue', it has to be 'T&' type.
Same applies when init_expression type is lvalue.
So, the solution is to add wrapper function that looks at results of `instruction` function and
expected expression type. Then if it's lvalue, wrap the type in reference.
Do this wrapping magic only when we know that lvalue mean reference type.
The rest of the changes is to make frontend tests pass - since we use different fields
in the AST, some of them were incorrectly set before and no one noticed.
Reviewed By: cristianoc
Differential Revision: D2549991
fb-gh-sync-id: 067f5d5
Summary: public
Dictionary literals are normally implemented using
`+dictionaryWithObjects:forKeys:count:` but were modeled as
`+dictionaryWithObjectsAndKeys:`
In particular, `@{@"aaa": nil}` would trigger a sentinel error instead of an NPE.
This models dictionary literals as a special infer builtin that the backend
interprets so as to give NPEs when passed nil objects or keys.
Reviewed By: dulmarod
Differential Revision: D2550039
fb-gh-sync-id: 1a10656
Summary: @public
This diff changes following things:
1. expression_info.type_ptr has type than decl_ref_info.type_ptr for reference types. Use type from decl_ref_info as a source of truth
2. reference types need to have one extra dereference that is not in AST. Add handling for this.
3. [small refactor] create function that creates temporary variable from res_trans expression and returns new res_trans.
Some caveats:
1. types are not quite right yet (see .dot files).
2. decl_ref_info might not be set for DeclRefExpr, make frontend crash in that case to catch when this happens
This is high risk change since it changes behavior of every translation on very widely used expr.
Reviewed By: @dulmarod
Differential Revision: D2540632
fb-gh-sync-id: aa28936
Summary: @public
This removes the old way of finding variable declarations to create sil variables and replaces it with
a a new way based on the map from pointers to declarations.
Basically, every variable dereference contains a pointer to the variable declaration, with that we can
build the corresponding sil variable.
Reviewed By: @akotulski
Differential Revision: D2536000
fb-gh-sync-id: dd29cf9
Summary: @public
Refactor exising code that handles __nonnull annotations.
Create extendable way to add extra stuff to be translated before
rest of statements get translated.
This will make handling of constructor initializer list simpler
Reviewed By: @dulmarod
Differential Revision: D2521659
fb-gh-sync-id: ba613e7
Summary: @public remove `is_instance` function parameter that was used for
blocks only. Instead, pass context everywhere - it holds information that is
very relevant when defining block.
Reviewed By: @dulmarod
Differential Revision: D2521772
fb-gh-sync-id: 5fb53f9
Summary: @public
1. Add support for `this` keyword. It will allow to access fields/methods of the object from the method body.
2. Fix problem with method formals to add pointer to type of first parameter (which corresponds to `this`)
Reviewed By: @dulmarod
Differential Revision: D2484882
fb-gh-sync-id: c318619
Summary: @public
First diff to give better language information in the frontend.
This information is necessary to understand when 'self' is objc keyword,
when 'this' is C++ keyword and when they are not.
Reviewed By: @ddino, @dulmarod
Differential Revision: D2489252
Summary: @public
qual_type was the same as type_ptr, so it was removed.
This commit makes it compatible with facebook-clang-plugins
Commands ran:
codemod --extensions ml,mli 'qual_type' 'type_ptr'
codemod --extensions ml,mli 'qt' 'tp'
If there is any other popular name for qual_type, let me know
Reviewed By: @dulmarod
Differential Revision: D2498289
Summary:
Using the qualified names of fields to create mangled names.
This removes the need to search for the fields in the tenv when translating a field access.
That was only done to build the correct mangled name,
The rest of the changes are using the qualified names for ivars and property names in the property module,
which is needed to make it work. Basically a big chain of changes of using qualified names to make the code
compile.
Summary:
This diff aims at removing the occurrences of the types in string form so that we can remove them
from the ast which will save space.
There is one occurrence left regarding attributes that will be handled later by Andrzej.
We build a function to create a string out of a function type used for name mangling.
Summary:
C function names depend only on their name (and their file is they are static, and their type if we are in C++)
This is more in sync with the actual semantics of C function names than the previous implementation.
Summary:
This is the second of 3 stack diffs to deal with replacing the parser of types.
This diff is about general changes to the frontend to make it cope with the change. There
are two main challenges:
1. We create pieces of ast in ast_expressions, such as getters and setters. For that we create
custom types.
2. We store types in cMethod_signature for parameters and return type of functions. This was
stored as strings, but that means losing the pointer information which is vital to get the
sil types.
So this diff consists mostly of dealing with these challenges. It change the signature of
cMethod_signature and update modules accordingly.
To deal with the custom types, we build methods in ast_expressions for creating those types,
with a custom type pointer, like "internal_typeint". At the beginning of the translation we save
all these custom types in the map from type pointers to sil types that we build as we compute the
types, so that they are available later.
Another custom type that we build is a type of classes or pointer of classes based on the current
class. I found a simple way to deal with it, giving it a pointer "class_name", and then we know
how to translate those. Something I tried is to save the declaration of the current class and pass
that declaration around, but somehow that lead to pref regression, so I removed it in favor of this
more lightweight version.
Summary:
Use the map of pointers to find method declarations and build method signatures.
Remove the need for having an extra map for method signatures (and remove that map).
Summary:
Handle C++ method declarations and create cfgs for them.
Doesn't do:
Method calls (CXXMethodCall)
Using `this` expression in methods (including implicit ones)
Summary:
Refactor of creating method signatures. First step to use the map of pointers to find method declarations.
The idea is to have a function that creates a method signature from a declaration, later we can get the declaration from a pointer
and use this function to retrieve the method signature.
(authored by @dulmarod)
Summary:
Add basic translation for C++ `new` keyword.
Currently, it's modeled as simple `malloc` call.
Following constructs are still not working properly:
- array new `new [size_expr]`
- run initializer attached to `new` (such as `new int(5)`)
- `delete[]`
Summary:
1. Unify the code now that MemberExpr has more information available and it can be shared with ObjCIvarRefExpr
2. Use type from decl_ref instead of expression type. For methods, expression type is useless (`<bound something something`>). For fields it should be the same
Summary:
The methods in objc can have the same name in the same class, but one be instance and the other class,
so that we need to take the instance flag into account when defining unique names for ObjC methods.
Summary:
This commit is the result of
`find infer/src -name '*.ml' -or -name '*.mli' -exec ocp-indent -i \{\} \;`
and
`INFER_CHECK_COPYRIGHT=1 InferPrint`
Summary:
In preparation for C++ methods, we need to have type with
class, method, mangled (for overloading?)
1. Change objc method to support it
2. Do some renames to be less confusing
Summary:
In objC we already prefix field names with classes.
It's better to make it consistent since it'll allow
us to share more code between C++ and objC
Summary:
This makes infer C frontend compatible
with new scheme for naming which has:
1. plain name (like 'fun')
2. qualified name (reversed list like ['fun', 'class', 'top_class', 'namespace'])
Summary:
@public
Add support for default function arguments.
As a side change - always create cmethod_signature for a function
Test Plan:
1. Call function with default parameter and confirm that it gets parsed and reports null dereference (B5 but still). It didn't before.
2. Created a test case
Summary: @publicThe first argument of builtin calls in C gets translated twice, which is bad if the argument is a side-effecting expression like a function call.
Test Plan: Attached test previously reported a memory leak because the translation introduces an extra call to malloc(), now reports nothing.
Summary:
@public
Translate CXXStaticCastExpr
Test Plan:
Add test, confirm that it gets translated.
Also create example to see that infer reports null dereference with this change:
struct X { int a; };
int main() {
X *x = static_cast<X*>(nullptr); // <- reports now
//X *x = (X*)nullptr; // <- reported before
return x->a;
}
Summary:
@public
Make c frontend understand CXXNullPtrLiteralExpr.
Note that the implementation differs from GNUNullExpr
Test Plan:
Create function that returns nullptr:
int* getPtr() {return nullptr;}
look at specs:
InferPrint infer-out/specs/getPtr\{831F\}.specs
Procedure: getPtr
int *getPtr()
Timestamp: 1
Status: INACTIVE
Phase: RE_EXECUTION
Dependency_map:
TIME:0.002853 s TIMEOUT:N SYMOPS:10 CALLS:1,0
ERRORS:
--------------------------- 1 of 1 [nvisited: 1] ---------------------------
PRE:
POST 1 of 1:
return = null:
----------------------------------------------------------------
Add test for it
Summary:
@public
Sorting the fields in structs and classes. Was needed in the backend and forgotten.
Fixes the github issue https://github.com/facebook/infer/issues/90.
Test Plan: Added a new test that shows that we now get a spec for the example from the github issue.