Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: tools/clang/plugins/ChromeClassTester.cpp

Issue 6368055: Commit my clang plugin and fix up documentation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add makefile for thakis Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // A general interface for filtering and only acting on classes in Chromium C++
6 // code.
7
8 #include "ChromeClassTester.h"
9
10 #include "clang/Basic/FileManager.h"
11
12 using namespace clang;
13
14 namespace {
15
16 bool starts_with(const std::string& one, const std::string& two) {
17 return one.substr(0, two.size()) == two;
18 }
19
20 bool ends_with(const std::string& one, const std::string& two) {
21 return one.substr(one.size() - two.size(), two.size()) == two;
22 }
23
24 } // namespace
25
26 ChromeClassTester::ChromeClassTester(CompilerInstance& instance)
27 : instance_(instance),
28 diagnostic_(instance.getDiagnostics()) {
29 banned_namespaces_.push_back("std");
30 banned_namespaces_.push_back("__gnu_cxx");
31
32 banned_directories_.push_back("third_party");
33 banned_directories_.push_back("native_client");
34 banned_directories_.push_back("breakpad");
35 banned_directories_.push_back("courgette");
36 banned_directories_.push_back("ppapi");
37 banned_directories_.push_back("/usr");
38 banned_directories_.push_back("testing");
39 banned_directories_.push_back("googleurl");
40 banned_directories_.push_back("v8");
41 banned_directories_.push_back("sdch");
42
43 // You are standing in a mazy of twisty dependencies, all resolved by
44 // putting everything in the header.
45 banned_directories_.push_back("chrome/test/automation");
46
47 // Used in really low level threading code that probably shouldn't be out of
48 // lined.
49 ignored_record_names_.push_back("ThreadLocalBoolean");
50
51 // A complicated pickle derived struct that is all packed integers.
52 ignored_record_names_.push_back("Header");
53
54 // Part of the GPU system that uses multiple included header
55 // weirdness. Never getting this right.
56 ignored_record_names_.push_back("Validators");
57
58 // RAII class that's simple enough (media/base/callback.h).
59 ignored_record_names_.push_back("AutoTaskRunner");
60 ignored_record_names_.push_back("AutoCallbackRunner");
61
62 // Part of our public interface that nacl and friends use. (Arguably, this
63 // should mean that this is a higher priority but fixing this looks hard.)
64 ignored_record_names_.push_back("PluginVersionInfo");
65 }
66
67 ChromeClassTester::~ChromeClassTester() {}
68
69 void ChromeClassTester::HandleTagDeclDefinition(TagDecl* tag) {
70 if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) {
71 // If this is a POD or a class template or a type dependent on a
72 // templated class, assume there's no ctor/dtor/virtual method
73 // optimization that we can do.
74 if (record->isPOD() ||
75 record->getDescribedClassTemplate() ||
76 record->getTemplateSpecializationKind() ||
77 record->isDependentType())
78 return;
79
80 if (InBannedNamespace(record))
81 return;
82
83 SourceLocation record_location = record->getInnerLocStart();
84 if (InBannedDirectory(record_location))
85 return;
86
87 // For now, due to large amounts of inlining in our unit test code, there's
88 // no way in hell we'll pass our checks but we want to deploy clang plugins
89 // now.
90 //
91 // TODO(erg): Deinline all our test code, and only perform something like
92 // this check for the "virtual" inlining tests on GMOCK code (since all of
93 // that is autogenerated and doesn't specify the "virtual" keyword).
94 if (IsTestCode(record)) {
95 return;
96 }
97
98 // We sadly need to maintain a blacklist of types that violate these
99 // rules, but do so for good reason or due to limitations of this
100 // checker (i.e., we don't handle extern templates very well).
101 if (IsIgnoredType(record))
102 return;
103
104 CheckChromeClass(record_location, record);
105 }
106 }
107
108 void ChromeClassTester::emitWarning(SourceLocation loc, const char* raw_error) {
109 FullSourceLoc full(loc, instance().getSourceManager());
110 std::string err;
111 err = "[chrome-style] ";
112 err += raw_error;
113 unsigned id = diagnostic().getCustomDiagID(Diagnostic::Warning, err);
114 DiagnosticBuilder B = diagnostic().Report(full, id);
115 }
116
117 bool ChromeClassTester::IsTestCode(Decl* record) {
118 if (instance_.hasSourceManager()) {
119 SourceManager& m = instance_.getSourceManager();
120 std::string name = m.getFileEntryForID(m.getMainFileID())->getName();
121 return name.find("test") != name.npos ||
122 name.find("mock") != name.npos;
123 }
124 return false;
125 }
126
127 bool ChromeClassTester::InBannedNamespace(Decl* record) {
128 std::string n = GetNamespace(record);
129 if (n != "") {
130 return std::find(banned_namespaces_.begin(), banned_namespaces_.end(), n)
131 != banned_namespaces_.end();
132 }
133
134 return false;
135 }
136
137 std::string ChromeClassTester::GetNamespace(Decl* record) {
138 return GetNamespaceImpl(record->getDeclContext(), "");
139 }
140
141 std::string ChromeClassTester::GetNamespaceImpl(const DeclContext* context,
142 std::string candidate) {
143 switch (context->getDeclKind()) {
144 case Decl::TranslationUnit: {
145 return candidate;
146 }
147 case Decl::Namespace: {
148 const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
149 std::string name_str;
150 llvm::raw_string_ostream OS(name_str);
151 if (decl->isAnonymousNamespace())
152 OS << "<anonymous namespace>";
153 else
154 OS << decl;
155 return GetNamespaceImpl(context->getParent(),
156 OS.str());
157 }
158 default: {
159 return GetNamespaceImpl(context->getParent(), candidate);
160 }
161 }
162 }
163
164 bool ChromeClassTester::InBannedDirectory(const SourceLocation& loc) {
165 if (loc.isFileID() && loc.isValid()) {
166 bool invalid = false;
167 const char* buffer_name = instance_.getSourceManager().getBufferName(
168 loc, &invalid);
169 if (!invalid && buffer_name) {
170 std::string b(buffer_name);
171
172 // Don't complain about these things in implementation files.
173 if (ends_with(b, ".cc") || ends_with(b, ".cpp")) {
174 return true;
175 }
176
177 // Don't complain about autogenerated protobuf files.
178 if (ends_with(b, ".pb.h")) {
179 return true;
180 }
181
182 // Strip preceding path crap.
183 if (starts_with(b, "./"))
184 b = b.substr(2);
185
186 for (std::vector<std::string>::const_iterator it =
187 banned_directories_.begin();
188 it != banned_directories_.end(); ++it) {
189 if (starts_with(b, *it))
190 return true;
191 }
192 }
193 }
194
195 return false;
196 }
197
198 bool ChromeClassTester::IsIgnoredType(RecordDecl* record) {
199 std::string base_name = record->getNameAsString();
200 for (std::vector<std::string>::const_iterator it =
201 ignored_record_names_.begin();
202 it != ignored_record_names_.end(); ++it) {
203 if (base_name == *it)
204 return true;
205 }
206
207 return false;
208 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698