Initial implementation of shared_ptr model

Summary:public
Create initial model of C++ std::shared_ptr. This means that infer will replace implementation of
shared_ptr and the resulting binary will change. Make sure no one will run it by crashing any binary that includes that code.

Reviewed By: jvillard

Differential Revision: D2999948

fb-gh-sync-id: 5753559
shipit-source-id: 5753559
master
Andrzej Kotulski 9 years ago committed by Facebook Github Bot 8
parent b2969820a4
commit eb76a441f9

@ -11,6 +11,8 @@ CLANG_COMPILER="${SCRIPT_DIR}/../../../facebook-clang-plugins/clang/bin/clang"
if [ "${0%++}" != "$0" ]; then XX="++"; else XX=""; fi
COMMAND=("${CLANG_COMPILER}${XX}")
COMMAND+=("-isystem")
COMMAND+=("${SCRIPT_DIR}/../../models/cpp/include")
# Remove command line options not supported by the opensource compiler or the plugins.
PREV=""

@ -0,0 +1,15 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
// this file exists in gcc headers and we need to capture those includes
#include <infer_model/begin_name_override.inc>
#include_next <bits/shared_ptr.h>
#include <infer_model/end_name_override.inc>
#include <infer_model/shared_ptr.h>

@ -0,0 +1,3 @@
#define make_shared std__make_shared
#define shared_ptr std__shared_ptr

@ -0,0 +1,31 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#pragma once
#include <infer_model/portability.h>
#include <cstdlib>
#include <cstdio>
#define static_assert(...)
namespace infer_model {
// code compiled with infer headers is not supposed to be executed
struct AbortWhenRun {
AbortWhenRun() {
fprintf(stderr,
"!!! This program must not be run !!!\n"
"This code was compiled to be analyzed by Infer.\n"
"To run this program, recompile it without Infer.\n");
std::abort();
}
};
static AbortWhenRun a{};
}

@ -0,0 +1,2 @@
#undef make_shared
#undef shared_ptr

@ -0,0 +1,31 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#pragma once
// TODO set it in configure script instead
// This is hacky attempt to follow what folly does
// https://github.com/facebook/folly/blob/b1eb6819f3ffe6b645f39d505ca8ace3116b7873/folly/configure.ac#L232
#if !defined(INFER_USE_LIBCPP) && defined(__APPLE__)
#define INFER_USE_LIBCPP 1
#elif defined(FOLLY_USE_LIBCPP)
#define INFER_USE_LIBCPP 1
#endif
// Follow what folly does - gnu libstdc++ implementation is different from
// llvm's libc++. This way folly can forward declare decls from std library
// even when they are infer models
// https://github.com/facebook/folly/blob/b1eb6819f3ffe6b645f39d505ca8ace3116b7873/folly/Portability.h#L253-L255
#if INFER_USE_LIBCPP
#include <__config>
#define INFER_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
#define INFER_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD
#else
#define INFER_NAMESPACE_STD_BEGIN namespace std {
#define INFER_NAMESPACE_STD_END }
#endif

