blob: 589aca6b287c6312413e558c8761406c99d85b6c [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "garnet/bin/zxdb/symbols/modified_type.h"
namespace zxdb {
namespace {
// Returns true if this tag is a modified type that is transparent with respect
// to the data stored in it.
bool IsTransparentTag(int tag) {
return tag == Symbol::kTagConstType || tag == Symbol::kTagVolatileType ||
tag == Symbol::kTagTypedef;
}
// Returns true if this modified holds some kind of pointer to the modified
// type.
bool IsPointerTag(int tag) {
return tag == Symbol::kTagPointerType || tag == Symbol::kTagReferenceType ||
tag == Symbol::kTagRvalueReferenceType;
}
} // namespace
ModifiedType::ModifiedType(int kind, LazySymbol modified)
: Type(kind), modified_(modified) {
if (IsTransparentTag(kind)) {
const Type* mod_type = modified_.Get()->AsType();
if (mod_type)
set_byte_size(mod_type->byte_size());
} else if (IsPointerTag(kind)) {
// Assume 64-bit pointers.
set_byte_size(8);
}
}
ModifiedType::~ModifiedType() = default;
const ModifiedType* ModifiedType::AsModifiedType() const { return this; }
const Type* ModifiedType::GetConcreteType() const {
if (IsTransparentTag(tag())) {
const Type* mod = modified_.Get()->AsType();
if (mod)
return mod->GetConcreteType();
}
return this;
}
// static
bool ModifiedType::IsTypeModifierTag(int tag) {
return tag == kTagConstType || tag == kTagPointerType ||
tag == kTagReferenceType || tag == kTagRestrictType ||
tag == kTagRvalueReferenceType || tag == kTagTypedef ||
tag == kTagVolatileType || tag == kTagImportedDeclaration;
}
std::string ModifiedType::ComputeFullName() const {
static const char kUnknown[] = "<unknown>";
const Type* modified_type = modified().Get()->AsType();
if (!modified_type)
return kUnknown;
switch (tag()) {
case kTagConstType:
if (modified_type->AsModifiedType()) {
// When the underlying type is another modifier, add it to the end,
// e.g. a "constant pointer to a nonconstant int" is "int* const".
return modified_type->GetFullName() + " const";
} else {
// Though the above formatting is always valid, most people write a
// "constant int" / "pointer to a constant int" as either "const int" /
// "const int*" so special-case.
return "const " + modified_type->GetFullName();
}
case kTagPointerType:
return modified_type->GetFullName() + "*";
case kTagReferenceType:
return modified_type->GetFullName() + "&";
case kTagRestrictType:
return "restrict " + modified_type->GetFullName();
case kTagRvalueReferenceType:
return modified_type->GetFullName() + "&&";
case kTagTypedef:
// Typedefs just use the assigned name.
return GetAssignedName();
case kTagVolatileType:
return "volatile " + modified_type->GetFullName();
case kTagImportedDeclaration:
// Using statements use the underlying name.
return modified_type->GetFullName();
}
return kUnknown;
}
} // namespace zxdb