nss: upgrade to release 3.73
[LibreOffice.git] / compilerplugins / clang / duplicate-defines.cxx
blob74a95f2ccad73fb66995f4eb96ba63b8132b15ba
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * Based on LLVM/Clang.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
12 #include <cassert>
13 #include <iostream>
14 #include <unordered_map>
16 #include "plugin.hxx"
18 #include <clang/Frontend/CompilerInstance.h>
19 #include <clang/Frontend/FrontendActions.h>
20 #include <clang/Tooling/CommonOptionsParser.h>
21 #include <clang/Tooling/Refactoring.h>
22 #include <llvm/Support/Signals.h>
24 /// Finds duplicated preprocessor defines, which generally indicate that some definition
25 /// needs to be centralised somewhere.
27 namespace
29 struct Entry
31 clang::SourceLocation m_aLoc;
34 class DuplicateDefines : public clang::PPCallbacks, public loplugin::Plugin
36 public:
37 explicit DuplicateDefines(const loplugin::InstantiationData& data);
38 virtual void run() override;
39 void MacroDefined(const Token& MacroNameTok, const MacroDirective* MD) override;
40 void MacroUndefined(const Token& MacroNameTok, const MacroDefinition& MD,
41 const MacroDirective* Undef) override;
42 enum
44 isPPCallback = true
47 private:
48 clang::Preprocessor& m_rPP;
49 std::unordered_map<std::string, Entry> m_aDefMap;
52 DuplicateDefines::DuplicateDefines(const loplugin::InstantiationData& data)
53 : Plugin(data)
54 , m_rPP(compiler.getPreprocessor())
56 compiler.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(this));
59 void DuplicateDefines::run()
61 // nothing, only check preprocessor usage
64 void DuplicateDefines::MacroDefined(const Token& rMacroNameTok, const MacroDirective*)
66 auto aLoc = rMacroNameTok.getLocation();
67 if (ignoreLocation(aLoc))
68 return;
70 std::string aMacroName = m_rPP.getSpelling(rMacroNameTok);
72 // some testing macro
73 if (aMacroName == "RTL_STRING_CONST_FUNCTION")
74 return;
75 if (aMacroName == "rtl")
76 return;
77 // we replicate these macros in all the .hrc files
78 if (aMacroName == "NC_" || aMacroName == "NNC_")
79 return;
80 // We define this prior to including <windows.h>:
81 if (aMacroName == "WIN32_LEAN_AND_MEAN")
83 return;
85 // TODO no obvious fix for these
86 if (aMacroName == "FID_SEARCH_NOW" || aMacroName == "FID_SVX_START" || aMacroName == "FN_PARAM")
87 return;
88 // ignore for now, requires adding too many includes to sw/
89 if (aMacroName == "MM50")
90 return;
92 // ignore for now, we have the same define in svx and sw, but I can't remove one of them because
93 // they reference strings in different resource bundles
94 if (aMacroName == "STR_UNDO_COL_DELETE" || aMacroName == "STR_UNDO_ROW_DELETE"
95 || aMacroName == "STR_TABLE_NUMFORMAT" || aMacroName == "STR_DELETE")
96 return;
98 if (m_aDefMap.emplace(aMacroName, Entry{ aLoc }).second)
100 return;
103 // Happens e.g. with macros defined in include/premac.h, which is intended to be included
104 // (without include guards) multiple times:
105 auto const other = m_aDefMap[aMacroName].m_aLoc;
106 assert(aLoc == compiler.getSourceManager().getSpellingLoc(aLoc));
107 assert(other == compiler.getSourceManager().getSpellingLoc(other));
108 if ((compiler.getSourceManager().getFilename(aLoc)
109 == compiler.getSourceManager().getFilename(other))
110 && (compiler.getSourceManager().getSpellingLineNumber(aLoc)
111 == compiler.getSourceManager().getSpellingLineNumber(other))
112 && (compiler.getSourceManager().getSpellingColumnNumber(aLoc)
113 == compiler.getSourceManager().getSpellingColumnNumber(other)))
115 return;
118 report(DiagnosticsEngine::Warning, "duplicate defines", aLoc);
119 report(DiagnosticsEngine::Note, "previous define", other);
122 void DuplicateDefines::MacroUndefined(const Token& rMacroNameTok, const MacroDefinition& /*MD*/,
123 const MacroDirective* /*Undef*/)
125 auto aLoc = rMacroNameTok.getLocation();
126 if (ignoreLocation(aLoc))
127 return;
129 std::string aMacroName = m_rPP.getSpelling(rMacroNameTok);
130 m_aDefMap.erase(aMacroName);
133 loplugin::Plugin::Registration<DuplicateDefines> X("duplicatedefines", true);
136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */