def check_syntax(self, c_file_name): """ Check the "syntax" of the file -- this is an abuse of terminology, since `fsyntax-only' performs symbol lookup, i.e., if a declaration is missing, an error is thrown. """ cmd = [self.cc, '-fsyntax-only', c_file_name] common_opts = [ '-Werror=incompatible-pointer-types', '-Werror=implicit-function-declaration' ] cmd += common_opts by_cc_opts = { CCompilerFacade.GCC: '-Werror=builtin-declaration-mismatch', CCompilerFacade.Clang: '-Werror=incompatible-library-redeclaration' } cmd.append(by_cc_opts[self.cc_family]) cmd += self.original_options() return execute(CCompilerFacade.ID(), cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def generate_constraints(self, unit: Unit, cc_cmd_summary): """ Generate constraints for a unit. """ cmd = [ PsycheCFacade._GENERATOR, unit.c_file, '-o', unit.cstr_file, '--cc', self.cc, '--cc-std', cc_cmd_summary.c_version ] cmd += CCompilerFacade.defined_macros('--cc-D') cmd += CCompilerFacade.undefined_macros('--cc-U') cmd += cc_cmd_summary.defined_macros('-cc-D ') cmd += cc_cmd_summary.undefined_macros('--cc-U ') cmd += cc_cmd_summary.include_paths('--cc-I ') maybe_append('--no-typedef', self.no_typedef, cmd) maybe_append('--no-heuristic', self.no_heuristic, cmd) if not self.no_stdlib: cmd.append('-p') dir_path = pathlib.Path(__file__).parent.parent.absolute() cmd.append(os.path.join(dir_path, 'libpsychecstd')) code = execute(PsycheCFacade.ID(), cmd) if code != 0: sys.exit( DiagnosticReporter.fatal(CONSTRAINT_GENERATION_FOR_FILE_FAILED, unit.c_file, error=code))
def generate_constraints(self, unit: Unit, cc_opts): """ Generate constraints for a unit. """ cmd = [self.generator, unit.c_file_path, '-o', unit.cstr_file_path, '--cc', self.host_cc, '--cc-std', cc_opts.c_version] cmd += CCompilerFacade.predefined_macros('--cc-D') cmd += CCompilerFacade.undefined_macros('--cc-U') maybe_append('--no-typedef', self.no_typedef, cmd) maybe_append('--no-heuristic', self.no_heuristic, cmd) if not self.no_stdlib: cmd.append('-p') cmd.append('libpsychecstd') ok = execute(PsycheFacade._id, cmd) if ok != 0: sys.exit( DiagnosticReporter.fatal(CONSTRAINT_GENERATION_FOR_FILE_FAILED, unit.c_file_path))
def execute(self): """ Entry point. """ trace_op(Driver._id, flatten(self.cnip_opt['host_cc_cmd'])) if not self.cc.is_supported(): sys.exit(DiagnosticReporter.fatal(HOST_C_COMPILER_NOT_FOUND)) cc_cmd = self.cc.parse_command() if not cc_cmd.out_file_name: gen_dir = '' else: (gen_dir, _) = os.path.split(cc_cmd.out_file_name) if gen_dir: gen_dir += '/' else: gen_dir = '' # The adjusted command that is forwarded to the host C compiler is the # one provided by the user, with input file replaced. new_cmd = self.cnip_opt['host_cc_cmd'] for c_file_path in cc_cmd.sources: if not os.path.isfile(c_file_path): sys.exit( DiagnosticReporter.fatal(FILE_DOES_NOT_EXIST, c_file_path)) if self.cc.check_syntax(c_file_path) == 0: # If there are missing declarations in the source, this check # would've failed. Since it didn't, there's nothing to infer. continue unit = make_unit(c_file_path, gen_dir) self._compile_unit(unit, cc_cmd) trace_op( Driver._id, f'replace {unit.c_file_path} for {unit.cnip_file_path} in command' ) new_cmd = [ w.replace(unit.c_file_path, unit.cnip_file_path) for w in new_cmd ] cmd = [self.cnip_opt['host_cc'], '-x', 'c'] + new_cmd ok = execute(Driver._id, cmd) if ok != 0: sys.exit( DiagnosticReporter.fatal(HOST_C_COMPILER_FORWARDING_FAILED)) return 0
def preprocess(self, c_file_name, pp_file_name): """ Preprocess the file. """ cmd = [self.host_cc, '-E', '-x', 'c', c_file_name, '-o', pp_file_name] cmd += CCompilerFacade.predefined_macros('-D') cmd += CCompilerFacade.undefined_macros('-U') ok = execute(CCompilerFacade._id, cmd) if ok != 0: sys.exit( DiagnosticReporter.fatal(PREPROCESSING_FILE_FAILED, c_file_name))
def execute(self): """ Entry point. """ debug(Driver.ID(), flatten(self.cnip_opts['cc_cmd_line'])) if not self.cc.is_supported(): sys.exit(DiagnosticReporter.fatal(HOST_C_COMPILER_NOT_FOUND)) cc_cmd = self.cc.parse_command() if not cc_cmd.out_file_name: gen_dir = '' else: (gen_dir, _) = os.path.split(cc_cmd.out_file_name) if gen_dir: gen_dir += '/' else: gen_dir = '' # The new command that is forwarded to the host C compiler is the # original one provided by the user, with the input file replaced. new_cmd = self.cnip_opts['cc_cmd_line'] for c_file in cc_cmd.c_files: if not os.path.isfile(c_file): sys.exit(DiagnosticReporter.fatal(FILE_DOES_NOT_EXIST, c_file)) if self.cc.check_syntax(c_file) == 0: # If there are missing declarations in the source, this check # would've failed. Since it didn't, there's nothing to infer. continue unit = make_unit(c_file, gen_dir) self._compile_unit(unit, cc_cmd) debug(Driver.ID(), f'replace {unit.c_file} for {unit.cnip_file} in command') new_cmd = [w.replace(unit.c_file, unit.cnip_file) for w in new_cmd] cmd = [self.cnip_opts['cc']] + new_cmd code = execute(Driver.ID(), cmd) if code != 0: sys.exit( DiagnosticReporter.fatal(HOST_C_COMPILER_FORWARDING_FAILED)) return 0
def solve_constraints(self, unit: Unit): """ Solve the constraint. """ cmd = [ PsycheCFacade._SOLVER, '--', '-i', unit.cstr_file, '-o', unit.cnip_file ] if not self.no_stdlib: cmd.append('--match-stdlib=approx') ok = execute(PsycheCFacade.ID(), cmd) if ok != 0: sys.exit( DiagnosticReporter.fatal(CONSTRAINT_SOLVING_FOR_FILE_FAILED, unit.c_file))
def preprocess(self, c_file_name, pp_file_name): """ Preprocess the file. """ cmd = [self.cc, '-E', '-x', 'c', c_file_name, '-o', pp_file_name] cmd += CCompilerFacade.defined_macros('-D') cmd += CCompilerFacade.undefined_macros('-U') cmd += self.original_options() code = execute(CCompilerFacade.ID(), cmd) if code != 0: sys.exit( DiagnosticReporter.fatal(PREPROCESSING_FILE_FAILED, c_file_name))