From 4b80bc4402ec88504265e6fdbcdb8a803d67eb64 Mon Sep 17 00:00:00 2001 From: Timur Iskhakov Date: Fri, 28 Jul 2017 15:59:06 -0700 Subject: Add Reference type Add Reference placeholder which keeps Type, FQName and Location. This type is necessary for adding forward reference support: it stores FQName until lookup happens, then stores resolved Type; it stores Location, as all type-related checks are to be moved outside of the parsing, so we need to keep Location for future error messages. Reference type has overwritten operators to make it work as Type*, providing additional checks that Type is resolved before being using. Reference type is also useful for adding forward reference support as it checks that every Type member call appears after lookup. ConstantExpression is to support Reference (and to not be evaluated during parsing) in future CL. Test: links, compiles, hidl_test Change-Id: I7a031b541e678032af1190209e9d2aaf4999bf1b --- Reference.h | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 Reference.h (limited to 'Reference.h') diff --git a/Reference.h b/Reference.h new file mode 100644 index 0000000..e83004a --- /dev/null +++ b/Reference.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2017 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 REFERENCE_H_ + +#define REFERENCE_H_ + +#include +#include + +#include "Location.h" + +namespace android { + +/** + * Reference placeholder + */ +template +struct Reference { + Reference() = default; + + Reference(const FQName& fqName, const Location& location) + : mResolved(nullptr), mFqName(fqName), mLocation(location) {} + + Reference(T* type, const Location& location) : mResolved(type), mLocation(location) { + CHECK(type != nullptr); + } + + Reference(const Reference& ref) + : mResolved(ref.mResolved), mFqName(ref.mFqName), mLocation(ref.mLocation) {} + + /* Storing type cast, valid only before resolving */ + template + Reference(const Reference& ref) + : mResolved(nullptr), mFqName(ref.mFqName), mLocation(ref.mLocation) { + CHECK(!ref.isResolved()); + } + + /* Returns true iff referred type is resolved + Referred type's field might be not resolved */ + bool isResolved() const { return mResolved != nullptr; } + + operator T*() const { return get(); } + + T* operator->() const { return get(); } + + T* get() const { + CHECK(mResolved != nullptr); + return mResolved; + } + + void set(T* resolved) { + CHECK(!isResolved()); + CHECK(resolved != nullptr); + mResolved = resolved; + } + + /* Returns true iff this is reference to null: + not resolved and has not name for lookup */ + bool isEmptyReference() const { return !isResolved() && !hasLookupFqName(); } + + const FQName& getLookupFqName() const { + CHECK(hasLookupFqName()); + return mFqName; + } + + bool hasLocation() const { return mLocation.isValid(); } + + const Location& getLocation() const { + CHECK(hasLocation()); + return mLocation; + } + + private: + /* Referred type */ + T* mResolved = nullptr; + /* Reference name for lookup */ + FQName mFqName; + /* Reference location is mainly used for printing errors */ + Location mLocation; + + bool hasLookupFqName() const { + // Valid only while not resolved to prevent confusion when + // ref.hasLookupFqName() is false while ref,get()->fqName is valid. + CHECK(!isResolved()); + return mFqName.isValid(); + } + + template + friend struct Reference; +}; + +} // namespace android + +#endif // REFERENCE_H_ -- cgit v1.2.3