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()) ; } } } }