Integrate LLVM analysis with infer script.

master
Rohan Jacob-Rao 9 years ago
parent 6f51b8c54b
commit f192b02f01

@ -88,6 +88,8 @@ base_group.add_argument('-nf', '--no-filtering', action='store_true',
help='''Also show the results from the experimental help='''Also show the results from the experimental
checks. Warning: some checks may contain many false checks. Warning: some checks may contain many false
alarms''') alarms''')
base_group.add_argument('-l', '--llvm', action='store_true',
help='Analyze C or C++ file using LLVM translation')
base_group.add_argument('--log_to_stderr', action='store_true', base_group.add_argument('--log_to_stderr', action='store_true',
help='''When set, all logging will go to stderr instead help='''When set, all logging will go to stderr instead

@ -140,6 +140,8 @@ def get_clang_frontend_envvars(args):
env_vars['FCP_DEBUG_MODE'] = '1' env_vars['FCP_DEBUG_MODE'] = '1'
if args.no_failures_allowed: if args.no_failures_allowed:
env_vars['FCP_REPORT_FRONTEND_FAILURE'] = '1' env_vars['FCP_REPORT_FRONTEND_FAILURE'] = '1'
if args.llvm:
env_vars['LLVM_MODE'] = '1'
# export an env variable with all the arguments to pass to InferClang # export an env variable with all the arguments to pass to InferClang
env_vars['FCP_INFER_FRONTEND_ARGS'] = ' '.join(frontend_args) env_vars['FCP_INFER_FRONTEND_ARGS'] = ' '.join(frontend_args)

@ -117,21 +117,29 @@ then
else else
ADD_PLUGIN_FLAG="-add-plugin" ADD_PLUGIN_FLAG="-add-plugin"
fi fi
ATTACH_PLUGIN="1" if [ -z "$LLVM_MODE" ]; then
ATTACH_PLUGIN="1"
fi
IFS=$'\n' IFS=$'\n'
EXTRA_ARGS=("-Xclang" "-load" if [ -n "$ATTACH_PLUGIN" ]; then
"-Xclang" "${PLUGIN_PATH}" EXTRA_ARGS=("-Xclang" "-load"
"-Xclang" "$ADD_PLUGIN_FLAG" "-Xclang" "${PLUGIN_PATH}"
"-Xclang" "${PLUGIN_NAME}" "-Xclang" "$ADD_PLUGIN_FLAG"
"-Xclang" "-plugin-arg-${PLUGIN_NAME}" "-Xclang" "${PLUGIN_NAME}"
"-Xclang" "-" "-Xclang" "-plugin-arg-${PLUGIN_NAME}"
"-Xclang" "-plugin-arg-${PLUGIN_NAME}" "-Xclang" "-"
"-Xclang" "PREPEND_CURRENT_DIR=1") "-Xclang" "-plugin-arg-${PLUGIN_NAME}"
"-Xclang" "PREPEND_CURRENT_DIR=1")
fi
if [ -n "$SYNTAX_ONLY" ]; then if [ -n "$SYNTAX_ONLY" ]; then
EXTRA_ARGS+=("-fsyntax-only") EXTRA_ARGS+=("-fsyntax-only")
fi fi
unset IFS unset IFS
if [ -n "$LLVM_MODE" ]; then
EXTRA_ARGS+=("-o" "-" "-g" "-S" "-emit-llvm")
fi
# using always the original clang command for several reasons: # using always the original clang command for several reasons:
# - to avoid handling the presence/absence of -Xclang if the standard command is used # - to avoid handling the presence/absence of -Xclang if the standard command is used
# - to emit the same command that was captured by this wrapper # - to emit the same command that was captured by this wrapper
@ -140,7 +148,7 @@ then
fi fi
fi fi
if [ -n "$ATTACH_PLUGIN" ]; then if [ -n "$ATTACH_PLUGIN" ] || [ -n "$LLVM_MODE" ]; then
FOBJC_ARC_FLAG=$(has_flag "-fobjc-arc" "${INPUT_ARGUMENTS[@]}") FOBJC_ARC_FLAG=$(has_flag "-fobjc-arc" "${INPUT_ARGUMENTS[@]}")
LANGUAGE=$(get_option_argument "-x" "${INPUT_ARGUMENTS[@]}") LANGUAGE=$(get_option_argument "-x" "${INPUT_ARGUMENTS[@]}")
@ -148,37 +156,43 @@ if [ -n "$ATTACH_PLUGIN" ]; then
if [ "$FOBJC_ARC_FLAG" == 0 ]; then INFER_FRONTEND_ARGS+=("-fobjc-arc"); fi if [ "$FOBJC_ARC_FLAG" == 0 ]; then INFER_FRONTEND_ARGS+=("-fobjc-arc"); fi
[[ "$SOURCE_FILE" = /* ]] || { SOURCE_FILE="${CWD}/$SOURCE_FILE"; } [[ "$SOURCE_FILE" = /* ]] || { SOURCE_FILE="${CWD}/$SOURCE_FILE"; }
INFERCLANG_CMD=(
"${BIN_DIR}/InferClang" if [ -n "$LLVM_MODE" ]; then
"-c" "$SOURCE_FILE" INFER_FRONTEND_CMD=("${BIN_DIR}/InferLLVM")
"-results_dir" "$RESULTS_DIR" INFER_FRONTEND_LOG_FILE="/dev/stdout"
"${INFER_FRONTEND_ARGS[@]}") else
INFER_FRONTEND_CMD=(
INFERCLANG_LOG_FILE="/dev/null" "${BIN_DIR}/InferClang"
"-c" "$SOURCE_FILE"
if [ -n "$DEBUG_MODE" ]; then "-results_dir" "$RESULTS_DIR"
# Emit the clang command with the extra args piped to InferClang "${INFER_FRONTEND_ARGS[@]}")
echo "${CLANG_CMD[@]} " \
"| tee ${OBJECT_FILENAME}.biniou " \ if [ -n "$DEBUG_MODE" ]; then
"| ${INFERCLANG_CMD[@]}" \ # Emit the clang command with the extra args piped to InferClang
> "${OBJECT_FILENAME}${CMD_FILE_EXT}" echo "${CLANG_CMD[@]} " \
echo "bdump -x -d ${ETC_DIR}/clang_ast.dict -w '!!DUMMY!!' ${OBJECT_FILENAME}.biniou " \ "| tee ${OBJECT_FILENAME}.biniou " \
"> ${OBJECT_FILENAME}.bdump" \ "| ${INFER_FRONTEND_CMD[@]}" \
>> "${OBJECT_FILENAME}${CMD_FILE_EXT}" > "${OBJECT_FILENAME}${CMD_FILE_EXT}"
# Emit the InferClang cmd used to run the frontend echo "bdump -x -d ${ETC_DIR}/clang_ast.dict -w '!!DUMMY!!' ${OBJECT_FILENAME}.biniou " \
INFERCLANG_LOG_FILE="${OBJECT_FILENAME}${INFERCLANG_LOG_FILE_EXT}" "> ${OBJECT_FILENAME}.bdump" \
echo "${INFERCLANG_CMD[@]}" > "$INFERCLANG_LOG_FILE" >> "${OBJECT_FILENAME}${CMD_FILE_EXT}"
# Emit the InferClang cmd used to run the frontend
INFER_FRONTEND_LOG_FILE="${OBJECT_FILENAME}${INFERCLANG_LOG_FILE_EXT}"
echo "${INFER_FRONTEND_CMD[@]}" > "$INFER_FRONTEND_LOG_FILE"
else
INFER_FRONTEND_LOG_FILE="/dev/null"
fi
fi fi
# run clang and pipe its output to InferClang, or flush it in case the latter crashes # run clang and pipe its output to InferClang/InferLLVM, or flush it in case the latter crashes
"${CLANG_CMD[@]}" | ("${INFERCLANG_CMD[@]}" || { EC=$?; cat > /dev/null; exit $EC; }) >> "$INFERCLANG_LOG_FILE" 2>&1 "${CLANG_CMD[@]}" | ("${INFER_FRONTEND_CMD[@]}" || { EC=$?; cat > /dev/null; exit $EC; }) >> "$INFER_FRONTEND_LOG_FILE" 2>&1
STATUSES=("${PIPESTATUS[@]}") STATUSES=("${PIPESTATUS[@]}")
STATUS="${STATUSES[0]}" STATUS="${STATUSES[0]}"
INFERCLANG_STATUS="${STATUSES[1]}" INFER_STATUS="${STATUSES[1]}"
# if clang fails, then fail, otherwise, fail with the frontend's exitcode if required # if clang fails, then fail, otherwise, fail with the frontend's exitcode if required
if [ "$STATUS" == 0 ] && [ -n "$REPORT_FRONTEND_FAILURE" ]; then if [ "$STATUS" == 0 ] && [ -n "$REPORT_FRONTEND_FAILURE" ]; then
STATUS="$INFERCLANG_STATUS" STATUS="$INFER_STATUS"
fi fi
else else
"${CLANG_CMD[@]}" "${CLANG_CMD[@]}"

@ -41,16 +41,18 @@ let store_tenv tenv =
Sil.store_tenv_to_file tenv_filename tenv Sil.store_tenv_to_file tenv_filename tenv
let () = try let () = try
if Array.length Sys.argv < 2 then let (input, filename) =
raise (UsageError ("Missing source file as first command line argument.")) if Array.length Sys.argv < 2 then
else (stdin, "stdin") (* need a file name for output files *)
let filename = Sys.argv.(1) in else
let source_file = DB.abs_source_file_from_path filename in let fname = Sys.argv.(1) in
let () = init_global_state source_file in (open_in fname, fname)
let lexbuf = Lexing.from_channel (open_in filename) in in
let prog = LParser.program LLexer.token lexbuf in let source_file = DB.abs_source_file_from_path filename in
(* let pretty = LPretty.pretty_prog prog in *) let () = init_global_state source_file in
let (cfg, cg, tenv) = LTrans.trans_program prog in let lexbuf = Lexing.from_channel input in
store_icfg tenv cg cfg source_file; store_tenv tenv let prog = LParser.program LLexer.token lexbuf in
let (cfg, cg, tenv) = LTrans.trans_program prog in
store_icfg tenv cg cfg source_file; store_tenv tenv
with with
| UsageError msg -> print_string ("Usage error: " ^ msg ^ "\n") | UsageError msg -> print_string ("Usage error: " ^ msg ^ "\n")

Loading…
Cancel
Save