blob: 2b462bda5575efe39e782b7096b204dc8b1c16f1 [file] [log] [blame]
Josh Gaobf8a2852016-05-27 11:59:09 -07001/*
2 * Copyright 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#pragma once
18
19#include <iostream>
20#include <map>
21#include <set>
Josh Gao173e7c02016-06-03 13:38:00 -070022#include <sstream>
Josh Gaobf8a2852016-05-27 11:59:09 -070023#include <string>
24#include <vector>
25
26#include <llvm/ADT/StringRef.h>
27
28#include "Utils.h"
29
30enum class DeclarationType {
31 function,
32 variable,
33 inconsistent,
34};
35
36static const char* declarationTypeName(DeclarationType type) {
37 switch (type) {
38 case DeclarationType::function:
39 return "function";
40 case DeclarationType::variable:
41 return "variable";
42 case DeclarationType::inconsistent:
43 return "inconsistent";
44 }
45}
46
47struct CompilationType {
48 std::string arch;
49 int api_level;
50
51 private:
52 auto tie() const {
53 return std::tie(arch, api_level);
54 }
55
56 public:
57 bool operator<(const CompilationType& other) const {
58 return tie() < other.tie();
59 }
60
61 bool operator==(const CompilationType& other) const {
62 return tie() == other.tie();
63 }
64
65 std::string describe() const {
66 return arch + "-" + std::to_string(api_level);
67 }
68};
69
70struct DeclarationAvailability {
71 int introduced = 0;
72 int deprecated = 0;
73 int obsoleted = 0;
74
75 void dump(std::ostream& out = std::cout) const {
Josh Gao173e7c02016-06-03 13:38:00 -070076 out << describe();
77 }
78
79 bool empty() const {
80 return !(introduced || deprecated || obsoleted);
81 }
82
83 auto tie() const {
84 return std::tie(introduced, deprecated, obsoleted);
85 }
86
87 bool operator==(const DeclarationAvailability& rhs) const {
88 return this->tie() == rhs.tie();
89 }
90
91 bool operator!=(const DeclarationAvailability& rhs) const {
92 return !(*this == rhs);
93 }
94
95 std::string describe() const {
96 if (!(introduced || deprecated || obsoleted)) {
97 return "no availability";
98 }
99
100 std::stringstream out;
Josh Gaobf8a2852016-05-27 11:59:09 -0700101 bool need_comma = false;
102 auto comma = [&out, &need_comma]() {
103 if (!need_comma) {
104 need_comma = true;
105 return;
106 }
107 out << ", ";
108 };
109
110 if (introduced != 0) {
111 comma();
112 out << "introduced = " << introduced;
113 }
114 if (deprecated != 0) {
115 comma();
116 out << "deprecated = " << deprecated;
117 }
118 if (obsoleted != 0) {
119 comma();
120 out << "obsoleted = " << obsoleted;
121 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700122
Josh Gao173e7c02016-06-03 13:38:00 -0700123 return out.str();
Josh Gaobf8a2852016-05-27 11:59:09 -0700124 }
125};
126
127struct DeclarationLocation {
128 std::string filename;
129 unsigned line_number;
130 unsigned column;
131 DeclarationType type;
132 bool is_extern;
133 bool is_definition;
134 DeclarationAvailability availability;
135
136 auto tie() const {
137 return std::tie(filename, line_number, column, type, is_extern, is_definition);
138 }
139
140 bool operator<(const DeclarationLocation& other) const {
141 return tie() < other.tie();
142 }
143
144 bool operator==(const DeclarationLocation& other) const {
145 return tie() == other.tie();
146 }
Josh Gao173e7c02016-06-03 13:38:00 -0700147
148 void dump(const std::string& base_path = "", std::ostream& out = std::cout) const {
149 const char* var_type = declarationTypeName(type);
150 const char* declaration_type = is_definition ? "definition" : "declaration";
151 const char* linkage = is_extern ? "extern" : "static";
152
153 std::string stripped_path;
154 if (llvm::StringRef(filename).startswith(base_path)) {
155 stripped_path = filename.substr(base_path.size());
156 } else {
157 stripped_path = filename;
158 }
159
160 out << " " << linkage << " " << var_type << " " << declaration_type << " @ "
161 << stripped_path << ":" << line_number << ":" << column;
162
163 out << "\t[";
164 availability.dump(out);
165 out << "]\n";
166 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700167};
168
169struct Declaration {
170 std::string name;
171 std::set<DeclarationLocation> locations;
172
173 bool hasDefinition() const {
174 for (const auto& location : locations) {
175 if (location.is_definition) {
176 return true;
177 }
178 }
179 return false;
180 }
181
182 DeclarationType type() const {
183 DeclarationType result = locations.begin()->type;
184 for (const DeclarationLocation& location : locations) {
185 if (location.type != result) {
186 result = DeclarationType::inconsistent;
187 }
188 }
189 return result;
190 }
191
192 void dump(const std::string& base_path = "", std::ostream& out = std::cout) const {
193 out << " " << name << " declared in " << locations.size() << " locations:\n";
194 for (const DeclarationLocation& location : locations) {
Josh Gao173e7c02016-06-03 13:38:00 -0700195 location.dump(base_path, out);
Josh Gaobf8a2852016-05-27 11:59:09 -0700196 }
197 }
198};
199
200namespace clang {
201class ASTUnit;
202}
203
204class HeaderDatabase {
205 public:
206 std::map<std::string, Declaration> declarations;
207
208 void parseAST(clang::ASTUnit* ast);
209
210 void dump(const std::string& base_path = "", std::ostream& out = std::cout) const {
211 out << "HeaderDatabase contains " << declarations.size() << " declarations:\n";
212 for (const auto& pair : declarations) {
213 pair.second.dump(base_path, out);
214 }
215 }
216};