aboutsummaryrefslogtreecommitdiff
path: root/Type.h
blob: 390ffda0a0b7767d8fb56ffa5b92d76d3a1e99d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TYPE_H_

#define TYPE_H_

#include <android-base/macros.h>
#include <utils/Errors.h>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "DocComment.h"
#include "Reference.h"

namespace android {

struct ConstantExpression;
struct Formatter;
struct FQName;
struct ScalarType;
struct Scope;

struct Type : DocCommentable {
    Type(Scope* parent, const std::string& definedName);
    virtual ~Type();

    virtual bool isArray() const;
    virtual bool isBitField() const;
    virtual bool isCompoundType() const;
    virtual bool isEnum() const;
    virtual bool isHandle() const;
    virtual bool isInterface() const;
    virtual bool isNamedType() const;
    virtual bool isMemory() const;
    virtual bool isPointer() const;
    virtual bool isScope() const;
    virtual bool isScalar() const;
    virtual bool isString() const;
    virtual bool isTemplatedType() const;
    virtual bool isTypeDef() const;
    virtual bool isVector() const;
    virtual bool isFmq() const;

    // Resolves the type by unwrapping typedefs
    Type* resolve();
    virtual const Type* resolve() const;

    // All types defined in this type.
    std::vector<Type*> getDefinedTypes();
    virtual std::vector<const Type*> getDefinedTypes() const;

    // All types referenced in this type.
    std::vector<Reference<Type>*> getReferences();
    virtual std::vector<const Reference<Type>*> getReferences() const;

    // All constant expressions referenced in this type.
    std::vector<ConstantExpression*> getConstantExpressions();
    virtual std::vector<const ConstantExpression*> getConstantExpressions() const;

    // All types referenced in this type that must have completed
    // definiton before being referenced.
    std::vector<Reference<Type>*> getStrongReferences();
    virtual std::vector<const Reference<Type>*> getStrongReferences() const;

    // Indicate stage of parsing.
    enum class ParseStage {
        // Indicate that the source file is being parsed and this object is being filled.
        PARSE,
        // Indicate that all source files are parsed, and program is working on type dependencies
        // and validation.
        POST_PARSE,
        // Indicate that parsing is completed, and program is in code-generation stage.
        COMPLETED,
    };

    // Proceeds recursive pass
    // Makes sure to visit each node only once.
    // If mParseStage < stage, object is not ready for this recursivePass() call
    // yet, and function will return error.
    status_t recursivePass(ParseStage stage, const std::function<status_t(Type*)>& func,
                           std::unordered_set<const Type*>* visited);
    status_t recursivePass(ParseStage stage, const std::function<status_t(const Type*)>& func,
                           std::unordered_set<const Type*>* visited) const;

    // Recursive tree pass that completes type declarations
    // that depend on super types
    virtual status_t resolveInheritance();

    // Recursive tree pass that validates all type-related
    // syntax restrictions
    virtual status_t validate() const;

    // Recursive tree pass checkAcyclic return type.
    // Stores cycle end for nice error messages.
    struct CheckAcyclicStatus {
        CheckAcyclicStatus(status_t status, const Type* cycleEnd = nullptr);

        status_t status;

        // If a cycle is found, stores the end of cycle.
        // While going back in recursion, this is used to stop printing the cycle.
        const Type* cycleEnd;
    };

    // Recursive tree pass that ensures that type definitions and references
    // are acyclic and builds reversed topological order of the types.
    // If some cases allow using of incomplete types, these cases are to be
    // declared in Type::getStrongReferences.
    CheckAcyclicStatus topologicalOrder(std::unordered_map<const Type*, size_t>* reversedOrder,
                                        std::unordered_set<const Type*>* stack) const;

    // Checks following C++ restriction on forward declaration:
    // inner struct could be forward declared only inside its parent.
    status_t checkForwardReferenceRestrictions(const Reference<Type>& ref) const;

    virtual const ScalarType *resolveToScalarType() const;

    virtual std::string typeName() const = 0;

    bool isValidEnumStorageType() const;
    virtual bool isElidableType() const;

