1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 */ 9 10 #ifndef LO_CLANG_SHARED_PLUGINS 11 12 #include <string> 13 14 #include "plugin.hxx" 15 16 // Having an extern prototype for a method in a module and not actually declaring that method is dodgy. 17 // 18 19 namespace { 20 21 class ExternAndNotDefined: 22 public loplugin::FilteringPlugin<ExternAndNotDefined> 23 { 24 public: ExternAndNotDefined(loplugin::InstantiationData const & data)25 explicit ExternAndNotDefined(loplugin::InstantiationData const & data): FilteringPlugin(data) {} 26 run()27 virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } 28 29 bool VisitFunctionDecl(const FunctionDecl * decl); 30 }; 31 VisitFunctionDecl(const FunctionDecl * functionDecl)32bool ExternAndNotDefined::VisitFunctionDecl(const FunctionDecl * functionDecl) { 33 if (ignoreLocation(functionDecl)) { 34 return true; 35 } 36 if (functionDecl->isDefined() || functionDecl->isPure() 37 || (functionDecl->getLinkageAndVisibility().getLinkage() 38 != ExternalLinkage)) { 39 return true; 40 } 41 //TODO, filtering out anything template for now: 42 if (functionDecl->isDependentContext()) { 43 return true; 44 } 45 CXXRecordDecl const * r = dyn_cast<CXXRecordDecl>(functionDecl->getDeclContext()); 46 if (r != nullptr && r->getTemplateSpecializationKind() != TSK_Undeclared) { 47 return true; 48 } 49 // this is the bison/flex C API, it has to be defined this way 50 std::string functionName = functionDecl->getNameAsString(); 51 if (functionName == "yyerror" || functionName == "yyparse" || functionName == "yylex") { 52 return true; 53 } 54 // see vcl/unx/gtk/app/gtksys.cxx, typename conflicts prevent using the right include 55 if (functionName == "gdk_x11_screen_get_screen_number") { 56 return true; 57 } 58 if (!compiler.getSourceManager().isInMainFile(functionDecl->getLocation())) 59 { 60 return true; 61 } 62 StringRef fileName { getFilenameOfLocation(functionDecl->getLocation()) }; 63 // the filters use some kind of dynamic loading stunt 64 if (loplugin::hasPathnamePrefix(fileName, SRCDIR "/filter/qa/")) { 65 return true; 66 } 67 report( 68 DiagnosticsEngine::Warning, 69 "extern prototype in main file without definition", 70 functionDecl->getLocation()) 71 << functionDecl->getSourceRange(); 72 return true; 73 } 74 75 76 loplugin::Plugin::Registration< ExternAndNotDefined > externandnotdefined("externandnotdefined"); 77 78 } 79 80 #endif // LO_CLANG_SHARED_PLUGINS 81 82 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 83