1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/*
This file is part of the clazy static checker.
Copyright (C) 2017 Sergio Martins <smartins@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "AccessSpecifierManager.h"
#include "checkmanager.h"
#include "ClazyContext.h"
#include "FixItExporter.h"
#include "PreProcessorVisitor.h"
#include <clang/AST/ParentMap.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Lex/PreprocessorOptions.h>
#include <clang/Rewrite/Frontend/FixItRewriter.h>
#include <llvm/Support/Regex.h>
#include <stdlib.h>
using namespace std;
using namespace clang;
ClazyContext::ClazyContext(const clang::CompilerInstance &compiler,
const string &headerFilter, const string &ignoreDirs,
string exportFixesFilename,
const std::vector<string> &translationUnitPaths, ClazyOptions opts)
: ci(compiler)
, astContext(ci.getASTContext())
, sm(ci.getSourceManager())
, m_noWerror(getenv("CLAZY_NO_WERROR") != nullptr) // Allows user to make clazy ignore -Werror
, m_checksPromotedToErrors(CheckManager::instance()->checksAsErrors())
, options(opts)
, extraOptions(clazy::splitString(getenv("CLAZY_EXTRA_OPTIONS"), ','))
, m_translationUnitPaths(translationUnitPaths)
{
if (!headerFilter.empty())
headerFilterRegex = std::unique_ptr<llvm::Regex>(new llvm::Regex(headerFilter));
if (!ignoreDirs.empty())
ignoreDirsRegex = std::unique_ptr<llvm::Regex>(new llvm::Regex(ignoreDirs));
if (exportFixesEnabled()) {
if (exportFixesFilename.empty()) {
// Only clazy-standalone sets the filename by argument.
// clazy plugin sets it automatically here:
const FileEntry *fileEntry = sm.getFileEntryForID(sm.getMainFileID());
exportFixesFilename = fileEntry->getName().str() + ".clazy.yaml";
}
const bool isClazyStandalone = !translationUnitPaths.empty();
exporter = new FixItExporter(ci.getDiagnostics(), sm, ci.getLangOpts(),
exportFixesFilename, isClazyStandalone);
}
}
ClazyContext::~ClazyContext()
{
//delete preprocessorVisitor; // we don't own it
delete accessSpecifierManager;
delete parentMap;
static unsigned long count = 0;
count++;
if (exporter) {
// With clazy-standalone we use the same YAML file for all translation-units, so only
// write out the last one. With clazy-plugin there's a YAML file per translation unit.
const bool isClazyPlugin = m_translationUnitPaths.empty();
const bool isLast = count == m_translationUnitPaths.size();
if (isLast || isClazyPlugin)
exporter->Export();
delete exporter;
}
preprocessorVisitor = nullptr;
accessSpecifierManager = nullptr;
parentMap = nullptr;
}
void ClazyContext::enableAccessSpecifierManager()
{
if (!accessSpecifierManager && !usingPreCompiledHeaders())
accessSpecifierManager = new AccessSpecifierManager(this);
}
void ClazyContext::enablePreprocessorVisitor()
{
if (!preprocessorVisitor && !usingPreCompiledHeaders())
preprocessorVisitor = new PreProcessorVisitor(ci);
}
void ClazyContext::enableVisitallTypeDefs()
{
// By default we only process decls from the .cpp file we're processing, not stuff included (for performance)
/// But we might need to process all typedefs, not only the ones in our current .cpp files
m_visitsAllTypeDefs = true;
}
bool ClazyContext::visitsAllTypedefs() const
{
return m_visitsAllTypeDefs;
}
bool ClazyContext::isQt() const
{
static const bool s_isQt = [this] {
for (auto s : ci.getPreprocessorOpts().Macros) {
if (s.first == "QT_CORE_LIB")
return true;
}
return false;
} ();
return s_isQt;
}
|