blob: 9a4522791767cf9679326afd322498a7e18e2205 [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 Gaob5c49632016-11-08 22:21:31 -080030#include "CompilationType.h"
Josh Gaobf8a2852016-05-27 11:59:09 -070031#include "Utils.h"
32
Josh Gaobfb6bae2016-07-15 17:25:21 -070033namespace clang {
Josh Gao16016df2016-11-07 18:27:16 -080034class ASTContext;
Josh Gaobfb6bae2016-07-15 17:25:21 -070035class Decl;
36}
37
Josh Gaobf8a2852016-05-27 11:59:09 -070038enum class DeclarationType {
39 function,
40 variable,
41 inconsistent,
42};
43
Josh Gaobfb6bae2016-07-15 17:25:21 -070044struct AvailabilityValues {
Josh Gaobf8a2852016-05-27 11:59:09 -070045 int introduced = 0;
46 int deprecated = 0;
47 int obsoleted = 0;
48
Josh Gaobfb6bae2016-07-15 17:25:21 -070049 bool empty() const {
Elliott Hughes52700172019-03-14 13:34:21 -070050 return !(introduced || deprecated || obsoleted);
Josh Gao173e7c02016-06-03 13:38:00 -070051 }
52
Josh Gaobfb6bae2016-07-15 17:25:21 -070053 bool operator==(const AvailabilityValues& rhs) const {
54 return std::tie(introduced, deprecated, obsoleted) ==
55 std::tie(rhs.introduced, rhs.deprecated, rhs.obsoleted);
56 }
57
58 bool operator!=(const AvailabilityValues& rhs) const {
59 return !(*this == rhs);
60 }
61};
62
63std::string to_string(const AvailabilityValues& av);
64
65struct DeclarationAvailability {
66 AvailabilityValues global_availability;
67 ArchMap<AvailabilityValues> arch_availability;
68
Josh Gao173e7c02016-06-03 13:38:00 -070069 bool empty() const {
Josh Gaobfb6bae2016-07-15 17:25:21 -070070 if (!global_availability.empty()) {
71 return false;
72 }
Josh Gao173e7c02016-06-03 13:38:00 -070073
Josh Gao16057882016-08-02 14:54:09 -070074 for (const auto& it : arch_availability) {
Josh Gaobfb6bae2016-07-15 17:25:21 -070075 if (!it.second.empty()) {
76 return false;
77 }
78 }
79
80 return true;
Josh Gao173e7c02016-06-03 13:38:00 -070081 }
82
83 bool operator==(const DeclarationAvailability& rhs) const {
Josh Gaobfb6bae2016-07-15 17:25:21 -070084 return std::tie(global_availability, arch_availability) ==
85 std::tie(rhs.global_availability, rhs.arch_availability);
Josh Gao173e7c02016-06-03 13:38:00 -070086 }
87
88 bool operator!=(const DeclarationAvailability& rhs) const {
89 return !(*this == rhs);
90 }
91
Josh Gaobfb6bae2016-07-15 17:25:21 -070092 // Returns false if the availability declarations conflict.
93 bool merge(const DeclarationAvailability& other);
Josh Gaobf8a2852016-05-27 11:59:09 -070094};
95
Josh Gaobfb6bae2016-07-15 17:25:21 -070096std::string to_string(const DeclarationAvailability& decl_av);
97
98struct FileLocation {
99 unsigned line;
Josh Gaobf8a2852016-05-27 11:59:09 -0700100 unsigned column;
Josh Gaobf8a2852016-05-27 11:59:09 -0700101
Josh Gaobfb6bae2016-07-15 17:25:21 -0700102 bool operator<(const FileLocation& rhs) const {
103 return std::tie(line, column) < std::tie(rhs.line, rhs.column);
Josh Gaobf8a2852016-05-27 11:59:09 -0700104 }
105
Josh Gaobfb6bae2016-07-15 17:25:21 -0700106 bool operator==(const FileLocation& rhs) const {
107 return std::tie(line, column) == std::tie(rhs.line, rhs.column);
Josh Gao173e7c02016-06-03 13:38:00 -0700108 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700109};
110
Josh Gaobfb6bae2016-07-15 17:25:21 -0700111struct Location {
112 std::string filename;
113 FileLocation start;
114 FileLocation end;
115
116 bool operator<(const Location& rhs) const {
117 return std::tie(filename, start, end) < std::tie(rhs.filename, rhs.start, rhs.end);
118 }
119};
120
121std::string to_string(const Location& loc);
122
Josh Gaobf8a2852016-05-27 11:59:09 -0700123struct Declaration {
Josh Gao16057882016-08-02 14:54:09 -0700124 std::string name;
Josh Gaobfb6bae2016-07-15 17:25:21 -0700125 Location location;
Josh Gaobf8a2852016-05-27 11:59:09 -0700126
Josh Gaobfb6bae2016-07-15 17:25:21 -0700127 bool is_extern;
128 bool is_definition;
Josh Gaofff29fe2016-09-07 18:29:08 -0700129 bool no_guard;
Logan Chienc88331b2019-12-20 10:27:45 -0800130 bool fortify_inline;
Josh Gaobfb6bae2016-07-15 17:25:21 -0700131 std::map<CompilationType, DeclarationAvailability> availability;
132
133 bool calculateAvailability(DeclarationAvailability* output) const;
134 bool operator<(const Declaration& rhs) const {
135 return location < rhs.location;
Josh Gaobf8a2852016-05-27 11:59:09 -0700136 }
137
Josh Gao566735d2016-08-02 15:07:32 -0700138 void dump(const std::string& base_path = "", FILE* out = stdout, unsigned indent = 0) const {
Josh Gaobfb6bae2016-07-15 17:25:21 -0700139 std::string indent_str(indent, ' ');
Josh Gao566735d2016-08-02 15:07:32 -0700140 fprintf(out, "%s", indent_str.c_str());
Josh Gaobf8a2852016-05-27 11:59:09 -0700141
Josh Gao566735d2016-08-02 15:07:32 -0700142 fprintf(out, "%s ", is_extern ? "extern" : "static");
143 fprintf(out, "%s ", is_definition ? "definition" : "declaration");
Josh Gaofff29fe2016-09-07 18:29:08 -0700144 if (no_guard) {
145 fprintf(out, "no_guard ");
146 }
Logan Chienc88331b2019-12-20 10:27:45 -0800147 if (fortify_inline) {
148 fprintf(out, "fortify_inline ");
149 }
Josh Gao566735d2016-08-02 15:07:32 -0700150 fprintf(out, "@ %s:%u:%u", StripPrefix(location.filename, base_path).str().c_str(),
151 location.start.line, location.start.column);
Josh Gaobfb6bae2016-07-15 17:25:21 -0700152
153 if (!availability.empty()) {
154 DeclarationAvailability avail;
155
Josh Gao566735d2016-08-02 15:07:32 -0700156 fprintf(out, "\n%s ", indent_str.c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700157 if (!calculateAvailability(&avail)) {
Josh Gaoa00e6722016-11-04 12:04:38 -0700158 fprintf(out, "invalid availability\n");
Josh Gaobfb6bae2016-07-15 17:25:21 -0700159 } else {
Josh Gaoa00e6722016-11-04 12:04:38 -0700160 fprintf(out, "%s\n", to_string(avail).c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700161 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700162 }
163 }
164};
165
Josh Gaobfb6bae2016-07-15 17:25:21 -0700166struct Symbol {
167 std::string name;
168 std::map<Location, Declaration> declarations;
Josh Gaobf8a2852016-05-27 11:59:09 -0700169
Josh Gaobfb6bae2016-07-15 17:25:21 -0700170 bool calculateAvailability(DeclarationAvailability* output) const;
171 bool hasDeclaration(const CompilationType& type) const;
Josh Gaobf8a2852016-05-27 11:59:09 -0700172
Josh Gaobfb6bae2016-07-15 17:25:21 -0700173 bool operator<(const Symbol& rhs) const {
174 return name < rhs.name;
175 }
176
177 bool operator==(const Symbol& rhs) const {
178 return name == rhs.name;
179 }
Josh Gaobf8a2852016-05-27 11:59:09 -0700180
Josh Gao566735d2016-08-02 15:07:32 -0700181 void dump(const std::string& base_path = "", FILE* out = stdout) const {
Josh Gaobfb6bae2016-07-15 17:25:21 -0700182 DeclarationAvailability availability;
183 bool valid_availability = calculateAvailability(&availability);
Josh Gao566735d2016-08-02 15:07:32 -0700184 fprintf(out, " %s: ", name.c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700185
186 if (valid_availability) {
Josh Gao566735d2016-08-02 15:07:32 -0700187 fprintf(out, "%s\n", to_string(availability).c_str());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700188 } else {
Josh Gao566735d2016-08-02 15:07:32 -0700189 fprintf(out, "invalid\n");
Josh Gaobfb6bae2016-07-15 17:25:21 -0700190 }
191
Josh Gaobfb6bae2016-07-15 17:25:21 -0700192 for (auto& it : declarations) {
193 it.second.dump(base_path, out, 4);
Josh Gaobfb6bae2016-07-15 17:25:21 -0700194 }
195 }
196};
197
198class HeaderDatabase {
199 std::mutex mutex;
200
201 public:
202 std::map<std::string, Symbol> symbols;
203
Josh Gao16016df2016-11-07 18:27:16 -0800204 void parseAST(CompilationType type, clang::ASTContext& ast);
Josh Gaobfb6bae2016-07-15 17:25:21 -0700205
Josh Gao566735d2016-08-02 15:07:32 -0700206 void dump(const std::string& base_path = "", FILE* out = stdout) const {
207 fprintf(out, "HeaderDatabase contains %zu symbols:\n", symbols.size());
Josh Gaobfb6bae2016-07-15 17:25:21 -0700208 for (const auto& pair : symbols) {
Josh Gaobf8a2852016-05-27 11:59:09 -0700209 pair.second.dump(base_path, out);
210 }
211 }
212};