• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "aidl_language.h"
2 #include "aidl_typenames.h"
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <algorithm>
8 #include <cassert>
9 #include <iostream>
10 #include <set>
11 #include <sstream>
12 #include <string>
13 #include <utility>
14 
15 #include <android-base/parsedouble.h>
16 #include <android-base/parseint.h>
17 #include <android-base/strings.h>
18 
19 #include "aidl_language_y.h"
20 #include "logging.h"
21 #include "type_java.h"
22 #include "type_namespace.h"
23 
24 #ifdef _WIN32
isatty(int fd)25 int isatty(int  fd)
26 {
27     return (fd == 0);
28 }
29 #endif
30 
31 using android::aidl::IoDelegate;
32 using android::base::Join;
33 using android::base::Split;
34 using std::cerr;
35 using std::endl;
36 using std::pair;
37 using std::set;
38 using std::string;
39 using std::unique_ptr;
40 using std::vector;
41 
42 void yylex_init(void **);
43 void yylex_destroy(void *);
44 void yyset_in(FILE *f, void *);
45 int yyparse(Parser*);
46 YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
47 void yy_delete_buffer(YY_BUFFER_STATE, void *);
48 
AidlToken(const std::string & text,const std::string & comments)49 AidlToken::AidlToken(const std::string& text, const std::string& comments)
50     : text_(text),
51       comments_(comments) {}
52 
AidlLocation(const std::string & file,Point begin,Point end)53 AidlLocation::AidlLocation(const std::string& file, Point begin, Point end)
54     : file_(file), begin_(begin), end_(end) {}
55 
operator <<(std::ostream & os,const AidlLocation & l)56 std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
57   os << l.file_ << ":" << l.begin_.line << "." << l.begin_.column << "-";
58   if (l.begin_.line != l.end_.line) {
59     os << l.end_.line << ".";
60   }
61   os << l.end_.column;
62   return os;
63 }
64 
AidlNode(const AidlLocation & location)65 AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
66 
PrintLocation() const67 std::string AidlNode::PrintLocation() const {
68   std::stringstream ss;
69   ss << location_.file_ << ":" << location_.begin_.line;
70   return ss.str();
71 }
72 
AidlError(bool fatal)73 AidlError::AidlError(bool fatal) : os_(std::cerr), fatal_(fatal) {
74   os_ << "ERROR: ";
75 }
76 
77 static const string kNullable("nullable");
78 static const string kUtf8InCpp("utf8InCpp");
79 static const string kUnsupportedAppUsage("UnsupportedAppUsage");
80 static const string kSystemApi("SystemApi");
81 static const string kStableParcelable("JavaOnlyStableParcelable");
82 
83 static const set<string> kAnnotationNames{kNullable, kUtf8InCpp, kUnsupportedAppUsage, kSystemApi,
84                                           kStableParcelable};
85 
Parse(const AidlLocation & location,const string & name)86 AidlAnnotation* AidlAnnotation::Parse(const AidlLocation& location, const string& name) {
87   if (kAnnotationNames.find(name) == kAnnotationNames.end()) {
88     std::ostringstream stream;
89     stream << "'" << name << "' is not a recognized annotation. ";
90     stream << "It must be one of:";
91     for (const string& kv : kAnnotationNames) {
92       stream << " " << kv;
93     }
94     stream << ".";
95     AIDL_ERROR(location) << stream.str();
96     return nullptr;
97   }
98   return new AidlAnnotation(location, name);
99 }
100 
AidlAnnotation(const AidlLocation & location,const string & name)101 AidlAnnotation::AidlAnnotation(const AidlLocation& location, const string& name)
102     : AidlNode(location), name_(name) {}
103 
HasAnnotation(const vector<AidlAnnotation> & annotations,const string & name)104 static bool HasAnnotation(const vector<AidlAnnotation>& annotations, const string& name) {
105   for (const auto& a : annotations) {
106     if (a.GetName() == name) {
107       return true;
108     }
109   }
110   return false;
111 }
112 
AidlAnnotatable(const AidlLocation & location)113 AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
114 
IsNullable() const115 bool AidlAnnotatable::IsNullable() const {
116   return HasAnnotation(annotations_, kNullable);
117 }
118 
IsUtf8InCpp() const119 bool AidlAnnotatable::IsUtf8InCpp() const {
120   return HasAnnotation(annotations_, kUtf8InCpp);
121 }
122 
IsUnsupportedAppUsage() const123 bool AidlAnnotatable::IsUnsupportedAppUsage() const {
124   return HasAnnotation(annotations_, kUnsupportedAppUsage);
125 }
126 
IsSystemApi() const127 bool AidlAnnotatable::IsSystemApi() const {
128   return HasAnnotation(annotations_, kSystemApi);
129 }
130 
IsStableParcelable() const131 bool AidlAnnotatable::IsStableParcelable() const {
132   return HasAnnotation(annotations_, kStableParcelable);
133 }
134 
ToString() const135 string AidlAnnotatable::ToString() const {
136   vector<string> ret;
137   for (const auto& a : annotations_) {
138     ret.emplace_back(a.ToString());
139   }
140   std::sort(ret.begin(), ret.end());
141   return Join(ret, " ");
142 }
143 
AidlTypeSpecifier(const AidlLocation & location,const string & unresolved_name,bool is_array,vector<unique_ptr<AidlTypeSpecifier>> * type_params,const string & comments)144 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
145                                      bool is_array,
146                                      vector<unique_ptr<AidlTypeSpecifier>>* type_params,
147                                      const string& comments)
148     : AidlAnnotatable(location),
149       unresolved_name_(unresolved_name),
150       is_array_(is_array),
151       type_params_(type_params),
152       comments_(comments) {}
153 
ArrayBase() const154 AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
155   AIDL_FATAL_IF(!is_array_, this);
156 
157   AidlTypeSpecifier arrayBase = *this;
158   arrayBase.is_array_ = false;
159   return arrayBase;
160 }
161 
ToString() const162 string AidlTypeSpecifier::ToString() const {
163   string ret = GetName();
164   if (IsGeneric()) {
165     vector<string> arg_names;
166     for (const auto& ta : GetTypeParameters()) {
167       arg_names.emplace_back(ta->ToString());
168     }
169     ret += "<" + Join(arg_names, ",") + ">";
170   }
171   if (IsArray()) {
172     ret += "[]";
173   }
174   return ret;
175 }
176 
Signature() const177 string AidlTypeSpecifier::Signature() const {
178   string ret = ToString();
179   string annotations = AidlAnnotatable::ToString();
180   if (annotations != "") {
181     ret = annotations + " " + ret;
182   }
183   return ret;
184 }
185 
Resolve(android::aidl::AidlTypenames & typenames)186 bool AidlTypeSpecifier::Resolve(android::aidl::AidlTypenames& typenames) {
187   assert(!IsResolved());
188   pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
189   if (result.second) {
190     fully_qualified_name_ = result.first;
191   }
192   return result.second;
193 }
194 
CheckValid(const AidlTypenames & typenames) const195 bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
196   if (IsGeneric()) {
197     const string& type_name = GetName();
198     const int num = GetTypeParameters().size();
199     if (type_name == "List") {
200       if (num > 1) {
201         AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
202                          << "'" << ToString() << "'";
203         return false;
204       }
205     } else if (type_name == "Map") {
206       if (num != 0 && num != 2) {
207         AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
208                          << "'" << ToString() << "'";
209         return false;
210       }
211     }
212   }
213 
214   if (GetName() == "void") {
215     if (IsArray() || IsNullable() || IsUtf8InCpp()) {
216       AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
217       return false;
218     }
219   }
220 
221   if (IsArray()) {
222     const auto definedType = typenames.TryGetDefinedType(GetName());
223     if (definedType != nullptr && definedType->AsInterface() != nullptr) {
224       AIDL_ERROR(this) << "Binder type cannot be an array";
225       return false;
226     }
227   }
228 
229   if (IsNullable()) {
230     if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
231       AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
232       return false;
233     }
234   }
235   return true;
236 }
237 
AidlConstantValueDecorator(const AidlTypeSpecifier &,const std::string & raw_value)238 std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
239                                        const std::string& raw_value) {
240   return raw_value;
241 }
242 
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)243 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
244                                                  AidlTypeSpecifier* type, const std::string& name)
245     : AidlVariableDeclaration(location, type, name, nullptr /*default_value*/) {}
246 
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * default_value)247 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
248                                                  AidlTypeSpecifier* type, const std::string& name,
249                                                  AidlConstantValue* default_value)
250     : AidlNode(location), type_(type), name_(name), default_value_(default_value) {}
251 
CheckValid(const AidlTypenames & typenames) const252 bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
253   bool valid = true;
254   valid &= type_->CheckValid(typenames);
255 
256   if (default_value_ == nullptr) return valid;
257   valid &= default_value_->CheckValid();
258 
259   if (!valid) return false;
260 
261   return !ValueString(AidlConstantValueDecorator).empty();
262 }
263 
ToString() const264 string AidlVariableDeclaration::ToString() const {
265   string ret = type_->Signature() + " " + name_;
266   if (default_value_ != nullptr) {
267     ret += " = " + ValueString(AidlConstantValueDecorator);
268   }
269   return ret;
270 }
271 
Signature() const272 string AidlVariableDeclaration::Signature() const {
273   return type_->Signature() + " " + name_;
274 }
275 
ValueString(const ConstantValueDecorator & decorator) const276 std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
277   if (default_value_ != nullptr) {
278     return GetDefaultValue()->As(GetType(), decorator);
279   } else {
280     return "";
281   }
282 }
283 
AidlArgument(const AidlLocation & location,AidlArgument::Direction direction,AidlTypeSpecifier * type,const std::string & name)284 AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
285                            AidlTypeSpecifier* type, const std::string& name)
286     : AidlVariableDeclaration(location, type, name),
287       direction_(direction),
288       direction_specified_(true) {}
289 
AidlArgument(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)290 AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
291                            const std::string& name)
292     : AidlVariableDeclaration(location, type, name),
293       direction_(AidlArgument::IN_DIR),
294       direction_specified_(false) {}
295 
GetDirectionSpecifier() const296 string AidlArgument::GetDirectionSpecifier() const {
297   string ret;
298   if (direction_specified_) {
299     switch(direction_) {
300     case AidlArgument::IN_DIR:
301       ret += "in ";
302       break;
303     case AidlArgument::OUT_DIR:
304       ret += "out ";
305       break;
306     case AidlArgument::INOUT_DIR:
307       ret += "inout ";
308       break;
309     }
310   }
311   return ret;
312 }
313 
ToString() const314 string AidlArgument::ToString() const {
315   return GetDirectionSpecifier() + AidlVariableDeclaration::ToString();
316 }
317 
Signature() const318 std::string AidlArgument::Signature() const {
319   class AidlInterface;
320   class AidlInterface;
321   class AidlParcelable;
322   class AidlStructuredParcelable;
323   class AidlParcelable;
324   class AidlStructuredParcelable;
325   return GetDirectionSpecifier() + AidlVariableDeclaration::Signature();
326 }
327 
AidlMember(const AidlLocation & location)328 AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
329 
AidlConstantValue(const AidlLocation & location,Type type,const std::string & checked_value)330 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
331                                      const std::string& checked_value)
332     : AidlNode(location), type_(type), value_(checked_value) {
333   CHECK(!value_.empty() || type_ == Type::ERROR);
334   CHECK(type_ != Type::ARRAY);
335 }
336 
AidlConstantValue(const AidlLocation & location,Type type,std::vector<std::unique_ptr<AidlConstantValue>> * values)337 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
338                                      std::vector<std::unique_ptr<AidlConstantValue>>* values)
339     : AidlNode(location), type_(type), values_(std::move(*values)) {}
340 
isValidLiteralChar(char c)341 static bool isValidLiteralChar(char c) {
342   return !(c <= 0x1f ||  // control characters are < 0x20
343            c >= 0x7f ||  // DEL is 0x7f
344            c == '\\');   // Disallow backslashes for future proofing.
345 }
346 
Boolean(const AidlLocation & location,bool value)347 AidlConstantValue* AidlConstantValue::Boolean(const AidlLocation& location, bool value) {
348   return new AidlConstantValue(location, Type::BOOLEAN, value ? "true" : "false");
349 }
350 
Character(const AidlLocation & location,char value)351 AidlConstantValue* AidlConstantValue::Character(const AidlLocation& location, char value) {
352   if (!isValidLiteralChar(value)) {
353     AIDL_ERROR(location) << "Invalid character literal " << value;
354     return new AidlConstantValue(location, Type::ERROR, "");
355   }
356   return new AidlConstantValue(location, Type::CHARACTER, std::string("'") + value + "'");
357 }
358 
Floating(const AidlLocation & location,const std::string & value)359 AidlConstantValue* AidlConstantValue::Floating(const AidlLocation& location,
360                                                const std::string& value) {
361   return new AidlConstantValue(location, Type::FLOATING, value);
362 }
363 
Hex(const AidlLocation & location,const std::string & value)364 AidlConstantValue* AidlConstantValue::Hex(const AidlLocation& location, const std::string& value) {
365   return new AidlConstantValue(location, Type::HEXIDECIMAL, value);
366 }
367 
Integral(const AidlLocation & location,const std::string & value)368 AidlConstantValue* AidlConstantValue::Integral(const AidlLocation& location,
369                                                const std::string& value) {
370   return new AidlConstantValue(location, Type::INTEGRAL, value);
371 }
372 
Array(const AidlLocation & location,std::vector<std::unique_ptr<AidlConstantValue>> * values)373 AidlConstantValue* AidlConstantValue::Array(
374     const AidlLocation& location, std::vector<std::unique_ptr<AidlConstantValue>>* values) {
375   return new AidlConstantValue(location, Type::ARRAY, values);
376 }
377 
String(const AidlLocation & location,const std::string & value)378 AidlConstantValue* AidlConstantValue::String(const AidlLocation& location,
379                                              const std::string& value) {
380   for (size_t i = 0; i < value.length(); ++i) {
381     if (!isValidLiteralChar(value[i])) {
382       AIDL_ERROR(location) << "Found invalid character at index " << i << " in string constant '"
383                            << value << "'";
384       return new AidlConstantValue(location, Type::ERROR, "");
385     }
386   }
387 
388   return new AidlConstantValue(location, Type::STRING, value);
389 }
390 
CheckValid() const391 bool AidlConstantValue::CheckValid() const {
392   // error always logged during creation
393   return type_ != AidlConstantValue::Type::ERROR;
394 }
395 
TrimIfSuffix(const string & str,const string & suffix)396 static string TrimIfSuffix(const string& str, const string& suffix) {
397   if (str.size() > suffix.size() &&
398       0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix)) {
399     return str.substr(0, str.size() - suffix.size());
400   }
401   return str;
402 }
403 
As(const AidlTypeSpecifier & type,const ConstantValueDecorator & decorator) const404 string AidlConstantValue::As(const AidlTypeSpecifier& type,
405                              const ConstantValueDecorator& decorator) const {
406   if (type.IsGeneric()) {
407     AIDL_ERROR(type) << "Generic type cannot be specified with a constant literal.";
408     return "";
409   }
410 
411   const std::string& type_string = type.GetName();
412 
413   if ((type_ == Type::ARRAY) != type.IsArray()) {
414     goto mismatch_error;
415   }
416 
417   switch (type_) {
418     case AidlConstantValue::Type::ARRAY: {
419       vector<string> raw_values;
420       raw_values.reserve(values_.size());
421 
422       bool success = true;
423       for (const auto& value : values_) {
424         const AidlTypeSpecifier& array_base = type.ArrayBase();
425         const std::string raw_value = value->As(array_base, decorator);
426 
427         success &= !raw_value.empty();
428         raw_values.push_back(decorator(array_base, raw_value));
429       }
430       if (!success) {
431         AIDL_ERROR(this) << "Default value must be a literal array of " << type_string << ".";
432         return "";
433       }
434       return decorator(type, "{" + Join(raw_values, ", ") + "}");
435     }
436     case AidlConstantValue::Type::BOOLEAN:
437       if (type_string == "boolean") return decorator(type, value_);
438       goto mismatch_error;
439     case AidlConstantValue::Type::CHARACTER:
440       if (type_string == "char") return decorator(type, value_);
441       goto mismatch_error;
442     case AidlConstantValue::Type::FLOATING: {
443       bool is_float_literal = value_.back() == 'f';
444       const std::string raw_value = TrimIfSuffix(value_, "f");
445 
446       if (type_string == "double") {
447         double parsed_value;
448         if (!android::base::ParseDouble(raw_value, &parsed_value)) goto parse_error;
449         return decorator(type, std::to_string(parsed_value));
450       }
451       if (is_float_literal && type_string == "float") {
452         float parsed_value;
453         if (!android::base::ParseFloat(raw_value, &parsed_value)) goto parse_error;
454         return decorator(type, std::to_string(parsed_value) + "f");
455       }
456       goto mismatch_error;
457     }
458     case AidlConstantValue::Type::HEXIDECIMAL:
459       // For historical reasons, a hexidecimal int needs to have the specified bits interpreted
460       // as the signed type, so the other types are made consistent with it.
461       if (type_string == "byte") {
462         uint8_t unsigned_value;
463         if (!android::base::ParseUint<uint8_t>(value_, &unsigned_value)) goto parse_error;
464         return decorator(type, std::to_string((int8_t)unsigned_value));
465       }
466       if (type_string == "int") {
467         uint32_t unsigned_value;
468         if (!android::base::ParseUint<uint32_t>(value_, &unsigned_value)) goto parse_error;
469         return decorator(type, std::to_string((int32_t)unsigned_value));
470       }
471       if (type_string == "long") {
472         uint64_t unsigned_value;
473         if (!android::base::ParseUint<uint64_t>(value_, &unsigned_value)) goto parse_error;
474         return decorator(type, std::to_string((int64_t)unsigned_value));
475       }
476       goto mismatch_error;
477     case AidlConstantValue::Type::INTEGRAL:
478       if (type_string == "byte") {
479         if (!android::base::ParseInt<int8_t>(value_, nullptr)) goto parse_error;
480         return decorator(type, value_);
481       }
482       if (type_string == "int") {
483         if (!android::base::ParseInt<int32_t>(value_, nullptr)) goto parse_error;
484         return decorator(type, value_);
485       }
486       if (type_string == "long") {
487         if (!android::base::ParseInt<int64_t>(value_, nullptr)) goto parse_error;
488         return decorator(type, value_);
489       }
490       goto mismatch_error;
491     case AidlConstantValue::Type::STRING:
492       if (type_string == "String") return decorator(type, value_);
493       goto mismatch_error;
494     default:
495       AIDL_FATAL(this) << "Unrecognized constant value type";
496   }
497 
498 mismatch_error:
499   AIDL_ERROR(this) << "Expecting type " << type_string << " but constant is " << ToString(type_);
500   return "";
501 parse_error:
502   AIDL_ERROR(this) << "Could not parse " << value_ << " as " << type_string;
503   return "";
504 }
505 
ToString(Type type)506 string AidlConstantValue::ToString(Type type) {
507   switch (type) {
508     case Type::ARRAY:
509       return "a literal array";
510     case Type::BOOLEAN:
511       return "a literal boolean";
512     case Type::CHARACTER:
513       return "a literal char";
514     case Type::FLOATING:
515       return "a floating-point literal";
516     case Type::HEXIDECIMAL:
517       return "a hexidecimal literal";
518     case Type::INTEGRAL:
519       return "an integral literal";
520     case Type::STRING:
521       return "a literal string";
522     case Type::ERROR:
523       LOG(FATAL) << "aidl internal error: error type failed to halt program";
524       return "";
525     default:
526       LOG(FATAL) << "aidl internal error: unknown constant type: " << static_cast<int>(type);
527       return "";  // not reached
528   }
529 }
530 
AidlConstantDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * value)531 AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
532                                                  AidlTypeSpecifier* type, const std::string& name,
533                                                  AidlConstantValue* value)
534     : AidlMember(location), type_(type), name_(name), value_(value) {}
535 
CheckValid(const AidlTypenames & typenames) const536 bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
537   bool valid = true;
538   valid &= type_->CheckValid(typenames);
539   valid &= value_->CheckValid();
540   if (!valid) return false;
541 
542   const static set<string> kSupportedConstTypes = {"String", "int"};
543   if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
544     AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
545     return false;
546   }
547 
548   return !ValueString(AidlConstantValueDecorator).empty();
549 }
550 
ToString() const551 string AidlConstantDeclaration::ToString() const {
552   return "const " + type_->ToString() + " " + name_ + " = " +
553          ValueString(AidlConstantValueDecorator);
554 }
555 
Signature() const556 string AidlConstantDeclaration::Signature() const {
557   return type_->Signature() + " " + name_;
558 }
559 
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const std::string & comments)560 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
561                        const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
562                        const std::string& comments)
563     : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
564   has_id_ = false;
565 }
566 
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)567 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
568                        const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
569                        const std::string& comments, int id, bool is_user_defined)
570     : AidlMember(location),
571       oneway_(oneway),
572       comments_(comments),
573       type_(type),
574       name_(name),
575       arguments_(std::move(*args)),
576       id_(id),
577       is_user_defined_(is_user_defined) {
578   has_id_ = true;
579   delete args;
580   for (const unique_ptr<AidlArgument>& a : arguments_) {
581     if (a->IsIn()) { in_arguments_.push_back(a.get()); }
582     if (a->IsOut()) { out_arguments_.push_back(a.get()); }
583   }
584 }
585 
586 
Signature() const587 string AidlMethod::Signature() const {
588   vector<string> arg_signatures;
589   for (const auto& arg : GetArguments()) {
590     arg_signatures.emplace_back(arg->GetType().ToString());
591   }
592   return GetName() + "(" + Join(arg_signatures, ", ") + ")";
593 }
594 
ToString() const595 string AidlMethod::ToString() const {
596   vector<string> arg_strings;
597   for (const auto& arg : GetArguments()) {
598     arg_strings.emplace_back(arg->Signature());
599   }
600   string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
601                Join(arg_strings, ", ") + ")";
602   if (HasId()) {
603     ret += " = " + std::to_string(GetId());
604   }
605   return ret;
606 }
607 
AidlDefinedType(const AidlLocation & location,const std::string & name,const std::string & comments,const std::vector<std::string> & package)608 AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
609                                  const std::string& comments,
610                                  const std::vector<std::string>& package)
611     : AidlAnnotatable(location), name_(name), comments_(comments), package_(package) {}
612 
GetPackage() const613 std::string AidlDefinedType::GetPackage() const {
614   return Join(package_, '.');
615 }
616 
GetCanonicalName() const617 std::string AidlDefinedType::GetCanonicalName() const {
618   if (package_.empty()) {
619     return GetName();
620   }
621   return GetPackage() + "." + GetName();
622 }
623 
AidlParcelable(const AidlLocation & location,AidlQualifiedName * name,const std::vector<std::string> & package,const std::string & comments,const std::string & cpp_header)624 AidlParcelable::AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
625                                const std::vector<std::string>& package, const std::string& comments,
626                                const std::string& cpp_header)
627     : AidlDefinedType(location, name->GetDotName(), comments, package),
628       name_(name),
629       cpp_header_(cpp_header) {
630   // Strip off quotation marks if we actually have a cpp header.
631   if (cpp_header_.length() >= 2) {
632     cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
633   }
634 }
635 
CheckValid(const AidlTypenames &) const636 bool AidlParcelable::CheckValid(const AidlTypenames&) const {
637   static const std::set<string> allowed{kStableParcelable};
638   for (const auto& v : GetAnnotations()) {
639     if (allowed.find(v.GetName()) == allowed.end()) {
640       std::ostringstream stream;
641       stream << "Unstructured parcelable can contain only";
642       for (const string& kv : allowed) {
643         stream << " " << kv;
644       }
645       stream << ".";
646       AIDL_ERROR(this) << stream.str();
647       return false;
648     }
649   }
650 
651   return true;
652 }
653 
Write(CodeWriter * writer) const654 void AidlParcelable::Write(CodeWriter* writer) const {
655   writer->Write("parcelable %s ;\n", GetName().c_str());
656 }
657 
AidlStructuredParcelable(const AidlLocation & location,AidlQualifiedName * name,const std::vector<std::string> & package,const std::string & comments,std::vector<std::unique_ptr<AidlVariableDeclaration>> * variables)658 AidlStructuredParcelable::AidlStructuredParcelable(
659     const AidlLocation& location, AidlQualifiedName* name, const std::vector<std::string>& package,
660     const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
661     : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
662       variables_(std::move(*variables)) {}
663 
Write(CodeWriter * writer) const664 void AidlStructuredParcelable::Write(CodeWriter* writer) const {
665   writer->Write("parcelable %s {\n", GetName().c_str());
666   writer->Indent();
667   for (const auto& field : GetFields()) {
668     writer->Write("%s;\n", field->ToString().c_str());
669   }
670   writer->Dedent();
671   writer->Write("}\n");
672 }
673 
CheckValid(const AidlTypenames & typenames) const674 bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
675   for (const auto& v : GetFields()) {
676     if (!(v->CheckValid(typenames))) {
677       return false;
678     }
679   }
680 
681   return true;
682 }
683 
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)684 AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
685                              const std::string& comments, bool oneway,
686                              std::vector<std::unique_ptr<AidlMember>>* members,
687                              const std::vector<std::string>& package)
688     : AidlDefinedType(location, name, comments, package) {
689   for (auto& member : *members) {
690     AidlMember* local = member.release();
691     AidlMethod* method = local->AsMethod();
692     AidlConstantDeclaration* constant = local->AsConstantDeclaration();
693 
694     CHECK(method == nullptr || constant == nullptr);
695 
696     if (method) {
697       method->ApplyInterfaceOneway(oneway);
698       methods_.emplace_back(method);
699     } else if (constant) {
700       constants_.emplace_back(constant);
701     } else {
702       AIDL_FATAL(this) << "Member is neither method nor constant!";
703     }
704   }
705 
706   delete members;
707 }
708 
Write(CodeWriter * writer) const709 void AidlInterface::Write(CodeWriter* writer) const {
710   writer->Write("interface %s {\n", GetName().c_str());
711   writer->Indent();
712   for (const auto& method : GetMethods()) {
713     writer->Write("%s;\n", method->ToString().c_str());
714   }
715   for (const auto& constdecl : GetConstantDeclarations()) {
716     writer->Write("%s;\n", constdecl->ToString().c_str());
717   }
718   writer->Dedent();
719   writer->Write("}\n");
720 }
721 
CheckValid(const AidlTypenames & typenames) const722 bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
723   // Has to be a pointer due to deleting copy constructor. No idea why.
724   map<string, const AidlMethod*> method_names;
725   for (const auto& m : GetMethods()) {
726     if (!m->GetType().CheckValid(typenames)) {
727       return false;
728     }
729 
730     if (m->IsOneway() && m->GetType().GetName() != "void") {
731       AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
732       return false;
733     }
734 
735     set<string> argument_names;
736     for (const auto& arg : m->GetArguments()) {
737       auto it = argument_names.find(arg->GetName());
738       if (it != argument_names.end()) {
739         AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
740                       << arg->GetName() << "'";
741         return false;
742       }
743       argument_names.insert(arg->GetName());
744 
745       if (!arg->GetType().CheckValid(typenames)) {
746         return false;
747       }
748 
749       if (m->IsOneway() && arg->IsOut()) {
750         AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
751         return false;
752       }
753     }
754 
755     auto it = method_names.find(m->GetName());
756     // prevent duplicate methods
757     if (it == method_names.end()) {
758       method_names[m->GetName()] = m.get();
759     } else {
760       AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
761       AIDL_ERROR(it->second) << "previously defined here.";
762       return false;
763     }
764 
765     static set<string> reserved_methods{"asBinder()", "getInterfaceVersion()",
766                                         "getTransactionName(int)"};
767 
768     if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
769       AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use." << endl;
770       return false;
771     }
772   }
773 
774   bool success = true;
775   set<string> constant_names;
776   for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
777     if (constant_names.count(constant->GetName()) > 0) {
778       LOG(ERROR) << "Found duplicate constant name '" << constant->GetName() << "'";
779       success = false;
780     }
781     constant_names.insert(constant->GetName());
782     success = success && constant->CheckValid(typenames);
783   }
784 
785   return success;
786 }
787 
AidlQualifiedName(const AidlLocation & location,const std::string & term,const std::string & comments)788 AidlQualifiedName::AidlQualifiedName(const AidlLocation& location, const std::string& term,
789                                      const std::string& comments)
790     : AidlNode(location), terms_({term}), comments_(comments) {
791   if (term.find('.') != string::npos) {
792     terms_ = Split(term, ".");
793     for (const auto& subterm : terms_) {
794       if (subterm.empty()) {
795         AIDL_FATAL(this) << "Malformed qualified identifier: '" << term << "'";
796       }
797     }
798   }
799 }
800 
AddTerm(const std::string & term)801 void AidlQualifiedName::AddTerm(const std::string& term) {
802   terms_.push_back(term);
803 }
804 
AidlImport(const AidlLocation & location,const std::string & needed_class)805 AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
806     : AidlNode(location), needed_class_(needed_class) {}
807 
Parse(const std::string & filename,const android::aidl::IoDelegate & io_delegate,AidlTypenames & typenames)808 std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
809                                       const android::aidl::IoDelegate& io_delegate,
810                                       AidlTypenames& typenames) {
811   // Make sure we can read the file first, before trashing previous state.
812   unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
813   if (raw_buffer == nullptr) {
814     AIDL_ERROR(filename) << "Error while opening file for parsing";
815     return nullptr;
816   }
817 
818   // We're going to scan this buffer in place, and yacc demands we put two
819   // nulls at the end.
820   raw_buffer->append(2u, '\0');
821 
822   std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
823 
824   if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) return nullptr;
825 
826   return parser;
827 }
828 
Package() const829 std::vector<std::string> Parser::Package() const {
830   if (!package_) {
831     return {};
832   }
833   return package_->GetTerms();
834 }
835 
AddImport(AidlImport * import)836 void Parser::AddImport(AidlImport* import) {
837   imports_.emplace_back(import);
838 }
839 
Resolve()840 bool Parser::Resolve() {
841   bool success = true;
842   for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
843     if (!typespec->Resolve(typenames_)) {
844       AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
845       success = false;
846       // don't stop to show more errors if any
847     }
848   }
849   return success;
850 }
851 
Parser(const std::string & filename,std::string & raw_buffer,android::aidl::AidlTypenames & typenames)852 Parser::Parser(const std::string& filename, std::string& raw_buffer,
853                android::aidl::AidlTypenames& typenames)
854     : filename_(filename), typenames_(typenames) {
855   yylex_init(&scanner_);
856   buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
857 }
858 
~Parser()859 Parser::~Parser() {
860   yy_delete_buffer(buffer_, scanner_);
861   yylex_destroy(scanner_);
862 }
863