• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015, 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 #include "aidl_language.h"
18 #include "aidl_typenames.h"
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <algorithm>
24 #include <iostream>
25 #include <set>
26 #include <sstream>
27 #include <string>
28 #include <utility>
29 
30 #include <android-base/parsedouble.h>
31 #include <android-base/parseint.h>
32 #include <android-base/strings.h>
33 
34 #include "aidl_language_y-module.h"
35 #include "logging.h"
36 
37 #include "aidl.h"
38 
39 #ifdef _WIN32
isatty(int fd)40 int isatty(int  fd)
41 {
42     return (fd == 0);
43 }
44 #endif
45 
46 using android::aidl::IoDelegate;
47 using android::base::Join;
48 using android::base::Split;
49 using std::cerr;
50 using std::endl;
51 using std::pair;
52 using std::set;
53 using std::string;
54 using std::unique_ptr;
55 using std::vector;
56 
57 namespace {
IsJavaKeyword(const char * str)58 bool IsJavaKeyword(const char* str) {
59   static const std::vector<std::string> kJavaKeywords{
60       "abstract", "assert", "boolean",    "break",     "byte",       "case",      "catch",
61       "char",     "class",  "const",      "continue",  "default",    "do",        "double",
62       "else",     "enum",   "extends",    "final",     "finally",    "float",     "for",
63       "goto",     "if",     "implements", "import",    "instanceof", "int",       "interface",
64       "long",     "native", "new",        "package",   "private",    "protected", "public",
65       "return",   "short",  "static",     "strictfp",  "super",      "switch",    "synchronized",
66       "this",     "throw",  "throws",     "transient", "try",        "void",      "volatile",
67       "while",    "true",   "false",      "null",
68   };
69   return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
70 }
71 
AddHideComment(CodeWriter * writer)72 void AddHideComment(CodeWriter* writer) {
73   writer->Write("/* @hide */\n");
74 }
75 
HasHideComment(const std::string & comment)76 inline bool HasHideComment(const std::string& comment) {
77   return std::regex_search(comment, std::regex("@hide\\b"));
78 }
79 }  // namespace
80 
81 void yylex_init(void **);
82 void yylex_destroy(void *);
83 void yyset_in(FILE *f, void *);
84 int yyparse(Parser*);
85 YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
86 void yy_delete_buffer(YY_BUFFER_STATE, void *);
87 
AidlToken(const std::string & text,const std::string & comments)88 AidlToken::AidlToken(const std::string& text, const std::string& comments)
89     : text_(text),
90       comments_(comments) {}
91 
AidlLocation(const std::string & file,Point begin,Point end)92 AidlLocation::AidlLocation(const std::string& file, Point begin, Point end)
93     : file_(file), begin_(begin), end_(end) {}
94 
operator <<(std::ostream & os,const AidlLocation & l)95 std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
96   os << l.file_ << ":" << l.begin_.line << "." << l.begin_.column << "-";
97   if (l.begin_.line != l.end_.line) {
98     os << l.end_.line << ".";
99   }
100   os << l.end_.column;
101   return os;
102 }
103 
AidlNode(const AidlLocation & location)104 AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
105 
PrintLine() const106 std::string AidlNode::PrintLine() const {
107   std::stringstream ss;
108   ss << location_.file_ << ":" << location_.begin_.line;
109   return ss.str();
110 }
111 
PrintLocation() const112 std::string AidlNode::PrintLocation() const {
113   std::stringstream ss;
114   ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
115      << location_.end_.line << ":" << location_.end_.column;
116   return ss.str();
117 }
118 
AidlError(bool fatal)119 AidlError::AidlError(bool fatal) : os_(std::cerr), fatal_(fatal) {
120   sHadError = true;
121 
122   os_ << "ERROR: ";
123 }
124 
125 bool AidlError::sHadError = false;
126 
127 static const string kNullable("nullable");
128 static const string kUtf8InCpp("utf8InCpp");
129 static const string kVintfStability("VintfStability");
130 static const string kUnsupportedAppUsage("UnsupportedAppUsage");
131 static const string kJavaStableParcelable("JavaOnlyStableParcelable");
132 static const string kHide("Hide");
133 static const string kBacking("Backing");
134 
135 static const std::map<string, std::map<std::string, std::string>> kAnnotationParameters{
136     {kNullable, {}},
137     {kUtf8InCpp, {}},
138     {kVintfStability, {}},
139     {kUnsupportedAppUsage,
140      {{"expectedSignature", "String"},
141       {"implicitMember", "String"},
142       {"maxTargetSdk", "int"},
143       {"publicAlternatives", "String"},
144       {"trackingBug", "long"}}},
145     {kJavaStableParcelable, {}},
146     {kHide, {}},
147     {kBacking, {{"type", "String"}}}};
148 
Parse(const AidlLocation & location,const string & name,std::map<std::string,std::shared_ptr<AidlConstantValue>> * parameter_list)149 AidlAnnotation* AidlAnnotation::Parse(
150     const AidlLocation& location, const string& name,
151     std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
152   if (kAnnotationParameters.find(name) == kAnnotationParameters.end()) {
153     std::ostringstream stream;
154     stream << "'" << name << "' is not a recognized annotation. ";
155     stream << "It must be one of:";
156     for (const auto& kv : kAnnotationParameters) {
157       stream << " " << kv.first;
158     }
159     stream << ".";
160     AIDL_ERROR(location) << stream.str();
161     return nullptr;
162   }
163   if (parameter_list == nullptr) {
164     return new AidlAnnotation(location, name);
165   }
166 
167   return new AidlAnnotation(location, name, std::move(*parameter_list));
168 }
169 
AidlAnnotation(const AidlLocation & location,const string & name)170 AidlAnnotation::AidlAnnotation(const AidlLocation& location, const string& name)
171     : AidlAnnotation(location, name, {}) {}
172 
AidlAnnotation(const AidlLocation & location,const string & name,std::map<std::string,std::shared_ptr<AidlConstantValue>> && parameters)173 AidlAnnotation::AidlAnnotation(
174     const AidlLocation& location, const string& name,
175     std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
176     : AidlNode(location), name_(name), parameters_(std::move(parameters)) {}
177 
CheckValid() const178 bool AidlAnnotation::CheckValid() const {
179   auto supported_params_iterator = kAnnotationParameters.find(GetName());
180   if (supported_params_iterator == kAnnotationParameters.end()) {
181     AIDL_ERROR(this) << GetName() << " annotation does not have any supported parameters.";
182     return false;
183   }
184   const auto& supported_params = supported_params_iterator->second;
185   for (const auto& name_and_param : parameters_) {
186     const std::string& param_name = name_and_param.first;
187     const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
188     if (!param->CheckValid()) {
189       AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
190                        << GetName() << ".";
191       return false;
192     }
193     auto parameter_mapping_it = supported_params.find(param_name);
194     if (parameter_mapping_it == supported_params.end()) {
195       std::ostringstream stream;
196       stream << "Parameter " << param_name << " not supported ";
197       stream << "for annotation " << GetName() << ".";
198       stream << "It must be one of:";
199       for (const auto& kv : supported_params) {
200         stream << " " << kv.first;
201       }
202       AIDL_ERROR(this) << stream.str();
203       return false;
204     }
205     AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
206     const std::string param_value = param->ValueString(type, AidlConstantValueDecorator);
207     // Assume error on empty string.
208     if (param_value == "") {
209       AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
210                        << GetName() << ".";
211       return false;
212     }
213   }
214   return true;
215 }
216 
AnnotationParams(const ConstantValueDecorator & decorator) const217 std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
218     const ConstantValueDecorator& decorator) const {
219   std::map<std::string, std::string> raw_params;
220   const auto& supported_params = kAnnotationParameters.at(GetName());
221   for (const auto& name_and_param : parameters_) {
222     const std::string& param_name = name_and_param.first;
223     const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
224     AidlTypeSpecifier type{AIDL_LOCATION_HERE, supported_params.at(param_name), false, nullptr, ""};
225     if (!param->CheckValid()) {
226       AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
227                        << GetName() << ".";
228       raw_params.clear();
229       return raw_params;
230     }
231 
232     raw_params.emplace(param_name, param->ValueString(type, decorator));
233   }
234   return raw_params;
235 }
236 
ToString(const ConstantValueDecorator & decorator) const237 std::string AidlAnnotation::ToString(const ConstantValueDecorator& decorator) const {
238   if (parameters_.empty()) {
239     return "@" + GetName();
240   } else {
241     vector<string> param_strings;
242     for (const auto& [name, value] : AnnotationParams(decorator)) {
243       param_strings.emplace_back(name + "=" + value);
244     }
245     return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
246   }
247 }
248 
HasAnnotation(const vector<AidlAnnotation> & annotations,const string & name)249 static bool HasAnnotation(const vector<AidlAnnotation>& annotations, const string& name) {
250   for (const auto& a : annotations) {
251     if (a.GetName() == name) {
252       return true;
253     }
254   }
255   return false;
256 }
257 
GetAnnotation(const vector<AidlAnnotation> & annotations,const string & name)258 static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
259                                            const string& name) {
260   for (const auto& a : annotations) {
261     if (a.GetName() == name) {
262       return &a;
263     }
264   }
265   return nullptr;
266 }
267 
AidlAnnotatable(const AidlLocation & location)268 AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
269 
IsNullable() const270 bool AidlAnnotatable::IsNullable() const {
271   return HasAnnotation(annotations_, kNullable);
272 }
273 
IsUtf8InCpp() const274 bool AidlAnnotatable::IsUtf8InCpp() const {
275   return HasAnnotation(annotations_, kUtf8InCpp);
276 }
277 
IsVintfStability() const278 bool AidlAnnotatable::IsVintfStability() const {
279   return HasAnnotation(annotations_, kVintfStability);
280 }
281 
UnsupportedAppUsage() const282 const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
283   return GetAnnotation(annotations_, kUnsupportedAppUsage);
284 }
285 
BackingType(const AidlTypenames & typenames) const286 const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
287   auto annotation = GetAnnotation(annotations_, kBacking);
288   if (annotation != nullptr) {
289     auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
290     if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
291       const string& type = it->second;
292       AidlTypeSpecifier* type_specifier =
293           new AidlTypeSpecifier(AIDL_LOCATION_HERE,
294                                 // Strip the quotes off the type String.
295                                 type.substr(1, type.length() - 2), false, nullptr, "");
296       type_specifier->Resolve(typenames);
297       return type_specifier;
298     }
299   }
300   return nullptr;
301 }
302 
IsStableApiParcelable(Options::Language lang) const303 bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
304   return HasAnnotation(annotations_, kJavaStableParcelable) && lang == Options::Language::JAVA;
305 }
306 
IsHide() const307 bool AidlAnnotatable::IsHide() const {
308   return HasAnnotation(annotations_, kHide);
309 }
310 
DumpAnnotations(CodeWriter * writer) const311 void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
312   if (annotations_.empty()) return;
313 
314   writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
315 }
316 
CheckValidAnnotations() const317 bool AidlAnnotatable::CheckValidAnnotations() const {
318   for (const auto& annotation : GetAnnotations()) {
319     if (!annotation.CheckValid()) {
320       return false;
321     }
322   }
323 
324   return true;
325 }
326 
ToString() const327 string AidlAnnotatable::ToString() const {
328   vector<string> ret;
329   for (const auto& a : annotations_) {
330     ret.emplace_back(a.ToString(AidlConstantValueDecorator));
331   }
332   std::sort(ret.begin(), ret.end());
333   return Join(ret, " ");
334 }
335 
AidlTypeSpecifier(const AidlLocation & location,const string & unresolved_name,bool is_array,vector<unique_ptr<AidlTypeSpecifier>> * type_params,const string & comments)336 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
337                                      bool is_array,
338                                      vector<unique_ptr<AidlTypeSpecifier>>* type_params,
339                                      const string& comments)
340     : AidlAnnotatable(location),
341       AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
342       unresolved_name_(unresolved_name),
343       is_array_(is_array),
344       comments_(comments),
345       split_name_(Split(unresolved_name, ".")) {}
346 
ArrayBase() const347 AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
348   AIDL_FATAL_IF(!is_array_, this);
349   // Declaring array of generic type cannot happen, it is grammar error.
350   AIDL_FATAL_IF(IsGeneric(), this);
351 
352   AidlTypeSpecifier array_base = *this;
353   array_base.is_array_ = false;
354   return array_base;
355 }
356 
IsHidden() const357 bool AidlTypeSpecifier::IsHidden() const {
358   return HasHideComment(GetComments());
359 }
360 
ToString() const361 string AidlTypeSpecifier::ToString() const {
362   string ret = GetName();
363   if (IsGeneric()) {
364     vector<string> arg_names;
365     for (const auto& ta : GetTypeParameters()) {
366       arg_names.emplace_back(ta->ToString());
367     }
368     ret += "<" + Join(arg_names, ",") + ">";
369   }
370   if (IsArray()) {
371     ret += "[]";
372   }
373   return ret;
374 }
375 
Signature() const376 string AidlTypeSpecifier::Signature() const {
377   string ret = ToString();
378   string annotations = AidlAnnotatable::ToString();
379   if (annotations != "") {
380     ret = annotations + " " + ret;
381   }
382   return ret;
383 }
384 
Resolve(const AidlTypenames & typenames)385 bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
386   CHECK(!IsResolved());
387   pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
388   if (result.second) {
389     fully_qualified_name_ = result.first;
390     split_name_ = Split(fully_qualified_name_, ".");
391   }
392   return result.second;
393 }
394 
CheckValid(const AidlTypenames & typenames) const395 bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
396   if (!CheckValidAnnotations()) {
397     return false;
398   }
399   if (IsGeneric()) {
400     const string& type_name = GetName();
401 
402     auto& types = GetTypeParameters();
403     // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
404     if (type_name == "List" || type_name == "Map") {
405       if (std::any_of(types.begin(), types.end(), [](auto& type_ptr) {
406             return AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
407           })) {
408         AIDL_ERROR(this) << "A generic type cannot has any primitive type parameters.";
409         return false;
410       }
411     }
412     const auto defined_type = typenames.TryGetDefinedType(type_name);
413     const auto parameterizable =
414         defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
415     const bool is_user_defined_generic_type =
416         parameterizable != nullptr && parameterizable->IsGeneric();
417     const size_t num_params = GetTypeParameters().size();
418     if (type_name == "List") {
419       if (num_params > 1) {
420         AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
421                          << "'" << ToString() << "'";
422         return false;
423       }
424     } else if (type_name == "Map") {
425       if (num_params != 0 && num_params != 2) {
426         AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
427                          << "'" << ToString() << "'";
428         return false;
429       }
430       if (num_params == 2) {
431         const string& key_type = GetTypeParameters()[0]->GetName();
432         if (key_type != "String") {
433           AIDL_ERROR(this) << "The type of key in map must be String, but it is "
434                            << "'" << key_type << "'";
435           return false;
436         }
437       }
438     } else if (is_user_defined_generic_type) {
439       const size_t allowed = parameterizable->GetTypeParameters().size();
440       if (num_params != allowed) {
441         AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
442                          << num_params;
443         return false;
444       }
445     } else {
446       AIDL_ERROR(this) << type_name << " is not a generic type.";
447       return false;
448     }
449   }
450 
451   const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
452                                       GetTypeParameters().size() == 1 &&
453                                       GetTypeParameters()[0]->GetName() == "String";
454   if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
455     AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
456     return false;
457   }
458 
459   if (GetName() == "void") {
460     if (IsArray() || IsNullable() || IsUtf8InCpp()) {
461       AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
462       return false;
463     }
464   }
465 
466   if (IsArray()) {
467     const auto defined_type = typenames.TryGetDefinedType(GetName());
468     if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
469       AIDL_ERROR(this) << "Binder type cannot be an array";
470       return false;
471     }
472   }
473 
474   if (IsNullable()) {
475     if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
476       AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
477       return false;
478     }
479     const auto defined_type = typenames.TryGetDefinedType(GetName());
480     if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
481       AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
482       return false;
483     }
484   }
485   return true;
486 }
487 
AidlConstantValueDecorator(const AidlTypeSpecifier &,const std::string & raw_value)488 std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
489                                        const std::string& raw_value) {
490   return raw_value;
491 }
492 
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)493 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
494                                                  AidlTypeSpecifier* type, const std::string& name)
495     : AidlVariableDeclaration(location, type, name, nullptr /*default_value*/) {}
496 
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * default_value)497 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
498                                                  AidlTypeSpecifier* type, const std::string& name,
499                                                  AidlConstantValue* default_value)
500     : AidlNode(location), type_(type), name_(name), default_value_(default_value) {}
501 
CheckValid(const AidlTypenames & typenames) const502 bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
503   bool valid = true;
504   valid &= type_->CheckValid(typenames);
505 
506   if (type_->GetName() == "void") {
507     AIDL_ERROR(this) << "Declaration " << name_
508                      << " is void, but declarations cannot be of void type.";
509     valid = false;
510   }
511 
512   if (default_value_ == nullptr) return valid;
513   valid &= default_value_->CheckValid();
514 
515   if (!valid) return false;
516 
517   return !ValueString(AidlConstantValueDecorator).empty();
518 }
519 
ToString() const520 string AidlVariableDeclaration::ToString() const {
521   string ret = type_->Signature() + " " + name_;
522   if (default_value_ != nullptr) {
523     ret += " = " + ValueString(AidlConstantValueDecorator);
524   }
525   return ret;
526 }
527 
Signature() const528 string AidlVariableDeclaration::Signature() const {
529   return type_->Signature() + " " + name_;
530 }
531 
ValueString(const ConstantValueDecorator & decorator) const532 std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
533   if (default_value_ != nullptr) {
534     return default_value_->ValueString(GetType(), decorator);
535   } else {
536     return "";
537   }
538 }
539 
AidlArgument(const AidlLocation & location,AidlArgument::Direction direction,AidlTypeSpecifier * type,const std::string & name)540 AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
541                            AidlTypeSpecifier* type, const std::string& name)
542     : AidlVariableDeclaration(location, type, name),
543       direction_(direction),
544       direction_specified_(true) {}
545 
AidlArgument(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)546 AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
547                            const std::string& name)
548     : AidlVariableDeclaration(location, type, name),
549       direction_(AidlArgument::IN_DIR),
550       direction_specified_(false) {}
551 
GetDirectionSpecifier() const552 string AidlArgument::GetDirectionSpecifier() const {
553   string ret;
554   if (direction_specified_) {
555     switch(direction_) {
556     case AidlArgument::IN_DIR:
557       ret += "in ";
558       break;
559     case AidlArgument::OUT_DIR:
560       ret += "out ";
561       break;
562     case AidlArgument::INOUT_DIR:
563       ret += "inout ";
564       break;
565     }
566   }
567   return ret;
568 }
569 
ToString() const570 string AidlArgument::ToString() const {
571   return GetDirectionSpecifier() + AidlVariableDeclaration::ToString();
572 }
573 
Signature() const574 std::string AidlArgument::Signature() const {
575   class AidlInterface;
576   class AidlInterface;
577   class AidlParcelable;
578   class AidlStructuredParcelable;
579   class AidlParcelable;
580   class AidlStructuredParcelable;
581   return GetDirectionSpecifier() + AidlVariableDeclaration::Signature();
582 }
583 
AidlMember(const AidlLocation & location)584 AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
585 
AidlConstantDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * value)586 AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
587                                                  AidlTypeSpecifier* type, const std::string& name,
588                                                  AidlConstantValue* value)
589     : AidlMember(location), type_(type), name_(name), value_(value) {}
590 
CheckValid(const AidlTypenames & typenames) const591 bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
592   bool valid = true;
593   valid &= type_->CheckValid(typenames);
594   valid &= value_->CheckValid();
595   if (!valid) return false;
596 
597   const static set<string> kSupportedConstTypes = {"String", "int"};
598   if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
599     AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
600     return false;
601   }
602 
603   return true;
604 }
605 
ToString() const606 string AidlConstantDeclaration::ToString() const {
607   return "const " + type_->ToString() + " " + name_ + " = " +
608          ValueString(AidlConstantValueDecorator);
609 }
610 
Signature() const611 string AidlConstantDeclaration::Signature() const {
612   return type_->Signature() + " " + name_;
613 }
614 
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const std::string & comments)615 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
616                        const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
617                        const std::string& comments)
618     : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
619   has_id_ = false;
620 }
621 
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const std::string & comments,int id,bool is_user_defined)622 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
623                        const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
624                        const std::string& comments, int id, bool is_user_defined)
625     : AidlMember(location),
626       oneway_(oneway),
627       comments_(comments),
628       type_(type),
629       name_(name),
630       arguments_(std::move(*args)),
631       id_(id),
632       is_user_defined_(is_user_defined) {
633   has_id_ = true;
634   delete args;
635   for (const unique_ptr<AidlArgument>& a : arguments_) {
636     if (a->IsIn()) { in_arguments_.push_back(a.get()); }
637     if (a->IsOut()) { out_arguments_.push_back(a.get()); }
638   }
639 }
640 
IsHidden() const641 bool AidlMethod::IsHidden() const {
642   return HasHideComment(GetComments());
643 }
644 
Signature() const645 string AidlMethod::Signature() const {
646   vector<string> arg_signatures;
647   for (const auto& arg : GetArguments()) {
648     arg_signatures.emplace_back(arg->GetType().ToString());
649   }
650   return GetName() + "(" + Join(arg_signatures, ", ") + ")";
651 }
652 
ToString() const653 string AidlMethod::ToString() const {
654   vector<string> arg_strings;
655   for (const auto& arg : GetArguments()) {
656     arg_strings.emplace_back(arg->Signature());
657   }
658   string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
659                Join(arg_strings, ", ") + ")";
660   if (HasId()) {
661     ret += " = " + std::to_string(GetId());
662   }
663   return ret;
664 }
665 
AidlDefinedType(const AidlLocation & location,const std::string & name,const std::string & comments,const std::vector<std::string> & package)666 AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
667                                  const std::string& comments,
668                                  const std::vector<std::string>& package)
669     : AidlAnnotatable(location), name_(name), comments_(comments), package_(package) {}
670 
GetPackage() const671 std::string AidlDefinedType::GetPackage() const {
672   return Join(package_, '.');
673 }
674 
IsHidden() const675 bool AidlDefinedType::IsHidden() const {
676   return HasHideComment(GetComments());
677 }
678 
GetCanonicalName() const679 std::string AidlDefinedType::GetCanonicalName() const {
680   if (package_.empty()) {
681     return GetName();
682   }
683   return GetPackage() + "." + GetName();
684 }
685 
DumpHeader(CodeWriter * writer) const686 void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
687   if (this->IsHidden()) {
688     AddHideComment(writer);
689   }
690   DumpAnnotations(writer);
691 }
692 
AidlParcelable(const AidlLocation & location,AidlQualifiedName * name,const std::vector<std::string> & package,const std::string & comments,const std::string & cpp_header,std::vector<std::string> * type_params)693 AidlParcelable::AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
694                                const std::vector<std::string>& package, const std::string& comments,
695                                const std::string& cpp_header, std::vector<std::string>* type_params)
696     : AidlDefinedType(location, name->GetDotName(), comments, package),
697       AidlParameterizable<std::string>(type_params),
698       name_(name),
699       cpp_header_(cpp_header) {
700   // Strip off quotation marks if we actually have a cpp header.
701   if (cpp_header_.length() >= 2) {
702     cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
703   }
704 }
705 template <typename T>
AidlParameterizable(const AidlParameterizable & other)706 AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
707   // Copying is not supported if it has type parameters.
708   // It doesn't make a problem because only ArrayBase() makes a copy,
709   // and it can be called only if a type is not generic.
710   CHECK(!other.IsGeneric());
711 }
712 
713 template <typename T>
CheckValid() const714 bool AidlParameterizable<T>::CheckValid() const {
715   return true;
716 };
717 
718 template <>
CheckValid() const719 bool AidlParameterizable<std::string>::CheckValid() const {
720   if (!IsGeneric()) {
721     return true;
722   }
723   std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
724   if (set.size() != GetTypeParameters().size()) {
725     AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
726     return false;
727   }
728   return true;
729 }
730 
CheckValid(const AidlTypenames &) const731 bool AidlParcelable::CheckValid(const AidlTypenames&) const {
732   static const std::set<string> allowed{kJavaStableParcelable};
733   if (!CheckValidAnnotations()) {
734     return false;
735   }
736   if (!AidlParameterizable<std::string>::CheckValid()) {
737     return false;
738   }
739   for (const auto& v : GetAnnotations()) {
740     if (allowed.find(v.GetName()) == allowed.end()) {
741       std::ostringstream stream;
742       stream << "Unstructured parcelable can contain only";
743       for (const string& kv : allowed) {
744         stream << " " << kv;
745       }
746       stream << ".";
747       AIDL_ERROR(this) << stream.str();
748       return false;
749     }
750   }
751 
752   return true;
753 }
754 
Dump(CodeWriter * writer) const755 void AidlParcelable::Dump(CodeWriter* writer) const {
756   DumpHeader(writer);
757   writer->Write("parcelable %s ;\n", GetName().c_str());
758 }
759 
AidlStructuredParcelable(const AidlLocation & location,AidlQualifiedName * name,const std::vector<std::string> & package,const std::string & comments,std::vector<std::unique_ptr<AidlVariableDeclaration>> * variables)760 AidlStructuredParcelable::AidlStructuredParcelable(
761     const AidlLocation& location, AidlQualifiedName* name, const std::vector<std::string>& package,
762     const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
763     : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
764       variables_(std::move(*variables)) {}
765 
Dump(CodeWriter * writer) const766 void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
767   DumpHeader(writer);
768   writer->Write("parcelable %s {\n", GetName().c_str());
769   writer->Indent();
770   for (const auto& field : GetFields()) {
771     if (field->GetType().IsHidden()) {
772       AddHideComment(writer);
773     }
774     writer->Write("%s;\n", field->ToString().c_str());
775   }
776   writer->Dedent();
777   writer->Write("}\n");
778 }
779 
CheckValid(const AidlTypenames & typenames) const780 bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
781   bool success = true;
782   for (const auto& v : GetFields()) {
783     success = success && v->CheckValid(typenames);
784   }
785   return success;
786 }
787 
788 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(Options::Language lang) const789 bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
790   if (lang != Options::Language::JAVA) {
791     if (this->GetName() == "List" && !this->IsGeneric()) {
792       AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
793       return false;
794     }
795   }
796   if (this->GetName() == "FileDescriptor" && lang == Options::Language::NDK) {
797     AIDL_ERROR(this) << "FileDescriptor isn't supported with the NDK.";
798     return false;
799   }
800   if (this->IsGeneric()) {
801     if (this->GetName() == "List") {
802       if (this->GetTypeParameters().size() != 1) {
803         AIDL_ERROR(this) << "List must have only one type parameter.";
804         return false;
805       }
806       if (lang == Options::Language::CPP) {
807         auto& name = this->GetTypeParameters()[0]->GetName();
808         if (!(name == "String" || name == "IBinder")) {
809           AIDL_ERROR(this) << "List in cpp supports only string and IBinder for now.";
810           return false;
811         }
812       } else if (lang == Options::Language::JAVA) {
813         const string& contained_type = this->GetTypeParameters()[0]->GetName();
814         if (AidlTypenames::IsBuiltinTypename(contained_type)) {
815           if (contained_type != "String" && contained_type != "IBinder" &&
816               contained_type != "ParcelFileDescriptor") {
817             AIDL_ERROR(this) << "List<" << contained_type << "> isn't supported in Java";
818             return false;
819           }
820         }
821       }
822     }
823   }
824   if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
825     if (lang != Options::Language::JAVA) {
826       AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
827       return false;
828     }
829   }
830   if (lang == Options::Language::JAVA) {
831     const string name = this->GetName();
832     // List[], Map[], CharSequence[] are not supported.
833     if (AidlTypenames::IsBuiltinTypename(name) && this->IsArray()) {
834       if (name == "List" || name == "Map" || name == "CharSequence") {
835         AIDL_ERROR(this) << "List[], Map[], CharSequence[] are not supported.";
836         return false;
837       }
838     }
839   }
840 
841   return true;
842 }
843 
844 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(Options::Language lang) const845 bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
846   if (lang != Options::Language::JAVA) {
847     const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
848     if (unstructured_parcelable != nullptr) {
849       if (unstructured_parcelable->GetCppHeader().empty()) {
850         AIDL_ERROR(unstructured_parcelable)
851             << "Unstructured parcelable must have C++ header defined.";
852         return false;
853       }
854     }
855   }
856   return true;
857 }
858 
859 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(Options::Language lang) const860 bool AidlStructuredParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
861   if (!AidlParcelable::LanguageSpecificCheckValid(lang)) {
862     return false;
863   }
864   for (const auto& v : this->GetFields()) {
865     if (!v->GetType().LanguageSpecificCheckValid(lang)) {
866       return false;
867     }
868   }
869   return true;
870 }
871 
AidlEnumerator(const AidlLocation & location,const std::string & name,AidlConstantValue * value,const std::string & comments)872 AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
873                                AidlConstantValue* value, const std::string& comments)
874     : AidlNode(location), name_(name), value_(value), comments_(comments) {}
875 
CheckValid(const AidlTypeSpecifier & enum_backing_type) const876 bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
877   if (GetValue() == nullptr) {
878     return false;
879   }
880   if (!GetValue()->CheckValid()) {
881     return false;
882   }
883   if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
884     AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
885     return false;
886   }
887   return true;
888 }
889 
ValueString(const AidlTypeSpecifier & backing_type,const ConstantValueDecorator & decorator) const890 string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
891                                    const ConstantValueDecorator& decorator) const {
892   return GetValue()->ValueString(backing_type, decorator);
893 }
894 
AidlEnumDeclaration(const AidlLocation & location,const std::string & name,std::vector<std::unique_ptr<AidlEnumerator>> * enumerators,const std::vector<std::string> & package,const std::string & comments)895 AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
896                                          std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
897                                          const std::vector<std::string>& package,
898                                          const std::string& comments)
899     : AidlDefinedType(location, name, comments, package), enumerators_(std::move(*enumerators)) {}
900 
SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type)901 void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
902   backing_type_ = std::move(type);
903 }
904 
Autofill()905 bool AidlEnumDeclaration::Autofill() {
906   const AidlEnumerator* previous = nullptr;
907   for (const auto& enumerator : enumerators_) {
908     if (enumerator->GetValue() == nullptr) {
909       if (previous == nullptr) {
910         enumerator->SetValue(std::unique_ptr<AidlConstantValue>(
911             AidlConstantValue::Integral(AIDL_LOCATION_HERE, "0")));
912       } else {
913         auto prev_value = std::unique_ptr<AidlConstantValue>(
914             AidlConstantValue::ShallowIntegralCopy(*previous->GetValue()));
915         if (prev_value == nullptr) {
916           return false;
917         }
918         enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
919             AIDL_LOCATION_HERE, std::move(prev_value), "+",
920             std::unique_ptr<AidlConstantValue>(
921                 AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1"))));
922       }
923     }
924     previous = enumerator.get();
925   }
926   return true;
927 }
928 
CheckValid(const AidlTypenames &) const929 bool AidlEnumDeclaration::CheckValid(const AidlTypenames&) const {
930   if (backing_type_ == nullptr) {
931     AIDL_ERROR(this) << "Enum declaration missing backing type.";
932     return false;
933   }
934   bool success = true;
935   for (const auto& enumerator : enumerators_) {
936     success = success && enumerator->CheckValid(GetBackingType());
937   }
938   return success;
939 }
940 
Dump(CodeWriter * writer) const941 void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
942   DumpHeader(writer);
943   writer->Write("enum %s {\n", GetName().c_str());
944   writer->Indent();
945   for (const auto& enumerator : GetEnumerators()) {
946     writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
947                   enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
948   }
949   writer->Dedent();
950   writer->Write("}\n");
951 }
952 
953 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(Options::Language lang) const954 bool AidlInterface::LanguageSpecificCheckValid(Options::Language lang) const {
955   for (const auto& m : this->GetMethods()) {
956     if (!m->GetType().LanguageSpecificCheckValid(lang)) {
957       return false;
958     }
959     for (const auto& arg : m->GetArguments()) {
960       if (!arg->GetType().LanguageSpecificCheckValid(lang)) {
961         return false;
962       }
963     }
964   }
965   return true;
966 }
967 
AidlInterface(const AidlLocation & location,const std::string & name,const std::string & comments,bool oneway,std::vector<std::unique_ptr<AidlMember>> * members,const std::vector<std::string> & package)968 AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
969                              const std::string& comments, bool oneway,
970                              std::vector<std::unique_ptr<AidlMember>>* members,
971                              const std::vector<std::string>& package)
972     : AidlDefinedType(location, name, comments, package) {
973   for (auto& member : *members) {
974     AidlMember* local = member.release();
975     AidlMethod* method = local->AsMethod();
976     AidlConstantDeclaration* constant = local->AsConstantDeclaration();
977 
978     CHECK(method == nullptr || constant == nullptr);
979 
980     if (method) {
981       method->ApplyInterfaceOneway(oneway);
982       methods_.emplace_back(method);
983     } else if (constant) {
984       constants_.emplace_back(constant);
985     } else {
986       AIDL_FATAL(this) << "Member is neither method nor constant!";
987     }
988   }
989 
990   delete members;
991 }
992 
Dump(CodeWriter * writer) const993 void AidlInterface::Dump(CodeWriter* writer) const {
994   DumpHeader(writer);
995   writer->Write("interface %s {\n", GetName().c_str());
996   writer->Indent();
997   for (const auto& method : GetMethods()) {
998     if (method->IsHidden()) {
999       AddHideComment(writer);
1000     }
1001     writer->Write("%s;\n", method->ToString().c_str());
1002   }
1003   for (const auto& constdecl : GetConstantDeclarations()) {
1004     if (constdecl->GetType().IsHidden()) {
1005       AddHideComment(writer);
1006     }
1007     writer->Write("%s;\n", constdecl->ToString().c_str());
1008   }
1009   writer->Dedent();
1010   writer->Write("}\n");
1011 }
1012 
CheckValid(const AidlTypenames & typenames) const1013 bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1014   if (!CheckValidAnnotations()) {
1015     return false;
1016   }
1017   // Has to be a pointer due to deleting copy constructor. No idea why.
1018   map<string, const AidlMethod*> method_names;
1019   for (const auto& m : GetMethods()) {
1020     if (!m->GetType().CheckValid(typenames)) {
1021       return false;
1022     }
1023 
1024     if (m->IsOneway() && m->GetType().GetName() != "void") {
1025       AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1026       return false;
1027     }
1028 
1029     set<string> argument_names;
1030     for (const auto& arg : m->GetArguments()) {
1031       auto it = argument_names.find(arg->GetName());
1032       if (it != argument_names.end()) {
1033         AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1034                       << arg->GetName() << "'";
1035         return false;
1036       }
1037       argument_names.insert(arg->GetName());
1038 
1039       if (!arg->GetType().CheckValid(typenames)) {
1040         return false;
1041       }
1042 
1043       if (m->IsOneway() && arg->IsOut()) {
1044         AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1045         return false;
1046       }
1047       const bool can_be_out = typenames.CanBeOutParameter(arg->GetType());
1048       if (!arg->DirectionWasSpecified() && can_be_out) {
1049         AIDL_ERROR(arg) << "'" << arg->GetType().ToString()
1050                         << "' can be an out type, so you must declare it as in, out, or inout.";
1051         return false;
1052       }
1053 
1054       if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
1055         AIDL_ERROR(arg) << "'" << arg->ToString() << "' can only be an in parameter.";
1056         return false;
1057       }
1058 
1059       // check that the name doesn't match a keyword
1060       if (IsJavaKeyword(arg->GetName().c_str())) {
1061         AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1062         return false;
1063       }
1064 
1065       // Reserve a namespace for internal use
1066       if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1067         AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1068         return false;
1069       }
1070     }
1071 
1072     auto it = method_names.find(m->GetName());
1073     // prevent duplicate methods
1074     if (it == method_names.end()) {
1075       method_names[m->GetName()] = m.get();
1076     } else {
1077       AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1078       AIDL_ERROR(it->second) << "previously defined here.";
1079       return false;
1080     }
1081 
1082     static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
1083                                         "getTransactionName(int)"};
1084 
1085     if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1086       AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use." << endl;
1087       return false;
1088     }
1089   }
1090 
1091   bool success = true;
1092   set<string> constant_names;
1093   for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
1094     if (constant_names.count(constant->GetName()) > 0) {
1095       LOG(ERROR) << "Found duplicate constant name '" << constant->GetName() << "'";
1096       success = false;
1097     }
1098     constant_names.insert(constant->GetName());
1099     success = success && constant->CheckValid(typenames);
1100   }
1101 
1102   return success;
1103 }
1104 
AidlQualifiedName(const AidlLocation & location,const std::string & term,const std::string & comments)1105 AidlQualifiedName::AidlQualifiedName(const AidlLocation& location, const std::string& term,
1106                                      const std::string& comments)
1107     : AidlNode(location), terms_({term}), comments_(comments) {
1108   if (term.find('.') != string::npos) {
1109     terms_ = Split(term, ".");
1110     for (const auto& subterm : terms_) {
1111       if (subterm.empty()) {
1112         AIDL_FATAL(this) << "Malformed qualified identifier: '" << term << "'";
1113       }
1114     }
1115   }
1116 }
1117 
AddTerm(const std::string & term)1118 void AidlQualifiedName::AddTerm(const std::string& term) {
1119   terms_.push_back(term);
1120 }
1121 
AidlImport(const AidlLocation & location,const std::string & needed_class)1122 AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1123     : AidlNode(location), needed_class_(needed_class) {}
1124 
Parse(const std::string & filename,const android::aidl::IoDelegate & io_delegate,AidlTypenames & typenames)1125 std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
1126                                       const android::aidl::IoDelegate& io_delegate,
1127                                       AidlTypenames& typenames) {
1128   // Make sure we can read the file first, before trashing previous state.
1129   unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
1130   if (raw_buffer == nullptr) {
1131     AIDL_ERROR(filename) << "Error while opening file for parsing";
1132     return nullptr;
1133   }
1134 
1135   // We're going to scan this buffer in place, and yacc demands we put two
1136   // nulls at the end.
1137   raw_buffer->append(2u, '\0');
1138 
1139   std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
1140 
1141   if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) return nullptr;
1142 
1143   return parser;
1144 }
1145 
Package() const1146 std::vector<std::string> Parser::Package() const {
1147   if (!package_) {
1148     return {};
1149   }
1150   return package_->GetTerms();
1151 }
1152 
AddImport(std::unique_ptr<AidlImport> && import)1153 void Parser::AddImport(std::unique_ptr<AidlImport>&& import) {
1154   for (const auto& i : imports_) {
1155     if (i->GetNeededClass() == import->GetNeededClass()) {
1156       return;
1157     }
1158   }
1159   imports_.emplace_back(std::move(import));
1160 }
1161 
Resolve()1162 bool Parser::Resolve() {
1163   bool success = true;
1164   for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
1165     if (!typespec->Resolve(typenames_)) {
1166       AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
1167       success = false;
1168       // don't stop to show more errors if any
1169     }
1170   }
1171   return success;
1172 }
1173 
Parser(const std::string & filename,std::string & raw_buffer,android::aidl::AidlTypenames & typenames)1174 Parser::Parser(const std::string& filename, std::string& raw_buffer,
1175                android::aidl::AidlTypenames& typenames)
1176     : filename_(filename), typenames_(typenames) {
1177   yylex_init(&scanner_);
1178   buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
1179 }
1180 
~Parser()1181 Parser::~Parser() {
1182   yy_delete_buffer(buffer_, scanner_);
1183   yylex_destroy(scanner_);
1184 }
1185