| 3731 | } |
| 3732 | |
| 3733 | const Check::FileInfo *CheckClass::getFileInfo(const Tokenizer &tokenizer, const Settings& /*settings*/, const std::string& currentConfig) const |
| 3734 | { |
| 3735 | if (!tokenizer.isCPP()) |
| 3736 | return nullptr; |
| 3737 | |
| 3738 | // One definition rule |
| 3739 | std::vector<MyFileInfo::NameLoc> classDefinitions; |
| 3740 | for (const Scope * classScope : tokenizer.getSymbolDatabase()->classAndStructScopes) { |
| 3741 | if (classScope->isAnonymous()) |
| 3742 | continue; |
| 3743 | |
| 3744 | if (classScope->classDef && Token::simpleMatch(classScope->classDef->previous(), ">")) |
| 3745 | continue; |
| 3746 | |
| 3747 | // the full definition must be compared |
| 3748 | const bool fullDefinition = std::all_of(classScope->functionList.cbegin(), |
| 3749 | classScope->functionList.cend(), |
| 3750 | [](const Function& f) { |
| 3751 | return f.hasBody(); |
| 3752 | }); |
| 3753 | if (!fullDefinition) |
| 3754 | continue; |
| 3755 | |
| 3756 | std::string name; |
| 3757 | const Scope *scope = classScope; |
| 3758 | while (scope->isClassOrStruct() && !classScope->className.empty()) { |
| 3759 | if (Token::Match(scope->classDef, "struct|class %name% :: %name%")) { |
| 3760 | // TODO handle such classnames |
| 3761 | name.clear(); |
| 3762 | break; |
| 3763 | } |
| 3764 | name = scope->className + "::" + name; |
| 3765 | scope = scope->nestedIn; |
| 3766 | } |
| 3767 | if (name.empty()) |
| 3768 | continue; |
| 3769 | name.erase(name.size() - 2); |
| 3770 | if (scope->type != ScopeType::eGlobal) |
| 3771 | continue; |
| 3772 | |
| 3773 | MyFileInfo::NameLoc nameLoc; |
| 3774 | nameLoc.className = std::move(name); |
| 3775 | nameLoc.fileName = tokenizer.list.file(classScope->classDef); |
| 3776 | nameLoc.lineNumber = classScope->classDef->linenr(); |
| 3777 | nameLoc.column = classScope->classDef->column(); |
| 3778 | |
| 3779 | // Calculate hash from the full class/struct definition |
| 3780 | std::string def; |
| 3781 | for (const Token *tok = classScope->classDef; tok != classScope->bodyEnd; tok = tok->next()) |
| 3782 | def += tok->str(); |
| 3783 | for (const Function &f: classScope->functionList) { |
| 3784 | if (f.functionScope && f.functionScope->nestedIn != classScope) { |
| 3785 | for (const Token *tok = f.functionScope->bodyStart; tok != f.functionScope->bodyEnd; tok = tok->next()) |
| 3786 | def += tok->str(); |
| 3787 | } |
| 3788 | } |
| 3789 | nameLoc.hash = std::hash<std::string> {}(def); |
| 3790 | nameLoc.configuration = currentConfig; |