    virtual bool canCheckEquality() const;
    bool canCheckEquality(std::unordered_set<const Type*>* visited) const;
    virtual bool deepCanCheckEquality(std::unordered_set<const Type*>* visited) const;

    // ParseStage can only be incremented.
    ParseStage getParseStage() const;
    void setParseStage(ParseStage stage);

    Scope* parent();
    const Scope* parent() const;

    const std::string& definedName() const;

    enum StorageMode {
        StorageMode_Stack,
        StorageMode_Argument,
        StorageMode_Result,
    };

    // specifyNamespaces: whether to specify namespaces for built-in types
    virtual std::string getCppType(
            StorageMode mode,
            bool specifyNamespaces) const;

    std::string decorateCppName(
            const std::string &name,
            StorageMode mode,
            bool specifyNamespaces) const;

    std::string getCppStackType(bool specifyNamespaces = true) const;

    std::string getCppResultType(bool specifyNamespaces = true) const;

    std::string getCppArgumentType(bool specifyNamespaces = true) const;

    std::string getCppTypeCast(const std::string& objName,
                               bool specifyNamespaces = true) const;

    // For an array type, dimensionality information will be accumulated at the
    // end of the returned string.
    // if forInitializer == true, actual dimensions are included, i.e. [3][5],
    // otherwise (and by default), they are omitted, i.e. [][].
    virtual std::string getJavaType(bool forInitializer = false) const;

    // Identical to getJavaType() for most types, except: primitives, in which
    // case the wrapper type is returned, and generics (such as ArrayList<?>),
    // where the type specialization is omitted to facilitate use of
    // instanceof or class.isInstance().
    virtual std::string getJavaTypeClass() const;

    virtual std::string getJavaTypeCast(const std::string& objName) const;
    virtual std::string getJavaSuffix() const;

    virtual std::string getVtsType() const;
    virtual std::string getVtsValueName() const;

    enum ErrorMode {
        ErrorMode_Goto,
        ErrorMode_Break,
        ErrorMode_Return,
        ErrorMode_ReturnNothing,
    };
    virtual void emitReaderWriter(
            Formatter &out,
            const std::string &name,
            const std::string &parcelObj,
            bool parcelObjIsPointer,
            bool isReader,
            ErrorMode mode) const;

    virtual void emitReaderWriterEmbedded(
            Formatter &out,
            size_t depth,
            const std::string &name,
            const std::string &sanitizedName,
            bool nameIsPointer,
            const std::string &parcelObj,
            bool parcelObjIsPointer,
            bool isReader,
            ErrorMode mode,
            const std::string &parentName,
            const std::string &offsetText) const;

    virtual void emitDump(
            Formatter &out,
            const std::string &streamName,
            const std::string &name) const;

    virtual void emitJavaDump(
            Formatter &out,
            const std::string &streamName,
            const std::string &name) const;

    virtual void emitJavaReaderWriter(
            Formatter &out,
            const std::string &parcelObj,
            const std::string &argName,
            bool isReader) const;

    virtual void emitJavaFieldInitializer(
            Formatter &out,
            const std::string &fieldName) const;

    virtual void emitJavaFieldDefaultInitialValue(
            Formatter &out,
            const std::string &declaredFieldName) const;

    virtual void emitJavaFieldReaderWriter(
            Formatter &out,
            size_t depth,
            const std::string &parcelName,
            const std::string &blobName,
            const std::string &fieldName,
            const std::string &offset,
            bool isReader) const;

    virtual void emitHidlDefinition(Formatter& out) const;

    virtual void emitTypeDeclarations(Formatter& out) const;

    virtual void emitGlobalTypeDeclarations(Formatter& out) const;

    // Emit scope C++ forward declaration.
    // There is no need to forward declare interfaces, as
    // they are always declared in global scope in dedicated file.
    virtual void emitTypeForwardDeclaration(Formatter& out) const;

    // Emit any declarations pertaining to this type that have to be
    // directly in a namespace, i.e. enum class operators.
    // For android.hardware.foo@1.0::*, this will be in namespace
    // android::hardware::foo::V1_0
    virtual void emitPackageTypeDeclarations(Formatter& out) const;

