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 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: 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 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 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 if (annotation == "introduced_in_future") { 151 // Tag the compiled-for arch, since this can vary across archs. 152 availability.arch_availability[type.arch].future = true; 153 } else { 154 llvm::SmallVector<llvm::StringRef, 2> fragments; 155 annotation.split(fragments, "="); 156 if (fragments.size() != 2) { 157 continue; 158 } 159 160 auto& global_availability = availability.global_availability; 161 auto& arch_availability = availability.arch_availability; 162 std::map<std::string, std::vector<int*>> prefix_map = { 163 { "introduced_in", { &global_availability.introduced } }, 164 { "deprecated_in", { &global_availability.deprecated } }, 165 { "obsoleted_in", { &global_availability.obsoleted } }, 166 { "introduced_in_arm", { &arch_availability[Arch::arm].introduced } }, 167 { "introduced_in_mips", { &arch_availability[Arch::mips].introduced } }, 168 { "introduced_in_x86", { &arch_availability[Arch::x86].introduced } }, 169 { "introduced_in_32", 170 { &arch_availability[Arch::arm].introduced, 171 &arch_availability[Arch::mips].introduced, 172 &arch_availability[Arch::x86].introduced } }, 173 { "introduced_in_64", 174 { &arch_availability[Arch::arm64].introduced, 175 &arch_availability[Arch::mips64].introduced, 176 &arch_availability[Arch::x86_64].introduced } }, 177 }; 178 179 if (auto it = prefix_map.find(fragments[0]); it != prefix_map.end()) { 180 int value; 181 if (fragments[1].getAsInteger(10, value)) { 182 errx(1, "invalid __ANDROID_AVAILABILITY_DUMP__ annotation: '%s'", 183 annotation.str().c_str()); 184 } 185 186 for (int* ptr : it->second) { 187 *ptr = value; 188 } 189 } 190 } 191 } 192 193 auto symbol_it = database.symbols.find(declaration_name); 194 if (symbol_it == database.symbols.end()) { 195 Symbol symbol = {.name = declaration_name }; 196 bool dummy; 197 std::tie(symbol_it, dummy) = database.symbols.insert({ declaration_name, symbol }); 198 } 199 200 auto expansion_range = src_manager.getExpansionRange(range); 201 auto filename = src_manager.getFilename(expansion_range.getBegin()); 202 if (filename != src_manager.getFilename(expansion_range.getEnd())) { 203 errx(1, "expansion range filenames don't match"); 204 } 205 206 Location location = { 207 .filename = filename, 208 .start = { 209 .line = src_manager.getExpansionLineNumber(expansion_range.getBegin()), 210 .column = src_manager.getExpansionColumnNumber(expansion_range.getBegin()), 211 }, 212 .end = { 213 .line = src_manager.getExpansionLineNumber(expansion_range.getEnd()), 214 .column = src_manager.getExpansionColumnNumber(expansion_range.getEnd()), 215 } 216 }; 217 218 // Find or insert an entry for the declaration. 219 if (auto declaration_it = symbol_it->second.declarations.find(location); 220 declaration_it != symbol_it->second.declarations.end()) { 221 if (declaration_it->second.is_extern != is_extern || 222 declaration_it->second.is_definition != is_definition || 223 declaration_it->second.no_guard != no_guard) { 224 errx(1, "varying declaration of '%s' at %s:%u:%u", declaration_name.c_str(), 225 location.filename.c_str(), location.start.line, location.start.column); 226 } 227 declaration_it->second.availability.insert(std::make_pair(type, availability)); 228 } else { 229 Declaration declaration; 230 declaration.name = declaration_name; 231 declaration.location = location; 232 declaration.is_extern = is_extern; 233 declaration.is_definition = is_definition; 234 declaration.no_guard = no_guard; 235 declaration.availability.insert(std::make_pair(type, availability)); 236 symbol_it->second.declarations.insert(std::make_pair(location, declaration)); 237 } 238 239 return true; 240 } 241 242 bool VisitDeclaratorDecl(DeclaratorDecl* decl) { 243 return VisitDeclaratorDecl(decl, decl->getSourceRange()); 244 } 245 246 bool TraverseLinkageSpecDecl(LinkageSpecDecl* decl) { 247 // Make sure that we correctly calculate the SourceRange of a declaration that has a non-braced 248 // extern "C"/"C++". 249 if (!decl->hasBraces()) { 250 DeclaratorDecl* child = nullptr; 251 for (auto child_decl : decl->decls()) { 252 if (child != nullptr) { 253 errx(1, "LinkageSpecDecl has multiple children"); 254 } 255 256 if (DeclaratorDecl* declarator_decl = dyn_cast<DeclaratorDecl>(child_decl)) { 257 child = declarator_decl; 258 } else { 259 errx(1, "child of LinkageSpecDecl is not a DeclaratorDecl"); 260 } 261 } 262 263 return VisitDeclaratorDecl(child, decl->getSourceRange()); 264 } 265 266 for (auto child : decl->decls()) { 267 if (!TraverseDecl(child)) { 268 return false; 269 } 270 } 271 return true; 272 } 273 }; 274 275 bool DeclarationAvailability::merge(const DeclarationAvailability& other) { 276 #define check_avail(expr) error |= (!this->expr.empty() && this->expr != other.expr); 277 bool error = false; 278 279 if (!other.global_availability.empty()) { 280 check_avail(global_availability); 281 this->global_availability = other.global_availability; 282 } 283 284 for (Arch arch : supported_archs) { 285 if (!other.arch_availability[arch].empty()) { 286 check_avail(arch_availability[arch]); 287 this->arch_availability[arch] = other.arch_availability[arch]; 288 } 289 } 290 #undef check_avail 291 292 return !error; 293 } 294 295 bool Declaration::calculateAvailability(DeclarationAvailability* output) const { 296 DeclarationAvailability avail; 297 for (const auto& it : this->availability) { 298 if (!avail.merge(it.second)) { 299 return false; 300 } 301 } 302 *output = avail; 303 return true; 304 } 305 306 bool Symbol::calculateAvailability(DeclarationAvailability* output) const { 307 DeclarationAvailability avail; 308 for (const auto& it : this->declarations) { 309 // Don't merge availability for inline functions (because they shouldn't have any). 310 if (it.second.is_definition) { 311 continue; 312 } 313 314 DeclarationAvailability decl_availability; 315 if (!it.second.calculateAvailability(&decl_availability)) { 316 return false; 317 abort(); 318 } 319 320 if (!avail.merge(decl_availability)) { 321 return false; 322 } 323 } 324 *output = avail; 325 return true; 326 } 327 328 bool Symbol::hasDeclaration(const CompilationType& type) const { 329 for (const auto& decl_it : this->declarations) { 330 for (const auto& compilation_it : decl_it.second.availability) { 331 if (compilation_it.first == type) { 332 return true; 333 } 334 } 335 } 336 return false; 337 } 338 339 void HeaderDatabase::parseAST(CompilationType type, ASTContext& ctx) { 340 std::unique_lock<std::mutex> lock(this->mutex); 341 Visitor visitor(*this, type, ctx); 342 visitor.TraverseDecl(ctx.getTranslationUnitDecl()); 343 } 344 345 std::string to_string(const AvailabilityValues& av) { 346 std::stringstream ss; 347 348 if (av.future) { 349 ss << "future, "; 350 } 351 352 if (av.introduced != 0) { 353 ss << "introduced = " << av.introduced << ", "; 354 } 355 356 if (av.deprecated != 0) { 357 ss << "deprecated = " << av.deprecated << ", "; 358 } 359 360 if (av.obsoleted != 0) { 361 ss << "obsoleted = " << av.obsoleted << ", "; 362 } 363 364 std::string result = ss.str(); 365 if (!result.empty()) { 366 result = result.substr(0, result.length() - 2); 367 } 368 return result; 369 } 370 371 std::string to_string(const DeclarationType& type) { 372 switch (type) { 373 case DeclarationType::function: 374 return "function"; 375 case DeclarationType::variable: 376 return "variable"; 377 case DeclarationType::inconsistent: 378 return "inconsistent"; 379 } 380 abort(); 381 } 382 383 std::string to_string(const DeclarationAvailability& decl_av) { 384 std::stringstream ss; 385 if (!decl_av.global_availability.empty()) { 386 ss << to_string(decl_av.global_availability) << ", "; 387 } 388 389 for (const auto& it : decl_av.arch_availability) { 390 if (!it.second.empty()) { 391 ss << to_string(it.first) << ": " << to_string(it.second) << ", "; 392 } 393 } 394 395 std::string result = ss.str(); 396 if (result.size() == 0) { 397 return "no availability"; 398 } 399 400 return result.substr(0, result.length() - 2); 401 } 402 403 std::string to_string(const Location& loc) { 404 std::stringstream ss; 405 ss << loc.filename << ":" << loc.start.line << ":" << loc.start.column; 406 return ss.str(); 407 } 408