1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "DeclarationDatabase.h"
18
19 #include <err.h>
20
21 #include <iostream>
22 #include <map>
23 #include <mutex>
24 #include <set>
25 #include <sstream>
26 #include <string>
27 #include <utility>
28
29 #include <clang/AST/AST.h>
30 #include <clang/AST/Attr.h>
31 #include <clang/AST/Mangle.h>
32 #include <clang/AST/RecursiveASTVisitor.h>
33 #include <clang/Frontend/ASTUnit.h>
34 #include <llvm/Support/raw_ostream.h>
35
36 using namespace clang;
37
shouldMangle(MangleContext * mangler,NamedDecl * decl)38 static bool shouldMangle(MangleContext* mangler, NamedDecl* decl) {
39 // Passing a decl with static linkage to the mangler gives incorrect results.
40 // Check some things ourselves before handing it off to the mangler.
41 if (auto FD = dyn_cast<FunctionDecl>(decl)) {
42 if (FD->isExternC()) {
43 return false;
44 }
45
46 if (FD->isInExternCContext()) {
47 return false;
48 }
49 }
50
51 return mangler->shouldMangleDeclName(decl);
52 }
53
54 class Visitor : public RecursiveASTVisitor<Visitor> {
55 HeaderDatabase& database;
56 CompilationType type;
57 SourceManager& src_manager;
58 std::unique_ptr<MangleContext> mangler;
59
60 public:
Visitor(HeaderDatabase & database,CompilationType type,ASTContext & ctx)61 Visitor(HeaderDatabase& database, CompilationType type, ASTContext& ctx)
62 : database(database), type(type), src_manager(ctx.getSourceManager()) {
63 mangler.reset(ItaniumMangleContext::create(ctx, ctx.getDiagnostics()));
64 }
65
getDeclName(NamedDecl * decl)66 std::string getDeclName(NamedDecl* decl) {
67 if (auto var_decl = dyn_cast<VarDecl>(decl)) {
68 if (!var_decl->isFileVarDecl()) {
69 return "<local var>";
70 }
71 }
72
73 // <math.h> maps fool onto foo on 32-bit, since long double is the same as double.
74 if (auto asm_attr = decl->getAttr<AsmLabelAttr>()) {
75 return asm_attr->getLabel();
76 }
77
78 // The decl might not have a name (e.g. bitfields).
79 if (auto identifier = decl->getIdentifier()) {
80 if (shouldMangle(mangler.get(), decl)) {
81 std::string mangled;
82 llvm::raw_string_ostream ss(mangled);
83 mangler->mangleName(decl, ss);
84 return mangled;
85 }
86
87 return identifier->getName();
88 }
89
90 return "<unnamed>";
91 }
92
VisitDeclaratorDecl(DeclaratorDecl * decl,SourceRange range)93 bool VisitDeclaratorDecl(DeclaratorDecl* decl, SourceRange range) {
94 // Skip declarations inside of functions (function arguments, variable declarations inside of
95 // inline functions, etc).
96 if (decl->getParentFunctionOrMethod()) {
97 return true;
98 }
99
100 auto named_decl = dyn_cast<NamedDecl>(decl);
101 if (!named_decl) {
102 return true;
103 }
104
105 std::string declaration_name = getDeclName(named_decl);
106 bool is_extern = named_decl->getFormalLinkage() == ExternalLinkage;
107 bool is_definition = false;
108 bool no_guard = false;
109
110 if (auto function_decl = dyn_cast<FunctionDecl>(decl)) {
111 is_definition = function_decl->isThisDeclarationADefinition();
112 } else if (auto var_decl = dyn_cast<VarDecl>(decl)) {
113 if (!var_decl->isFileVarDecl()) {
114 return true;
115 }
116
117 switch (var_decl->isThisDeclarationADefinition()) {
118 case VarDecl::DeclarationOnly:
119 is_definition = false;
120 break;
121
122 case VarDecl::Definition:
123 is_definition = true;
124 break;
125
126 case VarDecl::TentativeDefinition:
127 // Forbid tentative definitions in headers.
128 fprintf(stderr, "ERROR: declaration '%s' is a tentative definition\n",
129 declaration_name.c_str());
130 decl->dump();
131 abort();
132 }
133 } else {
134 // We only care about function and variable declarations.
135 return true;
136 }
137
138 if (decl->hasAttr<UnavailableAttr>()) {
139 // Skip declarations that exist only for compile-time diagnostics.
140 return true;
141 }
142
143 DeclarationAvailability availability;
144
145 // Find and parse __ANDROID_AVAILABILITY_DUMP__ annotations.
146 for (const AnnotateAttr* attr : decl->specific_attrs<AnnotateAttr>()) {
147 llvm::StringRef annotation = attr->getAnnotation();
148 if (annotation == "versioner_no_guard") {
149 no_guard = true;
150 } else {
151 llvm::SmallVector<llvm::StringRef, 2> fragments;
152 annotation.split(fragments, "=");
153 if (fragments.size() != 2) {
154 continue;
155 }
156
157 auto& global_availability = availability.global_availability;
158 auto& arch_availability = availability.arch_availability;
159 std::map<std::string, std::vector<int*>> prefix_map = {
160 { "introduced_in", { &global_availability.introduced } },
161 { "deprecated_in", { &global_availability.deprecated } },
162 { "obsoleted_in", { &global_availability.obsoleted } },
163 { "introduced_in_arm", { &arch_availability[Arch::arm].introduced } },
164 { "introduced_in_mips", { &arch_availability[Arch::mips].introduced } },
165 { "introduced_in_x86", { &arch_availability[Arch::x86].introduced } },
166 { "introduced_in_32",
167 { &arch_availability[Arch::arm].introduced,
168 &arch_availability[Arch::mips].introduced,
169 &arch_availability[Arch::x86].introduced } },
170 { "introduced_in_64",
171 { &arch_availability[Arch::arm64].introduced,
172 &arch_availability[Arch::mips64].introduced,
173 &arch_availability[Arch::x86_64].introduced } },
174 };
175
176 if (auto it = prefix_map.find(fragments[0]); it != prefix_map.end()) {
177 int value;
178 if (fragments[1].getAsInteger(10, value)) {
179 errx(1, "invalid __ANDROID_AVAILABILITY_DUMP__ annotation: '%s'",
180 annotation.str().c_str());
181 }
182
183 for (int* ptr : it->second) {
184 *ptr = value;
185 }
186 }
187 }
188 }
189
190 auto symbol_it = database.symbols.find(declaration_name);
191 if (symbol_it == database.symbols.end()) {
192 Symbol symbol = {.name = declaration_name };
193 bool dummy;
194 std::tie(symbol_it, dummy) = database.symbols.insert({ declaration_name, symbol });
195 }
196
197 auto expansion_range = src_manager.getExpansionRange(range);
198 auto filename = src_manager.getFilename(expansion_range.getBegin());
199 if (filename != src_manager.getFilename(expansion_range.getEnd())) {
200 errx(1, "expansion range filenames don't match");
201 }
202
203 Location location = {
204 .filename = filename,
205 .start = {
206 .line = src_manager.getExpansionLineNumber(expansion_range.getBegin()),
207 .column = src_manager.getExpansionColumnNumber(expansion_range.getBegin()),
208 },
209 .end = {
210 .line = src_manager.getExpansionLineNumber(expansion_range.getEnd()),
211 .column = src_manager.getExpansionColumnNumber(expansion_range.getEnd()),
212 }
213 };
214
215 // Find or insert an entry for the declaration.
216 if (auto declaration_it = symbol_it->second.declarations.find(location);
217 declaration_it != symbol_it->second.declarations.end()) {
218 if (declaration_it->second.is_extern != is_extern ||
219 declaration_it->second.is_definition != is_definition ||
220 declaration_it->second.no_guard != no_guard) {
221 errx(1, "varying declaration of '%s' at %s:%u:%u", declaration_name.c_str(),
222 location.filename.c_str(), location.start.line, location.start.column);
223 }
224 declaration_it->second.availability.insert(std::make_pair(type, availability));
225 } else {
226 Declaration declaration;
227 declaration.name = declaration_name;
228 declaration.location = location;
229 declaration.is_extern = is_extern;
230 declaration.is_definition = is_definition;
231 declaration.no_guard = no_guard;
232 declaration.availability.insert(std::make_pair(type, availability));
233 symbol_it->second.declarations.insert(std::make_pair(location, declaration));
234 }
235
236 return true;
237 }
238
VisitDeclaratorDecl(DeclaratorDecl * decl)239 bool VisitDeclaratorDecl(DeclaratorDecl* decl) {
240 return VisitDeclaratorDecl(decl, decl->getSourceRange());
241 }
242
TraverseLinkageSpecDecl(LinkageSpecDecl * decl)243 bool TraverseLinkageSpecDecl(LinkageSpecDecl* decl) {
244 // Make sure that we correctly calculate the SourceRange of a declaration that has a non-braced
245 // extern "C"/"C++".
246 if (!decl->hasBraces()) {
247 DeclaratorDecl* child = nullptr;
248 for (auto child_decl : decl->decls()) {
249 if (child != nullptr) {
250 errx(1, "LinkageSpecDecl has multiple children");
251 }
252
253 if (DeclaratorDecl* declarator_decl = dyn_cast<DeclaratorDecl>(child_decl)) {
254 child = declarator_decl;
255 } else {
256 errx(1, "child of LinkageSpecDecl is not a DeclaratorDecl");
257 }
258 }
259
260 return VisitDeclaratorDecl(child, decl->getSourceRange());
261 }
262
263 for (auto child : decl->decls()) {
264 if (!TraverseDecl(child)) {
265 return false;
266 }
267 }
268 return true;
269 }
270 };
271
merge(const DeclarationAvailability & other)272 bool DeclarationAvailability::merge(const DeclarationAvailability& other) {
273 #define check_avail(expr) error |= (!this->expr.empty() && this->expr != other.expr);
274 bool error = false;
275
276 if (!other.global_availability.empty()) {
277 check_avail(global_availability);
278 this->global_availability = other.global_availability;
279 }
280
281 for (Arch arch : supported_archs) {
282 if (!other.arch_availability[arch].empty()) {
283 check_avail(arch_availability[arch]);
284 this->arch_availability[arch] = other.arch_availability[arch];
285 }
286 }
287 #undef check_avail
288
289 return !error;
290 }
291
calculateAvailability(DeclarationAvailability * output) const292 bool Declaration::calculateAvailability(DeclarationAvailability* output) const {
293 DeclarationAvailability avail;
294 for (const auto& it : this->availability) {
295 if (!avail.merge(it.second)) {
296 return false;
297 }
298 }
299 *output = avail;
300 return true;
301 }
302
calculateAvailability(DeclarationAvailability * output) const303 bool Symbol::calculateAvailability(DeclarationAvailability* output) const {
304 DeclarationAvailability avail;
305 for (const auto& it : this->declarations) {
306 // Don't merge availability for inline functions (because they shouldn't have any).
307 if (it.second.is_definition) {
308 continue;
309 }
310
311 DeclarationAvailability decl_availability;
312 if (!it.second.calculateAvailability(&decl_availability)) {
313 return false;
314 abort();
315 }
316
317 if (!avail.merge(decl_availability)) {
318 return false;
319 }
320 }
321 *output = avail;
322 return true;
323 }
324
hasDeclaration(const CompilationType & type) const325 bool Symbol::hasDeclaration(const CompilationType& type) const {
326 for (const auto& decl_it : this->declarations) {
327 for (const auto& compilation_it : decl_it.second.availability) {
328 if (compilation_it.first == type) {
329 return true;
330 }
331 }
332 }
333 return false;
334 }
335
parseAST(CompilationType type,ASTContext & ctx)336 void HeaderDatabase::parseAST(CompilationType type, ASTContext& ctx) {
337 std::unique_lock<std::mutex> lock(this->mutex);
338 Visitor visitor(*this, type, ctx);
339 visitor.TraverseDecl(ctx.getTranslationUnitDecl());
340 }
341
to_string(const AvailabilityValues & av)342 std::string to_string(const AvailabilityValues& av) {
343 std::stringstream ss;
344
345 if (av.introduced != 0) {
346 ss << "introduced = " << av.introduced << ", ";
347 }
348
349 if (av.deprecated != 0) {
350 ss << "deprecated = " << av.deprecated << ", ";
351 }
352
353 if (av.obsoleted != 0) {
354 ss << "obsoleted = " << av.obsoleted << ", ";
355 }
356
357 std::string result = ss.str();
358 if (!result.empty()) {
359 result = result.substr(0, result.length() - 2);
360 }
361 return result;
362 }
363
to_string(const DeclarationType & type)364 std::string to_string(const DeclarationType& type) {
365 switch (type) {
366 case DeclarationType::function:
367 return "function";
368 case DeclarationType::variable:
369 return "variable";
370 case DeclarationType::inconsistent:
371 return "inconsistent";
372 }
373 abort();
374 }
375
to_string(const DeclarationAvailability & decl_av)376 std::string to_string(const DeclarationAvailability& decl_av) {
377 std::stringstream ss;
378 if (!decl_av.global_availability.empty()) {
379 ss << to_string(decl_av.global_availability) << ", ";
380 }
381
382 for (const auto& it : decl_av.arch_availability) {
383 if (!it.second.empty()) {
384 ss << to_string(it.first) << ": " << to_string(it.second) << ", ";
385 }
386 }
387
388 std::string result = ss.str();
389 if (result.size() == 0) {
390 return "no availability";
391 }
392
393 return result.substr(0, result.length() - 2);
394 }
395
to_string(const Location & loc)396 std::string to_string(const Location& loc) {
397 std::stringstream ss;
398 ss << loc.filename << ":" << loc.start.line << ":" << loc.start.column;
399 return ss.str();
400 }
401