1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
35#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
36#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
37
38#include <algorithm>
39#include <memory>
40#include <set>
41#include <string>
42#include <vector>
43
44#include <google/protobuf/stubs/common.h>
45#include <google/protobuf/compiler/cpp/field.h>
46#include <google/protobuf/compiler/cpp/helpers.h>
47#include <google/protobuf/compiler/scc.h>
48#include <google/protobuf/compiler/cpp/options.h>
49
50namespace google {
51namespace protobuf {
52class FileDescriptor; // descriptor.h
53namespace io {
54class Printer; // printer.h
55}
56} // namespace protobuf
57} // namespace google
58
59namespace google {
60namespace protobuf {
61namespace compiler {
62namespace cpp {
63
64class EnumGenerator; // enum.h
65class MessageGenerator; // message.h
66class ServiceGenerator; // service.h
67class ExtensionGenerator; // extension.h
68
69class FileGenerator {
70 public:
71 // See generator.cc for the meaning of dllexport_decl.
72 FileGenerator(const FileDescriptor* file, const Options& options);
73 ~FileGenerator();
74
75 // Shared code between the two header generators below.
76 void GenerateHeader(io::Printer* printer);
77
78 // info_path, if non-empty, should be the path (relative to printer's
79 // output) to the metadata file describing this proto header.
80 void GenerateProtoHeader(io::Printer* printer, const std::string& info_path);
81 // info_path, if non-empty, should be the path (relative to printer's
82 // output) to the metadata file describing this PB header.
83 void GeneratePBHeader(io::Printer* printer, const std::string& info_path);
84 void GenerateSource(io::Printer* printer);
85
86 // The following member functions are used when the lite_implicit_weak_fields
87 // option is set. In this mode the code is organized a bit differently to
88 // promote better linker stripping of unused code. In particular, we generate
89 // one .cc file per message, one .cc file per extension, and a main pb.cc file
90 // containing everything else.
91
92 int NumMessages() const { return message_generators_.size(); }
93 int NumExtensions() const { return extension_generators_.size(); }
94 // Generates the source file for one message.
95 void GenerateSourceForMessage(int idx, io::Printer* printer);
96 // Generates the source file for one extension.
97 void GenerateSourceForExtension(int idx, io::Printer* printer);
98 // Generates a source file containing everything except messages and
99 // extensions.
100 void GenerateGlobalSource(io::Printer* printer);
101
102 private:
103 // Internal type used by GenerateForwardDeclarations (defined in file.cc).
104 class ForwardDeclarations;
105 struct CrossFileReferences;
106
107 void IncludeFile(const std::string& google3_name, io::Printer* printer) {
108 DoIncludeFile(google3_name, do_export: false, printer);
109 }
110 void IncludeFileAndExport(const std::string& google3_name,
111 io::Printer* printer) {
112 DoIncludeFile(google3_name, do_export: true, printer);
113 }
114 void DoIncludeFile(const std::string& google3_name, bool do_export,
115 io::Printer* printer);
116
117 std::string CreateHeaderInclude(const std::string& basename,
118 const FileDescriptor* file);
119 void GetCrossFileReferencesForField(const FieldDescriptor* field,
120 CrossFileReferences* refs);
121 void GetCrossFileReferencesForFile(const FileDescriptor* file,
122 CrossFileReferences* refs);
123 void GenerateInternalForwardDeclarations(const CrossFileReferences& refs,
124 io::Printer* printer);
125 void GenerateSourceIncludes(io::Printer* printer);
126 void GenerateSourcePrelude(io::Printer* printer);
127 void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
128
129 void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs,
130 io::Printer* printer);
131 void GenerateReflectionInitializationCode(io::Printer* printer);
132
133 // For other imports, generates their forward-declarations.
134 void GenerateForwardDeclarations(io::Printer* printer);
135
136 // Generates top or bottom of a header file.
137 void GenerateTopHeaderGuard(io::Printer* printer, bool pb_h);
138 void GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h);
139
140 // Generates #include directives.
141 void GenerateLibraryIncludes(io::Printer* printer);
142 void GenerateDependencyIncludes(io::Printer* printer);
143
144 // Generate a pragma to pull in metadata using the given info_path (if
145 // non-empty). info_path should be relative to printer's output.
146 void GenerateMetadataPragma(io::Printer* printer,
147 const std::string& info_path);
148
149 // Generates a couple of different pieces before definitions:
150 void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
151
152 // Generates types for classes.
153 void GenerateMessageDefinitions(io::Printer* printer);
154
155 void GenerateEnumDefinitions(io::Printer* printer);
156
157 // Generates generic service definitions.
158 void GenerateServiceDefinitions(io::Printer* printer);
159
160 // Generates extension identifiers.
161 void GenerateExtensionIdentifiers(io::Printer* printer);
162
163 // Generates inline function definitions.
164 void GenerateInlineFunctionDefinitions(io::Printer* printer);
165
166 void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
167
168 // Sometimes the names we use in a .proto file happen to be defined as
169 // macros on some platforms (e.g., macro/minor used in plugin.proto are
170 // defined as macros in sys/types.h on FreeBSD and a few other platforms).
171 // To make the generated code compile on these platforms, we either have to
172 // undef the macro for these few platforms, or rename the field name for all
173 // platforms. Since these names are part of protobuf public API, renaming is
174 // generally a breaking change so we prefer the #undef approach.
175 void GenerateMacroUndefs(io::Printer* printer);
176
177 bool IsDepWeak(const FileDescriptor* dep) const {
178 if (weak_deps_.count(x: dep) != 0) {
179 GOOGLE_CHECK(!options_.opensource_runtime);
180 return true;
181 }
182 return false;
183 }
184
185 std::set<const FileDescriptor*> weak_deps_;
186
187 const FileDescriptor* file_;
188 const Options options_;
189
190 MessageSCCAnalyzer scc_analyzer_;
191
192 std::map<std::string, std::string> variables_;
193
194 // Contains the post-order walk of all the messages (and child messages) in
195 // this file. If you need a pre-order walk just reverse iterate.
196 std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
197 std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
198 std::vector<std::unique_ptr<ServiceGenerator>> service_generators_;
199 std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
200
201 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
202};
203
204} // namespace cpp
205} // namespace compiler
206} // namespace protobuf
207} // namespace google
208
209#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
210