aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/cpp
diff options
context:
space:
mode:
authorxiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2012-09-22 02:40:50 +0000
committerxiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2012-09-22 02:40:50 +0000
commitb55a20fa2c669b181f47ea9219b8e74d1263da19 (patch)
tree3936a0e7c22196587a6d8397372de41434fe2129 /src/google/protobuf/compiler/cpp
parent9ced30caf94bb4e7e9629c199679ff44e8ca7389 (diff)
downloadprotobuf-b55a20fa2c669b181f47ea9219b8e74d1263da19.tar.gz
protobuf-b55a20fa2c669b181f47ea9219b8e74d1263da19.tar.bz2
protobuf-b55a20fa2c669b181f47ea9219b8e74d1263da19.zip
Down-integrate from internal branch
Diffstat (limited to 'src/google/protobuf/compiler/cpp')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc23
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.h7
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc31
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h16
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc59
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc37
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h15
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc55
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc29
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_options.h58
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc17
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_service.cc6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_service.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc83
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc75
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.h51
28 files changed, 505 insertions, 138 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index bcfa5020..b7c1766b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -48,8 +48,8 @@
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 76d2b798..67c12d7a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -46,10 +46,10 @@ namespace compiler {
namespace cpp {
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor),
classname_(ClassName(descriptor, false)),
- dllexport_decl_(dllexport_decl) {
+ options_(options) {
}
EnumGenerator::~EnumGenerator() {}
@@ -88,10 +88,10 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
vars["min_name"] = min_value->name();
vars["max_name"] = max_value->name();
- if (dllexport_decl_.empty()) {
+ if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
} else {
- vars["dllexport"] = dllexport_decl_ + " ";
+ vars["dllexport"] = options_.dllexport_decl + " ";
}
printer->Print(vars,
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index 58f7721e..2e85a0bd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -36,8 +36,10 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#include <string>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
+
namespace google {
namespace protobuf {
namespace io {
@@ -53,7 +55,7 @@ class EnumGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit EnumGenerator(const EnumDescriptor* descriptor,
- const string& dllexport_decl);
+ const Options& options);
~EnumGenerator();
// Header stuff.
@@ -86,7 +88,7 @@ class EnumGenerator {
private:
const EnumDescriptor* descriptor_;
string classname_;
- string dllexport_decl_;
+ Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index a369f417..6e1620d4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -46,8 +46,9 @@ namespace cpp {
namespace {
void SetEnumVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
(*variables)["default"] = SimpleItoa(default_value->number());
@@ -58,9 +59,10 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
// ===================================================================
EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor)
+EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetEnumVariables(descriptor, &variables_);
+ SetEnumVariables(descriptor, &variables_, options);
}
EnumFieldGenerator::~EnumFieldGenerator() {}
@@ -84,7 +86,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return static_cast< $type$ >($name$_);\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
- " GOOGLE_DCHECK($type$_IsValid(value));\n"
+ " assert($type$_IsValid(value));\n"
" set_has_$name$();\n"
" $name$_ = value;\n"
"}\n");
@@ -152,9 +154,10 @@ GenerateByteSize(io::Printer* printer) const {
// ===================================================================
RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetEnumVariables(descriptor, &variables_);
+ SetEnumVariables(descriptor, &variables_, options);
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
@@ -187,11 +190,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
- " GOOGLE_DCHECK($type$_IsValid(value));\n"
+ " assert($type$_IsValid(value));\n"
" $name$_.Set(index, value);\n"
"}\n"
"inline void $classname$::add_$name$($type$ value) {\n"
- " GOOGLE_DCHECK($type$_IsValid(value));\n"
+ " assert($type$_IsValid(value));\n"
" $name$_.Add(value);\n"
"}\n");
printer->Print(variables_,
@@ -345,7 +348,9 @@ GenerateByteSize(io::Printer* printer) const {
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_$name$_cached_byte_size_ = data_size;\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 0793430c..65770083 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -46,7 +46,8 @@ namespace cpp {
class EnumFieldGenerator : public FieldGenerator {
public:
- explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+ explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~EnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@ class EnumFieldGenerator : public FieldGenerator {
class RepeatedEnumFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 658a7077..ef56b5e5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -57,9 +57,9 @@ string ExtendeeClassName(const FieldDescriptor* descriptor) {
} // anonymous namespace
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor),
- dllexport_decl_(dllexport_decl) {
+ options_(options) {
// Construct type_traits_.
if (descriptor_->is_repeated()) {
type_traits_ = "Repeated";
@@ -106,8 +106,8 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
// export/import specifier.
if (descriptor_->extension_scope() == NULL) {
vars["qualifier"] = "extern";
- if (!dllexport_decl_.empty()) {
- vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"];
+ if (!options_.dllexport_decl.empty()) {
+ vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
}
} else {
vars["qualifier"] = "static";
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h
index 3068b091..50ad035b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -37,6 +37,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -56,8 +57,8 @@ namespace cpp {
class ExtensionGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- explicit ExtensionGenerator(const FieldDescriptor* descriptor,
- const string& dllexport_decl);
+ explicit ExtensionGenerator(const FieldDescriptor* desycriptor,
+ const Options& options);
~ExtensionGenerator();
// Header stuff.
@@ -72,7 +73,7 @@ class ExtensionGenerator {
private:
const FieldDescriptor* descriptor_;
string type_traits_;
- string dllexport_decl_;
+ Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 103cac4a..0786176b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -52,7 +52,8 @@ namespace cpp {
using internal::WireFormat;
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
+ map<string, string>* variables,
+ const Options& options) {
(*variables)["name"] = FieldName(descriptor);
(*variables)["index"] = SimpleItoa(descriptor->index());
(*variables)["number"] = SimpleItoa(descriptor->number());
@@ -64,6 +65,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["deprecation"] = descriptor->options().deprecated()
? " PROTOBUF_DEPRECATED" : "";
+ (*variables)["cppget"] = "Get";
}
FieldGenerator::~FieldGenerator() {}
@@ -80,46 +82,47 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
}
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor),
- field_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+ field_generators_(new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
- field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
+ field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
}
}
-FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
+ const Options& options) {
if (field->is_repeated()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
- return new RepeatedMessageFieldGenerator(field);
+ return new RepeatedMessageFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // RepeatedStringFieldGenerator handles unknown ctypes.
case FieldOptions::STRING:
- return new RepeatedStringFieldGenerator(field);
+ return new RepeatedStringFieldGenerator(field, options);
}
case FieldDescriptor::CPPTYPE_ENUM:
- return new RepeatedEnumFieldGenerator(field);
+ return new RepeatedEnumFieldGenerator(field, options);
default:
- return new RepeatedPrimitiveFieldGenerator(field);
+ return new RepeatedPrimitiveFieldGenerator(field, options);
}
} else {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
- return new MessageFieldGenerator(field);
+ return new MessageFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // StringFieldGenerator handles unknown ctypes.
case FieldOptions::STRING:
- return new StringFieldGenerator(field);
+ return new StringFieldGenerator(field, options);
}
case FieldDescriptor::CPPTYPE_ENUM:
- return new EnumFieldGenerator(field);
+ return new EnumFieldGenerator(field, options);
default:
- return new PrimitiveFieldGenerator(field);
+ return new PrimitiveFieldGenerator(field, options);
}
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index c303a337..f7d99b15 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -40,6 +40,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -57,7 +58,8 @@ namespace cpp {
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
// 'deprecation'].
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables);
+ map<string, string>* variables,
+ const Options& options);
class FieldGenerator {
public:
@@ -114,6 +116,13 @@ class FieldGenerator {
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateDestructorCode(io::Printer* printer) const {}
+ // Generate code that allocates the fields's default instance.
+ virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {}
+
+ // Generate code that should be run when ShutdownProtobufLibrary() is called,
+ // to delete all dynamically-allocated objects.
+ virtual void GenerateShutdownCode(io::Printer* printer) const {}
+
// Generate lines to decode this field, which will be placed inside the
// message's MergeFromCodedStream() method.
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
@@ -144,7 +153,7 @@ class FieldGenerator {
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
- explicit FieldGeneratorMap(const Descriptor* descriptor);
+ explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
@@ -153,7 +162,8 @@ class FieldGeneratorMap {
const Descriptor* descriptor_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
- static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
+ static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+ const Options& options);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index b8e7708f..1bbc89c4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -51,7 +51,7 @@ namespace cpp {
// ===================================================================
FileGenerator::FileGenerator(const FileDescriptor* file,
- const string& dllexport_decl)
+ const Options& options)
: file_(file),
message_generators_(
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
@@ -61,26 +61,26 @@ FileGenerator::FileGenerator(const FileDescriptor* file,
new scoped_ptr<ServiceGenerator>[file->service_count()]),
extension_generators_(
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
- dllexport_decl_(dllexport_decl) {
+ options_(options) {
for (int i = 0; i < file->message_type_count(); i++) {
message_generators_[i].reset(
- new MessageGenerator(file->message_type(i), dllexport_decl));
+ new MessageGenerator(file->message_type(i), options));
}
for (int i = 0; i < file->enum_type_count(); i++) {
enum_generators_[i].reset(
- new EnumGenerator(file->enum_type(i), dllexport_decl));
+ new EnumGenerator(file->enum_type(i), options));
}
for (int i = 0; i < file->service_count(); i++) {
service_generators_[i].reset(
- new ServiceGenerator(file->service(i), dllexport_decl));
+ new ServiceGenerator(file->service(i), options));
}
for (int i = 0; i < file->extension_count(); i++) {
extension_generators_[i].reset(
- new ExtensionGenerator(file->extension(i), dllexport_decl));
+ new ExtensionGenerator(file->extension(i), options));
}
SplitStringUsing(file_->package(), ".", &package_parts_);
@@ -104,6 +104,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"filename", file_->name(),
"filename_identifier", filename_identifier);
+
printer->Print(
"#include <google/protobuf/stubs/common.h>\n"
"\n");
@@ -128,13 +129,23 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// OK, it's now safe to #include other files.
printer->Print(
- "#include <google/protobuf/generated_message_util.h>\n"
+ "#include <google/protobuf/generated_message_util.h>\n");
+ if (file_->message_type_count() > 0) {
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/message.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/message_lite.h>\n");
+ }
+ }
+ printer->Print(
"#include <google/protobuf/repeated_field.h>\n"
"#include <google/protobuf/extension_set.h>\n");
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
printer->Print(
- "#include <google/protobuf/generated_message_reflection.h>\n");
+ "#include <google/protobuf/generated_enum_reflection.h>\n");
}
if (HasGenericServices(file_)) {
@@ -142,6 +153,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"#include <google/protobuf/service.h>\n");
}
+ if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
+ printer->Print(
+ "#include <google/protobuf/unknown_field_set.h>\n");
+ }
+
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
@@ -149,9 +165,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"dependency", StripProto(file_->dependency(i)->name()));
}
+
printer->Print(
"// @@protoc_insertion_point(includes)\n");
+
// Open namespace.
GenerateNamespaceOpeners(printer);
@@ -162,7 +180,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"// Internal implementation detail -- do not call these.\n"
"void $dllexport_decl$ $adddescriptorsname$();\n",
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "dllexport_decl", dllexport_decl_);
+ "dllexport_decl", options_.dllexport_decl);
printer->Print(
// Note that we don't put dllexport_decl on these because they are only
@@ -282,6 +300,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
"\n"
// The generated code calls accessors that might be deprecated. We don't
@@ -294,11 +313,13 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/stubs/once.h>\n"
"#include <google/protobuf/io/coded_stream.h>\n"
"#include <google/protobuf/wire_format_lite_inl.h>\n",
+ "filename", file_->name(),
"basename", StripProto(file_->name()));
if (HasDescriptorMethods(file_)) {
printer->Print(
"#include <google/protobuf/descriptor.h>\n"
+ "#include <google/protobuf/generated_message_reflection.h>\n"
"#include <google/protobuf/reflection_ops.h>\n"
"#include <google/protobuf/wire_format.h>\n");
}
@@ -504,10 +525,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
" static bool already_here = false;\n"
" if (already_here) return;\n"
" already_here = true;\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n",
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n",
// Without.
"void $adddescriptorsname$_impl() {\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n",
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n",
// Vars.
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
@@ -521,9 +544,9 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
vector<string> dependency_package_parts;
SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
printer->Print("::");
- for (int i = 0; i < dependency_package_parts.size(); i++) {
+ for (int j = 0; j < dependency_package_parts.size(); j++) {
printer->Print("$name$::",
- "name", dependency_package_parts[i]);
+ "name", dependency_package_parts[j]);
}
// Call its AddDescriptors function.
printer->Print(
@@ -547,10 +570,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
static const int kBytesPerLine = 40;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
printer->Print("\n \"$data$\"",
- "data", EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
+ "data",
+ EscapeTrigraphs(
+ CEscape(file_data.substr(i, kBytesPerLine))));
}
printer->Print(
- ", $size$);\n",
+ ", $size$);\n",
"size", SimpleItoa(file_data.size()));
// Call MessageFactory::InternalRegisterGeneratedFile().
@@ -594,7 +619,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// Without.
"GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
"void $adddescriptorsname$() {\n"
- " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
+ " ::google::protobuf::::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
" &$adddescriptorsname$_impl);\n"
"}\n",
// Vars.
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index b4e01285..2deefaa8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -39,6 +39,7 @@
#include <vector>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -61,7 +62,7 @@ class FileGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit FileGenerator(const FileDescriptor* file,
- const string& dllexport_decl);
+ const Options& options);
~FileGenerator();
void GenerateHeader(io::Printer* printer);
@@ -85,7 +86,7 @@ class FileGenerator {
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
vector<string> package_parts_;
- string dllexport_decl_;
+ const Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index bb84e2ab..1813510b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -78,11 +78,13 @@ bool CppGenerator::Generate(const FileDescriptor* file,
// }
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
// __declspec(dllimport) depending on what is being compiled.
- string dllexport_decl;
+ Options file_options;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "dllexport_decl") {
- dllexport_decl = options[i].second;
+ file_options.dllexport_decl = options[i].second;
+ } else if (options[i].first == "safe_boundary_check") {
+ file_options.safe_boundary_check = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
@@ -95,7 +97,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
string basename = StripProto(file->name());
basename.append(".pb");
- FileGenerator file_generator(file, dllexport_decl);
+ FileGenerator file_generator(file, file_options);
// Generate header.
{
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index c4b868c2..28911ab0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -148,7 +148,7 @@ string ClassName(const Descriptor* descriptor, bool qualified) {
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
if (enum_descriptor->containing_type() == NULL) {
if (qualified) {
- return DotsToColons(enum_descriptor->full_name());
+ return "::" + DotsToColons(enum_descriptor->full_name());
} else {
return enum_descriptor->name();
}
@@ -259,10 +259,23 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
string DefaultValue(const FieldDescriptor* field) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
+ // gcc rejects the decimal form of kint32min and kint64min.
+ if (field->default_value_int32() == kint32min) {
+ // Make sure we are in a 2's complement system.
+ GOOGLE_COMPILE_ASSERT(kint32min == -0x80000000, kint32min_value_error);
+ return "-0x80000000";
+ }
return SimpleItoa(field->default_value_int32());
case FieldDescriptor::CPPTYPE_UINT32:
return SimpleItoa(field->default_value_uint32()) + "u";
case FieldDescriptor::CPPTYPE_INT64:
+ // See the comments for CPPTYPE_INT32.
+ if (field->default_value_int64() == kint64min) {
+ // Make sure we are in a 2's complement system.
+ GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(-0x8000000000000000),
+ kint64min_value_error);
+ return "GOOGLE_LONGLONG(-0x8000000000000000)";
+ }
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
case FieldDescriptor::CPPTYPE_UINT64:
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
@@ -308,8 +321,9 @@ string DefaultValue(const FieldDescriptor* field) {
ClassName(field->enum_type(), true),
field->default_value_enum()->number());
case FieldDescriptor::CPPTYPE_STRING:
- return "\"" + EscapeTrigraphs(CEscape(field->default_value_string())) +
- "\"";
+ return "\"" + EscapeTrigraphs(
+ CEscape(field->default_value_string())) +
+ "\"";
case FieldDescriptor::CPPTYPE_MESSAGE:
return FieldMessageTypeName(field) + "::default_instance()";
}
@@ -401,6 +415,23 @@ void PrintHandlingOptionalStaticInitializers(
}
}
+
+static bool HasEnumDefinitions(const Descriptor* message_type) {
+ if (message_type->enum_type_count() > 0) return true;
+ for (int i = 0; i < message_type->nested_type_count(); ++i) {
+ if (HasEnumDefinitions(message_type->nested_type(i))) return true;
+ }
+ return false;
+}
+
+bool HasEnumDefinitions(const FileDescriptor* file) {
+ if (file->enum_type_count() > 0) return true;
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasEnumDefinitions(file->message_type(i))) return true;
+ }
+ return false;
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 662a7c31..526e19cc 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -122,23 +122,27 @@ string GlobalShutdownFileName(const string& filename);
string EscapeTrigraphs(const string& to_escape);
// Do message classes in this file keep track of unknown fields?
-inline bool HasUnknownFields(const FileDescriptor *file) {
+inline bool HasUnknownFields(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
+
+// Does this file have any enum type definitions?
+bool HasEnumDefinitions(const FileDescriptor* file);
+
// Does this file have generated parsing, serialization, and other
// standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const FileDescriptor *file) {
+inline bool HasGeneratedMethods(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::CODE_SIZE;
}
-// Do message classes in this file have descriptor and refelction methods?
-inline bool HasDescriptorMethods(const FileDescriptor *file) {
+// Do message classes in this file have descriptor and reflection methods?
+inline bool HasDescriptorMethods(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
// Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor *file) {
+inline bool HasGenericServices(const FileDescriptor* file) {
return file->service_count() > 0 &&
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
file->options().cc_generic_services();
@@ -173,6 +177,7 @@ void PrintHandlingOptionalStaticInitializers(
io::Printer* printer, const char* with_static_init,
const char* without_static_init);
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 1c158be0..1ea4f13d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -48,6 +48,7 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/descriptor.pb.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -103,6 +104,13 @@ struct ExtensionRangeSorter {
}
};
+// Returns true if the "required" restriction check should be ignored for the
+// given field.
+inline static bool ShouldIgnoreRequiredFieldCheck(
+ const FieldDescriptor* field) {
+ return false;
+}
+
// Returns true if the message type has any required fields. If it doesn't,
// we can optimize out calls to its IsInitialized() method.
//
@@ -129,7 +137,8 @@ static bool HasRequiredFields(
if (field->is_required()) {
return true;
}
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !ShouldIgnoreRequiredFieldCheck(field)) {
if (HasRequiredFields(field->message_type(), already_seen)) {
return true;
}
@@ -280,11 +289,11 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
// ===================================================================
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor),
classname_(ClassName(descriptor, false)),
- dllexport_decl_(dllexport_decl),
- field_generators_(descriptor),
+ options_(options),
+ field_generators_(descriptor, options),
nested_generators_(new scoped_ptr<MessageGenerator>[
descriptor->nested_type_count()]),
enum_generators_(new scoped_ptr<EnumGenerator>[
@@ -294,17 +303,17 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
for (int i = 0; i < descriptor->nested_type_count(); i++) {
nested_generators_[i].reset(
- new MessageGenerator(descriptor->nested_type(i), dllexport_decl));
+ new MessageGenerator(descriptor->nested_type(i), options));
}
for (int i = 0; i < descriptor->enum_type_count(); i++) {
enum_generators_[i].reset(
- new EnumGenerator(descriptor->enum_type(i), dllexport_decl));
+ new EnumGenerator(descriptor->enum_type(i), options));
}
for (int i = 0; i < descriptor->extension_count(); i++) {
extension_generators_[i].reset(
- new ExtensionGenerator(descriptor->extension(i), dllexport_decl));
+ new ExtensionGenerator(descriptor->extension(i), options));
}
}
@@ -349,7 +358,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
PrintFieldComment(printer, field);
map<string, string> vars;
- SetCommonFieldVariables(field, &vars);
+ SetCommonFieldVariables(field, &vars, options_);
vars["constant_name"] = FieldConstantName(field);
if (field->is_repeated()) {
@@ -386,7 +395,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
PrintFieldComment(printer, field);
map<string, string> vars;
- SetCommonFieldVariables(field, &vars);
+ SetCommonFieldVariables(field, &vars, options_);
// Generate has_$name$() or $name$_size().
if (field->is_repeated()) {
@@ -446,10 +455,10 @@ GenerateClassDefinition(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = classname_;
vars["field_count"] = SimpleItoa(descriptor_->field_count());
- if (dllexport_decl_.empty()) {
+ if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
} else {
- vars["dllexport"] = dllexport_decl_ + " ";
+ vars["dllexport"] = options_.dllexport_decl + " ";
}
vars["superclass"] = SuperClassName(descriptor_);
@@ -507,6 +516,7 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
+
printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
@@ -605,6 +615,7 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(" private:\n");
printer->Indent();
+
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->is_repeated()) {
printer->Print(
@@ -680,7 +691,7 @@ GenerateClassDefinition(io::Printer* printer) {
// Without.
"friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
// Vars.
- "dllexport_decl", dllexport_decl_,
+ "dllexport_decl", options_.dllexport_decl,
"adddescriptorsname",
GlobalAddDescriptorsName(descriptor_->file()->name()));
@@ -772,9 +783,11 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
printer->Print(vars,
" -1,\n");
}
+ printer->Print(
+ " ::google::protobuf::DescriptorPool::generated_pool(),\n");
+ printer->Print(vars,
+ " ::google::protobuf::MessageFactory::generated_factory(),\n");
printer->Print(vars,
- " ::google::protobuf::DescriptorPool::generated_pool(),\n"
- " ::google::protobuf::MessageFactory::generated_factory(),\n"
" sizeof($classname$));\n");
// Handle nested types.
@@ -803,6 +816,13 @@ GenerateTypeRegistrations(io::Printer* printer) {
void MessageGenerator::
GenerateDefaultInstanceAllocator(io::Printer* printer) {
+ // Construct the default instances of all fields, as they will be used
+ // when creating the default instance of the entire message.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateDefaultInstanceAllocator(printer);
+ }
+
// Construct the default instance. We can't call InitAsDefaultInstance() yet
// because we need to make sure all default instances that this one might
// depend on are constructed first.
@@ -846,6 +866,12 @@ GenerateShutdownCode(io::Printer* printer) {
"classname", classname_);
}
+ // Handle default instances of fields.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateShutdownCode(printer);
+ }
+
// Handle nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateShutdownCode(printer);
@@ -1957,6 +1983,7 @@ GenerateIsInitialized(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !ShouldIgnoreRequiredFieldCheck(field) &&
HasRequiredFields(field->message_type())) {
if (field->is_repeated()) {
printer->Print(
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 04778f6d..a7e43d9c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -38,6 +38,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -57,7 +58,7 @@ class MessageGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit MessageGenerator(const Descriptor* descriptor,
- const string& dllexport_decl);
+ const Options& options);
~MessageGenerator();
// Header stuff.
@@ -153,7 +154,7 @@ class MessageGenerator {
const Descriptor* descriptor_;
string classname_;
- string dllexport_decl_;
+ Options options_;
FieldGeneratorMap field_generators_;
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 7c785e7e..447f975f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -45,8 +45,9 @@ namespace cpp {
namespace {
void SetMessageVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor);
(*variables)["stream_writer"] = (*variables)["declared_type"] +
(HasFastArraySerialization(descriptor->message_type()->file()) ?
@@ -59,9 +60,10 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
// ===================================================================
MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor)
+MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetMessageVariables(descriptor, &variables_);
+ SetMessageVariables(descriptor, &variables_, options);
}
MessageFieldGenerator::~MessageFieldGenerator() {}
@@ -76,7 +78,8 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $name$() const$deprecation$;\n"
"inline $type$* mutable_$name$()$deprecation$;\n"
- "inline $type$* release_$name$()$deprecation$;\n");
+ "inline $type$* release_$name$()$deprecation$;\n"
+ "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
}
void MessageFieldGenerator::
@@ -103,6 +106,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " delete $name$_;\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " } else {\n"
+ " clear_has_$name$();\n"
+ " }\n"
"}\n");
}
@@ -167,9 +179,10 @@ GenerateByteSize(io::Printer* printer) const {
// ===================================================================
RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetMessageVariables(descriptor, &variables_);
+ SetMessageVariables(descriptor, &variables_, options);
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
@@ -197,7 +210,7 @@ void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $classname$::$name$(int index) const {\n"
- " return $name$_.Get(index);\n"
+ " return $name$_.$cppget$(index);\n"
"}\n"
"inline $type$* $classname$::mutable_$name$(int index) {\n"
" return $name$_.Mutable(index);\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index f5147278..a5ed68a5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -46,7 +46,8 @@ namespace cpp {
class MessageFieldGenerator : public FieldGenerator {
public:
- explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+ explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~MessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@ class MessageFieldGenerator : public FieldGenerator {
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedMessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
new file mode 100644
index 00000000..78770662
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: rennie@google.com (Jeffrey Rennie)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Generator options:
+struct Options {
+ Options() : safe_boundary_check(false) {
+ }
+ string dllexport_decl;
+ bool safe_boundary_check;
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 5e8df0f4..1c35fefa 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -80,8 +80,9 @@ int FixedSize(FieldDescriptor::Type type) {
}
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
@@ -99,9 +100,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// ===================================================================
PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetPrimitiveVariables(descriptor, &variables_);
+ SetPrimitiveVariables(descriptor, &variables_, options);
}
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
@@ -190,9 +192,10 @@ GenerateByteSize(io::Printer* printer) const {
// ===================================================================
RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetPrimitiveVariables(descriptor, &variables_);
+ SetPrimitiveVariables(descriptor, &variables_, options);
if (descriptor->options().packed()) {
variables_["packed_reader"] = "ReadPackedPrimitive";
@@ -366,7 +369,9 @@ GenerateByteSize(io::Printer* printer) const {
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_$name$_cached_byte_size_ = data_size;\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 8fcd74ae..48249c40 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -46,7 +46,8 @@ namespace cpp {
class PrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@ class PrimitiveFieldGenerator : public FieldGenerator {
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc
index c2825683..d20018ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -43,14 +43,14 @@ namespace compiler {
namespace cpp {
ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor) {
vars_["classname"] = descriptor_->name();
vars_["full_name"] = descriptor_->full_name();
- if (dllexport_decl.empty()) {
+ if (options.dllexport_decl.empty()) {
vars_["dllexport"] = "";
} else {
- vars_["dllexport"] = dllexport_decl + " ";
+ vars_["dllexport"] = options.dllexport_decl + " ";
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h
index 10e9dd3c..820f9f5f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.h
+++ b/src/google/protobuf/compiler/cpp/cpp_service.h
@@ -38,6 +38,7 @@
#include <map>
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
namespace google {
@@ -55,7 +56,7 @@ class ServiceGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
explicit ServiceGenerator(const ServiceDescriptor* descriptor,
- const string& dllexport_decl);
+ const Options& options);
~ServiceGenerator();
// Header stuff.
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 3cec2b6b..9c0911ac 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -46,11 +46,14 @@ namespace cpp {
namespace {
void SetStringVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
(*variables)["default"] = DefaultValue(descriptor);
+ (*variables)["default_length"] =
+ SimpleItoa(descriptor->default_value_string().length());
(*variables)["default_variable"] = descriptor->default_value_string().empty()
- ? "::google::protobuf::internal::kEmptyString"
+ ? "&::google::protobuf::internal::kEmptyString"
: "_default_" + FieldName(descriptor) + "_";
(*variables)["pointer_type"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
@@ -61,9 +64,10 @@ void SetStringVariables(const FieldDescriptor* descriptor,
// ===================================================================
StringFieldGenerator::
-StringFieldGenerator(const FieldDescriptor* descriptor)
+StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetStringVariables(descriptor, &variables_);
+ SetStringVariables(descriptor, &variables_, options);
}
StringFieldGenerator::~StringFieldGenerator() {}
@@ -72,7 +76,7 @@ void StringFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_, "::std::string* $name$_;\n");
if (!descriptor_->default_value_string().empty()) {
- printer->Print(variables_, "static const ::std::string $default_variable$;\n");
+ printer->Print(variables_, "static ::std::string* $default_variable$;\n");
}
}
@@ -109,7 +113,9 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline void set_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
"inline ::std::string* mutable_$name$()$deprecation$;\n"
- "inline ::std::string* release_$name$()$deprecation$;\n");
+ "inline ::std::string* release_$name$()$deprecation$;\n"
+ "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+
if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
@@ -126,14 +132,14 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"}\n"
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(value);\n"
"}\n"
"inline void $classname$::set_$name$(const char* value) {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(value);\n"
@@ -141,20 +147,20 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"inline "
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$() {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n");
+ " if ($name$_ == $default_variable$) {\n");
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
" $name$_ = new ::std::string;\n");
} else {
printer->Print(variables_,
- " $name$_ = new ::std::string($default_variable$);\n");
+ " $name$_ = new ::std::string(*$default_variable$);\n");
}
printer->Print(variables_,
" }\n"
@@ -162,21 +168,34 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"}\n"
"inline ::std::string* $classname$::release_$name$() {\n"
" clear_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" return NULL;\n"
" } else {\n"
" ::std::string* temp = $name$_;\n"
- " $name$_ = const_cast< ::std::string*>(&$default_variable$);\n"
+ " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
" return temp;\n"
" }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if ($name$_ != $default_variable$) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " $name$_ = $name$;\n"
+ " } else {\n"
+ " clear_has_$name$();\n"
+ " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
+ " }\n"
"}\n");
}
void StringFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
if (!descriptor_->default_value_string().empty()) {
+ // Initialized in GenerateDefaultInstanceAllocator.
printer->Print(variables_,
- "const ::std::string $classname$::$default_variable$($default$);\n");
+ "::std::string* $classname$::$default_variable$ = NULL;\n");
}
}
@@ -184,13 +203,13 @@ void StringFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
- "if ($name$_ != &$default_variable$) {\n"
+ "if ($name$_ != $default_variable$) {\n"
" $name$_->clear();\n"
"}\n");
} else {
printer->Print(variables_,
- "if ($name$_ != &$default_variable$) {\n"
- " $name$_->assign($default_variable$);\n"
+ "if ($name$_ != $default_variable$) {\n"
+ " $name$_->assign(*$default_variable$);\n"
"}\n");
}
}
@@ -208,18 +227,35 @@ GenerateSwappingCode(io::Printer* printer) const {
void StringFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$_ = const_cast< ::std::string*>(&$default_variable$);\n");
+ "$name$_ = const_cast< ::std::string*>($default_variable$);\n");
}
void StringFieldGenerator::
GenerateDestructorCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($name$_ != &$default_variable$) {\n"
+ "if ($name$_ != $default_variable$) {\n"
" delete $name$_;\n"
"}\n");
}
void StringFieldGenerator::
+GenerateDefaultInstanceAllocator(io::Printer* printer) const {
+ if (!descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "$classname$::$default_variable$ =\n"
+ " new ::std::string($default$, $default_length$);\n");
+ }
+}
+
+void StringFieldGenerator::
+GenerateShutdownCode(io::Printer* printer) const {
+ if (!descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "delete $classname$::$default_variable$;\n");
+ }
+}
+
+void StringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
@@ -273,9 +309,10 @@ GenerateByteSize(io::Printer* printer) const {
// ===================================================================
RepeatedStringFieldGenerator::
-RepeatedStringFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetStringVariables(descriptor, &variables_);
+ SetStringVariables(descriptor, &variables_, options);
}
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
@@ -328,7 +365,7 @@ void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const ::std::string& $classname$::$name$(int index) const {\n"
- " return $name$_.Get(index);\n"
+ " return $name$_.$cppget$(index);\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
" return $name$_.Mutable(index);\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 7f45107d..3264134a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -46,7 +46,8 @@ namespace cpp {
class StringFieldGenerator : public FieldGenerator {
public:
- explicit StringFieldGenerator(const FieldDescriptor* descriptor);
+ explicit StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~StringFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -59,6 +60,8 @@ class StringFieldGenerator : public FieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateDestructorCode(io::Printer* printer) const;
+ void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
+ void GenerateShutdownCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
@@ -73,7 +76,8 @@ class StringFieldGenerator : public FieldGenerator {
class RepeatedStringFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedStringFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 54d830fc..e14a818c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -103,9 +103,19 @@ message TestConflictingSymbolNames {
message DO {}
optional DO do = 32;
+ // Some template parameter names for extensions.
+ optional int32 field_type = 33;
+ optional bool is_packed = 34;
+
extensions 1000 to max;
}
+message TestConflictingSymbolNamesExtension {
+ extend TestConflictingSymbolNames {
+ repeated int32 repeated_int32_ext = 20423638 [packed=true];
+ }
+}
+
message DummyMessage {}
service TestConflictingMethodNames {
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 301a7ce6..b5f9ab58 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -44,6 +44,8 @@
// correctly and produces the interfaces we expect, which is why this test
// is written this way.
+#include <google/protobuf/compiler/cpp/cpp_unittest.h>
+
#include <vector>
#include <google/protobuf/unittest.pb.h>
@@ -64,7 +66,7 @@
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -74,6 +76,8 @@ namespace cpp {
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
namespace cpp_unittest {
+namespace protobuf_unittest = ::protobuf_unittest;
+
class MockErrorCollector : public MultiFileErrorCollector {
public:
@@ -174,6 +178,15 @@ TEST(GeneratedMessageTest, Trigraph) {
EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
}
+TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) {
+ const unittest::TestExtremeDefaultValues& extreme_default =
+ unittest::TestExtremeDefaultValues::default_instance();
+ EXPECT_EQ(-0x80000000, kint32min);
+ EXPECT_EQ(GOOGLE_LONGLONG(-0x8000000000000000), kint64min);
+ EXPECT_EQ(kint32min, extreme_default.really_small_int32());
+ EXPECT_EQ(kint64min, extreme_default.really_small_int64());
+}
+
TEST(GeneratedMessageTest, Accessors) {
// Set every field to a unique value then go back and check all those
// values.
@@ -202,6 +215,13 @@ TEST(GeneratedMessageTest, MutableStringDefault) {
EXPECT_EQ("hello", *message.mutable_default_string());
}
+TEST(GeneratedMessageTest, StringDefaults) {
+ unittest::TestExtremeDefaultValues message;
+ // Check if '\000' can be used in default string value.
+ EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero());
+ EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero());
+}
+
TEST(GeneratedMessageTest, ReleaseString) {
// Check that release_foo() starts out NULL, and gives us a value
// that we can delete after it's been set.
@@ -244,6 +264,49 @@ TEST(GeneratedMessageTest, ReleaseMessage) {
EXPECT_FALSE(message.has_optional_nested_message());
}
+TEST(GeneratedMessageTest, SetAllocatedString) {
+ // Check that set_allocated_foo() works for strings.
+ unittest::TestAllTypes message;
+
+ EXPECT_FALSE(message.has_optional_string());
+ const string kHello("hello");
+ message.set_optional_string(kHello);
+ EXPECT_TRUE(message.has_optional_string());
+
+ message.set_allocated_optional_string(NULL);
+ EXPECT_FALSE(message.has_optional_string());
+ EXPECT_EQ("", message.optional_string());
+
+ message.set_allocated_optional_string(new string(kHello));
+ EXPECT_TRUE(message.has_optional_string());
+ EXPECT_EQ(kHello, message.optional_string());
+}
+
+TEST(GeneratedMessageTest, SetAllocatedMessage) {
+ // Check that set_allocated_foo() can be called in all cases.
+ unittest::TestAllTypes message;
+
+ EXPECT_FALSE(message.has_optional_nested_message());
+
+ message.mutable_optional_nested_message()->set_bb(1);
+ EXPECT_TRUE(message.has_optional_nested_message());
+
+ message.set_allocated_optional_nested_message(NULL);
+ EXPECT_FALSE(message.has_optional_nested_message());
+ EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
+ &message.optional_nested_message());
+
+ message.mutable_optional_nested_message()->set_bb(1);
+ unittest::TestAllTypes::NestedMessage* nest =
+ message.release_optional_nested_message();
+ ASSERT_TRUE(nest != NULL);
+ EXPECT_FALSE(message.has_optional_nested_message());
+
+ message.set_allocated_optional_nested_message(nest);
+ EXPECT_TRUE(message.has_optional_nested_message());
+ EXPECT_EQ(1, message.optional_nested_message().bb());
+}
+
TEST(GeneratedMessageTest, Clear) {
// Set every field to a unique value, clear the message, then check that
// it is cleared.
@@ -695,6 +758,13 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) {
message.set_friend_(5);
EXPECT_EQ(5, message.friend_());
+
+ // Instantiate extension template functions to test conflicting template
+ // parameter names.
+ typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
+ message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
+ EXPECT_EQ(123,
+ message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
}
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
@@ -869,11 +939,10 @@ TEST(GeneratedEnumTest, MinAndMax) {
EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX);
EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE);
- // Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases.
+ // Make sure we can use _MIN and _MAX as switch cases.
switch (unittest::SPARSE_A) {
case unittest::TestSparseEnum_MIN:
case unittest::TestSparseEnum_MAX:
- case unittest::TestSparseEnum_ARRAYSIZE:
break;
default:
break;
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.h b/src/google/protobuf/compiler/cpp/cpp_unittest.h
new file mode 100644
index 00000000..a3a1d1ba
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.h
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header declares the namespace google::protobuf::protobuf_unittest in order to expose
+// any problems with the generated class names. We use this header to ensure
+// unittest.cc will declare the namespace prior to other includes, while obeying
+// normal include ordering.
+//
+// When generating a class name of "foo.Bar" we must ensure we prefix the class
+// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
+// trigger that case here by declaring google::protobuf::protobuf_unittest.
+//
+// See ClassName in helpers.h for more details.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+
+namespace google {
+namespace protobuf {
+namespace protobuf_unittest {}
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__