@ -0,0 +1,235 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#pragma once
// ASSERT that __cplusplus >= 201103L
#include <infer_model/common.h>
INFER_NAMESPACE_STD_BEGIN
// use inheritance to avoid compilation errors when using
// methods / non-member functions that are not modeled
// WARNING: sizeof(shared_ptr) = 24, not 16 - this may
// lead to compilation errors
template <class T>
class shared_ptr : public std__shared_ptr<T> {
public:
// Conversion constructors to allow implicit conversions.
// it's here purely to avoid compilation errors
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr(const std__shared_ptr<Y>& r) {}
template <class Y>
shared_ptr(const std__shared_ptr<Y>& r, T* p) noexcept {}
T* data;
// constructors:
constexpr shared_ptr() noexcept : data(nullptr) {}
shared_ptr(nullptr_t) : shared_ptr() {}
// Extra template argument is used to create constructors/assignment overloads
// for Y types where it's possible to convert Y* to T*.
// typename = typename enable_if<is_convertible<Y*, T*>::value>::type
// thanks to that, clang will not create some functions that would cause
// compilation errors. More info:
// http://en.cppreference.com/w/cpp/language/sfinae
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
explicit shared_ptr(Y* p) {
data = p;
}
template <class Y,
class D,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr(Y* p, D d) : shared_ptr<T>(p) {}
template <class Y,
class D,
class A,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr(Y* p, D d, A a) : shared_ptr<T>(p) {}
template <class D>
shared_ptr(nullptr_t p, D d) : shared_ptr<T>(p) {}
template <class D, class A>
shared_ptr(nullptr_t p, D d, A a) : shared_ptr<T>(p) {}
template <class Y>
shared_ptr(const shared_ptr<Y>& r, T* p) noexcept : data(nullptr) { /* TODO */
}
shared_ptr(const shared_ptr& r) noexcept
: shared_ptr<T>(r.data) { /* TODO - increase refcount*/
}
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr(const shared_ptr<Y>& r) noexcept
: shared_ptr<T>(r.data) { /* TODO - increase refcount*/
}
shared_ptr(shared_ptr&& r) noexcept : shared_ptr<T>(r.data) {
r.data = nullptr;
}
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr(shared_ptr<Y>&& r) noexcept : shared_ptr<T>(r.data) {
r.data = nullptr;
}
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
explicit shared_ptr(const weak_ptr<Y>& r) {}
/* Because of implementation differences between libc++ and stdlibc++, don't
* define this constructor (it will be defined elsewhere in case of
* stdlibc++). Because it may be defined elsewhere, don't check whether Y*
* converts to T* - otherwise there might be compilation error (out-of-line
* definition).
* No definition here might cause compilation problems if project is
* using auto_ptrs with libc++ */
template <class Y>
shared_ptr(auto_ptr<Y>&& r); // {}
template <class Y,
class D,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr(unique_ptr<Y, D>&& r) : shared_ptr<T>(r.release()) {}
// destructor:
~shared_ptr() { reset((T*)nullptr); }
// assignment:
shared_ptr& operator=(const shared_ptr& r) noexcept {
// shared_ptr<T>(r).swap(*this);
data = r.data;
return *this;
}
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr& operator=(const shared_ptr<Y>& r) noexcept {
// shared_ptr<T>(r).swap(*this);
data = r.data;
return *this;
}
shared_ptr& operator=(shared_ptr&& r) noexcept {
// shared_ptr<T>(std::move(r)).swap(*this);
data = r.data;
return *this;
}
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr& operator=(shared_ptr<Y>&& r) {
// shared_ptr<T>(std::move(r)).swap(*this);
data = r.data;
return *this;
}
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr& operator=(auto_ptr<Y>&& r) { /* ?? */
}
template <class Y,
class D,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
shared_ptr& operator=(unique_ptr<Y, D>&& r) {
// shared_ptr<T>(std::move(r)).swap(*this);
return *this;
}
// modifiers:
void swap(shared_ptr& r) noexcept {
T* tmp = r.data;
r.data = data;
data = tmp;
}
void reset() noexcept { reset((T*)nullptr); }
template <class Y,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
void reset(Y* p) {
/*
if (unique()) {
delete data;
}
*/
data = p;
// TODO adjust refcounts
}
template <class Y,
class D,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
void reset(Y* p, D d) {
reset(p);
}
template <class Y,
class D,
class A,
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
void reset(Y* p, D d, A a) {
reset(p);
}
// observers:
T* get() const noexcept { return data; }
typename add_lvalue_reference<T>::type operator*() const noexcept {
return *data;
}
T* operator->() const noexcept { return data; }
long use_count() const noexcept { return 2; /* FIXME */ }
bool unique() const noexcept { return use_count() == 1; /* FIXME */ }
explicit operator bool() const noexcept { return (bool)data; }
template <class U>
bool owner_before(shared_ptr<U> const& b) const {
return true; /* FIXME - use non-det*/
}
template <class U>
bool owner_before(weak_ptr<U> const& b) const {
return true; /* FIXME - use non-det */
}
};
template <class T>
struct hash<shared_ptr<T>> : public hash<std__shared_ptr<T>> {};
// shared_ptr casts - call original functions but change return type to
// std::shared_ptr
template <class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r) noexcept {
return static_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
}
template <class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept {
return dynamic_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
}
template <class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r) noexcept {
return const_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
}
template <class T, class... Args>
shared_ptr<T> make_shared(Args&&... args) {
return shared_ptr<T>(new T(std::forward<Args>(args)...));
}
INFER_NAMESPACE_STD_END

