bool ASTPrinter::visit(VariableDeclaration const& _node) { writeLine("VariableDeclaration \"" + _node.name() + "\""); *m_ostream << indentation() << ( _node.annotation().type ? string(" Type: ") + _node.annotation().type->toString() : string(" Type unknown.") ) << "\n"; printSourcePart(_node); return goDeeper(); }
StackVariable::StackVariable(CompilerContext& _compilerContext, VariableDeclaration const& _declaration): LValue(_compilerContext, _declaration.annotation().type.get()), m_baseStackOffset(m_context.baseStackOffsetOfVariable(_declaration)), m_size(m_dataType->sizeOnStack()) { }
StorageItem::StorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration): StorageItem(_compilerContext, *_declaration.annotation().type) { auto const& location = m_context.storageLocationOfVariable(_declaration); m_context << location.first << u256(location.second); }
void ReferencesResolver::endVisit(VariableDeclaration const& _variable) { if (_variable.annotation().type) return; TypePointer type; if (_variable.typeName()) { type = _variable.typeName()->annotation().type; using Location = VariableDeclaration::Location; Location varLoc = _variable.referenceLocation(); DataLocation typeLoc = DataLocation::Memory; // References are forced to calldata for external function parameters (not return) // and memory for parameters (also return) of publicly visible functions. // They default to memory for function parameters and storage for local variables. // As an exception, "storage" is allowed for library functions. if (auto ref = dynamic_cast<ReferenceType const*>(type.get())) { bool isPointer = true; if (_variable.isExternalCallableParameter()) { auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope()); if (contract.isLibrary()) { if (varLoc == Location::Memory) fatalTypeError(_variable.location(), "Location has to be calldata or storage for external " "library functions (remove the \"memory\" keyword)." ); } else { // force location of external function parameters (not return) to calldata if (varLoc != Location::Default) fatalTypeError(_variable.location(), "Location has to be calldata for external functions " "(remove the \"memory\" or \"storage\" keyword)." ); } if (varLoc == Location::Default) typeLoc = DataLocation::CallData; else typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage; } else if (_variable.isCallableParameter() && _variable.scope()->isPublic()) { auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope()); // force locations of public or external function (return) parameters to memory if (varLoc == Location::Storage && !contract.isLibrary()) fatalTypeError(_variable.location(), "Location has to be memory for publicly visible functions " "(remove the \"storage\" keyword)." ); if (varLoc == Location::Default || !contract.isLibrary()) typeLoc = DataLocation::Memory; else typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage; } else { if (_variable.isConstant()) { if (varLoc != Location::Default && varLoc != Location::Memory) fatalTypeError( _variable.location(), "Storage location has to be \"memory\" (or unspecified) for constants." ); typeLoc = DataLocation::Memory; } else if (varLoc == Location::Default) typeLoc = _variable.isCallableParameter() ? DataLocation::Memory : DataLocation::Storage; else typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage; isPointer = !_variable.isStateVariable(); } type = ref->copyForLocation(typeLoc, isPointer); } else if (varLoc != Location::Default && !ref) fatalTypeError(_variable.location(), "Storage location can only be given for array or struct types."); if (!type) fatalTypeError(_variable.location(), "Invalid type name."); } else if (!_variable.canHaveAutoType()) fatalTypeError(_variable.location(), "Explicit type needed."); // otherwise we have a "var"-declaration whose type is resolved by the first assignment _variable.annotation().type = type; }