| 816 | } |
| 817 | |
| 818 | std::pair<bool, std::string> PreprocessFile::evaluateMacro_( |
| 819 | std::string_view name, std::vector<std::string>& actual_args, |
| 820 | PreprocessFile* callingFile, uint32_t callingLine, LoopCheck& loopChecker, |
| 821 | MacroInfo* macroInfo, SpecialInstructions& instructions, |
| 822 | uint32_t embeddedMacroCallLine, PathId embeddedMacroCallFile) { |
| 823 | FileSystem* const fileSystem = FileSystem::getInstance(); |
| 824 | std::string result; |
| 825 | bool found = false; |
| 826 | const std::vector<std::string>& formal_args = macroInfo->m_arguments; |
| 827 | const std::vector<std::string>& orig_body_tokens = macroInfo->m_tokens; |
| 828 | |
| 829 | if (instructions.m_check_macro_loop) { |
| 830 | bool loop = loopChecker.addEdge(callingFile->m_macroId, getId(name)); |
| 831 | if (loop) { |
| 832 | std::vector<SymbolId> loop = loopChecker.reportLoop(); |
| 833 | for (const auto& id : loop) { |
| 834 | MacroInfo* macroInfo2 = m_compilationUnit->getMacroInfo(getSymbol(id)); |
| 835 | if (macroInfo2) { |
| 836 | Location loc(macroInfo2->m_fileId, macroInfo2->m_startLine, |
| 837 | macroInfo2->m_startColumn, id); |
| 838 | Location exloc(macroInfo->m_fileId, macroInfo->m_startLine, |
| 839 | macroInfo->m_startColumn, getId(name)); |
| 840 | Error err(ErrorDefinition::PP_RECURSIVE_MACRO_DEFINITION, loc, exloc); |
| 841 | addError(err); |
| 842 | return std::make_pair(false, |
| 843 | std::string(SymbolTable::getBadSymbol())); |
| 844 | } |
| 845 | } |
| 846 | } |
| 847 | } |
| 848 | // Don't modify the actual tokens of the macro, make a copy... |
| 849 | std::vector<std::string> body_tokens; |
| 850 | for (const std::string& tok : orig_body_tokens) { |
| 851 | if (tok == "``_``") { |
| 852 | body_tokens.push_back("``"); |
| 853 | body_tokens.push_back("_"); |
| 854 | body_tokens.push_back("``"); |
| 855 | } else { |
| 856 | body_tokens.push_back(tok); |
| 857 | } |
| 858 | } |
| 859 | |
| 860 | StringUtils::replaceInTokenVector(body_tokens, "`\"", "\""); |
| 861 | StringUtils::replaceInTokenVector(body_tokens, "`\\`\"", "\\\""); |
| 862 | |
| 863 | // argument substitution |
| 864 | for (std::string& actual_arg : actual_args) { |
| 865 | if (actual_arg.find('`') != std::string::npos) { |
| 866 | actual_arg = evaluateMacroInstance( |
| 867 | actual_arg, callingFile, callingLine, SpecialInstructions::CheckLoop, |
| 868 | SpecialInstructions::AsIsUndefinedMacroInstr::ComplainUndefinedMacro); |
| 869 | } |
| 870 | actual_arg = StringUtils::trim(actual_arg); |
| 871 | } |
| 872 | |
| 873 | if ((actual_args.size() > formal_args.size() && (!m_instructions.m_mute))) { |
| 874 | if (formal_args.empty() && (getFirstNonEmptyToken(body_tokens) == "(")) { |
| 875 | Location loc(macroInfo->m_fileId, macroInfo->m_startLine, |
nothing calls this directly
no test coverage detected