@ -0,0 +1,13 @@
#if __cplusplus >= 201103L
#include <infer_model/begin_name_override.inc>
#include_next <memory>
#include <infer_model/end_name_override.inc>
#include<infer_model/shared_ptr.h>
#else // __cplusplus < 201103L
// don't model memory for pre-C++11 code
#include_next <memory>
#endif

@ -99,11 +99,14 @@ let should_translate (loc_start, loc_end) =
in
let file_in_project = map_path_of file_in_project loc_end
|| map_path_of file_in_project loc_start in
let file_in_models file = Str.string_match (Str.regexp "^.*/infer/models/cpp/include/") file 0 in
let file_in_models = map_path_of file_in_models loc_end
|| map_path_of file_in_models loc_start in
equal_current_source !curr_file
|| map_file_of equal_current_source loc_end
|| map_file_of equal_current_source loc_start
|| (!CFrontend_config.cxx_experimental && file_in_project
&& not (!CFrontend_config.testing_mode))
|| file_in_models
|| (!CFrontend_config.cxx_experimental && file_in_project)
let should_translate_lib source_range =
not !CFrontend_config.no_translate_libs

@ -0,0 +1,64 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
struct X {
int field;
int* getPtr() { return &field; }
int* getNull() { return nullptr; }
};
struct SmartPtr {
SmartPtr() : data(nullptr) {}
X* data;
X* get() { return data; }
};
void smart_ptr_null_field_deref() {
SmartPtr p;
int f = p.get()->field;
}
void smart_ptr_null_method_deref() {
SmartPtr p;
int* f = p.get()->getPtr();
}
void smart_ptr_null_method_deref2() {
SmartPtr p;
int* f = p.get()->getNull();
}
void smart_ptr_ok_field_deref() {
SmartPtr p;
X x;
p.data = &x;
int f = p.get()->field;
}
void smart_ptr_ok_method_deref() {
SmartPtr p;
X x;
p.data = &x;
int* f = p.get()->getNull();
int* g = f;
}
void smart_ptr_result_method_null_deref() {
SmartPtr p;
X x;
p.data = &x;
int f = *(p.get()->getNull());
}
void smart_ptr_result_method_ok_deref() {
SmartPtr p;
X x;
p.data = &x;
int f = *(p.get()->getPtr());
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#include <memory>
struct Base {
int* f1;
};
struct Derived : public Base {
int* f2;
};
std::shared_ptr<Base> getFromBase1(Base* b) { return std::shared_ptr<Base>(b); }
std::shared_ptr<Base> getFromBase2(Base* b) {
std::shared_ptr<Base> result;
result = std::shared_ptr<Base>(b); // assignment operator
return result;
}
std::shared_ptr<Base> getFromDerived1(Derived* d) {
return std::shared_ptr<Base>(d);
}
std::shared_ptr<Base> getFromDerived2(Derived* d) {
std::shared_ptr<Derived> sd(d);
return std::shared_ptr<Base>(sd);
}
std::shared_ptr<Base> getFromDerived3(Derived* d) {
std::shared_ptr<Derived> sd(d);
std::shared_ptr<Base> result;
result = sd; // assignment operator
return result;
}
void get_from_base1_nullptr_deref() { Base b = *(getFromBase1(nullptr)); }
void get_from_base2_nullptr_deref() { Base b = *(getFromBase2(nullptr)); }
void get_from_derived1_nullptr_deref() { Base b = *(getFromDerived1(nullptr)); }
void get_from_derived2_nullptr_deref() { Base b = *(getFromDerived2(nullptr)); }
void get_from_derived3_nullptr_deref() { Base b = *(getFromDerived3(nullptr)); }
void get_from_base1_null_f1_deref() {
Base b;
int v;
b.f1 = &v;
std::shared_ptr<Base> p = getFromBase1(&b);
b.f1 = nullptr;
int r = *(p->f1);
}
void get_from_base2_null_f1_deref() {
Base b;
int v;
b.f1 = &v;
std::shared_ptr<Base> p = getFromBase2(&b);
b.f1 = nullptr;
int r = *(p->f1);
}
void get_from_derived1_null_f1_deref() {
Derived b;
int v;
b.f1 = &v;
std::shared_ptr<Base> p = getFromDerived1(&b);
b.f1 = nullptr;
int r = *(p->f1);
}
void get_from_derived2_null_f1_deref() {
Derived b;
int v;
b.f1 = &v;
std::shared_ptr<Base> p = getFromDerived2(&b);
b.f1 = nullptr;
int r = *(p->f1);
}
void get_from_derived3_null_f1_deref() {
Derived b;
int v;
b.f1 = &v;
std::shared_ptr<Base> p = getFromDerived3(&b);
b.f1 = nullptr;
int r = *(p->f1);
}

@ -0,0 +1,103 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#include <memory>
struct X {
int field;
int get() { return field; }
void set(int value) { field = value; }
};
int empty_ptr_access() {
std::shared_ptr<int> x;
int* p = x.get(); // no dereference
if (p) {
return 1;
}
return 0;
}
int empty_ptr_deref() {
std::shared_ptr<int> x;
return *x;
}
int nullptr_ptr_deref() {
std::shared_ptr<int> x(nullptr);
return *x;
}
int empty_ptr_field_deref() {
std::shared_ptr<X> x;
return x.get()->field;
}
int empty_ptr_field_deref2() {
std::shared_ptr<X> x;
return x->field;
}
int empty_ptr_method_deref() {
std::shared_ptr<X> x;
return x->get();
}
int reset_ptr_null_deref() {
std::shared_ptr<int> x(new int);
x.reset();
return *x;
}
int reset_ptr_null_deref2() {
std::shared_ptr<int> x(new int);
x.reset(new int);
x.reset();
return *x;
}
int reset_ptr_ok_deref() {
std::shared_ptr<int> x;
x.reset(new int);
return *x;
}
int reset_ptr_ok_deref2() {
std::shared_ptr<int> x;
x.reset();
x.reset(new int);
return *x;
}
int shared_ptr_copy_null_deref() {
std::shared_ptr<int> p1;
std::shared_ptr<int> p2 = p1;
return *p2;
}
int shared_ptr_assign_null_deref() {
std::shared_ptr<int> p1(new int);
std::shared_ptr<int> p2;
p1 = p2;
return *p1;
}
int shared_ptr_copy_ok_deref() {
std::shared_ptr<int> p1(new int);
std::shared_ptr<int> p2 = p1;
return *p2;
}
int shared_ptr_assign_ok_deref() {
std::shared_ptr<int> p1(new int);
std::shared_ptr<int> p2;
p2 = p1;
p1.reset();
return *p2;
}

@ -0,0 +1,67 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package endtoend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferResults;
import utils.InferRunner;
public class BoxedPtrTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/errors/npe/boxed_ptr.cpp";
private static ImmutableList<String> inferCmd;
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
@ClassRule
public static DebuggableTemporaryFolder folder =
new DebuggableTemporaryFolder();
@BeforeClass
public static void runInfer() throws InterruptedException, IOException {
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
}
@Test
public void whenInferRunsNullDerefFunctionsErrorIsFound()
throws InterruptedException, IOException, InferException {
String[] procedures = {
"smart_ptr_null_field_deref",
"smart_ptr_null_method_deref",
"smart_ptr_null_method_deref2",
"smart_ptr_result_method_null_deref",
};
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
assertThat(
"Results should contain divide by 0 error",
inferResults,
containsExactly(
NULL_DEREFERENCE,
FILE,
procedures
)
);
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package endtoend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferResults;
import utils.InferRunner;
public class SharedPtrConstructorsTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp";
private static ImmutableList<String> inferCmd;
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
@ClassRule
public static DebuggableTemporaryFolder folder =
new DebuggableTemporaryFolder();
@BeforeClass
public static void runInfer() throws InterruptedException, IOException {
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
}
@Test
public void whenInferRunsNullDerefFunctionsErrorIsFound()
throws InterruptedException, IOException, InferException {
String[] procedures = {
"get_from_base1_nullptr_deref",
"get_from_base2_nullptr_deref",
"get_from_derived1_nullptr_deref",
"get_from_derived2_nullptr_deref",
"get_from_derived3_nullptr_deref",
"get_from_base1_null_f1_deref",
"get_from_base2_null_f1_deref",
"get_from_derived1_null_f1_deref",
"get_from_derived2_null_f1_deref",
"get_from_derived3_null_f1_deref",
};
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
assertThat(
"Results should contain divide by 0 error",
inferResults,
containsExactly(
NULL_DEREFERENCE,
FILE,
procedures
)
);
}
}

@ -0,0 +1,72 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package endtoend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import com.google.common.collect.ImmutableList;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferResults;
import utils.InferRunner;
public class SharedPtrDerefTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_deref.cpp";
private static ImmutableList<String> inferCmd;
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
@ClassRule
public static DebuggableTemporaryFolder folder =
new DebuggableTemporaryFolder();
@BeforeClass
public static void runInfer() throws InterruptedException, IOException {
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
}
@Test
public void whenInferRunsNullDerefFunctionsErrorIsFound()
throws InterruptedException, IOException, InferException {
String[] procedures = {
"empty_ptr_deref",
"nullptr_ptr_deref",
"empty_ptr_field_deref",
"empty_ptr_field_deref2",
"empty_ptr_method_deref",
"reset_ptr_null_deref",
"reset_ptr_null_deref2",
"shared_ptr_copy_null_deref",
"shared_ptr_assign_null_deref",
};
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
assertThat(
"Results should contain divide by 0 error",
inferResults,
containsExactly(
NULL_DEREFERENCE,
FILE,
procedures
)
);
}
}

@ -52,6 +52,9 @@ public class InferRunner {
"/dependencies/java/jackson/jackson-2.2.3.jar",
};
private static final String CXX_INCLUDE_DIR =
"/facebook-clang-plugins/clang/include/c++/v1/";
private static final String IPHONESIMULATOR_ISYSROOT_SUFFIX =
"/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk";
@ -202,6 +205,21 @@ public class InferRunner {
return stdParam;
}
private static String getSystemHeaderFlag(Language lang) {
String headerFlag = "";
switch (lang) {
case CPP:
String current_dir = System.getProperty("user.dir");
headerFlag = new StringBuilder()
.append("-isystem")
.append(current_dir)
.append(CXX_INCLUDE_DIR)
.toString();
break;
}
return headerFlag;
}
public static ImmutableList<String> createClangCommand(
String sourceFile,
Language lang,
@ -226,6 +244,7 @@ public class InferRunner {
.add("-x")
.add(getClangLangOption(lang))
.add(getStdParam(lang))
.add(getSystemHeaderFlag(lang))
.addAll(isysrootOption.build())
.addAll(arcOption.build())
.add("-c")

Loading…
Cancel
Save