blob: 4ec15d9638940c209c43034d810dd50bae152391 [file] [log] [blame]
Josh Gaobf8a2852016-05-27 11:59:09 -07001/*
Elliott Hughesdfb74c52016-10-24 12:53:17 -07002 * Copyright (C) 2016 The Android Open Source Project
Josh Gaobf8a2852016-05-27 11:59:09 -07003 *
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 *
Elliott Hughesdfb74c52016-10-24 12:53:17 -07008 * http://www.apache.org/licenses/LICENSE-2.0
Josh Gaobf8a2852016-05-27 11:59:09 -07009 *
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#pragma once
18
Josh Gao566735d2016-08-02 15:07:32 -070019#include <stdio.h>
20
Josh Gaobf8a2852016-05-27 11:59:09 -070021#include <map>
Josh Gaobfb6bae2016-07-15 17:25:21 -070022#include <mutex>
Josh Gaobf8a2852016-05-27 11:59:09 -070023#include <set>
24#include <string>
25#include <vector>
26
27#include <llvm/ADT/StringRef.h>
28
Josh Gaobfb6bae2016-07-15 17:25:21 -070029#include "Arch.h"
Josh Gaobf8a2852016-05-27 11:59:09 -070030#include "Utils.h"
31
Josh Gaobfb6bae2016-07-15 17:25:21 -070032namespace clang {
Josh Gao16016df2016-11-07 18:27:16 -080033class ASTContext;
Josh Gaobfb6bae2016-07-15 17:25:21 -070034class Decl;
35}
36
Josh Gaobf8a2852016-05-27 11:59:09 -070037enum class DeclarationType {
38 function,
39 variable,
40 inconsistent,
41};
42
Josh Gaobf8a2852016-05-27 11:59:09 -070043struct CompilationType {
Josh Gaobfb6bae2016-07-15 17:25:21 -070044 Arch arch;
Josh Gaobf8a2852016-05-27 11:59:09 -070045 int api_level;
Josh Gaoa77b3a92016-08-15 16:39:27 -070046 int file_offset_bits;
Josh Gaobf8a2852016-05-27 11:59:09 -070047
48 private:
49 auto tie() const {
Josh Gaoa77b3a92016-08-15 16:39:27 -070050 return std::tie(arch, api_level, file_offset_bits);
Josh Gaobf8a2852016-05-27 11:59:09 -070051 }
52
53 public:
54 bool operator<(const CompilationType& other) const {
55 return tie() < other.tie();
56 }
57
58 bool operator==(const CompilationType& other) const {
59 return tie() == other.tie();
60 }
Josh Gaobf8a2852016-05-27 11:59:09 -070061};
62
Josh Gaobfb6bae2016-07-15 17:25:21 -070063std::string to_string(const CompilationType& type);
64
65struct AvailabilityValues {
66 bool future = false;
Josh Gaobf8a2852016-05-27 11:59:09 -070067 int introduced = 0;
68 int deprecated = 0;
69 int obsoleted = 0;
70
Josh Gaobfb6bae2016-07-15 17:25:21 -070071 bool empty() const {
72 return !(future || introduced || deprecated || obsoleted);
Josh Gao173e7c02016-06-03 13:38:00 -070073 }
74
Josh Gaobfb6bae2016-07-15 17:25:21 -070075 bool operator==(const AvailabilityValues& rhs) const {
76 return std::tie(introduced, deprecated, obsoleted) ==
77 std::tie(rhs.introduced, rhs.deprecated, rhs.obsoleted);
78 }
79
80 bool operator!=(const AvailabilityValues& rhs) const {
81 return !(*this == rhs);
82 }
83};
84
85std::string to_string(const AvailabilityValues& av);
86
87struct DeclarationAvailability {
88 AvailabilityValues global_availability;
89 ArchMap<AvailabilityValues> arch_availability;
90
Josh Gao173e7c02016-06-03 13:38:00 -070091 bool empty() const {
Josh Gaobfb6bae2016-07-15 17:25:21 -070092 if (!global_availability.empty()) {
93 return false;
94 }
Josh Gao173e7c02016-06-03 13:38:00 -070095
Josh Gao16057882016-08-02 14:54:09 -070096 for (const auto& it : arch_availability) {
Josh Gaobfb6bae2016-07-15 17:25:21 -070097 if (!it.second.empty()) {
98 return false;
99 }
100 }
101
102 return true;
Josh Gao173e7c02016-06-03 13:38:00 -0700103 }
104
105 bool operator==(const DeclarationAvailability& rhs) const {
Josh Gaobfb6bae2016-07-15 17:25:21 -0700106 return std::tie(global_availability, arch_availability) ==
107 std::tie(rhs.global_availability, rhs.arch_availability);
Josh Gao173e7c02016-06-03 13:38:00 -0700108 }
109
110 bool operator!=(const DeclarationAvailability& rhs) const {
111 return !(*this == rhs);
112 }
113
Josh Gaobfb6bae2016-07-15 17:25:21 -0700114 // Returns false if the availability declarations conflict.
115 bool merge(const DeclarationAvailability& other);
Josh Gaobf8a2852016-05-27 11:59:09 -0700116};
117
Josh Gaobfb6bae2016-07-15 17:25:21 -0700118std::string to_string(const DeclarationAvailability& decl_av);
119
120struct FileLocation {
121 unsigned line;
Josh Gaobf8a2852016-05-27 11:59:09 -0700122 unsigned column;
Josh Gaobf8a2852016-05-27 11:59:09 -0700123
Josh Gaobfb6bae2016-07-15 17:25:21 -0700124 bool operator<(const FileLocation& rhs) const {
125 return std::tie(line, column) < std::tie(rhs.line, rhs.column);
Josh Gaobf8a2852016-05-27 11:59:09 -0700126 }
127
Josh Gaobfb6bae2016-07-15 17:25:21 -0700128 bool operator==(const FileLocation& rhs) const {
129 return std::tie(line, column) == std::tie(rhs.line, rhs.column);
Josh Gao173e7c02016-06-03 13:38:00 -0700130 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700131};
132
Josh Gaobfb6bae2016-07-15 17:25:21 -0700133struct Location {
134 std::string filename;
135 FileLocation start;
136 FileLocation end;
137
138 bool operator<(const Location& rhs) const {
139 return std::tie(filename, start, end) < std::tie(rhs.filename, rhs.start, rhs.end);
140 }
141};
142
143std::string to_string(const Location& loc);
144
Josh Gaobf8a2852016-05-27 11:59:09 -0700145struct Declaration {
Josh Gao16057882016-08-02 14:54:09 -0700146 std::string name;
Josh Gaobfb6bae2016-07-15 17:25:21 -0700147 Location location;
Josh Gaobf8a2852016-05-27 11:59:09 -0700148
Josh Gaobfb6bae2016-07-15 17:25:21 -0700149 bool is_extern;
150 bool is_definition;
Josh Gaofff29fe2016-09-07 18:29:08 -0700151 bool no_guard;
Josh Gaobfb6bae2016-07-15 17:25:21 -0700152 std::map<CompilationType, DeclarationAvailability> availability;
153
154 bool calculateAvailability(DeclarationAvailability* output) const;
155 bool operator<(const Declaration& rhs) const {
156 return location < rhs.location;
Josh Gaobf8a2852016-05-27 11:59:09 -0700157 }
158
Josh Gao566735d2016-08-02 15:07:32 -0700159 void dump(const std::string& base_path = "", FILE* out = stdout, unsigned indent = 0) const {
Josh Gaobfb6bae2016-07-15 17:25:21 -0700160 std::string indent_str(indent, ' ');
Josh Gao566735d2016-08-02 15:07:32 -0700161 fprintf(out, "%s", indent_str.c_str());
Josh Gaobf8a2852016-05-27 11:59:09 -0700162
Josh Gao566735d2016-08-02 15:07:32 -0700163 fprintf(out, "%s ", is_extern ? "extern" : "static");
164 fprintf(out, "%s ", is_definition ? "definition" : "declaration");
Josh Gaofff29fe2016-09-07 18:29:08 -0700165 if (no_guard) {
166 fprintf(out, "no_guard ");
167 }
Josh Gao566735d2016-08-02 15:07:32 -0700168 fprintf(out, "@ %s:%u:%u", StripPrefix(location.filename, base_path).str().c_str(),
169 location.start.line, location.start.column);
Josh Gaobfb6bae2016-07-15 17:25:21 -0700170
171 if (!availability.empty()) {
172 DeclarationAvailability avail;
173
Josh Gao566735d2016-08-02 15:07:32 -0700174 fprintf(out, "\n%s ", indent_str.c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700175 if (!calculateAvailability(&avail)) {
Josh Gao566735d2016-08-02 15:07:32 -0700176 fprintf(out, "invalid availability");
Josh Gaobfb6bae2016-07-15 17:25:21 -0700177 } else {
Josh Gao566735d2016-08-02 15:07:32 -0700178 fprintf(out, "%s", to_string(avail).c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700179 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700180 }
181 }
182};
183
Josh Gaobfb6bae2016-07-15 17:25:21 -0700184struct Symbol {
185 std::string name;
186 std::map<Location, Declaration> declarations;
Josh Gaobf8a2852016-05-27 11:59:09 -0700187
Josh Gaobfb6bae2016-07-15 17:25:21 -0700188 bool calculateAvailability(DeclarationAvailability* output) const;
189 bool hasDeclaration(const CompilationType& type) const;
Josh Gaobf8a2852016-05-27 11:59:09 -0700190
Josh Gaobfb6bae2016-07-15 17:25:21 -0700191 bool operator<(const Symbol& rhs) const {
192 return name < rhs.name;
193 }
194
195 bool operator==(const Symbol& rhs) const {
196 return name == rhs.name;
197 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700198
Josh Gao566735d2016-08-02 15:07:32 -0700199 void dump(const std::string& base_path = "", FILE* out = stdout) const {
Josh Gaobfb6bae2016-07-15 17:25:21 -0700200 DeclarationAvailability availability;
201 bool valid_availability = calculateAvailability(&availability);
Josh Gao566735d2016-08-02 15:07:32 -0700202 fprintf(out, " %s: ", name.c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700203
204 if (valid_availability) {
Josh Gao566735d2016-08-02 15:07:32 -0700205 fprintf(out, "%s\n", to_string(availability).c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700206 } else {
Josh Gao566735d2016-08-02 15:07:32 -0700207 fprintf(out, "invalid\n");
Josh Gaobfb6bae2016-07-15 17:25:21 -0700208 }
209
Josh Gaobfb6bae2016-07-15 17:25:21 -0700210 for (auto& it : declarations) {
211 it.second.dump(base_path, out, 4);
Josh Gao566735d2016-08-02 15:07:32 -0700212 fprintf(out, "\n");
Josh Gaobfb6bae2016-07-15 17:25:21 -0700213 }
214 }
215};
216
217class HeaderDatabase {
218 std::mutex mutex;
219
220 public:
221 std::map<std::string, Symbol> symbols;
222
Josh Gao16016df2016-11-07 18:27:16 -0800223 void parseAST(CompilationType type, clang::ASTContext& ast);
Josh Gaobfb6bae2016-07-15 17:25:21 -0700224
Josh Gao566735d2016-08-02 15:07:32 -0700225 void dump(const std::string& base_path = "", FILE* out = stdout) const {
226 fprintf(out, "HeaderDatabase contains %zu symbols:\n", symbols.size());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700227 for (const auto& pair : symbols) {
Josh Gaobf8a2852016-05-27 11:59:09 -0700228 pair.second.dump(base_path, out);
229 }
230 }
231};