static void include_file(Analyser& analyser, SourceLocation where, bool, std::string const& name) { data& status(analyser.attachment<data>()); if (status.check_) { if (analyser.is_component_header(name) || analyser.is_component_header(analyser.toplevel())) { status.header_seen_ = true; } else if (!status.header_seen_ && analyser.toplevel() != name && builtin != name && command_line != name && "bdes_ident.h" != name && !analyser.is_main()) { analyser.report(where, check_name, "TR09", "Include files precede component header", true); status.check_ = false; } } }
static void open_file(Analyser& analyser, SourceLocation where, const std::string&, const std::string& name) { FileName fn(name); std::string filename = fn.name(); if (analyser.is_component_header(filename) || name == analyser.toplevel()) { const SourceManager &m = analyser.manager(); llvm::StringRef buf = m.getBuffer(m.getFileID(where))->getBuffer(); if (buf.size() == 0) { return; } buf = buf.substr(0, buf.find('\n')).rtrim(); std::string expectcpp("// " + filename); expectcpp.resize(70, ' '); expectcpp += "-*-C++-*-"; std::string expectc("/* " + filename); expectc.resize(69, ' '); expectc += "-*-C-*- */"; if ( !buf.equals(expectcpp) && !buf.equals(expectc) && buf.find("GENERATED") == buf.npos) { std::pair<size_t, size_t> mcpp = mid_mismatch(buf, expectcpp); std::pair<size_t, size_t> mc = mid_mismatch(buf, expectc); std::pair<size_t, size_t> m; std::string expect; if (mcpp.first >= mc.first || mcpp.second >= mc.second) { m = mcpp; expect = expectcpp; } else { m = mc; expect = expectc; } analyser.report(where.getLocWithOffset(m.first), check_name, "HL01", "File headline incorrect", true); analyser.report(where.getLocWithOffset(m.first), check_name, "HL01", "Correct format is\n%0", true, DiagnosticIDs::Note) << expect; if (m.first == 0) { analyser.InsertTextAfter( where.getLocWithOffset(m.first), expect + "\n"); } else { analyser.ReplaceText(analyser.get_line_range(where), expect); } } } }
static void close_file(Analyser& analyser, SourceLocation where, std::string const&, std::string const& name) { if (analyser.is_component_header(name)) { analyser.attachment<data>().line_ = analyser.get_location(where).line(); } }
static void declaration(Analyser& analyser, Decl const* decl) { data& status(analyser.attachment<data>()); if (status.check_) { if (!status.header_seen_ || analyser.is_component_header(analyser.toplevel())) { status.header_seen_ = true; status.line_ = 0; } Location loc(analyser.get_location(decl)); if ((analyser.toplevel() != loc.file() && status.header_seen_) || (analyser.toplevel() == loc.file() && status.line_ < loc.line())) { status.check_ = false; } else if (((analyser.toplevel() != loc.file() && !status.header_seen_) || loc.line() < status.line_) && builtin != loc.file() && command_line != loc.file() && (llvm::dyn_cast<NamedDecl>(decl) == 0 || utils::end(id_names) == std::find(utils::begin(id_names), utils::end(id_names), llvm::dyn_cast<NamedDecl>(decl) ->getNameAsString())) && !analyser.is_main()) { analyser.report(decl, check_name, "TR09", "Declarations precede component header", true); status.check_ = false; } } }
static void check(Analyser& analyser, Decl const* decl) { if (analyser.is_main() && analyser.config()->value("main_namespace_check") == "off") { return; // RETURN } if (analyser.is_global_package()) { return; // RETURN } Location location(analyser.get_location(decl)); NamedDecl const* named(llvm::dyn_cast<NamedDecl>(decl)); if (analyser.is_component(location.file()) && named) { if (llvm::dyn_cast<NamespaceDecl>(decl) || llvm::dyn_cast<UsingDirectiveDecl>(decl)) { // namespace declarations are permissible e.g. for forward declarations. return; // RETURN } else if (TagDecl const* tag = llvm::dyn_cast<TagDecl>(decl)) { // Forward declarations are always permissible but definitions are not. if (!tag->isThisDeclarationADefinition() && analyser.is_component_header(location.file())) { return; // RETURN } } else if (llvm::dyn_cast<NamespaceAliasDecl>(decl) && analyser.is_component_source(decl)) { return; // RETURN } DeclContext const* context(decl->getDeclContext()); std::string name = named->getNameAsString(); if (llvm::dyn_cast<TranslationUnitDecl>(context)) { if (name != "main" && name != "RCSId" && !llvm::dyn_cast<ClassTemplateSpecializationDecl>(decl) && !llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(decl) && name.find("operator new") == std::string::npos && name.find("operator delete") == std::string::npos ) { analyser.report(decl, check_name, "TR04", "Declaration of '%0' at global scope", true) << decl->getSourceRange() << name; } return; // RETURN } NamespaceDecl const* space = llvm::dyn_cast<NamespaceDecl>(context); if (!space) { return; // RETURN } std::string pkgns = analyser.package(); if ( space->isAnonymousNamespace() && llvm::dyn_cast<NamespaceDecl>(space->getDeclContext())) { space = llvm::dyn_cast<NamespaceDecl>(space->getDeclContext()); } if (space->getNameAsString() == analyser.config()->toplevel_namespace()) { // No package namespace. This is OK if no package namespace has // been seen, for the sake of legacy "package_name" components. DeclContext::decl_iterator b = space->decls_begin(); DeclContext::decl_iterator e = space->decls_end(); bool found = false; while (!found && b != e) { const NamespaceDecl *ns = llvm::dyn_cast<NamespaceDecl>(*b++); found = ns && ns->getNameAsString() == analyser.package(); } if (!found) { pkgns = analyser.config()->toplevel_namespace(); } } if (name.length() > 0) { std::string spname = space->getNameAsString(); NamespaceDecl const* outer = space; if (pkgns == analyser.package()) { outer = llvm::dyn_cast<NamespaceDecl>( space->getDeclContext()); } if ((spname != pkgns || !outer || outer->getNameAsString() != analyser.config()->toplevel_namespace()) && ( spname != analyser.config()->toplevel_namespace() || name.find(analyser.package() + '_') != 0 ) && to_lower(spname) != to_lower(analyser.component()) && !llvm::dyn_cast<ClassTemplateSpecializationDecl>(decl) && !llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(decl) && name.find("operator new") == std::string::npos && name.find("operator delete") == std::string::npos && !isSpecialFunction(named) && ( analyser.is_component_header(named) || named->hasLinkage() ) && !analyser.is_ADL_candidate(decl) ) { //-dk:TODO check if this happens in the correct namespace analyser.report(decl, check_name, "TR04", "Declaration of '%0' not within package namespace '%1'", true) << decl->getSourceRange() << name << (analyser.config()->toplevel_namespace() + "::" + analyser.package()) ; } } } }