    // Emit any definitions pertaining to this type that have to be
    // directly in a namespace. Typically, these are things that are only
    // used for a small subset of types, so by putting them in the header,
    // the space cost is moved to the small number of clients that use the
    // feature.
    // For android.hardware.foo@1.0::*, this will be in namespace
    // android::hardware::foo::V1_0
    virtual void emitPackageTypeHeaderDefinitions(Formatter& out) const;

    // Emit any declarations pertaining to this type that have to be
    // at global scope for transport, e.g. read/writeEmbeddedTo/FromParcel
    // For android.hardware.foo@1.0::*, this will be in namespace
    // android::hardware::foo::V1_0
    virtual void emitPackageHwDeclarations(Formatter& out) const;

    virtual void emitTypeDefinitions(Formatter& out, const std::string& prefix) const;

    virtual void emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const;

    virtual bool needsEmbeddedReadWrite() const;
    virtual bool resultNeedsDeref() const;

    // Generates type declaration for vts proto file.
    // TODO (b/30844146): make it a pure virtual method.
    virtual void emitVtsTypeDeclarations(Formatter& out) const;
    // Generates type declaration as attribute of method (return value or method
    // argument) or attribute of compound type for vts proto file.
    virtual void emitVtsAttributeType(Formatter& out) const;

    // Returns true iff this type is supported through the Java backend.
    bool isJavaCompatible() const;
    bool isJavaCompatible(std::unordered_set<const Type*>* visited) const;
    virtual bool deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const;
    // Returns true iff type contains pointer
    // (excluding methods and inner types).
    bool containsPointer() const;
    bool containsPointer(std::unordered_set<const Type*>* visited) const;
    virtual bool deepContainsPointer(std::unordered_set<const Type*>* visited) const;

    virtual void getAlignmentAndSize(size_t *align, size_t *size) const;

    virtual void appendToExportedTypesVector(
            std::vector<const Type *> *exportedTypes) const;

    virtual void emitExportedHeader(Formatter& out, bool forJava) const;

    virtual bool isNeverStrongReference() const;

    static void handleError(Formatter &out, ErrorMode mode);
   protected:
    void emitReaderWriterEmbeddedForTypeName(
            Formatter &out,
            const std::string &name,
            bool nameIsPointer,
            const std::string &parcelObj,
            bool parcelObjIsPointer,
            bool isReader,
            ErrorMode mode,
            const std::string &parentName,
            const std::string &offsetText,
            const std::string &typeName,
            const std::string &childName,
            const std::string &funcNamespace) const;

    void emitJavaReaderWriterWithSuffix(
            Formatter &out,
            const std::string &parcelObj,
            const std::string &argName,
            bool isReader,
            const std::string &suffix,
            const std::string &extra) const;

    void emitDumpWithMethod(
            Formatter &out,
            const std::string &streamName,
            const std::string &methodName,
            const std::string &name) const;

    // This is the name given to the type in the hidl file
    std::string mDefinedName;

  private:
    ParseStage mParseStage = ParseStage::PARSE;
    Scope* const mParent;

    DISALLOW_COPY_AND_ASSIGN(Type);
};

struct TemplatedType : public Type {
    void setElementType(const Reference<Type>& elementType);
    const Type* getElementType() const;

    virtual std::string templatedTypeName() const = 0;
    std::string typeName() const override;

    bool isTemplatedType() const override;

    virtual bool isCompatibleElementType(const Type* elementType) const = 0;

    std::vector<const Reference<Type>*> getReferences() const override;

    virtual status_t validate() const override;

    void emitVtsTypeDeclarations(Formatter& out) const override;
    void emitVtsAttributeType(Formatter& out) const override;

   protected:
     TemplatedType(Scope* parent, const std::string& definedName);
     Reference<Type> mElementType;

   private:
    DISALLOW_COPY_AND_ASSIGN(TemplatedType);
};

}  // namespace android

#endif  // TYPE_H_